From 3a997cdc565f8e46910af3fff1cb039131ba8368 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Thu, 10 Mar 2022 19:39:57 +0100 Subject: [PATCH] Start to fix null safety migration errors --- lib/forez/helpers/forez_group_helper.dart | 12 +- lib/forez/init.dart | 8 +- lib/forez/main_forez_dev.dart | 2 +- lib/forez/tour/forez_tour_builder.dart | 6 +- lib/forez/tour/join_group_pane.dart | 30 ++-- .../ui/routes/forez_member_profile_route.dart | 46 ++--- lib/forez/ui/routes/forez_route.dart | 42 ++--- lib/forez/ui/routes/search_users.dart | 10 +- .../ui/screens/forez_directory_screen.dart | 50 +++--- lib/helpers/account_helper.dart | 39 ++--- lib/helpers/api_helper.dart | 14 +- lib/helpers/calls_helper.dart | 6 +- lib/helpers/comments_helper.dart | 4 +- lib/helpers/conversations_helper.dart | 73 ++++---- lib/helpers/database/database_helper.dart | 6 +- .../database/model_database_helper.dart | 40 ++--- lib/helpers/events_helper.dart | 42 ++--- lib/helpers/firebase_messaging_helper.dart | 2 +- lib/helpers/forez_groups_helper.dart | 6 +- lib/helpers/forez_presence_helper.dart | 10 +- lib/helpers/friends_helper.dart | 11 +- lib/helpers/groups_helper.dart | 56 +++---- ...independent_push_notifications_helper.dart | 2 +- lib/helpers/likes_helper.dart | 7 +- lib/helpers/notifications_helper.dart | 8 +- lib/helpers/posts_helper.dart | 42 ++--- lib/helpers/preferences_helper.dart | 32 ++-- lib/helpers/push_notifications_helper.dart | 20 +-- lib/helpers/search_helper.dart | 6 +- .../base_serialization_helper.dart | 41 +++-- ...ersation_message_serialization_helper.dart | 10 +- .../conversations_serialization_helper.dart | 2 +- .../user_list_serialization_helper.dart | 6 +- lib/helpers/server_config_helper.dart | 10 +- lib/helpers/settings_helper.dart | 14 +- lib/helpers/survey_helper.dart | 5 +- lib/helpers/users_helper.dart | 20 +-- lib/helpers/version_helper.dart | 6 +- lib/helpers/virtual_directory_helper.dart | 9 +- lib/helpers/webapp_helper.dart | 4 +- lib/helpers/websocket_helper.dart | 18 +- lib/lists/abstract_list.dart | 3 + lib/lists/base_set.dart | 6 +- lib/lists/call_members_list.dart | 4 +- lib/lists/conversation_messages_list.dart | 39 ++--- lib/lists/conversations_list.dart | 7 +- lib/lists/custom_emojies_list.dart | 3 +- lib/lists/forez_presences_set.dart | 6 +- lib/lists/groups_list.dart | 14 +- lib/lists/memberships_list.dart | 24 +-- lib/lists/notifications_list.dart | 8 +- lib/lists/posts_list.dart | 12 +- lib/lists/unread_conversations_list.dart | 8 +- lib/lists/users_list.dart | 9 +- lib/main.dart | 4 +- lib/main_dev.dart | 2 +- lib/models/account_image_settings.dart | 14 +- lib/models/advanced_group_info.dart | 45 +++-- lib/models/advanced_user_info.dart | 59 ++++--- lib/models/api_request.dart | 33 ++-- lib/models/api_response.dart | 10 +- lib/models/application_preferences.dart | 14 +- lib/models/authentication_details.dart | 8 +- lib/models/cache_model.dart | 5 +- lib/models/call_config.dart | 6 +- lib/models/call_member.dart | 11 +- lib/models/comment.dart | 33 ++-- lib/models/config.dart | 32 ++-- lib/models/conversation.dart | 58 +++---- lib/models/conversation_member.dart | 22 +-- lib/models/conversation_message.dart | 92 +++++----- lib/models/count_unread_notifications.dart | 8 +- lib/models/custom_emoji.dart | 18 +- .../data_conservation_policy_settings.dart | 12 +- lib/models/displayed_content.dart | 18 +- lib/models/forez_presence.dart | 10 +- lib/models/friend.dart | 17 +- lib/models/friend_status.dart | 12 +- lib/models/general_settings.dart | 29 ++-- lib/models/group.dart | 35 ++-- lib/models/group_membership.dart | 9 +- lib/models/like_element.dart | 4 +- lib/models/membership.dart | 21 ++- lib/models/new_account.dart | 10 +- lib/models/new_comment.dart | 10 +- lib/models/new_conversation.dart | 14 +- lib/models/new_conversation_message.dart | 11 +- lib/models/new_conversation_settings.dart | 16 +- lib/models/new_emoji.dart | 6 +- lib/models/new_group_conversation.dart | 7 +- lib/models/new_post.dart | 41 +++-- lib/models/notification.dart | 24 +-- lib/models/notifications_settings.dart | 6 +- lib/models/post.dart | 73 ++++---- .../res_check_password_reset_token.dart | 8 +- lib/models/search_result.dart | 6 +- lib/models/security_settings.dart | 10 +- lib/models/server_config.dart | 113 +++++++------ lib/models/survey.dart | 21 ++- lib/models/survey_choice.dart | 8 +- lib/models/unread_conversation.dart | 5 +- lib/models/user.dart | 29 ++-- lib/models/ws_message.dart | 8 +- lib/ui/dialogs/alert_dialog.dart | 6 +- lib/ui/dialogs/audio_player_dialog.dart | 28 ++-- lib/ui/dialogs/color_picker_dialog.dart | 14 +- lib/ui/dialogs/deprecation_dialog.dart | 14 +- lib/ui/dialogs/input_new_password_dialog.dart | 38 ++--- lib/ui/dialogs/input_url_dialog.dart | 12 +- .../dialogs/input_user_password_dialog.dart | 8 +- lib/ui/dialogs/input_youtube_link_dialog.dart | 10 +- lib/ui/dialogs/multi_choices_dialog.dart | 34 ++-- lib/ui/dialogs/new_survey_dialog.dart | 32 ++-- lib/ui/dialogs/pick_file_dialog.dart | 46 ++--- lib/ui/dialogs/pick_user_dialog.dart | 10 +- .../post_visibility_picker_dialog.dart | 20 +-- lib/ui/dialogs/record_audio_dialog.dart | 76 ++++----- lib/ui/dialogs/screen_dialog.dart | 6 +- lib/ui/dialogs/single_input_dialog.dart | 34 ++-- lib/ui/dialogs/virtual_directory_dialog.dart | 28 ++-- .../conversation_message_stats_route.dart | 28 ++-- lib/ui/routes/conversation_route.dart | 26 +-- lib/ui/routes/create_account_route.dart | 8 +- .../routes/forez_presence_settings_route.dart | 18 +- lib/ui/routes/forgot_password_route.dart | 48 +++--- lib/ui/routes/full_screen_image.dart | 2 +- lib/ui/routes/image_editor_route.dart | 16 +- lib/ui/routes/login_route.dart | 4 +- lib/ui/routes/main_route/main_route.dart | 20 +-- lib/ui/routes/main_route/page_info.dart | 4 +- .../routes/main_route/smartphone_route.dart | 2 +- lib/ui/routes/main_route/tablet_route.dart | 12 +- lib/ui/routes/password_reset_route.dart | 24 +-- lib/ui/routes/push_notifications_route.dart | 52 +++--- lib/ui/routes/settings/about_settings.dart | 8 +- .../settings/account_image_settings.dart | 30 ++-- .../settings/account_privacy_settings.dart | 80 ++++----- .../settings/account_security_settings.dart | 32 ++-- .../settings/account_settings_route.dart | 46 ++--- .../routes/settings/application_settings.dart | 24 +-- .../custom_emojies_account_settings.dart | 34 ++-- .../settings/general_account_settings.dart | 40 ++--- .../settings/notifications_settings.dart | 8 +- lib/ui/routes/single_post_route.dart | 12 +- lib/ui/routes/tour_route.dart | 48 +++--- lib/ui/routes/update_conversation_route.dart | 2 +- lib/ui/routes/video_player_route.dart | 20 +-- lib/ui/routes/welcome_route.dart | 4 +- .../screens/authorized_group_page_screen.dart | 36 ++-- lib/ui/screens/call_screen.dart | 138 +++++++-------- .../screens/conversation_members_screen.dart | 18 +- lib/ui/screens/conversation_screen.dart | 106 ++++++------ lib/ui/screens/conversations_list_screen.dart | 36 ++-- lib/ui/screens/friends_list_screen.dart | 40 ++--- .../screens/group_access_denied_screen.dart | 18 +- lib/ui/screens/group_screen.dart | 14 +- .../group_sections/about_group_section.dart | 44 ++--- .../forez_presence_section.dart | 14 +- .../group_conversation_section.dart | 10 +- .../group_sections/group_members_screen.dart | 58 +++---- .../group_sections/group_posts_section.dart | 6 +- lib/ui/screens/group_settings_screen.dart | 158 +++++++++--------- lib/ui/screens/groups_list_screen.dart | 24 +-- lib/ui/screens/notifications_screen.dart | 86 +++++----- .../screens/other_friends_lists_screen.dart | 20 +-- lib/ui/screens/search_screen.dart | 22 +-- .../screens/unread_conversations_screen.dart | 33 ++-- .../screens/update_conversation_screen.dart | 72 ++++---- lib/ui/screens/user_access_denied_screen.dart | 14 +- lib/ui/screens/user_page_screen.dart | 16 +- .../about_user_section.dart | 42 ++--- .../user_page_sections/user_page_header.dart | 6 +- .../user_posts_section.dart | 10 +- lib/ui/tiles/accepted_friend_tile.dart | 24 +-- lib/ui/tiles/comment_tile.dart | 18 +- lib/ui/tiles/conversation_message_tile.dart | 30 ++-- lib/ui/tiles/conversation_tile.dart | 44 ++--- lib/ui/tiles/menu_tile.dart | 4 +- lib/ui/tiles/pending_friend_tile.dart | 12 +- lib/ui/tiles/post_tile.dart | 92 +++++----- lib/ui/tiles/post_visibility_level_tile.dart | 8 +- .../server_conversation_message_tile.dart | 8 +- lib/ui/tiles/simple_user_tile.dart | 14 +- lib/ui/widgets/FrienshipStatusWidget.dart | 18 +- lib/ui/widgets/account_image_widget.dart | 6 +- lib/ui/widgets/async_screen_widget.dart | 14 +- lib/ui/widgets/banner_widget.dart | 26 +-- lib/ui/widgets/conversation_file_tile.dart | 22 +-- lib/ui/widgets/conversation_image_widget.dart | 24 +-- lib/ui/widgets/copy_icon.dart | 2 +- lib/ui/widgets/countdown_widget.dart | 10 +- lib/ui/widgets/create_account_widget.dart | 66 ++++---- lib/ui/widgets/custom_app_bar_size.dart | 2 +- lib/ui/widgets/custom_list_tile.dart | 32 ++-- .../auto_sized_dialog_content_widget.dart | 4 +- .../widgets/dialogs/cancel_dialog_button.dart | 2 +- .../dialogs/confirm_dialog_button.dart | 6 +- .../forez_presence_calendar_widget.dart | 26 +-- lib/ui/widgets/group_following_widget.dart | 14 +- lib/ui/widgets/group_icon_widget.dart | 4 +- lib/ui/widgets/group_membership_widget.dart | 36 ++-- lib/ui/widgets/icon_button_badge.dart | 6 +- lib/ui/widgets/init_widget.dart | 18 +- lib/ui/widgets/like_widget.dart | 14 +- lib/ui/widgets/login_route_container.dart | 4 +- lib/ui/widgets/login_routes_theme.dart | 18 +- lib/ui/widgets/login_scaffold.dart | 10 +- lib/ui/widgets/login_widget.dart | 8 +- .../mobile_mode/mobile_appbar_widget.dart | 79 +++++---- .../widgets/mobile_mode/user_page_mobile.dart | 20 +-- lib/ui/widgets/network_image_widget.dart | 16 +- lib/ui/widgets/new_password_input_widget.dart | 42 ++--- lib/ui/widgets/pick_user_widget.dart | 26 +-- lib/ui/widgets/post_container_widget.dart | 2 +- lib/ui/widgets/post_create_form_widget.dart | 52 +++--- lib/ui/widgets/posts_list_widget.dart | 65 ++++--- lib/ui/widgets/scroll_watcher.dart | 4 +- .../settings/multi_choices_settings_tile.dart | 14 +- .../settings/text_settings_edit_tile.dart | 12 +- lib/ui/widgets/status_widget.dart | 10 +- lib/ui/widgets/survey_widget.dart | 36 ++-- lib/ui/widgets/tab_transition_widget.dart | 2 +- .../appbar_custom_dropdown_widget.dart | 32 ++-- .../tablet_mode/calls/call_window_widget.dart | 22 +-- .../widgets/tablet_mode/calls/calls_area.dart | 2 +- .../conversations/conversation_window.dart | 32 ++-- .../conversation_window_container.dart | 20 +-- .../conversations_area_widget.dart | 10 +- .../tablet_mode/current_user_panel.dart | 8 +- .../tablet_mode/global_search_field.dart | 34 ++-- .../tablet_mode/memberships_panel.dart | 86 +++++----- .../tablet_mode/tablet_appbar_widget.dart | 34 ++-- .../widgets/tablet_mode/user_page_tablet.dart | 42 ++--- lib/ui/widgets/text_rich_content_widget.dart | 10 +- lib/ui/widgets/text_widget.dart | 14 +- .../widgets/tour/account_image_tour_pane.dart | 6 +- lib/ui/widgets/tour/first_pane.dart | 6 +- .../tour/fixed_tour_size_text_area.dart | 4 +- lib/ui/widgets/tour/last_pane.dart | 2 +- lib/ui/widgets/tour/presentation_pane.dart | 28 ++-- .../widgets/tour/tour_notifications_pane.dart | 14 +- .../user_writing_in_conv_notifier.dart | 10 +- lib/utils/account_utils.dart | 2 +- lib/utils/api_utils.dart | 4 +- lib/utils/bbcode_parser.dart | 86 +++++----- lib/utils/clipboard_utils.dart | 2 +- lib/utils/color_utils.dart | 2 +- lib/utils/conversations_utils.dart | 6 +- lib/utils/date_utils.dart | 6 +- lib/utils/files_utils.dart | 4 +- lib/utils/identicon_utils.dart | 7 +- lib/utils/input_utils.dart | 2 +- lib/utils/intl_utils.dart | 14 +- lib/utils/navigation_utils.dart | 20 +-- lib/utils/ui_utils.dart | 82 ++++----- lib/utils/video_utils.dart | 11 +- pubspec.lock | 2 +- pubspec.yaml | 3 +- 258 files changed, 2879 insertions(+), 2912 deletions(-) diff --git a/lib/forez/helpers/forez_group_helper.dart b/lib/forez/helpers/forez_group_helper.dart index bcb6a90..93d1127 100644 --- a/lib/forez/helpers/forez_group_helper.dart +++ b/lib/forez/helpers/forez_group_helper.dart @@ -8,16 +8,16 @@ import 'package:comunic/models/advanced_group_info.dart'; /// /// @author Pierre Hubert -AdvancedGroupInfo _forezGroup; +AdvancedGroupInfo? _forezGroup; class ForezGroupHelper { static Future setId(int groupID) async { - (await PreferencesHelper.getInstance()) + (await PreferencesHelper.getInstance())! .setInt(PreferencesKeyList.FOREZ_GROUP, groupID); } - static Future getId() async { - return (await PreferencesHelper.getInstance()) + static Future getId() async { + return (await PreferencesHelper.getInstance())! .getInt(PreferencesKeyList.FOREZ_GROUP); } @@ -27,7 +27,7 @@ class ForezGroupHelper { _forezGroup = res.info; } - static AdvancedGroupInfo getGroup() => _forezGroup; + static AdvancedGroupInfo? getGroup() => _forezGroup; } -AdvancedGroupInfo get forezGroup => ForezGroupHelper.getGroup(); +AdvancedGroupInfo? get forezGroup => ForezGroupHelper.getGroup(); diff --git a/lib/forez/init.dart b/lib/forez/init.dart index 6447a69..e375c03 100644 --- a/lib/forez/init.dart +++ b/lib/forez/init.dart @@ -11,10 +11,10 @@ import 'package:flutter/material.dart'; class ForezConfig extends Config { ForezConfig({ - @required String apiServerName, - @required String apiServerUri, - @required bool apiServerSecure, - @required String clientName, + required String apiServerName, + required String apiServerUri, + required bool apiServerSecure, + required String clientName, }) : super( apiServerName: apiServerName, apiServerUri: apiServerUri, diff --git a/lib/forez/main_forez_dev.dart b/lib/forez/main_forez_dev.dart index 7055b25..c21d446 100644 --- a/lib/forez/main_forez_dev.dart +++ b/lib/forez/main_forez_dev.dart @@ -11,7 +11,7 @@ import 'package:comunic/models/config.dart'; /// Fix HTTPS issue class MyHttpOverride extends HttpOverrides { @override - HttpClient createHttpClient(SecurityContext context) { + HttpClient createHttpClient(SecurityContext? context) { return super.createHttpClient(context) ..badCertificateCallback = (cert, host, port) { return host == "devweb.local"; // Forcefully trust local website diff --git a/lib/forez/tour/forez_tour_builder.dart b/lib/forez/tour/forez_tour_builder.dart index 392c73e..f9f4587 100644 --- a/lib/forez/tour/forez_tour_builder.dart +++ b/lib/forez/tour/forez_tour_builder.dart @@ -29,7 +29,7 @@ List buildTour(TourRouteState state) { msgTwo: tr("Let's first join a Forez group!"), ), JoinForezGroupPane( - key: state.pubKeys[_JOIN_GROUP_KEY_ID], + key: state.pubKeys[_JOIN_GROUP_KEY_ID] as GlobalKey?, onUpdated: () => state.rebuild(), ), FirstTourPane( @@ -51,7 +51,7 @@ List buildTour(TourRouteState state) { // Forez specific features PresentationPane( icon: Icons.calendar_today, - title: tr("Presence in Forez"), + title: tr("Presence in Forez")!, text: tr( "Easily specify the days you are in Forez plain, so that everyone can know it!"), actionTitle: tr("Do it now!"), @@ -62,7 +62,7 @@ List buildTour(TourRouteState state) { // Chat pane PresentationPane( icon: Icons.question_answer, - title: tr("Conversations"), + title: tr("Conversations")!, text: tr( "#Forez now integrates the conversation system of Comunic, so you have access both to public and private conversations!"), ), diff --git a/lib/forez/tour/join_group_pane.dart b/lib/forez/tour/join_group_pane.dart index ff45047..d4c6d0e 100644 --- a/lib/forez/tour/join_group_pane.dart +++ b/lib/forez/tour/join_group_pane.dart @@ -16,17 +16,17 @@ import 'package:flutter/material.dart'; class JoinForezGroupPane extends PresentationPane { JoinForezGroupPane({ - @required Function() onUpdated, - @required GlobalKey key, + required Function() onUpdated, + required GlobalKey? key, }) : super( icon: Icons.login, - title: tr("Join a Forez group"), + title: tr("Join a Forez group")!, child: (c) => _JoinGroupPaneBody( key: key, onUpdated: onUpdated, ), canGoNext: key?.currentState?.canGoNext ?? false, - onTapNext: (c) => key.currentState.validateChoice(), + onTapNext: (c) => key!.currentState!.validateChoice(), ); } @@ -34,8 +34,8 @@ class _JoinGroupPaneBody extends StatefulWidget { final Function() onUpdated; const _JoinGroupPaneBody({ - Key key, - @required this.onUpdated, + Key? key, + required this.onUpdated, }) : assert(onUpdated != null), super(key: key); @@ -46,10 +46,10 @@ class _JoinGroupPaneBody extends StatefulWidget { class JoinGroupPaneBodyState extends State<_JoinGroupPaneBody> { final _key = GlobalKey(); - List _groups; - int _currChoice; + late List _groups; + int? _currChoice; - bool get canGoNext => _currChoice != null && _currChoice > 0; + bool get canGoNext => _currChoice != null && _currChoice! > 0; Group get _currGroup => _groups.firstWhere((e) => e.id == _currChoice); @@ -65,17 +65,17 @@ class JoinGroupPaneBodyState extends State<_JoinGroupPaneBody> { key: _key, onReload: _load, onBuild: onBuild, - errorMessage: tr("Failed to load the list of Forez groups!")); + errorMessage: tr("Failed to load the list of Forez groups!")!); Widget onBuild() => ConstrainedBox( constraints: BoxConstraints(maxWidth: 300), child: Column( children: [ - Text(tr("Please choose now the Forez group you want to join...")), + Text(tr("Please choose now the Forez group you want to join...")!), ]..addAll(_groups.map((e) => RadioListTile( value: e.id, groupValue: _currChoice, - onChanged: (v) => setState(() => _currChoice = e.id), + onChanged: (dynamic v) => setState(() => _currChoice = e.id), title: Text(e.name), subtitle: Text(e.membershipText), ))), @@ -112,7 +112,7 @@ class JoinGroupPaneBodyState extends State<_JoinGroupPaneBody> { await alert(context, "${tr("You can not access this group yet, please wait for a member of the group to accept your request.")}\n${tr("Hopefully this will not be too long.")}\n${tr("Please check back soon!")}"); - _key.currentState.refresh(); + _key.currentState!.refresh(); return false; } @@ -121,8 +121,8 @@ class JoinGroupPaneBodyState extends State<_JoinGroupPaneBody> { return true; } catch (e, s) { logError(e, s); - snack(context, tr("Failed to register to group!")); - _key.currentState.refresh(); + snack(context, tr("Failed to register to group!")!); + _key.currentState!.refresh(); return false; } } diff --git a/lib/forez/ui/routes/forez_member_profile_route.dart b/lib/forez/ui/routes/forez_member_profile_route.dart index 66127a8..539c2ba 100644 --- a/lib/forez/ui/routes/forez_member_profile_route.dart +++ b/lib/forez/ui/routes/forez_member_profile_route.dart @@ -24,8 +24,8 @@ class ForezMemberProfileRoute extends StatefulWidget { final int userID; const ForezMemberProfileRoute({ - Key key, - @required this.userID, + Key? key, + required this.userID, }) : assert(userID != null), super(key: key); @@ -39,13 +39,13 @@ class _ForezMemberProfileRouteState extends State { final _key = GlobalKey(); - AdvancedUserInfo _user; - PresenceSet _presence; + late AdvancedUserInfo _user; + late PresenceSet _presence; Future _load() async { - _user = await ForezGroupsHelper.getMemberInfo(forezGroup.id, widget.userID); + _user = await ForezGroupsHelper.getMemberInfo(forezGroup!.id, widget.userID); _presence = - await ForezPresenceHelper.getForUser(forezGroup.id, widget.userID); + await ForezPresenceHelper.getForUser(forezGroup!.id, widget.userID); } @override @@ -56,25 +56,25 @@ class _ForezMemberProfileRouteState extends State { loadingWidget: _buildLoading(), errorWidget: _buildError(), errorMessage: tr( - "Failed to load user information, maybe it is not a Forez member yet?")); + "Failed to load user information, maybe it is not a Forez member yet?")!); Widget _buildLoading() => Scaffold( appBar: AppBar( - title: Text(tr("Loading...")), + title: Text(tr("Loading...")!), ), body: buildCenteredProgressBar(), ); Widget _buildError() => Scaffold( appBar: AppBar( - title: Text(tr("Error")), + 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")), + onPressed: () => _key.currentState!.refresh(), + child: Text(tr("Try again")!), textColor: Colors.white, ) ]), @@ -101,7 +101,7 @@ class _ForezMemberProfileRouteState extends State { ? Container() : CachedNetworkImage( fit: BoxFit.cover, - imageUrl: _user.accountImageURL, + imageUrl: _user.accountImageURL!, height: _appBarHeight, ), // This gradient ensures that the toolbar icons are distinct @@ -135,7 +135,7 @@ class _ForezMemberProfileRouteState extends State { : ListTile( leading: Icon(Icons.note), title: TextWidget(content: DisplayedString(_user.publicNote)), - subtitle: Text(tr("Note")), + subtitle: Text(tr("Note")!), ), // Email address @@ -143,9 +143,9 @@ class _ForezMemberProfileRouteState extends State { ? Container() : ListTile( leading: Icon(Icons.email), - title: Text(_user.emailAddress), - subtitle: Text(tr("Email address")), - trailing: CopyIcon(_user.emailAddress), + title: Text(_user.emailAddress!), + subtitle: Text(tr("Email address")!), + trailing: CopyIcon(_user.emailAddress!), ), // Location @@ -153,9 +153,9 @@ class _ForezMemberProfileRouteState extends State { ? Container() : ListTile( leading: Icon(Icons.location_on), - title: Text(_user.location), - subtitle: Text(tr("Location")), - trailing: CopyIcon(_user.location), + title: Text(_user.location!), + subtitle: Text(tr("Location")!), + trailing: CopyIcon(_user.location!), ), // Website @@ -164,7 +164,7 @@ class _ForezMemberProfileRouteState extends State { : ListTile( leading: Icon(Icons.link), title: Text(_user.personalWebsite), - subtitle: Text(tr("Website")), + subtitle: Text(tr("Website")!), trailing: IconButton( icon: Icon(Icons.open_in_new), onPressed: () => launch(_user.personalWebsite), @@ -174,10 +174,10 @@ class _ForezMemberProfileRouteState extends State { Divider(), ListTile( leading: Icon(Icons.calendar_today), - title: Text(tr("Presence in Forez")), + title: Text(tr("Presence in Forez")!), subtitle: Text(_presence.containsDate(DateTime.now()) - ? tr("Present today") - : tr("Absent")), + ? tr("Present today")! + : tr("Absent")!), ), PresenceCalendarWidget(presenceSet: _presence), Divider(), diff --git a/lib/forez/ui/routes/forez_route.dart b/lib/forez/ui/routes/forez_route.dart index c8f2bbd..c9757a1 100644 --- a/lib/forez/ui/routes/forez_route.dart +++ b/lib/forez/ui/routes/forez_route.dart @@ -21,7 +21,7 @@ import 'package:flutter/material.dart'; /// @author Pierre Hubert class ForezRoute extends StatefulWidget implements MainRoute { - const ForezRoute({Key key}) : super(key: key); + const ForezRoute({Key? key}) : super(key: key); @override State createState() => _MainRouteState(); @@ -40,7 +40,7 @@ class _MainRouteState extends MainController { @override Widget build(BuildContext context) { - if (forezGroup == null) return Text(tr("Missing Forez group!")); + if (forezGroup == null) return Text(tr("Missing Forez group!")!); return StatusWidget( child: (c) => SafeArea( @@ -67,11 +67,11 @@ class _MainRouteState extends MainController { @override void openConversation(Conversation conv, {fullScreen: false}) { // Forcefully open conversations in a "normal" way (do not display groups) - openConversationById(conv.id, fullScreen: fullScreen); + openConversationById(conv.id!, fullScreen: fullScreen); } @override - void openGroup(int groupID, {int conversationID}) => _unsupportedFeature(); + void openGroup(int groupID, {int? conversationID}) => _unsupportedFeature(); @override void openUserPage(int userID) => pushPage(PageInfo( @@ -92,7 +92,7 @@ class _MainRouteState extends MainController { enum _PopupMenuItems { ACTION_SETTINGS, ACTION_SIGN_OUT } class ForezRouteBody extends StatefulWidget { - ForezRouteBody({Key key}) : super(key: key); + ForezRouteBody({Key? key}) : super(key: key); @override _ForezRouteBodyState createState() => _ForezRouteBodyState(); @@ -112,7 +112,7 @@ class _ForezRouteBodyState extends SafeState { length: _tabs.length, child: Scaffold( appBar: AppBar( - title: Text(forezGroup.name), + title: Text(forezGroup!.name), actions: [_buildPopupMenuButton()], bottom: TabBar(tabs: _tabs), ), @@ -129,11 +129,11 @@ class _ForezRouteBodyState extends SafeState { Widget _buildPopupMenuButton() => PopupMenuButton<_PopupMenuItems>( itemBuilder: (c) => [ PopupMenuItem( - child: Text(tr("Settings")), + child: Text(tr("Settings")!), value: _PopupMenuItems.ACTION_SETTINGS, ), PopupMenuItem( - child: Text(tr("Sign out")), + child: Text(tr("Sign out")!), value: _PopupMenuItems.ACTION_SIGN_OUT, ), ], @@ -143,10 +143,10 @@ class _ForezRouteBodyState extends SafeState { void _onMenuSelection(_PopupMenuItems value) { switch (value) { case _PopupMenuItems.ACTION_SETTINGS: - MainController.of(context).openSettings(); + MainController.of(context)!.openSettings(); break; case _PopupMenuItems.ACTION_SIGN_OUT: - MainController.of(context).requestLogout(); + MainController.of(context)!.requestLogout(); break; } } @@ -155,29 +155,29 @@ class _ForezRouteBodyState extends SafeState { // Posts tab _Tab( icon: Icons.auto_stories, - title: tr("Posts"), - widget: () => GroupPostsSection(group: forezGroup), + title: tr("Posts")!, + widget: () => GroupPostsSection(group: forezGroup!), ), // Presence tab _Tab( icon: Icons.calendar_today, - title: tr("Presence"), - widget: () => ForezPresenceSection(groupID: forezGroup.id), + title: tr("Presence")!, + widget: () => ForezPresenceSection(groupID: forezGroup!.id), ), // Conversations tab _Tab( icon: Icons.question_answer, - title: tr("Conversations"), + title: tr("Conversations")!, widget: () => ConversationsListScreen(), - isUnread: (c) => StatusWidgetState.of(c).unreadConversations > 0, + isUnread: (c) => StatusWidgetState.of(c)!.unreadConversations! > 0, ), // Directory tab _Tab( icon: Icons.import_contacts, - title: tr("Directory"), + title: tr("Directory")!, widget: () => ForezDirectoryScreen(), ), ]; @@ -203,12 +203,12 @@ class _Tab { final IconData icon; final String title; final Widget Function() widget; - final bool Function(BuildContext) isUnread; + final bool Function(BuildContext)? isUnread; const _Tab({ - @required this.icon, - @required this.title, - @required this.widget, + required this.icon, + required this.title, + required this.widget, this.isUnread, }) : assert(icon != null), assert(title != null), diff --git a/lib/forez/ui/routes/search_users.dart b/lib/forez/ui/routes/search_users.dart index 2b59fd5..abeb11f 100644 --- a/lib/forez/ui/routes/search_users.dart +++ b/lib/forez/ui/routes/search_users.dart @@ -7,18 +7,18 @@ import 'package:flutter/material.dart'; /// /// @author Pierre Hubert -Future searchUser(BuildContext context, UsersList users) async { - return await showSearch( +Future searchUser(BuildContext context, UsersList users) async { + return await showSearch( context: context, delegate: _SearchDelegate(users)); } -class _SearchDelegate extends SearchDelegate { +class _SearchDelegate extends SearchDelegate { final UsersList _usersList; _SearchDelegate(this._usersList) : assert(_usersList != null); @override - List buildActions(BuildContext context) => null; + List? buildActions(BuildContext context) => null; @override Widget buildLeading(BuildContext context) => IconButton( @@ -28,7 +28,7 @@ class _SearchDelegate extends SearchDelegate { @override Widget buildSuggestions(BuildContext context) { - final list = _usersList + final List list = _usersList .where((element) => element.fullName.toLowerCase().contains(query.toLowerCase())) .toList(); diff --git a/lib/forez/ui/screens/forez_directory_screen.dart b/lib/forez/ui/screens/forez_directory_screen.dart index 88a3f4a..07f713e 100644 --- a/lib/forez/ui/screens/forez_directory_screen.dart +++ b/lib/forez/ui/screens/forez_directory_screen.dart @@ -35,11 +35,11 @@ class ForezDirectoryScreen extends StatefulWidget { class _ForezDirectoryScreenState extends State { final _key = GlobalKey(); - UsersList _users; - GroupMembersList _members; + late UsersList _users; + late GroupMembersList _members; Future _load() async { - _members = await GroupsHelper.getMembersList(forezGroup.id); + _members = await GroupsHelper.getMembersList(forezGroup!.id); _users = await UsersHelper().getListWithThrow(_members.usersID); } @@ -49,7 +49,7 @@ class _ForezDirectoryScreenState extends State { AsyncScreenWidget( onReload: _load, onBuild: onBuild, - errorMessage: tr("Failed to load members list!"), + errorMessage: tr("Failed to load members list!")!, key: _key, ), Positioned( @@ -88,13 +88,13 @@ class _ForezDirectoryScreenState extends State { "Do you really want to cancel the invitation sent to %u%?", args: {"u": user.fullName}))) return; - await GroupsHelper.cancelInvitation(forezGroup.id, user.id); - _key.currentState.refresh(); + await GroupsHelper.cancelInvitation(forezGroup!.id, user.id); + _key.currentState!.refresh(); break; case _PopupMenuActions.ACCEPT_REQUEST: - await GroupsHelper.respondRequest(forezGroup.id, user.id, true); - _key.currentState.refresh(); + await GroupsHelper.respondRequest(forezGroup!.id, user.id, true); + _key.currentState!.refresh(); break; case _PopupMenuActions.REJECT_REQUEST: @@ -104,13 +104,13 @@ class _ForezDirectoryScreenState extends State { "Do you really want to reject the request of %u% to join the Forez group?", args: {"u": user.fullName}))) return; - await GroupsHelper.respondRequest(forezGroup.id, user.id, false); - _key.currentState.refresh(); + await GroupsHelper.respondRequest(forezGroup!.id, user.id, false); + _key.currentState!.refresh(); break; } } catch (e, s) { logError(e, s); - snack(context, tr("Error while processing action!")); + snack(context, tr("Error while processing action!")!); } } @@ -125,7 +125,7 @@ class _ForezDirectoryScreenState extends State { } void _openUserProfile(User user) => - MainController.of(context).openUserPage(user.id); + MainController.of(context)!.openUserPage(user.id!); } class _ForezMemberTile extends StatelessWidget { @@ -135,11 +135,11 @@ class _ForezMemberTile extends StatelessWidget { final Function(User) onTap; const _ForezMemberTile({ - Key key, - @required this.user, - @required this.member, - @required this.selectedAction, - @required this.onTap, + Key? key, + required this.user, + required this.member, + required this.selectedAction, + required this.onTap, }) : super(key: key); @override @@ -147,7 +147,7 @@ class _ForezMemberTile extends StatelessWidget { leading: AccountImageWidget(user: user), title: Text(user.fullName), subtitle: Text(member.membershipText), - trailing: !member.isAtLeastMember && forezGroup.isAtLeastModerator + trailing: !member.isAtLeastMember && forezGroup!.isAtLeastModerator ? (member.isInvited ? _buildInvitedButton() : _buildRequestedButton()) @@ -155,7 +155,7 @@ class _ForezMemberTile extends StatelessWidget { onTap: member.isAtLeastMember ? () => onTap(user) : null, ); - Widget _buildConversationButton() => user.id == userID() + Widget? _buildConversationButton() => user.id == userID() ? null : IconButton( icon: Icon(Icons.message), @@ -201,12 +201,12 @@ class _MembershipButton extends StatelessWidget { final IconData icon; const _MembershipButton({ - Key key, - @required this.user, - @required this.action, - @required this.onTap, - @required this.color, - @required this.icon, + Key? key, + required this.user, + required this.action, + required this.onTap, + required this.color, + required this.icon, }) : assert(user != null), assert(action != null), assert(onTap != null), diff --git a/lib/helpers/account_helper.dart b/lib/helpers/account_helper.dart index a3c7334..fa18d48 100644 --- a/lib/helpers/account_helper.dart +++ b/lib/helpers/account_helper.dart @@ -26,14 +26,14 @@ enum CreateAccountResult { class AccountHelper { // Current user ID - static int _currentUserID = -1; + static int? _currentUserID = -1; /// Checkout whether current user is signed in or not /// /// Warning : This method MUST BE CALLED AT LEAST ONCE AFTER APP START !!! Future signedIn() async { bool signedIn = - (await PreferencesHelper.getInstance()).getLoginToken() != null; + (await PreferencesHelper.getInstance())!.getLoginToken() != null; // Load current user ID for later use if (signedIn && _currentUserID == -1) await _loadCurrentUserID(); @@ -56,8 +56,8 @@ class AccountHelper { else if (response.code != 200) return AuthResult.NETWORK_ERROR; // Save login token - await (await PreferencesHelper.getInstance()) - .setLoginToken(response.getObject()["token"]); + await (await PreferencesHelper.getInstance())! + .setLoginToken(response.getObject()!["token"]); // Get current user ID final userID = await _downloadCurrentUserID(); @@ -67,7 +67,7 @@ class AccountHelper { } // Save current user ID - final preferences = await PreferencesHelper.getInstance(); + final preferences = await (PreferencesHelper.getInstance()); await preferences.setInt(PreferencesKeyList.USER_ID, userID); _currentUserID = userID; @@ -130,27 +130,27 @@ class AccountHelper { .getObject()["exists"]; /// Get current user email address - static Future getCurrentAccountEmailAddress() async => + static Future getCurrentAccountEmailAddress() async => (await APIRequest.withLogin("account/mail") - .execWithThrowGetObject())["mail"]; + .execWithThrowGetObject())!["mail"]; /// Check out whether security questions have been set for an account or not /// /// Throws in case of failure - static Future hasSecurityQuestions(String email) async => + static Future hasSecurityQuestions(String email) async => (await APIRequest.withoutLogin("account/has_security_questions") .addString("email", email) .execWithThrow()) - .getObject()["defined"]; + .getObject()!["defined"]; /// Get the security questions of the user /// /// Throws in case of failure - static Future> getSecurityQuestions(String email) async => + static Future?> getSecurityQuestions(String? email) async => ((await APIRequest.withoutLogin("account/get_security_questions") .addString("email", email) .execWithThrow()) - .getObject()["questions"]) + .getObject()!["questions"]) .cast(); /// Validate given security answers @@ -158,14 +158,14 @@ class AccountHelper { /// Throws an [Exception] in case of failure /// /// Returns a password reset token in case of success - static Future checkAnswers( - String email, List answers) async => + static Future checkAnswers( + String? email, List answers) async => (await APIRequest.withoutLogin("account/check_security_answers") .addString("email", email) .addString("answers", answers.map((f) => Uri.encodeComponent(f)).join("&")) .execWithThrow()) - .getObject()["reset_token"]; + .getObject()!["reset_token"]; /// Check a password reset token /// @@ -195,25 +195,26 @@ class AccountHelper { .execWithThrow(); /// Get current user ID from the server - Future _downloadCurrentUserID() async { + Future _downloadCurrentUserID() async { final response = await APIRequest.withLogin("account/id").exec(); if (response.code != 200) return null; - return response.getObject()["userID"]; + return response.getObject()!["userID"]; } /// Get the ID of the currently signed in user Future _loadCurrentUserID() async { - final preferences = await PreferencesHelper.getInstance(); + final preferences = + await PreferencesHelper.getInstance(); _currentUserID = preferences.getInt(PreferencesKeyList.USER_ID); } /// Check if current user ID is loaded or not - static bool get isUserIDLoaded => _currentUserID > 0; + static bool get isUserIDLoaded => _currentUserID! > 0; /// Get the ID of the currently signed in user - static int getCurrentUserID() { + static int? getCurrentUserID() { if (_currentUserID == -1) throw "Current user ID has not been loaded yet!"; return _currentUserID; } diff --git a/lib/helpers/api_helper.dart b/lib/helpers/api_helper.dart index 0e5c983..145a475 100644 --- a/lib/helpers/api_helper.dart +++ b/lib/helpers/api_helper.dart @@ -23,7 +23,7 @@ class APIHelper { //Add user token (if required) if (request.needLogin) { - final token = (await PreferencesHelper.getInstance()).getLoginToken(); + final token = (await PreferencesHelper.getInstance())!.getLoginToken(); if (token == null) { EventsHelper.emit(InvalidLoginTokensEvent()); @@ -41,13 +41,13 @@ class APIHelper { else url = Uri.https(config().apiServerName, path); - final data = FormData.fromMap(request.args); + final data = FormData.fromMap(request.args!); // Process files (if required) if (multipart) { // Process filesystem files for (final key in request.files.keys) { - var v = request.files[key]; + var v = request.files[key]!; data.files.add(MapEntry( key, await MultipartFile.fromFile(v.path, @@ -56,11 +56,11 @@ class APIHelper { // Process in-memory files for (final key in request.bytesFiles.keys) { - var v = request.bytesFiles[key]; + var v = request.bytesFiles[key]!; data.files.add(MapEntry( key, MultipartFile.fromBytes( - v.bytes, + v.bytes!, filename: v.filename.split("/").last, contentType: v.type, ))); @@ -85,9 +85,9 @@ class APIHelper { EventsHelper.emit(InvalidLoginTokensEvent()); if (response.statusCode != HttpStatus.ok) - return APIResponse(response.statusCode, response.data); + return APIResponse(response.statusCode!, response.data); - return APIResponse(response.statusCode, response.data); + return APIResponse(response.statusCode!, response.data); } catch (e, stack) { print(e.toString()); print("Could not execute a request!"); diff --git a/lib/helpers/calls_helper.dart b/lib/helpers/calls_helper.dart index d021891..c8e6e78 100644 --- a/lib/helpers/calls_helper.dart +++ b/lib/helpers/calls_helper.dart @@ -39,12 +39,12 @@ class CallsHelper { .cast()); /// Request an offer to access another peer's stream - static Future requestOffer(int callID, int peerID) async => + static Future requestOffer(int callID, int? peerID) async => await ws("calls/request_offer", {"callID": callID, "peerID": peerID}); /// Send a Session Description message to the server static Future sendSessionDescription( - int callID, int peerID, RTCSessionDescription sdp) async => + int callID, int? peerID, RTCSessionDescription sdp) async => await ws("calls/signal", { "callID": callID, "peerID": peerID, @@ -54,7 +54,7 @@ class CallsHelper { /// Send an IceCandidate static Future sendIceCandidate( - int callID, int peerID, RTCIceCandidate candidate) async => + int callID, int? peerID, RTCIceCandidate candidate) async => await ws("calls/signal", { "callID": callID, "peerID": peerID, diff --git a/lib/helpers/comments_helper.dart b/lib/helpers/comments_helper.dart index 2903165..2bfe732 100644 --- a/lib/helpers/comments_helper.dart +++ b/lib/helpers/comments_helper.dart @@ -27,7 +27,7 @@ class CommentsHelper { } /// Get a single comment from the server, specified by its [id] - Future getSingle(int id) async { + Future getSingle(int id) async { final response = await APIRequest( uri: "comments/get_single", needLogin: true, @@ -39,7 +39,7 @@ class CommentsHelper { } /// Update comment content - Future updateContent(int id, String newContent) async { + Future updateContent(int id, String? newContent) async { return (await APIRequest(uri: "comments/edit", needLogin: true, args: { "commentID": id.toString(), "content": newContent, diff --git a/lib/helpers/conversations_helper.dart b/lib/helpers/conversations_helper.dart index d7a22dd..1c0f7be 100644 --- a/lib/helpers/conversations_helper.dart +++ b/lib/helpers/conversations_helper.dart @@ -21,7 +21,6 @@ import 'package:comunic/utils/account_utils.dart'; import 'package:comunic/utils/color_utils.dart'; import 'package:comunic/utils/dart_color.dart'; import 'package:dio/dio.dart'; -import 'package:meta/meta.dart'; /// Conversation helper /// @@ -47,13 +46,13 @@ class ConversationsHelper { .addBool("canEveryoneAddMembers", settings.canEveryoneAddMembers) .execWithThrow(); - return response.getObject()["conversationID"]; + return response.getObject()!["conversationID"]; } /// Add a member to a conversation. /// /// Throws in case of failure - static Future addMember(int convID, int userID) async => + static Future addMember(int? convID, int? userID) async => await APIRequest.withLogin("conversations/addMember") .addInt("convID", convID) .addInt("userID", userID) @@ -62,7 +61,7 @@ class ConversationsHelper { /// Remove a member from a conversation. /// /// Throws in case of failure - static Future removeMember(int convID, int userID) async => + static Future removeMember(int? convID, int? userID) async => await APIRequest.withLogin("conversations/removeMember") .addInt("convID", convID) .addInt("userID", userID) @@ -71,7 +70,7 @@ class ConversationsHelper { /// Update admin status of a user in a conversation /// /// Throws in case of failure - static Future setAdmin(int/*!*/ convID, int/*!*/ userID, bool admin) async => + static Future setAdmin(int convID, int userID, bool admin) async => await APIRequest.withLogin("conversations/setAdmin") .addInt("convID", convID) .addInt("userID", userID) @@ -91,7 +90,7 @@ class ConversationsHelper { if (settings.isComplete) request .addString("name", settings.name ?? "") - .addBool("canEveryoneAddMembers", settings.canEveryoneAddMembers) + .addBool("canEveryoneAddMembers", settings.canEveryoneAddMembers!) .addString("color", colorToHex(settings.color)); await request.execWithThrow(); @@ -104,7 +103,7 @@ class ConversationsHelper { /// Set a new conversation logo /// /// Throws in case of failure - static Future changeImage(int convID, BytesFile file) async => + static Future changeImage(int? convID, BytesFile file) async => await APIRequest.withLogin("conversations/change_image") .addInt("convID", convID) .addBytesFile("file", file) @@ -113,13 +112,13 @@ class ConversationsHelper { /// Remove conversation logo /// /// Throws in case of failure - static Future removeLogo(int convID) async => + static Future removeLogo(int? convID) async => await APIRequest.withLogin("conversations/delete_image") .addInt("convID", convID) .execWithThrow(); /// Delete a conversation specified by its [id] - Future deleteConversation(int id) async => + Future deleteConversation(int? id) async => await APIRequest.withLogin("conversations/delete") .addInt("conversationID", id) .execWithThrow(); @@ -132,7 +131,7 @@ class ConversationsHelper { await APIRequest.withLogin("conversations/getList").execWithThrow(); ConversationsList list = ConversationsList(); - response.getArray().forEach((f) => list.add(apiToConversation(f))); + response.getArray()!.forEach((f) => list.add(apiToConversation(f))); // Update the database await ConversationsSerializationHelper().setList(list); @@ -148,13 +147,13 @@ class ConversationsHelper { } /// Get information about a single conversation specified by its [id] - Future _downloadSingle(int id) async { + Future _downloadSingle(int? id) async { final response = await APIRequest( uri: "conversations/get_single", needLogin: true, args: {"conversationID": id.toString()}).execWithThrow(); - final conversation = apiToConversation(response.getObject()); + final conversation = apiToConversation(response.getObject()!); await ConversationsSerializationHelper() .insertOrReplaceElement((c) => c.id == conversation.id, conversation); @@ -167,7 +166,7 @@ class ConversationsHelper { /// case of failure /// /// Return value of this method is never null. - Future getSingle(int id, {bool force = false}) async { + Future getSingle(int? id, {bool force = false}) async { if (force || !await ConversationsSerializationHelper().any((c) => c.id == id)) return await _downloadSingle(id); @@ -178,19 +177,19 @@ class ConversationsHelper { /// Get the name of a [conversation]. This requires information /// about the users of this conversation static String getConversationName( - Conversation conversation, UsersList users) { - if (conversation.hasName) return conversation.name; + Conversation conversation, UsersList? users) { + if (conversation.hasName) return conversation.name!; String name = ""; int count = 0; - for (int i = 0; i < 3 && i < conversation.members.length; i++) - if (conversation.members[i].userID != userID()) { + for (int i = 0; i < 3 && i < conversation.members!.length; i++) + if (conversation.members![i].userID != userID()) { name += (count > 0 ? ", " : "") + - users.getUser(conversation.members[i].userID).fullName; + users!.getUser(conversation.members![i].userID).fullName; count++; } - if (conversation.members.length > 3) name += ", ..."; + if (conversation.members!.length > 3) name += ", ..."; return name; } @@ -200,7 +199,7 @@ class ConversationsHelper { /// true /// /// Throws an exception in case of failure - Future getPrivate(int userID, {bool allowCreate = true}) async { + Future getPrivate(int? userID, {bool allowCreate = true}) async { final response = await APIRequest( uri: "conversations/getPrivate", needLogin: true, @@ -211,7 +210,7 @@ class ConversationsHelper { ).execWithThrow(); // Get and return conversation ID - return int.parse(response.getObject()["conversationsID"][0].toString()); + return int.parse(response.getObject()!["conversationsID"][0].toString()); } /// Asynchronously get the name of the conversation @@ -222,7 +221,7 @@ class ConversationsHelper { /// Throws an exception in case of failure static Future getConversationNameAsync( Conversation conversation) async { - if (conversation.hasName) return conversation.name; + if (conversation.hasName) return conversation.name!; //Get information about the members of the conversation final members = await UsersHelper().getList(conversation.membersID); @@ -273,7 +272,7 @@ class ConversationsHelper { // Parse the response of the server ConversationMessagesList list = ConversationMessagesList(); - response.getArray().forEach((f) { + response.getArray()!.forEach((f) { list.add( apiToConversationMessage(f), ); @@ -294,7 +293,7 @@ class ConversationsHelper { /// Throws an exception in case of failure Future _downloadNewMessagesSingle( int conversationID, - {int lastMessageID = 0}) async { + {int? lastMessageID = 0}) async { // Execute the request on the server final response = await APIRequest( uri: "conversations/refresh_single", @@ -311,8 +310,8 @@ class ConversationsHelper { /// /// Throws in case of failure Future getOlderMessages({ - @required int conversationID, - @required int oldestMessagesID, + required int conversationID, + required int? oldestMessagesID, int limit = 15, }) async { // Perform the request online @@ -334,8 +333,8 @@ class ConversationsHelper { /// /// Throws in case of failure Future getNewMessages( - {@required int conversationID, - int lastMessageID = 0, + {required int conversationID, + int? lastMessageID = 0, bool online = true}) async { if (online) return await _downloadNewMessagesSingle(conversationID, @@ -348,8 +347,8 @@ class ConversationsHelper { /// Send a new message to the server Future sendMessage( NewConversationMessage message, { - ProgressCallback sendProgress, - CancelToken cancelToken, + ProgressCallback? sendProgress, + CancelToken? cancelToken, }) async { final request = APIRequest.withLogin("conversations/sendMessage") .addInt("conversationID", message.conversationID) @@ -388,7 +387,7 @@ class ConversationsHelper { await ConversationsMessagesSerializationHelper(msg.convID).remove(msg); /// Update a message content - Future updateMessage(int id, String newContent) async { + Future updateMessage(int? id, String newContent) async { final response = await APIRequest( uri: "conversations/updateMessage", needLogin: true, @@ -400,7 +399,7 @@ class ConversationsHelper { } /// Delete permanently a message specified by its [id] - Future deleteMessage(int id) async { + Future deleteMessage(int? id) async { // Delete the message online final response = await APIRequest( uri: "conversations/deleteMessage", @@ -418,7 +417,7 @@ class ConversationsHelper { static Future getListUnread() async { final list = (await APIRequest.withLogin("conversations/get_list_unread") .execWithThrow()) - .getArray(); + .getArray()!; return UnreadConversationsList() ..addAll(list.map((f) => UnreadConversation( @@ -431,7 +430,7 @@ class ConversationsHelper { /// conversation through WebSocket Future registerConversationEvents(int id) async { if (_registeredConversations.containsKey(id)) - _registeredConversations[id]++; + _registeredConversations.update(id, (value) => value + 1); else { _registeredConversations[id] = 1; await ws("\$main/register_conv", {"convID": id}); @@ -442,16 +441,16 @@ class ConversationsHelper { Future unregisterConversationEvents(int id) async { if (!_registeredConversations.containsKey(id)) return; - _registeredConversations[id]--; + _registeredConversations.update(id, (value) => value - 1); - if (_registeredConversations[id] <= 0) { + if (_registeredConversations[id]! <= 0) { _registeredConversations.remove(id); await ws("\$main/unregister_conv", {"convID": id}); } } /// Send a notification to inform that the user is writing a message - static Future sendWritingEvent(int convID) async => + static Future sendWritingEvent(int? convID) async => await ws("conversations/is_writing", {"convID": convID}); /// Turn an API response into a ConversationMessage object diff --git a/lib/helpers/database/database_helper.dart b/lib/helpers/database/database_helper.dart index 7d1675b..ee5d119 100644 --- a/lib/helpers/database/database_helper.dart +++ b/lib/helpers/database/database_helper.dart @@ -9,11 +9,11 @@ import 'package:sqflite/sqflite.dart'; /// @author Pierre HUBERT abstract class DatabaseHelper { - static Database _db; + static Database? _db; /// Open the database static Future open() async { - if (_db != null && _db.isOpen) return; + if (_db != null && _db!.isOpen) return; var databasePath = await getDatabasesPath(); _db = await openDatabase( @@ -24,7 +24,7 @@ abstract class DatabaseHelper { } /// Get a database instance - static Future get() async { + static Future get() async { await open(); return _db; } diff --git a/lib/helpers/database/model_database_helper.dart b/lib/helpers/database/model_database_helper.dart index addddff..dbbb94d 100644 --- a/lib/helpers/database/model_database_helper.dart +++ b/lib/helpers/database/model_database_helper.dart @@ -18,12 +18,12 @@ abstract class ModelDatabaseHelper { /// Insert an entry in the database Future _insertDB(T el) async { - await (await DatabaseHelper.get()).insert(tableName(), el.toMap()); + await (await DatabaseHelper.get())!.insert(tableName(), el.toMap()); } /// Update an element in the database Future _updateDB(T el) async { - await (await DatabaseHelper.get()).update( + await (await DatabaseHelper.get())!.update( tableName(), el.toMap(), where: "${BaseTableContract.C_ID} = ?", @@ -34,14 +34,14 @@ abstract class ModelDatabaseHelper { /// Get an element from the database with a specified [id] /// /// Returns null if none found - Future get(int id) async { - List maps = await (await DatabaseHelper.get()).query( + Future get(int id) async { + List maps = await (await DatabaseHelper.get())!.query( tableName(), where: '${BaseTableContract.C_ID} = ?', whereArgs: [id], ); - if (maps.length > 0) return initializeFromMap(maps[0]); + if (maps.length > 0) return initializeFromMap(maps[0] as Map); return null; } @@ -50,7 +50,7 @@ abstract class ModelDatabaseHelper { /// /// Return true if at least one entry was deleted / false else Future delete(int id) async { - return await (await DatabaseHelper.get()).delete( + return await (await DatabaseHelper.get())!.delete( tableName(), where: '${BaseTableContract.C_ID} = ?', whereArgs: [id], @@ -59,22 +59,22 @@ abstract class ModelDatabaseHelper { /// Get all the entries from the table Future> getAll() async { - List maps = await (await DatabaseHelper.get()).query(tableName()); - return maps.map((f) => initializeFromMap(f)).toList(); + List maps = await (await DatabaseHelper.get())!.query(tableName()); + return maps.map((f) => initializeFromMap(f as Map)).toList(); } /// Get some entries from the table based on some conditions Future> getMultiple( - {bool distinct, - List columns, - String where, - List whereArgs, - String groupBy, - String having, - String orderBy, - int limit, - int offset}) async { - List maps = await (await DatabaseHelper.get()).query( + {bool? distinct, + List? columns, + String? where, + List? whereArgs, + String? groupBy, + String? having, + String? orderBy, + int? limit, + int? offset}) async { + List maps = await (await DatabaseHelper.get())!.query( tableName(), distinct: distinct, columns: columns, @@ -86,12 +86,12 @@ abstract class ModelDatabaseHelper { limit: limit, offset: offset, ); - return maps.map((f) => initializeFromMap(f)).toList(); + return maps.map((f) => initializeFromMap(f as Map)).toList(); } /// Empty the table Future clearTable() async { - await (await DatabaseHelper.get()).execute("DELETE FROM ${tableName()}"); + await (await DatabaseHelper.get())!.execute("DELETE FROM ${tableName()}"); } /// Check out whether an element specified with its [id] is present diff --git a/lib/helpers/events_helper.dart b/lib/helpers/events_helper.dart index 1fea463..d8dd6bc 100644 --- a/lib/helpers/events_helper.dart +++ b/lib/helpers/events_helper.dart @@ -17,14 +17,14 @@ class WSClosedEvent {} /// New number of notifications class NewNumberNotifsEvent { - final int newNum; + final int? newNum; NewNumberNotifsEvent(this.newNum); } /// New number of unread conversations class NewNumberUnreadConversations { - final int newNum; + final int? newNum; NewNumberUnreadConversations(this.newNum); } @@ -45,15 +45,15 @@ class UpdatedCommentEvent { /// Deleted comment class DeletedCommentEvent { - final int commentID; + final int? commentID; DeletedCommentEvent(this.commentID); } /// Writing message in conversation event class WritingMessageInConversationEvent { - final int convID; - final int userID; + final int? convID; + final int? userID; WritingMessageInConversationEvent(this.convID, this.userID); } @@ -81,31 +81,31 @@ class DeletedConversationMessageEvent { /// Remove user from conversation class RemovedUserFromConversationEvent { - final int convID; - final int userID; + final int? convID; + final int? userID; RemovedUserFromConversationEvent(this.convID, this.userID); } /// Deleted conversation class DeletedConversationEvent { - final int convID; + final int? convID; DeletedConversationEvent(this.convID); } /// User joined call event class UserJoinedCallEvent { - final int callID; - final int userID; + final int? callID; + final int? userID; UserJoinedCallEvent(this.callID, this.userID); } /// User left call event class UserLeftCallEvent { - final int callID; - final int userID; + final int? callID; + final int? userID; UserLeftCallEvent(this.callID, this.userID); } @@ -114,12 +114,12 @@ class UserLeftCallEvent { class NewCallSignalEvent { final int callID; final int peerID; - final RTCSessionDescription sessionDescription; - final RTCIceCandidate candidate; + final RTCSessionDescription? sessionDescription; + final RTCIceCandidate? candidate; const NewCallSignalEvent({ - this.callID, - this.peerID, + required this.callID, + required this.peerID, this.sessionDescription, this.candidate, }) : assert(callID != null), @@ -129,23 +129,23 @@ class NewCallSignalEvent { /// Call peer ready event class CallPeerReadyEvent { - final int callID; - final int peerID; + final int? callID; + final int? peerID; CallPeerReadyEvent(this.callID, this.peerID); } /// Call peer interrupted streaming event class CallPeerInterruptedStreamingEvent { - final int callID; - final int peerID; + final int? callID; + final int? peerID; CallPeerInterruptedStreamingEvent(this.callID, this.peerID); } /// Call closed event class CallClosedEvent { - final int callID; + final int? callID; CallClosedEvent(this.callID); } diff --git a/lib/helpers/firebase_messaging_helper.dart b/lib/helpers/firebase_messaging_helper.dart index be8da5d..d76719c 100644 --- a/lib/helpers/firebase_messaging_helper.dart +++ b/lib/helpers/firebase_messaging_helper.dart @@ -20,7 +20,7 @@ class FirebaseMessagingHelper { } /// Get a Firebase access token - static Future getToken() async { + static Future getToken() async { return await FirebaseMessaging.instance.getToken(); } } diff --git a/lib/helpers/forez_groups_helper.dart b/lib/helpers/forez_groups_helper.dart index aa8c14d..7844c68 100644 --- a/lib/helpers/forez_groups_helper.dart +++ b/lib/helpers/forez_groups_helper.dart @@ -11,7 +11,7 @@ import 'package:comunic/models/group.dart'; class ForezGroupsHelper { static Future> getForezGroups() async { return (await APIRequest.withLogin("forez/get_groups").execWithThrow()) - .getArray() + .getArray()! .cast>() .map(GroupsHelper.getGroupFromAPI) .toList(); @@ -21,10 +21,10 @@ class ForezGroupsHelper { /// /// This methods throws an exception in case of failure static Future getMemberInfo(int groupID, int userID) async { - final response = await APIRequest.withLogin("forez/get_member_info") + final response = await (APIRequest.withLogin("forez/get_member_info") .addInt("group", groupID) .addInt("user", userID) - .execWithThrowGetObject(); + .execWithThrowGetObject()); return UsersHelper.apiToAdvancedUserInfo(response); } diff --git a/lib/helpers/forez_presence_helper.dart b/lib/helpers/forez_presence_helper.dart index d3f3d4f..2b8169e 100644 --- a/lib/helpers/forez_presence_helper.dart +++ b/lib/helpers/forez_presence_helper.dart @@ -6,8 +6,8 @@ import 'package:comunic/models/forez_presence.dart'; /// /// @author Pierre Hubert -int _cachedGroup; -PresenceSet _cache; +int? _cachedGroup; +PresenceSet? _cache; class ForezPresenceHelper { /// Refresh presence cache @@ -40,16 +40,16 @@ class ForezPresenceHelper { /// Get the presences of a given user /// /// Throws in case of failure - static Future getForUser(int groupID, int userID) async { + static Future getForUser(int groupID, int? userID) async { await _checkCache(groupID); - return _cache.getForUser(userID); + return _cache!.getForUser(userID); } /// Get all the available presences /// /// Throws in case of failure - static Future getAll(int groupID) async { + static Future getAll(int groupID) async { await _checkCache(groupID); return _cache; } diff --git a/lib/helpers/friends_helper.dart b/lib/helpers/friends_helper.dart index 5b7366f..f0782ae 100644 --- a/lib/helpers/friends_helper.dart +++ b/lib/helpers/friends_helper.dart @@ -3,7 +3,6 @@ import 'package:comunic/lists/friends_list.dart'; import 'package:comunic/models/api_request.dart'; import 'package:comunic/models/friend.dart'; import 'package:comunic/models/friend_status.dart'; -import 'package:meta/meta.dart'; /// Friends helper /// @@ -16,7 +15,7 @@ class FriendsHelper { /// /// Returns the list of friends in case of success, or null if an error /// occurred - Future _downloadList() async { + Future _downloadList() async { final response = await APIRequest( uri: "friends/getList", needLogin: true, @@ -30,7 +29,7 @@ class FriendsHelper { // Parse and return the list of friends FriendsList list = FriendsList() ..addAll(response - .getArray() + .getArray()! .cast>() .map(apiToFriend) .toList()); @@ -54,7 +53,7 @@ class FriendsHelper { } /// Get the list, either from an online or an offline source - Future getList({@required bool online}) async { + Future getList({required bool online}) async { if (online) return await _downloadList(); else @@ -108,7 +107,7 @@ class FriendsHelper { if (response.code != 200) throw Exception("Could not get friendship status!"); - final obj = response.getObject(); + final obj = response.getObject()!; return FriendStatus( userID: userID, @@ -132,7 +131,7 @@ class FriendsHelper { if (response.code != 200) throw new Exception("Could not get the list of friends of this user!"); - return Set.from(response.getArray()); + return Set.from(response.getArray()!); } /// Send a friendship request to a specified user diff --git a/lib/helpers/groups_helper.dart b/lib/helpers/groups_helper.dart index 64004c9..1e7f2c6 100644 --- a/lib/helpers/groups_helper.dart +++ b/lib/helpers/groups_helper.dart @@ -49,7 +49,7 @@ enum GetAdvancedInfoStatus { SUCCESS, ACCESS_DENIED } class GetAdvancedInfoResult { final GetAdvancedInfoStatus status; - final AdvancedGroupInfo info; + final AdvancedGroupInfo? info; GetAdvancedInfoResult(this.status, this.info) : assert(status != null); } @@ -57,7 +57,7 @@ class GetAdvancedInfoResult { /// Groups helper class GroupsHelper { /// Download a list of groups information from the server - Future _downloadList(Set groups) async { + Future _downloadList(Set groups) async { final response = await APIRequest( uri: "groups/get_multiple_info", needLogin: true, @@ -69,7 +69,7 @@ class GroupsHelper { final list = GroupsList(); response - .getObject() + .getObject()! .forEach((k, d) => list[int.parse(k)] = getGroupFromAPI(d)); return list; @@ -77,7 +77,7 @@ class GroupsHelper { /// Get a list of groups from the server. In case of error, this method throws /// an exception - Future getListOrThrow(Set groups, + Future getListOrThrow(Set groups, {bool force = false}) async { final list = await getList(groups, force: force); @@ -87,11 +87,11 @@ class GroupsHelper { } /// Get a list of groups from the server - Future getList(Set groups, {bool force = false}) async { + Future getList(Set groups, {bool force = false}) async { final list = GroupsList(); // Check which groups information to download - final toDownload = Set(); + final toDownload = Set(); groups.forEach((groupID) { if (!force && _groupsListCache.containsKey(groupID)) list[groupID] = _groupsListCache[groupID]; @@ -122,10 +122,10 @@ class GroupsHelper { } /// Get the list of groups of a user - Future> getListUser() async => + Future> getListUser() async => (await APIRequest(uri: "groups/get_my_list", needLogin: true).exec()) .assertOk() - .getArray() + .getArray()! .map((f) => cast(f)) .toSet(); @@ -142,7 +142,7 @@ class GroupsHelper { /// Perform a simple membership request static Future _simpleMembershipRequest(int groupID, String uri, - {Map args}) async => + {Map? args}) async => (await (APIRequest.withLogin(uri) ..addInt("id", groupID) ..addArgs(args == null ? Map() : args)) @@ -176,7 +176,7 @@ class GroupsHelper { .isOK; /// Get advanced information about the user - Future getAdvancedInfo(int groupID) async { + Future getAdvancedInfo(int? groupID) async { // Get advanced information about the user final result = await (APIRequest(uri: "groups/get_advanced_info", needLogin: true) @@ -189,7 +189,7 @@ class GroupsHelper { case 200: return GetAdvancedInfoResult(GetAdvancedInfoStatus.SUCCESS, - _getAdvancedGroupInfoFromAPI(result.getObject())); + _getAdvancedGroupInfoFromAPI(result.getObject()!)); default: throw Exception("Could not get advanced group information!"); @@ -202,7 +202,7 @@ class GroupsHelper { /// change in the future /// /// Throws in case of error - Future getSettings(int groupID) async { + Future getSettings(int groupID) async { final groupInfo = await getAdvancedInfo(groupID); if (groupInfo.status != GetAdvancedInfoStatus.SUCCESS) @@ -239,7 +239,7 @@ class GroupsHelper { "posts_level", invertMap( _APIGroupsPostsCreationLevelsMap)[settings.postCreationLevel]) - .addBool("is_members_list_public", settings.isMembersListPublic) + .addBool("is_members_list_public", settings.isMembersListPublic!) .addString("description", settings.description) .addString("url", settings.url) .execWithThrow(); @@ -248,7 +248,7 @@ class GroupsHelper { /// Upload a new logo /// /// Throws in case of failure - static Future uploadNewLogo(int groupID, Uint8List bytes) async => + static Future uploadNewLogo(int groupID, Uint8List? bytes) async => await APIRequest(uri: "groups/upload_logo", needLogin: true) .addInt("id", groupID) .addBytesFile("logo", BytesFile("logo.png", bytes)) @@ -279,7 +279,7 @@ class GroupsHelper { ..addAll((await APIRequest(uri: "groups/get_members", needLogin: true) .addInt("id", groupID) .execWithThrow()) - .getArray() + .getArray()! .map((f) => _apiToGroupMembership(f)) .toList()); @@ -295,7 +295,7 @@ class GroupsHelper { /// Cancel a group membership invitation /// /// Throws an exception in case of failure - static Future cancelInvitation(int groupID, int userID) async => + static Future cancelInvitation(int groupID, int? userID) async => await APIRequest.withLogin("groups/cancel_invitation") .addInt("groupID", groupID) .addInt("userID", userID) @@ -305,7 +305,7 @@ class GroupsHelper { /// /// Throws an exception in case of failure static Future respondRequest( - int groupID, int userID, bool accept) async => + int groupID, int? userID, bool accept) async => await APIRequest.withLogin("groups/respond_request") .addInt("groupID", groupID) .addInt("userID", userID) @@ -351,7 +351,7 @@ class GroupsHelper { /// /// Throws in case of failure static Future setConversationVisibility( - int convID, GroupMembershipLevel newLevel) async => + int? convID, GroupMembershipLevel? newLevel) async => await APIRequest.withLogin("groups/set_conversation_visibility") .addInt("conv_id", convID) .addString( @@ -364,7 +364,7 @@ class GroupsHelper { /// Delete a group's conversation /// /// Throws in case of failure - static Future deleteConversation(int convID) async => + static Future deleteConversation(int? convID) async => await APIRequest.withLogin("groups/delete_conversation") .addInt("conv_id", convID) .execWithThrow(); @@ -376,11 +376,11 @@ class GroupsHelper { name: map["name"], iconURL: map["icon_url"], numberMembers: map["number_members"], - membershipLevel: APIGroupsMembershipLevelsMap[map["membership"]], - visibilityLevel: _APIGroupsVisibilityLevelsMap[map["visibility"]], + membershipLevel: APIGroupsMembershipLevelsMap[map["membership"]]!, + visibilityLevel: _APIGroupsVisibilityLevelsMap[map["visibility"]]!, registrationLevel: - _APIGroupsRegistrationLevelsMap[map["registration_level"]], - postCreationLevel: _APIGroupsPostsCreationLevelsMap[map["posts_level"]], + _APIGroupsRegistrationLevelsMap[map["registration_level"]]!, + postCreationLevel: _APIGroupsPostsCreationLevelsMap[map["posts_level"]]!, virtualDirectory: nullToEmpty(map["virtual_directory"]), following: map["following"]); } @@ -392,11 +392,11 @@ class GroupsHelper { name: map["name"], iconURL: map["icon_url"], numberMembers: map["number_members"], - membershipLevel: APIGroupsMembershipLevelsMap[map["membership"]], - visibilityLevel: _APIGroupsVisibilityLevelsMap[map["visibility"]], + membershipLevel: APIGroupsMembershipLevelsMap[map["membership"]]!, + visibilityLevel: _APIGroupsVisibilityLevelsMap[map["visibility"]]!, registrationLevel: - _APIGroupsRegistrationLevelsMap[map["registration_level"]], - postCreationLevel: _APIGroupsPostsCreationLevelsMap[map["posts_level"]], + _APIGroupsRegistrationLevelsMap[map["registration_level"]]!, + postCreationLevel: _APIGroupsPostsCreationLevelsMap[map["posts_level"]]!, isMembersListPublic: map["is_members_list_public"], virtualDirectory: nullToEmpty(map["virtual_directory"]), following: map["following"], @@ -418,6 +418,6 @@ class GroupsHelper { userID: row["user_id"], groupID: row["group_id"], timeCreate: row["time_create"], - level: APIGroupsMembershipLevelsMap[row["level"]], + level: APIGroupsMembershipLevelsMap[row["level"]]!, ); } diff --git a/lib/helpers/independent_push_notifications_helper.dart b/lib/helpers/independent_push_notifications_helper.dart index 30710d3..7227da4 100644 --- a/lib/helpers/independent_push_notifications_helper.dart +++ b/lib/helpers/independent_push_notifications_helper.dart @@ -29,7 +29,7 @@ class IndependentPushNotificationsHelper { } /// Configure independent push notification services with a pull URL - static Future configure(String wsURL) async { + static Future configure(String? wsURL) async { await platform.invokeMethod("configure", wsURL); } diff --git a/lib/helpers/likes_helper.dart b/lib/helpers/likes_helper.dart index c319660..d9be376 100644 --- a/lib/helpers/likes_helper.dart +++ b/lib/helpers/likes_helper.dart @@ -1,6 +1,5 @@ import 'package:comunic/enums/likes_type.dart'; import 'package:comunic/helpers/websocket_helper.dart'; -import 'package:meta/meta.dart'; /// Likes helper /// @@ -16,9 +15,9 @@ const LikesAPIMap = { class LikesHelper { /// Update liking status of an element Future setLiking({ - @required LikesType type, - @required bool like, - @required int id, + required LikesType type, + required bool like, + required int id, }) async { return (await ws("likes/update", { "type": LikesAPIMap[type], diff --git a/lib/helpers/notifications_helper.dart b/lib/helpers/notifications_helper.dart index 7afe452..761c283 100644 --- a/lib/helpers/notifications_helper.dart +++ b/lib/helpers/notifications_helper.dart @@ -55,7 +55,7 @@ class NotificationsHelper { await APIRequest(uri: "notifications/count_all_news", needLogin: true) .exec(); - final content = response.assertOk().getObject(); + final content = response.assertOk().getObject()!; return CountUnreadNotifications( notifications: content["notifications"], @@ -75,15 +75,15 @@ class NotificationsHelper { // Parse the list of notifications return NotificationsList() ..addAll(response - .getArray() + .getArray()! .map((f) => Notification( id: f["id"], timeCreate: f["time_create"], seen: f["seen"], fromUser: f["from_user_id"], onElemId: f["on_elem_id"], - onElemType: _NotificationElementTypeAPImapping[f["on_elem_type"]], - type: _NotificationsTypeAPImapping[f["type"]], + onElemType: _NotificationElementTypeAPImapping[f["on_elem_type"]]!, + type: _NotificationsTypeAPImapping[f["type"]]!, fromContainerId: f["from_container_id"], fromContainerType: f["from_container_type"] == "" ? null diff --git a/lib/helpers/posts_helper.dart b/lib/helpers/posts_helper.dart index f951963..e84f3b8 100644 --- a/lib/helpers/posts_helper.dart +++ b/lib/helpers/posts_helper.dart @@ -55,7 +55,7 @@ class PostsHelper { /// Get the list of latest posts. Return the list of posts or null in case of /// failure - Future getLatest({int from = 0}) async { + Future getLatest({int from = 0}) async { final response = await APIRequest(uri: "posts/get_latest", needLogin: true, args: { "include_groups": true.toString(), @@ -66,7 +66,8 @@ class PostsHelper { try { // Parse & return the list of posts - return PostsList()..addAll(response.getArray().map((f) => _apiToPost(f))); + return PostsList() + ..addAll(response.getArray()!.map((f) => _apiToPost(f))); } catch (e) { print(e.toString()); return null; @@ -74,7 +75,7 @@ class PostsHelper { } /// Get the list of posts of a user - Future getUserPosts(int userID, {int from = 0}) async { + Future getUserPosts(int? userID, {int from = 0}) async { final response = await (APIRequest(uri: "posts/get_user", needLogin: true) ..addInt("userID", userID) ..addInt("startFrom", from == 0 ? 0 : from - 1)) @@ -84,7 +85,8 @@ class PostsHelper { try { // Parse & return the list of posts - return PostsList()..addAll(response.getArray().map((f) => _apiToPost(f))); + return PostsList() + ..addAll(response.getArray()!.map((f) => _apiToPost(f))); } catch (e) { print(e.toString()); return null; @@ -92,7 +94,7 @@ class PostsHelper { } /// Get the list of posts of a group - Future getGroupPosts(int groupID, {int from = 0}) async { + Future getGroupPosts(int groupID, {int from = 0}) async { final response = await (APIRequest(uri: "posts/get_group", needLogin: true) ..addInt("groupID", groupID) ..addInt("startFrom", from == 0 ? 0 : from - 1)) @@ -102,7 +104,8 @@ class PostsHelper { try { // Parse & return the list of posts - return PostsList()..addAll(response.getArray().map((f) => _apiToPost(f))); + return PostsList() + ..addAll(response.getArray()!.map((f) => _apiToPost(f))); } catch (e) { print(e.toString()); return null; @@ -120,7 +123,7 @@ class PostsHelper { if (!response.isOK) throw Exception("Could not get information about the post!"); - return _apiToPost(response.getObject()); + return _apiToPost(response.getObject()!); } /// Create a new post @@ -158,13 +161,14 @@ class PostsHelper { case PostKind.COUNTDOWN: request.addInt( - "time-end", (post.timeEnd.millisecondsSinceEpoch / 1000).floor()); + "time-end", (post.timeEnd!.millisecondsSinceEpoch / 1000).floor()); break; case PostKind.SURVEY: - request.addString("question", post.survey.question); - request.addString("answers", post.survey.answers.join("<>")); - request.addBool("allowNewAnswers", post.survey.allowNewChoicesCreation); + request.addString("question", post.survey!.question); + request.addString("answers", post.survey!.answers.join("<>")); + request.addBool( + "allowNewAnswers", post.survey!.allowNewChoicesCreation); break; case PostKind.YOUTUBE: @@ -221,7 +225,7 @@ class PostsHelper { /// Register to a post events Future registerPostEvents(int id) async { if (_registeredPosts.containsKey(id)) - _registeredPosts[id]++; + _registeredPosts.update(id, (v) => v + 1); else { _registeredPosts[id] = 1; await ws("\$main/register_post", {"postID": id}); @@ -232,9 +236,9 @@ class PostsHelper { Future unregisterPostEvents(int id) async { if (!_registeredPosts.containsKey(id)) return; - _registeredPosts[id]--; + _registeredPosts.update(id, (v) => v - 1); - if (_registeredPosts[id] <= 0) { + if (_registeredPosts[id]! <= 0) { _registeredPosts.remove(id); await ws("\$main/unregister_post", {"postID": id}); } @@ -242,14 +246,14 @@ class PostsHelper { /// Turn an API entry into a [Post] object Post _apiToPost(Map map) { - final postKind = _APIPostsKindsMap[map["kind"]]; + final postKind = _APIPostsKindsMap[map["kind"]]!; // Parse comments - CommentsList comments; + CommentsList? comments; if (map["comments"] != null) { comments = CommentsList(); map["comments"] - .forEach((v) => comments.add(CommentsHelper.apiToComment(v))); + .forEach((v) => comments!.add(CommentsHelper.apiToComment(v))); } final survey = postKind == PostKind.SURVEY @@ -263,7 +267,7 @@ class PostsHelper { groupID: map["group_id"], timeSent: map["post_time"], content: DisplayedString(map["content"]), - visibilityLevel: _APIPostsVisibilityLevelMap[map["visibility_level"]], + visibilityLevel: _APIPostsVisibilityLevelMap[map["visibility_level"]]!, kind: postKind, fileSize: map["file_size"], fileType: map["file_type"], @@ -276,7 +280,7 @@ class PostsHelper { linkImage: map["link_image"], likes: map["likes"], userLike: map["userlike"], - access: _APIUserAccessMap[map["user_access"]], + access: _APIUserAccessMap[map["user_access"]]!, comments: comments, survey: survey); } diff --git a/lib/helpers/preferences_helper.dart b/lib/helpers/preferences_helper.dart index 2486621..bafc4ae 100644 --- a/lib/helpers/preferences_helper.dart +++ b/lib/helpers/preferences_helper.dart @@ -30,7 +30,7 @@ const _PreferenceKeysName = { }; class PreferencesHelper { - static PreferencesHelper _instance; + static PreferencesHelper? _instance; static Future getInstance() async { if (_instance == null) { @@ -38,10 +38,10 @@ class PreferencesHelper { await _init(); } - return _instance; + return _instance!; } - static SharedPreferences _sharedPreferences; + static late SharedPreferences _sharedPreferences; PreferencesHelper._(); @@ -50,7 +50,7 @@ class PreferencesHelper { } /// Set new login tokens - Future setLoginToken(String token) async { + Future setLoginToken(String? token) async { if (token != null) await setString(PreferencesKeyList.LOGIN_TOKEN, token); else @@ -58,7 +58,7 @@ class PreferencesHelper { } /// Get current [LoginTokens]. Returns null if none or in case of failure - String getLoginToken() { + String? getLoginToken() { try { final string = getString(PreferencesKeyList.LOGIN_TOKEN); return string; @@ -69,35 +69,35 @@ class PreferencesHelper { } bool containsKey(PreferencesKeyList key) { - return _sharedPreferences.containsKey(_PreferenceKeysName[key]); + return _sharedPreferences.containsKey(_PreferenceKeysName[key]!); } Future removeKey(PreferencesKeyList key) async { - return await _sharedPreferences.remove(_PreferenceKeysName[key]); + return await _sharedPreferences.remove(_PreferenceKeysName[key]!); } Future setString(PreferencesKeyList key, String value) async { - return await _sharedPreferences.setString(_PreferenceKeysName[key], value); + return await _sharedPreferences.setString(_PreferenceKeysName[key]!, value); } - String getString(PreferencesKeyList key) { - return _sharedPreferences.getString(_PreferenceKeysName[key]); + String? getString(PreferencesKeyList key) { + return _sharedPreferences.getString(_PreferenceKeysName[key]!); } Future setBool(PreferencesKeyList key, bool value) async { - return await _sharedPreferences.setBool(_PreferenceKeysName[key], value); + return await _sharedPreferences.setBool(_PreferenceKeysName[key]!, value); } Future setInt(PreferencesKeyList key, int value) async { - return await _sharedPreferences.setInt(_PreferenceKeysName[key], value); + return await _sharedPreferences.setInt(_PreferenceKeysName[key]!, value); } - int getInt(PreferencesKeyList key) { - return _sharedPreferences.getInt(_PreferenceKeysName[key]); + int? getInt(PreferencesKeyList key) { + return _sharedPreferences.getInt(_PreferenceKeysName[key]!); } bool getBool(PreferencesKeyList key, {bool alternative = false}) { - final v = _sharedPreferences.getBool(_PreferenceKeysName[key]); + final v = _sharedPreferences.getBool(_PreferenceKeysName[key]!); return v == null ? alternative : v; } @@ -115,7 +115,7 @@ class PreferencesHelper { } } -PreferencesHelper preferences() { +PreferencesHelper? preferences() { if (PreferencesHelper._instance == null) throw Exception("Try to get preference before their initialization!"); diff --git a/lib/helpers/push_notifications_helper.dart b/lib/helpers/push_notifications_helper.dart index 6b82888..5064397 100644 --- a/lib/helpers/push_notifications_helper.dart +++ b/lib/helpers/push_notifications_helper.dart @@ -21,14 +21,14 @@ const _PushNotificationsAPIMap = { class PushNotificationsHelper { /// Get cached status of push notifications - static Future getLocalStatus() async { + static Future getLocalStatus() async { final pref = await PreferencesHelper.getInstance(); if (!pref.containsKey(PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS)) return PushNotificationsStatus.UNDEFINED; return _PushNotificationsAPIMap[ - pref.getString(PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS)]; + pref.getString(PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS)!]; } /// Refresh local status with information from server @@ -47,13 +47,13 @@ class PushNotificationsHelper { response["independent_push_url"]); } - await (await PreferencesHelper.getInstance()).setString( + await (await PreferencesHelper.getInstance())!.setString( PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS, response["status"]); } /// Clear local push notifications status static Future clearLocalStatus() async { - await (await PreferencesHelper.getInstance()) + await (await PreferencesHelper.getInstance())! .removeKey(PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS); // Stop local refresh notification refresh @@ -62,8 +62,8 @@ class PushNotificationsHelper { /// Configure push notifications static Future configure( - BuildContext context, PushNotificationsStatus newStatus) async { - String firebaseToken = ""; + BuildContext context, PushNotificationsStatus? newStatus) async { + String? firebaseToken = ""; switch (newStatus) { case PushNotificationsStatus.DISABLED: break; @@ -90,8 +90,8 @@ class PushNotificationsHelper { /// Set new push notification status on the server static Future setNewStatus( - PushNotificationsStatus newStatus, { - String firebaseToken = "", + PushNotificationsStatus? newStatus, { + String? firebaseToken = "", }) async => await APIRequest.withLogin("push_notifications/configure") .addString( @@ -104,6 +104,6 @@ class PushNotificationsHelper { /// Is true if possible if push notifications are configurable static bool get arePushNotificationsAvailable => - srvConfig.notificationsPolicy.hasFirebase || - (isAndroid && srvConfig.notificationsPolicy.hasIndependent); + srvConfig!.notificationsPolicy.hasFirebase || + (isAndroid && srvConfig!.notificationsPolicy.hasIndependent); } diff --git a/lib/helpers/search_helper.dart b/lib/helpers/search_helper.dart index eb3a340..dd26617 100644 --- a/lib/helpers/search_helper.dart +++ b/lib/helpers/search_helper.dart @@ -13,7 +13,7 @@ class SearchHelper { /// Search for user. This method returns information about the target users /// /// Returns information about the target users or null if an error occurred - Future searchUser(String query) async { + Future searchUser(String query) async { // Execute the query on the server final response = await APIRequest( uri: "user/search", needLogin: true, args: {"query": query}).exec(); @@ -21,7 +21,7 @@ class SearchHelper { if (response.code != 200) return null; return await UsersHelper() - .getUsersInfo(response.getArray().map((f) => cast(f)).toList()); + .getUsersInfo(response.getArray()!.map((f) => cast(f)).toList()); } /// Perform a global search @@ -31,7 +31,7 @@ class SearchHelper { result.assertOk(); - return SearchResultsList()..addAll(result.getArray().map((f) { + return SearchResultsList()..addAll(result.getArray()!.map((f) { switch (f["kind"]) { case "user": return SearchResult(id: f["id"], kind: SearchResultKind.USER); diff --git a/lib/helpers/serialization/base_serialization_helper.dart b/lib/helpers/serialization/base_serialization_helper.dart index cf4df6c..dedf6e2 100644 --- a/lib/helpers/serialization/base_serialization_helper.dart +++ b/lib/helpers/serialization/base_serialization_helper.dart @@ -17,7 +17,7 @@ abstract class SerializableElement extends Comparable { abstract class BaseSerializationHelper { /// List cache - List _cache; + List? _cache; /// The name of the type of data to serialise String get type; @@ -48,12 +48,15 @@ abstract class BaseSerializationHelper { try { final file = await _getFilePath(); - if (!await file.exists()) return _cache = []; + if (!await file.exists()) { + _cache = []; + return; + } final List json = jsonDecode(await file.readAsString()); _cache = json.cast>().map(parse).toList(); - _cache.sort(); + _cache!.sort(); } catch (e, s) { logError(e, s); print("Failed to read serialized data!"); @@ -67,8 +70,10 @@ abstract class BaseSerializationHelper { try { final file = await _getFilePath(); - await file.writeAsString(jsonEncode( - _cache.map((e) => e.toJson()).toList().cast>())); + await file.writeAsString(jsonEncode(_cache! + .map((e) => e.toJson()) + .toList() + .cast>())); } catch (e, s) { print("Failed to write file!"); logError(e, s); @@ -78,7 +83,7 @@ abstract class BaseSerializationHelper { /// Get the current list of elements Future> getList() async { await _loadCache(); - return List.from(_cache); + return List.from(_cache!); } /// Set a new list of conversations @@ -90,23 +95,23 @@ abstract class BaseSerializationHelper { /// Insert new element Future insert(T el) async { await _loadCache(); - _cache.add(el); - _cache.sort(); + _cache!.add(el); + _cache!.sort(); await _saveCache(); } /// Insert new element Future insertMany(List els) async { await _loadCache(); - _cache.addAll(els); - _cache.sort(); + _cache!.addAll(els); + _cache!.sort(); await _saveCache(); } /// Check if any entry in the last match the predicate Future any(bool isContained(T t)) async { await _loadCache(); - return _cache.any((element) => isContained(element)); + return _cache!.any((element) => isContained(element)); } Future has(T el) => any((t) => t == el); @@ -114,7 +119,7 @@ abstract class BaseSerializationHelper { /// Check if any entry in the last match the predicate Future first(bool filter(T t)) async { await _loadCache(); - return _cache.firstWhere((element) => filter(element)); + return _cache!.firstWhere((element) => filter(element)); } /// Replace an element with another one @@ -122,10 +127,10 @@ abstract class BaseSerializationHelper { await _loadCache(); // Insert or replace the element - _cache = _cache.where((element) => !isToReplace(element)).toList(); - _cache.add(newEl); + _cache = _cache!.where((element) => !isToReplace(element)).toList(); + _cache!.add(newEl); - _cache.sort(); + _cache!.sort(); await _saveCache(); } @@ -133,8 +138,8 @@ abstract class BaseSerializationHelper { Future insertOrReplaceElements(List list) async { await _loadCache(); - _cache.removeWhere((element) => list.any((newEl) => element == newEl)); - _cache.addAll(list); + _cache!.removeWhere((element) => list.any((newEl) => element == newEl)); + _cache!.addAll(list); await _saveCache(); } @@ -142,7 +147,7 @@ abstract class BaseSerializationHelper { /// Remove elements Future removeElement(bool isToRemove(T t)) async { await _loadCache(); - _cache.removeWhere((element) => isToRemove(element)); + _cache!.removeWhere((element) => isToRemove(element)); await _saveCache(); } diff --git a/lib/helpers/serialization/conversation_message_serialization_helper.dart b/lib/helpers/serialization/conversation_message_serialization_helper.dart index 8afa5df..4175f69 100644 --- a/lib/helpers/serialization/conversation_message_serialization_helper.dart +++ b/lib/helpers/serialization/conversation_message_serialization_helper.dart @@ -8,7 +8,7 @@ import 'package:comunic/models/conversation_message.dart'; /// /// @author Pierre Hubert -HashMap _instances; +HashMap? _instances; class ConversationsMessagesSerializationHelper extends BaseSerializationHelper { @@ -18,13 +18,13 @@ class ConversationsMessagesSerializationHelper : convID = convID, assert(convID != null); - factory ConversationsMessagesSerializationHelper(int convID) { + factory ConversationsMessagesSerializationHelper(int? convID) { if (_instances == null) _instances = HashMap(); - if (!_instances.containsKey(convID)) - _instances[convID] = ConversationsMessagesSerializationHelper._(convID); + if (!_instances!.containsKey(convID)) + _instances![convID] = ConversationsMessagesSerializationHelper._(convID!); - return _instances[convID]; + return _instances![convID]!; } @override diff --git a/lib/helpers/serialization/conversations_serialization_helper.dart b/lib/helpers/serialization/conversations_serialization_helper.dart index 30ffbfe..1612530 100644 --- a/lib/helpers/serialization/conversations_serialization_helper.dart +++ b/lib/helpers/serialization/conversations_serialization_helper.dart @@ -28,5 +28,5 @@ class ConversationsSerializationHelper ConversationsList()..addAll(await super.getList()); /// Get a conversation - Future get(int id) => first((t) => t.id == id); + Future get(int? id) => first((t) => t.id == id); } diff --git a/lib/helpers/serialization/user_list_serialization_helper.dart b/lib/helpers/serialization/user_list_serialization_helper.dart index fa385c3..99de1b8 100644 --- a/lib/helpers/serialization/user_list_serialization_helper.dart +++ b/lib/helpers/serialization/user_list_serialization_helper.dart @@ -5,7 +5,7 @@ import 'package:comunic/models/user.dart'; /// /// @author Pierre Hubert -UsersListSerialisationHelper _singleton; +UsersListSerialisationHelper? _singleton; class UsersListSerialisationHelper extends BaseSerializationHelper { UsersListSerialisationHelper._(); @@ -13,7 +13,7 @@ class UsersListSerialisationHelper extends BaseSerializationHelper { factory UsersListSerialisationHelper() { if (_singleton == null) _singleton = UsersListSerialisationHelper._(); - return _singleton; + return _singleton!; } @override @@ -23,6 +23,6 @@ class UsersListSerialisationHelper extends BaseSerializationHelper { User parse(Map m) => User.fromJson(m); /// Remove a user by its ID - Future removeUserByID(int userID) => + Future removeUserByID(int? userID) => removeElement((t) => t.id == userID); } diff --git a/lib/helpers/server_config_helper.dart b/lib/helpers/server_config_helper.dart index 821ffd9..e16d45d 100644 --- a/lib/helpers/server_config_helper.dart +++ b/lib/helpers/server_config_helper.dart @@ -7,7 +7,7 @@ import 'package:version/version.dart'; /// @author Pierre Hubert class ServerConfigurationHelper { - static ServerConfig _config; + static ServerConfig? _config; /// Make sure the configuration has been correctly loaded static Future ensureLoaded() async { @@ -15,7 +15,7 @@ class ServerConfigurationHelper { final response = (await APIRequest.withoutLogin("server/config").execWithThrow()) - .getObject(); + .getObject()!; final banner = response["banner"]; final pushNotificationsPolicy = response["push_notifications"]; @@ -97,7 +97,7 @@ class ServerConfigurationHelper { } /// Get current server configuration, throwing if it is not loaded yet - static ServerConfig get config { + static ServerConfig? get config { if (_config == null) throw Exception( "Trying to access server configuration but it is not loaded yet!"); @@ -107,6 +107,6 @@ class ServerConfigurationHelper { } /// Shortcut for server configuration -ServerConfig get srvConfig => ServerConfigurationHelper.config; +ServerConfig? get srvConfig => ServerConfigurationHelper.config; -bool get showBanner => srvConfig.banner != null && srvConfig.banner.visible; \ No newline at end of file +bool get showBanner => srvConfig!.banner != null && srvConfig!.banner!.visible; \ No newline at end of file diff --git a/lib/helpers/settings_helper.dart b/lib/helpers/settings_helper.dart index 96c42bf..f172992 100644 --- a/lib/helpers/settings_helper.dart +++ b/lib/helpers/settings_helper.dart @@ -25,7 +25,7 @@ class SettingsHelper { final response = (await APIRequest(uri: "settings/get_general", needLogin: true).exec()) .assertOk() - .getObject(); + .getObject()!; return GeneralSettings( email: response["email"], @@ -88,13 +88,13 @@ class SettingsHelper { (await APIRequest(uri: "settings/get_account_image", needLogin: true) .exec()) .assertOk() - .getObject(); + .getObject()!; return AccountImageSettings( hasImage: response["has_image"], imageURL: response["image_url"], visibility: - _APIAccountImageVisibilityAPILevels[response["visibility"]]); + _APIAccountImageVisibilityAPILevels[response["visibility"]]!); } /// Upload a new account image @@ -143,7 +143,7 @@ class SettingsHelper { /// Delete a custom emoji /// /// Throws in case of failure - static Future deleteCustomEmoji(int emojiID) async => + static Future deleteCustomEmoji(int? emojiID) async => (await APIRequest(uri: "settings/delete_custom_emoji", needLogin: true) .addInt("emojiID", emojiID) .exec()) @@ -175,7 +175,7 @@ class SettingsHelper { (await APIRequest(uri: "settings/get_security", needLogin: true) .addString("password", password) .execWithThrow()) - .getObject(); + .getObject()!; return SecuritySettings( securityQuestion1: response["security_question_1"], @@ -207,7 +207,7 @@ class SettingsHelper { final response = (await APIRequest.withLogin("settings/get_data_conservation_policy") .execWithThrow()) - .getObject(); + .getObject()!; return DataConservationPolicySettings( inactiveAccountLifeTime: response["inactive_account_lifetime"], @@ -223,7 +223,7 @@ class SettingsHelper { /// /// Throws in case of failure static Future setDataConservationPolicy( - String password, DataConservationPolicySettings newSettings) async { + String? password, DataConservationPolicySettings newSettings) async { await APIRequest( uri: "settings/set_data_conservation_policy", needLogin: true) .addString("password", password) diff --git a/lib/helpers/survey_helper.dart b/lib/helpers/survey_helper.dart index c458bef..2e7e5d6 100644 --- a/lib/helpers/survey_helper.dart +++ b/lib/helpers/survey_helper.dart @@ -1,7 +1,6 @@ import 'package:comunic/models/api_request.dart'; import 'package:comunic/models/survey.dart'; import 'package:comunic/models/survey_choice.dart'; -import 'package:meta/meta.dart'; /// Survey helper /// @@ -13,7 +12,7 @@ class SurveyHelper { apiToSurvey((await APIRequest.withLogin("surveys/get_info") .addInt("postID", postID) .execWithThrow()) - .getObject()); + .getObject()!); /// Cancel the response of a user to a survey Future cancelResponse(Survey survey) async { @@ -26,7 +25,7 @@ class SurveyHelper { /// Send the response of a user to a survey Future respondToSurvey( - {@required Survey survey, @required SurveyChoice choice}) async { + {required Survey survey, required SurveyChoice choice}) async { assert(survey != null); assert(choice != null); diff --git a/lib/helpers/users_helper.dart b/lib/helpers/users_helper.dart index 157cb13..7af3e58 100644 --- a/lib/helpers/users_helper.dart +++ b/lib/helpers/users_helper.dart @@ -31,7 +31,7 @@ class UsersHelper { /// /// Return the list of users information in case of success, null in case of /// failure - Future _downloadInfo(List users) async { + Future _downloadInfo(List users) async { // Execute the request final response = await APIRequest( uri: "user/getInfoMultiple", @@ -42,7 +42,7 @@ class UsersHelper { if (response.code != 200) return null; final list = UsersList(); - response.getObject().forEach( + response.getObject()!.forEach( (k, v) => list.add( User( id: v["userID"], @@ -69,7 +69,7 @@ class UsersHelper { /// Get users information from a given [Set]. Throws an exception in case /// of failure - Future getListWithThrow(Set users, + Future getListWithThrow(Set users, {bool forceDownload = false}) async { final list = await getUsersInfo(users.toList(), forceDownload: forceDownload); @@ -82,16 +82,16 @@ class UsersHelper { } /// Get information about a single user. Throws in case of failure - Future getSingleWithThrow(int user, + Future getSingleWithThrow(int? user, {bool forceDownload = false}) async { - return (await getListWithThrow(Set()..add(user), + return (await getListWithThrow(Set()..add(user), forceDownload: forceDownload))[0]; } /// Get users information from a given [Set] /// /// Throws in case of failure - Future getList(Set users, + Future getList(Set users, {bool forceDownload = false}) async { final list = await getUsersInfo(users.toList()); @@ -104,13 +104,13 @@ class UsersHelper { /// /// If [forceDownload] is set to true, the data will always be retrieved from /// the server, otherwise cached data will be used if available - Future getUsersInfo(List users, + Future getUsersInfo(List users, {bool forceDownload = false}) async { - List toDownload = []; + List toDownload = []; UsersList list = UsersList(); // Check cache - for (int userID in users) { + for (int? userID in users) { if (!forceDownload && await UsersListSerialisationHelper().any((u) => u.id == userID)) list.add( @@ -151,7 +151,7 @@ class UsersHelper { throw new GetUserAdvancedUserError(cause); } - return apiToAdvancedUserInfo(response.getObject()); + return apiToAdvancedUserInfo(response.getObject()!); } /// Parse the list of custom emojies diff --git a/lib/helpers/version_helper.dart b/lib/helpers/version_helper.dart index 8bac1cb..91bc1db 100644 --- a/lib/helpers/version_helper.dart +++ b/lib/helpers/version_helper.dart @@ -7,15 +7,15 @@ import 'package:version/version.dart'; /// @author Pierre Hubert class VersionHelper { - static PackageInfo _info; + static PackageInfo? _info; static Future ensureLoaded() async { if (!isWeb) _info = await PackageInfo.fromPlatform(); } /// Get current version information - static PackageInfo get info => _info; + static PackageInfo? get info => _info; /// Get current application version, in parsed format - static Version get version => Version.parse(info.version); + static Version get version => Version.parse(info!.version); } diff --git a/lib/helpers/virtual_directory_helper.dart b/lib/helpers/virtual_directory_helper.dart index 1bcbe8d..681d8d9 100644 --- a/lib/helpers/virtual_directory_helper.dart +++ b/lib/helpers/virtual_directory_helper.dart @@ -1,5 +1,4 @@ import 'package:comunic/models/api_request.dart'; -import 'package:flutter/material.dart'; /// Virtual directory helper /// @@ -9,10 +8,10 @@ enum VirtualDirectoryType { USER, GROUP, NONE } class VirtualDirectoryResult { final VirtualDirectoryType type; - final int id; + final int? id; const VirtualDirectoryResult({ - @required this.type, + required this.type, this.id, }) : assert(type != null); } @@ -30,8 +29,8 @@ class VirtualDirectoryHelper { return VirtualDirectoryResult(type: VirtualDirectoryType.NONE); case 200: - final id = response.getObject()["id"]; - final kind = response.getObject()["kind"]; + final id = response.getObject()!["id"]; + final kind = response.getObject()!["kind"]; switch (kind) { case "user": return VirtualDirectoryResult( diff --git a/lib/helpers/webapp_helper.dart b/lib/helpers/webapp_helper.dart index 343e2b0..b6d48b8 100644 --- a/lib/helpers/webapp_helper.dart +++ b/lib/helpers/webapp_helper.dart @@ -15,7 +15,7 @@ class WebAppHelper { static Future getMemberships() async { final response = (await APIRequest.withLogin("webApp/getMemberships").execWithThrow()) - .getArray(); + .getArray()!; return MembershipList() ..addAll(response @@ -26,7 +26,7 @@ class WebAppHelper { } /// Turn an API entry into a membership entry - static Membership _apiToMembership(Map entry) { + static Membership? _apiToMembership(Map entry) { switch (entry["type"]) { case "conversation": return Membership.conversation( diff --git a/lib/helpers/websocket_helper.dart b/lib/helpers/websocket_helper.dart index 0288c47..68eaf92 100644 --- a/lib/helpers/websocket_helper.dart +++ b/lib/helpers/websocket_helper.dart @@ -15,7 +15,7 @@ import 'package:web_socket_channel/web_socket_channel.dart'; /// @author Pierre Hubert class WebSocketHelper { - static WebSocketChannel _ws; + static WebSocketChannel? _ws; static int _counter = 0; @@ -23,14 +23,14 @@ class WebSocketHelper { /// Check out whether we are currently connected to WebSocket or not static bool isConnected() { - return _ws != null && _ws.closeCode == null; + return _ws != null && _ws!.closeCode == null; } /// Get WebSocket access token - static Future _getWsToken() async => + static Future _getWsToken() async => (await APIRequest(uri: "ws/token", needLogin: true).exec()) .assertOk() - .getObject()["token"]; + .getObject()!["token"]; /// Connect to WebSocket static connect() async { @@ -47,7 +47,7 @@ class WebSocketHelper { // Connect _ws = WebSocketChannel.connect(wsURI); - _ws.stream.listen( + _ws!.stream.listen( // When we got data (data) { print("WS New data: $data"); @@ -75,7 +75,7 @@ class WebSocketHelper { /// Close current WebSocket (if any) static close() { - if (isConnected()) _ws.sink.close(); + if (isConnected()) _ws!.sink.close(); } /// Send a new message @@ -93,7 +93,7 @@ class WebSocketHelper { print("WS Send message: $msg"); - _ws.sink.add(msg); + _ws!.sink.add(msg); _requests[id] = completer; return completer.future; @@ -240,11 +240,11 @@ class WebSocketHelper { // Handles errors if (msg.title != "success") { - completer.completeError(Exception("Could not process request!")); + completer!.completeError(Exception("Could not process request!")); return; } - completer.complete(msg.data); + completer!.complete(msg.data); } } diff --git a/lib/lists/abstract_list.dart b/lib/lists/abstract_list.dart index de0c8da..68fba10 100644 --- a/lib/lists/abstract_list.dart +++ b/lib/lists/abstract_list.dart @@ -16,4 +16,7 @@ class AbstractList extends ListBase { @override void operator []=(int index, E value) => _list[index] = value; + + @override + void add(E element) => _list.add(element); } diff --git a/lib/lists/base_set.dart b/lib/lists/base_set.dart index d67724f..1e6f56d 100644 --- a/lib/lists/base_set.dart +++ b/lib/lists/base_set.dart @@ -11,7 +11,7 @@ class BaseSet extends SetBase { bool add(T value) => _set.add(value); @override - bool contains(Object element) => _set.contains(element); + bool contains(Object? element) => _set.contains(element); @override Iterator get iterator => _set.iterator; @@ -20,10 +20,10 @@ class BaseSet extends SetBase { int get length => _set.length; @override - T lookup(Object element) => _set.lookup(element); + T? lookup(Object? element) => _set.lookup(element); @override - bool remove(Object value) => _set.remove(value); + bool remove(Object? value) => _set.remove(value); @override Set toSet() => _set.toSet(); diff --git a/lib/lists/call_members_list.dart b/lib/lists/call_members_list.dart index 783d4ad..3e17ab8 100644 --- a/lib/lists/call_members_list.dart +++ b/lib/lists/call_members_list.dart @@ -10,10 +10,10 @@ class CallMembersList extends AbstractList { Set get usersID => this.map((f) => f.userID).toSet(); /// Remove a specific member from this list - void removeUser(int userID) => this.removeWhere((f) => f.userID == userID); + void removeUser(int? userID) => this.removeWhere((f) => f.userID == userID); /// Get the connection of a specific user - CallMember getUser(int userID) => this.firstWhere((f) => f.userID == userID); + CallMember getUser(int? userID) => this.firstWhere((f) => f.userID == userID); /// Extract ready peers from this list CallMembersList get readyPeers => diff --git a/lib/lists/conversation_messages_list.dart b/lib/lists/conversation_messages_list.dart index 48b5a98..04eb4a8 100644 --- a/lib/lists/conversation_messages_list.dart +++ b/lib/lists/conversation_messages_list.dart @@ -1,31 +1,14 @@ -import 'dart:collection'; - +import 'package:comunic/lists/abstract_list.dart'; import 'package:comunic/models/conversation_message.dart'; /// Conversations messages list /// /// @author Pierre HUBERT -class ConversationMessagesList extends ListBase { - final List _list = []; - - set length(int v) => _list.length = v; - - int get length => _list.length; - - @override - ConversationMessage operator [](int index) { - return _list[index]; - } - - @override - void operator []=(int index, ConversationMessage value) { - _list[index] = value; - } - +class ConversationMessagesList extends AbstractList { /// Get the list of the users ID who own a message in this list - Set getUsersID() { - final Set users = Set(); + Set getUsersID() { + final Set users = Set(); for (ConversationMessage message in this) users.addAll(message.usersID); @@ -33,18 +16,18 @@ class ConversationMessagesList extends ListBase { } /// Get the ID of the last message present in this list - int get lastMessageID { - int lastMessageID = 0; + int? get lastMessageID { + int? lastMessageID = 0; for (ConversationMessage message in this) - if (message.id > lastMessageID) lastMessageID = message.id; + if (message.id! > lastMessageID!) lastMessageID = message.id; return lastMessageID; } /// Get the ID of the first message present in this list - int get firstMessageID { - int firstMessageID = this[0].id; + int? get firstMessageID { + int? firstMessageID = this[0].id; for (ConversationMessage message in this) - if (message.id < firstMessageID) firstMessageID = message.id; + if (message.id! < firstMessageID!) firstMessageID = message.id; return firstMessageID; } @@ -55,5 +38,5 @@ class ConversationMessagesList extends ListBase { } /// Remove a message from this list - void removeMsg(int id) => removeWhere((f) => f.id == id); + void removeMsg(int? id) => removeWhere((f) => f.id == id); } diff --git a/lib/lists/conversations_list.dart b/lib/lists/conversations_list.dart index 447f59c..1e9cc57 100644 --- a/lib/lists/conversations_list.dart +++ b/lib/lists/conversations_list.dart @@ -22,12 +22,15 @@ class ConversationsList extends ListBase { /// Get the entire lists of users ID in this list Set get allUsersID { final Set list = Set(); - forEach((c) => c.members.forEach((member) => list.add(member.userID))); + forEach((c) => c.members!.forEach((member) => list.add(member.userID))); return list; } /// Get the entire lists of groups ID in this list - Set get allGroupsID => where((element) => element.isGroupConversation) + Set get allGroupsID => where((element) => element.isGroupConversation) .map((e) => e.groupID) .toSet(); + + @override + void add(Conversation element) => _list.add(element); } diff --git a/lib/lists/custom_emojies_list.dart b/lib/lists/custom_emojies_list.dart index 043ec56..5aa42a5 100644 --- a/lib/lists/custom_emojies_list.dart +++ b/lib/lists/custom_emojies_list.dart @@ -7,8 +7,7 @@ import 'package:comunic/models/custom_emoji.dart'; class CustomEmojiesList extends AbstractList { /// Check if an emoji, identified by its shortcut, is present in this list - bool hasShortcut(String shortcut) => - firstWhere((f) => f.shortcut == shortcut, orElse: () => null) != null; + bool hasShortcut(String shortcut) => any((f) => f.shortcut == shortcut); /// Serialize this list List> toSerializableList() => diff --git a/lib/lists/forez_presences_set.dart b/lib/lists/forez_presences_set.dart index f733e58..12ba42d 100644 --- a/lib/lists/forez_presences_set.dart +++ b/lib/lists/forez_presences_set.dart @@ -7,7 +7,7 @@ import 'package:comunic/models/forez_presence.dart'; class PresenceSet extends BaseSet { /// Get the presence of a specific user - PresenceSet getForUser(int userID) => + PresenceSet getForUser(int? userID) => PresenceSet()..addAll(where((element) => element.userID == userID)); bool containsDate(DateTime dt) => any( @@ -24,11 +24,11 @@ class PresenceSet extends BaseSet { element.day == dt.day, ); - void toggleDate(DateTime dt, int userID) { + void toggleDate(DateTime dt, int? userID) { if (containsDate(dt)) removeDate(dt); else - add(Presence.fromDateTime(dt, userID)); + add(Presence.fromDateTime(dt, userID!)); } int countAtDate(DateTime dt) => where( diff --git a/lib/lists/groups_list.dart b/lib/lists/groups_list.dart index 25ca175..8fe6297 100644 --- a/lib/lists/groups_list.dart +++ b/lib/lists/groups_list.dart @@ -6,23 +6,23 @@ import 'package:comunic/models/group.dart'; /// /// @author Pierre HUBERT -class GroupsList extends MapBase { - final Map _groups = Map(); +class GroupsList extends MapBase { + final Map _groups = Map(); @override - Group operator [](Object key) => _groups[key]; + Group? operator [](Object? key) => _groups[key]; @override - void operator []=(int key, Group value) => _groups[key] = value; + void operator []=(int? key, Group? value) => _groups[key] = value; @override void clear() => _groups.clear(); @override - Iterable get keys => _groups.keys; + Iterable get keys => _groups.keys; @override - Group remove(Object key) => _groups.remove(key); + Group? remove(Object? key) => _groups.remove(key); - Group getGroup(int id) => this[id]; + Group? getGroup(int? id) => this[id]; } diff --git a/lib/lists/memberships_list.dart b/lib/lists/memberships_list.dart index eae92bc..3e2b399 100644 --- a/lib/lists/memberships_list.dart +++ b/lib/lists/memberships_list.dart @@ -5,20 +5,20 @@ import 'package:comunic/models/membership.dart'; /// /// @author Pierre Hubert -class MembershipList extends AbstractList { +class MembershipList extends AbstractList { /// Get the IDs of all the users included in some way in this list - Set get usersId { - final s = Set(); + Set get usersId { + final s = Set(); forEach((m) { - switch (m.type) { + switch (m!.type) { case MembershipType.FRIEND: - s.add(m.friend.id); + s.add(m.friend!.id); break; case MembershipType.GROUP: break; case MembershipType.CONVERSATION: - s.addAll(m.conversation.membersID); + s.addAll(m.conversation!.membersID); break; } }); @@ -27,16 +27,16 @@ class MembershipList extends AbstractList { } /// Get the ID of the groups included in this list - Set get groupsId => where((f) => f.type == MembershipType.GROUP) - .map((f) => f.groupID) + Set get groupsId => where((f) => f!.type == MembershipType.GROUP) + .map((f) => f!.groupID) .toSet(); /// Remove a friend membership from the list void removeFriend(int friendID) => remove(firstWhere( - (f) => f.type == MembershipType.FRIEND && f.friend.id == friendID)); + (f) => f!.type == MembershipType.FRIEND && f.friend!.id == friendID)); /// Get the list of conversations of a group - Set getGroupConversations(int groupID) => where((element) => - element.type == MembershipType.CONVERSATION && - element.conversation.groupID == groupID).toSet(); + Set getGroupConversations(int groupID) => where((element) => + element!.type == MembershipType.CONVERSATION && + element.conversation!.groupID == groupID).toSet(); } diff --git a/lib/lists/notifications_list.dart b/lib/lists/notifications_list.dart index 159b332..cd2f290 100644 --- a/lib/lists/notifications_list.dart +++ b/lib/lists/notifications_list.dart @@ -8,8 +8,8 @@ import 'package:comunic/models/notification.dart'; class NotificationsList extends AbstractList { /// Get the ID of all the users related to the notifications /// included in the list - Set get usersIds { - final list = Set(); + Set get usersIds { + final list = Set(); forEach((n) { list.add(n.fromUser); @@ -28,8 +28,8 @@ class NotificationsList extends AbstractList { /// Get the ID of all the groups related to the notifications /// included in the list - Set get groupsIds { - final list = Set(); + Set get groupsIds { + final list = Set(); forEach((n) { if (n.onElemType == NotificationElementType.GROUP_PAGE) diff --git a/lib/lists/posts_list.dart b/lib/lists/posts_list.dart index 4c18014..d2fbc30 100644 --- a/lib/lists/posts_list.dart +++ b/lib/lists/posts_list.dart @@ -22,23 +22,23 @@ class PostsList extends ListBase { void operator []=(int index, Post value) => _list[index] = value; // Get the list of users ID in this set - Set get usersID { - Set set = Set(); + Set get usersID { + Set set = Set(); forEach((p) { set.add(p.userID); - if (p.userPageID != null && p.userPageID > 0) set.add(p.userPageID); + if (p.userPageID != null && p.userPageID! > 0) set.add(p.userPageID); - if (p.comments != null) set.addAll(p.comments.usersID); + if (p.comments != null) set.addAll(p.comments!.usersID); }); return set; } /// Get the list of groups in this list of posts - Set get groupsID { - Set set = Set(); + Set get groupsID { + Set set = Set(); forEach((p) { if (p.isGroupPost) set.add(p.groupID); diff --git a/lib/lists/unread_conversations_list.dart b/lib/lists/unread_conversations_list.dart index ae8d568..0df5caf 100644 --- a/lib/lists/unread_conversations_list.dart +++ b/lib/lists/unread_conversations_list.dart @@ -7,8 +7,8 @@ import 'package:comunic/models/unread_conversation.dart'; class UnreadConversationsList extends AbstractList { /// Get the ID of the users included in this list - Set get usersID { - final set = Set(); + Set get usersID { + final set = Set(); forEach((element) { set.addAll(element.conv.membersID); set.addAll(element.message.usersID); @@ -17,8 +17,8 @@ class UnreadConversationsList extends AbstractList { } /// Get the ID of the groups references ind this list - Set get groupsID { - final set = Set(); + Set get groupsID { + final set = Set(); forEach((element) { if (element.conv.isGroupConversation) set.add(element.conv.groupID); }); diff --git a/lib/lists/users_list.dart b/lib/lists/users_list.dart index 66b8392..f3422d4 100644 --- a/lib/lists/users_list.dart +++ b/lib/lists/users_list.dart @@ -24,7 +24,7 @@ class UsersList extends ListBase { } /// Find a user with a specific ID - User getUser(int userID) { + User getUser(int? userID) { for (int i = 0; i < this.length; i++) if (this[i].id == userID) return this[i]; @@ -32,8 +32,11 @@ class UsersList extends ListBase { } /// Check if the user is included in this list or not - bool hasUser(int userID) => any((f) => f.id == userID); + bool hasUser(int? userID) => any((f) => f.id == userID); /// Get the list of users ID present in this list - List get usersID => List.generate(length, (i) => this[i].id); + List get usersID => List.generate(length, (i) => this[i].id); + + @override + void add(User element) => _list.add(element); } diff --git a/lib/main.dart b/lib/main.dart index 595e63a..2c071ea 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -44,8 +44,8 @@ class ComunicApplication extends StatefulWidget { final PreferencesHelper preferences; const ComunicApplication({ - Key key, - @required this.preferences, + Key? key, + required this.preferences, }) : assert(preferences != null), super(key: key); diff --git a/lib/main_dev.dart b/lib/main_dev.dart index a89f357..8fc9b48 100644 --- a/lib/main_dev.dart +++ b/lib/main_dev.dart @@ -11,7 +11,7 @@ import 'package:comunic/utils/flutter_utils.dart'; /// Fix HTTPS issue class MyHttpOverride extends HttpOverrides { @override - HttpClient createHttpClient(SecurityContext context) { + HttpClient createHttpClient(SecurityContext? context) { return super.createHttpClient(context) ..badCertificateCallback = (cert, host, port) { return host == "devweb.local"; // Forcefully trust local website diff --git a/lib/models/account_image_settings.dart b/lib/models/account_image_settings.dart index 580fdfb..46f76c8 100644 --- a/lib/models/account_image_settings.dart +++ b/lib/models/account_image_settings.dart @@ -1,4 +1,4 @@ -import 'package:flutter/widgets.dart'; + /// Account image settings /// @@ -7,14 +7,14 @@ import 'package:flutter/widgets.dart'; enum AccountImageVisibilityLevels { EVERYONE, COMUNIC_USERS, FRIENDS_ONLY } class AccountImageSettings { - final bool/*!*/ hasImage; - final String/*!*/ imageURL; - final AccountImageVisibilityLevels/*!*/ visibility; + final bool hasImage; + final String imageURL; + final AccountImageVisibilityLevels visibility; const AccountImageSettings({ - @required this.hasImage, - @required this.imageURL, - @required this.visibility, + required this.hasImage, + required this.imageURL, + required this.visibility, }) : assert(hasImage != null), assert(imageURL != null), assert(visibility != null); diff --git a/lib/models/advanced_group_info.dart b/lib/models/advanced_group_info.dart index 6cd2d5e..accb034 100644 --- a/lib/models/advanced_group_info.dart +++ b/lib/models/advanced_group_info.dart @@ -1,7 +1,6 @@ import 'package:comunic/enums/likes_type.dart'; import 'package:comunic/models/conversation.dart'; import 'package:comunic/models/like_element.dart'; -import 'package:flutter/material.dart'; import 'group.dart'; @@ -10,34 +9,34 @@ import 'group.dart'; /// @author Pierre Hubert class AdvancedGroupInfo extends Group implements LikeElement { - bool isMembersListPublic; - final int timeCreate; + bool? isMembersListPublic; + final int? timeCreate; String description; String url; int likes; bool userLike; - List conversations; - bool/*!*/ isForezGroup; + List? conversations; + bool isForezGroup; AdvancedGroupInfo({ - @required int id, - @required String name, - @required String iconURL, - @required int numberMembers, - @required GroupMembershipLevel membershipLevel, - @required GroupVisibilityLevel visibilityLevel, - @required GroupRegistrationLevel registrationLevel, - @required GroupPostCreationLevel postCreationLevel, - @required String virtualDirectory, - @required bool following, - @required this.isMembersListPublic, - @required this.timeCreate, - @required this.description, - @required this.url, - @required this.likes, - @required this.userLike, - @required this.conversations, - @required this.isForezGroup, + required int id, + required String name, + required String iconURL, + required int numberMembers, + required GroupMembershipLevel membershipLevel, + required GroupVisibilityLevel visibilityLevel, + required GroupRegistrationLevel registrationLevel, + required GroupPostCreationLevel postCreationLevel, + required String virtualDirectory, + required bool following, + required this.isMembersListPublic, + required this.timeCreate, + required this.description, + required this.url, + required this.likes, + required this.userLike, + required this.conversations, + required this.isForezGroup, }) : assert(isForezGroup != null), super( id: id, diff --git a/lib/models/advanced_user_info.dart b/lib/models/advanced_user_info.dart index 8d5bbc2..f54e03e 100644 --- a/lib/models/advanced_user_info.dart +++ b/lib/models/advanced_user_info.dart @@ -3,42 +3,41 @@ import 'package:comunic/enums/user_page_visibility.dart'; import 'package:comunic/lists/custom_emojies_list.dart'; import 'package:comunic/models/like_element.dart'; import 'package:comunic/models/user.dart'; -import 'package:meta/meta.dart'; /// Advanced user information /// /// @author Pierre HUBERT class AdvancedUserInfo extends User implements LikeElement { - final String emailAddress; - final String/*!*/ publicNote; - final bool/*!*/ canPostTexts; - final bool/*!*/ isFriendsListPublic; - final int/*!*/ numberFriends; - final int/*!*/ accountCreationTime; - final String/*!*/ personalWebsite; - final String location; - bool/*!*/ userLike; - int/*!*/ likes; + final String? emailAddress; + final String publicNote; + final bool canPostTexts; + final bool isFriendsListPublic; + final int numberFriends; + final int accountCreationTime; + final String personalWebsite; + final String? location; + bool userLike; + int likes; AdvancedUserInfo({ - @required int id, - @required String firstName, - @required String lastName, - @required UserPageVisibility pageVisibility, - @required String virtualDirectory, - @required String accountImageURL, - @required CustomEmojiesList customEmojies, - @required this.emailAddress, - @required this.publicNote, - @required this.canPostTexts, - @required this.isFriendsListPublic, - @required this.numberFriends, - @required this.accountCreationTime, - @required this.personalWebsite, - @required this.location, - @required this.userLike, - @required this.likes, + required int id, + required String firstName, + required String lastName, + required UserPageVisibility pageVisibility, + required String? virtualDirectory, + required String accountImageURL, + required CustomEmojiesList customEmojies, + required this.emailAddress, + required this.publicNote, + required this.canPostTexts, + required this.isFriendsListPublic, + required this.numberFriends, + required this.accountCreationTime, + required this.personalWebsite, + required this.location, + required this.userLike, + required this.likes, }) : assert(publicNote != null), assert(canPostTexts != null), assert(isFriendsListPublic != null), @@ -60,9 +59,9 @@ class AdvancedUserInfo extends User implements LikeElement { bool get hasPersonalWebsite => personalWebsite.isNotEmpty; - bool get hasEmailAddress => emailAddress != null && emailAddress.isNotEmpty; + bool get hasEmailAddress => emailAddress != null && emailAddress!.isNotEmpty; - bool get hasLocation => location != null && location.isNotEmpty; + bool get hasLocation => location != null && location!.isNotEmpty; @override LikesType get likeType => LikesType.USER; diff --git a/lib/models/api_request.dart b/lib/models/api_request.dart index ab310dd..106f5cb 100644 --- a/lib/models/api_request.dart +++ b/lib/models/api_request.dart @@ -4,7 +4,6 @@ import 'package:comunic/helpers/api_helper.dart'; import 'package:comunic/models/api_response.dart'; import 'package:dio/dio.dart'; import 'package:http_parser/http_parser.dart'; -import 'package:meta/meta.dart'; /// API Request model /// @@ -14,8 +13,8 @@ import 'package:meta/meta.dart'; class BytesFile { final String filename; - final List bytes; - final MediaType type; + final List? bytes; + final MediaType? type; const BytesFile( this.filename, @@ -25,15 +24,15 @@ class BytesFile { } class APIRequest { - final String/*!*/ uri; - final bool/*!*/ needLogin; - ProgressCallback progressCallback; - CancelToken cancelToken; - Map args; + final String uri; + final bool needLogin; + ProgressCallback? progressCallback; + CancelToken? cancelToken; + Map? args; Map files = Map(); - Map bytesFiles = Map(); + Map bytesFiles = Map(); - APIRequest({@required this.uri, this.needLogin = false, this.args}) + APIRequest({required this.uri, this.needLogin = false, this.args}) : assert(uri != null), assert(needLogin != null) { if (this.args == null) this.args = Map(); @@ -51,18 +50,18 @@ class APIRequest { if (args == null) this.args = Map(); } - APIRequest addString(String name, String value) { - args[name] = value; + APIRequest addString(String name, String? value) { + args![name] = value; return this; } - APIRequest addInt(String name, int value) { - args[name] = value.toString(); + APIRequest addInt(String name, int? value) { + args![name] = value.toString(); return this; } APIRequest addBool(String name, bool value) { - args[name] = value ? "true" : "false"; + args![name] = value ? "true" : "false"; return this; } @@ -71,12 +70,12 @@ class APIRequest { return this; } - APIRequest addBytesFile(String name, BytesFile file) { + APIRequest addBytesFile(String name, BytesFile? file) { this.bytesFiles[name] = file; return this; } - void addArgs(Map newArgs) => args.addAll(newArgs); + void addArgs(Map newArgs) => args!.addAll(newArgs); /// Execute the request Future exec() async => APIHelper().exec(this); diff --git a/lib/models/api_response.dart b/lib/models/api_response.dart index 8cfa68a..fa50351 100644 --- a/lib/models/api_response.dart +++ b/lib/models/api_response.dart @@ -5,14 +5,14 @@ import 'dart:convert'; /// @author Pierre HUBERT class APIResponse { - final int/*!*/ code; - final String content; + final int code; + final String? content; - const APIResponse(this.code, this.content) : assert(code != null); + const APIResponse(this.code, this.content); - List getArray() => jsonDecode(this.content); + List? getArray() => jsonDecode(this.content!); - Map getObject() => jsonDecode(this.content); + Map getObject() => jsonDecode(this.content!); /// Check if the request is successful or not bool get isOK => code == 200; diff --git a/lib/models/application_preferences.dart b/lib/models/application_preferences.dart index 64832d7..2a95bb5 100644 --- a/lib/models/application_preferences.dart +++ b/lib/models/application_preferences.dart @@ -1,18 +1,18 @@ -import 'package:flutter/cupertino.dart'; + /// Application settings /// /// @author Pierre Hubert class ApplicationPreferences { - bool/*!*/ enableDarkMode; - bool/*!*/ forceMobileMode; - bool/*!*/ showPerformancesOverlay; + bool enableDarkMode; + bool forceMobileMode; + bool showPerformancesOverlay; ApplicationPreferences({ - @required this.enableDarkMode, - @required this.forceMobileMode, - @required this.showPerformancesOverlay, + required this.enableDarkMode, + required this.forceMobileMode, + required this.showPerformancesOverlay, }) : assert(enableDarkMode != null), assert(forceMobileMode != null), assert(showPerformancesOverlay != null); diff --git a/lib/models/authentication_details.dart b/lib/models/authentication_details.dart index 6f6b88b..1fc84f1 100644 --- a/lib/models/authentication_details.dart +++ b/lib/models/authentication_details.dart @@ -1,14 +1,14 @@ -import 'package:meta/meta.dart'; + /// Authentication details /// /// @author Pierre HUBERT class AuthenticationDetails { - final String/*!*/ email; - final String/*!*/ password; + final String email; + final String password; - const AuthenticationDetails({@required this.email, @required this.password}) + const AuthenticationDetails({required this.email, required this.password}) : assert(email != null), assert(password != null); } diff --git a/lib/models/cache_model.dart b/lib/models/cache_model.dart index c736146..50bb53f 100644 --- a/lib/models/cache_model.dart +++ b/lib/models/cache_model.dart @@ -1,14 +1,13 @@ import 'package:comunic/helpers/database/database_contract.dart'; -import 'package:meta/meta.dart'; /// Cache base model /// /// @author Pierre HUBERT abstract class CacheModel { - final int/*!*/ id; + final int id; - const CacheModel({@required this.id}) : assert(id != null); + const CacheModel({required this.id}) : assert(id != null); /// Initialize a CacheModel from a map CacheModel.fromMap(Map map) diff --git a/lib/models/call_config.dart b/lib/models/call_config.dart index 3f8b92d..20e4829 100644 --- a/lib/models/call_config.dart +++ b/lib/models/call_config.dart @@ -1,14 +1,14 @@ -import 'package:flutter/material.dart'; + /// Call configuration /// /// @author Pierre Hubert class CallConfig { - final List/*!*/ iceServers; + final List iceServers; const CallConfig({ - @required this.iceServers, + required this.iceServers, }) : assert(iceServers != null); /// Turn this call configuration into the right for the WebRTC plugin diff --git a/lib/models/call_member.dart b/lib/models/call_member.dart index ef66bed..808c12c 100644 --- a/lib/models/call_member.dart +++ b/lib/models/call_member.dart @@ -1,4 +1,3 @@ -import 'package:flutter/material.dart'; import 'package:flutter_webrtc/flutter_webrtc.dart'; /// Single call member information @@ -8,16 +7,16 @@ import 'package:flutter_webrtc/flutter_webrtc.dart'; enum MemberStatus { JOINED, READY } class CallMember { - final int/*!*/ userID; - MemberStatus/*!*/ status; - MediaStream stream; + final int userID; + MemberStatus status; + MediaStream? stream; CallMember({ - @required this.userID, + required this.userID, this.status = MemberStatus.JOINED, }) : assert(userID != null), assert(status != null); bool get hasVideoStream => - stream != null && stream.getVideoTracks().length > 0; + stream != null && stream!.getVideoTracks().length > 0; } diff --git a/lib/models/comment.dart b/lib/models/comment.dart index 3cbc570..1038ad6 100644 --- a/lib/models/comment.dart +++ b/lib/models/comment.dart @@ -2,7 +2,6 @@ import 'package:comunic/enums/likes_type.dart'; import 'package:comunic/models/displayed_content.dart'; import 'package:comunic/models/like_element.dart'; import 'package:comunic/utils/account_utils.dart' as account; -import 'package:meta/meta.dart'; /// Comments /// @@ -11,24 +10,24 @@ import 'package:meta/meta.dart'; /// @author Pierre HUBERT class Comment implements LikeElement { - final int/*!*/ id; - final int/*!*/ userID; - final int/*!*/ postID; - final int/*!*/ timeSent; - DisplayedString/*!*/ content; - final String imageURL; - int/*!*/ likes; - bool/*!*/ userLike; + final int id; + final int userID; + final int postID; + final int timeSent; + DisplayedString content; + final String? imageURL; + int likes; + bool userLike; Comment({ - @required this.id, - @required this.userID, - @required this.postID, - @required this.timeSent, - @required this.content, - @required this.imageURL, - @required this.likes, - @required this.userLike, + required this.id, + required this.userID, + required this.postID, + required this.timeSent, + required this.content, + required this.imageURL, + required this.likes, + required this.userLike, }) : assert(id != null), assert(userID != null), assert(postID != null), diff --git a/lib/models/config.dart b/lib/models/config.dart index b477b3a..868ed48 100644 --- a/lib/models/config.dart +++ b/lib/models/config.dart @@ -16,27 +16,27 @@ class Config { // Theme customization final Color splashBackgroundColor; - final Color primaryColor; - final Color primaryColorDark; + final Color? primaryColor; + final Color? primaryColorDark; final String appName; - final String appQuickDescription; - final Color unreadConversationColor; - final Color defaultConversationColor; + final String? appQuickDescription; + final Color? unreadConversationColor; + final Color? defaultConversationColor; // Entries for the welcome tour - final TourEntriesBuilder toursEntriesBuilder; + final TourEntriesBuilder? toursEntriesBuilder; // Custom initialization - final Future Function() additionalLoading; + final Future Function()? additionalLoading; // Custom main application route - final Widget Function(BuildContext, GlobalKey) mainRouteBuilder; + final Widget Function(BuildContext, GlobalKey)? mainRouteBuilder; const Config({ - @required this.apiServerName, - @required this.apiServerUri, - @required this.apiServerSecure, - @required this.clientName, + required this.apiServerName, + required this.apiServerUri, + required this.apiServerSecure, + required this.clientName, this.splashBackgroundColor = defaultColor, this.primaryColor, this.primaryColorDark, @@ -55,9 +55,9 @@ class Config { assert(appName != null); /// Get and set static configuration - static Config/*?*/ _config; + static Config? _config; - static Config get() { + static Config? get() { return _config; } @@ -67,6 +67,6 @@ class Config { } /// Get the current configuration of the application -Config/*!*/ config() { - return Config.get(); +Config config() { + return Config.get()!; } diff --git a/lib/models/conversation.dart b/lib/models/conversation.dart index dc75413..d06c93d 100644 --- a/lib/models/conversation.dart +++ b/lib/models/conversation.dart @@ -1,3 +1,4 @@ +import 'package:collection/collection.dart' show IterableExtension; import 'package:comunic/helpers/serialization/base_serialization_helper.dart'; import 'package:comunic/models/conversation_member.dart'; import 'package:comunic/utils/account_utils.dart'; @@ -12,28 +13,28 @@ import 'group.dart'; enum CallCapabilities { NONE, AUDIO, VIDEO } class Conversation extends SerializableElement { - final int id; - final int lastActivity; - final String name; - final Color color; - final String logoURL; - final int groupID; - final GroupMembershipLevel groupMinMembershipLevel; - final List members; - final bool canEveryoneAddMembers; + final int? id; + final int? lastActivity; + final String? name; + final Color? color; + final String? logoURL; + final int? groupID; + final GroupMembershipLevel? groupMinMembershipLevel; + final List? members; + final bool? canEveryoneAddMembers; final CallCapabilities callCapabilities; final bool isHavingCall; Conversation({ - /*required*/ @required this.id, - /*required*/ @required this.lastActivity, - @required this.name, - @required this.color, - @required this.logoURL, - @required this.groupID, - @required this.groupMinMembershipLevel, - /*required*/ @required this.members, - /*required*/ @required this.canEveryoneAddMembers, + /*required*/ required int this.id, + /*required*/ required int this.lastActivity, + required this.name, + required this.color, + required this.logoURL, + required this.groupID, + required this.groupMinMembershipLevel, + /*required*/ required List this.members, + /*required*/ required bool this.canEveryoneAddMembers, this.callCapabilities = CallCapabilities.NONE, this.isHavingCall = false, }) : assert(id != null), @@ -49,7 +50,7 @@ class Conversation extends SerializableElement { /// Get current user membership ConversationMember get membership => - members.firstWhere((m) => m.userID == userID()); + members!.firstWhere((m) => m.userID == userID()); /// Check out whether current user of the application is an admin bool get isAdmin => membership.isAdmin; @@ -61,17 +62,17 @@ class Conversation extends SerializableElement { bool get following => membership.following; /// Get the list of members in the conversation - Set get membersID => members.map((e) => e.userID).toSet(); + Set get membersID => members!.map((e) => e.userID).toSet(); /// Get the list of admins in the conversation - Set get adminsID => - members.where((e) => e.isAdmin).map((e) => e.userID).toSet(); + Set get adminsID => + members!.where((e) => e.isAdmin).map((e) => e.userID).toSet(); /// Get the list of the OTHER members of the conversation (all except current user) - Set get otherMembersID => membersID..remove(userID()); + Set get otherMembersID => membersID..remove(userID()); /// Check if the last message has been seen or not - bool get sawLastMessage => lastActivity <= membership.lastAccessTime; + bool get sawLastMessage => lastActivity! <= membership.lastAccessTime; /// Check out whether a conversation is managed or not bool get isManaged => isGroupConversation; @@ -86,9 +87,8 @@ class Conversation extends SerializableElement { color = map["color"] == null ? null : Color(map["color"]), logoURL = map["logoURL"], groupID = map["groupID"], - groupMinMembershipLevel = GroupMembershipLevel.values.firstWhere( - (element) => element.toString() == map["groupMinMembershipLevel"], - orElse: () => null), + groupMinMembershipLevel = GroupMembershipLevel.values.firstWhereOrNull( + (element) => element.toString() == map["groupMinMembershipLevel"]), lastActivity = map["lastActivity"], members = map["members"] .map((el) => ConversationMember.fromJSON(el)) @@ -109,13 +109,13 @@ class Conversation extends SerializableElement { "groupID": groupID, "groupMinMembershipLevel": groupMinMembershipLevel?.toString(), "lastActivity": lastActivity, - "members": members.map((e) => e.toJson()).toList(), + "members": members!.map((e) => e.toJson()).toList(), "canEveryoneAddMembers": canEveryoneAddMembers, }; } @override int compareTo(Conversation other) { - return other.lastActivity.compareTo(this.lastActivity); + return other.lastActivity!.compareTo(this.lastActivity!); } } diff --git a/lib/models/conversation_member.dart b/lib/models/conversation_member.dart index e816995..eb763ee 100644 --- a/lib/models/conversation_member.dart +++ b/lib/models/conversation_member.dart @@ -1,22 +1,22 @@ -import 'package:flutter/widgets.dart'; + /// Conversation member /// /// @author Pierre Hubert class ConversationMember { - final int/*!*/ userID; - final int/*!*/ lastMessageSeen; - final int/*!*/ lastAccessTime; - final bool/*!*/ following; - final bool/*!*/ isAdmin; + final int userID; + final int lastMessageSeen; + final int lastAccessTime; + final bool following; + final bool isAdmin; const ConversationMember({ - /*required*/ @required this.userID, - /*required*/ @required this.lastMessageSeen, - /*required*/ @required this.lastAccessTime, - /*required*/ @required this.following, - /*required*/ @required this.isAdmin, + /*required*/ required this.userID, + /*required*/ required this.lastMessageSeen, + /*required*/ required this.lastAccessTime, + /*required*/ required this.following, + /*required*/ required this.isAdmin, }) : assert(userID != null), assert(lastMessageSeen != null), assert(lastAccessTime != null), diff --git a/lib/models/conversation_message.dart b/lib/models/conversation_message.dart index 7a9d1e5..a53ee23 100644 --- a/lib/models/conversation_message.dart +++ b/lib/models/conversation_message.dart @@ -30,27 +30,27 @@ const _ConversationFileMimeTypeMapping = { }; class ConversationMessageFile { - final String url; - final int size; - final String name; - final String thumbnail; - final String type; + final String? url; + final int? size; + final String? name; + final String? thumbnail; + final String? type; const ConversationMessageFile({ - @required this.url, - @required this.size, - @required this.name, - @required this.thumbnail, - @required this.type, + required String this.url, + required int this.size, + required String this.name, + required this.thumbnail, + required String this.type, }) : assert(url != null), assert(size != null), assert(name != null), assert(type != null); /// Get the type of file - ConversationMessageFileType get fileType { + ConversationMessageFileType? get fileType { if (type != null && _ConversationFileMimeTypeMapping.containsKey(type)) - return _ConversationFileMimeTypeMapping[type]; + return _ConversationFileMimeTypeMapping[type!]; else return ConversationMessageFileType.OTHER; } @@ -102,19 +102,19 @@ enum ConversationServerMessageType { class ConversationServerMessage { final ConversationServerMessageType type; - final int userID; - final int userWhoAdded; - final int userAdded; - final int userWhoRemoved; - final int userRemoved; + final int? userID; + final int? userWhoAdded; + final int? userAdded; + final int? userWhoRemoved; + final int? userRemoved; const ConversationServerMessage({ - @required this.type, - @required this.userID, - @required this.userWhoAdded, - @required this.userAdded, - @required this.userWhoRemoved, - @required this.userRemoved, + required this.type, + required this.userID, + required this.userWhoAdded, + required this.userAdded, + required this.userWhoRemoved, + required this.userRemoved, }) : assert(type != null), assert(userID != null || (type != ConversationServerMessageType.USER_CREATED_CONVERSATION && @@ -124,7 +124,7 @@ class ConversationServerMessage { assert((userWhoRemoved != null && userRemoved != null) || type != ConversationServerMessageType.USER_REMOVED_ANOTHER_USER); - Set get usersID { + Set get usersID { switch (type) { case ConversationServerMessageType.USER_CREATED_CONVERSATION: case ConversationServerMessageType.USER_LEFT_CONV: @@ -144,26 +144,26 @@ class ConversationServerMessage { throw Exception("Unsupported server message type!"); } - String getText(UsersList list) { + String? getText(UsersList? list) { switch (type) { case ConversationServerMessageType.USER_CREATED_CONVERSATION: return tr("%1% created the conversation", - args: {"1": list.getUser(userID).fullName}); + args: {"1": list!.getUser(userID).fullName}); case ConversationServerMessageType.USER_ADDED_ANOTHER_USER: return tr("%1% added %2% to the conversation", args: { - "1": list.getUser(userWhoAdded).fullName, + "1": list!.getUser(userWhoAdded).fullName, "2": list.getUser(userAdded).fullName, }); case ConversationServerMessageType.USER_LEFT_CONV: return tr("%1% left the conversation", args: { - "1": list.getUser(userID).fullName, + "1": list!.getUser(userID).fullName, }); case ConversationServerMessageType.USER_REMOVED_ANOTHER_USER: return tr("%1% removed %2% from the conversation", args: { - "1": list.getUser(userWhoRemoved).fullName, + "1": list!.getUser(userWhoRemoved).fullName, "2": list.getUser(userRemoved).fullName, }); } @@ -191,29 +191,29 @@ class ConversationServerMessage { } class ConversationMessage extends SerializableElement { - final int id; - final int convID; - final int userID; - final int timeSent; + final int? id; + final int? convID; + final int? userID; + final int? timeSent; final DisplayedString message; - final ConversationMessageFile file; - final ConversationServerMessage serverMessage; + final ConversationMessageFile? file; + final ConversationServerMessage? serverMessage; ConversationMessage({ - @required this.id, - @required this.convID, - @required this.userID, - @required this.timeSent, - @required this.message, - @required this.file, - @required this.serverMessage, + required int this.id, + required int this.convID, + required this.userID, + required int this.timeSent, + required this.message, + required this.file, + required this.serverMessage, }) : assert(id != null), assert(convID != null), assert(userID != null || serverMessage != null), assert(timeSent != null), assert(message != null || file != null || serverMessage != null); - DateTime get date => DateTime.fromMillisecondsSinceEpoch(timeSent * 1000); + DateTime get date => DateTime.fromMillisecondsSinceEpoch(timeSent! * 1000); bool get hasMessage => !message.isNull && message.length > 0; @@ -224,16 +224,16 @@ class ConversationMessage extends SerializableElement { bool get isServerMessage => serverMessage != null; /// Get the list of the ID of the users implied in this message - Set get usersID { + Set get usersID { if (userID != null) return Set()..add(userID); - if (serverMessage != null) return serverMessage.usersID; + if (serverMessage != null) return serverMessage!.usersID; return Set(); } @override int compareTo(ConversationMessage other) { - return id.compareTo(other.id); + return id!.compareTo(other.id!); } Map toJson() { diff --git a/lib/models/count_unread_notifications.dart b/lib/models/count_unread_notifications.dart index 5b263c0..a7e7968 100644 --- a/lib/models/count_unread_notifications.dart +++ b/lib/models/count_unread_notifications.dart @@ -3,12 +3,12 @@ /// @author Pierre Hubert class CountUnreadNotifications { - int notifications; - int conversations; + int? notifications; + int? conversations; CountUnreadNotifications({ - this.notifications, - this.conversations, + required int this.notifications, + required int this.conversations, }) : assert(notifications != null), assert(conversations != null); } diff --git a/lib/models/custom_emoji.dart b/lib/models/custom_emoji.dart index ec76a70..85211d5 100644 --- a/lib/models/custom_emoji.dart +++ b/lib/models/custom_emoji.dart @@ -1,20 +1,20 @@ -import 'package:flutter/material.dart'; + /// Single custom emoji information /// /// @author Pierre Hubert class CustomEmoji { - final int id; - final int userID; - final String shortcut; - final String url; + final int? id; + final int? userID; + final String? shortcut; + final String? url; const CustomEmoji({ - @required this.id, - @required this.userID, - @required this.shortcut, - @required this.url, + required int this.id, + required int this.userID, + required String this.shortcut, + required String this.url, }) : assert(id != null), assert(userID != null), assert(shortcut != null), diff --git a/lib/models/data_conservation_policy_settings.dart b/lib/models/data_conservation_policy_settings.dart index 6049d2a..d0e5225 100644 --- a/lib/models/data_conservation_policy_settings.dart +++ b/lib/models/data_conservation_policy_settings.dart @@ -3,12 +3,12 @@ /// @author Pierre Hubert class DataConservationPolicySettings { - int inactiveAccountLifeTime; - int notificationLifetime; - int commentsLifetime; - int postsLifetime; - int conversationMessagesLifetime; - int likesLifetime; + int? inactiveAccountLifeTime; + int? notificationLifetime; + int? commentsLifetime; + int? postsLifetime; + int? conversationMessagesLifetime; + int? likesLifetime; DataConservationPolicySettings({ this.inactiveAccountLifeTime, diff --git a/lib/models/displayed_content.dart b/lib/models/displayed_content.dart index a9a2ce0..131978b 100644 --- a/lib/models/displayed_content.dart +++ b/lib/models/displayed_content.dart @@ -5,32 +5,32 @@ import 'package:comunic/utils/ui_utils.dart'; /// @author Pierre Hubert class DisplayedString { - String _string; - String _parseCache; + String? _string; + String? _parseCache; DisplayedString(this._string); - int get length => _string.length; + int get length => _string!.length; - bool get isEmpty => _string.isEmpty; + bool get isEmpty => _string!.isEmpty; bool get isNull => _string == null; - String get content => _string; + String? get content => _string; - set content(String content) { + set content(String? content) { _string = content; _parseCache = null; } @override String toString() { - return _string; + return _string!; } - String get parsedString { + String? get parsedString { if (_parseCache == null) { - _parseCache = parseEmojies(this._string); + _parseCache = parseEmojies(this._string!); } return _parseCache; diff --git a/lib/models/forez_presence.dart b/lib/models/forez_presence.dart index 236bb9a..b307ec0 100644 --- a/lib/models/forez_presence.dart +++ b/lib/models/forez_presence.dart @@ -1,4 +1,4 @@ -import 'package:flutter/material.dart'; + /// Single presence information /// @@ -11,10 +11,10 @@ class Presence { final int day; const Presence({ - @required this.userID, - @required this.year, - @required this.month, - @required this.day, + required this.userID, + required this.year, + required this.month, + required this.day, }) : assert(userID != null), assert(year != null), assert(month != null), diff --git a/lib/models/friend.dart b/lib/models/friend.dart index c6630e3..09310d3 100644 --- a/lib/models/friend.dart +++ b/lib/models/friend.dart @@ -1,7 +1,6 @@ import 'package:comunic/helpers/database/database_contract.dart'; import 'package:comunic/models/cache_model.dart'; import 'package:comunic/utils/date_utils.dart'; -import 'package:meta/meta.dart'; /// Single user Friend information /// @@ -9,16 +8,16 @@ import 'package:meta/meta.dart'; class Friend extends CacheModel implements Comparable { bool accepted; - final int lastActive; + final int? lastActive; final bool following; final bool canPostTexts; Friend({ - @required int id, - @required this.accepted, - @required this.lastActive, - @required this.following, - @required this.canPostTexts, + required int id, + required this.accepted, + required int this.lastActive, + required this.following, + required this.canPostTexts, }) : assert(id != null), assert(accepted != null), assert(lastActive != null), @@ -27,10 +26,10 @@ class Friend extends CacheModel implements Comparable { super(id: id); /// Check out whether friend is connected or not - bool get isConnected => time() - 30 < lastActive; + bool get isConnected => time() - 30 < lastActive!; @override - int compareTo(Friend other) => other.lastActive.compareTo(lastActive); + int compareTo(Friend other) => other.lastActive!.compareTo(lastActive!); @override Map toMap() => { diff --git a/lib/models/friend_status.dart b/lib/models/friend_status.dart index 49e57a0..5a0814e 100644 --- a/lib/models/friend_status.dart +++ b/lib/models/friend_status.dart @@ -1,4 +1,4 @@ -import 'package:meta/meta.dart'; + /// Simple friendship status /// @@ -12,11 +12,11 @@ class FriendStatus { final bool following; const FriendStatus({ - @required this.userID, - @required this.areFriend, - @required this.sentRequest, - @required this.receivedRequest, - @required this.following, + required this.userID, + required this.areFriend, + required this.sentRequest, + required this.receivedRequest, + required this.following, }) : assert(userID != null), assert(areFriend != null), assert(sentRequest != null), diff --git a/lib/models/general_settings.dart b/lib/models/general_settings.dart index c66cae3..c47358f 100644 --- a/lib/models/general_settings.dart +++ b/lib/models/general_settings.dart @@ -1,5 +1,4 @@ import 'package:comunic/enums/user_page_visibility.dart'; -import 'package:flutter/material.dart'; /// General settings /// @@ -18,22 +17,22 @@ class GeneralSettings { String virtualDirectory; String personalWebsite; String publicNote; - String location; + String? location; GeneralSettings({ - @required this.email, - @required this.firstName, - @required this.lastName, - @required this.pageVisibility, - @required this.allowComments, - @required this.allowPostsFromFriends, - @required this.allowComunicEmails, - @required this.publicFriendsList, - @required this.publicEmail, - @required this.virtualDirectory, - @required this.personalWebsite, - @required this.publicNote, - @required this.location, + required this.email, + required this.firstName, + required this.lastName, + required this.pageVisibility, + required this.allowComments, + required this.allowPostsFromFriends, + required this.allowComunicEmails, + required this.publicFriendsList, + required this.publicEmail, + required this.virtualDirectory, + required this.personalWebsite, + required this.publicNote, + required this.location, }) : assert(email != null), assert(firstName != null), assert(lastName != null), diff --git a/lib/models/group.dart b/lib/models/group.dart index a812416..6523c84 100644 --- a/lib/models/group.dart +++ b/lib/models/group.dart @@ -1,5 +1,4 @@ import 'package:comunic/utils/intl_utils.dart'; -import 'package:meta/meta.dart'; /// Group information /// @@ -14,20 +13,20 @@ enum GroupMembershipLevel { VISITOR } -String/*!*/ membershipToText(GroupMembershipLevel level) { +String membershipToText(GroupMembershipLevel level) { switch (level) { case GroupMembershipLevel.ADMINISTRATOR: - return tr("Administrator"); + return tr("Administrator")!; case GroupMembershipLevel.MODERATOR: - return tr("Moderator"); + return tr("Moderator")!; case GroupMembershipLevel.MEMBER: - return tr("Member"); + return tr("Member")!; case GroupMembershipLevel.INVITED: - return tr("Invited"); + return tr("Invited")!; case GroupMembershipLevel.PENDING: - return tr("Requested"); + return tr("Requested")!; case GroupMembershipLevel.VISITOR: - return tr("Visitor"); + return tr("Visitor")!; } throw new Exception("Unreachable statement!"); } @@ -51,16 +50,16 @@ class Group implements Comparable { bool following; Group({ - @required this.id, - @required this.name, - @required this.iconURL, - @required this.numberMembers, - @required this.membershipLevel, - @required this.visibilityLevel, - @required this.registrationLevel, - @required this.postCreationLevel, - @required this.virtualDirectory, - @required this.following, + required this.id, + required this.name, + required this.iconURL, + required this.numberMembers, + required this.membershipLevel, + required this.visibilityLevel, + required this.registrationLevel, + required this.postCreationLevel, + required this.virtualDirectory, + required this.following, }) : assert(id != null), assert(name != null), assert(iconURL != null), diff --git a/lib/models/group_membership.dart b/lib/models/group_membership.dart index 7d46d5f..fa0e4b4 100644 --- a/lib/models/group_membership.dart +++ b/lib/models/group_membership.dart @@ -1,5 +1,4 @@ import 'package:comunic/models/group.dart'; -import 'package:flutter/material.dart'; /// Group membership information /// @@ -12,10 +11,10 @@ class GroupMembership { final GroupMembershipLevel level; const GroupMembership({ - @required this.userID, - @required this.groupID, - @required this.timeCreate, - @required this.level, + required this.userID, + required this.groupID, + required this.timeCreate, + required this.level, }) : assert(userID != null), assert(groupID != null), assert(timeCreate != null), diff --git a/lib/models/like_element.dart b/lib/models/like_element.dart index adfb38e..eaf1c06 100644 --- a/lib/models/like_element.dart +++ b/lib/models/like_element.dart @@ -9,6 +9,6 @@ abstract class LikeElement { int get id; - bool userLike; - int likes; + late bool userLike; + late int likes; } diff --git a/lib/models/membership.dart b/lib/models/membership.dart index 3c66ef3..1516eea 100644 --- a/lib/models/membership.dart +++ b/lib/models/membership.dart @@ -1,6 +1,5 @@ import 'package:comunic/models/conversation.dart'; import 'package:comunic/models/friend.dart'; -import 'package:flutter/material.dart'; /// Membership information /// @@ -10,40 +9,40 @@ enum MembershipType { FRIEND, GROUP, CONVERSATION } class Membership { final MembershipType type; - final Conversation conversation; - final Friend friend; - final int groupID; - final int groupLastActive; + final Conversation? conversation; + final Friend? friend; + final int? groupID; + final int? groupLastActive; - Membership.conversation(this.conversation) + Membership.conversation(Conversation this.conversation) : type = MembershipType.CONVERSATION, friend = null, groupID = null, groupLastActive = null, assert(conversation != null); - Membership.friend(this.friend) + Membership.friend(Friend this.friend) : type = MembershipType.FRIEND, conversation = null, groupID = null, groupLastActive = null, assert(friend != null); - Membership.group({@required this.groupID, @required this.groupLastActive}) + Membership.group({required int this.groupID, required int this.groupLastActive}) : type = MembershipType.GROUP, conversation = null, friend = null, assert(groupID != null), assert(groupLastActive != null); - int get lastActive { + int? get lastActive { switch (type) { case MembershipType.FRIEND: - return friend.lastActive; + return friend!.lastActive; case MembershipType.GROUP: return groupLastActive; case MembershipType.CONVERSATION: - return conversation.lastActivity; + return conversation!.lastActivity; default: throw Exception("Unreachable statment!"); } diff --git a/lib/models/new_account.dart b/lib/models/new_account.dart index 8195633..524a13a 100644 --- a/lib/models/new_account.dart +++ b/lib/models/new_account.dart @@ -1,4 +1,4 @@ -import 'package:flutter/widgets.dart'; + /// New account information container /// @@ -11,10 +11,10 @@ class NewAccount { final String password; NewAccount({ - @required this.firstName, - @required this.lastName, - @required this.email, - @required this.password, + required this.firstName, + required this.lastName, + required this.email, + required this.password, }) : assert(firstName != null), assert(lastName != null), assert(email != null), diff --git a/lib/models/new_comment.dart b/lib/models/new_comment.dart index 9d86d26..885dcfd 100644 --- a/lib/models/new_comment.dart +++ b/lib/models/new_comment.dart @@ -1,5 +1,3 @@ -import 'package:meta/meta.dart'; - import 'api_request.dart'; /// New comment information @@ -9,12 +7,12 @@ import 'api_request.dart'; class NewComment { final int postID; final String content; - final BytesFile image; + final BytesFile? image; const NewComment({ - @required this.postID, - @required this.content, - @required this.image, + required this.postID, + required this.content, + required this.image, }) : assert(postID != null); bool get hasContent => content != null && content.length > 0; diff --git a/lib/models/new_conversation.dart b/lib/models/new_conversation.dart index 167259b..8f4e662 100644 --- a/lib/models/new_conversation.dart +++ b/lib/models/new_conversation.dart @@ -6,17 +6,17 @@ import 'package:flutter/cupertino.dart'; class NewConversation { final String name; - final List members; + final List members; final bool follow; final bool canEveryoneAddMembers; - final Color color; + final Color? color; const NewConversation({ - @required this.name, - @required this.members, - @required this.follow, - @required this.canEveryoneAddMembers, - @required this.color, + required this.name, + required this.members, + required this.follow, + required this.canEveryoneAddMembers, + required this.color, }) : assert(members != null), assert(members.length > 0), assert(follow != null), diff --git a/lib/models/new_conversation_message.dart b/lib/models/new_conversation_message.dart index c4264a3..cd08af4 100644 --- a/lib/models/new_conversation_message.dart +++ b/lib/models/new_conversation_message.dart @@ -1,5 +1,4 @@ import 'package:comunic/models/api_request.dart'; -import 'package:meta/meta.dart'; /// New conversation message model /// @@ -9,13 +8,13 @@ import 'package:meta/meta.dart'; class NewConversationMessage { final int conversationID; - final String message; - final BytesFile file; - final BytesFile thumbnail; + final String? message; + final BytesFile? file; + final BytesFile? thumbnail; NewConversationMessage({ - @required this.conversationID, - @required this.message, + required this.conversationID, + required this.message, this.file, this.thumbnail, }) : assert(conversationID != null), diff --git a/lib/models/new_conversation_settings.dart b/lib/models/new_conversation_settings.dart index 894117b..6c580b7 100644 --- a/lib/models/new_conversation_settings.dart +++ b/lib/models/new_conversation_settings.dart @@ -9,16 +9,16 @@ class NewConversationsSettings { final bool following; final bool isComplete; final String name; - final bool canEveryoneAddMembers; - final Color color; + final bool? canEveryoneAddMembers; + final Color? color; const NewConversationsSettings({ - @required this.convID, - @required this.following, - @required this.isComplete, - @required this.name, - @required this.canEveryoneAddMembers, - @required this.color, + required this.convID, + required this.following, + required this.isComplete, + required this.name, + required this.canEveryoneAddMembers, + required this.color, }) : assert(convID != null), assert(convID > 0), assert(following != null), diff --git a/lib/models/new_emoji.dart b/lib/models/new_emoji.dart index db6822f..1749898 100644 --- a/lib/models/new_emoji.dart +++ b/lib/models/new_emoji.dart @@ -1,5 +1,3 @@ -import 'package:flutter/material.dart'; - import 'api_request.dart'; /// New emoji information @@ -11,8 +9,8 @@ class NewEmoji { final BytesFile image; const NewEmoji({ - @required this.shortcut, - @required this.image, + required this.shortcut, + required this.image, }) : assert(shortcut != null), assert(image != null); } diff --git a/lib/models/new_group_conversation.dart b/lib/models/new_group_conversation.dart index dc017e3..ac5ca33 100644 --- a/lib/models/new_group_conversation.dart +++ b/lib/models/new_group_conversation.dart @@ -1,5 +1,4 @@ import 'package:comunic/models/group.dart'; -import 'package:flutter/foundation.dart'; /// This class contains information about a conversation linked to a group /// to create @@ -12,9 +11,9 @@ class NewGroupConversation { final GroupMembershipLevel minMembershipLevel; const NewGroupConversation({ - @required this.groupID, - @required this.name, - @required this.minMembershipLevel, + required this.groupID, + required this.name, + required this.minMembershipLevel, }) : assert(groupID != null), assert(name != null), assert(minMembershipLevel != null); diff --git a/lib/models/new_post.dart b/lib/models/new_post.dart index 4f3dd64..16165c3 100644 --- a/lib/models/new_post.dart +++ b/lib/models/new_post.dart @@ -1,7 +1,6 @@ import 'package:comunic/enums/post_kind.dart'; import 'package:comunic/enums/post_target.dart'; import 'package:comunic/enums/post_visibility_level.dart'; -import 'package:meta/meta.dart'; import 'api_request.dart'; @@ -15,9 +14,9 @@ class NewSurvey { final bool allowNewChoicesCreation; const NewSurvey({ - @required this.question, - @required this.answers, - @required this.allowNewChoicesCreation, + required this.question, + required this.answers, + required this.allowNewChoicesCreation, }) : assert(question != null), assert(answers.length > 1), assert(allowNewChoicesCreation != null); @@ -28,26 +27,26 @@ class NewPost { final int targetID; final PostVisibilityLevel visibility; final String content; - final BytesFile image; - final String url; - final List pdf; + final BytesFile? image; + final String? url; + final List? pdf; final PostKind kind; - final DateTime timeEnd; - final NewSurvey survey; - final String youtubeId; + final DateTime? timeEnd; + final NewSurvey? survey; + final String? youtubeId; const NewPost({ - @required this.target, - @required this.targetID, - @required this.visibility, - @required this.content, - @required this.kind, - @required this.image, - @required this.url, - @required this.pdf, - @required this.timeEnd, - @required this.survey, - @required this.youtubeId, + required this.target, + required this.targetID, + required this.visibility, + required this.content, + required this.kind, + required this.image, + required this.url, + required this.pdf, + required this.timeEnd, + required this.survey, + required this.youtubeId, }) : assert(target != null), assert(targetID != null), assert(visibility != null), diff --git a/lib/models/notification.dart b/lib/models/notification.dart index 301bf9b..09865cc 100644 --- a/lib/models/notification.dart +++ b/lib/models/notification.dart @@ -1,4 +1,4 @@ -import 'package:flutter/widgets.dart'; + /// Notification model /// @@ -45,19 +45,19 @@ class Notification { final int onElemId; final NotificationElementType onElemType; final NotificationType type; - final int fromContainerId; - final NotificationElementType fromContainerType; + final int? fromContainerId; + final NotificationElementType? fromContainerType; const Notification({ - @required this.id, - @required this.timeCreate, - @required this.seen, - @required this.fromUser, - @required this.onElemId, - @required this.onElemType, - @required this.type, - @required this.fromContainerId, - @required this.fromContainerType, + required this.id, + required this.timeCreate, + required this.seen, + required this.fromUser, + required this.onElemId, + required this.onElemType, + required this.type, + required this.fromContainerId, + required this.fromContainerType, }) : assert(id != null), assert(timeCreate != null), assert(seen != null), diff --git a/lib/models/notifications_settings.dart b/lib/models/notifications_settings.dart index e0f5d9d..ce39e1d 100644 --- a/lib/models/notifications_settings.dart +++ b/lib/models/notifications_settings.dart @@ -1,4 +1,4 @@ -import 'package:flutter/material.dart'; + /// Notifications settings /// @@ -9,8 +9,8 @@ class NotificationsSettings { bool allowNotificationsSound; NotificationsSettings({ - @required this.allowConversations, - @required this.allowNotificationsSound, + required this.allowConversations, + required this.allowNotificationsSound, }) : assert(allowConversations != null), assert(allowNotificationsSound != null); } diff --git a/lib/models/post.dart b/lib/models/post.dart index 1ec6ae9..fc7cfe8 100644 --- a/lib/models/post.dart +++ b/lib/models/post.dart @@ -6,7 +6,6 @@ import 'package:comunic/lists/comments_list.dart'; import 'package:comunic/models/displayed_content.dart'; import 'package:comunic/models/like_element.dart'; import 'package:comunic/models/survey.dart'; -import 'package:meta/meta.dart'; /// Single post information /// @@ -15,50 +14,50 @@ import 'package:meta/meta.dart'; class Post implements LikeElement { final int id; final int userID; - final int userPageID; - final int groupID; + final int? userPageID; + final int? groupID; final int timeSent; DisplayedString content; PostVisibilityLevel visibilityLevel; final PostKind kind; - final int fileSize; - final String fileType; - final String filePath; - final String fileURL; - final int timeEnd; - final String linkURL; - final String linkTitle; - final String linkDescription; - final String linkImage; + final int? fileSize; + final String? fileType; + final String? filePath; + final String? fileURL; + final int? timeEnd; + final String? linkURL; + final String? linkTitle; + final String? linkDescription; + final String? linkImage; int likes; bool userLike; final UserAccessLevels access; - final CommentsList comments; - Survey survey; + final CommentsList? comments; + Survey? survey; Post( - {@required this.id, - @required this.userID, - @required this.userPageID, - @required this.groupID, - @required this.timeSent, - @required this.content, - @required this.visibilityLevel, - @required this.kind, - @required this.fileSize, - @required this.fileType, - @required this.filePath, - @required this.fileURL, - @required this.timeEnd, - @required this.linkURL, - @required this.linkTitle, - @required this.linkDescription, - @required this.linkImage, - @required this.likes, - @required this.userLike, - @required this.access, - @required this.comments, - @required this.survey}) + {required this.id, + required this.userID, + required this.userPageID, + required this.groupID, + required this.timeSent, + required this.content, + required this.visibilityLevel, + required this.kind, + required this.fileSize, + required this.fileType, + required this.filePath, + required this.fileURL, + required this.timeEnd, + required this.linkURL, + required this.linkTitle, + required this.linkDescription, + required this.linkImage, + required this.likes, + required this.userLike, + required this.access, + required this.comments, + required this.survey}) : assert(id != null), assert(userID != null), assert(userPageID != 0 || groupID != 0), @@ -72,7 +71,7 @@ class Post implements LikeElement { assert(userLike != null), assert(access != null); - bool get isGroupPost => groupID != null && groupID > 0; + bool get isGroupPost => groupID != null && groupID! > 0; bool get hasContent => content != null && !content.isNull; diff --git a/lib/models/res_check_password_reset_token.dart b/lib/models/res_check_password_reset_token.dart index f3bd53a..aa57b2d 100644 --- a/lib/models/res_check_password_reset_token.dart +++ b/lib/models/res_check_password_reset_token.dart @@ -1,4 +1,4 @@ -import 'package:flutter/material.dart'; + /// Check password reset token result /// @@ -10,9 +10,9 @@ class ResCheckPasswordToken { final String email; const ResCheckPasswordToken({ - @required this.firstName, - @required this.lastName, - @required this.email, + required this.firstName, + required this.lastName, + required this.email, }) : assert(firstName != null), assert(lastName != null), assert(email != null); diff --git a/lib/models/search_result.dart b/lib/models/search_result.dart index 3a136a4..54db2fa 100644 --- a/lib/models/search_result.dart +++ b/lib/models/search_result.dart @@ -1,4 +1,4 @@ -import 'package:flutter/cupertino.dart'; + /// Single search result /// @@ -11,8 +11,8 @@ class SearchResult { final SearchResultKind kind; SearchResult({ - @required this.id, - @required this.kind, + required this.id, + required this.kind, }) : assert(id != null), assert(kind != null); } diff --git a/lib/models/security_settings.dart b/lib/models/security_settings.dart index 157f01f..dfe9599 100644 --- a/lib/models/security_settings.dart +++ b/lib/models/security_settings.dart @@ -1,4 +1,4 @@ -import 'package:flutter/material.dart'; + /// Security settings of the user /// @@ -11,10 +11,10 @@ class SecuritySettings { final String securityAnswer2; const SecuritySettings({ - @required this.securityQuestion1, - @required this.securityAnswer1, - @required this.securityQuestion2, - @required this.securityAnswer2, + required this.securityQuestion1, + required this.securityAnswer1, + required this.securityQuestion2, + required this.securityAnswer2, }) : assert(securityQuestion1 != null), assert(securityAnswer1 != null), assert(securityQuestion2 != null), diff --git a/lib/models/server_config.dart b/lib/models/server_config.dart index b60983e..c3128ba 100644 --- a/lib/models/server_config.dart +++ b/lib/models/server_config.dart @@ -1,5 +1,4 @@ import 'package:comunic/utils/date_utils.dart'; -import 'package:flutter/widgets.dart'; import 'package:version/version.dart'; /// Server static configuration @@ -11,8 +10,8 @@ class NotificationsPolicy { final bool hasIndependent; const NotificationsPolicy({ - @required this.hasFirebase, - @required this.hasIndependent, + required this.hasFirebase, + required this.hasIndependent, }) : assert(hasFirebase != null), assert(hasIndependent != null); } @@ -28,14 +27,14 @@ class PasswordPolicy { final int minCategoriesPresence; const PasswordPolicy({ - @required this.allowMailInPassword, - @required this.allowNameInPassword, - @required this.minPasswordLength, - @required this.minNumberUpperCaseLetters, - @required this.minNumberLowerCaseLetters, - @required this.minNumberDigits, - @required this.minNumberSpecialCharacters, - @required this.minCategoriesPresence, + required this.allowMailInPassword, + required this.allowNameInPassword, + required this.minPasswordLength, + required this.minNumberUpperCaseLetters, + required this.minNumberLowerCaseLetters, + required this.minNumberDigits, + required this.minNumberSpecialCharacters, + required this.minCategoriesPresence, }) : assert(allowMailInPassword != null), assert(allowNameInPassword != null), assert(minPasswordLength != null), @@ -55,12 +54,12 @@ class ServerDataConservationPolicy { final int minLikesLifetime; const ServerDataConservationPolicy({ - @required this.minInactiveAccountLifetime, - @required this.minNotificationLifetime, - @required this.minCommentsLifetime, - @required this.minPostsLifetime, - @required this.minConversationMessagesLifetime, - @required this.minLikesLifetime, + required this.minInactiveAccountLifetime, + required this.minNotificationLifetime, + required this.minCommentsLifetime, + required this.minPostsLifetime, + required this.minConversationMessagesLifetime, + required this.minLikesLifetime, }) : assert(minInactiveAccountLifetime != null), assert(minNotificationLifetime != null), assert(minCommentsLifetime != null), @@ -85,19 +84,19 @@ class ConversationsPolicy { final int maxLogoHeight; const ConversationsPolicy({ - @required this.maxConversationNameLen, - @required this.minMessageLen, - @required this.maxMessageLen, - @required this.allowedFilesType, - @required this.filesMaxSize, - @required this.writingEventInterval, - @required this.writingEventLifetime, - @required this.maxMessageImageWidth, - @required this.maxMessageImageHeight, - @required this.maxThumbnailWidth, - @required this.maxThumbnailHeight, - @required this.maxLogoWidth, - @required this.maxLogoHeight, + required this.maxConversationNameLen, + required this.minMessageLen, + required this.maxMessageLen, + required this.allowedFilesType, + required this.filesMaxSize, + required this.writingEventInterval, + required this.writingEventLifetime, + required this.maxMessageImageWidth, + required this.maxMessageImageHeight, + required this.maxThumbnailWidth, + required this.maxThumbnailHeight, + required this.maxLogoWidth, + required this.maxLogoHeight, }) : assert(maxConversationNameLen != null), assert(minMessageLen != null), assert(maxMessageLen != null), @@ -121,11 +120,11 @@ class AccountInformationPolicy { final int maxLocationLength; const AccountInformationPolicy({ - @required this.minFirstNameLength, - @required this.maxFirstNameLength, - @required this.minLastNameLength, - @required this.maxLastNameLength, - @required this.maxLocationLength, + required this.minFirstNameLength, + required this.maxFirstNameLength, + required this.minLastNameLength, + required this.maxLastNameLength, + required this.maxLocationLength, }) : assert(minFirstNameLength != null), assert(maxFirstNameLength != null), assert(minLastNameLength != null), @@ -136,7 +135,7 @@ class AccountInformationPolicy { enum BannerNature { Information, Warning, Success } extension BannerNatureExt on BannerNature { - static BannerNature fromStr(String s) { + static BannerNature fromStr(String? s) { switch (s) { case "information": return BannerNature.Information; @@ -151,22 +150,22 @@ extension BannerNatureExt on BannerNature { class Banner { final bool enabled; - final int expire; + final int? expire; final BannerNature nature; final Map message; - final String link; + final String? link; const Banner({ - @required this.enabled, - @required this.expire, - @required this.nature, - @required this.message, - @required this.link, + required this.enabled, + required this.expire, + required this.nature, + required this.message, + required this.link, }) : assert(enabled != null), assert(nature != null), assert(message != null); - bool get visible => enabled && (expire == null || expire > time()); + bool get visible => enabled && (expire == null || expire! > time()); } class ServerConfig { @@ -176,7 +175,7 @@ class ServerConfig { final String contactEmail; final String playStoreURL; final String androidDirectDownloadURL; - final Banner banner; + final Banner? banner; final NotificationsPolicy notificationsPolicy; final PasswordPolicy passwordPolicy; final ServerDataConservationPolicy dataConservationPolicy; @@ -184,18 +183,18 @@ class ServerConfig { final AccountInformationPolicy accountInformationPolicy; const ServerConfig({ - @required this.minSupportedMobileVersion, - @required this.termsURL, - @required this.privacyPolicyURL, - @required this.contactEmail, - @required this.playStoreURL, - @required this.androidDirectDownloadURL, - @required this.banner, - @required this.notificationsPolicy, - @required this.passwordPolicy, - @required this.dataConservationPolicy, - @required this.conversationsPolicy, - @required this.accountInformationPolicy, + required this.minSupportedMobileVersion, + required this.termsURL, + required this.privacyPolicyURL, + required this.contactEmail, + required this.playStoreURL, + required this.androidDirectDownloadURL, + required this.banner, + required this.notificationsPolicy, + required this.passwordPolicy, + required this.dataConservationPolicy, + required this.conversationsPolicy, + required this.accountInformationPolicy, }) : assert(minSupportedMobileVersion != null), assert(termsURL != null), assert(privacyPolicyURL != null), diff --git a/lib/models/survey.dart b/lib/models/survey.dart index 9aa657d..304ead1 100644 --- a/lib/models/survey.dart +++ b/lib/models/survey.dart @@ -1,6 +1,5 @@ import 'package:comunic/models/survey_choice.dart'; import 'package:comunic/utils/account_utils.dart' as account; -import 'package:meta/meta.dart'; /// Survey information /// @@ -17,14 +16,14 @@ class Survey { bool allowNewChoicesCreation; Survey({ - @required this.id, - @required this.userID, - @required this.postID, - @required this.creationTime, - @required this.question, - @required this.userChoice, - @required this.choices, - @required this.allowNewChoicesCreation, + required this.id, + required this.userID, + required this.postID, + required this.creationTime, + required this.question, + required this.userChoice, + required this.choices, + required this.allowNewChoicesCreation, }) : assert(id != null), assert(userID != null), assert(postID != null), @@ -43,14 +42,14 @@ class Survey { bool get canBlockNewChoicesCreation => allowNewChoicesCreation && account.userID() == this.userID; - SurveyChoice get userResponse { + SurveyChoice? get userResponse { if (!hasResponded) return null; return choices.firstWhere((e) => e.id == userChoice); } void cancelUserResponse() { - if (hasResponded) userResponse.responses--; + if (hasResponded) userResponse!.responses--; userChoice = 0; } diff --git a/lib/models/survey_choice.dart b/lib/models/survey_choice.dart index a5a768f..aad40e5 100644 --- a/lib/models/survey_choice.dart +++ b/lib/models/survey_choice.dart @@ -1,4 +1,4 @@ -import 'package:meta/meta.dart'; + /// Single survey choice /// @@ -10,9 +10,9 @@ class SurveyChoice { int responses; SurveyChoice({ - @required this.id, - @required this.name, - @required this.responses, + required this.id, + required this.name, + required this.responses, }) : assert(id != null), assert(name != null), assert(responses != null); diff --git a/lib/models/unread_conversation.dart b/lib/models/unread_conversation.dart index 325b8d1..ccea0ff 100644 --- a/lib/models/unread_conversation.dart +++ b/lib/models/unread_conversation.dart @@ -1,6 +1,5 @@ import 'package:comunic/models/conversation.dart'; import 'package:comunic/models/conversation_message.dart'; -import 'package:flutter/material.dart'; /// Unread conversation information /// @@ -11,8 +10,8 @@ class UnreadConversation { final ConversationMessage message; const UnreadConversation({ - @required this.conv, - @required this.message, + required this.conv, + required this.message, }) : assert(conv != null), assert(message != null); } diff --git a/lib/models/user.dart b/lib/models/user.dart index c0ebf6a..4b38146 100644 --- a/lib/models/user.dart +++ b/lib/models/user.dart @@ -5,7 +5,6 @@ import 'package:comunic/helpers/serialization/base_serialization_helper.dart'; import 'package:comunic/lists/custom_emojies_list.dart'; import 'package:comunic/utils/account_utils.dart'; import 'package:comunic/utils/ui_utils.dart'; -import 'package:meta/meta.dart'; /// Single user information /// @@ -13,21 +12,21 @@ import 'package:meta/meta.dart'; class User implements SerializableElement { final int id; - final String firstName; - final String lastName; + final String? firstName; + final String? lastName; final UserPageVisibility pageVisibility; - final String virtualDirectory; - final String accountImageURL; + final String? virtualDirectory; + final String? accountImageURL; final CustomEmojiesList customEmojies; const User({ - @required this.id, - @required this.firstName, - @required this.lastName, - @required this.pageVisibility, - @required this.virtualDirectory, - @required this.accountImageURL, - @required this.customEmojies, + required int this.id, + required String this.firstName, + required String this.lastName, + required this.pageVisibility, + required this.virtualDirectory, + required String this.accountImageURL, + required this.customEmojies, }) : assert(id != null), assert(id > 0), assert(firstName != null), @@ -37,13 +36,13 @@ class User implements SerializableElement { assert(customEmojies != null); /// Get user full name - String get fullName => firstName + " " + lastName; + String get fullName => firstName! + " " + lastName!; /// Get user display name String get displayName => htmlDecodeCharacters(fullName); bool get hasVirtualDirectory => - virtualDirectory != null && virtualDirectory.length > 0; + virtualDirectory != null && virtualDirectory!.length > 0; bool get isCurrentUser => id == userID(); @@ -69,5 +68,5 @@ class User implements SerializableElement { jsonDecode(map["customEmojies"])); @override - int compareTo(User other) => id.compareTo(other.id); + int compareTo(User other) => id!.compareTo(other.id!); } diff --git a/lib/models/ws_message.dart b/lib/models/ws_message.dart index fdeae0b..3cf4d96 100644 --- a/lib/models/ws_message.dart +++ b/lib/models/ws_message.dart @@ -1,7 +1,5 @@ import 'dart:convert'; -import 'package:flutter/widgets.dart'; - /// WebSocket message /// /// @author Pierre Hubert @@ -12,9 +10,9 @@ class WsMessage { final dynamic data; const WsMessage({ - @required this.id, - @required this.title, - @required this.data, + required this.id, + required this.title, + required this.data, }) : assert(id != null), assert(title != null), assert(title.length > 0); diff --git a/lib/ui/dialogs/alert_dialog.dart b/lib/ui/dialogs/alert_dialog.dart index 07deb0d..6bca726 100644 --- a/lib/ui/dialogs/alert_dialog.dart +++ b/lib/ui/dialogs/alert_dialog.dart @@ -4,14 +4,14 @@ import 'package:flutter/material.dart'; /// /// @author Pierre Hubert -Future alert(BuildContext context, String msg) async { - await showDialog(context: context, builder: (c) => _AlertDialog(msg: msg)); +Future alert(BuildContext context, String? msg) async { + await showDialog(context: context, builder: (c) => _AlertDialog(msg: msg!)); } class _AlertDialog extends StatelessWidget { final String msg; - const _AlertDialog({Key key, @required this.msg}) + const _AlertDialog({Key? key, required this.msg}) : assert(msg != null), super(key: key); diff --git a/lib/ui/dialogs/audio_player_dialog.dart b/lib/ui/dialogs/audio_player_dialog.dart index f9a6030..972f759 100644 --- a/lib/ui/dialogs/audio_player_dialog.dart +++ b/lib/ui/dialogs/audio_player_dialog.dart @@ -9,16 +9,16 @@ import 'package:video_player/video_player.dart'; /// @author Pierre Hubert /// Show audio player dialog -Future showAudioPlayerDialog(BuildContext context, String url) async { - showDialog(context: context, builder: (c) => _AudioPlayerDialog(url: url)); +Future showAudioPlayerDialog(BuildContext context, String? url) async { + showDialog(context: context, builder: (c) => _AudioPlayerDialog(url: url!)); } class _AudioPlayerDialog extends StatefulWidget { final String url; const _AudioPlayerDialog({ - Key key, - @required this.url, + Key? key, + required this.url, }) : assert(url != null), super(key: key); @@ -27,16 +27,16 @@ class _AudioPlayerDialog extends StatefulWidget { } class __AudioPlayerDialogState extends State<_AudioPlayerDialog> { - VideoPlayerController _videoPlayerController; - ChewieAudioController _chewieAudioController; + VideoPlayerController? _videoPlayerController; + ChewieAudioController? _chewieAudioController; Future _initialize() async { _videoPlayerController = VideoPlayerController.network(widget.url); - await _videoPlayerController.initialize(); + await _videoPlayerController!.initialize(); _chewieAudioController = ChewieAudioController( - videoPlayerController: _videoPlayerController, + videoPlayerController: _videoPlayerController!, autoPlay: true, looping: false, ); @@ -48,20 +48,20 @@ class __AudioPlayerDialogState extends State<_AudioPlayerDialog> { @override void dispose() { - if (_videoPlayerController != null) _videoPlayerController.dispose(); - if (_chewieAudioController != null) _chewieAudioController.dispose(); + if (_videoPlayerController != null) _videoPlayerController!.dispose(); + if (_chewieAudioController != null) _chewieAudioController!.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return AlertDialog( - title: Text(tr("Audio Player")), + title: Text(tr("Audio Player")!), content: _buildContent(), actions: [ MaterialButton( onPressed: _closeDialog, - child: Text(tr("Close").toUpperCase()), + child: Text(tr("Close")!.toUpperCase()), ) ], ); @@ -72,10 +72,10 @@ class __AudioPlayerDialogState extends State<_AudioPlayerDialog> { child: AsyncScreenWidget( onReload: _initialize, onBuild: _buildReadyContent, - errorMessage: tr("Failed to initialize audio player!"), + errorMessage: tr("Failed to initialize audio player!")!, ), ); Widget _buildReadyContent() => - ChewieAudio(controller: _chewieAudioController); + ChewieAudio(controller: _chewieAudioController!); } diff --git a/lib/ui/dialogs/color_picker_dialog.dart b/lib/ui/dialogs/color_picker_dialog.dart index 4672b66..20fee8f 100644 --- a/lib/ui/dialogs/color_picker_dialog.dart +++ b/lib/ui/dialogs/color_picker_dialog.dart @@ -6,17 +6,17 @@ import 'package:flutter_colorpicker/flutter_colorpicker.dart'; /// /// @author Pierre Hubert -Future showColorPickerDialog( - BuildContext context, Color initialColor) async => +Future showColorPickerDialog( + BuildContext context, Color? initialColor) async => await showDialog( context: context, builder: (c) => _ColorPickerDialog(initialColor: initialColor), ); class _ColorPickerDialog extends StatefulWidget { - final Color initialColor; + final Color? initialColor; - const _ColorPickerDialog({Key key, @required this.initialColor}) + const _ColorPickerDialog({Key? key, required this.initialColor}) : super(key: key); @override @@ -24,7 +24,7 @@ class _ColorPickerDialog extends StatefulWidget { } class __ColorPickerDialogState extends State<_ColorPickerDialog> { - Color _newColor; + Color? _newColor; @override void initState() { @@ -42,11 +42,11 @@ class __ColorPickerDialogState extends State<_ColorPickerDialog> { actions: [ MaterialButton( onPressed: () => Navigator.pop(context, widget.initialColor), - child: Text(tr("Cancel").toUpperCase()), + child: Text(tr("Cancel")!.toUpperCase()), ), MaterialButton( onPressed: () => Navigator.pop(context, _newColor), - child: Text(tr("Ok").toUpperCase()), + child: Text(tr("Ok")!.toUpperCase()), ), ], ); diff --git a/lib/ui/dialogs/deprecation_dialog.dart b/lib/ui/dialogs/deprecation_dialog.dart index f7f0f2d..354c743 100644 --- a/lib/ui/dialogs/deprecation_dialog.dart +++ b/lib/ui/dialogs/deprecation_dialog.dart @@ -16,23 +16,23 @@ class _DeprecationDialog extends StatelessWidget { @override Widget build(BuildContext context) { return AlertDialog( - title: Text(tr("Deprecated application version")), + title: Text(tr("Deprecated application version")!), content: Text(tr( - "This version of the Comunic application is deprecated. You might still be able to use it, but some features may not work. We recommend you to update to the latest version of the application.")), + "This version of the Comunic application is deprecated. You might still be able to use it, but some features may not work. We recommend you to update to the latest version of the application.")!), actions: [ MaterialButton( onPressed: () => - launch(ServerConfigurationHelper.config.playStoreURL), - child: Text(tr("Go to the Play Store")), + launch(ServerConfigurationHelper.config!.playStoreURL), + child: Text(tr("Go to the Play Store")!), ), MaterialButton( onPressed: () => - launch(ServerConfigurationHelper.config.androidDirectDownloadURL), - child: Text(tr("Download update outside Play Store")), + launch(ServerConfigurationHelper.config!.androidDirectDownloadURL), + child: Text(tr("Download update outside Play Store")!), ), MaterialButton( onPressed: () => Navigator.pop(context), - child: Text(tr("Use the old application anyway")), + child: Text(tr("Use the old application anyway")!), ) ], ); diff --git a/lib/ui/dialogs/input_new_password_dialog.dart b/lib/ui/dialogs/input_new_password_dialog.dart index 85e7766..28cd45f 100644 --- a/lib/ui/dialogs/input_new_password_dialog.dart +++ b/lib/ui/dialogs/input_new_password_dialog.dart @@ -8,9 +8,9 @@ import 'package:flutter/material.dart'; /// @author Pierre HUBERT /// Ask the user to enter a new password -Future showInputNewPassword({ - @required BuildContext context, - @required UserInfoForPassword userInfo, +Future showInputNewPassword({ + required BuildContext context, + required UserInfoForPassword userInfo, }) async { assert(context != null); assert(userInfo != null); @@ -25,8 +25,8 @@ class _InputNewPasswordDialog extends StatefulWidget { final UserInfoForPassword userInfo; const _InputNewPasswordDialog({ - Key key, - @required this.userInfo, + Key? key, + required this.userInfo, }) : assert(userInfo != null), super(key: key); @@ -40,16 +40,16 @@ class __InputNewPasswordDialogState extends State<_InputNewPasswordDialog> { final _controller2 = TextEditingController(); final _focusScopeNode = FocusScopeNode(); - String get _password => _controller1.currentState.value; + String get _password => _controller1.currentState!.value; bool get _input1Valid => - _controller1.currentState != null && _controller1.currentState.valid; + _controller1.currentState != null && _controller1.currentState!.valid; - bool get _input2Valid => _controller1.currentState.value == _controller2.text; + bool get _input2Valid => _controller1.currentState!.value == _controller2.text; bool get _isValid => _input1Valid && _input2Valid; - void Function() get _submitAction => + void Function()? get _submitAction => _isValid ? () => Navigator.of(context).pop(_password) : null; @override @@ -61,16 +61,16 @@ class __InputNewPasswordDialogState extends State<_InputNewPasswordDialog> { @override Widget build(BuildContext context) { return AlertDialog( - title: Text(tr("New password")), + title: Text(tr("New password")!), content: AutoSizeDialogContentWidget(child: _buildContent()), actions: [ MaterialButton( onPressed: () => Navigator.of(context).pop(), - child: Text(tr("Cancel").toUpperCase()), + child: Text(tr("Cancel")!.toUpperCase()), ), MaterialButton( onPressed: _submitAction, - child: Text(tr("Confirm").toUpperCase()), + child: Text(tr("Confirm")!.toUpperCase()), ), ], ); @@ -85,7 +85,7 @@ class __InputNewPasswordDialogState extends State<_InputNewPasswordDialog> { NewPasswordInputWidget( key: _controller1, user: widget.userInfo, - label: tr("Your new password"), + label: tr("Your new password")!, textInputAction: TextInputAction.next, onSubmitted: () => _focusScopeNode.nextFocus(), ), @@ -105,17 +105,17 @@ class __InputNewPasswordDialogState extends State<_InputNewPasswordDialog> { } Widget _buildPasswordField({ - @required TextEditingController controller, - @required String label, - @required String errorText, - @required TextInputAction textInputAction, - @required void Function() onSubmitted, + required TextEditingController controller, + required String? label, + required String? errorText, + required TextInputAction textInputAction, + required void Function()? onSubmitted, }) { return TextFormField( textInputAction: textInputAction, controller: controller, onChanged: (s) => setState(() {}), - onFieldSubmitted: (s) => onSubmitted(), + onFieldSubmitted: (s) => onSubmitted!(), obscureText: true, decoration: InputDecoration( alignLabelWithHint: true, diff --git a/lib/ui/dialogs/input_url_dialog.dart b/lib/ui/dialogs/input_url_dialog.dart index 81602ca..d75c7b2 100644 --- a/lib/ui/dialogs/input_url_dialog.dart +++ b/lib/ui/dialogs/input_url_dialog.dart @@ -8,20 +8,20 @@ import 'package:flutter/material.dart'; /// @author Pierre Hubert /// Ask the user to enter an URL -Future showInputURLDialog({ - @required BuildContext context, - @required String title, - String initialURL, +Future showInputURLDialog({ + required BuildContext context, + required String? title, + String? initialURL, }) async { return await showDialog( context: context, builder: (c) => SingleInputDialog( - title: title, + title: title!, icon: Icons.link, initialValue: initialURL, label: "http://...", checkInput: (s) => validateUrl(s), - errorMessage: tr("Invalid URL!"), + errorMessage: tr("Invalid URL!")!, ), ); } diff --git a/lib/ui/dialogs/input_user_password_dialog.dart b/lib/ui/dialogs/input_user_password_dialog.dart index 44414ee..445b92b 100644 --- a/lib/ui/dialogs/input_user_password_dialog.dart +++ b/lib/ui/dialogs/input_user_password_dialog.dart @@ -11,7 +11,7 @@ import 'package:flutter/material.dart'; enum _Status { NONE, CHECKING, ERROR } -Future showUserPasswordDialog(BuildContext context) async { +Future showUserPasswordDialog(BuildContext context) async { return await showDialog( context: context, builder: (c) => _InputUserPasswordDialog()); } @@ -37,16 +37,16 @@ class __InputUserPasswordDialogState @override Widget build(BuildContext context) { return AlertDialog( - title: Text(tr("Password required")), + title: Text(tr("Password required")!), content: _buildContent(), actions: [ MaterialButton( onPressed: () => Navigator.of(context).pop(), - child: Text(tr("Cancel").toUpperCase()), + child: Text(tr("Cancel")!.toUpperCase()), ), MaterialButton( onPressed: _canSubmit ? _checkPassword : null, - child: Text(tr("Submit").toUpperCase()), + child: Text(tr("Submit")!.toUpperCase()), ), ], ); diff --git a/lib/ui/dialogs/input_youtube_link_dialog.dart b/lib/ui/dialogs/input_youtube_link_dialog.dart index ca0c675..455a197 100644 --- a/lib/ui/dialogs/input_youtube_link_dialog.dart +++ b/lib/ui/dialogs/input_youtube_link_dialog.dart @@ -7,19 +7,19 @@ import 'package:flutter/material.dart'; /// @author Pierre Hubert /// Ask the user to input a YouTube ID -Future showInputYouTubeIDDialog( - BuildContext context, String initialID) async { +Future showInputYouTubeIDDialog( + BuildContext context, String? initialID) async { final value = await showDialog( context: context, builder: (b) => SingleInputDialog( - title: tr("Input YouTube URL"), + title: tr("Input YouTube URL")!, icon: Icons.ondemand_video, initialValue: initialID == null ? null : "https://www.youtube.com/watch/?v=" + initialID, - label: tr("https://www.youtube.com/watch/?v="), + label: tr("https://www.youtube.com/watch/?v=")!, checkInput: (s) => RegExp(r'watch\/\?v=[\w\-\_]+').hasMatch(s), - errorMessage: tr("Invalid YouTube link!"), + errorMessage: tr("Invalid YouTube link!")!, )); if (value == null) return null; diff --git a/lib/ui/dialogs/multi_choices_dialog.dart b/lib/ui/dialogs/multi_choices_dialog.dart index 15466b6..a19591d 100644 --- a/lib/ui/dialogs/multi_choices_dialog.dart +++ b/lib/ui/dialogs/multi_choices_dialog.dart @@ -10,12 +10,12 @@ import 'package:flutter/material.dart'; class MultiChoiceEntry { final T id; final String title; - final String subtitle; + final String? subtitle; final bool hidden; const MultiChoiceEntry({ - @required this.id, - @required this.title, + required this.id, + required this.title, this.subtitle, this.hidden = false, }) : assert(id != null), @@ -26,16 +26,16 @@ class MultiChoiceEntry { } /// Show multiple choices dialog -Future showMultiChoicesDialog({ - @required BuildContext context, - @required List> choices, - @required T defaultChoice, - @required String title, +Future showMultiChoicesDialog({ + required BuildContext context, + required List> choices, + required T defaultChoice, + required String? title, }) async { return await showDialog( context: context, builder: (c) => _MultiChoicesEntryDialog( - title: title, + title: title!, defaultChoice: defaultChoice, choices: choices, )); @@ -47,10 +47,10 @@ class _MultiChoicesEntryDialog extends StatefulWidget { final List> choices; const _MultiChoicesEntryDialog({ - Key key, - @required this.title, - @required this.defaultChoice, - @required this.choices, + Key? key, + required this.title, + required this.defaultChoice, + required this.choices, }) : assert(title != null), assert(defaultChoice != null), assert(choices != null), @@ -63,7 +63,7 @@ class _MultiChoicesEntryDialog extends StatefulWidget { class __MultiChoicesEntryDialogState extends State<_MultiChoicesEntryDialog> { - T _currChoice; + T? _currChoice; @override void initState() { @@ -86,7 +86,7 @@ class __MultiChoicesEntryDialogState onChanged: (v) => setState(() => _currChoice = v), ), title: Text(f.title), - subtitle: f.hasSubtitle ? Text(f.subtitle) : null, + subtitle: f.hasSubtitle ? Text(f.subtitle!) : null, )) .toList(), ), @@ -94,12 +94,12 @@ class __MultiChoicesEntryDialogState actions: [ MaterialButton( onPressed: () => Navigator.of(context).pop(), - child: Text(tr("Cancel").toUpperCase()), + child: Text(tr("Cancel")!.toUpperCase()), textColor: Colors.red, ), MaterialButton( onPressed: () => Navigator.of(context).pop(_currChoice), - child: Text(tr("Confirm").toUpperCase()), + child: Text(tr("Confirm")!.toUpperCase()), textColor: Colors.green, ), ], diff --git a/lib/ui/dialogs/new_survey_dialog.dart b/lib/ui/dialogs/new_survey_dialog.dart index 8a6fbae..3578712 100644 --- a/lib/ui/dialogs/new_survey_dialog.dart +++ b/lib/ui/dialogs/new_survey_dialog.dart @@ -7,8 +7,8 @@ import 'package:flutter/material.dart'; /// @author Pierre Hubert /// Show a dialog to prompt information about a new survey to create -Future showNewSurveyDialog( - {@required BuildContext context, NewSurvey initialSurvey}) async { +Future showNewSurveyDialog( + {required BuildContext context, NewSurvey? initialSurvey}) async { return await showDialog( context: context, builder: (c) => _SurveyDialog( @@ -17,25 +17,25 @@ Future showNewSurveyDialog( } class _SurveyDialog extends StatefulWidget { - final NewSurvey initialSurvey; + final NewSurvey? initialSurvey; - const _SurveyDialog({Key key, this.initialSurvey}) : super(key: key); + const _SurveyDialog({Key? key, this.initialSurvey}) : super(key: key); @override __SurveyDialogState createState() => __SurveyDialogState(); } class __SurveyDialogState extends State<_SurveyDialog> { - TextEditingController _questionController; + TextEditingController? _questionController; final _choiceController = TextEditingController(); var _choices = Set(); var _allowNewChoices = false; bool get canConfirm => - _questionController.text.length > 2 && _choices.length > 1; + _questionController!.text.length > 2 && _choices.length > 1; NewSurvey get newSurvey => NewSurvey( - question: _questionController.text, + question: _questionController!.text, answers: _choices, allowNewChoicesCreation: _allowNewChoices); @@ -43,31 +43,31 @@ class __SurveyDialogState extends State<_SurveyDialog> { void initState() { super.initState(); _questionController = TextEditingController( - text: widget.initialSurvey == null ? "" : widget.initialSurvey.question, + text: widget.initialSurvey == null ? "" : widget.initialSurvey!.question, ); if (widget.initialSurvey != null) { - _choices = widget.initialSurvey.answers; - _allowNewChoices = widget.initialSurvey.allowNewChoicesCreation; + _choices = widget.initialSurvey!.answers; + _allowNewChoices = widget.initialSurvey!.allowNewChoicesCreation; } } @override Widget build(BuildContext context) { return AlertDialog( - title: Text(tr("New survey")), + title: Text(tr("New survey")!), content: _buildBody(), actions: [ // Cancel MaterialButton( onPressed: () => Navigator.of(context).pop(), - child: Text(tr("Cancel").toUpperCase()), + child: Text(tr("Cancel")!.toUpperCase()), ), // Confirm MaterialButton( onPressed: canConfirm ? () => Navigator.of(context).pop(newSurvey) : null, - child: Text(tr("Confirm").toUpperCase()), + child: Text(tr("Confirm")!.toUpperCase()), ), ], ); @@ -90,7 +90,7 @@ class __SurveyDialogState extends State<_SurveyDialog> { ), Container(height: 30), - Text(tr("Current choices:")), + Text(tr("Current choices:")!), _buildCurrentChoices(), Container( @@ -118,7 +118,7 @@ class __SurveyDialogState extends State<_SurveyDialog> { value: _allowNewChoices, onChanged: (v) => setState(() => _allowNewChoices = v), ), - title: Text(tr("Allow users to create new choices")), + title: Text(tr("Allow users to create new choices")!), ) ]), ), @@ -126,7 +126,7 @@ class __SurveyDialogState extends State<_SurveyDialog> { } Widget _buildCurrentChoices() { - if (_choices.length == 0) return Text(tr("No choice yet.")); + if (_choices.length == 0) return Text(tr("No choice yet.")!); return Column( children: _choices diff --git a/lib/ui/dialogs/pick_file_dialog.dart b/lib/ui/dialogs/pick_file_dialog.dart index 2589de2..693fe4c 100644 --- a/lib/ui/dialogs/pick_file_dialog.dart +++ b/lib/ui/dialogs/pick_file_dialog.dart @@ -35,10 +35,10 @@ class _PickFileOption { final _CanEnable canEnable; const _PickFileOption({ - @required this.value, - @required this.label, - @required this.icon, - @required this.canEnable, + required this.value, + required this.label, + required this.icon, + required this.canEnable, }) : assert(value != null), assert(label != null), assert(icon != null), @@ -49,50 +49,50 @@ List<_PickFileOption> get _optionsList => [ // Image _PickFileOption( value: _FileChoices.PICK_IMAGE, - label: tr("Choose an image"), + label: tr("Choose an image")!, icon: Icons.image, canEnable: (l) => l.any(isImage)), _PickFileOption( value: _FileChoices.TAKE_PICTURE, - label: tr("Take a picture"), + label: tr("Take a picture")!, icon: Icons.camera_alt, canEnable: (l) => l.any(isImage)), // Video _PickFileOption( value: _FileChoices.PICK_VIDEO, - label: tr("Choose a video"), + label: tr("Choose a video")!, icon: Icons.video_library, canEnable: (l) => l.any(isVideo)), _PickFileOption( value: _FileChoices.TAKE_VIDEO, - label: tr("Take a video"), + label: tr("Take a video")!, icon: Icons.videocam, canEnable: (l) => l.any(isVideo)), // Audio _PickFileOption( value: _FileChoices.RECORD_AUDIO, - label: tr("Record audio"), + label: tr("Record audio")!, icon: Icons.mic, canEnable: (l) => l.any(isAudio)), // Other _PickFileOption( value: _FileChoices.PICK_OTHER_FILE, - label: tr("Browse files"), + label: tr("Browse files")!, icon: Icons.folder_open, canEnable: (l) => l.any((el) => !isImage(el) && !isVideo(el) && !isAudio(el))), ]; -Future showPickFileDialog({ - @required BuildContext context, - int maxFileSize, - List allowedMimeTypes, - int imageMaxWidth, - int imageMaxHeight, - CropAspectRatio aspectRatio, +Future showPickFileDialog({ + required BuildContext context, + int? maxFileSize, + required List allowedMimeTypes, + int? imageMaxWidth, + int? imageMaxHeight, + CropAspectRatio? aspectRatio, }) async { assert(allowedMimeTypes != null); @@ -118,7 +118,7 @@ Future showPickFileDialog({ if (choice == null) return null; - BytesFile file; + BytesFile? file; switch (choice) { // Pick an image case _FileChoices.PICK_IMAGE: @@ -127,8 +127,8 @@ Future showPickFileDialog({ source: choice == _FileChoices.PICK_IMAGE ? ImageSource.gallery : ImageSource.camera, - maxWidth: imageMaxWidth.toDouble(), - maxHeight: imageMaxHeight.toDouble(), + maxWidth: imageMaxWidth!.toDouble(), + maxHeight: imageMaxHeight!.toDouble(), ); if (image == null) return null; @@ -179,11 +179,11 @@ Future showPickFileDialog({ if (file == null) return null; // Check file size - if (maxFileSize != null && file.bytes.length > maxFileSize) { + if (maxFileSize != null && file.bytes!.length > maxFileSize) { showSimpleSnack( context, tr("This file could not be sent: it is too big! (Max allowed size: %1%)", - args: {"1": filesize(file.bytes.length)})); + args: {"1": filesize(file.bytes!.length)})!); return null; } @@ -195,7 +195,7 @@ class _BottomSheetPickOption extends StatelessWidget { final _OnOptionSelected onOptionSelected; const _BottomSheetPickOption( - {Key key, @required this.options, @required this.onOptionSelected}) + {Key? key, required this.options, required this.onOptionSelected}) : assert(options != null), assert(onOptionSelected != null), super(key: key); diff --git a/lib/ui/dialogs/pick_user_dialog.dart b/lib/ui/dialogs/pick_user_dialog.dart index abafa7e..21c9ff1 100644 --- a/lib/ui/dialogs/pick_user_dialog.dart +++ b/lib/ui/dialogs/pick_user_dialog.dart @@ -13,7 +13,7 @@ import 'package:flutter/material.dart'; /// Ask the user to pick a user /// /// Returns null if no user was selected -Future showPickUserDialog(BuildContext context) async { +Future showPickUserDialog(BuildContext context) async { return await showDialog(context: context, builder: (c) => _PickUserDialog()); } @@ -23,19 +23,19 @@ class _PickUserDialog extends StatefulWidget { } class __PickUserDialogState extends SafeState<_PickUserDialog> { - User _user; + User? _user; bool get _isValid => _user != null; @override Widget build(BuildContext context) { return AlertDialog( - title: Text(tr("Choose a user")), + title: Text(tr("Choose a user")!), content: _buildContent(), actions: [ CancelDialogButton(), ConfirmDialogButton( - value: _isValid ? _user.id : null, + value: _isValid ? _user!.id : null, enabled: _isValid, ), ], @@ -52,7 +52,7 @@ class __PickUserDialogState extends SafeState<_PickUserDialog> { children: [ PickUserWidget( onSelectUser: (u) => setState(() => _user = u), - label: tr("Search user..."), + label: tr("Search user...")!, onValueChange: (u) => setState(() => _user = null), ), ], diff --git a/lib/ui/dialogs/post_visibility_picker_dialog.dart b/lib/ui/dialogs/post_visibility_picker_dialog.dart index 332f8c0..b185553 100644 --- a/lib/ui/dialogs/post_visibility_picker_dialog.dart +++ b/lib/ui/dialogs/post_visibility_picker_dialog.dart @@ -9,9 +9,9 @@ import 'package:flutter/material.dart'; /// Show post visibility level picker and return selected visibility level Future showPostVisibilityPickerDialog({ - @required BuildContext context, - @required PostVisibilityLevel initialLevel, - @required bool isGroup, + required BuildContext context, + required PostVisibilityLevel initialLevel, + required bool isGroup, }) async { assert(context != null); assert(initialLevel != null); @@ -30,12 +30,12 @@ Future showPostVisibilityPickerDialog({ class _PostVisibilityPickerWidget extends StatelessWidget { final bool isGroup; - const _PostVisibilityPickerWidget({Key key, @required this.isGroup}) + const _PostVisibilityPickerWidget({Key? key, required this.isGroup}) : super(key: key); @override Widget build(BuildContext c) => AlertDialog( - title: Text(tr("Select new post visibility level")), + title: Text(tr("Select new post visibility level")!), // Show all options content: ConstrainedBox( @@ -45,14 +45,14 @@ class _PostVisibilityPickerWidget extends StatelessWidget { // Public PostVisibilityLevelTile( level: PostVisibilityLevel.PUBLIC, - title: tr("Public"), + title: tr("Public")!, onSelect: (o) => Navigator.pop(c, o), ), // Friends only (User page only) PostVisibilityLevelTile( level: PostVisibilityLevel.FRIENDS, - title: tr("Friends only"), + title: tr("Friends only")!, onSelect: (o) => Navigator.pop(c, o), visible: !isGroup, ), @@ -60,7 +60,7 @@ class _PostVisibilityPickerWidget extends StatelessWidget { // User only (User page only) PostVisibilityLevelTile( level: PostVisibilityLevel.USER, - title: tr("Me only"), + title: tr("Me only")!, onSelect: (o) => Navigator.pop(c, o), visible: !isGroup, ), @@ -68,7 +68,7 @@ class _PostVisibilityPickerWidget extends StatelessWidget { // Group members only (Group page only) PostVisibilityLevelTile( level: PostVisibilityLevel.GROUP_MEMBERS, - title: tr("Group members only"), + title: tr("Group members only")!, onSelect: (o) => Navigator.pop(c, o), visible: isGroup, ), @@ -80,7 +80,7 @@ class _PostVisibilityPickerWidget extends StatelessWidget { actions: [ // Cancel TextButton( - child: Text(tr("Cancel").toUpperCase()), + child: Text(tr("Cancel")!.toUpperCase()), onPressed: () => Navigator.pop(c, null), ), ], diff --git a/lib/ui/dialogs/record_audio_dialog.dart b/lib/ui/dialogs/record_audio_dialog.dart index 0fa8c5e..bfeb728 100644 --- a/lib/ui/dialogs/record_audio_dialog.dart +++ b/lib/ui/dialogs/record_audio_dialog.dart @@ -18,7 +18,7 @@ import 'package:video_player/video_player.dart'; /// @author Pierre Hubert /// Record audio -Future showRecordAudioDialog(BuildContext context) async { +Future showRecordAudioDialog(BuildContext context) async { // Request record permission if (!await requestPermission(context, Permission.microphone)) { alert(context, tr("Did not get permission to access microphone!")); @@ -43,15 +43,15 @@ class _RecordAudioDialog extends StatefulWidget { } class __RecordAudioDialogState extends State<_RecordAudioDialog> { - String _recordPath; + String? _recordPath; - File get _recordFile => _recordPath == null ? null : File(_recordPath); + File? get _recordFile => _recordPath == null ? null : File(_recordPath!); bool _recording = false; bool get _hasRecord => !_recording && _recordPath != null; - VideoPlayerController _videoPlayerController; + VideoPlayerController? _videoPlayerController; bool _playing = false; @@ -59,8 +59,8 @@ class __RecordAudioDialogState extends State<_RecordAudioDialog> { /// Get record data. This getter can be accessed only once Uint8List get _bytes { - final bytes = _recordFile.readAsBytesSync(); - File(_recordPath).deleteSync(); + final bytes = _recordFile!.readAsBytesSync(); + File(_recordPath!).deleteSync(); return bytes; } @@ -73,7 +73,7 @@ class __RecordAudioDialogState extends State<_RecordAudioDialog> { void _disposePlayer() { if (_videoPlayerController != null) { - _videoPlayerController.dispose(); + _videoPlayerController!.dispose(); } _videoPlayerController = null; } @@ -81,24 +81,24 @@ class __RecordAudioDialogState extends State<_RecordAudioDialog> { @override Widget build(BuildContext context) { return AlertDialog( - title: Text(tr("Audio record")), + title: Text(tr("Audio record")!), content: _buildContent(), actions: [ _ActionButton( visible: !_recording, - text: tr("Cancel"), + text: tr("Cancel")!, onPressed: () => Navigator.of(context).pop(), ), _ActionButton( visible: _hasRecord, - text: tr("Send"), + text: tr("Send")!, onPressed: () => Navigator.of(context).pop(_bytes), ), ], ); } - String get _status { + String? get _status { if (_recording) return tr("Recording..."); else if (_paused) @@ -113,7 +113,7 @@ class __RecordAudioDialogState extends State<_RecordAudioDialog> { Widget _buildContent() => Row( children: [ - Text(_status), + Text(_status!), Spacer(), @@ -165,21 +165,21 @@ class __RecordAudioDialogState extends State<_RecordAudioDialog> { void _startRecording() async { try { - if (_recordFile != null) _recordFile.deleteSync(); + if (_recordFile != null) _recordFile!.deleteSync(); final dir = await getTemporaryDirectory(); _recordPath = path.join(dir.absolute.path, "tmp-audio-record.mp3"); - RecordMp3.instance.start(_recordPath, (fail) { + RecordMp3.instance.start(_recordPath!, (fail) { print(fail); - snack(context, tr("Failed to start recording!")); + snack(context, tr("Failed to start recording!")!); }); setState(() => _recording = true); } catch (e, s) { logError(e, s); - snack(context, tr("Error while recording!")); + snack(context, tr("Error while recording!")!); } } @@ -190,7 +190,7 @@ class __RecordAudioDialogState extends State<_RecordAudioDialog> { setState(() => _recording = false); } catch (e, s) { logError(e, s); - snack(context, tr("Error while recording!")); + snack(context, tr("Error while recording!")!); } } @@ -198,17 +198,17 @@ class __RecordAudioDialogState extends State<_RecordAudioDialog> { try { _disposePlayer(); - _videoPlayerController = VideoPlayerController.file(File(_recordPath)); - await _videoPlayerController.initialize(); + _videoPlayerController = VideoPlayerController.file(File(_recordPath!)); + await _videoPlayerController!.initialize(); - _videoPlayerController.addListener(() async { + _videoPlayerController!.addListener(() async { if (_videoPlayerController == null) return; - if (_videoPlayerController.value.position == - _videoPlayerController.value.duration) _stopPlayback(); + if (_videoPlayerController!.value.position == + _videoPlayerController!.value.duration) _stopPlayback(); }); - await _videoPlayerController.play(); + await _videoPlayerController!.play(); setState(() { _playing = true; @@ -216,27 +216,27 @@ class __RecordAudioDialogState extends State<_RecordAudioDialog> { }); } catch (e, s) { logError(e, s); - snack(context, tr("Error while playing record!")); + snack(context, tr("Error while playing record!")!); } } void _pausePlayback() async { try { - await _videoPlayerController.pause(); + await _videoPlayerController!.pause(); setState(() => _paused = true); } catch (e, s) { logError(e, s); - snack(context, tr("Error while pausing playback!")); + snack(context, tr("Error while pausing playback!")!); } } void _resumePlayback() async { try { - await _videoPlayerController.play(); + await _videoPlayerController!.play(); setState(() => _paused = false); } catch (e, s) { logError(e, s); - snack(context, tr("Error while resuming playback!")); + snack(context, tr("Error while resuming playback!")!); } } @@ -249,7 +249,7 @@ class __RecordAudioDialogState extends State<_RecordAudioDialog> { }); } catch (e, s) { logError(e, s); - snack(context, tr("Error while stopping playback!")); + snack(context, tr("Error while stopping playback!")!); } } } @@ -258,13 +258,13 @@ class _RecordAction extends StatelessWidget { final bool visible; final IconData icon; final void Function() onTap; - final Color color; + final Color? color; const _RecordAction({ - Key key, - @required this.visible, - @required this.icon, - @required this.onTap, + Key? key, + required this.visible, + required this.icon, + required this.onTap, this.color, }) : assert(visible != null), assert(icon != null), @@ -280,12 +280,12 @@ class _RecordAction extends StatelessWidget { class _ActionButton extends StatelessWidget { final bool visible; final String text; - final void Function() onPressed; + final void Function()? onPressed; const _ActionButton({ - Key key, - this.visible, - this.text, + Key? key, + required this.visible, + required this.text, this.onPressed, }) : assert(visible != null), assert(text != null), diff --git a/lib/ui/dialogs/screen_dialog.dart b/lib/ui/dialogs/screen_dialog.dart index 694dba4..3bda616 100644 --- a/lib/ui/dialogs/screen_dialog.dart +++ b/lib/ui/dialogs/screen_dialog.dart @@ -11,7 +11,7 @@ import 'package:flutter/material.dart'; /// /// This widget automatically adapt himself if we are in tablet /// or in mobile mode -Future showScreenDialog(BuildContext context, Widget screen) async { +Future showScreenDialog(BuildContext context, Widget screen) async { // TODO : add mobile support if (!isTablet(context)) throw Exception("Unsupported mode!"); @@ -20,9 +20,9 @@ Future showScreenDialog(BuildContext context, Widget screen) async { } class _ScreenDialog extends StatelessWidget { - final Widget body; + final Widget? body; - const _ScreenDialog({Key key, this.body}) : super(key: key); + const _ScreenDialog({Key? key, this.body}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/ui/dialogs/single_input_dialog.dart b/lib/ui/dialogs/single_input_dialog.dart index 7145050..eb4378f 100644 --- a/lib/ui/dialogs/single_input_dialog.dart +++ b/lib/ui/dialogs/single_input_dialog.dart @@ -7,23 +7,23 @@ import 'package:flutter/material.dart'; class SingleInputDialog extends StatefulWidget { final String title; - final IconData icon; - final String initialValue; + final IconData? icon; + final String? initialValue; final String label; final bool Function(String) checkInput; final String errorMessage; final bool canBeEmpty; final int maxLines; - final int maxLength; + final int? maxLength; const SingleInputDialog({ - Key key, - @required this.title, - @required this.icon, - @required this.initialValue, - @required this.label, - @required this.checkInput, - @required this.errorMessage, + Key? key, + required this.title, + required this.icon, + required this.initialValue, + required this.label, + required this.checkInput, + required this.errorMessage, this.canBeEmpty = false, this.maxLines = 1, this.maxLength, @@ -39,11 +39,11 @@ class SingleInputDialog extends StatefulWidget { } class __InputURLDialogState extends State { - TextEditingController _controller; + TextEditingController? _controller; bool get _isValid => - (_controller.text.isEmpty && widget.canBeEmpty) || - (_controller.text.isNotEmpty && widget.checkInput(_controller.text)); + (_controller!.text.isEmpty && widget.canBeEmpty) || + (_controller!.text.isNotEmpty && widget.checkInput(_controller!.text)); @override void initState() { @@ -64,7 +64,7 @@ class __InputURLDialogState extends State { icon: widget.icon == null ? null : Icon(widget.icon), alignLabelWithHint: true, labelText: widget.label, - errorText: _controller.text.isNotEmpty && !_isValid + errorText: _controller!.text.isNotEmpty && !_isValid ? widget.errorMessage : null, ), @@ -72,16 +72,16 @@ class __InputURLDialogState extends State { actions: [ // Cancel MaterialButton( - child: Text(tr("Cancel").toUpperCase()), + child: Text(tr("Cancel")!.toUpperCase()), onPressed: () => Navigator.of(context).pop(), textColor: Colors.red, ), // Confirm MaterialButton( - child: Text(tr("Confirm").toUpperCase()), + child: Text(tr("Confirm")!.toUpperCase()), onPressed: _isValid - ? () => Navigator.of(context).pop(_controller.text) + ? () => Navigator.of(context).pop(_controller!.text) : null, ), ], diff --git a/lib/ui/dialogs/virtual_directory_dialog.dart b/lib/ui/dialogs/virtual_directory_dialog.dart index dcefab3..244bfaf 100644 --- a/lib/ui/dialogs/virtual_directory_dialog.dart +++ b/lib/ui/dialogs/virtual_directory_dialog.dart @@ -12,11 +12,11 @@ enum VirtualDirectoryTargetType { USER, GROUP } enum _CheckStatus { EMPTY, PENDING, VALID, INVALID } -Future showVirtualDirectoryDialog({ - @required BuildContext context, - @required String initialDirectory, - @required int id, - @required VirtualDirectoryTargetType type, +Future showVirtualDirectoryDialog({ + required BuildContext context, + required String initialDirectory, + required int id, + required VirtualDirectoryTargetType type, }) async { assert(context != null); assert(initialDirectory != null); @@ -35,10 +35,10 @@ class _VirtualDirectoryPicker extends StatefulWidget { final VirtualDirectoryTargetType type; const _VirtualDirectoryPicker({ - Key key, - @required this.initialDirectory, - @required this.id, - @required this.type, + Key? key, + required this.initialDirectory, + required this.id, + required this.type, }) : assert(initialDirectory != null), assert(id != null), assert(type != null), @@ -50,10 +50,10 @@ class _VirtualDirectoryPicker extends StatefulWidget { } class __VirtualDirectoryPickerState extends SafeState<_VirtualDirectoryPicker> { - TextEditingController _controller; + TextEditingController? _controller; var _status = _CheckStatus.VALID; - String get _currentValue => _controller.text; + String get _currentValue => _controller!.text; @override void initState() { @@ -64,7 +64,7 @@ class __VirtualDirectoryPickerState extends SafeState<_VirtualDirectoryPicker> { @override Widget build(BuildContext context) { return AlertDialog( - title: Text(tr("Choose a virtual directory")), + title: Text(tr("Choose a virtual directory")!), // Dialog content content: TextField( @@ -89,7 +89,7 @@ class __VirtualDirectoryPickerState extends SafeState<_VirtualDirectoryPicker> { // Cancel MaterialButton( onPressed: () => Navigator.of(context).pop(), - child: Text(tr("Cancel").toUpperCase()), + child: Text(tr("Cancel")!.toUpperCase()), ), // Confirm @@ -98,7 +98,7 @@ class __VirtualDirectoryPickerState extends SafeState<_VirtualDirectoryPicker> { _status == _CheckStatus.VALID || _status == _CheckStatus.EMPTY ? () => Navigator.of(context).pop(_currentValue) : null, - child: Text(tr("Confirm").toUpperCase()), + child: Text(tr("Confirm")!.toUpperCase()), ), ], ); diff --git a/lib/ui/routes/conversation_message_stats_route.dart b/lib/ui/routes/conversation_message_stats_route.dart index 1b52480..38328d1 100644 --- a/lib/ui/routes/conversation_message_stats_route.dart +++ b/lib/ui/routes/conversation_message_stats_route.dart @@ -18,9 +18,9 @@ class ConversationMessageStatsRoute extends StatefulWidget { final ConversationMessage message; const ConversationMessageStatsRoute({ - Key key, - @required this.conv, - @required this.message, + Key? key, + required this.conv, + required this.message, }) : assert(conv != null), assert(message != null), super(key: key); @@ -32,7 +32,7 @@ class ConversationMessageStatsRoute extends StatefulWidget { class _ConversationMessageStatsRouteState extends State { - UsersList _users; + late UsersList _users; Future _init() async { _users = await UsersHelper() @@ -43,23 +43,23 @@ class _ConversationMessageStatsRouteState Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text(tr("Message statistics")), + title: Text(tr("Message statistics")!), leading: IconButton( icon: Icon(Icons.close), - onPressed: () => MainController.of(context).popPage(), + onPressed: () => MainController.of(context)!.popPage(), ), ), body: AsyncScreenWidget( onReload: _init, onBuild: _buildScreen, - errorMessage: tr("Failed to load message information!")), + errorMessage: tr("Failed to load message information!")!), ); } List get _firstItems => [ ListTile( leading: Icon(Icons.access_time_rounded), - title: Text(tr("Created on")), + title: Text(tr("Created on")!), subtitle: Text(dateTimeToString(widget.message.date)), ), ListTile( @@ -67,17 +67,17 @@ class _ConversationMessageStatsRouteState user: _users.getUser(widget.message.userID), ), title: Text(_users.getUser(widget.message.userID).fullName), - subtitle: Text(tr("Creator")), + subtitle: Text(tr("Creator")!), ), ]; Widget _buildScreen() => ListView.builder( - itemCount: _firstItems.length + widget.conv.members.length, + itemCount: _firstItems.length + widget.conv.members!.length, itemBuilder: (c, i) { final firstItems = _firstItems; if (i < firstItems.length) return firstItems[i]; - final convMember = widget.conv.members[i - firstItems.length]; + final convMember = widget.conv.members![i - firstItems.length]; if (convMember.userID == widget.message.userID) return Container(); @@ -86,9 +86,9 @@ class _ConversationMessageStatsRouteState user: _users.getUser(convMember.userID), ), title: Text(_users.getUser(convMember.userID).fullName), - subtitle: Text(convMember.lastMessageSeen < widget.message.id - ? tr("Message not seen yet") - : tr("Message seen")), + subtitle: Text(convMember.lastMessageSeen < widget.message.id! + ? tr("Message not seen yet")! + : tr("Message seen")!), ); }, ); diff --git a/lib/ui/routes/conversation_route.dart b/lib/ui/routes/conversation_route.dart index 2e31d00..7dd19bb 100644 --- a/lib/ui/routes/conversation_route.dart +++ b/lib/ui/routes/conversation_route.dart @@ -19,8 +19,8 @@ class ConversationRoute extends StatefulWidget { final int conversationID; const ConversationRoute({ - Key key, - @required this.conversationID, + Key? key, + required this.conversationID, }) : assert(conversationID != null), super(key: key); @@ -30,9 +30,9 @@ class ConversationRoute extends StatefulWidget { class _ConversationRouteState extends SafeState { final ConversationsHelper _conversationsHelper = ConversationsHelper(); - Conversation _conversation; - UsersList _users; - String _conversationName; + Conversation? _conversation; + UsersList? _users; + String? _conversationName; bool _error = false; setError(bool err) => setState(() => _error = err); @@ -50,10 +50,10 @@ class _ConversationRouteState extends SafeState { _conversation = await _conversationsHelper .getSingle(widget.conversationID, force: true); - _users = await UsersHelper().getList(_conversation.membersID); + _users = await UsersHelper().getList(_conversation!.membersID); final conversationName = - ConversationsHelper.getConversationName(_conversation, _users); + ConversationsHelper.getConversationName(_conversation!, _users); if (!this.mounted) return null; @@ -65,7 +65,7 @@ class _ConversationRouteState extends SafeState { } void _openSettings() => - MainController.of(context).openConversationSettingsRoute(_conversation); + MainController.of(context)!.openConversationSettingsRoute(_conversation!); Widget _buildRouteBody() { //Handle errors @@ -76,7 +76,7 @@ class _ConversationRouteState extends SafeState { TextButton( onPressed: _loadConversation, child: Text( - tr("Try again").toUpperCase(), + tr("Try again")!.toUpperCase(), style: TextStyle( color: Colors.white, ), @@ -101,19 +101,19 @@ class _ConversationRouteState extends SafeState { ? (_conversation == null || _users == null ? null : ConversationImageWidget( - conversation: _conversation, users: _users)) + conversation: _conversation!, users: _users!)) : ComunicBackButton(), title: Text( - _conversationName == null ? tr("Loading") : _conversationName, + _conversationName == null ? tr("Loading")! : _conversationName!, ), actions: [ // Start call (if possible) _conversation == null || - _conversation.callCapabilities == CallCapabilities.NONE + _conversation!.callCapabilities == CallCapabilities.NONE ? Container() : IconButton( icon: Icon(Icons.phone), - onPressed: () => MainController.of(context) + onPressed: () => MainController.of(context)! .startCall(widget.conversationID), ), diff --git a/lib/ui/routes/create_account_route.dart b/lib/ui/routes/create_account_route.dart index 0b5e6c0..b02b9f3 100644 --- a/lib/ui/routes/create_account_route.dart +++ b/lib/ui/routes/create_account_route.dart @@ -15,7 +15,7 @@ class CreateAccountRoute extends StatelessWidget { return LoginRouteContainer( child: Scaffold( appBar: AppBar( - title: Text(tr("Create an account")), + title: Text(tr("Create an account")!), ), body: _CreateAccountRouteBody(), ), @@ -38,12 +38,12 @@ class __CreateAccountRouteBodyState extends State<_CreateAccountRouteBody> { await showCupertinoDialog( context: context, builder: (c) => CupertinoAlertDialog( - title: Text(tr("Account created")), + title: Text(tr("Account created")!), content: Text(tr( - "Your account has been successfully created. You can now login to start to use it.")), + "Your account has been successfully created. You can now login to start to use it.")!), actions: [ CupertinoButton( - child: Text(tr("Login")), onPressed: () => Navigator.of(c).pop()) + child: Text(tr("Login")!), onPressed: () => Navigator.of(c).pop()) ], ), ); diff --git a/lib/ui/routes/forez_presence_settings_route.dart b/lib/ui/routes/forez_presence_settings_route.dart index de637aa..123e01a 100644 --- a/lib/ui/routes/forez_presence_settings_route.dart +++ b/lib/ui/routes/forez_presence_settings_route.dart @@ -16,16 +16,16 @@ import 'package:flutter/material.dart'; /// Show presence settings route Future showPresenceSettingsRoute( - BuildContext context, int groupID) async => + BuildContext context, int? groupID) async => await Navigator.push(context, - MaterialPageRoute(builder: (c) => PresenceSettings(groupID: groupID))); + MaterialPageRoute(builder: (c) => PresenceSettings(groupID: groupID!))); class PresenceSettings extends StatefulWidget { final int groupID; const PresenceSettings({ - Key key, - @required this.groupID, + Key? key, + required this.groupID, }) : assert(groupID != null), super(key: key); @@ -34,7 +34,7 @@ class PresenceSettings extends StatefulWidget { } class _PresenceSettingsState extends State { - PresenceSet _currPresences; + late PresenceSet _currPresences; Future _load() async { await ForezPresenceHelper.refreshCache(widget.groupID); @@ -46,12 +46,12 @@ class _PresenceSettingsState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text(tr("Presence settings")), + title: Text(tr("Presence settings")!), ), body: AsyncScreenWidget( onReload: _load, onBuild: _buildScreen, - errorMessage: tr("Failed to load data!"), + errorMessage: tr("Failed to load data!")!, ), ); } @@ -61,7 +61,7 @@ class _PresenceSettingsState extends State { Padding( padding: const EdgeInsets.all(8.0), child: Text( - tr("Please click on the day you will be in the plain, so that everyone gets informed ! ;)"), + tr("Please click on the day you will be in the plain, so that everyone gets informed ! ;)")!, textAlign: TextAlign.center, ), ), @@ -85,7 +85,7 @@ class _PresenceSettingsState extends State { } catch (e, s) { logError(e, s); _currPresences.toggleDate(dt, userID()); - snack(context, tr("Failed to update information!")); + snack(context, tr("Failed to update information!")!); } } } diff --git a/lib/ui/routes/forgot_password_route.dart b/lib/ui/routes/forgot_password_route.dart index db26234..242cc00 100644 --- a/lib/ui/routes/forgot_password_route.dart +++ b/lib/ui/routes/forgot_password_route.dart @@ -18,7 +18,7 @@ class ForgotPasswordRoute extends StatelessWidget { return LoginRouteContainer( child: Scaffold( appBar: AppBar( - title: Text(tr("Password forgotten")), + title: Text(tr("Password forgotten")!), ), body: Padding( padding: const EdgeInsets.all(8.0), @@ -45,7 +45,7 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> { var _loading = false; /// Step 1 - check email address - String _emailAddress; + String? _emailAddress; final _emailController = TextEditingController(); String get _inputEmail => _emailController.text; @@ -54,14 +54,14 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> { _inputEmail.isNotEmpty && validateEmail(_inputEmail); /// Step 2 - Offer options - bool _hasSecurityQuestions; + bool? _hasSecurityQuestions; var _selectedOption = _SelectedOption.NONE; void _setLoading(bool loading) => setState(() => _loading = loading); /// Step 3b - Answer security questions - List _questions; + List? _questions; var _questionsControllers = []; List get _answers => @@ -90,7 +90,7 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> { return Column( mainAxisSize: MainAxisSize.min, children: [ - Text(tr("Please enter your email address to reset your password:")), + Text(tr("Please enter your email address to reset your password:")!), TextField( controller: _emailController, onChanged: (s) => setState(() {}), @@ -120,9 +120,9 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> { _setLoading(true); // Check if email address exists or not - if (!await AccountHelper.existsMailAccount(_inputEmail)) { + if (!await AccountHelper.existsMailAccount(_inputEmail) ) { _setLoading(false); - showSimpleSnack(context, tr("Specified email address was not found!")); + showSimpleSnack(context, tr("Specified email address was not found!")!); return; } @@ -135,7 +135,7 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> { } catch (e, s) { print("Could not check given email! $e\n$s"); showSimpleSnack(context, - tr("An error occurred while checking your recovery options !")); + tr("An error occurred while checking your recovery options !")!); _setLoading(false); } } @@ -145,19 +145,19 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Text(tr("Here are your options to reset your account:")), + Text(tr("Here are your options to reset your account:")!), _Spacer(), OutlinedButton.icon( onPressed: _openSendEmailDialog, icon: Icon(Icons.email), label: Flexible( - child: Text(tr("Send us an email to ask for help")))), - _Spacer(visible: _hasSecurityQuestions), - _hasSecurityQuestions + child: Text(tr("Send us an email to ask for help")!))), + _Spacer(visible: _hasSecurityQuestions!), + _hasSecurityQuestions! ? OutlinedButton.icon( onPressed: _loadSecurityQuestions, icon: Icon(Icons.help_outline), - label: Text(tr("Answer your security questions")), + label: Text(tr("Answer your security questions")!), ) : Container(), ], @@ -169,7 +169,7 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> { context: context, builder: (c) => AlertDialog( title: Text("Contact us"), - content: Text(tr("You can reach us at contact@communiquons.org")), + content: Text(tr("You can reach us at contact@communiquons.org")!), actions: [CancelDialogButton()], )); } @@ -181,11 +181,11 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> { _questions = await AccountHelper.getSecurityQuestions(_emailAddress); _questionsControllers = - List.generate(_questions.length, (i) => TextEditingController()); + List.generate(_questions!.length, (i) => TextEditingController()); _selectedOption = _SelectedOption.SECURITY_QUESTIONS; } catch (e, s) { print("Could not load security questions! $e\n$s"); - showSimpleSnack(context, tr("Could not load your security questions!")); + showSimpleSnack(context, tr("Could not load your security questions!")!); } _setLoading(false); } @@ -196,20 +196,20 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [] - ..add(Text(tr("Please answer now your security questions:"))) + ..add(Text(tr("Please answer now your security questions:")!)) ..add(_Spacer()) - ..addAll(List.generate(_questions.length, _buildSecurityQuestionField)) + ..addAll(List.generate(_questions!.length, _buildSecurityQuestionField)) ..add(_Spacer()) ..add(OutlinedButton( onPressed: _canSubmitAnswers ? _submitSecurityAnswers : null, - child: Text(tr("Submit")), + child: Text(tr("Submit")!), )), ); } Widget _buildSecurityQuestionField(int id) => Column( children: [ - Text(_questions[id]), + Text(_questions![id]), TextField( controller: _questionsControllers[id], onChanged: (s) => setState(() {}), @@ -234,20 +234,20 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> { } catch (e, s) { print("Could not submit security answers! $e\n$s"); showSimpleSnack( - context, tr("Could not validate these security answers!")); + context, tr("Could not validate these security answers!")!); } _setLoading(false); } /// Call this method whenever the user managed to get a password reset token - void _useResetToken(String token) => Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (c) => PasswordResetRoute(token: token))); + void _useResetToken(String? token) => Navigator.of(context).pushReplacement( + MaterialPageRoute(builder: (c) => PasswordResetRoute(token: token!))); } class _Spacer extends StatelessWidget { final bool visible; - const _Spacer({Key key, this.visible = true}) + const _Spacer({Key? key, this.visible = true}) : assert(visible != null), super(key: key); diff --git a/lib/ui/routes/full_screen_image.dart b/lib/ui/routes/full_screen_image.dart index 5db7b52..ebb0291 100644 --- a/lib/ui/routes/full_screen_image.dart +++ b/lib/ui/routes/full_screen_image.dart @@ -22,7 +22,7 @@ class _FullScreenImageRouteState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text(tr("Image")), + title: Text(tr("Image")!), actions: [ IconButton( icon: Icon(Icons.launch), onPressed: () => launch(widget.url)) diff --git a/lib/ui/routes/image_editor_route.dart b/lib/ui/routes/image_editor_route.dart index 34abf2b..f1eaab5 100644 --- a/lib/ui/routes/image_editor_route.dart +++ b/lib/ui/routes/image_editor_route.dart @@ -18,18 +18,16 @@ import '../../utils/files_utils.dart'; /// /// Return original image in case of error / if the user did not crop the image Future showImageCropper(BuildContext context, BytesFile source, - {CropAspectRatio aspectRatio}) async { - assert(context != null); - assert(source != null); + {CropAspectRatio? aspectRatio}) async { - File file; - File cropped; + File? file; + File? cropped; try { file = await generateTemporaryFile(); - await file.writeAsBytes(source.bytes); + await file.writeAsBytes(source.bytes!); - File cropped = await ImageCropper().cropImage( + File? cropped = await ImageCropper().cropImage( sourcePath: file.absolute.path, compressFormat: ImageCompressFormat.png, aspectRatio: aspectRatio, @@ -40,12 +38,12 @@ Future showImageCropper(BuildContext context, BytesFile source, ), ); - if (cropped == null) return null; + if (cropped == null) return source; return BytesFile("cropped.png", await cropped.readAsBytes()); } catch (e, s) { logError(e, s); - snack(context, tr("Failed to execute image cropper!")); + snack(context, tr("Failed to execute image cropper!")!); return source; } finally { if (file != null && await file.exists()) file.delete(); diff --git a/lib/ui/routes/login_route.dart b/lib/ui/routes/login_route.dart index b492e08..341fae7 100644 --- a/lib/ui/routes/login_route.dart +++ b/lib/ui/routes/login_route.dart @@ -25,7 +25,7 @@ class _LoginRouteState extends State { return LoginRouteContainer( child: Scaffold( appBar: AppBar( - title: Text(tr("Login to Comunic")), + title: Text(tr("Login to Comunic")!), ), body: Padding( padding: const EdgeInsets.all(8.0), @@ -44,7 +44,7 @@ class _LoginRouteState extends State { ), ListTile( leading: Icon(Icons.help), - title: Text(tr("Password forgotten")), + title: Text(tr("Password forgotten")!), onTap: _openResetPasswordPage, ) ], diff --git a/lib/ui/routes/main_route/main_route.dart b/lib/ui/routes/main_route/main_route.dart index b8b241c..03348c7 100644 --- a/lib/ui/routes/main_route/main_route.dart +++ b/lib/ui/routes/main_route/main_route.dart @@ -50,7 +50,7 @@ abstract class MainController extends State { int get numberOfPages => _pagesStack.length; /// Get current instance of Home controller - static MainController of(BuildContext context) { + static MainController? of(BuildContext context) { assert(context != null); // A future implementation might need context again return mainControllerKey.currentState; } @@ -75,7 +75,7 @@ abstract class MainController extends State { /// Pop until main route is reached void popUntilMainRoute() => Navigator.of(context).popUntil((settings) => - ModalRoute.of(context).isCurrent || !ModalRoute.of(context).isActive); + ModalRoute.of(context)!.isCurrent || !ModalRoute.of(context)!.isActive); /// Go to the previous page (use for [WillPop] widget) @protected @@ -109,13 +109,13 @@ abstract class MainController extends State { pushPage(PageInfo(child: UserAccessDeniedScreen(userID: userID))); /// Open current user page - void openCurrentUserPage() => this.openUserPage(userID()); + void openCurrentUserPage() => this.openUserPage(userID()!); /// Open a specific group page specified by its [groupID] /// /// [conversationID] is an optional parameter specifying a conversation /// that should be opened instead of posts thread - void openGroup(int groupID, {int conversationID}) => pushPage(PageInfo( + void openGroup(int groupID, {int? conversationID}) => pushPage(PageInfo( type: PageType.GROUP_PAGE, child: GroupPageScreen( groupID: groupID, @@ -137,10 +137,10 @@ abstract class MainController extends State { void openGroupsListPage() => pushPage(PageInfo(child: GroupsListScreen())); /// Display the list of friends of a user - void openUserFriendsList(int id) { + void openUserFriendsList(int? id) { if (id != userID()) pushPage(PageInfo( - child: OtherUserFriendsListScreen(userID: id), + child: OtherUserFriendsListScreen(userID: id!), canShowAsDialog: true, )); else @@ -156,9 +156,9 @@ abstract class MainController extends State { /// Open a conversation in its context (in group page for group conversations) void openConversation(Conversation conv, {fullScreen: false}) { if (conv.isGroupConversation) - openGroup(conv.groupID, conversationID: conv.id); + openGroup(conv.groupID!, conversationID: conv.id); else - openConversationById(conv.id, fullScreen: fullScreen); + openConversationById(conv.id!, fullScreen: fullScreen); } /// Open a conversation @@ -173,7 +173,7 @@ abstract class MainController extends State { /// Open conversation settings route void openConversationSettingsRoute(Conversation conv) => pushPage(PageInfo( child: UpdateConversationRoute( - conversationID: conv.id, + conversationID: conv.id!, ), canShowAsDialog: true, hideNavBar: true, @@ -215,7 +215,7 @@ abstract class MainController extends State { /// /// If the current route is not the main route, we pop one page void popPage() { - if (!ModalRoute.of(context).isCurrent) + if (!ModalRoute.of(context)!.isCurrent) Navigator.of(context).pop(); else doPopPage(); diff --git a/lib/ui/routes/main_route/page_info.dart b/lib/ui/routes/main_route/page_info.dart index e142add..f4e3d96 100644 --- a/lib/ui/routes/main_route/page_info.dart +++ b/lib/ui/routes/main_route/page_info.dart @@ -18,7 +18,7 @@ enum PageType { class PageInfo { final PageType type; final Widget child; - final int id; + final int? id; final bool hideNavBar; final bool canShowAsDialog; @@ -27,7 +27,7 @@ class PageInfo { PageInfo({ this.type = PageType.OTHER_PAGE, - @required this.child, + required this.child, this.id, this.hideNavBar = false, this.canShowAsDialog = false, diff --git a/lib/ui/routes/main_route/smartphone_route.dart b/lib/ui/routes/main_route/smartphone_route.dart index 41b05e5..e40c0c3 100644 --- a/lib/ui/routes/main_route/smartphone_route.dart +++ b/lib/ui/routes/main_route/smartphone_route.dart @@ -10,7 +10,7 @@ import 'package:flutter/material.dart'; /// @author Pierre HUBERT class SmartphoneMainRoute extends StatefulWidget implements MainRoute { - const SmartphoneMainRoute({Key key}) : super(key: key); + const SmartphoneMainRoute({Key? key}) : super(key: key); @override State createState() => _MainRouteState(); diff --git a/lib/ui/routes/main_route/tablet_route.dart b/lib/ui/routes/main_route/tablet_route.dart index c8c7504..69ca1c2 100644 --- a/lib/ui/routes/main_route/tablet_route.dart +++ b/lib/ui/routes/main_route/tablet_route.dart @@ -19,7 +19,7 @@ import 'package:flutter/material.dart'; const _SideBarSize = 300.0; class TabletRoute extends StatefulWidget implements MainRoute { - const TabletRoute({Key key}) : super(key: key); + const TabletRoute({Key? key}) : super(key: key); @override _TabletRouteState createState() => _TabletRouteState(); @@ -37,7 +37,7 @@ class _TabletRouteState extends MainController { return WillPopScope( onWillPop: willPop, child: Scaffold( - appBar: _buildAppBar(), + appBar: _buildAppBar() as PreferredSizeWidget?, body: _buildBody(), ), ); @@ -105,14 +105,14 @@ class _TabletRouteState extends MainController { } @override - void openConversationById(int convID, {fullScreen = false}) { + void openConversationById(int? convID, {fullScreen = false}) { if (!fullScreen) { popUntilMainRoute(); - _conversationsKey.currentState.openConversations(convID); + _conversationsKey.currentState!.openConversations(convID); } else - super.openConversationById(convID, fullScreen: fullScreen); + super.openConversationById(convID!, fullScreen: fullScreen); } @override - void startCall(int convID) => _callsKey.currentState.openCall(convID); + void startCall(int convID) => _callsKey.currentState!.openCall(convID); } diff --git a/lib/ui/routes/password_reset_route.dart b/lib/ui/routes/password_reset_route.dart index 8c55a96..3f2f2a8 100644 --- a/lib/ui/routes/password_reset_route.dart +++ b/lib/ui/routes/password_reset_route.dart @@ -17,8 +17,8 @@ class PasswordResetRoute extends StatelessWidget { final String token; const PasswordResetRoute({ - Key key, - @required this.token, + Key? key, + required this.token, }) : assert(token != null), super(key: key); @@ -27,7 +27,7 @@ class PasswordResetRoute extends StatelessWidget { return LoginRouteContainer( child: Scaffold( appBar: AppBar( - title: Text(tr("Change your password")), + title: Text(tr("Change your password")!), ), body: _PasswordResetBody(token: token), ), @@ -38,7 +38,7 @@ class PasswordResetRoute extends StatelessWidget { class _PasswordResetBody extends StatefulWidget { final String token; - const _PasswordResetBody({Key key, @required this.token}) + const _PasswordResetBody({Key? key, required this.token}) : assert(token != null), super(key: key); @@ -52,7 +52,7 @@ class __PasswordResetBodyState extends SafeState<_PasswordResetBody> { final _key = GlobalKey(); var _status = _Status.BEFORE_CHANGE; - ResCheckPasswordToken _tokenInfo; + late ResCheckPasswordToken _tokenInfo; void _setStatus(_Status s) => setState(() => _status = s); @@ -68,7 +68,7 @@ class __PasswordResetBodyState extends SafeState<_PasswordResetBody> { onReload: _validateToken, // The first time, we validate the token onBuild: _buildBody, errorMessage: tr( - "Could not validate your password reset token! Maybe it has expired now..."), + "Could not validate your password reset token! Maybe it has expired now...")!, ); } @@ -79,10 +79,10 @@ class __PasswordResetBodyState extends SafeState<_PasswordResetBody> { child: Column( mainAxisSize: MainAxisSize.min, children: [ - Text(tr("You can choose a new password.")), + Text(tr("You can choose a new password.")!), OutlinedButton( onPressed: _changePassword, - child: Text(tr("Choose a new password")), + child: Text(tr("Choose a new password")!), ) ], )); @@ -97,12 +97,12 @@ class __PasswordResetBodyState extends SafeState<_PasswordResetBody> { mainAxisSize: MainAxisSize.min, children: [ Text( - tr("Congratulations! Your password has now been successfully changed!"), + tr("Congratulations! Your password has now been successfully changed!")!, textAlign: TextAlign.center, ), OutlinedButton( onPressed: _quitScreen, - child: Text(tr("Login")), + child: Text(tr("Login")!), ) ], )); @@ -130,10 +130,10 @@ class __PasswordResetBodyState extends SafeState<_PasswordResetBody> { _setStatus(_Status.AFTER_CHANGE); } catch (e, s) { print("Could not change user password! $e\n$s"); - showSimpleSnack(context, tr("Could not change your password!")); + showSimpleSnack(context, tr("Could not change your password!")!); // We start everything again - _key.currentState.refresh(); + _key.currentState!.refresh(); } } diff --git a/lib/ui/routes/push_notifications_route.dart b/lib/ui/routes/push_notifications_route.dart index 9c1d7cd..d93c423 100644 --- a/lib/ui/routes/push_notifications_route.dart +++ b/lib/ui/routes/push_notifications_route.dart @@ -52,9 +52,9 @@ class _PushNotificationsConfigurationRouteState Spacer(), OutlinedButton( onPressed: _key?.currentState?.canSubmit ?? false - ? _key.currentState.submit + ? _key.currentState!.submit : null, - child: Text(tr("Configure").toUpperCase()), + child: Text(tr("Configure")!.toUpperCase()), style: OutlinedButton.styleFrom(primary: Colors.white)), Spacer(), ], @@ -69,9 +69,9 @@ class PushNotificationsConfigurationWidget extends StatefulWidget { final Function() onChanged; const PushNotificationsConfigurationWidget({ - Key key, - @required this.onConfigured, - @required this.onChanged, + Key? key, + required this.onConfigured, + required this.onChanged, }) : super(key: key); @override @@ -81,7 +81,7 @@ class PushNotificationsConfigurationWidget extends StatefulWidget { class PushNotificationsConfigurationWidgetState extends State { - PushNotificationsStatus currStatus; + PushNotificationsStatus? currStatus; bool get canSubmit => (currStatus ?? PushNotificationsStatus.UNDEFINED) != @@ -92,7 +92,7 @@ class PushNotificationsConfigurationWidgetState currStatus = await PushNotificationsHelper.getLocalStatus(); if (currStatus == PushNotificationsStatus.UNDEFINED && - srvConfig.notificationsPolicy.hasFirebase) + srvConfig!.notificationsPolicy.hasFirebase) currStatus = PushNotificationsStatus.FIREBASE; widget.onChanged(); @@ -103,7 +103,7 @@ class PushNotificationsConfigurationWidgetState return AsyncScreenWidget( onReload: _refresh, onBuild: _buildForm, - errorMessage: tr("Failed to load push notifications settings!"), + errorMessage: tr("Failed to load push notifications settings!")!, ); } @@ -114,16 +114,16 @@ class PushNotificationsConfigurationWidgetState Text( tr("%app% can send push notifications to your device.", args: { "app": config().appName, - }), + })!, textAlign: TextAlign.center, ), SizedBox(height: 10), _NotificationOption( - title: tr("Use Google services (recommended)"), + title: tr("Use Google services (recommended)")!, description: tr("Save your battery life."), option: PushNotificationsStatus.FIREBASE, - current: currStatus, - available: srvConfig.notificationsPolicy.hasFirebase, + current: currStatus!, + available: srvConfig!.notificationsPolicy.hasFirebase, onChanged: (s) { setState(() => currStatus = s); if (widget.onChanged != null) widget.onChanged(); @@ -131,13 +131,13 @@ class PushNotificationsConfigurationWidgetState ), SizedBox(height: 5), _NotificationOption( - title: tr("Use independent notifications service"), + title: tr("Use independent notifications service")!, description: tr( "Protect more your privacy, but drains battery and is less reliable."), option: PushNotificationsStatus.INDEPENDENT, - current: currStatus, + current: currStatus!, available: - srvConfig.notificationsPolicy.hasIndependent && isAndroid, + srvConfig!.notificationsPolicy.hasIndependent && isAndroid, onChanged: (s) { setState(() => currStatus = s); if (widget.onChanged != null) widget.onChanged(); @@ -145,9 +145,9 @@ class PushNotificationsConfigurationWidgetState ), SizedBox(height: 5), _NotificationOption( - title: tr("Do not send notification"), + title: tr("Do not send notification")!, option: PushNotificationsStatus.DISABLED, - current: currStatus, + current: currStatus!, available: true, onChanged: (s) { setState(() => currStatus = s); @@ -181,20 +181,20 @@ class PushNotificationsConfigurationWidgetState class _NotificationOption extends StatelessWidget { final String title; - final String description; + final String? description; final PushNotificationsStatus option; final PushNotificationsStatus current; final bool available; - final Function(PushNotificationsStatus) onChanged; + final Function(PushNotificationsStatus?) onChanged; const _NotificationOption({ - Key key, - @required this.title, + Key? key, + required this.title, this.description, - @required this.option, - @required this.current, - @required this.available, - @required this.onChanged, + required this.option, + required this.current, + required this.available, + required this.onChanged, }) : assert(title != null), assert(option != null), assert(current != null), @@ -219,7 +219,7 @@ class _NotificationOption extends StatelessWidget { title: Text(title, style: TextStyle(color: Colors.white)), subtitle: description == null ? null - : Text(description, style: TextStyle(color: Colors.white)), + : Text(description!, style: TextStyle(color: Colors.white)), contentPadding: EdgeInsets.all(0), onTap: () => onChanged(option), ), diff --git a/lib/ui/routes/settings/about_settings.dart b/lib/ui/routes/settings/about_settings.dart index 1cf5f99..5aa797d 100644 --- a/lib/ui/routes/settings/about_settings.dart +++ b/lib/ui/routes/settings/about_settings.dart @@ -24,16 +24,16 @@ class AboutApplicationSettings extends StatelessWidget { tiles: [ SettingsTile( title: tr("Privacy policy"), - onPressed: (c) => launch(srvConfig.privacyPolicyURL), + onPressed: (c) => launch(srvConfig!.privacyPolicyURL), ), SettingsTile( title: tr("Terms of Use"), - onPressed: (c) => launch(srvConfig.termsURL), + onPressed: (c) => launch(srvConfig!.termsURL), ), SettingsTile( title: tr("Contact us"), - subtitle: srvConfig.contactEmail, - trailing: CopyIcon(srvConfig.contactEmail), + subtitle: srvConfig!.contactEmail, + trailing: CopyIcon(srvConfig!.contactEmail), ), SettingsTile( title: tr("About this application"), diff --git a/lib/ui/routes/settings/account_image_settings.dart b/lib/ui/routes/settings/account_image_settings.dart index 0e19dbf..8ec2713 100644 --- a/lib/ui/routes/settings/account_image_settings.dart +++ b/lib/ui/routes/settings/account_image_settings.dart @@ -30,7 +30,7 @@ class AccountImageSettingsScreen extends StatefulWidget { class _AccountImageSettingsScreenState extends State { - AccountImageSettings _settings; + late AccountImageSettings _settings; final _key = GlobalKey(); @@ -49,7 +49,7 @@ class _AccountImageSettingsScreenState onReload: () async => _settings = await SettingsHelper.getAccountImageSettings(), onBuild: () => _buildLayout(), - errorMessage: tr("Could not get account image settings!"), + errorMessage: tr("Could not get account image settings!")!, ); } @@ -96,19 +96,19 @@ class _AccountImageSettingsScreenState [ MultiChoiceEntry( id: AccountImageVisibilityLevels.EVERYONE, - title: tr("Everyone"), + title: tr("Everyone")!, subtitle: tr( "Your account image is visible by everyone, including users external to Comunic."), ), MultiChoiceEntry( id: AccountImageVisibilityLevels.COMUNIC_USERS, - title: tr("Connected users"), + title: tr("Connected users")!, subtitle: tr( "Your account image is visible only to connected Comunic users."), ), MultiChoiceEntry( id: AccountImageVisibilityLevels.FRIENDS_ONLY, - title: tr("My friends"), + title: tr("My friends")!, subtitle: tr("Your account image is visible only by your friends."), ), ]; @@ -139,14 +139,14 @@ class _AccountImageSettingsScreenState // Change account image visibility MultiChoicesSettingsTile( - title: tr("Account image visibility"), + title: tr("Account image visibility")!, choices: _visibilityLevels, currentValue: _settings.visibility, - onChanged: (newLevel) async { + onChanged: (dynamic newLevel) async { if (!await SettingsHelper.setAccountImageVisibilityLevel(newLevel)) showSimpleSnack(context, - tr("Could not update account image visibility level!")); - _key.currentState.refresh(); + tr("Could not update account image visibility level!")!); + _key.currentState!.refresh(); }), // Delete account image @@ -160,7 +160,7 @@ class _AccountImageSettingsScreenState /// Upload a new account image void _uploadAccountImage() async { await uploadNewAccountImage(context); - _key.currentState.refresh(); + _key.currentState!.refresh(); } /// Generate a random account image @@ -170,11 +170,11 @@ class _AccountImageSettingsScreenState if (!await SettingsHelper.uploadAccountImageFromMemory(bytes)) { showSimpleSnack( - context, tr("Could not upload your generated account image!")); + context, tr("Could not upload your generated account image!")!); return; } - _key.currentState.refresh(); + _key.currentState!.refresh(); } /// Delete user account image @@ -185,11 +185,11 @@ class _AccountImageSettingsScreenState return; if (!await SettingsHelper.deleteAccountImage()) { - showSimpleSnack(context, tr("Could not delete user account image!")); + showSimpleSnack(context, tr("Could not delete user account image!")!); return; } - _key.currentState.refresh(); + _key.currentState!.refresh(); } } @@ -203,6 +203,6 @@ Future uploadNewAccountImage(BuildContext context) async { await SettingsHelper.uploadAccountImage(image); } catch (e, s) { logError(e, s); - snack(context, tr("Failed to upload new account image!")); + snack(context, tr("Failed to upload new account image!")!); } } diff --git a/lib/ui/routes/settings/account_privacy_settings.dart b/lib/ui/routes/settings/account_privacy_settings.dart index e8181a2..6ee4145 100644 --- a/lib/ui/routes/settings/account_privacy_settings.dart +++ b/lib/ui/routes/settings/account_privacy_settings.dart @@ -25,9 +25,9 @@ class AccountPrivacySettings extends StatefulWidget { class _AccountPrivacySettingsState extends State { final _key = GlobalKey(); - ServerConfig _serverConfig; - DataConservationPolicySettings _userSettings; - String _cachedPassword; + ServerConfig? _serverConfig; + late DataConservationPolicySettings _userSettings; + String? _cachedPassword; Future _loadSettings() async { _serverConfig = ServerConfigurationHelper.config; @@ -59,68 +59,68 @@ class _AccountPrivacySettingsState extends State { ) ]) ]), - errorMessage: tr("Failed to load privacy settings!"), + errorMessage: tr("Failed to load privacy settings!")!, ); } List get _dataConservationPolicyTiles => [ DataConservationPolicyTile( value: _userSettings.notificationLifetime, - title: tr("Automatically delete unread notifications after"), + title: tr("Automatically delete unread notifications after")!, onChange: (val) { _userSettings.notificationLifetime = val; _updateDataConservationPolicy(); }, minValue: - _serverConfig.dataConservationPolicy.minNotificationLifetime, + _serverConfig!.dataConservationPolicy.minNotificationLifetime, ), DataConservationPolicyTile( value: _userSettings.commentsLifetime, - title: tr("Automatically delete your comments after"), + title: tr("Automatically delete your comments after")!, onChange: (val) { _userSettings.commentsLifetime = val; _updateDataConservationPolicy(); }, - minValue: _serverConfig.dataConservationPolicy.minCommentsLifetime, + minValue: _serverConfig!.dataConservationPolicy.minCommentsLifetime, ), DataConservationPolicyTile( value: _userSettings.postsLifetime, - title: tr("Automatically delete your posts after"), + title: tr("Automatically delete your posts after")!, onChange: (val) { _userSettings.postsLifetime = val; _updateDataConservationPolicy(); }, - minValue: _serverConfig.dataConservationPolicy.minPostsLifetime, + minValue: _serverConfig!.dataConservationPolicy.minPostsLifetime, ), DataConservationPolicyTile( value: _userSettings.conversationMessagesLifetime, - title: tr("Automatically delete your conversation messages after"), + title: tr("Automatically delete your conversation messages after")!, onChange: (val) { _userSettings.conversationMessagesLifetime = val; _updateDataConservationPolicy(); }, - minValue: _serverConfig + minValue: _serverConfig! .dataConservationPolicy.minConversationMessagesLifetime, ), DataConservationPolicyTile( value: _userSettings.likesLifetime, - title: tr("Automatically delete your likes after"), + title: tr("Automatically delete your likes after")!, onChange: (val) { _userSettings.likesLifetime = val; _updateDataConservationPolicy(); }, - minValue: _serverConfig.dataConservationPolicy.minLikesLifetime, + minValue: _serverConfig!.dataConservationPolicy.minLikesLifetime, ), DataConservationPolicyTile( value: _userSettings.inactiveAccountLifeTime, title: tr( - "Automatically delete your account if you have been inactive for"), + "Automatically delete your account if you have been inactive for")!, onChange: (val) { _userSettings.inactiveAccountLifeTime = val; _updateDataConservationPolicy(); }, minValue: - _serverConfig.dataConservationPolicy.minInactiveAccountLifetime, + _serverConfig!.dataConservationPolicy.minInactiveAccountLifetime, ), ]; @@ -132,11 +132,11 @@ class _AccountPrivacySettingsState extends State { await SettingsHelper.setDataConservationPolicy( _cachedPassword, _userSettings); - _key.currentState.refresh(); + _key.currentState!.refresh(); } catch (e, s) { print("Could not update data conservation policy! $e\n$s"); showSimpleSnack( - context, tr("Failed to update data conservation policy!")); + context, tr("Failed to update data conservation policy!")!); } } @@ -164,22 +164,22 @@ class _AccountPrivacySettingsState extends State { await AccountHelper.deleteAccount(password); } catch (e, stack) { print("Could not delete user account! $e\n$stack"); - showSimpleSnack(context, tr("Could not delete your account!")); + showSimpleSnack(context, tr("Could not delete your account!")!); } } } class DataConservationPolicyTile extends SettingsTile { - final int value; + final int? value; final String title; final Function(int) onChange; final int minValue; DataConservationPolicyTile({ - @required this.value, - @required this.title, - @required this.onChange, - @required this.minValue, + required this.value, + required this.title, + required this.onChange, + required this.minValue, }) : assert(title != null), assert(onChange != null), assert(minValue != null); @@ -203,59 +203,59 @@ class DataConservationPolicyTile extends SettingsTile { int get _roundValue { if (this.value == null) return 0; - return _choices.firstWhere((element) => element.id >= this.value).id; + return _choices.firstWhere((element) => element.id >= this.value!).id; } List> get _choices => [ - MultiChoiceEntry(id: 0, title: tr("Never"), hidden: false), + MultiChoiceEntry(id: 0, title: tr("Never")!, hidden: false), MultiChoiceEntry( id: _day * 7, - title: tr("7 days"), + title: tr("7 days")!, hidden: _day * 7 < minValue, ), MultiChoiceEntry( id: _day * 15, - title: tr("15 days"), + title: tr("15 days")!, hidden: _day * 15 < minValue, ), MultiChoiceEntry( id: _month, - title: tr("1 month"), + title: tr("1 month")!, hidden: _month < minValue, ), MultiChoiceEntry( id: _month * 3, - title: tr("3 months"), + title: tr("3 months")!, hidden: _month * 3 < minValue, ), MultiChoiceEntry( id: _month * 6, - title: tr("6 months"), + title: tr("6 months")!, hidden: _month * 6 < minValue, ), MultiChoiceEntry( id: _year, - title: tr("1 year"), + title: tr("1 year")!, hidden: _year < minValue, ), MultiChoiceEntry( id: _year * 2, - title: tr("2 years"), + title: tr("2 years")!, hidden: _year * 5 < minValue, ), MultiChoiceEntry( id: _year * 5, - title: tr("5 years"), + title: tr("5 years")!, hidden: _year * 5 < minValue, ), MultiChoiceEntry( id: _year * 10, - title: tr("10 years"), + title: tr("10 years")!, hidden: _year * 10 < minValue, ), MultiChoiceEntry( id: _year * 50, - title: tr("50 years"), + title: tr("50 years")!, hidden: _year * 50 < minValue, ), ]; @@ -265,18 +265,18 @@ class _LastChanceDeleteAccountDialog extends StatelessWidget { @override Widget build(BuildContext context) { return CupertinoAlertDialog( - title: Text(tr("Delete your account")), + title: Text(tr("Delete your account")!), content: Text(tr( - "Let us ask you one last time. Do you really want to delete your account? If you decide to do so, your data will be permanently removed from our servers, so we will not be able to recover your account. If you decide to proceed, the deletion process will start immediatly and you will automatically get disconnected from your account.")), + "Let us ask you one last time. Do you really want to delete your account? If you decide to do so, your data will be permanently removed from our servers, so we will not be able to recover your account. If you decide to proceed, the deletion process will start immediatly and you will automatically get disconnected from your account.")!), actions: [ CupertinoDialogAction( isDefaultAction: true, - child: Text(tr("Cancel")), + child: Text(tr("Cancel")!), onPressed: () => Navigator.of(context).pop(false), ), CupertinoDialogAction( isDestructiveAction: true, - child: Text(tr("Confirm")), + child: Text(tr("Confirm")!), onPressed: () => Navigator.of(context).pop(true), ), ], diff --git a/lib/ui/routes/settings/account_security_settings.dart b/lib/ui/routes/settings/account_security_settings.dart index db249c6..22ee0e9 100644 --- a/lib/ui/routes/settings/account_security_settings.dart +++ b/lib/ui/routes/settings/account_security_settings.dart @@ -86,10 +86,10 @@ class _AccountSecuritySettingsScreenState await SettingsHelper.changePassword(currPassword, newPassword); showSimpleSnack( - context, tr("Your password has been successfully changed!")); + context, tr("Your password has been successfully changed!")!); } catch (e, stack) { print("Could not update current user password! $e\n$stack"); - showSimpleSnack(context, tr("Could not update password!")); + showSimpleSnack(context, tr("Could not update password!")!); } } @@ -111,10 +111,10 @@ class _AccountSecuritySettingsScreenState await SettingsHelper.setSecuritySettings(password, newSettings); showSimpleSnack(context, - tr("You security questions have been successfully updated!")); + tr("You security questions have been successfully updated!")!); } catch (e, stack) { print("Could not update security questions!$e\n$stack"); - showSimpleSnack(context, tr("Could not update security questions!")); + showSimpleSnack(context, tr("Could not update security questions!")!); } } @@ -131,7 +131,7 @@ class _AccountSecuritySettingsScreenState } catch (e, stack) { print("Could not disconnect user on all devices! $e\n$stack"); showSimpleSnack( - context, tr("Could not disconnect you from all your devices!")); + context, tr("Could not disconnect you from all your devices!")!); } } } @@ -139,7 +139,7 @@ class _AccountSecuritySettingsScreenState class _SecurityQuestionsDialog extends StatefulWidget { final SecuritySettings settings; - const _SecurityQuestionsDialog({Key key, @required this.settings}) + const _SecurityQuestionsDialog({Key? key, required this.settings}) : assert(settings != null), super(key: key); @@ -149,10 +149,10 @@ class _SecurityQuestionsDialog extends StatefulWidget { } class __SecurityQuestionsDialogState extends State<_SecurityQuestionsDialog> { - TextEditingController _controllerQuestion1; - TextEditingController _controllerAnswer1; - TextEditingController _controllerQuestion2; - TextEditingController _controllerAnswer2; + late TextEditingController _controllerQuestion1; + late TextEditingController _controllerAnswer1; + late TextEditingController _controllerQuestion2; + late TextEditingController _controllerAnswer2; SecuritySettings get _newSettings => SecuritySettings( securityQuestion1: _controllerQuestion1.text, @@ -177,16 +177,16 @@ class __SecurityQuestionsDialogState extends State<_SecurityQuestionsDialog> { @override Widget build(BuildContext context) { return AlertDialog( - title: Text(tr("Update security questions")), + title: Text(tr("Update security questions")!), content: AutoSizeDialogContentWidget(child: _buildContent()), actions: [ MaterialButton( onPressed: () => Navigator.of(context).pop(), - child: Text(tr("Cancel").toUpperCase()), + child: Text(tr("Cancel")!.toUpperCase()), ), MaterialButton( onPressed: () => Navigator.of(context).pop(_newSettings), - child: Text(tr("Update").toUpperCase()), + child: Text(tr("Update")!.toUpperCase()), ) ], ); @@ -196,7 +196,7 @@ class __SecurityQuestionsDialogState extends State<_SecurityQuestionsDialog> { return Column( children: [ Text(tr( - "Note: Your two questions and answers MUST be completed in order to be able to recover your account using your security questions!")), + "Note: Your two questions and answers MUST be completed in order to be able to recover your account using your security questions!")!), _buildTextField( controller: _controllerQuestion1, label: tr("Question 1")), _buildTextField(controller: _controllerAnswer1, label: tr("Answer 1")), @@ -208,8 +208,8 @@ class __SecurityQuestionsDialogState extends State<_SecurityQuestionsDialog> { } Widget _buildTextField({ - @required TextEditingController controller, - @required String label, + required TextEditingController controller, + required String? label, }) { return TextField( controller: controller, diff --git a/lib/ui/routes/settings/account_settings_route.dart b/lib/ui/routes/settings/account_settings_route.dart index c5edc90..5011775 100644 --- a/lib/ui/routes/settings/account_settings_route.dart +++ b/lib/ui/routes/settings/account_settings_route.dart @@ -27,10 +27,10 @@ class _SettingsSection { final Widget Function() onBuild; const _SettingsSection({ - @required this.title, - @required this.subtitle, - @required this.icon, - @required this.onBuild, + required this.title, + required this.subtitle, + required this.icon, + required this.onBuild, }) : assert(title != null), assert(subtitle != null), assert(icon != null), @@ -42,14 +42,14 @@ class AccountSettingsRoute extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text(tr("Settings")), + title: Text(tr("Settings")!), actions: [ PopupMenuButton<_MainMenuActions>( onSelected: (v) => _doPopupMenuAction(context, v), itemBuilder: (c) => [ PopupMenuItem( value: _MainMenuActions.SHOW_TOUR, - child: Text(tr("See the tour again")), + child: Text(tr("See the tour again")!), ), ]), ], @@ -74,7 +74,7 @@ class _AccountSettingsBody extends StatefulWidget { } class __AccountSettingsBodyState extends State<_AccountSettingsBody> { - _SettingsSection _currentSection; + late _SettingsSection _currentSection; @override void initState() { @@ -87,64 +87,64 @@ class __AccountSettingsBodyState extends State<_AccountSettingsBody> { /// The list of settings sections List<_SettingsSection> get _sections => [ _SettingsSection( - title: tr("General settings"), - subtitle: tr("Configure the main settings of your account"), + title: tr("General settings")!, + subtitle: tr("Configure the main settings of your account")!, icon: Icons.settings, onBuild: () => GeneralAccountSettingsScreen(), ), // Emoticons _SettingsSection( - title: tr("Custom emojis"), - subtitle: tr("Set your own emoticon shorcuts"), + title: tr("Custom emojis")!, + subtitle: tr("Set your own emoticon shorcuts")!, icon: Icons.insert_emoticon, onBuild: () => CustomEmojisAccountSettings(), ), // Account image _SettingsSection( - title: tr("Account image"), - subtitle: tr("Customize your account image"), + title: tr("Account image")!, + subtitle: tr("Customize your account image")!, icon: Icons.account_circle, onBuild: () => AccountImageSettingsScreen(), ), // Notifications settings _SettingsSection( - title: tr("Notifications"), - subtitle: tr("Choose the notifications you receive on your phone"), + title: tr("Notifications")!, + subtitle: tr("Choose the notifications you receive on your phone")!, icon: Icons.notifications, onBuild: () => NotificationsSettingsScreen(), ), // Security settings _SettingsSection( - title: tr("Security"), - subtitle: tr("Manage security options of your account"), + title: tr("Security")!, + subtitle: tr("Manage security options of your account")!, icon: Icons.lock, onBuild: () => AccountSecuritySettingsScreen(), ), // Privacy settings _SettingsSection( - title: tr("Privacy"), - subtitle: tr("Here you can make actions to protect your privacy"), + title: tr("Privacy")!, + subtitle: tr("Here you can make actions to protect your privacy")!, icon: Icons.security, onBuild: () => AccountPrivacySettings(), ), // Application settings _SettingsSection( - title: tr("Application settings"), - subtitle: tr("Manage local application settings"), + title: tr("Application settings")!, + subtitle: tr("Manage local application settings")!, icon: Icons.smartphone, onBuild: () => ApplicationSettings(), ), // About settings _SettingsSection( - title: tr("About this application"), - subtitle: tr("Learn more about us"), + title: tr("About this application")!, + subtitle: tr("Learn more about us")!, icon: Icons.info, onBuild: () => AboutApplicationSettings(), ), diff --git a/lib/ui/routes/settings/application_settings.dart b/lib/ui/routes/settings/application_settings.dart index 07d86ea..150a567 100644 --- a/lib/ui/routes/settings/application_settings.dart +++ b/lib/ui/routes/settings/application_settings.dart @@ -17,7 +17,7 @@ class ApplicationSettings extends StatefulWidget { } class _ApplicationSettingsState extends State { - PreferencesHelper _preferencesHelper; + PreferencesHelper? _preferencesHelper; Future _refresh() async { _preferencesHelper = await PreferencesHelper.getInstance(); @@ -27,7 +27,7 @@ class _ApplicationSettingsState extends State { Widget build(BuildContext context) => AsyncScreenWidget( onReload: _refresh, onBuild: _buildSections, - errorMessage: tr("Could not load settings!")); + errorMessage: tr("Could not load settings!")!); Widget _buildSections() { return SettingsList( @@ -89,17 +89,17 @@ class _ApplicationSettingsState extends State { class _PreferencesSettingsTile extends SettingsTile { final PreferencesKeyList preferencesKey; - final String title; - final String subtitle; + final String? title; + final String? subtitle; final Function onChange; - final PreferencesHelper helper; + final PreferencesHelper? helper; _PreferencesSettingsTile({ - @required this.preferencesKey, - @required this.title, - @required this.subtitle, - @required this.onChange, - @required this.helper, + required this.preferencesKey, + required this.title, + required this.subtitle, + required this.onChange, + required this.helper, }); @override @@ -108,14 +108,14 @@ class _PreferencesSettingsTile extends SettingsTile { title: title, subtitle: subtitle, onToggle: _doChange, - switchValue: helper.getBool(preferencesKey), + switchValue: helper!.getBool(preferencesKey), titleMaxLines: 2, subtitleMaxLines: 4, ); } void _doChange(bool value) async { - await helper.setBool(preferencesKey, value); + await helper!.setBool(preferencesKey, value); onChange(); } } diff --git a/lib/ui/routes/settings/custom_emojies_account_settings.dart b/lib/ui/routes/settings/custom_emojies_account_settings.dart index d7a5232..837e4f4 100644 --- a/lib/ui/routes/settings/custom_emojies_account_settings.dart +++ b/lib/ui/routes/settings/custom_emojies_account_settings.dart @@ -28,7 +28,7 @@ class CustomEmojisAccountSettings extends StatefulWidget { class _CustomEmojisAccountSettingsState extends State { - User _user; + late User _user; final _key = GlobalKey(); @@ -45,7 +45,7 @@ class _CustomEmojisAccountSettingsState key: _key, onReload: _reload, onBuild: _buildSettings, - errorMessage: tr("Could not refresh user information!"), + errorMessage: tr("Could not refresh user information!")!, showOldDataWhileUpdating: true, ); } @@ -63,8 +63,8 @@ class _CustomEmojisAccountSettingsState return ListView( children: _user.customEmojies .map((u) => ListTile( - leading: NetworkImageWidget(url: u.url, width: 50), - title: Text(u.shortcut), + leading: NetworkImageWidget(url: u.url!, width: 50), + title: Text(u.shortcut!), trailing: IconButton( icon: Icon(Icons.delete), onPressed: () => _deleteEmoji(u)), @@ -98,10 +98,10 @@ class _CustomEmojisAccountSettingsState await SettingsHelper.uploadNewCustomEmoji(newEmoji); } catch (e, stack) { print("Could not add a new emoji: $e\n$stack"); - showSimpleSnack(context, tr("Could not upload emoji!")); + showSimpleSnack(context, tr("Could not upload emoji!")!); } - _key.currentState.refresh(); + _key.currentState!.refresh(); } /// Ask for confirmation before deleting permanently an emoji @@ -115,10 +115,10 @@ class _CustomEmojisAccountSettingsState await SettingsHelper.deleteCustomEmoji(u.id); } catch (e, stack) { print("Could not delete custom emoji! $e\n$stack"); - showSimpleSnack(context, tr("Could not delete custom emoji!")); + showSimpleSnack(context, tr("Could not delete custom emoji!")!); } - _key.currentState.refresh(); + _key.currentState!.refresh(); } } @@ -127,8 +127,8 @@ class _NewCustomEmojiDialog extends StatefulWidget { final CustomEmojiesList currentList; const _NewCustomEmojiDialog({ - Key key, - @required this.currentList, + Key? key, + required this.currentList, }) : assert(currentList != null), super(key: key); @@ -138,7 +138,7 @@ class _NewCustomEmojiDialog extends StatefulWidget { class _NewCustomEmojiDialogState extends State<_NewCustomEmojiDialog> { final _controller = TextEditingController(); - BytesFile _file; + BytesFile? _file; bool get _hasImage => _file != null; @@ -151,12 +151,12 @@ class _NewCustomEmojiDialogState extends State<_NewCustomEmojiDialog> { bool get _valid => _hasImage && _shortcutValid; - NewEmoji get _emoji => NewEmoji(shortcut: _shortcut, image: _file); + NewEmoji get _emoji => NewEmoji(shortcut: _shortcut, image: _file!); @override Widget build(BuildContext context) { return AlertDialog( - title: Text(tr("Add new emoji")), + title: Text(tr("Add new emoji")!), content: ConstrainedBox( constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height - 50), @@ -167,11 +167,11 @@ class _NewCustomEmojiDialogState extends State<_NewCustomEmojiDialog> { actions: [ MaterialButton( onPressed: () => Navigator.of(context).pop(), - child: Text(tr("Cancel").toUpperCase()), + child: Text(tr("Cancel")!.toUpperCase()), ), MaterialButton( onPressed: _valid ? () => Navigator.of(context).pop(_emoji) : null, - child: Text(tr("Add").toUpperCase()), + child: Text(tr("Add")!.toUpperCase()), ), ], ); @@ -194,7 +194,7 @@ class _NewCustomEmojiDialogState extends State<_NewCustomEmojiDialog> { ), MaterialButton( onPressed: _pickImage, - child: Text(_hasImage ? tr("Replace image") : tr("Add image")), + child: Text(_hasImage ? tr("Replace image")! : tr("Add image")!), ) ], ); @@ -211,7 +211,7 @@ class _NewCustomEmojiDialogState extends State<_NewCustomEmojiDialog> { }); } catch (e, stack) { print("Could not pick an image! $e\n$stack"); - snack(context, tr("Failed to pick an image!")); + snack(context, tr("Failed to pick an image!")!); } } } diff --git a/lib/ui/routes/settings/general_account_settings.dart b/lib/ui/routes/settings/general_account_settings.dart index 8b0a383..aaeacf7 100644 --- a/lib/ui/routes/settings/general_account_settings.dart +++ b/lib/ui/routes/settings/general_account_settings.dart @@ -28,7 +28,7 @@ class GeneralAccountSettingsScreen extends StatefulWidget { class _GeneralAccountSettingsScreenState extends State { - GeneralSettings _settings; + late GeneralSettings _settings; final _key = GlobalKey(); @@ -47,7 +47,7 @@ class _GeneralAccountSettingsScreenState onReload: () async => _settings = await SettingsHelper.getGeneralSettings(), onBuild: _buildSettings, - errorMessage: tr("Could not load general settings!"), + errorMessage: tr("Could not load general settings!")!, showOldDataWhileUpdating: true, ); } @@ -81,28 +81,28 @@ class _GeneralAccountSettingsScreenState // First name TextEditSettingsTile( - title: tr("First name"), + title: tr("First name")!, currValue: _settings.firstName, onChanged: (s) { _settings.firstName = s; _updateSettings(); }, - maxLength: srvConfig.accountInformationPolicy.maxFirstNameLength, + maxLength: srvConfig!.accountInformationPolicy.maxFirstNameLength, checkInput: (s) => - s.length >= srvConfig.accountInformationPolicy.minFirstNameLength, + s.length >= srvConfig!.accountInformationPolicy.minFirstNameLength, ), // Last name TextEditSettingsTile( - title: tr("Last name"), + title: tr("Last name")!, currValue: _settings.lastName, onChanged: (s) { _settings.lastName = s; _updateSettings(); }, - maxLength: srvConfig.accountInformationPolicy.maxLastNameLength, + maxLength: srvConfig!.accountInformationPolicy.maxLastNameLength, checkInput: (s) => - s.length >= srvConfig.accountInformationPolicy.minLastNameLength, + s.length >= srvConfig!.accountInformationPolicy.minLastNameLength, ), // Emails settings @@ -121,15 +121,15 @@ class _GeneralAccountSettingsScreenState List get _visibilityChoices => [ MultiChoiceEntry( id: UserPageVisibility.PRIVATE, - title: tr("Private"), + title: tr("Private")!, subtitle: tr("Private, accessible only to your friends")), MultiChoiceEntry( id: UserPageVisibility.PUBLIC, - title: tr("Public"), + title: tr("Public")!, subtitle: tr("Public, accessible to all Comunic members")), MultiChoiceEntry( id: UserPageVisibility.OPEN, - title: tr("Open"), + title: tr("Open")!, subtitle: tr("Accessible to everyone, including non-Comunic users")), ]; @@ -139,10 +139,10 @@ class _GeneralAccountSettingsScreenState return [ // Page visibility MultiChoicesSettingsTile( - title: tr("Page visibility"), + title: tr("Page visibility")!, choices: _visibilityChoices, currentValue: _settings.pageVisibility, - onChanged: (v) { + onChanged: (dynamic v) { _settings.pageVisibility = v; _updateSettings(); }), @@ -191,7 +191,7 @@ class _GeneralAccountSettingsScreenState // Personal website TextEditSettingsTile( - title: tr("Personal website URL (optional)"), + title: tr("Personal website URL (optional)")!, currValue: _settings.personalWebsite, onChanged: (v) { _settings.personalWebsite = v; @@ -203,19 +203,19 @@ class _GeneralAccountSettingsScreenState // Location TextEditSettingsTile( - title: tr("Location (optional)"), + title: tr("Location (optional)")!, currValue: _settings.location ?? "", onChanged: (v) { _settings.location = v; _updateSettings(); }, - maxLength: srvConfig.accountInformationPolicy.maxLocationLength, + maxLength: srvConfig!.accountInformationPolicy.maxLocationLength, allowEmptyValues: true, ), // Public notes TextEditSettingsTile( - title: tr("Public note (optional)"), + title: tr("Public note (optional)")!, currValue: _settings.publicNote, onChanged: (v) { _settings.publicNote = v; @@ -235,7 +235,7 @@ class _GeneralAccountSettingsScreenState context: context, initialDirectory: _settings.virtualDirectory, type: VirtualDirectoryTargetType.USER, - id: userID()); + id: userID()!); if (dir == null) return; @@ -252,8 +252,8 @@ class _GeneralAccountSettingsScreenState await SettingsHelper.updateGeneralSettings(_settings); } catch (e, stack) { print("Error while updating settings! $e/n$stack"); - showSimpleSnack(context, tr("Could not update general settings!")); + showSimpleSnack(context, tr("Could not update general settings!")!); } - _key.currentState.refresh(); + _key.currentState!.refresh(); } } diff --git a/lib/ui/routes/settings/notifications_settings.dart b/lib/ui/routes/settings/notifications_settings.dart index 225e2cb..330e888 100644 --- a/lib/ui/routes/settings/notifications_settings.dart +++ b/lib/ui/routes/settings/notifications_settings.dart @@ -24,8 +24,8 @@ class _NotificationsSettingsScreenState extends State { final key = GlobalKey(); - NotificationsSettings _settings; - PushNotificationsStatus _pushNotificationsStatus; + late NotificationsSettings _settings; + PushNotificationsStatus? _pushNotificationsStatus; Future _loadSettings() async { _settings = await SettingsHelper.getNotificationsSettings(); @@ -37,7 +37,7 @@ class _NotificationsSettingsScreenState key: key, onReload: _loadSettings, onBuild: _buildScreen, - errorMessage: tr("Failed to load notifications settings!"), + errorMessage: tr("Failed to load notifications settings!")!, ); Widget _buildScreen() => SettingsList(sections: [ @@ -81,7 +81,7 @@ class _NotificationsSettingsScreenState setState(() {}); } catch (e, s) { logError(e, s); - snack(context, tr("Failed to update settings!")); + snack(context, tr("Failed to update settings!")!); } } } diff --git a/lib/ui/routes/single_post_route.dart b/lib/ui/routes/single_post_route.dart index 733f9e7..709e2a8 100644 --- a/lib/ui/routes/single_post_route.dart +++ b/lib/ui/routes/single_post_route.dart @@ -12,8 +12,8 @@ class SinglePostRoute extends StatelessWidget { final int postID; const SinglePostRoute({ - Key key, - @required this.postID, + Key? key, + required this.postID, }) : assert(postID != null), super(key: key); @@ -21,7 +21,7 @@ class SinglePostRoute extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text(tr("Post")), + title: Text(tr("Post")!), ), body: _SinglePostRouteBody(postID: postID), ); @@ -32,8 +32,8 @@ class _SinglePostRouteBody extends StatefulWidget { final int postID; const _SinglePostRouteBody({ - Key key, - @required this.postID, + Key? key, + required this.postID, }) : assert(postID != null), super(key: key); @@ -42,7 +42,7 @@ class _SinglePostRouteBody extends StatefulWidget { } class __SinglePostRouteBodyState extends State<_SinglePostRouteBody> { - Future _getPost() async { + Future _getPost() async { try { return PostsList()..add(await PostsHelper().getSingle(widget.postID)); } on Exception catch (e) { diff --git a/lib/ui/routes/tour_route.dart b/lib/ui/routes/tour_route.dart index 9d8a5ec..4e20fc5 100644 --- a/lib/ui/routes/tour_route.dart +++ b/lib/ui/routes/tour_route.dart @@ -40,7 +40,7 @@ class TourRouteState extends State { final Map pubKeys = Map(); - User currUser; + late User currUser; int _defaultIndex = 0; @@ -57,7 +57,7 @@ class TourRouteState extends State { areNotificationsConfigured = true; // Attempt to automatically register to FCM - else if (srvConfig.notificationsPolicy.hasFirebase) { + else if (srvConfig!.notificationsPolicy.hasFirebase) { try { await PushNotificationsHelper.configure( context, PushNotificationsStatus.FIREBASE); @@ -71,12 +71,12 @@ class TourRouteState extends State { void rebuild() => setState(() {}); void setStateKeepCurrentIndex(BuildContext cxt) async { - _defaultIndex = DefaultTabController.of(cxt).index; - await _key.currentState.refresh(); + _defaultIndex = DefaultTabController.of(cxt)!.index; + await _key.currentState!.refresh(); } List get _list => (config().toursEntriesBuilder != null - ? config().toursEntriesBuilder(this) + ? config().toursEntriesBuilder!(this) : [ FirstTourPane(), @@ -96,25 +96,25 @@ class TourRouteState extends State { PresentationPane( icon: Icons.group_add, - title: tr("Friends"), + title: tr("Friends")!, text: "${tr("You can search the people you know and ask them to become your friends!")}\n\n${tr("This will help you to reach them to exchange information!")}", ), PresentationPane( icon: Icons.question_answer, - title: tr("Conversations"), + title: tr("Conversations")!, text: "${tr("With Comunic, you can have conversations with all your friends.")}\n\n${tr("It is also possible to make video calls!")}", ), PresentationPane( icon: Icons.group, - title: tr("Groups"), + title: tr("Groups")!, text: "${tr("You can join groups where people share the same interests as you!")}\n\n${tr("It is also easy to create your own groups!")}", ), PresentationPane( icon: Icons.lock, - title: tr("Privacy"), + title: tr("Privacy")!, text: "${tr("Your data is YOUR DATA. We will never use it or sell it.")}\n\n${tr("If you do not trust us, you can always check out our source code to verify it!")}", ), @@ -135,7 +135,7 @@ class TourRouteState extends State { child: AsyncScreenWidget( key: _key, onReload: _init, - errorMessage: tr("Failed to load tour!"), + errorMessage: tr("Failed to load tour!")!, onBuild: () => DefaultTabController( initialIndex: _defaultIndex, length: _list.length, @@ -150,22 +150,22 @@ class TourRouteState extends State { } class _RouteBody extends StatefulWidget { - final List panes; + final List? panes; - const _RouteBody({Key key, this.panes}) : super(key: key); + const _RouteBody({Key? key, this.panes}) : super(key: key); @override __RouteBodyState createState() => __RouteBodyState(); } class __RouteBodyState extends State<_RouteBody> { - TabController _controller; + TabController? _controller; - bool get _isLastPane => _controller.index >= widget.panes.length - 1; + bool get _isLastPane => _controller!.index >= widget.panes!.length - 1; - PresentationPane get _currPane => - widget.panes[_controller.index] is PresentationPane - ? widget.panes[_controller.index] + PresentationPane? get _currPane => + widget.panes![_controller!.index] is PresentationPane + ? widget.panes![_controller!.index] as PresentationPane? : null; bool get _canGoNext => _currPane?.canGoNext ?? true; @@ -184,7 +184,7 @@ class __RouteBodyState extends State<_RouteBody> { void _updateController() { _controller = DefaultTabController.of(context); - _controller.addListener(() => setState(() {})); + _controller!.addListener(() => setState(() {})); } @override @@ -195,7 +195,7 @@ class __RouteBodyState extends State<_RouteBody> { Spacer(flex: 1), Expanded( child: TabBarView( - children: widget.panes, + children: widget.panes!, physics: NeverScrollableScrollPhysics(), ), flex: 10), @@ -204,7 +204,7 @@ class __RouteBodyState extends State<_RouteBody> { Spacer(flex: 1), OutlinedButton( onPressed: _canGoNext ? _nextOrFinish : null, - child: Text(!_isLastPane ? tr("Next") : tr("Let's go!")), + child: Text(!_isLastPane ? tr("Next")! : tr("Let's go!")!), ), Spacer(flex: 1), ], @@ -212,17 +212,17 @@ class __RouteBodyState extends State<_RouteBody> { ); void _nextOrFinish() async { - if (_controller.indexIsChanging) return; + if (_controller!.indexIsChanging) return; if (!_isLastPane) { // Check if the next click has to be captured if (_currPane?.onTapNext != null) { - if (!await _currPane.onTapNext(context)) return; + if (!await _currPane!.onTapNext!(context)) return; } - _controller.animateTo(_controller.index + 1); + _controller!.animateTo(_controller!.index + 1); } else { - (await PreferencesHelper.getInstance()) + (await PreferencesHelper.getInstance())! .setBool(PreferencesKeyList.IS_TOUR_SEEN, true); Navigator.of(context).pop(); } diff --git a/lib/ui/routes/update_conversation_route.dart b/lib/ui/routes/update_conversation_route.dart index 7668c3b..cd5eb2c 100644 --- a/lib/ui/routes/update_conversation_route.dart +++ b/lib/ui/routes/update_conversation_route.dart @@ -8,7 +8,7 @@ import 'package:flutter/material.dart'; class UpdateConversationRoute extends StatefulWidget { final int conversationID; - const UpdateConversationRoute({Key key, this.conversationID}) + const UpdateConversationRoute({Key? key, required this.conversationID}) : assert(conversationID != null), super(key: key); diff --git a/lib/ui/routes/video_player_route.dart b/lib/ui/routes/video_player_route.dart index f534e5b..f615f6e 100644 --- a/lib/ui/routes/video_player_route.dart +++ b/lib/ui/routes/video_player_route.dart @@ -13,8 +13,8 @@ class VideoPlayerRoute extends StatefulWidget { final String url; const VideoPlayerRoute({ - Key key, - @required this.url, + Key? key, + required this.url, }) : assert(url != null), super(key: key); @@ -23,16 +23,16 @@ class VideoPlayerRoute extends StatefulWidget { } class _VideoPlayerRouteState extends State { - VideoPlayerController _videoPlayerController; - ChewieController _chewieController; + VideoPlayerController? _videoPlayerController; + ChewieController? _chewieController; Future _initialize() async { _videoPlayerController = VideoPlayerController.network(widget.url); - await _videoPlayerController.initialize(); + await _videoPlayerController!.initialize(); _chewieController = ChewieController( - videoPlayerController: _videoPlayerController, + videoPlayerController: _videoPlayerController!, looping: false, allowFullScreen: true, allowMuting: true, @@ -42,8 +42,8 @@ class _VideoPlayerRouteState extends State { @override void dispose() { - if (_videoPlayerController != null) _videoPlayerController.dispose(); - if (_chewieController != null) _chewieController.dispose(); + if (_videoPlayerController != null) _videoPlayerController!.dispose(); + if (_chewieController != null) _chewieController!.dispose(); super.dispose(); } @@ -61,8 +61,8 @@ class _VideoPlayerRouteState extends State { Widget _buildBody() => AsyncScreenWidget( onReload: _initialize, onBuild: _showBody, - errorMessage: tr("Failed to initialize video!"), + errorMessage: tr("Failed to initialize video!")!, ); - Widget _showBody() => Chewie(controller: _chewieController); + Widget _showBody() => Chewie(controller: _chewieController!); } diff --git a/lib/ui/routes/welcome_route.dart b/lib/ui/routes/welcome_route.dart index 6f0f6ba..9e26faa 100644 --- a/lib/ui/routes/welcome_route.dart +++ b/lib/ui/routes/welcome_route.dart @@ -32,12 +32,12 @@ class _WelcomeRouteState extends State { children: [ ListTile( leading: Icon(Icons.login, color: Colors.white), - title: Text(tr("Login")), + title: Text(tr("Login")!), onTap: _openLoginPage, ), ListTile( leading: Icon(Icons.person_add_alt_1, color: Colors.white), - title: Text(tr("Join the network")), + title: Text(tr("Join the network")!), onTap: _openCreateAccountPage, ) ], diff --git a/lib/ui/screens/authorized_group_page_screen.dart b/lib/ui/screens/authorized_group_page_screen.dart index 3f8e40d..fcce8cf 100644 --- a/lib/ui/screens/authorized_group_page_screen.dart +++ b/lib/ui/screens/authorized_group_page_screen.dart @@ -27,14 +27,14 @@ Color get _headerColor => Colors.blueAccent.shade700; class AuthorizedGroupPageScreen extends StatefulWidget { final AdvancedGroupInfo advancedGroupInfo; - final int conversationID; + final int? conversationID; final Function() needRefresh; const AuthorizedGroupPageScreen({ - Key key, - @required this.advancedGroupInfo, - @required this.conversationID, - @required this.needRefresh, + Key? key, + required this.advancedGroupInfo, + required this.conversationID, + required this.needRefresh, }) : assert(advancedGroupInfo != null), assert(needRefresh != null), super(key: key); @@ -49,42 +49,42 @@ class _AuthorizedGroupPageScreenState with SingleTickerProviderStateMixin { AdvancedGroupInfo get _group => widget.advancedGroupInfo; - TabController _tabController; + TabController? _tabController; List<_GroupPageTab> get _tabs => [ // Posts list _GroupPageTab( widget: (c) => GroupPostsSection(group: _group), - label: tr("Posts"), + label: tr("Posts")!, ), // Forez presence tab _GroupPageTab( widget: (c) => ForezPresenceSection(groupID: _group.id), - label: tr("Presence"), + label: tr("Presence")!, visible: _group.isForezGroup, ), // About the group _GroupPageTab( widget: (c) => AboutGroupSection(group: _group), - label: tr("About"), + label: tr("About")!, ), _GroupPageTab( widget: (c) => GroupMembersSection(groupID: _group.id), - label: tr("Members"), - visible: _group.isAtLeastModerator || _group.isMembersListPublic, + label: tr("Members")!, + visible: _group.isAtLeastModerator || _group.isMembersListPublic!, ) ].where((element) => element.visible).toList() // Add group conversations ..insertAll( (_group.isForezGroup ? 2 : 1), - _group.conversations + _group.conversations! .map((e) => _GroupPageTab( widget: (c) => GroupConversationSection(conv: e), - label: e.name)) + label: e.name!)) .toList()); @override @@ -94,7 +94,7 @@ class _AuthorizedGroupPageScreenState initialIndex: widget.conversationID == null ? 0 : (_group.isForezGroup ? 2 : 1) + - _group.conversations + _group.conversations! .indexWhere((element) => element.id == widget.conversationID), vsync: this, ); @@ -104,7 +104,7 @@ class _AuthorizedGroupPageScreenState @override void dispose() { - _tabController.dispose(); + _tabController!.dispose(); super.dispose(); } @@ -189,7 +189,7 @@ class _AuthorizedGroupPageScreenState _group.isAdmin ? IconButton( icon: Icon(Icons.settings, color: _headerTextColor), - onPressed: () => MainController.of(context).push( + onPressed: () => MainController.of(context)!.push( GroupSettingsScreen(groupID: _group.id), canShowAsDialog: true)) : Container(), @@ -207,9 +207,9 @@ class _GroupPageTab { final String label; const _GroupPageTab({ - @required this.widget, + required this.widget, this.visible = true, - @required this.label, + required this.label, }) : assert(widget != null), assert(visible != null), assert(label != null); diff --git a/lib/ui/screens/call_screen.dart b/lib/ui/screens/call_screen.dart index 6f7d837..dff747e 100644 --- a/lib/ui/screens/call_screen.dart +++ b/lib/ui/screens/call_screen.dart @@ -33,16 +33,16 @@ class CallScreen extends StatefulWidget { /// Use custom application bar. This function takes as parameter a nullable /// String which is the title of the conversation - final PreferredSizeWidget Function(String) buildCustomAppBar; + final PreferredSizeWidget Function(String?)? buildCustomAppBar; /// Execute custom action when the call is closed /// /// The default behavior is to pop the page - final void Function() onClose; + final void Function()? onClose; const CallScreen({ - Key key, - @required this.convID, + Key? key, + required this.convID, this.floatingButtons = true, this.buildCustomAppBar, this.onClose, @@ -60,15 +60,15 @@ class _CallScreenState extends SafeState { int get convID => widget.convID; // State properties - Conversation _conversation; - String _convName; - CallConfig _conf; + late Conversation _conversation; + String? _convName; + late CallConfig _conf; var _error = false; - CallMembersList _membersList; - UsersList _usersList; - final _peersConnections = Map(); - final _renderers = Map(); - MediaStream _localStream; + CallMembersList? _membersList; + late UsersList _usersList; + final _peersConnections = Map(); + final _renderers = Map(); + MediaStream? _localStream; var _isLocalStreamVisible = true; var _hideMenuBars = false; @@ -81,16 +81,16 @@ class _CallScreenState extends SafeState { _conversation.callCapabilities == CallCapabilities.VIDEO; bool get isStreamingAudio => - _localStream != null && _localStream.getAudioTracks().length > 0; + _localStream != null && _localStream!.getAudioTracks().length > 0; bool get isStreamingVideo => - _localStream != null && _localStream.getVideoTracks().length > 0; + _localStream != null && _localStream!.getVideoTracks().length > 0; bool get isAudioMuted => - isStreamingAudio && !_localStream.getAudioTracks()[0].enabled; + isStreamingAudio && !_localStream!.getAudioTracks()[0].enabled; bool get isVideoMuted => - isStreamingVideo && !_localStream.getVideoTracks()[0].enabled; + isStreamingVideo && !_localStream!.getVideoTracks()[0].enabled; @override void initState() { @@ -137,7 +137,7 @@ class _CallScreenState extends SafeState { try { if (!_usersList.hasUser(e.userID)) _usersList.add(await UsersHelper().getSingleWithThrow(e.userID)); - setState(() => _membersList.add(CallMember(userID: e.userID))); + setState(() => _membersList!.add(CallMember(userID: e.userID!))); } catch (e, stack) { print("$e\n$stack"); } @@ -164,7 +164,7 @@ class _CallScreenState extends SafeState { }); // Connect to ready peers - for (final peer in _membersList.readyPeers) + for (final peer in _membersList!.readyPeers) await this._memberReady(peer.userID); setState(() {}); @@ -183,7 +183,7 @@ class _CallScreenState extends SafeState { await setWakeLock(false); // Close all ready members - for (final member in _membersList.readyPeers) + for (final member in _membersList!.readyPeers) await _removeMember(member.userID); // Close local stream @@ -204,9 +204,9 @@ class _CallScreenState extends SafeState { message: tr("Do you really want to leave this call ?"))) return; if (widget.onClose == null) - MainController.of(context).popPage(); + MainController.of(context)!.popPage(); else - widget.onClose(); + widget.onClose!(); } /// Start streaming on our end @@ -232,8 +232,8 @@ class _CallScreenState extends SafeState { // Start renderer _renderers[userID()] = RTCVideoRenderer(); - await _renderers[userID()].initialize(); - _renderers[userID()].srcObject = _localStream; + await _renderers[userID()]!.initialize(); + _renderers[userID()]!.srcObject = _localStream; setState(() {}); // Open stream @@ -244,8 +244,8 @@ class _CallScreenState extends SafeState { _peersConnections[userID()] = peerConnection; - for (final track in _localStream.getTracks()) { - await peerConnection.addTrack(track, _localStream); + for (final track in _localStream!.getTracks()) { + await peerConnection.addTrack(track, _localStream!); } peerConnection.onAddStream = @@ -275,7 +275,7 @@ class _CallScreenState extends SafeState { await CallsHelper.sendSessionDescription(convID, userID(), offer); } catch (e, stack) { print("Could not start streaming! $e\n$stack"); - showSimpleSnack(context, tr("Could not start streaming!")); + showSimpleSnack(context, tr("Could not start streaming!")!); } } @@ -283,7 +283,7 @@ class _CallScreenState extends SafeState { Future _stopStreaming() async { // Close peer connection if (_peersConnections.containsKey(userID())) { - _peersConnections[userID()].close(); + _peersConnections[userID()]!.close(); _peersConnections.remove(userID()); await CallsHelper.notifyStoppedStreaming(convID); @@ -291,13 +291,13 @@ class _CallScreenState extends SafeState { // Stop local stream if (_localStream != null) { - await _localStream.dispose(); + await _localStream!.dispose(); _localStream = null; } // Close renderer if (_renderers.containsKey(userID())) { - await _renderers[userID()].dispose(); + await _renderers[userID()]!.dispose(); _renderers.remove(userID()); } } @@ -324,20 +324,20 @@ class _CallScreenState extends SafeState { // Toggle appropriate mute else { if (!isVideo) - _localStream.getAudioTracks()[0].enabled = - !_localStream.getAudioTracks()[0].enabled; + _localStream!.getAudioTracks()[0].enabled = + !_localStream!.getAudioTracks()[0].enabled; else - _localStream.getVideoTracks()[0].enabled = - !_localStream.getVideoTracks()[0].enabled; + _localStream!.getVideoTracks()[0].enabled = + !_localStream!.getVideoTracks()[0].enabled; } setState(() {}); } /// Call this when a user started to stream media - Future _memberReady(int memberID) async { + Future _memberReady(int? memberID) async { try { - _membersList.getUser(memberID).status = MemberStatus.READY; + _membersList!.getUser(memberID).status = MemberStatus.READY; setState(() {}); // Create peer connection @@ -353,15 +353,15 @@ class _CallScreenState extends SafeState { // Create a renderer _renderers[memberID] = RTCVideoRenderer(); - await _renderers[memberID].initialize(); + await _renderers[memberID]!.initialize(); // Register callbacks peerConnection.onIceCandidate = (c) => CallsHelper.sendIceCandidate(convID, memberID, c); peerConnection.onAddStream = (s) { setState(() { - _membersList.getUser(memberID).stream = s; - _renderers[memberID].srcObject = s; + _membersList!.getUser(memberID).stream = s; + _renderers[memberID]!.srcObject = s; }); }; @@ -371,7 +371,7 @@ class _CallScreenState extends SafeState { setState(() {}); } catch (e, stack) { print("Could not connect to remote peer $e\n$stack!"); - showSimpleSnack(context, tr("Could not connect to a remote peer!")); + showSimpleSnack(context, tr("Could not connect to a remote peer!")!); } } @@ -388,13 +388,13 @@ class _CallScreenState extends SafeState { // Check the kind of signal // SessionDescription if (ev.sessionDescription != null) { - await _peersConnections[ev.peerID] - .setRemoteDescription(ev.sessionDescription); + await _peersConnections[ev.peerID]! + .setRemoteDescription(ev.sessionDescription!); // Send answer if required - if (ev.sessionDescription.type == "offer") { - final answer = await _peersConnections[ev.peerID].createAnswer({}); - await _peersConnections[ev.peerID].setLocalDescription(answer); + if (ev.sessionDescription!.type == "offer") { + final answer = await _peersConnections[ev.peerID]!.createAnswer({}); + await _peersConnections[ev.peerID]!.setLocalDescription(answer); await CallsHelper.sendSessionDescription(convID, ev.peerID, answer); } @@ -402,41 +402,41 @@ class _CallScreenState extends SafeState { // Ice Candidate else { - await _peersConnections[ev.peerID].addCandidate(ev.candidate); + await _peersConnections[ev.peerID]!.addCandidate(ev.candidate!); } } catch (e, stack) { print("Error while handling new signal ! $e\n$stack"); - showSimpleSnack(context, tr("Error while processing new signal!")); + showSimpleSnack(context, tr("Error while processing new signal!")!); } } /// Call this when a user has interrupted streaming - Future _removeRemotePeerConnection(int memberID) async { - final member = _membersList.getUser(memberID); + Future _removeRemotePeerConnection(int? memberID) async { + final member = _membersList!.getUser(memberID); member.status = MemberStatus.JOINED; setState(() {}); if (_peersConnections.containsKey(memberID)) { - await _peersConnections[memberID].close(); + await _peersConnections[memberID]!.close(); _peersConnections.remove(memberID); } if (_renderers.containsKey(memberID)) { - await _renderers[memberID].dispose(); + await _renderers[memberID]!.dispose(); _renderers.remove(memberID); } if (member.stream != null) { - member.stream.dispose(); + member.stream!.dispose(); member.stream = null; } } /// Call this when a member has completely left the call - Future _removeMember(int memberID) async { + Future _removeMember(int? memberID) async { await _removeRemotePeerConnection(memberID); - _membersList.removeUser(memberID); + _membersList!.removeUser(memberID); setState(() {}); } @@ -453,7 +453,7 @@ class _CallScreenState extends SafeState { switch (option) { // Switch camera case _PopupMenuOption.SWITCH_CAMERA: - await Helper.switchCamera(_localStream.getVideoTracks()[0]); + await Helper.switchCamera(_localStream!.getVideoTracks()[0]); break; // Stop streaming @@ -478,14 +478,14 @@ class _CallScreenState extends SafeState { /// Build application bar PreferredSizeWidget _buildAppBar() { if (widget.buildCustomAppBar != null) - return widget.buildCustomAppBar(_convName); + return widget.buildCustomAppBar!(_convName); return AppBar( leading: IconButton( icon: Icon(Icons.arrow_back), onPressed: () => _leaveCall(), ), - title: _convName == null ? CircularProgressIndicator() : Text(_convName), + title: _convName == null ? CircularProgressIndicator() : Text(_convName!), ); } @@ -496,7 +496,7 @@ class _CallScreenState extends SafeState { return buildErrorCard(tr("Could not initialize call!"), actions: [ MaterialButton( onPressed: () => _initCall(), - child: Text(tr("Try again").toUpperCase()), + child: Text(tr("Try again")!.toUpperCase()), ) ]); @@ -526,7 +526,7 @@ class _CallScreenState extends SafeState { padding: const EdgeInsets.all(8.0), child: RichText( text: TextSpan( - children: _membersList + children: _membersList! .map((f) => TextSpan( text: _usersList.getUser(f.userID).displayName + " ", style: TextStyle( @@ -540,7 +540,7 @@ class _CallScreenState extends SafeState { /// Videos area Widget _buildVideosArea(BuildContext context, BoxConstraints constraints) { - final availableVideos = _membersList.readyPeers + final List availableVideos = _membersList!.readyPeers .where((f) => f.hasVideoStream && _renderers.containsKey(f.userID)) .toList(); @@ -591,12 +591,12 @@ class _CallScreenState extends SafeState { } Widget _buildMemberVideo(int peerID) { - return RTCVideoView(_renderers[peerID]); + return RTCVideoView(_renderers[peerID]!); } Widget _buildLocalVideo() { return Positioned( - child: RTCVideoView(_renderers[userID()]), + child: RTCVideoView(_renderers[userID()]!), height: 50, width: 50, right: 10, @@ -657,12 +657,12 @@ class _CallScreenState extends SafeState { // Switch camera PopupMenuItem( enabled: isStreamingVideo, - child: Text(tr("Switch camera")), + child: Text(tr("Switch camera")!), value: _PopupMenuOption.SWITCH_CAMERA), // Interrupt streaming PopupMenuItem( - child: Text(tr("Stop streaming")), + child: Text(tr("Stop streaming")!), value: _PopupMenuOption.STOP_STREAMING) ], child: _FooterButton( @@ -679,7 +679,7 @@ class _CallScreenState extends SafeState { } class _FooterButton extends StatelessWidget { - final Function() onPressed; + final Function()? onPressed; final Widget icon; final bool visible; final double width; @@ -687,13 +687,13 @@ class _FooterButton extends StatelessWidget { final bool roundedButtons; const _FooterButton({ - Key key, - @required this.icon, - @required this.onPressed, + Key? key, + required this.icon, + required this.onPressed, this.visible = true, this.width = 45, this.bgColor = Colors.black, - @required this.roundedButtons, + required this.roundedButtons, }) : assert(icon != null), assert(visible != null), assert(roundedButtons != null), @@ -712,7 +712,7 @@ class _FooterButton extends StatelessWidget { child: FloatingActionButton( child: icon, foregroundColor: Colors.white, - onPressed: onPressed == null ? null : () => onPressed(), + onPressed: onPressed == null ? null : () => onPressed!(), backgroundColor: bgColor, ), )); diff --git a/lib/ui/screens/conversation_members_screen.dart b/lib/ui/screens/conversation_members_screen.dart index 62b1cd5..6cafe18 100644 --- a/lib/ui/screens/conversation_members_screen.dart +++ b/lib/ui/screens/conversation_members_screen.dart @@ -15,8 +15,8 @@ class ConversationMembersScreen extends StatefulWidget { final int convID; const ConversationMembersScreen({ - Key key, - @required this.convID, + Key? key, + required this.convID, }) : assert(convID != null), super(key: key); @@ -26,8 +26,8 @@ class ConversationMembersScreen extends StatefulWidget { } class _ConversationMembersScreenState extends State { - Conversation _conversation; - UsersList _members; + late Conversation _conversation; + late UsersList _members; Future _refresh() async { _conversation = @@ -38,28 +38,28 @@ class _ConversationMembersScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text(tr("Conversation members"))), + appBar: AppBar(title: Text(tr("Conversation members")!)), body: AsyncScreenWidget( onReload: _refresh, onBuild: _buildMembersList, errorMessage: - tr("Could not load the list of members of this conversation!"), + tr("Could not load the list of members of this conversation!")!, ), ); } Widget _buildMembersList() => ListView.builder( itemBuilder: _buildItem, - itemCount: _conversation.members.length, + itemCount: _conversation.members!.length, ); Widget _buildItem(BuildContext context, int index) { - final member = _conversation.members[index]; + final member = _conversation.members![index]; final user = _members.getUser(member.userID); return ListTile( leading: AccountImageWidget(user: user), title: Text(user.displayName), - subtitle: Text(member.isAdmin ? tr("Admin") : tr("Member")), + subtitle: Text(member.isAdmin ? tr("Admin")! : tr("Member")!), ); } } diff --git a/lib/ui/screens/conversation_screen.dart b/lib/ui/screens/conversation_screen.dart index 299c049..3e9967c 100644 --- a/lib/ui/screens/conversation_screen.dart +++ b/lib/ui/screens/conversation_screen.dart @@ -42,7 +42,7 @@ enum _OlderMessagesLevel { NONE, LOADING, NO_MORE_AVAILABLE } class ConversationScreen extends StatefulWidget { final int conversationID; - const ConversationScreen({Key key, this.conversationID}) + const ConversationScreen({Key? key, required this.conversationID}) : assert(conversationID != null), super(key: key); @@ -56,8 +56,8 @@ class _ConversationScreenState extends SafeState { final UsersHelper _usersHelper = UsersHelper(); // Class members - Conversation _conversation; - ConversationMessagesList _messages; + late Conversation _conversation; + ConversationMessagesList? _messages; UsersList _usersInfo = UsersList(); ErrorLevel _error = ErrorLevel.NONE; final _textFieldFocus = FocusNode(); @@ -66,21 +66,21 @@ class _ConversationScreenState extends SafeState { bool _isSendingMessage = false; TextEditingController _textController = TextEditingController(); - ScrollWatcher _scrollController; + ScrollWatcher? _scrollController; _OlderMessagesLevel _loadingOlderMessages = _OlderMessagesLevel.NONE; int _lastWritingEventSent = 0; - CancelToken _sendCancel; - double _sendProgress; + CancelToken? _sendCancel; + double? _sendProgress; String get textMessage => _textController.text; bool get _isMessageValid => textMessage.length >= - ServerConfigurationHelper.config.conversationsPolicy.minMessageLen && + ServerConfigurationHelper.config!.conversationsPolicy.minMessageLen && textMessage.length < - ServerConfigurationHelper.config.conversationsPolicy.maxMessageLen; + ServerConfigurationHelper.config!.conversationsPolicy.maxMessageLen; showKeyboard() => _textFieldFocus.requestFocus(); @@ -179,14 +179,14 @@ class _ConversationScreenState extends SafeState { this.listen((ev) async { if (ev.msg.convID == widget.conversationID) { await _conversationsHelper.saveMessage(ev.msg); - setState(() => _messages.replace(ev.msg)); + setState(() => _messages!.replace(ev.msg)); } }); this.listen((ev) async { if (ev.msg.convID == widget.conversationID) { await _conversationsHelper.removeMessage(ev.msg); - setState(() => _messages.removeMsg(ev.msg.id)); + setState(() => _messages!.removeMsg(ev.msg.id)); } }); @@ -216,7 +216,7 @@ class _ConversationScreenState extends SafeState { //First, get the messages final messages = await _conversationsHelper.getNewMessages( conversationID: widget.conversationID, - lastMessageID: _messages == null ? 0 : _messages.lastMessageID, + lastMessageID: _messages == null ? 0 : _messages!.lastMessageID, online: online, ); @@ -235,14 +235,14 @@ class _ConversationScreenState extends SafeState { Future _loadOlderMessages() async { if (_loadingOlderMessages != _OlderMessagesLevel.NONE || _messages == null || - _messages.length == 0) return; + _messages!.length == 0) return; try { // Let's start to load older messages _setLoadingOlderMessagesState(_OlderMessagesLevel.LOADING); final messages = await _conversationsHelper.getOlderMessages( conversationID: widget.conversationID, - oldestMessagesID: _messages.firstMessageID); + oldestMessagesID: _messages!.firstMessageID); // Mark as not loading anymore _setLoadingOlderMessagesState(_OlderMessagesLevel.NONE); @@ -280,14 +280,14 @@ class _ConversationScreenState extends SafeState { if (_messages == null) _messages = messages; else - _messages.addAll(messages); + _messages!.addAll(messages); //Reverse the order of the messages (if required) if (messages.length > 0) { - _messages.sort(); - final reverse = _messages.reversed; + _messages!.sort(); + final Iterable reverse = _messages!.reversed; _messages = ConversationMessagesList(); - _messages.addAll(reverse); + _messages!.addAll(reverse); } }); @@ -300,20 +300,20 @@ class _ConversationScreenState extends SafeState { try { final file = await showPickFileDialog( context: context, - maxFileSize: srvConfig.conversationsPolicy.filesMaxSize, - allowedMimeTypes: srvConfig.conversationsPolicy.allowedFilesType, - imageMaxWidth: srvConfig.conversationsPolicy.maxMessageImageWidth, - imageMaxHeight: srvConfig.conversationsPolicy.maxMessageImageHeight, + maxFileSize: srvConfig!.conversationsPolicy.filesMaxSize, + allowedMimeTypes: srvConfig!.conversationsPolicy.allowedFilesType, + imageMaxWidth: srvConfig!.conversationsPolicy.maxMessageImageWidth, + imageMaxHeight: srvConfig!.conversationsPolicy.maxMessageImageHeight, ); if (file == null) return; - BytesFile thumbnail; + BytesFile? thumbnail; - if (isVideo(lookupMimeType(file.filename))) + if (isVideo(lookupMimeType(file.filename)!)) thumbnail = await generateVideoThumbnail( videoFile: file, - maxWidth: srvConfig.conversationsPolicy.maxThumbnailWidth, + maxWidth: srvConfig!.conversationsPolicy.maxThumbnailWidth, ); _sendCancel = CancelToken(); @@ -331,7 +331,7 @@ class _ConversationScreenState extends SafeState { assert(res == SendMessageResult.SUCCESS); } catch (e, s) { logError(e, s); - showSimpleSnack(context, tr("Failed to send a file!")); + showSimpleSnack(context, tr("Failed to send a file!")!); } setState(() { @@ -363,8 +363,8 @@ class _ConversationScreenState extends SafeState { SnackBar( content: Text( result == SendMessageResult.MESSAGE_REJECTED - ? tr("Message rejected by the server!") - : tr("Could not send message!"), + ? tr("Message rejected by the server!")! + : tr("Could not send message!")!, ), duration: Duration(milliseconds: 500), ), @@ -395,7 +395,7 @@ class _ConversationScreenState extends SafeState { Widget _buildNoMessagesNotice() { return Expanded( child: Center( - child: Text(tr("There is no message yet in this conversation.")), + child: Text(tr("There is no message yet in this conversation.")!), ), ); } @@ -406,15 +406,15 @@ class _ConversationScreenState extends SafeState { child: ListView.builder( controller: _scrollController, reverse: true, - itemCount: _messages.length, + itemCount: _messages!.length, itemBuilder: (c, i) => _buildMessageItem(i), )); } Widget _buildMessageItem(int msgIndex) { - final msg = _messages[msgIndex]; + final msg = _messages![msgIndex]; final nextMessage = - msgIndex + 1 < _messages.length ? _messages[msgIndex + 1] : null; + msgIndex + 1 < _messages!.length ? _messages![msgIndex + 1] : null; return Column( children: [ @@ -427,7 +427,7 @@ class _ConversationScreenState extends SafeState { ? Container( alignment: Alignment.center, child: ServerConversationMessageTile( - message: msg.serverMessage, users: _usersInfo), + message: msg.serverMessage!, users: _usersInfo), ) : Container( margin: EdgeInsets.symmetric(vertical: 5), @@ -442,7 +442,7 @@ class _ConversationScreenState extends SafeState { } Widget _buildSenderLayout( - ConversationMessage message, ConversationMessage previousMessage) { + ConversationMessage message, ConversationMessage? previousMessage) { final messageRadius = Radius.circular(10); return Container( @@ -466,7 +466,7 @@ class _ConversationScreenState extends SafeState { } Widget _buildReceiverLayout( - ConversationMessage message, ConversationMessage previousMessage) { + ConversationMessage message, ConversationMessage? previousMessage) { final messageRadius = Radius.circular(10); return Row(children: [ @@ -640,11 +640,11 @@ class _ConversationScreenState extends SafeState { flex: 5, ), Spacer(flex: 1), - Text("${(_sendProgress * 100).toInt()}%"), + Text("${(_sendProgress! * 100).toInt()}%"), Spacer(flex: 1), OutlinedButton( - onPressed: () => _sendCancel.cancel(), - child: Text(tr("Cancel").toUpperCase()), + onPressed: () => _sendCancel!.cancel(), + child: Text(tr("Cancel")!.toUpperCase()), ), Spacer(flex: 1), ], @@ -667,8 +667,8 @@ class _ConversationScreenState extends SafeState { ? _buildLoadingOlderMessage() : null, ), - _messages.length == 0 ? _buildNoMessagesNotice() : _buildMessagesList(), - UserWritingInConvNotifier(convID: _conversation.id), + _messages!.length == 0 ? _buildNoMessagesNotice() : _buildMessagesList(), + UserWritingInConvNotifier(convID: _conversation.id!), _sendCancel != null ? _buildSendingWidget() : _buildSendMessageForm(), _showEmojiPicker ? _buildEmojiContainer() : Container(), ], @@ -681,7 +681,7 @@ class _ConversationScreenState extends SafeState { final t = time(); if (t - _lastWritingEventSent < - srvConfig.conversationsPolicy.writingEventInterval) return; + srvConfig!.conversationsPolicy.writingEventInterval) return; _lastWritingEventSent = t; await ConversationsHelper.sendWritingEvent(_conversation.id); @@ -692,7 +692,7 @@ class _ConversationScreenState extends SafeState { /// Request message statistics void _requestMessageStats(ConversationMessage message) async { - MainController.of(context) + MainController.of(context)! .openConversationMessageStats(_conversation, message); } @@ -700,20 +700,20 @@ class _ConversationScreenState extends SafeState { Future _updateMessage(ConversationMessage message) async { final newContent = await askUserString( context: context, - title: tr("Update message"), - message: tr("Please enter new message content:"), - defaultValue: message.message.content, - hint: tr("New message"), + title: tr("Update message")!, + message: tr("Please enter new message content:")!, + defaultValue: message.message.content!, + hint: tr("New message")!, minLength: - ServerConfigurationHelper.config.conversationsPolicy.minMessageLen, + ServerConfigurationHelper.config!.conversationsPolicy.minMessageLen, maxLength: - ServerConfigurationHelper.config.conversationsPolicy.maxMessageLen, + ServerConfigurationHelper.config!.conversationsPolicy.maxMessageLen, ); if (newContent == null) return; if (!await _conversationsHelper.updateMessage(message.id, newContent)) { - showSimpleSnack(context, tr("Could not update message content!")); + showSimpleSnack(context, tr("Could not update message content!")!); return; } } @@ -723,21 +723,21 @@ class _ConversationScreenState extends SafeState { final choice = await showDialog( context: context, builder: (c) => AlertDialog( - title: Text(tr("Confirm deletion")), + title: Text(tr("Confirm deletion")!), content: Text( - tr("Do you really want to delete this message ? The operation can not be cancelled !"), + tr("Do you really want to delete this message ? The operation can not be cancelled !")!, textAlign: TextAlign.justify, ), actions: [ TextButton( child: Text( - tr("Cancel").toUpperCase(), + tr("Cancel")!.toUpperCase(), ), onPressed: () => Navigator.pop(c, false), ), TextButton( child: Text( - tr("Confirm").toUpperCase(), + tr("Confirm")!.toUpperCase(), style: TextStyle(color: Colors.red), ), onPressed: () => Navigator.pop(c, true), @@ -750,6 +750,6 @@ class _ConversationScreenState extends SafeState { // Execute the request if (!await _conversationsHelper.deleteMessage(message.id)) - showSimpleSnack(context, tr("Could not delete conversation message!")); + showSimpleSnack(context, tr("Could not delete conversation message!")!); } } diff --git a/lib/ui/screens/conversations_list_screen.dart b/lib/ui/screens/conversations_list_screen.dart index fa7cd73..dd4d97e 100644 --- a/lib/ui/screens/conversations_list_screen.dart +++ b/lib/ui/screens/conversations_list_screen.dart @@ -21,10 +21,10 @@ import 'package:flutter/material.dart'; class ConversationsListScreen extends StatefulWidget { final bool useSmallFAB; - final Function() onOpen; + final Function()? onOpen; const ConversationsListScreen({ - Key key, + Key? key, this.useSmallFAB = false, this.onOpen, }) : assert(useSmallFAB != null), @@ -37,9 +37,9 @@ class ConversationsListScreen extends StatefulWidget { class _ConversationScreenState extends SafeState { final ConversationsHelper _conversationsHelper = ConversationsHelper(); final UsersHelper _usersHelper = UsersHelper(); - ConversationsList _list; - UsersList _users; - GroupsList _groups; + ConversationsList? _list; + late UsersList _users; + GroupsList? _groups; LoadErrorLevel _error = LoadErrorLevel.NONE; final GlobalKey _refreshIndicatorKey = GlobalKey(); @@ -49,7 +49,7 @@ class _ConversationScreenState extends SafeState { super.initState(); this.listen( - (d) => _refreshIndicatorKey.currentState.show()); + (d) => _refreshIndicatorKey.currentState!.show()); } @override @@ -94,9 +94,9 @@ class _ConversationScreenState extends SafeState { tr("Could not retrieve the list of conversations!"), actions: [ TextButton( - onPressed: () => _refreshIndicatorKey.currentState.show(), + onPressed: () => _refreshIndicatorKey.currentState!.show(), child: Text( - tr("Retry").toUpperCase(), + tr("Retry")!.toUpperCase(), style: TextStyle( color: Colors.white, ), @@ -108,23 +108,23 @@ class _ConversationScreenState extends SafeState { /// Open a conversation void _openConversation(Conversation conv) { - MainController.of(context).openConversation(conv); - if (widget.onOpen != null) widget.onOpen(); + MainController.of(context)!.openConversation(conv); + if (widget.onOpen != null) widget.onOpen!(); } /// Create a new conversation void _createConversation() { - MainController.of(context).push( + MainController.of(context)!.push( CreateConversationScreen(), canShowAsDialog: true, hideNavBar: true, ); - if (widget.onOpen != null) widget.onOpen(); + if (widget.onOpen != null) widget.onOpen!(); } /// Handle conversations updated requests void _updateConversation(Conversation conversation) { - MainController.of(context).openConversationSettingsRoute(conversation); + MainController.of(context)!.openConversationSettingsRoute(conversation); } /// Handle conversation deletion request @@ -153,7 +153,7 @@ class _ConversationScreenState extends SafeState { } catch (e, s) { print("Failed to leave conversation! $e => $s"); ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(tr("Could not leave the conversation!")))); + SnackBar(content: Text(tr("Could not leave the conversation!")!))); } // Reload the list of conversations @@ -181,11 +181,11 @@ class _ConversationScreenState extends SafeState { physics: AlwaysScrollableScrollPhysics(), controller: ScrollController(), itemBuilder: (context, index) { - if (_list[index].isGroupConversation && - !_list[index].following) return Container(); + if (_list![index].isGroupConversation && + !_list![index].following) return Container(); return ConversationTile( - conversation: _list.elementAt(index), + conversation: _list!.elementAt(index), usersList: _users, groupsList: _groups, onOpen: (c) { @@ -195,7 +195,7 @@ class _ConversationScreenState extends SafeState { onRequestLeave: _requestLeaveConversation, ); }, - itemCount: _list.length, + itemCount: _list!.length, ), ), ), diff --git a/lib/ui/screens/friends_list_screen.dart b/lib/ui/screens/friends_list_screen.dart index a7a9f90..700ea0c 100644 --- a/lib/ui/screens/friends_list_screen.dart +++ b/lib/ui/screens/friends_list_screen.dart @@ -22,7 +22,7 @@ enum _ErrorsLevel { NONE, MINOR, MAJOR } class FriendsListScreen extends StatefulWidget { final bool showAppBar; - const FriendsListScreen({Key key, this.showAppBar = true}) : super(key: key); + const FriendsListScreen({Key? key, this.showAppBar = true}) : super(key: key); @override State createState() => _FriendsListScreenState(); @@ -35,8 +35,8 @@ class _FriendsListScreenState extends SafeState { /// Widget members _ErrorsLevel _error = _ErrorsLevel.NONE; - FriendsList _friendsList; - UsersList _usersInfo; + FriendsList? _friendsList; + late UsersList _usersInfo; GlobalKey _refreshIndicatorKey = GlobalKey(); @@ -61,7 +61,7 @@ class _FriendsListScreenState extends SafeState { /// Refresh the list of friends Future _refreshList() async { - await _refreshIndicatorKey.currentState.show(); + await _refreshIndicatorKey.currentState!.show(); } /// Load the list of friends @@ -72,7 +72,7 @@ class _FriendsListScreenState extends SafeState { final list = await _friendsHelper.getList(online: online); // Check if there is no cache yet - if (!online && list.isEmpty) return; + if (!online && list!.isEmpty) return; // Check for errors if (list == null) return _gotError(); @@ -98,7 +98,7 @@ class _FriendsListScreenState extends SafeState { TextButton( onPressed: _refreshList, child: Text( - tr("Retry").toUpperCase(), + tr("Retry")!.toUpperCase(), style: TextStyle(color: Colors.white), ), ), @@ -109,7 +109,7 @@ class _FriendsListScreenState extends SafeState { Widget build(BuildContext context) => Scaffold( appBar: widget.showAppBar ? AppBar( - title: Text(tr("Your friends list")), + title: Text(tr("Your friends list")!), ) : null, body: _buildBody(), @@ -131,18 +131,18 @@ class _FriendsListScreenState extends SafeState { onRefresh: () => _loadList(true), child: ListView.builder( physics: AlwaysScrollableScrollPhysics(), - itemCount: _friendsList.length, - itemBuilder: (c, i) => _friendsList[i].accepted + itemCount: _friendsList!.length, + itemBuilder: (c, i) => _friendsList![i].accepted ? AcceptedFriendTile( - friend: _friendsList[i], - user: _usersInfo.getUser(_friendsList[i].id), + friend: _friendsList![i], + user: _usersInfo.getUser(_friendsList![i].id), onOpenPrivateConversation: _openPrivateConversation, onSetFollowing: _setFollowingFriend, onRequestDelete: _deleteFriend, ) : PendingFriendTile( - friend: _friendsList[i], - user: _usersInfo.getUser(_friendsList[i].id), + friend: _friendsList![i], + user: _usersInfo.getUser(_friendsList![i].id), onRespond: _respondRequest, )), ), @@ -154,7 +154,7 @@ class _FriendsListScreenState extends SafeState { /// Respond to friendship request Future _respondRequest(Friend f, bool accept) async { if (!await _friendsHelper.respondRequest(f.id, accept)) - showSimpleSnack(context, tr("Could not respond to friendship request!")); + showSimpleSnack(context, tr("Could not respond to friendship request!")!); // Load the list of friends again _refreshList(); @@ -163,7 +163,7 @@ class _FriendsListScreenState extends SafeState { /// Update following status of a friend Future _setFollowingFriend(Friend friend, bool follow) async { if (!await _friendsHelper.setFollowing(friend.id, follow)) - showSimpleSnack(context, tr("Could not update following status!")); + showSimpleSnack(context, tr("Could not update following status!")!); _refreshList(); } @@ -173,18 +173,18 @@ class _FriendsListScreenState extends SafeState { final choice = await showDialog( context: context, builder: (b) => AlertDialog( - title: Text(tr("Delete friend")), + title: Text(tr("Delete friend")!), content: Text(tr( - "Are you sure do you want to remove this friend from your list of friends ? A friendship request will have to be sent to get this user back to your list!")), + "Are you sure do you want to remove this friend from your list of friends ? A friendship request will have to be sent to get this user back to your list!")!), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), - child: Text(tr("Cancel").toUpperCase()), + child: Text(tr("Cancel")!.toUpperCase()), ), TextButton( onPressed: () => Navigator.pop(context, true), child: Text( - tr("Confirm").toUpperCase(), + tr("Confirm")!.toUpperCase(), style: TextStyle(color: Colors.red), ), ), @@ -197,7 +197,7 @@ class _FriendsListScreenState extends SafeState { // Forward the request to the server if (!await _friendsHelper.removeFriend(f.id)) showSimpleSnack( - context, tr("Could not delete this person from your friends list!")); + context, tr("Could not delete this person from your friends list!")!); // Refresh list _refreshList(); diff --git a/lib/ui/screens/group_access_denied_screen.dart b/lib/ui/screens/group_access_denied_screen.dart index 0760861..cf9297e 100644 --- a/lib/ui/screens/group_access_denied_screen.dart +++ b/lib/ui/screens/group_access_denied_screen.dart @@ -16,9 +16,9 @@ class GroupAccessDeniedScreen extends StatefulWidget { final Function() onMembershipAcquired; const GroupAccessDeniedScreen({ - Key key, - @required this.groupID, - @required this.onMembershipAcquired, + Key? key, + required this.groupID, + required this.onMembershipAcquired, }) : assert(groupID != null), assert(onMembershipAcquired != null), super(key: key); @@ -29,7 +29,7 @@ class GroupAccessDeniedScreen extends StatefulWidget { } class _GroupAccessDeniedScreenState extends SafeState { - Group _group; + Group? _group; bool error = false; @@ -45,7 +45,7 @@ class _GroupAccessDeniedScreenState extends SafeState { return buildErrorCard(tr("Could not get basic group information!"), actions: [ MaterialButton( - child: Text(tr("Try again").toUpperCase()), + child: Text(tr("Try again")!.toUpperCase()), onPressed: () => this._refresh(), ) ]); @@ -61,20 +61,20 @@ class _GroupAccessDeniedScreenState extends SafeState { Spacer( flex: 5, ), - GroupIcon(group: _group), + GroupIcon(group: _group!), Spacer(), Text( - _group.displayName, + _group!.displayName, style: TextStyle(fontSize: 20), ), Spacer(), Text( - tr("A registration is required to access this group page."), + tr("A registration is required to access this group page.")!, textAlign: TextAlign.center, ), Spacer(), GroupMembershipWidget( - group: _group, + group: _group!, onUpdated: () => this._refresh(), onError: () => this._refresh(), ), diff --git a/lib/ui/screens/group_screen.dart b/lib/ui/screens/group_screen.dart index 0f5ccd3..185aa4a 100644 --- a/lib/ui/screens/group_screen.dart +++ b/lib/ui/screens/group_screen.dart @@ -12,11 +12,11 @@ import 'package:flutter/material.dart'; class GroupPageScreen extends StatefulWidget { final int groupID; - final int conversationID; + final int? conversationID; const GroupPageScreen({ - Key key, - @required this.groupID, + Key? key, + required this.groupID, this.conversationID, }) : assert(groupID != null), super(key: key); @@ -28,7 +28,7 @@ class GroupPageScreen extends StatefulWidget { class _GroupPageScreenState extends SafeState { int get groupID => widget.groupID; - GetAdvancedInfoResult _getGroupResult; + GetAdvancedInfoResult? _getGroupResult; var error = false; @override @@ -44,7 +44,7 @@ class _GroupPageScreenState extends SafeState { actions: [ MaterialButton( onPressed: () => _refreshPage(), - child: Text(tr("Try again").toUpperCase()), + child: Text(tr("Try again")!.toUpperCase()), ) ]); @@ -52,7 +52,7 @@ class _GroupPageScreenState extends SafeState { if (_getGroupResult == null) return buildCenteredProgressBar(); // Check if access to the group was denied - if (_getGroupResult.status == GetAdvancedInfoStatus.ACCESS_DENIED) + if (_getGroupResult!.status == GetAdvancedInfoStatus.ACCESS_DENIED) return GroupAccessDeniedScreen( groupID: groupID, onMembershipAcquired: () => _refreshPage(), @@ -60,7 +60,7 @@ class _GroupPageScreenState extends SafeState { // Now we can show group page return AuthorizedGroupPageScreen( - advancedGroupInfo: _getGroupResult.info, + advancedGroupInfo: _getGroupResult!.info!, conversationID: widget.conversationID, needRefresh: () => _refreshPage(), ); diff --git a/lib/ui/screens/group_sections/about_group_section.dart b/lib/ui/screens/group_sections/about_group_section.dart index ea88c9e..2f80ebc 100644 --- a/lib/ui/screens/group_sections/about_group_section.dart +++ b/lib/ui/screens/group_sections/about_group_section.dart @@ -13,8 +13,8 @@ class AboutGroupSection extends StatelessWidget { final AdvancedGroupInfo group; const AboutGroupSection({ - Key key, - @required this.group, + Key? key, + required this.group, }) : assert(group != null), super(key: key); @@ -25,7 +25,7 @@ class AboutGroupSection extends StatelessWidget { group.hasURL ? ListTile( leading: Icon(Icons.link), - title: Text(tr("URL")), + title: Text(tr("URL")!), subtitle: Text(group.url), onTap: () => launch(group.url), ) @@ -35,7 +35,7 @@ class AboutGroupSection extends StatelessWidget { group.hasDescription ? ListTile( leading: Icon(Icons.note), - title: Text(tr("Description")), + title: Text(tr("Description")!), subtitle: Text(group.description), ) : Container(), @@ -44,64 +44,64 @@ class AboutGroupSection extends StatelessWidget { ListTile( leading: Icon(Icons.access_time), title: Text("Created"), - subtitle: Text(diffTimeFromNowToStr(group.timeCreate)), + subtitle: Text(diffTimeFromNowToStr(group.timeCreate!)!), ), // Number of members ListTile( leading: Icon(Icons.group), - title: Text(tr("Members")), + title: Text(tr("Members")!), subtitle: Text( - tr("%1% members", args: {"1": group.numberMembers.toString()})), + tr("%1% members", args: {"1": group.numberMembers.toString()})!), ), // Who can create posts ListTile( leading: Icon(Icons.add), - title: Text(tr("Who can create posts")), + title: Text(tr("Who can create posts")!), subtitle: Text( group.postCreationLevel == GroupPostCreationLevel.MEMBERS - ? tr("Every members") - : tr("Only moderators and administrators")), + ? tr("Every members")! + : tr("Only moderators and administrators")!), ), // Registration process ListTile( leading: Icon(Icons.login), - title: Text(tr("Registration process")), + title: Text(tr("Registration process")!), subtitle: Text(group.registrationLevel == GroupRegistrationLevel.CLOSED - ? tr("On invitation only") + ? tr("On invitation only")! : (group.registrationLevel == GroupRegistrationLevel.MODERATED - ? tr("A moderator has to approve requests") - : tr("Anyone can join the group without approval"))), + ? tr("A moderator has to approve requests")! + : tr("Anyone can join the group without approval")!)), ), // Group visibility ListTile( leading: Icon(Icons.remove_red_eye), - title: Text(tr("Visibility")), + title: Text(tr("Visibility")!), subtitle: Text(group.visibilityLevel == GroupVisibilityLevel.SECRETE - ? tr("Secrete group") + ? tr("Secrete group")! : (group.visibilityLevel == GroupVisibilityLevel.PRIVATE - ? tr("Private group") - : tr("Open group"))), + ? tr("Private group")! + : tr("Open group")!)), ), // Group members visibility ListTile( leading: Icon(Icons.remove_red_eye), - title: Text(tr("Members list visibility")), + title: Text(tr("Members list visibility")!), subtitle: - Text(group.isMembersListPublic ? tr("Public") : tr("Private")), + Text(group.isMembersListPublic! ? tr("Public")! : tr("Private")!), ), group.isForezGroup ? // Group members visibility ListTile( leading: Icon(Icons.info_outline), - title: Text(tr("Forez group")), - subtitle: Text(tr("Forez special features enabled")), + title: Text(tr("Forez group")!), + subtitle: Text(tr("Forez special features enabled")!), ) : Container(), ], diff --git a/lib/ui/screens/group_sections/forez_presence_section.dart b/lib/ui/screens/group_sections/forez_presence_section.dart index 9efdbdd..952e3f0 100644 --- a/lib/ui/screens/group_sections/forez_presence_section.dart +++ b/lib/ui/screens/group_sections/forez_presence_section.dart @@ -16,8 +16,8 @@ class ForezPresenceSection extends StatefulWidget { final int groupID; const ForezPresenceSection({ - Key key, - @required this.groupID, + Key? key, + required this.groupID, }) : assert(groupID != null), super(key: key); @@ -26,17 +26,17 @@ class ForezPresenceSection extends StatefulWidget { } class _ForezPresenceSectionState extends State { - PresenceSet _presences; - UsersList _users; + PresenceSet? _presences; + late UsersList _users; DateTime _currentDay = DateTime.now(); - List get _currentListOfUsers => _presences.getUsersAtDate(_currentDay); + List get _currentListOfUsers => _presences!.getUsersAtDate(_currentDay); Future _refresh() async { await ForezPresenceHelper.refreshCache(widget.groupID); _presences = await ForezPresenceHelper.getAll(widget.groupID); - _users = await UsersHelper().getList(_presences.usersID); + _users = await UsersHelper().getList(_presences!.usersID); } @override @@ -71,7 +71,7 @@ class _ForezPresenceSectionState extends State { } Widget _buildCalendar() => PresenceCalendarWidget( - presenceSet: _presences, + presenceSet: _presences!, mode: CalendarDisplayMode.MULTIPLE_USERS, selectedDay: _currentDay, onDayClicked: _selectDay, diff --git a/lib/ui/screens/group_sections/group_conversation_section.dart b/lib/ui/screens/group_sections/group_conversation_section.dart index 6a902b1..1ab4bfe 100644 --- a/lib/ui/screens/group_sections/group_conversation_section.dart +++ b/lib/ui/screens/group_sections/group_conversation_section.dart @@ -12,8 +12,8 @@ class GroupConversationSection extends StatelessWidget { final Conversation conv; const GroupConversationSection({ - Key key, - @required this.conv, + Key? key, + required this.conv, }) : assert(conv != null), super(key: key); @@ -21,7 +21,7 @@ class GroupConversationSection extends StatelessWidget { Widget build(BuildContext context) => Stack( children: [ ConversationScreen( - conversationID: conv.id, + conversationID: conv.id!, ), Positioned( right: 1.0, @@ -31,12 +31,12 @@ class GroupConversationSection extends StatelessWidget { ? IconButton( icon: Icon(Icons.phone), onPressed: () => - MainController.of(context).startCall(conv.id), + MainController.of(context)!.startCall(conv.id!), ) : Container(), IconButton( icon: Icon(Icons.settings), - onPressed: () => MainController.of(context) + onPressed: () => MainController.of(context)! .openConversationSettingsRoute(conv), ), ], diff --git a/lib/ui/screens/group_sections/group_members_screen.dart b/lib/ui/screens/group_sections/group_members_screen.dart index 2db22bd..05900ef 100644 --- a/lib/ui/screens/group_sections/group_members_screen.dart +++ b/lib/ui/screens/group_sections/group_members_screen.dart @@ -21,7 +21,7 @@ import 'package:flutter/material.dart'; class GroupMembersSection extends StatefulWidget { final int groupID; - const GroupMembersSection({Key key, this.groupID}) + const GroupMembersSection({Key? key, required this.groupID}) : assert(groupID != null), super(key: key); @@ -31,9 +31,9 @@ class GroupMembersSection extends StatefulWidget { class _GroupMembersSectionState extends State { final _key = GlobalKey(); - Group _group; - GroupMembersList _members; - UsersList _users; + late Group _group; + late GroupMembersList _members; + late UsersList _users; Future _refresh() async { final group = await GroupsHelper().getSingle(widget.groupID, force: true); @@ -50,7 +50,7 @@ class _GroupMembersSectionState extends State { key: _key, onReload: _refresh, onBuild: _buildBodyContent, - errorMessage: tr("Could not load the list of members of this group!"), + errorMessage: tr("Could not load the list of members of this group!")!, showOldDataWhileUpdating: true, ); @@ -70,7 +70,7 @@ class _GroupMembersSectionState extends State { group: _group, membership: membership, user: user, - onUpdated: () => _key.currentState.refresh(), + onUpdated: () => _key.currentState!.refresh(), ); } @@ -93,40 +93,40 @@ class _GroupMembersSectionState extends State { await GroupsHelper.sendInvitation(widget.groupID, userID); } catch (e, s) { print("Could not invite a user! $e\n$s"); - showSimpleSnack(context, tr("Could not invite a user!")); + showSimpleSnack(context, tr("Could not invite a user!")!); } - _key.currentState.refresh(); + _key.currentState!.refresh(); } } List> get _membershipLevels => [ MultiChoiceEntry( id: GroupMembershipLevel.ADMINISTRATOR, - title: tr("Administrator"), + title: tr("Administrator")!, subtitle: tr("Can change members privileges and group settings")), MultiChoiceEntry( id: GroupMembershipLevel.MODERATOR, - title: tr("Moderator"), + title: tr("Moderator")!, subtitle: tr( "Can always create posts, invite users and respond to membership request")), MultiChoiceEntry( id: GroupMembershipLevel.MEMBER, - title: tr("Member"), + title: tr("Member")!, subtitle: tr("Can access to all group posts")), MultiChoiceEntry( id: GroupMembershipLevel.PENDING, - title: tr("Requested"), + title: tr("Requested")!, hidden: true, ), MultiChoiceEntry( id: GroupMembershipLevel.INVITED, - title: tr("Invited"), + title: tr("Invited")!, hidden: true, ), MultiChoiceEntry( id: GroupMembershipLevel.VISITOR, - title: tr("Visitor"), + title: tr("Visitor")!, hidden: true, ), ]; @@ -138,11 +138,11 @@ class _GroupMembershipTile extends StatefulWidget { final void Function() onUpdated; const _GroupMembershipTile({ - Key key, - @required this.group, - @required this.membership, - @required this.user, - @required this.onUpdated, + Key? key, + required this.group, + required this.membership, + required this.user, + required this.onUpdated, }) : assert(group != null), assert(membership != null), assert(user != null), @@ -176,7 +176,7 @@ class __GroupMembershipTileState extends State<_GroupMembershipTile> { ); } - Widget _buildTrailing() { + Widget? _buildTrailing() { switch (widget.membership.level) { case GroupMembershipLevel.ADMINISTRATOR: case GroupMembershipLevel.MODERATOR: @@ -205,14 +205,14 @@ class __GroupMembershipTileState extends State<_GroupMembershipTile> { itemBuilder: (c) => [ // Change membership level PopupMenuItem( - child: Text(tr("Change level")), + child: Text(tr("Change level")!), enabled: !_isCurrentUser && widget.group.isAdmin, value: _MemberMenuOptions.CHANGE_LEVEL, ), // Remove membership PopupMenuItem( - child: Text(tr("Remove")), + child: Text(tr("Remove")!), value: _MemberMenuOptions.DELETE, enabled: !_isCurrentUser, ), @@ -247,7 +247,7 @@ class __GroupMembershipTileState extends State<_GroupMembershipTile> { await GroupsHelper.setNewLevel(groupID, memberID, newLevel); } catch (e, s) { print("Could not change group membership level! $e\n$s"); - showSimpleSnack(context, tr("Could not change group membership level!")); + showSimpleSnack(context, tr("Could not change group membership level!")!); } widget.onUpdated(); @@ -263,7 +263,7 @@ class __GroupMembershipTileState extends State<_GroupMembershipTile> { await GroupsHelper.removeMemberFromGroup(groupID, memberID); } catch (e, s) { print("Could not remove membership! $e\n$s"); - showSimpleSnack(context, tr("Could not remove this membership!")); + showSimpleSnack(context, tr("Could not remove this membership!")!); } widget.onUpdated(); @@ -272,7 +272,7 @@ class __GroupMembershipTileState extends State<_GroupMembershipTile> { Widget _buildInvitedCase() { return MaterialButton( onPressed: _cancelMembership, - child: Text(tr("Cancel").toUpperCase()), + child: Text(tr("Cancel")!.toUpperCase()), textColor: Colors.red, ); } @@ -282,7 +282,7 @@ class __GroupMembershipTileState extends State<_GroupMembershipTile> { await GroupsHelper.cancelInvitation(groupID, memberID); } catch (e, s) { print("Could not cancel invitation! $e\n$s"); - showSimpleSnack(context, tr("Could not cancel invitation!")); + showSimpleSnack(context, tr("Could not cancel invitation!")!); } widget.onUpdated(); @@ -294,12 +294,12 @@ class __GroupMembershipTileState extends State<_GroupMembershipTile> { children: [ MaterialButton( onPressed: () => _respondRequest(false), - child: Text(tr("Reject").toUpperCase()), + child: Text(tr("Reject")!.toUpperCase()), textColor: Colors.red, ), MaterialButton( onPressed: () => _respondRequest(true), - child: Text(tr("Accept").toUpperCase()), + child: Text(tr("Accept")!.toUpperCase()), textColor: Colors.green, ) ], @@ -311,7 +311,7 @@ class __GroupMembershipTileState extends State<_GroupMembershipTile> { await GroupsHelper.respondRequest(groupID, memberID, accept); } catch (e, s) { print("Could not respond to membership request! $e\n$s"); - showSimpleSnack(context, tr("Could not respond to membership request!")); + showSimpleSnack(context, tr("Could not respond to membership request!")!); } widget.onUpdated(); diff --git a/lib/ui/screens/group_sections/group_posts_section.dart b/lib/ui/screens/group_sections/group_posts_section.dart index 88db809..6f6af21 100644 --- a/lib/ui/screens/group_sections/group_posts_section.dart +++ b/lib/ui/screens/group_sections/group_posts_section.dart @@ -12,8 +12,8 @@ class GroupPostsSection extends StatefulWidget { final AdvancedGroupInfo group; const GroupPostsSection({ - Key key, - @required this.group, + Key? key, + required this.group, }) : assert(group != null), super(key: key); @@ -31,7 +31,7 @@ class _GroupPostsSectionState extends State { return PostCreateFormWidget( postTarget: PostTarget.GROUP_PAGE, targetID: widget.group.id, - onCreated: () => _postsKey.currentState.loadPostsList(getOlder: false), + onCreated: () => _postsKey.currentState!.loadPostsList(getOlder: false), ); } diff --git a/lib/ui/screens/group_settings_screen.dart b/lib/ui/screens/group_settings_screen.dart index 2c52778..70149f8 100644 --- a/lib/ui/screens/group_settings_screen.dart +++ b/lib/ui/screens/group_settings_screen.dart @@ -34,7 +34,7 @@ import 'package:flutter_settings_ui/flutter_settings_ui.dart'; class GroupSettingsScreen extends StatefulWidget { final int groupID; - const GroupSettingsScreen({Key key, @required this.groupID}) + const GroupSettingsScreen({Key? key, required this.groupID}) : assert(groupID != null), super(key: key); @@ -43,7 +43,7 @@ class GroupSettingsScreen extends StatefulWidget { } class _GroupSettingsScreenState extends SafeState { - AdvancedGroupInfo _groupSettings; + AdvancedGroupInfo? _groupSettings; final _key = GlobalKey(); @@ -53,13 +53,13 @@ class _GroupSettingsScreenState extends SafeState { Future _updateSettings() async { try { - await GroupsHelper.setSettings(_groupSettings); + await GroupsHelper.setSettings(_groupSettings!); } catch (e, stack) { print("Could not update group settings! $e\n$stack"); - showSimpleSnack(context, tr("Could not update group settings!")); + showSimpleSnack(context, tr("Could not update group settings!")!); } - _key.currentState.refresh(); + _key.currentState!.refresh(); } @override @@ -67,7 +67,7 @@ class _GroupSettingsScreenState extends SafeState { return Scaffold( appBar: AppBar( leading: ComunicBackButton(), - title: Text(tr("Group settings")), + title: Text(tr("Group settings")!), ), body: _buildBody(), ); @@ -78,7 +78,7 @@ class _GroupSettingsScreenState extends SafeState { key: _key, onReload: _refresh, onBuild: _buildContent, - errorMessage: tr("Could not get group settings!"), + errorMessage: tr("Could not get group settings!")!, showOldDataWhileUpdating: true, ); } @@ -96,65 +96,65 @@ class _GroupSettingsScreenState extends SafeState { ); } - Widget _buildGeneralSection() { + SettingsSection _buildGeneralSection() { return SettingsSection( title: tr("General information"), tiles: [ // Group ID SettingsTile( title: tr("Group ID"), - subtitle: _groupSettings.id.toString(), + subtitle: _groupSettings!.id.toString(), ), // Group name TextEditSettingsTile( - title: tr("Group name"), - currValue: _groupSettings.name, + title: tr("Group name")!, + currValue: _groupSettings!.name, onChanged: (s) { - _groupSettings.name = s; + _groupSettings!.name = s; _updateSettings(); }), // Group virtual directory SettingsTile( title: tr("Virtual directory (optional)"), - subtitle: _groupSettings.virtualDirectory, + subtitle: _groupSettings!.virtualDirectory, onPressed: (_) async { final newDir = await showVirtualDirectoryDialog( context: context, - initialDirectory: _groupSettings.virtualDirectory, - id: _groupSettings.id, + initialDirectory: _groupSettings!.virtualDirectory, + id: _groupSettings!.id, type: VirtualDirectoryTargetType.GROUP, ); if (newDir == null) return; - _groupSettings.virtualDirectory = newDir; + _groupSettings!.virtualDirectory = newDir; _updateSettings(); }, ), // Group URL TextEditSettingsTile( - title: tr("Group URL (optional)"), - currValue: _groupSettings.url, + title: tr("Group URL (optional)")!, + currValue: _groupSettings!.url, checkInput: validateUrl, allowEmptyValues: true, onChanged: (s) { - _groupSettings.url = s; + _groupSettings!.url = s; _updateSettings(); }, ), // Group description TextEditSettingsTile( - title: tr("Group description (optional)"), - currValue: _groupSettings.description, + title: tr("Group description (optional)")!, + currValue: _groupSettings!.description, maxLines: 3, maxLength: 255, allowEmptyValues: true, onChanged: (s) { - _groupSettings.description = s; + _groupSettings!.description = s; _updateSettings(); }), ], @@ -164,18 +164,18 @@ class _GroupSettingsScreenState extends SafeState { List> get _visibilityLevels => [ MultiChoiceEntry( id: GroupVisibilityLevel.OPEN, - title: tr("Open group"), + title: tr("Open group")!, subtitle: tr("Group information & public posts are available to everyone."), ), MultiChoiceEntry( id: GroupVisibilityLevel.PRIVATE, - title: tr("Private group"), + title: tr("Private group")!, subtitle: tr("The group is accessible to accepted members only."), ), MultiChoiceEntry( id: GroupVisibilityLevel.SECRETE, - title: tr("Secrete group"), + title: tr("Secrete group")!, subtitle: tr("The group is visible only to invited members."), ), ]; @@ -183,19 +183,19 @@ class _GroupSettingsScreenState extends SafeState { List> get _registrationLevels => [ MultiChoiceEntry( id: GroupRegistrationLevel.OPEN, - title: tr("Open registration"), + title: tr("Open registration")!, subtitle: tr( "Everyone can choose to join the group without moderator approval"), ), MultiChoiceEntry( id: GroupRegistrationLevel.MODERATED, - title: tr("Moderated registration"), + title: tr("Moderated registration")!, subtitle: tr( "Everyone can request a membership, but a moderator review the request"), ), MultiChoiceEntry( id: GroupRegistrationLevel.CLOSED, - title: tr("Closed registration"), + title: tr("Closed registration")!, subtitle: tr( "The only way to join the group is to be invited by a moderator"), ), @@ -204,48 +204,48 @@ class _GroupSettingsScreenState extends SafeState { List> get _postsCreationLevels => [ MultiChoiceEntry( id: GroupPostCreationLevel.MEMBERS, - title: tr("All members"), + title: tr("All members")!, subtitle: tr("All the members of the group can create posts on the group"), ), MultiChoiceEntry( id: GroupPostCreationLevel.MODERATORS, - title: tr("Moderators only"), + title: tr("Moderators only")!, subtitle: tr( "Only moderators and administrators of the group can create posts on it"), ), ]; - Widget _buildAccessRestrictions() => SettingsSection( + SettingsSection _buildAccessRestrictions() => SettingsSection( title: tr("Access restrictions"), tiles: [ // Group visibility MultiChoicesSettingsTile( - title: tr("Group visibility"), + title: tr("Group visibility")!, choices: _visibilityLevels, - currentValue: _groupSettings.visibilityLevel, - onChanged: (v) { - _groupSettings.visibilityLevel = v; + currentValue: _groupSettings!.visibilityLevel, + onChanged: (dynamic v) { + _groupSettings!.visibilityLevel = v; _updateSettings(); }), // Group registration level MultiChoicesSettingsTile( - title: tr("Group registration level"), + title: tr("Group registration level")!, choices: _registrationLevels, - currentValue: _groupSettings.registrationLevel, - onChanged: (v) { - _groupSettings.registrationLevel = v; + currentValue: _groupSettings!.registrationLevel, + onChanged: (dynamic v) { + _groupSettings!.registrationLevel = v; _updateSettings(); }), // Group posts creation levels MultiChoicesSettingsTile( - title: tr("Posts creation level"), + title: tr("Posts creation level")!, choices: _postsCreationLevels, - currentValue: _groupSettings.postCreationLevel, - onChanged: (s) { - _groupSettings.postCreationLevel = s; + currentValue: _groupSettings!.postCreationLevel, + onChanged: (dynamic s) { + _groupSettings!.postCreationLevel = s; _updateSettings(); }), @@ -253,10 +253,10 @@ class _GroupSettingsScreenState extends SafeState { SettingsTile.switchTile( title: tr("Make members list public"), onToggle: (s) { - _groupSettings.isMembersListPublic = s; + _groupSettings!.isMembersListPublic = s; _updateSettings(); }, - switchValue: _groupSettings.isMembersListPublic, + switchValue: _groupSettings!.isMembersListPublic, titleMaxLines: 2, ) ], @@ -266,19 +266,19 @@ class _GroupSettingsScreenState extends SafeState { get _conversationMinMembershipLevel => [ MultiChoiceEntry( id: GroupMembershipLevel.ADMINISTRATOR, - title: tr("Administrators only"), + title: tr("Administrators only")!, subtitle: tr( "Only the administrators of the group can access the conversation"), ), MultiChoiceEntry( id: GroupMembershipLevel.MODERATOR, - title: tr("Moderators and administrators"), + title: tr("Moderators and administrators")!, subtitle: tr( "Only moderators and administrators of the group can access the conversation"), ), MultiChoiceEntry( id: GroupMembershipLevel.MEMBER, - title: tr("All members"), + title: tr("All members")!, subtitle: tr( "All the members of the group can access the conversation"), ), @@ -286,17 +286,17 @@ class _GroupSettingsScreenState extends SafeState { SettingsSection _buildConversationsArea() => SettingsSection( title: tr("Group conversations"), - tiles: _groupSettings.conversations + tiles: _groupSettings!.conversations! .map( (e) { SettingsTile tile = - MultiChoicesSettingsTile( - title: e.name, + MultiChoicesSettingsTile( + title: e.name!, choices: _conversationMinMembershipLevel, currentValue: e.groupMinMembershipLevel, leading: e.hasLogo ? CachedNetworkImage( - imageUrl: e.logoURL, + imageUrl: e.logoURL!, width: 30, ) : Icon(Icons.group, size: 30), @@ -324,13 +324,13 @@ class _GroupSettingsScreenState extends SafeState { try { final name = await askUserString( context: context, - title: tr("New conversation name"), - message: tr("Please give a name to the new conversation"), + title: tr("New conversation name")!, + message: tr("Please give a name to the new conversation")!, defaultValue: "", - hint: tr("Name"), + hint: tr("Name")!, minLength: 1, maxLength: ServerConfigurationHelper - .config.conversationsPolicy.maxConversationNameLen, + .config!.conversationsPolicy.maxConversationNameLen, ); if (name == null) return; @@ -345,27 +345,27 @@ class _GroupSettingsScreenState extends SafeState { if (visibility == null) return; await GroupsHelper.createGroupConversation(NewGroupConversation( - groupID: _groupSettings.id, + groupID: _groupSettings!.id, name: name, minMembershipLevel: visibility, )); - _key.currentState.refresh(); + _key.currentState!.refresh(); } catch (e, s) { logError(e, s); - snack(context, tr("Failed to create a conversation!")); + snack(context, tr("Failed to create a conversation!")!); } } void _changeConversationVisibility( - Conversation conv, GroupMembershipLevel newLevel) async { + Conversation conv, GroupMembershipLevel? newLevel) async { try { await GroupsHelper.setConversationVisibility(conv.id, newLevel); - _key.currentState.refresh(); + _key.currentState!.refresh(); } catch (e, s) { logError(e, s); - snack(context, tr("Failed to change conversation visibility level!")); + snack(context, tr("Failed to change conversation visibility level!")!); } } @@ -378,21 +378,21 @@ class _GroupSettingsScreenState extends SafeState { await GroupsHelper.deleteConversation(conv.id); - _key.currentState.refresh(); + _key.currentState!.refresh(); } catch (e, s) { logError(e, s); - snack(context, tr("Failed to delete conversation!")); + snack(context, tr("Failed to delete conversation!")!); } } - Widget _buildGroupLogoArea() { + SettingsSection _buildGroupLogoArea() { return SettingsSection( title: tr("Group logo"), tiles: [ // Current logo SettingsTile( title: tr("Current logo"), - leading: GroupIcon(group: _groupSettings), + leading: GroupIcon(group: _groupSettings!), ), // Upload a new logo @@ -421,10 +421,10 @@ class _GroupSettingsScreenState extends SafeState { try { final logo = await pickImage(context); if (logo == null) return; - await _doUploadLogo(logo.bytes); + await _doUploadLogo(logo.bytes as Uint8List?); } catch (e, stack) { print("Could not upload new logo! $e\n$stack"); - showSimpleSnack(context, tr("Could not upload new logo!")); + showSimpleSnack(context, tr("Could not upload new logo!")!); } } @@ -435,13 +435,13 @@ class _GroupSettingsScreenState extends SafeState { await _doUploadLogo(newLogo); } catch (e, stack) { print("Could not generate new logo! $e\n$stack"); - showSimpleSnack(context, tr("Could not generate new random logo!")); + showSimpleSnack(context, tr("Could not generate new random logo!")!); } } - Future _doUploadLogo(Uint8List bytes) async { - await GroupsHelper.uploadNewLogo(_groupSettings.id, bytes); - _key.currentState.refresh(); + Future _doUploadLogo(Uint8List? bytes) async { + await GroupsHelper.uploadNewLogo(_groupSettings!.id, bytes); + _key.currentState!.refresh(); } /// Delete previous group logo @@ -452,15 +452,15 @@ class _GroupSettingsScreenState extends SafeState { message: tr("Do you really want to delete the logo of this group ?"))) return; - await GroupsHelper.deleteLogo(_groupSettings.id); - _key.currentState.refresh(); + await GroupsHelper.deleteLogo(_groupSettings!.id); + _key.currentState!.refresh(); } catch (e, s) { print("Could not delete group logo! $e\n$s"); - showSimpleSnack(context, tr("Could not delete group logo!")); + showSimpleSnack(context, tr("Could not delete group logo!")!); } } - Widget _buildDangerZone() { + SettingsSection _buildDangerZone() { return SettingsSection( title: tr("Danger zone"), tiles: [ @@ -485,12 +485,12 @@ class _GroupSettingsScreenState extends SafeState { "Do you really want to delete this group ? All the posts related to it will be permanently deleted!"))) return; - await GroupsHelper.deleteGroup(_groupSettings.id, password); + await GroupsHelper.deleteGroup(_groupSettings!.id, password); - MainController.of(context).popPage(); + MainController.of(context)!.popPage(); } catch (e, s) { print("Could not delete the group! $e\n$s"); - showSimpleSnack(context, tr("Could not delete the group")); + showSimpleSnack(context, tr("Could not delete the group")!); } } } diff --git a/lib/ui/screens/groups_list_screen.dart b/lib/ui/screens/groups_list_screen.dart index dfe4777..78c4637 100644 --- a/lib/ui/screens/groups_list_screen.dart +++ b/lib/ui/screens/groups_list_screen.dart @@ -19,7 +19,7 @@ class GroupsListScreen extends StatefulWidget { } class _GroupsListScreenState extends SafeState { - GroupsList _groups; + GroupsList? _groups; bool _error = false; final _refreshIndicatorKey = GlobalKey(); @@ -41,7 +41,7 @@ class _GroupsListScreenState extends SafeState { hide: !_error, actions: [ MaterialButton( - child: Text(tr("Try again").toUpperCase()), + child: Text(tr("Try again")!.toUpperCase()), onPressed: () => _refreshList(), ), ], @@ -61,19 +61,19 @@ class _GroupsListScreenState extends SafeState { } Widget _buildGroupsList() => ListView( - children: (_groups.values.toList() + children: (_groups!.values.toList() ..sort((one, two) => two.id.compareTo(one.id))) .map((g) => ListTile( leading: GroupIcon(group: g), title: Text(g.displayName), subtitle: GroupMembershipWidget( group: g, - onUpdated: () => _refreshIndicatorKey.currentState.show(), + onUpdated: () => _refreshIndicatorKey.currentState!.show(), ), trailing: IconButton( icon: Icon(Icons.delete), onPressed: () => _deleteGroup(g)), - onTap: () => MainController.of(context).openGroup(g.id), + onTap: () => MainController.of(context)!.openGroup(g.id), )) .toList(), ); @@ -116,10 +116,10 @@ class _GroupsListScreenState extends SafeState { if (!await GroupsHelper().removeMembership(g.id)) showSimpleSnack( - context, tr("Could not remove your membership to this group!")); + context, tr("Could not remove your membership to this group!")!); // Refresh the list of groups - _refreshIndicatorKey.currentState.show(); + _refreshIndicatorKey.currentState!.show(); } /// Add a group @@ -127,10 +127,10 @@ class _GroupsListScreenState extends SafeState { try { final name = await askUserString( context: context, - title: tr("Group name"), - message: tr("Name of the group to create"), + title: tr("Group name")!, + message: tr("Name of the group to create")!, defaultValue: "", - hint: tr("Name of the group"), + hint: tr("Name of the group")!, maxLength: 50, ); @@ -138,10 +138,10 @@ class _GroupsListScreenState extends SafeState { final groupID = await GroupsHelper.create(name); - MainController.of(context).openGroup(groupID); + MainController.of(context)!.openGroup(groupID); } catch (e, s) { print("Could not create a new group! $e\n$s"); - showSimpleSnack(context, tr("Could not create a new group!")); + showSimpleSnack(context, tr("Could not create a new group!")!); } } } diff --git a/lib/ui/screens/notifications_screen.dart b/lib/ui/screens/notifications_screen.dart index 67f4870..31cf7e6 100644 --- a/lib/ui/screens/notifications_screen.dart +++ b/lib/ui/screens/notifications_screen.dart @@ -28,7 +28,7 @@ class NotificationsScreen extends StatefulWidget { final bool useSmallDeleteButton; const NotificationsScreen({ - Key key, + Key? key, this.useSmallDeleteButton = false, }) : assert(useSmallDeleteButton != null), super(key: key); @@ -38,9 +38,9 @@ class NotificationsScreen extends StatefulWidget { } class _NotificationsScreenState extends SafeState { - NotificationsList _list; - UsersList _users; - GroupsList _groups; + NotificationsList? _list; + late UsersList _users; + late GroupsList _groups; _Status _status = _Status.LOADING; final _refreshKey = GlobalKey(); @@ -64,12 +64,12 @@ class _NotificationsScreenState extends SafeState { }); setStatus(_Status.NONE); - } on Exception catch (e) { + } on Exception catch (e, s) { print("Exception while getting the list of notifications!"); - print(e); - } on Error catch (e) { + print("$e, $s"); + } on Error catch (e, s) { print("Error while getting the list of notifications!"); - print(e.stackTrace); + print("$e, $s"); } } @@ -77,7 +77,7 @@ class _NotificationsScreenState extends SafeState { void initState() { super.initState(); - this.listen((d) => _refreshKey.currentState.show()); + this.listen((d) => _refreshKey.currentState!.show()); } @override @@ -121,14 +121,14 @@ class _NotificationsScreenState extends SafeState { /// Build body Widget _buildBody() { - if (_status == _Status.ERROR || _list.length == 0) + if (_status == _Status.ERROR || _list!.length == 0) return SingleChildScrollView( physics: AlwaysScrollableScrollPhysics(), child: _buildSingleChildCases(), ); return ListView( - children: _list + children: _list! .map((f) => _NotificationTile( notification: f, usersList: _users, @@ -146,16 +146,16 @@ class _NotificationsScreenState extends SafeState { actions: [ MaterialButton( onPressed: () => _loadList(), - child: Text(tr("Try again".toUpperCase())), + child: Text(tr("Try again".toUpperCase())!), ) ]); // When there is no notification - if (_list.length == 0) + if (_list!.length == 0) return Padding( padding: const EdgeInsets.all(8.0), child: Center( - child: Text(tr("You do not have any notification now.")), + child: Text(tr("You do not have any notification now.")!), ), ); @@ -165,7 +165,7 @@ class _NotificationsScreenState extends SafeState { /// Delete a notification void _deleteNotification(n.Notification notif) async { setState(() { - _list.remove(notif); + _list!.remove(notif); }); NotificationsHelper().markSeen(notif); @@ -179,11 +179,11 @@ class _NotificationsScreenState extends SafeState { return; if (!await NotificationsHelper().deleteAllNotifications()) { - showSimpleSnack(context, tr("Could not delete all your notifications!")); + showSimpleSnack(context, tr("Could not delete all your notifications!")!); return; } - _refreshKey.currentState.show(); + _refreshKey.currentState!.show(); } } @@ -194,11 +194,11 @@ class _NotificationTile extends StatelessWidget { final void Function(n.Notification) onDelete; const _NotificationTile({ - Key key, - @required this.notification, - @required this.usersList, - @required this.groupsList, - @required this.onDelete, + Key? key, + required this.notification, + required this.usersList, + required this.groupsList, + required this.onDelete, }) : assert(notification != null), assert(usersList != null), assert(groupsList != null), @@ -214,51 +214,51 @@ class _NotificationTile extends StatelessWidget { switch (notification.type) { // Comment case n.NotificationType.COMMENT_CREATED: - message += tr("posted a comment"); + message += tr("posted a comment")!; break; // Friendship requests case n.NotificationType.SENT_FRIEND_REQUEST: - message += tr("sent you a friendship request."); + message += tr("sent you a friendship request.")!; break; case n.NotificationType.ACCEPTED_FRIEND_REQUEST: - message += tr("accepted your friendship request."); + message += tr("accepted your friendship request.")!; break; case n.NotificationType.REJECTED_FRIEND_REQUEST: - message += tr("rejected your friendship request."); + message += tr("rejected your friendship request.")!; break; // Groups membership case n.NotificationType.SENT_GROUP_MEMBERSHIP_INVITATION: - message += tr("invited you to join the group"); + message += tr("invited you to join the group")!; break; case n.NotificationType.ACCEPTED_GROUP_MEMBERSHIP_INVITATION: - message += tr("accepted his invitation to join the group"); + message += tr("accepted his invitation to join the group")!; break; case n.NotificationType.REJECTED_GROUP_MEMBERSHIP_INVITATION: - message += tr("rejected his invitation to join the group"); + message += tr("rejected his invitation to join the group")!; break; case n.NotificationType.SENT_GROUP_MEMBERSHIP_REQUEST: - message += tr("sent a request to join the group"); + message += tr("sent a request to join the group")!; break; case n.NotificationType.ACCEPTED_GROUP_MEMBERSHIP_REQUEST: - message += tr("accepted you request to join the group"); + message += tr("accepted you request to join the group")!; break; case n.NotificationType.REJECTED_GROUP_MEMBERSHIP_REQUEST: - message += tr("rejected your request to join the group"); + message += tr("rejected your request to join the group")!; break; // Generic element creation case n.NotificationType.ELEM_CREATED: if (notification.onElemType == n.NotificationElementType.POST) - message += tr("created a new post"); + message += tr("created a new post")!; break; case n.NotificationType.ELEM_UPDATED: @@ -274,24 +274,24 @@ class _NotificationTile extends StatelessWidget { // User page if (notification.fromContainerType == n.NotificationElementType.USER_PAGE) { if (notification.fromUser == notification.fromContainerId) - message += tr("on his / her page"); + message += tr("on his / her page")!; else message += tr("on %user_name%'s page", args: { "user_name": usersList.getUser(notification.fromContainerId).fullName - }); + })!; } // Group page if (notification.fromContainerType == n.NotificationElementType.GROUP_PAGE) { message += tr("on the group %group%.", args: { - "group": groupsList[notification.fromContainerId].displayName - }); + "group": groupsList[notification.fromContainerId]!.displayName + })!; } // Group membership if (notification.onElemType == n.NotificationElementType.GROUP_MEMBERSHIP) - message += groupsList[notification.onElemId].displayName; + message += groupsList[notification.onElemId]!.displayName; return CustomListTile( leading: AccountImageWidget( @@ -299,11 +299,11 @@ class _NotificationTile extends StatelessWidget { ), onTap: () => _onTap(context), title: Text(message), - subtitle: Text(diffTimeFromNowToStr(notification.timeCreate)), + subtitle: Text(diffTimeFromNowToStr(notification.timeCreate)!), onLongPressOpenMenu: (position) { showMenu(context: context, position: position, items: [ PopupMenuItem( - child: Text(tr("Delete")), + child: Text(tr("Delete")!), value: _PopupMenuActions.DELETE, ), ]).then(_popupMenuAction); @@ -311,7 +311,7 @@ class _NotificationTile extends StatelessWidget { ); } - void _popupMenuAction(_PopupMenuActions value) { + void _popupMenuAction(_PopupMenuActions? value) { switch (value) { case _PopupMenuActions.DELETE: onDelete(notification); @@ -327,10 +327,10 @@ class _NotificationTile extends StatelessWidget { openUserPage(userID: notification.fromUser, context: context); } else if (notification.onElemType == n.NotificationElementType.GROUP_MEMBERSHIP) { - MainController.of(context).openGroup(notification.onElemId); + MainController.of(context)!.openGroup(notification.onElemId); } else { showSimpleSnack(context, - tr("This kind of notification is not supported yet by this application.")); + tr("This kind of notification is not supported yet by this application.")!); return; } diff --git a/lib/ui/screens/other_friends_lists_screen.dart b/lib/ui/screens/other_friends_lists_screen.dart index 0017d80..5adc64a 100644 --- a/lib/ui/screens/other_friends_lists_screen.dart +++ b/lib/ui/screens/other_friends_lists_screen.dart @@ -16,8 +16,8 @@ class OtherUserFriendsListScreen extends StatefulWidget { final bool enableAppBar; const OtherUserFriendsListScreen({ - Key key, - @required this.userID, + Key? key, + required this.userID, this.enableAppBar = true, }) : assert(userID != null), assert(enableAppBar != null), @@ -33,12 +33,12 @@ class _OtherUserFriendsListScreenState final FriendsHelper friendsHelper = FriendsHelper(); final UsersHelper usersHelper = UsersHelper(); - Set _friendsList; - UsersList _usersInfo; + late Set _friendsList; + UsersList? _usersInfo; bool _error = false; - String get _routeName => tr("Friends of %name%", - args: {"name": _usersInfo.getUser(widget.userID).displayName}); + String? get _routeName => tr("Friends of %name%", + args: {"name": _usersInfo!.getUser(widget.userID).displayName}); void setError(bool e) => setState(() => _error = e); @@ -79,16 +79,16 @@ class _OtherUserFriendsListScreenState return Scaffold( appBar: widget.enableAppBar ? AppBar( - title: Text(_routeName), + title: Text(_routeName!), ) : null, body: ListView.builder( itemCount: _friendsList.length, itemBuilder: (c, i) => SimpleUserTile( - user: _usersInfo.getUser(_friendsList.elementAt(i)), + user: _usersInfo!.getUser(_friendsList.elementAt(i)), onTap: (u) => openUserPage( context: context, - userID: u.id, + userID: u.id!, ), ), ), @@ -104,7 +104,7 @@ class _OtherUserFriendsListScreenState actions: [ TextButton( child: Text( - tr("Try again").toUpperCase(), + tr("Try again")!.toUpperCase(), style: TextStyle(color: Colors.white), ), onPressed: load, diff --git a/lib/ui/screens/search_screen.dart b/lib/ui/screens/search_screen.dart index d186da4..c2fc142 100644 --- a/lib/ui/screens/search_screen.dart +++ b/lib/ui/screens/search_screen.dart @@ -24,9 +24,9 @@ class SearchScreen extends StatefulWidget { } class _SearchScreenState extends State { - SearchResultsList _searchResultsList; - UsersList _usersList; - GroupsList _groupsList; + SearchResultsList? _searchResultsList; + late UsersList _usersList; + late GroupsList _groupsList; @override Widget build(BuildContext context) { @@ -44,13 +44,13 @@ class _SearchScreenState extends State { ? Container() : Expanded( child: ListView( - children: _searchResultsList + children: _searchResultsList! .map((f) => f.kind == SearchResultKind.USER ? _SearchResultUser( user: _usersList.getUser(f.id), ) : _SearchResultGroup( - group: _groupsList[f.id], + group: _groupsList[f.id]!, )) .toList(), ), @@ -78,7 +78,7 @@ class _SearchScreenState extends State { print(e); print(stack); - showSimpleSnack(context, tr("Could not peform search!")); + showSimpleSnack(context, tr("Could not peform search!")!); } } } @@ -86,7 +86,7 @@ class _SearchScreenState extends State { class _SearchResultUser extends StatelessWidget { final User user; - const _SearchResultUser({Key key, this.user}) + const _SearchResultUser({Key? key, required this.user}) : assert(user != null), super(key: key); @@ -97,7 +97,7 @@ class _SearchResultUser extends StatelessWidget { user: user, ), title: Text(user.displayName), - onTap: () => MainController.of(context).openUserPage(user.id), + onTap: () => MainController.of(context)!.openUserPage(user.id!), ); } } @@ -105,7 +105,7 @@ class _SearchResultUser extends StatelessWidget { class _SearchResultGroup extends StatelessWidget { final Group group; - const _SearchResultGroup({Key key, this.group}) + const _SearchResultGroup({Key? key, required this.group}) : assert(group != null), super(key: key); @@ -114,8 +114,8 @@ class _SearchResultGroup extends StatelessWidget { return ListTile( leading: GroupIcon(group: group), title: Text(group.displayName), - subtitle: Text(tr("Group")), - onTap: () => MainController.of(context).openGroup(group.id), + subtitle: Text(tr("Group")!), + onTap: () => MainController.of(context)!.openGroup(group.id), ); } } diff --git a/lib/ui/screens/unread_conversations_screen.dart b/lib/ui/screens/unread_conversations_screen.dart index 2e896c0..d71558b 100644 --- a/lib/ui/screens/unread_conversations_screen.dart +++ b/lib/ui/screens/unread_conversations_screen.dart @@ -5,6 +5,7 @@ import 'package:comunic/helpers/users_helper.dart'; import 'package:comunic/lists/groups_list.dart'; import 'package:comunic/lists/unread_conversations_list.dart'; import 'package:comunic/lists/users_list.dart'; +import 'package:comunic/models/unread_conversation.dart'; import 'package:comunic/ui/routes/main_route/main_route.dart'; import 'package:comunic/ui/widgets/async_screen_widget.dart'; import 'package:comunic/ui/widgets/conversation_image_widget.dart'; @@ -25,9 +26,9 @@ class UnreadConversationsScreen extends StatefulWidget { class _UnreadConversationsScreenState extends SafeState { - UnreadConversationsList _list; - UsersList _users; - GroupsList _groups; + late UnreadConversationsList _list; + UsersList? _users; + GroupsList? _groups; final _key = GlobalKey(); @@ -41,7 +42,7 @@ class _UnreadConversationsScreenState void initState() { super.initState(); - listen((e) => _key.currentState.refresh()); + listen((e) => _key.currentState!.refresh()); } @override @@ -50,7 +51,7 @@ class _UnreadConversationsScreenState key: _key, onReload: _refresh, onBuild: _buildList, - errorMessage: tr("Could not load the list of unread conversations!"), + errorMessage: tr("Could not load the list of unread conversations!")!, ); } @@ -61,7 +62,7 @@ class _UnreadConversationsScreenState child: Padding( padding: const EdgeInsets.all(8.0), child: Text( - tr("You do not have any unread conversation yet..."), + tr("You do not have any unread conversation yet...")!, textAlign: TextAlign.center, ), ), @@ -74,34 +75,34 @@ class _UnreadConversationsScreenState } Widget _tileBuilder(BuildContext context, int index) { - final conv = _list[index]; + final UnreadConversation conv = _list[index]; final message = _list[index].message; - final singleUserConv = conv.conv.members.length < 3; + final singleUserConv = conv.conv.members!.length < 3; - String messageStr; + String? messageStr; if (message.hasFile) messageStr = tr("New file"); else if (message.hasMessage) messageStr = singleUserConv ? message.message.content : tr("%1% : %2%", args: { - "1": _users.getUser(message.userID).fullName, + "1": _users!.getUser(message.userID).fullName, "2": message.message.content, }); else - message.serverMessage.getText(_users); + message.serverMessage!.getText(_users); return ListTile( leading: ConversationImageWidget( conversation: conv.conv, - users: _users, + users: _users!, group: conv.conv.isGroupConversation - ? _groups.getGroup(conv.conv.groupID) + ? _groups!.getGroup(conv.conv.groupID) : null, ), - title: Text(ConversationsHelper.getConversationName(conv.conv, _users)), + title: Text(ConversationsHelper.getConversationName(conv.conv, _users)!), subtitle: RichText( text: TextSpan(style: Theme.of(context).textTheme.bodyText2, children: [ TextSpan( @@ -110,9 +111,9 @@ class _UnreadConversationsScreenState ), ]), ), - trailing: Text(diffTimeFromNowToStr(conv.message.timeSent)), + trailing: Text(diffTimeFromNowToStr(conv.message.timeSent!)!), onTap: () => - MainController.of(context).openConversationById(conv.conv.id), + MainController.of(context)!.openConversationById(conv.conv.id!), ); } } diff --git a/lib/ui/screens/update_conversation_screen.dart b/lib/ui/screens/update_conversation_screen.dart index 56482c4..b426b38 100644 --- a/lib/ui/screens/update_conversation_screen.dart +++ b/lib/ui/screens/update_conversation_screen.dart @@ -32,7 +32,7 @@ class UpdateConversationScreen extends StatefulWidget { final convID; const UpdateConversationScreen({ - Key key, + Key? key, this.convID, }) : super(key: key); @@ -41,19 +41,19 @@ class UpdateConversationScreen extends StatefulWidget { } class _UpdateConversationScreen extends State { - Conversation _conversation; + late Conversation _conversation; TextEditingController _nameController = TextEditingController(); TextEditingController _colorController = TextEditingController(); UsersList _members = UsersList(); - Set _admins = Set(); + Set _admins = Set(); bool _followConversation = true; - bool _canEveryoneAddMembers = true; - String _image; + bool? _canEveryoneAddMembers = true; + String? _image; String get _conversationColor => _colorController.text; - Color get _color { + Color? get _color { if (_conversationColor == null || _conversationColor.isEmpty) return null; try { @@ -72,7 +72,7 @@ class _UpdateConversationScreen extends State { isUpdating && _conversation.isGroupConversation; bool get _canAddMembers => - (isAdmin || _conversation.canEveryoneAddMembers) && + (isAdmin || _conversation.canEveryoneAddMembers!) && (!isUpdating || !_conversation.isManaged); get _isValid => _members.length > 0; @@ -104,8 +104,8 @@ class _UpdateConversationScreen extends State { appBar: AppBar( leading: ComunicBackButton(), title: Text(isUpdating - ? tr("Update conversation") - : tr("Create a conversation")), + ? tr("Update conversation")! + : tr("Create a conversation")!), actions: [ IconButton( icon: Icon(Icons.check), @@ -115,7 +115,7 @@ class _UpdateConversationScreen extends State { body: AsyncScreenWidget( onReload: _init, onBuild: _buildBody, - errorMessage: tr("Failed to load conversation settings!"), + errorMessage: tr("Failed to load conversation settings!")!, ), ); @@ -126,7 +126,7 @@ class _UpdateConversationScreen extends State { child: Column( children: [ _isGroupConversation - ? Text(tr("This conversation is managed by a group")) + ? Text(tr("This conversation is managed by a group")!) : Container(), // Conversation name @@ -163,7 +163,7 @@ class _UpdateConversationScreen extends State { _followConversation = b; }), ), - Text(tr("Follow conversation")) + Text(tr("Follow conversation")!) ], ), @@ -173,7 +173,7 @@ class _UpdateConversationScreen extends State { : Row( children: [ Switch.adaptive( - value: _canEveryoneAddMembers, + value: _canEveryoneAddMembers!, onChanged: isAdmin ? (b) => setState(() { _canEveryoneAddMembers = b; @@ -182,7 +182,7 @@ class _UpdateConversationScreen extends State { ), Flexible( child: Text(tr( - "Allow all members of the conversation to add users"))) + "Allow all members of the conversation to add users")!)) ], ), @@ -190,7 +190,7 @@ class _UpdateConversationScreen extends State { PickUserWidget( resetOnChoose: true, keepFocusOnChoose: true, - label: tr("Add member"), + label: tr("Add member")!, enabled: _canAddMembers, onSelectUser: (user) => _addMember(user)), @@ -215,12 +215,12 @@ class _UpdateConversationScreen extends State { onSelected: (choice) => _membersMenuItemSelected(user, choice), itemBuilder: (c) => >[ PopupMenuItem( - child: Text(tr("Toggle admin status")), + child: Text(tr("Toggle admin status")!), value: _MembersMenuChoices.TOGGLE_ADMIN_STATUS, enabled: isUpdating && isAdmin && user.id != userID(), ), PopupMenuItem( - child: Text(tr("Remove")), + child: Text(tr("Remove")!), value: _MembersMenuChoices.REMOVE, enabled: isAdmin && user.id != userID(), ), @@ -260,7 +260,7 @@ class _UpdateConversationScreen extends State { setState(() => _members.insert(0, user)); } catch (e, s) { logError(e, s); - snack(context, tr("Failed to add member to conversation!")); + snack(context, tr("Failed to add member to conversation!")!); } } @@ -275,14 +275,14 @@ class _UpdateConversationScreen extends State { }); } catch (e, s) { logError(e, s); - snack(context, tr("Failed to remove member!")); + snack(context, tr("Failed to remove member!")!); } } void _toggleAdminStatus(User user) async { try { final setAdmin = !_admins.contains(user.id); - await ConversationsHelper.setAdmin(_conversation.id, user.id, setAdmin); + await ConversationsHelper.setAdmin(_conversation.id!, user.id!, setAdmin); setState(() { if (!setAdmin) @@ -292,7 +292,7 @@ class _UpdateConversationScreen extends State { }); } catch (e, s) { logError(e, s); - snack(context, tr("Failed to toggle admin status of user!")); + snack(context, tr("Failed to toggle admin status of user!")!); } } @@ -306,17 +306,17 @@ class _UpdateConversationScreen extends State { name: _nameController.text, members: _members.map((element) => element.id).toList(), follow: _followConversation, - canEveryoneAddMembers: _canEveryoneAddMembers, - color: _color)); + canEveryoneAddMembers: _canEveryoneAddMembers!, + color: _color)) ; - MainController.of(context).popPage(); - MainController.of(context).openConversationById(conversationID); + MainController.of(context)!.popPage(); + MainController.of(context)!.openConversationById(conversationID); return; } // Update conversation settings final newSettings = NewConversationsSettings( - convID: _conversation.id, + convID: _conversation.id!, following: _followConversation, isComplete: isAdmin, name: _nameController.text, @@ -326,10 +326,10 @@ class _UpdateConversationScreen extends State { await ConversationsHelper.updateConversation(newSettings); - MainController.of(context).popPage(); + MainController.of(context)!.popPage(); } catch (e, s) { logError(e, s); - snack(context, tr("Failed to update conversation settings!")); + snack(context, tr("Failed to update conversation settings!")!); } } @@ -337,12 +337,12 @@ class _UpdateConversationScreen extends State { Widget _buildConversationImageWidget() => Column( children: [ SizedBox(height: 10), - Text(tr("Conversation logo"), + Text(tr("Conversation logo")!, style: TextStyle(fontWeight: FontWeight.bold)), SizedBox(height: 5), _image == null ? Text("No logo defined yet.") - : CachedNetworkImage(imageUrl: _image), + : CachedNetworkImage(imageUrl: _image!), SizedBox(height: 5), isAdmin ? Row( @@ -350,14 +350,14 @@ class _UpdateConversationScreen extends State { children: [ OutlinedButton( onPressed: _uploadNewLogo, - child: Text(tr("Change logo")), + child: Text(tr("Change logo")!), ), SizedBox(width: 5), _image == null ? Container() : ElevatedButton( onPressed: _deleteLogo, - child: Text(tr("Delete logo")), + child: Text(tr("Delete logo")!), style: ButtonStyle( backgroundColor: MaterialStateProperty.all(Colors.red)), @@ -375,8 +375,8 @@ class _UpdateConversationScreen extends State { final newLogo = await showPickFileDialog( context: context, allowedMimeTypes: ["image/png", "image/jpeg", "image/gif"], - imageMaxWidth: srvConfig.conversationsPolicy.maxLogoWidth, - imageMaxHeight: srvConfig.conversationsPolicy.maxLogoHeight, + imageMaxWidth: srvConfig!.conversationsPolicy.maxLogoWidth, + imageMaxHeight: srvConfig!.conversationsPolicy.maxLogoHeight, ); if (newLogo == null) return; @@ -388,7 +388,7 @@ class _UpdateConversationScreen extends State { setState(() => _image = newConvSettings.logoURL); } catch (e, s) { logError(e, s); - snack(context, tr("Failed to change conversation logo !")); + snack(context, tr("Failed to change conversation logo !")!); } } @@ -404,7 +404,7 @@ class _UpdateConversationScreen extends State { setState(() => _image = null); } catch (e, s) { logError(e, s); - snack(context, tr("Failed to remove conversation logo!")); + snack(context, tr("Failed to remove conversation logo!")!); } } } diff --git a/lib/ui/screens/user_access_denied_screen.dart b/lib/ui/screens/user_access_denied_screen.dart index 06e40af..9e9200c 100644 --- a/lib/ui/screens/user_access_denied_screen.dart +++ b/lib/ui/screens/user_access_denied_screen.dart @@ -17,7 +17,7 @@ import 'package:flutter/material.dart'; class UserAccessDeniedScreen extends StatefulWidget { final int userID; - const UserAccessDeniedScreen({Key key, @required this.userID}) + const UserAccessDeniedScreen({Key? key, required this.userID}) : assert(userID != null), super(key: key); @@ -31,8 +31,8 @@ class _UserAccessDeniedScreenState extends SafeState { final _key = GlobalKey(); - FriendStatus _status; - User _user; + late FriendStatus _status; + late User _user; Future refresh() async { final status = await friendsHelper.getFriendshipStatus(widget.userID); @@ -40,7 +40,7 @@ class _UserAccessDeniedScreenState extends SafeState { // Check if the two users are friend now if (status.areFriend) { - final controller = MainController.of(context); + final controller = MainController.of(context)!; controller.popPage(); controller.openUserPage(widget.userID); } @@ -55,7 +55,7 @@ class _UserAccessDeniedScreenState extends SafeState { key: _key, onReload: refresh, onBuild: _buildPage, - errorMessage: tr("Could not load friendship information!")); + errorMessage: tr("Could not load friendship information!")!); } Widget _buildPage() { @@ -77,10 +77,10 @@ class _UserAccessDeniedScreenState extends SafeState { _user.displayName, style: TextStyle(fontSize: 25.0), ), - Text(tr("This account is private.")), + Text(tr("This account is private.")!), FriendshipStatusWidget( status: _status, - onFriendshipUpdated: () => _key.currentState.refresh(), + onFriendshipUpdated: () => _key.currentState!.refresh(), ) ], ), diff --git a/lib/ui/screens/user_page_screen.dart b/lib/ui/screens/user_page_screen.dart index 28c42f6..f1a0903 100644 --- a/lib/ui/screens/user_page_screen.dart +++ b/lib/ui/screens/user_page_screen.dart @@ -20,7 +20,7 @@ enum _PageStatus { LOADING, ERROR, READY } class UserPageScreen extends StatefulWidget { final int userID; - const UserPageScreen({Key key, @required this.userID}) + const UserPageScreen({Key? key, required this.userID}) : assert(userID != null), super(key: key); @@ -34,8 +34,8 @@ class _UserPageScreenState extends SafeState { // Objects members _PageStatus _status = _PageStatus.LOADING; - AdvancedUserInfo _userInfo; - FriendStatus _frienshipStatus; + late AdvancedUserInfo _userInfo; + FriendStatus? _frienshipStatus; final _refreshIndicatorKey = GlobalKey(); _setStatus(_PageStatus s) => setState(() => _status = s); @@ -65,7 +65,7 @@ class _UserPageScreenState extends SafeState { _setStatus(_PageStatus.ERROR); if (e.cause == GetUserAdvancedInformationErrorCause.NOT_AUTHORIZED) { - final controller = MainController.of(context); + final controller = MainController.of(context)!; controller.popPage(); controller.openUserAccessDeniedPage(widget.userID); } @@ -94,7 +94,7 @@ class _UserPageScreenState extends SafeState { Widget _buildError() { return Scaffold( appBar: AppBar( - title: Text(tr("Error")), + title: Text(tr("Error")!), ), body: Center( child: @@ -102,7 +102,7 @@ class _UserPageScreenState extends SafeState { TextButton( onPressed: _getUserInfo, child: Text( - tr("Retry").toUpperCase(), + tr("Retry")!.toUpperCase(), style: TextStyle(color: Colors.white), ), ) @@ -114,12 +114,12 @@ class _UserPageScreenState extends SafeState { return isTablet(context) ? UserPageTablet( userInfo: _userInfo, - onNeedRefresh: () => _refreshIndicatorKey.currentState.show(), + onNeedRefresh: () => _refreshIndicatorKey.currentState!.show(), friendshipStatus: _frienshipStatus, ) : UserMobilePage( userInfo: _userInfo, - onNeedRefresh: () => _refreshIndicatorKey.currentState.show(), + onNeedRefresh: () => _refreshIndicatorKey.currentState!.show(), ); } } diff --git a/lib/ui/screens/user_page_sections/about_user_section.dart b/lib/ui/screens/user_page_sections/about_user_section.dart index d78b4fb..5b6406e 100644 --- a/lib/ui/screens/user_page_sections/about_user_section.dart +++ b/lib/ui/screens/user_page_sections/about_user_section.dart @@ -19,8 +19,8 @@ class AboutUserSection extends StatefulWidget { final AdvancedUserInfo user; const AboutUserSection({ - Key key, - @required this.user, + Key? key, + required this.user, }) : assert(user != null), super(key: key); @@ -29,7 +29,7 @@ class AboutUserSection extends StatefulWidget { } class _AboutUserSectionState extends State { - FriendStatus _friendStatus; + late FriendStatus _friendStatus; final _screenKey = GlobalKey(); @@ -38,14 +38,14 @@ class _AboutUserSectionState extends State { _friendStatus = await FriendsHelper().getFriendshipStatus(widget.user.id); } - void _toggleRefresh() => _screenKey.currentState.refresh(); + void _toggleRefresh() => _screenKey.currentState!.refresh(); @override Widget build(BuildContext context) => AsyncScreenWidget( key: _screenKey, onReload: _init, onBuild: _buildList, - errorMessage: tr("Failed to load user information!")); + errorMessage: tr("Failed to load user information!")!); Widget _buildList() => ListView( children: [ @@ -58,7 +58,7 @@ class _AboutUserSectionState extends State { widget.user.hasPersonalWebsite ? ListTile( leading: Icon(Icons.link), - title: Text(tr("Personal Website")), + title: Text(tr("Personal Website")!), subtitle: Text(widget.user.personalWebsite), onTap: () => launch(widget.user.personalWebsite), ) @@ -68,7 +68,7 @@ class _AboutUserSectionState extends State { widget.user.hasPublicNote ? ListTile( leading: Icon(Icons.note), - title: Text(tr("Note")), + title: Text(tr("Note")!), subtitle: TextWidget( content: DisplayedString(widget.user.publicNote)), ) @@ -78,7 +78,7 @@ class _AboutUserSectionState extends State { widget.user.hasVirtualDirectory ? ListTile( leading: Icon(Icons.alternate_email), - title: Text(tr("Virtual directory")), + title: Text(tr("Virtual directory")!), subtitle: Text("@${widget.user.virtualDirectory}")) : Container(), @@ -87,10 +87,10 @@ class _AboutUserSectionState extends State { ? Container() : ListTile( leading: Icon(Icons.email_outlined), - title: Text(tr("Email address")), - subtitle: Text(widget.user.emailAddress), + title: Text(tr("Email address")!), + subtitle: Text(widget.user.emailAddress!), onTap: () => - copyToClipboard(context, widget.user.emailAddress), + copyToClipboard(context, widget.user.emailAddress!), ), // User location @@ -98,16 +98,16 @@ class _AboutUserSectionState extends State { ? Container() : ListTile( leading: Icon(Icons.location_on), - title: Text(tr("Location")), - subtitle: Text(widget.user.location), - onTap: () => copyToClipboard(context, widget.user.location), + title: Text(tr("Location")!), + subtitle: Text(widget.user.location!), + onTap: () => copyToClipboard(context, widget.user.location!), ), // Number of friends widget.user.isFriendsListPublic ? ListTile( leading: Icon(Icons.group), - title: Text(tr("Number of friends")), + title: Text(tr("Number of friends")!), subtitle: Text(widget.user.numberFriends.toString()), ) : Container(), @@ -115,20 +115,20 @@ class _AboutUserSectionState extends State { // Member for ListTile( leading: Icon(Icons.access_time_rounded), - title: Text(tr("Member for")), + title: Text(tr("Member for")!), subtitle: - Text(diffTimeFromNowToStr(widget.user.accountCreationTime)), + Text(diffTimeFromNowToStr(widget.user.accountCreationTime)!), ), // Account visibility ListTile( leading: Icon(Icons.remove_red_eye), - title: Text(tr("Account visibility")), + title: Text(tr("Account visibility")!), subtitle: Text(widget.user.pageVisibility == UserPageVisibility.OPEN - ? tr("Open page") + ? tr("Open page")! : (widget.user.pageVisibility == UserPageVisibility.PUBLIC - ? tr("Public page") - : tr("Private page"))), + ? tr("Public page")! + : tr("Private page")!)), ), ], ); diff --git a/lib/ui/screens/user_page_sections/user_page_header.dart b/lib/ui/screens/user_page_sections/user_page_header.dart index 2031984..c9dc128 100644 --- a/lib/ui/screens/user_page_sections/user_page_header.dart +++ b/lib/ui/screens/user_page_sections/user_page_header.dart @@ -14,9 +14,9 @@ class UserPageHeader extends StatelessWidget { final Color bgColor; const UserPageHeader({ - Key key, - @required this.user, - @required this.bgColor, + Key? key, + required this.user, + required this.bgColor, }) : assert(user != null), super(key: key); diff --git a/lib/ui/screens/user_page_sections/user_posts_section.dart b/lib/ui/screens/user_page_sections/user_posts_section.dart index 10019e2..96b5d00 100644 --- a/lib/ui/screens/user_page_sections/user_posts_section.dart +++ b/lib/ui/screens/user_page_sections/user_posts_section.dart @@ -13,8 +13,8 @@ class UserPostsSection extends StatefulWidget { final AdvancedUserInfo user; const UserPostsSection({ - Key key, - @required this.user, + Key? key, + required this.user, }) : assert(user != null), super(key: key); @@ -23,7 +23,7 @@ class UserPostsSection extends StatefulWidget { } class _UserPostsSectionState extends State { - int get _userID => widget.user.id; + int? get _userID => widget.user.id; final _postsKey = GlobalKey(); @@ -34,7 +34,7 @@ class _UserPostsSectionState extends State { widget.user.canPostTexts ? PostCreateFormWidget( postTarget: PostTarget.USER_PAGE, - targetID: _userID, + targetID: _userID!, onCreated: _postCreated, ) : Container() @@ -45,6 +45,6 @@ class _UserPostsSectionState extends State { ); void _postCreated() { - _postsKey.currentState.loadPostsList(getOlder: false); + _postsKey.currentState!.loadPostsList(getOlder: false); } } diff --git a/lib/ui/tiles/accepted_friend_tile.dart b/lib/ui/tiles/accepted_friend_tile.dart index 0a090b0..7a68a36 100644 --- a/lib/ui/tiles/accepted_friend_tile.dart +++ b/lib/ui/tiles/accepted_friend_tile.dart @@ -24,12 +24,12 @@ class AcceptedFriendTile extends StatelessWidget { final OnOpenPrivateConversation onOpenPrivateConversation; const AcceptedFriendTile({ - Key key, - @required this.friend, - @required this.user, - @required this.onRequestDelete, - @required this.onSetFollowing, - @required this.onOpenPrivateConversation, + Key? key, + required this.friend, + required this.user, + required this.onRequestDelete, + required this.onSetFollowing, + required this.onOpenPrivateConversation, }) : assert(friend != null), assert(user != null), assert(onRequestDelete != null), @@ -40,24 +40,24 @@ class AcceptedFriendTile extends StatelessWidget { @override Widget build(BuildContext context) { return ListTile( - onTap: () => openUserPage(context: context, userID: user.id), + onTap: () => openUserPage(context: context, userID: user.id!), leading: AccountImageWidget(user: user), title: Text(user.displayName), subtitle: friend.isConnected ? Text( tr( "Online", - ), + )!, style: TextStyle(color: Colors.green), ) : Text( - diffTimeFromNowToStr(friend.lastActive), + diffTimeFromNowToStr(friend.lastActive!)!, ), trailing: PopupMenuButton<_FriendMenuChoices>( itemBuilder: (c) => [ //Open a private conversation PopupMenuItem( - child: Text(tr("Private conversation")), + child: Text(tr("Private conversation")!), value: _FriendMenuChoices.PRIVATE_CONVERSATION, ), @@ -69,7 +69,7 @@ class AcceptedFriendTile extends StatelessWidget { ? Icons.check_box : Icons.check_box_outline_blank), Container(width: 10.0), - Text(friend.following ? tr("Following") : tr("Follow")), + Text(friend.following ? tr("Following")! : tr("Follow")!), ], ), value: _FriendMenuChoices.TOGGLE_FOLLOWING, @@ -77,7 +77,7 @@ class AcceptedFriendTile extends StatelessWidget { // Remove the friend from the list PopupMenuItem( - child: Text(tr("Remove")), + child: Text(tr("Remove")!), value: _FriendMenuChoices.REMOVE, ), ], diff --git a/lib/ui/tiles/comment_tile.dart b/lib/ui/tiles/comment_tile.dart index d3b1492..8513e7f 100644 --- a/lib/ui/tiles/comment_tile.dart +++ b/lib/ui/tiles/comment_tile.dart @@ -22,11 +22,11 @@ class CommentTile extends StatelessWidget { final void Function(Comment) onDeleteComment; const CommentTile({ - Key key, - @required this.comment, - @required this.user, - @required this.onUpdateComment, - @required this.onDeleteComment, + Key? key, + required this.comment, + required this.user, + required this.onUpdateComment, + required this.onDeleteComment, }) : assert(comment != null), assert(user != null), assert(onUpdateComment != null), @@ -42,7 +42,7 @@ class CommentTile extends StatelessWidget { ), subtitle: _buildCommentContent(), trailing: Text( - diffTimeFromNowToStr(comment.timeSent), + diffTimeFromNowToStr(comment.timeSent)!, style: TextStyle(fontSize: 10.0), ), ); @@ -58,14 +58,14 @@ class CommentTile extends StatelessWidget { // Update comment content PopupMenuItem( enabled: comment.isOwner, - child: Text(tr("Update")), + child: Text(tr("Update")!), value: _CommentAction.UPDATE, ), // Delete comment PopupMenuItem( enabled: comment.isOwner, - child: Text(tr("Delete")), + child: Text(tr("Delete")!), value: _CommentAction.DELETE, ), ], @@ -80,7 +80,7 @@ class CommentTile extends StatelessWidget { Container( child: comment.hasImage ? NetworkImageWidget( - url: comment.imageURL, + url: comment.imageURL!, allowFullScreen: true, height: 100.0, width: null, diff --git a/lib/ui/tiles/conversation_message_tile.dart b/lib/ui/tiles/conversation_message_tile.dart index ae7444c..494158c 100644 --- a/lib/ui/tiles/conversation_message_tile.dart +++ b/lib/ui/tiles/conversation_message_tile.dart @@ -31,12 +31,12 @@ class ConversationMessageTile extends StatelessWidget { final OnRequestMessageDelete onRequestMessageDelete; const ConversationMessageTile({ - Key key, - @required this.message, - @required this.user, - @required this.onRequestMessageStats, - @required this.onRequestMessageUpdate, - @required this.onRequestMessageDelete, + Key? key, + required this.message, + required this.user, + required this.onRequestMessageStats, + required this.onRequestMessageUpdate, + required this.onRequestMessageDelete, }) : assert(message != null), assert(user != null), assert(onRequestMessageStats != null), @@ -66,34 +66,34 @@ class ConversationMessageTile extends StatelessWidget { PopupMenuItem( enabled: (message.message?.content ?? "") != "", value: _MenuChoices.COPY_MESSAGE, - child: Text(tr("Copy message")), + child: Text(tr("Copy message")!), ), PopupMenuItem( enabled: message.file != null, value: _MenuChoices.COPY_URL, - child: Text(tr("Copy URL")), + child: Text(tr("Copy URL")!), ), PopupMenuItem( value: _MenuChoices.GET_STATS, - child: Text(tr("Statistics")), + child: Text(tr("Statistics")!), ), // Update message content PopupMenuItem( enabled: message.isOwner && message.message != null && - message.message.content.isNotEmpty, + message.message.content!.isNotEmpty, value: _MenuChoices.REQUEST_UPDATE_CONTENT, - child: Text(tr("Update")), + child: Text(tr("Update")!), ), // Delete the message PopupMenuItem( enabled: message.isOwner, value: _MenuChoices.DELETE, - child: Text(tr("Delete")), + child: Text(tr("Delete")!), ), ]..removeWhere((element) => !element.enabled), ), @@ -113,18 +113,18 @@ class ConversationMessageTile extends StatelessWidget { linksColor: Colors.white, ); - return ConversationFileWidget(messageID: message.id, file: message.file); + return ConversationFileWidget(messageID: message.id!, file: message.file!); } /// Process menu choice void _menuOptionSelected(BuildContext context, _MenuChoices value) { switch (value) { case _MenuChoices.COPY_MESSAGE: - copyToClipboard(context, message.message.content); + copyToClipboard(context, message.message.content!); break; case _MenuChoices.COPY_URL: - copyToClipboard(context, message.file.url); + copyToClipboard(context, message.file!.url!); break; case _MenuChoices.GET_STATS: diff --git a/lib/ui/tiles/conversation_tile.dart b/lib/ui/tiles/conversation_tile.dart index 39d2a37..0823ebe 100644 --- a/lib/ui/tiles/conversation_tile.dart +++ b/lib/ui/tiles/conversation_tile.dart @@ -23,19 +23,19 @@ enum _PopupMenuChoices { UPDATE, LEAVE } class ConversationTile extends StatelessWidget { final Conversation conversation; final UsersList usersList; - final GroupsList groupsList; + final GroupsList? groupsList; final OpenConversationCallback onOpen; final RequestUpdateConversationCallback onRequestUpdate; final RequestLeaveConversationCallback onRequestLeave; const ConversationTile({ - Key key, - @required this.conversation, - @required this.usersList, - @required this.groupsList, - @required this.onOpen, - @required this.onRequestUpdate, - @required this.onRequestLeave, + Key? key, + required this.conversation, + required this.usersList, + required this.groupsList, + required this.onOpen, + required this.onRequestUpdate, + required this.onRequestLeave, }) : assert(conversation != null), assert(usersList != null), assert(onOpen != null), @@ -68,7 +68,7 @@ class ConversationTile extends StatelessWidget { ConversationsHelper.getConversationName( conversation, usersList, - ), + )!, style: TextStyle( fontWeight: conversation.sawLastMessage ? null : FontWeight.bold, ), @@ -87,7 +87,7 @@ class ConversationTile extends StatelessWidget { conversation: conversation, users: usersList, group: conversation.isGroupConversation - ? groupsList.getGroup(conversation.groupID) + ? groupsList!.getGroup(conversation.groupID) : null, ), @@ -97,24 +97,24 @@ class ConversationTile extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ _buildSubInformation(Icons.access_time, - diffTimeFromNowToStr(conversation.lastActivity)), + diffTimeFromNowToStr(conversation.lastActivity!)!), conversation.isGroupConversation ? _buildSubInformation( Icons.link, tr("Group: %group_name%", args: { "group_name": - groupsList.getGroup(conversation.groupID).name - })) + groupsList!.getGroup(conversation.groupID)!.name + })!) : _buildSubInformation( Icons.group, - conversation.members.length == 1 - ? tr("1 member") + conversation.members!.length == 1 + ? tr("1 member")! : tr( "%num% members", args: { - "num": conversation.members.length.toString(), + "num": conversation.members!.length.toString(), }, - ), + )!, ), ], ), @@ -125,11 +125,11 @@ class ConversationTile extends StatelessWidget { position: position, items: [ PopupMenuItem( - child: Text(tr("Update")), + child: Text(tr("Update")!), value: _PopupMenuChoices.UPDATE, ), PopupMenuItem( - child: Text(tr("Leave")), + child: Text(tr("Leave")!), value: _PopupMenuChoices.LEAVE, ) ]).then(_conversationMenuCallback); @@ -143,9 +143,9 @@ class ConversationTile extends StatelessWidget { return Padding( padding: EdgeInsets.only(bottom: 20), child: ListTile( - onTap: () => MainController.of(context).startCall(conversation.id), + onTap: () => MainController.of(context)!.startCall(conversation.id!), dense: true, - title: Text(tr("Ongoing call")), + title: Text(tr("Ongoing call")!), leading: Icon(Icons.call), tileColor: Colors.yellow.withOpacity(0.2), ), @@ -153,7 +153,7 @@ class ConversationTile extends StatelessWidget { } /// Method called each time an option of the menu is selected - void _conversationMenuCallback(_PopupMenuChoices c) { + void _conversationMenuCallback(_PopupMenuChoices? c) { switch (c) { case _PopupMenuChoices.UPDATE: onRequestUpdate(conversation); diff --git a/lib/ui/tiles/menu_tile.dart b/lib/ui/tiles/menu_tile.dart index 748b8b4..4ff48ba 100644 --- a/lib/ui/tiles/menu_tile.dart +++ b/lib/ui/tiles/menu_tile.dart @@ -6,9 +6,9 @@ import 'package:flutter/material.dart'; class MenuTile extends StatelessWidget { final String title; - final GestureTapCallback onTap; + final GestureTapCallback? onTap; - const MenuTile({@required this.title, this.onTap}) : assert(title != null); + const MenuTile({required this.title, this.onTap}) : assert(title != null); @override Widget build(BuildContext context) { diff --git a/lib/ui/tiles/pending_friend_tile.dart b/lib/ui/tiles/pending_friend_tile.dart index f17d100..d696414 100644 --- a/lib/ui/tiles/pending_friend_tile.dart +++ b/lib/ui/tiles/pending_friend_tile.dart @@ -16,10 +16,10 @@ class PendingFriendTile extends StatelessWidget { final RespondFriendshipRequestCallback onRespond; const PendingFriendTile( - {Key key, - @required this.friend, - @required this.user, - @required this.onRespond}) + {Key? key, + required this.friend, + required this.user, + required this.onRespond}) : assert(friend != null), assert(user != null), assert(onRespond != null), @@ -41,7 +41,7 @@ class PendingFriendTile extends StatelessWidget { children: [ ElevatedButton( child: Text( - tr("Accept").toUpperCase(), + tr("Accept")!.toUpperCase(), style: TextStyle(color: Colors.white), ), style: ButtonStyle( @@ -53,7 +53,7 @@ class PendingFriendTile extends StatelessWidget { ), ElevatedButton( child: Text( - tr("Reject").toUpperCase(), + tr("Reject")!.toUpperCase(), style: TextStyle(color: Colors.white), ), style: ButtonStyle( diff --git a/lib/ui/tiles/post_tile.dart b/lib/ui/tiles/post_tile.dart index 04b5565..20928c5 100644 --- a/lib/ui/tiles/post_tile.dart +++ b/lib/ui/tiles/post_tile.dart @@ -52,13 +52,13 @@ class PostTile extends StatefulWidget { final bool userNamesClickable; const PostTile({ - Key key, - @required this.post, - @required this.usersInfo, - @required this.onDeletedPost, - @required this.showPostTarget, - @required this.groupsInfo, - @required this.userNamesClickable, + Key? key, + required this.post, + required this.usersInfo, + required this.onDeletedPost, + required this.showPostTarget, + required this.groupsInfo, + required this.userNamesClickable, }) : assert(post != null), assert(usersInfo != null), assert(onDeletedPost != null), @@ -78,7 +78,7 @@ class _PostTileState extends State { // Class members TextEditingController _commentController = TextEditingController(); - BytesFile _commentImage; + BytesFile? _commentImage; bool _submitting = false; int _maxNumberOfCommentToShow = 10; @@ -99,7 +99,7 @@ class _PostTileState extends State { return " > " + (widget.post.isGroupPost - ? widget.groupsInfo[widget.post.groupID].displayName + ? widget.groupsInfo[widget.post.groupID]!.displayName : widget.usersInfo.getUser(widget.post.userPageID).displayName); } @@ -114,7 +114,7 @@ class _PostTileState extends State { child: AccountImageWidget(user: _user), onTap: widget.userNamesClickable ? () => openUserPage( - userID: _user.id, + userID: _user.id!, context: context, ) : null, @@ -130,7 +130,7 @@ class _PostTileState extends State { _user.displayName + _getPostTarget(), style: _userNameStyle, ), - Text(diffTimeFromNowToStr(widget.post.timeSent)), + Text(diffTimeFromNowToStr(widget.post.timeSent)!), ], ), ), @@ -147,14 +147,14 @@ class _PostTileState extends State { itemBuilder: (c) => [ // Update post content PopupMenuItem( - child: Text(tr("Update content")), + child: Text(tr("Update content")!), value: _PostActions.UPDATE_CONTENT, enabled: widget.post.canUpdate, ), // Delete post PopupMenuItem( - child: Text(tr("Delete")), + child: Text(tr("Delete")!), value: _PostActions.DELETE, enabled: widget.post.canDelete, ), @@ -166,7 +166,7 @@ class _PostTileState extends State { } Widget _buildContentRow() { - Widget postContent; + Widget? postContent; switch (widget.post.kind) { case PostKind.IMAGE: postContent = _buildPostImage(); @@ -258,7 +258,7 @@ class _PostTileState extends State { Widget _buildPostImage() { return NetworkImageWidget( - url: widget.post.fileURL, + url: widget.post.fileURL!, allowFullScreen: true, roundedEdges: false, loadingHeight: 150, @@ -273,11 +273,11 @@ class _PostTileState extends State { mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.ondemand_video), - Text(tr("YouTube movie")) + Text(tr("YouTube movie")!) ], ), onPressed: () => - launch("https://youtube.com/watch/?v=" + widget.post.filePath), + launch("https://youtube.com/watch/?v=" + widget.post.filePath!), ); } @@ -286,14 +286,14 @@ class _PostTileState extends State { color: darkTheme() ? darkerAccentColor : Color.fromRGBO(0xf7, 0xf7, 0xf7, 1), child: InkWell( - onTap: () => launch(widget.post.linkURL), + onTap: () => launch(widget.post.linkURL!), child: Row( children: [ Padding( padding: const EdgeInsets.only(right: 8.0), child: widget.post.hasLinkImage ? NetworkImageWidget( - url: widget.post.linkImage, + url: widget.post.linkImage!, width: 70, roundedEdges: false, ) @@ -309,7 +309,7 @@ class _PostTileState extends State { Text(htmlDecodeCharacters(widget.post.linkTitle), style: TextStyle(fontSize: 20.0)), Text( - widget.post.linkURL, + widget.post.linkURL!, maxLines: 3, ), Text(htmlDecodeCharacters(widget.post.linkDescription)) @@ -325,24 +325,24 @@ class _PostTileState extends State { Widget _buildPostPDF() { return ElevatedButton.icon( onPressed: () { - launch(widget.post.fileURL); + launch(widget.post.fileURL!); }, icon: Icon(Icons.picture_as_pdf), - label: Text(tr("PDF")), + label: Text(tr("PDF")!), ); } Widget _buildCountDownTimer() { return CountdownWidget( startTime: widget.post.timeSent, - endTime: widget.post.timeEnd, + endTime: widget.post.timeEnd!, ); } /// Build post survey Widget _buildPostSurvey() { return SurveyWidget( - survey: widget.post.survey, + survey: widget.post.survey!, onUpdated: (s) => setState(() => widget.post.survey = s), ); } @@ -352,11 +352,11 @@ class _PostTileState extends State { assert(widget.post.hasComments); final comments = List.generate( - min(widget.post.comments.length, _maxNumberOfCommentToShow), + min(widget.post.comments!.length, _maxNumberOfCommentToShow), (num) { final index = num + - max(0, widget.post.comments.length - _maxNumberOfCommentToShow); - final comment = widget.post.comments[index]; + max(0, widget.post.comments!.length - _maxNumberOfCommentToShow); + final comment = widget.post.comments![index as int]; return CommentTile( comment: comment, user: widget.usersInfo.getUser(comment.userID), @@ -374,7 +374,7 @@ class _PostTileState extends State { child: Padding( padding: const EdgeInsets.only(top: 8.0, bottom: 8.0), child: Column( - children: (widget.post.comments.length > _maxNumberOfCommentToShow + children: (widget.post.comments!.length > _maxNumberOfCommentToShow ? [_buildShowMoreCommentsButton()] : []) ..addAll(comments), @@ -389,7 +389,7 @@ class _PostTileState extends State { onTap: () => setState(() => _maxNumberOfCommentToShow += 10), child: Padding( padding: const EdgeInsets.all(8.0), - child: Text(tr("Show more comments").toUpperCase()), + child: Text(tr("Show more comments")!.toUpperCase()), ), ), ); @@ -400,7 +400,7 @@ class _PostTileState extends State { padding: EdgeInsets.only( left: 8.0, right: 8.0, - top: (widget.post.comments.length > 0 ? 8.0 : 0)), + top: (widget.post.comments!.length > 0 ? 8.0 : 0)), child: Row( children: [ // Comment input @@ -502,7 +502,7 @@ class _PostTileState extends State { }); } catch (e, s) { logError(e, s); - snack(context, tr("Failed to choose an image!")); + snack(context, tr("Failed to choose an image!")!); } } @@ -515,7 +515,7 @@ class _PostTileState extends State { postID: widget.post.id, content: _commentController.text, image: _commentImage, - )); + )) ; _sendingComment = false; @@ -524,7 +524,7 @@ class _PostTileState extends State { clearCommentForm(); } catch (e) { print(e); - showSimpleSnack(context, tr("Could not create comment!")); + showSimpleSnack(context, tr("Could not create comment!")!); } } @@ -532,14 +532,14 @@ class _PostTileState extends State { Future _updateCommentContent(Comment comment) async { final newContent = await askUserString( context: context, - title: tr("Update comment content"), - message: tr("New content:"), - defaultValue: comment.content.isNull ? "" : comment.content.content, - hint: tr("New content..."), + title: tr("Update comment content")!, + message: tr("New content:")!, + defaultValue: comment.content.isNull ? "" : comment.content.content!, + hint: tr("New content...")!, ); if (!(await _commentsHelper.updateContent(comment.id, newContent))) - return showSimpleSnack(context, tr("Could not update comment content!")); + return showSimpleSnack(context, tr("Could not update comment content!")!); } /// Process the deletion of a user @@ -550,7 +550,7 @@ class _PostTileState extends State { title: tr("Delete comment"))) return; if (!await _commentsHelper.delete(comment.id)) { - showSimpleSnack(context, tr("Could not delete the comment!")); + showSimpleSnack(context, tr("Could not delete the comment!")!); return; } } @@ -582,7 +582,7 @@ class _PostTileState extends State { // Update post visibility if (!await _postsHelper.setVisibility(widget.post.id, newLevel)) { - showSimpleSnack(context, tr("Could not update post visibility!")); + showSimpleSnack(context, tr("Could not update post visibility!")!); return; } @@ -593,17 +593,17 @@ class _PostTileState extends State { Future updateContent() async { final newContent = await askUserString( context: context, - title: tr("Update post content"), - message: tr("Please enter message content: "), + title: tr("Update post content")!, + message: tr("Please enter message content: ")!, defaultValue: - widget.post.content.isNull ? "" : widget.post.content.content, - hint: tr("Post content"), + widget.post.content.isNull ? "" : widget.post.content.content!, + hint: tr("Post content")!, ); if (newContent == null) return; if (!await _postsHelper.updateContent(widget.post.id, newContent)) { - showSimpleSnack(context, tr("Could not update post content!")); + showSimpleSnack(context, tr("Could not update post content!")!); return; } @@ -620,7 +620,7 @@ class _PostTileState extends State { )) return; if (!await _postsHelper.delete(widget.post.id)) { - showSimpleSnack(context, tr("Could not delete the post!")); + showSimpleSnack(context, tr("Could not delete the post!")!); return; } diff --git a/lib/ui/tiles/post_visibility_level_tile.dart b/lib/ui/tiles/post_visibility_level_tile.dart index 95d195b..b193a73 100644 --- a/lib/ui/tiles/post_visibility_level_tile.dart +++ b/lib/ui/tiles/post_visibility_level_tile.dart @@ -12,10 +12,10 @@ class PostVisibilityLevelTile extends StatelessWidget { final bool visible; const PostVisibilityLevelTile({ - Key key, - @required this.level, - @required this.title, - @required this.onSelect, + Key? key, + required this.level, + required this.title, + required this.onSelect, this.visible = true, }) : assert(level != null), assert(title != null), diff --git a/lib/ui/tiles/server_conversation_message_tile.dart b/lib/ui/tiles/server_conversation_message_tile.dart index 0fc44ea..b6ba017 100644 --- a/lib/ui/tiles/server_conversation_message_tile.dart +++ b/lib/ui/tiles/server_conversation_message_tile.dart @@ -11,9 +11,9 @@ class ServerConversationMessageTile extends StatelessWidget { final UsersList users; const ServerConversationMessageTile({ - Key key, - @required this.message, - @required this.users, + Key? key, + required this.message, + required this.users, }) : assert(message != null), assert(users != null), super(key: key); @@ -22,7 +22,7 @@ class ServerConversationMessageTile extends StatelessWidget { Widget build(BuildContext context) { return Center( child: Text( - message.getText(users), + message.getText(users)!, style: TextStyle( fontStyle: FontStyle.italic, fontSize: 12, diff --git a/lib/ui/tiles/simple_user_tile.dart b/lib/ui/tiles/simple_user_tile.dart index e694bb3..8e1440d 100644 --- a/lib/ui/tiles/simple_user_tile.dart +++ b/lib/ui/tiles/simple_user_tile.dart @@ -12,13 +12,13 @@ typedef OnUserTap = void Function(User); class SimpleUserTile extends StatelessWidget { final User user; - final OnUserTap onTap; - final Widget trailing; - final String subtitle; + final OnUserTap? onTap; + final Widget? trailing; + final String? subtitle; const SimpleUserTile({ - Key key, - this.user, + Key? key, + required this.user, this.onTap, this.trailing, this.subtitle, @@ -28,12 +28,12 @@ class SimpleUserTile extends StatelessWidget { @override Widget build(BuildContext context) { return ListTile( - onTap: onTap == null ? null : () => onTap(user), + onTap: onTap == null ? null : () => onTap!(user), leading: AccountImageWidget( user: user, ), title: Text(user.fullName), - subtitle: subtitle == null ? null : Text(subtitle), + subtitle: subtitle == null ? null : Text(subtitle!), trailing: trailing, ); } diff --git a/lib/ui/widgets/FrienshipStatusWidget.dart b/lib/ui/widgets/FrienshipStatusWidget.dart index c14402d..767115f 100644 --- a/lib/ui/widgets/FrienshipStatusWidget.dart +++ b/lib/ui/widgets/FrienshipStatusWidget.dart @@ -15,9 +15,9 @@ class FriendshipStatusWidget extends StatefulWidget { final void Function() onFriendshipUpdated; const FriendshipStatusWidget({ - Key key, - @required this.status, - @required this.onFriendshipUpdated, + Key? key, + required this.status, + required this.onFriendshipUpdated, }) : assert(status != null), assert(onFriendshipUpdated != null), super(key: key); @@ -48,7 +48,7 @@ class _FriendshipStatusWidgetState extends State { // No request sent yet if (widget.status.noRequestExchanged) { return ElevatedButton( - child: Text(tr("Send request").toUpperCase()), + child: Text(tr("Send request")!.toUpperCase()), onPressed: () => executeRequest(() => _friendsHelper.sendRequest(friendID)), ); @@ -58,7 +58,7 @@ class _FriendshipStatusWidgetState extends State { if (widget.status.sentRequest) { return ElevatedButton( child: Text( - tr("Cancel request").toUpperCase(), + tr("Cancel request")!.toUpperCase(), style: WhiteTextColorStyle, ), style: @@ -74,7 +74,7 @@ class _FriendshipStatusWidgetState extends State { children: [ ElevatedButton( child: Text( - tr("Accept request").toUpperCase(), + tr("Accept request")!.toUpperCase(), style: WhiteTextColorStyle, ), style: ButtonStyle( @@ -84,7 +84,7 @@ class _FriendshipStatusWidgetState extends State { ), ElevatedButton( child: Text( - tr("Reject request").toUpperCase(), + tr("Reject request")!.toUpperCase(), style: WhiteTextColorStyle, ), style: ButtonStyle( @@ -98,7 +98,7 @@ class _FriendshipStatusWidgetState extends State { // The two users are friends, offers to follow him return ElevatedButton( - child: Text((widget.status.following ? tr("Following") : tr("Follow")) + child: Text((widget.status.following ? tr("Following") : tr("Follow"))! .toUpperCase()), onPressed: () => executeRequest(() => _friendsHelper.setFollowing(friendID, !widget.status.following)), @@ -110,7 +110,7 @@ class _FriendshipStatusWidgetState extends State { setSentRequest(true); if (!await func()) - showSimpleSnack(context, tr("Could not update your membership!")); + showSimpleSnack(context, tr("Could not update your membership!")!); widget.onFriendshipUpdated(); } diff --git a/lib/ui/widgets/account_image_widget.dart b/lib/ui/widgets/account_image_widget.dart index 827d53d..8c8c68e 100644 --- a/lib/ui/widgets/account_image_widget.dart +++ b/lib/ui/widgets/account_image_widget.dart @@ -13,8 +13,8 @@ class AccountImageWidget extends StatelessWidget { final double width; const AccountImageWidget({ - Key key, - this.user, + Key? key, + required this.user, this.width = 35.0, }) : assert(user != null), super(key: key); @@ -23,7 +23,7 @@ class AccountImageWidget extends StatelessWidget { Widget build(BuildContext context) { return Material( child: CachedNetworkImage( - imageUrl: user.accountImageURL, + imageUrl: user.accountImageURL!, width: width, height: width, fit: BoxFit.cover, diff --git a/lib/ui/widgets/async_screen_widget.dart b/lib/ui/widgets/async_screen_widget.dart index d32672f..fa9888d 100644 --- a/lib/ui/widgets/async_screen_widget.dart +++ b/lib/ui/widgets/async_screen_widget.dart @@ -31,18 +31,18 @@ class AsyncScreenWidget extends StatefulWidget { /// Widget to use while we are refreshing /// /// This widget is optional - final Widget loadingWidget; + final Widget? loadingWidget; /// Widget to use in case of error /// /// This widget is optional - final Widget errorWidget; + final Widget? errorWidget; const AsyncScreenWidget({ - Key key, - @required this.onReload, - @required this.onBuild, - @required this.errorMessage, + Key? key, + required this.onReload, + required this.onBuild, + required this.errorMessage, this.showOldDataWhileUpdating = false, this.loadingWidget, this.errorWidget, @@ -76,7 +76,7 @@ class AsyncScreenWidgetState extends SafeState { MaterialButton( textColor: Colors.white, onPressed: () => refresh(), - child: Text(tr("Try again").toUpperCase()), + child: Text(tr("Try again")!.toUpperCase()), ) ]); diff --git a/lib/ui/widgets/banner_widget.dart b/lib/ui/widgets/banner_widget.dart index 4351801..751e09f 100644 --- a/lib/ui/widgets/banner_widget.dart +++ b/lib/ui/widgets/banner_widget.dart @@ -10,14 +10,14 @@ import 'package:url_launcher/url_launcher.dart'; bool _bannerDismissed = false; class BannerWidget extends StatefulWidget { - const BannerWidget({Key key}) : super(key: key); + const BannerWidget({Key? key}) : super(key: key); @override _BannerWidgetState createState() => _BannerWidgetState(); } class _BannerWidgetState extends State { - Timer _timer; + Timer? _timer; bool get _shouldShowBanner => showBanner && !_bannerDismissed; @@ -26,22 +26,22 @@ class _BannerWidgetState extends State { } void _openLink() { - launch(srvConfig.banner.link); + launch(srvConfig!.banner!.link!); } @override void initState() { super.initState(); - if (_shouldShowBanner && srvConfig.banner.expire != null) { + if (_shouldShowBanner && srvConfig!.banner!.expire != null) { _timer = Timer( - Duration(seconds: srvConfig.banner.expire - time()), _hideBanner); + Duration(seconds: srvConfig!.banner!.expire! - time()), _hideBanner); } } @override void dispose() { - if (_timer != null) _timer.cancel(); + if (_timer != null) _timer!.cancel(); super.dispose(); } @@ -49,7 +49,7 @@ class _BannerWidgetState extends State { Widget build(BuildContext context) { if (!_shouldShowBanner) return Container(); - final banner = srvConfig.banner; + final banner = srvConfig!.banner!; return Card( color: banner.nature == BannerNature.Information ? Colors.blue @@ -72,8 +72,8 @@ class _BannerWidgetState extends State { Expanded( child: Text( banner.message.containsKey(shortLang) - ? banner.message[shortLang] - : banner.message["en"], + ? banner.message[shortLang]! + : banner.message["en"]!, style: TextStyle(color: Colors.white), ), ), @@ -95,16 +95,16 @@ class _BannerWidgetState extends State { } class BannerButton extends StatelessWidget { - final Function() onPressed; - final Widget icon; + final Function()? onPressed; + final Widget? icon; - const BannerButton({this.onPressed, this.icon, Key key}) : super(key: key); + const BannerButton({this.onPressed, this.icon, Key? key}) : super(key: key); @override Widget build(BuildContext context) { return IconButton( onPressed: onPressed, - icon: icon, + icon: icon!, color: Colors.white, disabledColor: Colors.white, padding: EdgeInsets.all(1.0), diff --git a/lib/ui/widgets/conversation_file_tile.dart b/lib/ui/widgets/conversation_file_tile.dart index bfff39e..1d177d3 100644 --- a/lib/ui/widgets/conversation_file_tile.dart +++ b/lib/ui/widgets/conversation_file_tile.dart @@ -19,9 +19,9 @@ class ConversationFileWidget extends StatefulWidget { final ConversationMessageFile file; const ConversationFileWidget({ - Key key, - @required this.messageID, - @required this.file, + Key? key, + required this.messageID, + required this.file, }) : assert(messageID != null), assert(file != null), super(key: key); @@ -44,7 +44,7 @@ class _ConversationFileWidgetState extends State { : Opacity( opacity: 0.8, child: CachedNetworkImage( - imageUrl: file.thumbnail, + imageUrl: file.thumbnail!, width: _AreaWidth, height: _AreaHeight, fit: BoxFit.cover, @@ -64,7 +64,7 @@ class _ConversationFileWidgetState extends State { case ConversationMessageFileType.IMAGE: return Center( child: NetworkImageWidget( - url: file.url, + url: file.url!, thumbnailURL: file.thumbnail, allowFullScreen: true, ), @@ -83,9 +83,9 @@ class _ConversationFileWidgetState extends State { Icon(file.icon, color: Colors.white), Spacer(), Text( - file.name.length < 23 - ? file.name - : file.name.substring(0, 20) + "...", + file.name!.length < 23 + ? file.name! + : file.name!.substring(0, 20) + "...", textAlign: TextAlign.center, style: TextStyle(color: Colors.white), ), @@ -112,15 +112,15 @@ class _ConversationFileWidgetState extends State { break; case ConversationMessageFileType.VIDEO: - MainController.of(context).push( - VideoPlayerRoute(url: file.url), + MainController.of(context)!.push( + VideoPlayerRoute(url: file.url!), hideNavBar: true, canShowAsDialog: true, ); break; default: - launch(file.url); + launch(file.url!); } } } diff --git a/lib/ui/widgets/conversation_image_widget.dart b/lib/ui/widgets/conversation_image_widget.dart index a1433f7..72c1825 100644 --- a/lib/ui/widgets/conversation_image_widget.dart +++ b/lib/ui/widgets/conversation_image_widget.dart @@ -14,13 +14,13 @@ class ConversationImageWidget extends StatelessWidget { final Conversation conversation; final UsersList users; final double size; - final Group group; - final bool noUserImage; + final Group? group; + final bool? noUserImage; const ConversationImageWidget({ - Key key, - @required this.conversation, - @required this.users, + Key? key, + required this.conversation, + required this.users, this.group, this.size = 30, this.noUserImage, @@ -42,26 +42,26 @@ class ConversationImageWidget extends StatelessWidget { Widget _buildIcon() { if (conversation.logoURL != null) return CachedNetworkImage( - imageUrl: conversation.logoURL, + imageUrl: conversation.logoURL!, width: size, ); if (group != null) { return CachedNetworkImage( - imageUrl: group.iconURL, + imageUrl: group!.iconURL, width: size, ); } if (noUserImage == true) return Container(width: size); - if (conversation.members.length < 2) + if (conversation.members!.length < 2) return Icon( Icons.lock, size: size, ); - if (conversation.members.length == 2) + if (conversation.members!.length == 2) return AccountImageWidget( width: size, user: users.getUser(conversation.otherMembersID.first), @@ -80,9 +80,9 @@ class MultipleAccountImagesWidget extends StatelessWidget { final double size; const MultipleAccountImagesWidget({ - Key key, - @required this.users, - @required this.size, + Key? key, + required this.users, + required this.size, }) : assert(users != null), assert(size != null), assert(size > 0), diff --git a/lib/ui/widgets/copy_icon.dart b/lib/ui/widgets/copy_icon.dart index 8501732..d366962 100644 --- a/lib/ui/widgets/copy_icon.dart +++ b/lib/ui/widgets/copy_icon.dart @@ -18,7 +18,7 @@ class CopyIcon extends StatelessWidget { icon: Icon(Icons.content_copy), onPressed: () { FlutterClipboard.copy(value); - snack(context, tr("'%c%' was copied to clipboard", args: {"c": value})); + snack(context, tr("'%c%' was copied to clipboard", args: {"c": value})!); }, ); } diff --git a/lib/ui/widgets/countdown_widget.dart b/lib/ui/widgets/countdown_widget.dart index 1ea8971..dbde1fb 100644 --- a/lib/ui/widgets/countdown_widget.dart +++ b/lib/ui/widgets/countdown_widget.dart @@ -13,9 +13,9 @@ class CountdownWidget extends StatefulWidget { final int endTime; const CountdownWidget({ - Key key, - @required this.startTime, - @required this.endTime, + Key? key, + required this.startTime, + required this.endTime, }) : assert(startTime != null), assert(endTime != null), super(key: key); @@ -29,7 +29,7 @@ class _CountdownWidgetState extends State { int get totalDuration => (widget.endTime - widget.startTime).abs(); - String get remainingTimeStr { + String? get remainingTimeStr { final remaining = Duration(seconds: remainingTime.abs()); return tr( @@ -67,7 +67,7 @@ class _CountdownWidgetState extends State { children: [ Padding( padding: const EdgeInsets.all(8.0), - child: Text(remainingTimeStr), + child: Text(remainingTimeStr!), ), Padding( padding: const EdgeInsets.all(8.0), diff --git a/lib/ui/widgets/create_account_widget.dart b/lib/ui/widgets/create_account_widget.dart index 9c6c753..edc3013 100644 --- a/lib/ui/widgets/create_account_widget.dart +++ b/lib/ui/widgets/create_account_widget.dart @@ -17,7 +17,7 @@ import 'new_password_input_widget.dart'; class CreateAccountWidget extends StatefulWidget { final void Function() onCreated; - const CreateAccountWidget({Key key, @required this.onCreated}) + const CreateAccountWidget({Key? key, required this.onCreated}) : super(key: key); @override @@ -30,28 +30,28 @@ class _CreateAccountWidgetState extends State { final _emailController = TextEditingController(); final _passwordInputKey = GlobalKey(); final _verifyPasswordController = TextEditingController(); - bool _acceptedTOS = false; + bool? _acceptedTOS = false; bool _isCreating = false; - CreateAccountResult _createAccountResult; + CreateAccountResult? _createAccountResult; bool _showErrors = false; bool get _isFirstNameValid => _firstNameController.text.length >= - srvConfig.accountInformationPolicy.minFirstNameLength; + srvConfig!.accountInformationPolicy.minFirstNameLength; bool get _isLastNameValid => _lastNameController.text.length >= - srvConfig.accountInformationPolicy.minLastNameLength; + srvConfig!.accountInformationPolicy.minLastNameLength; bool get _isEmailValid => validateEmail(_emailController.text); - bool get _isPasswordValid => _passwordInputKey.currentState.valid; + bool get _isPasswordValid => _passwordInputKey.currentState!.valid; bool get _isPasswordConfirmationValid => _passwordInputKey.currentState != null && - _passwordInputKey.currentState.value == _verifyPasswordController.text; + _passwordInputKey.currentState!.value == _verifyPasswordController.text; bool get _isFormValid => _isFirstNameValid && @@ -59,9 +59,9 @@ class _CreateAccountWidgetState extends State { _isEmailValid && _isPasswordValid && _isPasswordConfirmationValid && - _acceptedTOS; + _acceptedTOS!; - String get errorMessage => _createAccountResult == + String? get errorMessage => _createAccountResult == CreateAccountResult.ERROR_EXISTING_EMAIL ? tr("An account is already associated to this email address!") : _createAccountResult == CreateAccountResult.ERROR_TOO_MANY_REQUESTS @@ -91,11 +91,11 @@ class _CreateAccountWidgetState extends State { // First name _InputEntry( controller: _firstNameController, - label: tr("First name"), + label: tr("First name")!, onEdited: _updateUI, icon: Icon(Icons.perm_identity), maxLength: - srvConfig.accountInformationPolicy.maxFirstNameLength, + srvConfig!.accountInformationPolicy.maxFirstNameLength, error: _showErrors && !_isFirstNameValid ? tr("Invalid first name!") : null, @@ -104,10 +104,10 @@ class _CreateAccountWidgetState extends State { // Last name _InputEntry( controller: _lastNameController, - label: tr("Last name"), + label: tr("Last name")!, onEdited: _updateUI, icon: Icon(Icons.perm_identity), - maxLength: srvConfig.accountInformationPolicy.maxLastNameLength, + maxLength: srvConfig!.accountInformationPolicy.maxLastNameLength, error: _showErrors && !_isLastNameValid ? tr("Invalid last name!") : null, @@ -116,7 +116,7 @@ class _CreateAccountWidgetState extends State { // Email address _InputEntry( controller: _emailController, - label: tr("Email address"), + label: tr("Email address")!, onEdited: _updateUI, icon: Icon(Icons.email), keyboard: TextInputType.emailAddress, @@ -128,7 +128,7 @@ class _CreateAccountWidgetState extends State { // Password NewPasswordInputWidget( key: _passwordInputKey, - label: tr("Password"), + label: tr("Password")!, onEdited: _updateUI, icon: Icon(Icons.lock), user: UserInfoForPassword( @@ -141,7 +141,7 @@ class _CreateAccountWidgetState extends State { // Verify password _InputEntry( controller: _verifyPasswordController, - label: tr("Confirm your password"), + label: tr("Confirm your password")!, onEdited: _updateUI, icon: Icon(Icons.lock_outline), isPassword: true, @@ -155,15 +155,15 @@ class _CreateAccountWidgetState extends State { // TOS CheckboxListTile( title: - Text(tr("I have read and accepted the Terms Of Service.")), + Text(tr("I have read and accepted the Terms Of Service.")!), value: _acceptedTOS, onChanged: (b) { _acceptedTOS = b; _updateUI(); }, - subtitle: _showErrors && !_acceptedTOS + subtitle: _showErrors && !_acceptedTOS! ? Text( - tr("You must accept the Terms Of Service to continue."), + tr("You must accept the Terms Of Service to continue.")!, style: TextStyle(color: Colors.redAccent), ) : null, @@ -180,7 +180,7 @@ class _CreateAccountWidgetState extends State { Center( child: ElevatedButton( onPressed: _submitForm, - child: Text(tr("Create account")), + child: Text(tr("Create account")!), ), ), ], @@ -211,7 +211,7 @@ class _CreateAccountWidgetState extends State { firstName: _firstNameController.text, lastName: _lastNameController.text, email: _emailController.text, - password: _passwordInputKey.currentState.value, + password: _passwordInputKey.currentState!.value, )); setState(() { @@ -228,17 +228,17 @@ class _CreateAccountWidgetState extends State { widget.onCreated(); } - void _openTOS() => launch(ServerConfigurationHelper.config.termsURL); + void _openTOS() => launch(ServerConfigurationHelper.config!.termsURL); void _showCreateAccountError() async { await showCupertinoDialog( context: context, builder: (c) => CupertinoAlertDialog( - title: Text(tr("Error while creating your account")), - content: Text(errorMessage), + title: Text(tr("Error while creating your account")!), + content: Text(errorMessage!), actions: [ CupertinoButton( - child: Text(tr("Ok").toUpperCase()), + child: Text(tr("Ok")!.toUpperCase()), onPressed: () => Navigator.of(context).pop(), ) ], @@ -252,16 +252,16 @@ class _InputEntry extends StatelessWidget { final String label; final VoidCallback onEdited; final bool isPassword; - final String error; - final Widget icon; - final TextInputType keyboard; - final int maxLength; + final String? error; + final Widget? icon; + final TextInputType? keyboard; + final int? maxLength; const _InputEntry({ - Key key, - @required this.controller, - @required this.label, - @required this.onEdited, + Key? key, + required this.controller, + required this.label, + required this.onEdited, this.isPassword = false, this.error, this.icon, diff --git a/lib/ui/widgets/custom_app_bar_size.dart b/lib/ui/widgets/custom_app_bar_size.dart index 49b3105..65bea8a 100644 --- a/lib/ui/widgets/custom_app_bar_size.dart +++ b/lib/ui/widgets/custom_app_bar_size.dart @@ -9,7 +9,7 @@ class AppBarWrapper extends StatelessWidget implements PreferredSizeWidget { final Widget appBar; final double height; - const AppBarWrapper({@required this.height, @required this.appBar}) + const AppBarWrapper({required this.height, required this.appBar}) : assert(height != null), assert(appBar != null), super(); diff --git a/lib/ui/widgets/custom_list_tile.dart b/lib/ui/widgets/custom_list_tile.dart index 087da54..432a977 100644 --- a/lib/ui/widgets/custom_list_tile.dart +++ b/lib/ui/widgets/custom_list_tile.dart @@ -6,27 +6,27 @@ import 'package:flutter/material.dart'; /// @author Pierre HUBERT class CustomListTile extends StatelessWidget { - final Widget leading; - final Widget title; - final Widget subtitle; - final Widget trailing; + final Widget? leading; + final Widget? title; + final Widget? subtitle; + final Widget? trailing; final bool isThreeLine; - final bool dense; - final EdgeInsetsGeometry contentPadding; + final bool? dense; + final EdgeInsetsGeometry? contentPadding; final bool enabled; - final GestureTapCallback onTap; - final GestureLongPressCallback onLongPress; + final GestureTapCallback? onTap; + final GestureLongPressCallback? onLongPress; final bool selected; - final Color tileColor; + final Color? tileColor; /// Custom onLongPress function - final Function(Size, Offset) onLongPressWithInfo; + final Function(Size, Offset)? onLongPressWithInfo; /// Show menu onLongPress - final Function(RelativeRect) onLongPressOpenMenu; + final Function(RelativeRect)? onLongPressOpenMenu; const CustomListTile({ - Key key, + Key? key, this.leading, this.title, this.subtitle, @@ -66,14 +66,14 @@ class CustomListTile extends StatelessWidget { } void _longPress(BuildContext context) { - if (onLongPress != null) onLongPress(); + if (onLongPress != null) onLongPress!(); if (onLongPressWithInfo != null || onLongPressOpenMenu != null) { - RenderBox renderBox = context.findRenderObject(); + RenderBox renderBox = context.findRenderObject() as RenderBox; final size = renderBox.size; final offset = renderBox.localToGlobal(Offset(size.width, size.height)); - if (onLongPressWithInfo != null) onLongPressWithInfo(size, offset); + if (onLongPressWithInfo != null) onLongPressWithInfo!(size, offset); if (onLongPressOpenMenu != null) { final position = RelativeRect.fromLTRB( @@ -83,7 +83,7 @@ class CustomListTile extends StatelessWidget { offset.dy + size.height, ); - onLongPressOpenMenu(position); + onLongPressOpenMenu!(position); } } } diff --git a/lib/ui/widgets/dialogs/auto_sized_dialog_content_widget.dart b/lib/ui/widgets/dialogs/auto_sized_dialog_content_widget.dart index 53ab723..3893f81 100644 --- a/lib/ui/widgets/dialogs/auto_sized_dialog_content_widget.dart +++ b/lib/ui/widgets/dialogs/auto_sized_dialog_content_widget.dart @@ -7,8 +7,8 @@ class AutoSizeDialogContentWidget extends StatelessWidget { final Widget child; const AutoSizeDialogContentWidget({ - Key key, - @required this.child, + Key? key, + required this.child, }) : super(key: key); @override diff --git a/lib/ui/widgets/dialogs/cancel_dialog_button.dart b/lib/ui/widgets/dialogs/cancel_dialog_button.dart index b174608..de73023 100644 --- a/lib/ui/widgets/dialogs/cancel_dialog_button.dart +++ b/lib/ui/widgets/dialogs/cancel_dialog_button.dart @@ -10,7 +10,7 @@ class CancelDialogButton extends StatelessWidget { Widget build(BuildContext context) { return MaterialButton( onPressed: () => Navigator.of(context).pop(), - child: Text(tr("Cancel").toUpperCase()), + child: Text(tr("Cancel")!.toUpperCase()), textColor: Colors.red, ); } diff --git a/lib/ui/widgets/dialogs/confirm_dialog_button.dart b/lib/ui/widgets/dialogs/confirm_dialog_button.dart index 2ab8ca6..65d1700 100644 --- a/lib/ui/widgets/dialogs/confirm_dialog_button.dart +++ b/lib/ui/widgets/dialogs/confirm_dialog_button.dart @@ -10,9 +10,9 @@ class ConfirmDialogButton extends StatelessWidget { final T value; const ConfirmDialogButton({ - Key key, + Key? key, this.enabled = true, - @required this.value, + required this.value, }) : assert(enabled != null), super(key: key); @@ -20,7 +20,7 @@ class ConfirmDialogButton extends StatelessWidget { Widget build(BuildContext context) { return MaterialButton( onPressed: enabled ? () => Navigator.of(context).pop(value) : null, - child: Text(tr("Confirm").toUpperCase()), + child: Text(tr("Confirm")!.toUpperCase()), textColor: Colors.green, ); } diff --git a/lib/ui/widgets/forez_presence_calendar_widget.dart b/lib/ui/widgets/forez_presence_calendar_widget.dart index 65a7a4e..996c803 100644 --- a/lib/ui/widgets/forez_presence_calendar_widget.dart +++ b/lib/ui/widgets/forez_presence_calendar_widget.dart @@ -11,18 +11,18 @@ import 'package:table_calendar/table_calendar.dart'; enum CalendarDisplayMode { SINGLE_USER, MULTIPLE_USERS } extension DateOnlyCompare on DateTime { - bool isSameDate(DateTime other) => date_utils.isSameDate(this, other); + bool isSameDate(DateTime? other) => date_utils.isSameDate(this, other); } class PresenceCalendarWidget extends StatefulWidget { final PresenceSet presenceSet; - final void Function(DateTime) onDayClicked; + final void Function(DateTime)? onDayClicked; final CalendarDisplayMode mode; - final DateTime selectedDay; + final DateTime? selectedDay; const PresenceCalendarWidget({ - Key key, - @required this.presenceSet, + Key? key, + required this.presenceSet, this.onDayClicked, this.mode = CalendarDisplayMode.SINGLE_USER, this.selectedDay, @@ -35,7 +35,7 @@ class PresenceCalendarWidget extends StatefulWidget { } class _PresenceCalendarWidgetState extends State { - var selectedDay = DateTime.now(); + DateTime? selectedDay = DateTime.now(); @override void didUpdateWidget(covariant PresenceCalendarWidget oldWidget) { @@ -63,7 +63,7 @@ class _PresenceCalendarWidgetState extends State { ), onDaySelected: _selectedDay, availableCalendarFormats: const {CalendarFormat.month: "Mois"}, - focusedDay: selectedDay, + focusedDay: selectedDay!, onPageChanged: (s) { setState(() { selectedDay = s; @@ -129,21 +129,21 @@ class _PresenceCalendarWidgetState extends State { } void _selectedDay(DateTime selecteDay, DateTime focusedDay) { - if (widget.onDayClicked != null) widget.onDayClicked(selecteDay); + if (widget.onDayClicked != null) widget.onDayClicked!(selecteDay); setState(() {}); } } class CellWidget extends StatelessWidget { final String text; - final Color color; - final Color textColor; + final Color? color; + final Color? textColor; final bool circle; - final bool selected; + final bool? selected; const CellWidget({ - Key key, - @required this.text, + Key? key, + required this.text, this.color, this.textColor, this.circle = true, diff --git a/lib/ui/widgets/group_following_widget.dart b/lib/ui/widgets/group_following_widget.dart index a3a0b4b..629b851 100644 --- a/lib/ui/widgets/group_following_widget.dart +++ b/lib/ui/widgets/group_following_widget.dart @@ -12,13 +12,13 @@ import 'package:flutter/material.dart'; class GroupFollowingWidget extends StatefulWidget { final Group group; final Function() onUpdated; - final Color inactiveColor; - final Color activeColor; + final Color? inactiveColor; + final Color? activeColor; const GroupFollowingWidget({ - Key key, - @required this.group, - @required this.onUpdated, + Key? key, + required this.group, + required this.onUpdated, this.activeColor, this.inactiveColor, }) : assert(group != null), @@ -46,7 +46,7 @@ class _GroupFollowingWidgetState extends SafeState { color: _group.following ? widget.activeColor : widget.inactiveColor, )), TextSpan( - text: " " + (_group.following ? tr("Following") : tr("Follow"))), + text: " " + (_group.following ? tr("Following")! : tr("Follow")!)), ]), ), onTap: () => _toggleFollowing(), @@ -56,7 +56,7 @@ class _GroupFollowingWidgetState extends SafeState { /// Toggle following status void _toggleFollowing() async { if (!await GroupsHelper().setFollowing(_group.id, !_group.following)) { - showSimpleSnack(context, tr("Could not update following status!")); + showSimpleSnack(context, tr("Could not update following status!")!); return; } diff --git a/lib/ui/widgets/group_icon_widget.dart b/lib/ui/widgets/group_icon_widget.dart index 43c4d63..bbc84e5 100644 --- a/lib/ui/widgets/group_icon_widget.dart +++ b/lib/ui/widgets/group_icon_widget.dart @@ -10,8 +10,8 @@ class GroupIcon extends StatelessWidget { final double width; const GroupIcon({ - Key key, - @required this.group, + Key? key, + required this.group, this.width = 50, }) : assert(group != null), assert(width != null), diff --git a/lib/ui/widgets/group_membership_widget.dart b/lib/ui/widgets/group_membership_widget.dart index 794fe9e..58c8ad6 100644 --- a/lib/ui/widgets/group_membership_widget.dart +++ b/lib/ui/widgets/group_membership_widget.dart @@ -12,11 +12,11 @@ import 'package:flutter/material.dart'; class GroupMembershipWidget extends StatefulWidget { final Group group; - final Function() onUpdated; - final Function() onError; + final Function()? onUpdated; + final Function()? onError; const GroupMembershipWidget( - {@required this.group, this.onUpdated, this.onError}) + {required this.group, this.onUpdated, this.onError}) : assert(group != null); @override @@ -34,13 +34,13 @@ class _GroupMembershipWidgetState extends SafeState { Widget build(BuildContext context) { switch (_level) { case GroupMembershipLevel.ADMINISTRATOR: - return Text(tr("Administrator")); + return Text(tr("Administrator")!); case GroupMembershipLevel.MODERATOR: - return Text(tr("Moderator")); + return Text(tr("Moderator")!); case GroupMembershipLevel.MEMBER: - return Text(tr("Member")); + return Text(tr("Member")!); case GroupMembershipLevel.INVITED: return _buildInvitedState(); @@ -63,7 +63,7 @@ class _GroupMembershipWidgetState extends SafeState { WidgetSpan( child: Icon(Icons.info_outline, size: 12), alignment: PlaceholderAlignment.middle), - TextSpan(text: " " + tr("Invited") + " ", style: blackForWhiteTheme()), + TextSpan(text: " " + tr("Invited")! + " ", style: blackForWhiteTheme()), TextSpan( text: tr("Accept"), style: TextStyle(color: Colors.green), @@ -88,15 +88,15 @@ class _GroupMembershipWidgetState extends SafeState { return; if (!await GroupsHelper.respondInvitation(_id, accept)) { - showSimpleSnack(context, tr("Could not respond to your invitation!")); - if (this.widget.onError != null) this.widget.onError(); + showSimpleSnack(context, tr("Could not respond to your invitation!")!); + if (this.widget.onError != null) this.widget.onError!(); } else { // Refresh state group.membershipLevel = accept ? GroupMembershipLevel.MEMBER : GroupMembershipLevel.VISITOR; this.setState(() {}); - if (this.widget.onUpdated != null) this.widget.onUpdated(); + if (this.widget.onUpdated != null) this.widget.onUpdated!(); } } @@ -108,7 +108,7 @@ class _GroupMembershipWidgetState extends SafeState { child: Icon(Icons.access_time, size: 12), alignment: PlaceholderAlignment.middle), TextSpan( - text: " " + tr("Requested") + " ", style: blackForWhiteTheme()), + text: " " + tr("Requested")! + " ", style: blackForWhiteTheme()), TextSpan( text: tr("Cancel"), style: TextStyle(color: Colors.blue), @@ -120,14 +120,14 @@ class _GroupMembershipWidgetState extends SafeState { /// Cancel group membership request void _cancelRequest() async { if (!await GroupsHelper().cancelRequest(_id)) { - showSimpleSnack(context, tr("Could not cancel your membership request!")); - if (this.widget.onError != null) this.widget.onError(); + showSimpleSnack(context, tr("Could not cancel your membership request!")!); + if (this.widget.onError != null) this.widget.onError!(); } else { // Refresh state group.membershipLevel = GroupMembershipLevel.VISITOR; this.setState(() {}); - if (this.widget.onUpdated != null) this.widget.onUpdated(); + if (this.widget.onUpdated != null) this.widget.onUpdated!(); } } @@ -135,7 +135,7 @@ class _GroupMembershipWidgetState extends SafeState { Widget _buildVisitorState() { // Check if the user can request membership if (group.registrationLevel == GroupRegistrationLevel.CLOSED) - return Text(tr("Closed registration")); + return Text(tr("Closed registration")!); return RichText( text: TextSpan( @@ -149,14 +149,14 @@ class _GroupMembershipWidgetState extends SafeState { /// Create new membership request void _requestMembership() async { if (!await GroupsHelper.sendRequest(_id)) { - showSimpleSnack(context, tr("Could not send your membership request!")); - if (this.widget.onError != null) this.widget.onError(); + showSimpleSnack(context, tr("Could not send your membership request!")!); + if (this.widget.onError != null) this.widget.onError!(); } else { // Refresh state group.membershipLevel = GroupMembershipLevel.PENDING; this.setState(() {}); - if (this.widget.onUpdated != null) this.widget.onUpdated(); + if (this.widget.onUpdated != null) this.widget.onUpdated!(); } } } diff --git a/lib/ui/widgets/icon_button_badge.dart b/lib/ui/widgets/icon_button_badge.dart index 1f8ff85..76888d8 100644 --- a/lib/ui/widgets/icon_button_badge.dart +++ b/lib/ui/widgets/icon_button_badge.dart @@ -13,9 +13,9 @@ class IconButtonWithBadge extends StatelessWidget { final bool active; const IconButtonWithBadge({ - Key key, - @required this.icon, - @required this.onPressed, + Key? key, + required this.icon, + required this.onPressed, this.number = 0, this.active = false, }) : assert(icon != null), diff --git a/lib/ui/widgets/init_widget.dart b/lib/ui/widgets/init_widget.dart index 3c7fd12..01f625f 100644 --- a/lib/ui/widgets/init_widget.dart +++ b/lib/ui/widgets/init_widget.dart @@ -69,7 +69,7 @@ class _InitializeWidgetState extends SafeState { await ServerConfigurationHelper.ensureLoaded(); if (!isWeb && - ServerConfigurationHelper.config.minSupportedMobileVersion > + ServerConfigurationHelper.config!.minSupportedMobileVersion > VersionHelper.version) await showDeprecationDialog(context); if (!AccountHelper.isUserIDLoaded) { @@ -91,7 +91,7 @@ class _InitializeWidgetState extends SafeState { print("Attempting WebSocket connection..."); if (config().additionalLoading != null) - await config().additionalLoading(); + await config().additionalLoading!(); await WebSocketHelper.connect(); @@ -113,7 +113,7 @@ class _InitializeWidgetState extends SafeState { if (_error || !WebSocketHelper.isConnected()) return _buildNonReadyWidget(); if (config().mainRouteBuilder != null) - return config().mainRouteBuilder(context, mainControllerKey); + return config().mainRouteBuilder!(context, mainControllerKey); return isTablet(context) ? TabletRoute(key: mainControllerKey) @@ -149,9 +149,9 @@ class _InitializeWidgetState extends SafeState { ), !isWeb ? Text(tr("Version %version% - Build %build%", args: { - "version": VersionHelper.info.version.toString(), - "build": VersionHelper.info.buildNumber.toString() - })) + "version": VersionHelper.info!.version.toString(), + "build": VersionHelper.info!.buildNumber.toString() + })!) : Container(), Spacer(flex: 1), ], @@ -171,13 +171,13 @@ class _InitializeWidgetState extends SafeState { children: [ Icon(Icons.error, color: Colors.white), SizedBox(height: 30), - Text(tr("Could not connect to server!")), + Text(tr("Could not connect to server!")!), SizedBox( height: 30, ), ElevatedButton( onPressed: () => _tryConnect(), - child: Text(tr("Try again")), + child: Text(tr("Try again")!), ), ], ); @@ -186,6 +186,6 @@ class _InitializeWidgetState extends SafeState { void _popToMainRoute() { // Pop until we reach main route Navigator.of(context).popUntil((settings) => - ModalRoute.of(context).isCurrent || !ModalRoute.of(context).isActive); + ModalRoute.of(context)!.isCurrent || !ModalRoute.of(context)!.isActive); } } diff --git a/lib/ui/widgets/like_widget.dart b/lib/ui/widgets/like_widget.dart index 5a3f974..e73d98c 100644 --- a/lib/ui/widgets/like_widget.dart +++ b/lib/ui/widgets/like_widget.dart @@ -15,13 +15,13 @@ typedef UpdatedLikingCallBack = Function(int, bool); class LikeWidget extends StatefulWidget { final LikeElement likeElement; - final double buttonIconSize; - final Color activeColor; - final Color inativeColor; + final double? buttonIconSize; + final Color? activeColor; + final Color? inativeColor; const LikeWidget( - {Key key, - @required this.likeElement, + {Key? key, + required this.likeElement, this.buttonIconSize = 15.0, this.activeColor, this.inativeColor}) @@ -35,7 +35,7 @@ class LikeWidget extends StatefulWidget { class _LikeWidgetState extends SafeState { LikeElement get elem => widget.likeElement; - String get _likeString { + String? get _likeString { switch (elem.likes) { case 0: return tr("Like"); @@ -66,7 +66,7 @@ class _LikeWidgetState extends SafeState { SizedBox( width: 8.0, ), - Text(_likeString), + Text(_likeString!), ], ), ), diff --git a/lib/ui/widgets/login_route_container.dart b/lib/ui/widgets/login_route_container.dart index d634cb2..6579cbf 100644 --- a/lib/ui/widgets/login_route_container.dart +++ b/lib/ui/widgets/login_route_container.dart @@ -12,14 +12,14 @@ import 'package:flutter/material.dart'; class LoginRouteContainer extends StatelessWidget { final Widget child; - const LoginRouteContainer({Key key, @required this.child}) : super(key: key); + const LoginRouteContainer({Key? key, required this.child}) : super(key: key); @override Widget build(BuildContext context) { if (!isTablet(context)) return LoginRoutesTheme(child: child); return Container( - color: Config.get().splashBackgroundColor, + color: Config.get()!.splashBackgroundColor, child: Padding( padding: EdgeInsets.only(top: 10), child: Center( diff --git a/lib/ui/widgets/login_routes_theme.dart b/lib/ui/widgets/login_routes_theme.dart index 6593075..296d419 100644 --- a/lib/ui/widgets/login_routes_theme.dart +++ b/lib/ui/widgets/login_routes_theme.dart @@ -8,12 +8,12 @@ import 'package:flutter/material.dart'; class LoginRoutesTheme extends StatelessWidget { final Widget child; - const LoginRoutesTheme({Key key, @required this.child}) : super(key: key); + const LoginRoutesTheme({Key? key, required this.child}) : super(key: key); @override Widget build(BuildContext context) => Theme( data: Theme.of(context).copyWith( - scaffoldBackgroundColor: Config.get().splashBackgroundColor, + scaffoldBackgroundColor: Config.get()!.splashBackgroundColor, appBarTheme: AppBarTheme( backgroundColor: Colors.transparent, elevation: 0, @@ -30,9 +30,9 @@ class LoginRoutesTheme extends StatelessWidget { checkboxTheme: CheckboxThemeData( fillColor: MaterialStateProperty.all(Colors.white), checkColor: - MaterialStateProperty.all(Config.get().splashBackgroundColor), + MaterialStateProperty.all(Config.get()!.splashBackgroundColor), ), - dialogBackgroundColor: Config.get().splashBackgroundColor, + dialogBackgroundColor: Config.get()!.splashBackgroundColor, dialogTheme: DialogTheme( contentTextStyle: TextStyle( color: Colors.white, @@ -40,7 +40,7 @@ class LoginRoutesTheme extends StatelessWidget { ), buttonTheme: ButtonThemeData(buttonColor: Colors.white), primaryColor: Colors.white, - backgroundColor: Config.get().splashBackgroundColor, + backgroundColor: Config.get()!.splashBackgroundColor, disabledColor: Colors.grey, highlightColor: Colors.white12, hintColor: Colors.white, @@ -51,11 +51,11 @@ class LoginRoutesTheme extends StatelessWidget { colorScheme: ColorScheme( primary: Colors.white, secondary: Colors.white, - surface: Config.get().splashBackgroundColor, - background: Config.get().splashBackgroundColor, + surface: Config.get()!.splashBackgroundColor, + background: Config.get()!.splashBackgroundColor, error: Colors.redAccent, - onPrimary: Config.get().splashBackgroundColor, - onSecondary: Config.get().splashBackgroundColor, + onPrimary: Config.get()!.splashBackgroundColor, + onSecondary: Config.get()!.splashBackgroundColor, onSurface: Colors.white, onBackground: Colors.white, onError: Colors.redAccent, diff --git a/lib/ui/widgets/login_scaffold.dart b/lib/ui/widgets/login_scaffold.dart index c7751e4..9622261 100644 --- a/lib/ui/widgets/login_scaffold.dart +++ b/lib/ui/widgets/login_scaffold.dart @@ -8,10 +8,10 @@ import 'package:flutter/material.dart'; /// @author Pierre Hubert class LoginScaffold extends StatelessWidget { - final Widget child; - final Widget noStyleChild; + final Widget? child; + final Widget? noStyleChild; - const LoginScaffold({Key key, @required this.child, this.noStyleChild}) + const LoginScaffold({Key? key, required this.child, this.noStyleChild}) : assert(child != null || noStyleChild != null), super(key: key); @@ -37,7 +37,7 @@ class LoginScaffold extends StatelessWidget { fillColor: Colors.white, hoverColor: Colors.white, ), - scaffoldBackgroundColor: Config.get().splashBackgroundColor, + scaffoldBackgroundColor: Config.get()!.splashBackgroundColor, textTheme: TextTheme( bodyText2: TextStyle(color: Colors.white), button: TextStyle(color: Colors.white), @@ -64,7 +64,7 @@ class LoginScaffold extends StatelessWidget { Spacer(flex: 1), Text( tr(config().appQuickDescription ?? - tr("Free social network that respect your privacy")), + tr("Free social network that respect your privacy"))!, textAlign: TextAlign.center, ), Spacer(flex: 3), diff --git a/lib/ui/widgets/login_widget.dart b/lib/ui/widgets/login_widget.dart index a25d824..74e9ea7 100644 --- a/lib/ui/widgets/login_widget.dart +++ b/lib/ui/widgets/login_widget.dart @@ -14,7 +14,7 @@ import 'package:flutter/material.dart'; class LoginWidget extends StatefulWidget { final void Function() onSignedIn; - const LoginWidget({Key key, @required this.onSignedIn}) : super(key: key); + const LoginWidget({Key? key, required this.onSignedIn}) : super(key: key); @override _LoginWidgetState createState() => _LoginWidgetState(); @@ -24,7 +24,7 @@ class _LoginWidgetState extends State { final _emailEditingController = TextEditingController(); final _passwordEditingController = TextEditingController(); bool _loading = false; - AuthResult _authResult; + AuthResult? _authResult; String get _currEmail => _emailEditingController.text; @@ -33,7 +33,7 @@ class _LoginWidgetState extends State { bool get _canSubmit => validateEmail(_currEmail) && _currPassword.length >= 3; /// Build error card - Widget _buildErrorCard() { + Widget? _buildErrorCard() { if (_authResult == null) return null; //Determine the right message @@ -83,7 +83,7 @@ class _LoginWidgetState extends State { child: _loading ? CircularProgressIndicator() : ElevatedButton( - child: Text(tr("Sign in")), + child: Text(tr("Sign in")!), onPressed: _canSubmit ? () => _submitForm(context) : null, ), ), diff --git a/lib/ui/widgets/mobile_mode/mobile_appbar_widget.dart b/lib/ui/widgets/mobile_mode/mobile_appbar_widget.dart index a1a0d37..8df7197 100644 --- a/lib/ui/widgets/mobile_mode/mobile_appbar_widget.dart +++ b/lib/ui/widgets/mobile_mode/mobile_appbar_widget.dart @@ -12,7 +12,7 @@ import 'package:flutter/material.dart'; /// /// @author Pierre HUBERT -typedef OnSelectMenuAction = void Function(BarCallbackActions); +typedef OnSelectMenuAction = void Function(BarCallbackActions?); /// Callback actions enum BarCallbackActions { @@ -35,15 +35,15 @@ Color _secondaryColor() => darkTheme() ? darkAccentColor : Colors.white; class _MenuItem { final String label; final Widget icon; - final BarCallbackActions action; + final BarCallbackActions? action; final bool isMenu; - final PageType pageType; + final PageType? pageType; const _MenuItem({ - @required this.label, - @required this.icon, - @required this.action, - @required this.pageType, + required this.label, + required this.icon, + required this.action, + required this.pageType, this.isMenu = false, }) : assert(label != null), assert(isMenu != null), @@ -57,7 +57,7 @@ class _ActionMenuItem { final String label; final BarCallbackActions action; - const _ActionMenuItem({@required this.label, @required this.action}) + const _ActionMenuItem({required this.label, required this.action}) : assert(label != null), assert(action != null); } @@ -65,27 +65,27 @@ class _ActionMenuItem { /// List of menu items to show final _menuItems = <_MenuItem>[ _MenuItem( - label: tr("Notifications"), + label: tr("Notifications")!, icon: Icon(Icons.notifications), action: BarCallbackActions.OPEN_NOTIFICATIONS, pageType: PageType.NOTIFICATIONS_PAGE), _MenuItem( - label: tr("Conversations"), + label: tr("Conversations")!, icon: Icon(Icons.comment), action: BarCallbackActions.OPEN_CONVERSATIONS, pageType: PageType.CONVERSATIONS_LIST_PAGE), _MenuItem( - label: tr("Newest"), + label: tr("Newest")!, icon: Icon(Icons.refresh), action: BarCallbackActions.OPEN_NEWEST_POSTS, pageType: PageType.LATEST_POSTS_PAGE), _MenuItem( - label: tr("Friends"), + label: tr("Friends")!, icon: Icon(Icons.group), action: BarCallbackActions.OPEN_FRIENDS, pageType: PageType.FRIENDS_LIST_PAGE), _MenuItem( - label: tr("Menu"), + label: tr("Menu")!, icon: Icon(Icons.more_vert), isMenu: true, action: null, @@ -95,14 +95,14 @@ final _menuItems = <_MenuItem>[ /// List of menu actions items final _menuActionsItem = <_ActionMenuItem>[ _ActionMenuItem( - label: tr("My Page"), action: BarCallbackActions.OPEN_MY_PAGE), - _ActionMenuItem(label: tr("Groups"), action: BarCallbackActions.OPEN_GROUPS), + label: tr("My Page")!, action: BarCallbackActions.OPEN_MY_PAGE), + _ActionMenuItem(label: tr("Groups")!, action: BarCallbackActions.OPEN_GROUPS), _ActionMenuItem( - label: tr("Search"), action: BarCallbackActions.OPEN_SEARCH_PAGE), + label: tr("Search")!, action: BarCallbackActions.OPEN_SEARCH_PAGE), _ActionMenuItem( - label: tr("Settings"), action: BarCallbackActions.OPEN_SETTINGS), + label: tr("Settings")!, action: BarCallbackActions.OPEN_SETTINGS), _ActionMenuItem( - label: tr("Sign out"), action: BarCallbackActions.ACTION_LOGOUT), + label: tr("Sign out")!, action: BarCallbackActions.ACTION_LOGOUT), ]; /// Public widget @@ -111,8 +111,8 @@ class ComunicMobileAppBar extends StatefulWidget final PageInfo currentPage; const ComunicMobileAppBar({ - Key key, - @required this.currentPage, + Key? key, + required this.currentPage, }) : assert(currentPage != null), super(key: key); @@ -153,7 +153,7 @@ class _ComunicMobileAppBarState extends SafeState { } /// Get the number of unread notifications for the selected notice - int getNumberUnread(BarCallbackActions action) { + int? getNumberUnread(BarCallbackActions? action) { if (_unreadNotifications == null) return 0; switch (action) { @@ -187,35 +187,35 @@ class _ComunicMobileAppBarState extends SafeState { ); } - void _handleAction(BarCallbackActions action) { + void _handleAction(BarCallbackActions? action) { final controller = MainController.of(context); switch (action) { case BarCallbackActions.OPEN_NOTIFICATIONS: - controller.openNotificationsPage(); + controller!.openNotificationsPage(); break; case BarCallbackActions.OPEN_CONVERSATIONS: - controller.openConversationsPage(); + controller!.openConversationsPage(); break; case BarCallbackActions.OPEN_NEWEST_POSTS: - controller.openLatestPostsPage(); + controller!.openLatestPostsPage(); break; case BarCallbackActions.OPEN_FRIENDS: - controller.openFriendsList(); + controller!.openFriendsList(); break; case BarCallbackActions.OPEN_MY_PAGE: - controller.openCurrentUserPage(); + controller!.openCurrentUserPage(); break; case BarCallbackActions.OPEN_SEARCH_PAGE: - controller.openSearchPage(); + controller!.openSearchPage(); break; case BarCallbackActions.OPEN_GROUPS: - controller.openGroupsListPage(); + controller!.openGroupsListPage(); break; case BarCallbackActions.OPEN_SETTINGS: - controller.openSettings(); + controller!.openSettings(); break; case BarCallbackActions.ACTION_LOGOUT: - controller.requestLogout(); + controller!.requestLogout(); break; } } @@ -228,18 +228,15 @@ class _MenuItemWidget extends StatelessWidget { final bool isSelected; /// Notifications notice - final int newNotice; + final int? newNotice; const _MenuItemWidget({ - Key key, - @required this.item, - @required this.onTap, - @required this.isSelected, + Key? key, + required this.item, + required this.onTap, + required this.isSelected, this.newNotice = 0, - }) : assert(item != null), - assert(onTap != null), - assert(isSelected != null), - super(key: key); + }) : super(key: key); @override Widget build(BuildContext context) { @@ -269,7 +266,7 @@ class _MenuItemWidget extends StatelessWidget { color: isSelected ? _primaryColor() : _secondaryColor()), child: item.icon, ), - newNotice > 0 ? Spacer() : Container(), + newNotice! > 0 ? Spacer() : Container(), newNotice == 0 ? Container() : Material( diff --git a/lib/ui/widgets/mobile_mode/user_page_mobile.dart b/lib/ui/widgets/mobile_mode/user_page_mobile.dart index 805949f..0586c5a 100644 --- a/lib/ui/widgets/mobile_mode/user_page_mobile.dart +++ b/lib/ui/widgets/mobile_mode/user_page_mobile.dart @@ -16,9 +16,9 @@ class UserMobilePage extends StatefulWidget { final void Function() onNeedRefresh; const UserMobilePage({ - Key key, - @required this.userInfo, - @required this.onNeedRefresh, + Key? key, + required this.userInfo, + required this.onNeedRefresh, }) : assert(userInfo != null), assert(onNeedRefresh != null), super(key: key); @@ -29,12 +29,12 @@ class UserMobilePage extends StatefulWidget { class _UserMobilePageState extends State with SingleTickerProviderStateMixin { - TabController _tabController; + TabController? _tabController; List get _tabs => [ // User posts UserPageTab( - label: tr("Posts"), + label: tr("Posts")!, onBuild: (c) => UserPostsSection( user: widget.userInfo, ), @@ -42,13 +42,13 @@ class _UserMobilePageState extends State // About user UserPageTab( - label: tr("About"), + label: tr("About")!, onBuild: (c) => AboutUserSection(user: widget.userInfo), ), // User friends UserPageTab( - label: tr("Friends"), + label: tr("Friends")!, onBuild: (c) => widget.userInfo.isCurrentUser ? FriendsListScreen( showAppBar: false, @@ -70,7 +70,7 @@ class _UserMobilePageState extends State @override void dispose() { - _tabController.dispose(); + _tabController!.dispose(); super.dispose(); } @@ -111,8 +111,8 @@ class UserPageTab { final bool visible; UserPageTab({ - @required this.label, - @required this.onBuild, + required this.label, + required this.onBuild, this.visible = true, }) : assert(label != null), assert(onBuild != null), diff --git a/lib/ui/widgets/network_image_widget.dart b/lib/ui/widgets/network_image_widget.dart index c957bb8..f35d070 100644 --- a/lib/ui/widgets/network_image_widget.dart +++ b/lib/ui/widgets/network_image_widget.dart @@ -10,16 +10,16 @@ import 'package:flutter/material.dart'; class NetworkImageWidget extends StatelessWidget { final String url; - final String thumbnailURL; + final String? thumbnailURL; final bool allowFullScreen; final bool roundedEdges; - final double width; - final double height; - final double loadingHeight; + final double? width; + final double? height; + final double? loadingHeight; const NetworkImageWidget({ - Key key, - @required this.url, + Key? key, + required this.url, this.thumbnailURL, this.allowFullScreen = false, this.width, @@ -30,9 +30,9 @@ class NetworkImageWidget extends StatelessWidget { assert(allowFullScreen != null), super(key: key); - double get _loadingHeight => loadingHeight != null ? loadingHeight : height; + double? get _loadingHeight => loadingHeight != null ? loadingHeight : height; - double get _loadingWidth => width; + double? get _loadingWidth => width; @override Widget build(BuildContext context) { diff --git a/lib/ui/widgets/new_password_input_widget.dart b/lib/ui/widgets/new_password_input_widget.dart index 3ed8bcc..5ea8e0c 100644 --- a/lib/ui/widgets/new_password_input_widget.dart +++ b/lib/ui/widgets/new_password_input_widget.dart @@ -8,34 +8,34 @@ import 'package:flutter/material.dart'; /// @author Pierre Hubert class UserInfoForPassword { - final String firstName; - final String lastName; - final String email; + final String? firstName; + final String? lastName; + final String? email; const UserInfoForPassword({ - @required this.firstName, - @required this.lastName, - @required this.email, + required this.firstName, + required this.lastName, + required this.email, }); } class NewPasswordInputWidget extends StatefulWidget { - final Widget icon; - final VoidCallback onEdited; - final VoidCallback onSubmitted; - final TextInputAction textInputAction; + final Widget? icon; + final VoidCallback? onEdited; + final VoidCallback? onSubmitted; + final TextInputAction? textInputAction; final String label; final UserInfoForPassword user; const NewPasswordInputWidget({ - Key key, + Key? key, this.icon, this.onEdited, this.onSubmitted, this.textInputAction, - @required this.label, - @required this.user, + required this.label, + required this.user, }) : assert(label != null), assert(user != null), super(key: key); @@ -51,7 +51,7 @@ class NewPasswordInputWidgetState extends State { bool get valid => value.isNotEmpty && (_errorMessage ?? "").isEmpty; - PasswordPolicy get _policy => ServerConfigurationHelper.config.passwordPolicy; + PasswordPolicy get _policy => ServerConfigurationHelper.config!.passwordPolicy; @override void didUpdateWidget(covariant NewPasswordInputWidget oldWidget) { @@ -65,7 +65,7 @@ class NewPasswordInputWidgetState extends State { obscureText: true, onChanged: (s) => _onChanged(), onSubmitted: - widget.onSubmitted == null ? null : (s) => widget.onSubmitted(), + widget.onSubmitted == null ? null : (s) => widget.onSubmitted!(), textInputAction: widget.textInputAction, decoration: InputDecoration( errorText: _errorMessage, @@ -77,30 +77,30 @@ class NewPasswordInputWidgetState extends State { void _onChanged() { setState(() {}); - if (widget.onEdited != null) widget.onEdited(); + if (widget.onEdited != null) widget.onEdited!(); } /// Generate an error message associated with current password - String get _errorMessage { + String? get _errorMessage { if (value.isEmpty) return null; // Mandatory checks if (!_policy.allowMailInPassword && (widget.user.email ?? "").isNotEmpty && - (widget.user.email.toLowerCase().contains(value.toLowerCase()) || - value.toLowerCase().contains(widget.user.email.toLowerCase()))) { + (widget.user.email!.toLowerCase().contains(value.toLowerCase()) || + value.toLowerCase().contains(widget.user.email!.toLowerCase()))) { return tr("Your password must not contains part of your email address!"); } if (!_policy.allowNameInPassword && (widget.user.firstName ?? "").isNotEmpty && - value.toLowerCase().contains(widget.user.firstName.toLowerCase())) { + value.toLowerCase().contains(widget.user.firstName!.toLowerCase())) { return tr("Your password must not contains your first name!"); } if (!_policy.allowNameInPassword && (widget.user.lastName ?? "").isNotEmpty && - value.toLowerCase().contains(widget.user.lastName.toLowerCase())) { + value.toLowerCase().contains(widget.user.lastName!.toLowerCase())) { return tr("Your password must not contains your last name!"); } diff --git a/lib/ui/widgets/pick_user_widget.dart b/lib/ui/widgets/pick_user_widget.dart index a67b381..786b981 100644 --- a/lib/ui/widgets/pick_user_widget.dart +++ b/lib/ui/widgets/pick_user_widget.dart @@ -15,16 +15,16 @@ typedef OnSelectUserCallback = void Function(User); class PickUserWidget extends StatefulWidget { final OnSelectUserCallback onSelectUser; - final void Function(String) onValueChange; + final void Function(String)? onValueChange; final String label; final bool resetOnChoose; final bool keepFocusOnChoose; final bool enabled; const PickUserWidget({ - Key key, - @required this.onSelectUser, - @required this.label, + Key? key, + required this.onSelectUser, + required this.label, this.resetOnChoose = false, this.keepFocusOnChoose = false, this.onValueChange, @@ -46,8 +46,8 @@ class _PickUserWidgetState extends State { // Widget properties final FocusNode _focusNode = FocusNode(); final TextEditingController _controller = TextEditingController(); - OverlayEntry _overlayEntry; - UsersList _suggestions; + OverlayEntry? _overlayEntry; + UsersList? _suggestions; @override void initState() { @@ -79,7 +79,7 @@ class _PickUserWidgetState extends State { } OverlayEntry _createOverlayEntry() { - RenderBox renderBox = context.findRenderObject(); + RenderBox renderBox = context.findRenderObject() as RenderBox; final size = renderBox.size; final offset = renderBox.localToGlobal(Offset.zero); @@ -93,9 +93,9 @@ class _PickUserWidgetState extends State { child: ListView.builder( padding: EdgeInsets.zero, shrinkWrap: true, - itemCount: _suggestions == null ? 0 : _suggestions.length, + itemCount: _suggestions == null ? 0 : _suggestions!.length, itemBuilder: (c, i) => SimpleUserTile( - user: _suggestions[i], + user: _suggestions![i], onTap: _userTapped, ), ), @@ -106,19 +106,19 @@ class _PickUserWidgetState extends State { void _showOverlay() { _overlayEntry = _createOverlayEntry(); - Overlay.of(context).insert(_overlayEntry); + Overlay.of(context)!.insert(_overlayEntry!); } void _removeOverlay() { if (_overlayEntry != null) { - _overlayEntry.remove(); + _overlayEntry!.remove(); _overlayEntry = null; } } /// This method get called each time the input value is updated Future _updateSuggestions() async { - if (widget.onValueChange != null) widget.onValueChange(_controller.text); + if (widget.onValueChange != null) widget.onValueChange!(_controller.text); if (_controller.text.length == 0) return _removeOverlay(); @@ -128,7 +128,7 @@ class _PickUserWidgetState extends State { _suggestions = results; if (_overlayEntry != null) - _overlayEntry.markNeedsBuild(); + _overlayEntry!.markNeedsBuild(); else _showOverlay(); } diff --git a/lib/ui/widgets/post_container_widget.dart b/lib/ui/widgets/post_container_widget.dart index db6306c..2d48945 100644 --- a/lib/ui/widgets/post_container_widget.dart +++ b/lib/ui/widgets/post_container_widget.dart @@ -7,7 +7,7 @@ import 'package:flutter/material.dart'; class PostContainer extends StatelessWidget { final Widget child; - const PostContainer({Key key, @required this.child}) + const PostContainer({Key? key, required this.child}) : assert(child != null), super(key: key); diff --git a/lib/ui/widgets/post_create_form_widget.dart b/lib/ui/widgets/post_create_form_widget.dart index c69cda0..d76b000 100644 --- a/lib/ui/widgets/post_create_form_widget.dart +++ b/lib/ui/widgets/post_create_form_widget.dart @@ -31,10 +31,10 @@ class PostCreateFormWidget extends StatefulWidget { final void Function() onCreated; const PostCreateFormWidget({ - Key key, - @required this.postTarget, - @required this.targetID, - @required this.onCreated, + Key? key, + required this.postTarget, + required this.targetID, + required this.onCreated, }) : assert(postTarget != null), assert(targetID != null), super(key: key); @@ -50,13 +50,13 @@ class _PostCreateFormWidgetState extends State { // Class members bool _isCreating = false; final TextEditingController _postTextController = TextEditingController(); - PostVisibilityLevel _postVisibilityLevel; - BytesFile _postImage; - String _postURL; - List _postPDF; - DateTime _timeEnd; - NewSurvey _postSurvey; - String _youtubeID; + PostVisibilityLevel? _postVisibilityLevel; + BytesFile? _postImage; + String? _postURL; + List? _postPDF; + DateTime? _timeEnd; + NewSurvey? _postSurvey; + String? _youtubeID; bool get hasImage => _postImage != null; @@ -184,7 +184,7 @@ class _PostCreateFormWidgetState extends State { // Post visibility level _PostOptionWidget( - icon: PostVisibilityLevelsMapIcons[_postVisibilityLevel], + icon: PostVisibilityLevelsMapIcons[_postVisibilityLevel!]!, selected: false, customColor: Colors.black, onTap: _changeVisibilityLevel, @@ -194,7 +194,7 @@ class _PostCreateFormWidgetState extends State { _isCreating ? Container() : ElevatedButton( - child: Text(tr("Send").toUpperCase()), + child: Text(tr("Send")!.toUpperCase()), onPressed: canSubmitForm ? _submitForm : null), ], ), @@ -221,7 +221,7 @@ class _PostCreateFormWidgetState extends State { Future _changeVisibilityLevel() async { final newLevel = await showPostVisibilityPickerDialog( context: context, - initialLevel: _postVisibilityLevel, + initialLevel: _postVisibilityLevel!, isGroup: widget.postTarget == PostTarget.GROUP_PAGE, ); @@ -254,7 +254,7 @@ class _PostCreateFormWidgetState extends State { }); } catch (e, s) { logError(e, s); - snack(context, tr("Failed to pick an image for the post!")); + snack(context, tr("Failed to pick an image for the post!")!); } } @@ -293,7 +293,7 @@ class _PostCreateFormWidgetState extends State { }); } catch (e, stack) { print("Pick PDF error: $e\n$stack"); - showSimpleSnack(context, tr("Could not pick a PDF!")); + showSimpleSnack(context, tr("Could not pick a PDF!")!); } } @@ -301,7 +301,7 @@ class _PostCreateFormWidgetState extends State { Future _pickCountdownTime() async { final yesterday = DateTime.now().subtract(Duration(days: 1)); - final initialDate = _timeEnd == null ? DateTime.now() : _timeEnd; + final initialDate = _timeEnd == null ? DateTime.now() : _timeEnd!; // Pick date final newDate = await showDatePicker( @@ -358,7 +358,7 @@ class _PostCreateFormWidgetState extends State { /// Submit new post Future _submitForm() async { if (!canSubmitForm) - showSimpleSnack(context, tr("Form can not be submitted at this point!")); + showSimpleSnack(context, tr("Form can not be submitted at this point!")!); setState(() => _isCreating = true); @@ -366,7 +366,7 @@ class _PostCreateFormWidgetState extends State { await _postHelper.createPost(NewPost( target: widget.postTarget, targetID: widget.targetID, - visibility: _postVisibilityLevel, + visibility: _postVisibilityLevel!, content: _postTextController.text, kind: postKind, image: _postImage, @@ -378,14 +378,14 @@ class _PostCreateFormWidgetState extends State { )); setState(() => _isCreating = false); - showSimpleSnack(context, tr("The post has been successfully created!")); + showSimpleSnack(context, tr("The post has been successfully created!")!); this._resetForm(); widget.onCreated(); } catch (e, s) { setState(() => _isCreating = false); print("Error while creating post : $e $s"); - showSimpleSnack(context, tr("Could not create post !")); + showSimpleSnack(context, tr("Could not create post !")!); } } } @@ -394,14 +394,14 @@ class _PostCreateFormWidgetState extends State { class _PostOptionWidget extends StatelessWidget { final IconData icon; final bool selected; - final Color customColor; + final Color? customColor; final void Function() onTap; const _PostOptionWidget( - {Key key, - @required this.icon, - @required this.selected, - @required this.onTap, + {Key? key, + required this.icon, + required this.selected, + required this.onTap, this.customColor}) : assert(icon != null), assert(selected != null), diff --git a/lib/ui/widgets/posts_list_widget.dart b/lib/ui/widgets/posts_list_widget.dart index f82d83e..b2989e7 100644 --- a/lib/ui/widgets/posts_list_widget.dart +++ b/lib/ui/widgets/posts_list_widget.dart @@ -24,18 +24,18 @@ import 'package:flutter/material.dart'; /// @author Pierre HUBERT class PostsListWidget extends StatefulWidget { - final List topWidgets; - final Future Function() getPostsList; - final Future Function(int from) getOlder; + final List? topWidgets; + final Future Function() getPostsList; + final Future Function(int from)? getOlder; final bool showPostsTarget; final bool buildListView; final bool userNamesClickable; final bool disablePullToRefresh; const PostsListWidget({ - Key key, - @required this.getPostsList, - @required this.showPostsTarget, + Key? key, + required this.getPostsList, + required this.showPostsTarget, this.userNamesClickable = true, this.buildListView = true, this.getOlder, @@ -58,10 +58,10 @@ class PostsListWidgetState extends SafeState { final GroupsHelper _groupsHelper = GroupsHelper(); // Class members - PostsList _list; - UsersList _users; - GroupsList _groups; - ScrollWatcher _scrollController; + PostsList? _list; + late UsersList _users; + late GroupsList _groups; + ScrollWatcher? _scrollController; ErrorLevel _error = ErrorLevel.NONE; bool _loading = false; @@ -70,7 +70,7 @@ class PostsListWidgetState extends SafeState { set error(ErrorLevel err) => setState(() => _error = err); int get _numberTopWidgets => - widget.topWidgets == null ? 0 : widget.topWidgets.length; + widget.topWidgets == null ? 0 : widget.topWidgets!.length; @override void initState() { @@ -122,7 +122,7 @@ class PostsListWidgetState extends SafeState { try { final list = !getOlder ? await widget.getPostsList() - : await widget.getOlder(_list.oldestID); + : await widget.getOlder!(_list!.oldestID); if (list == null) return _loadError(); @@ -140,7 +140,7 @@ class PostsListWidgetState extends SafeState { _users = users; _groups = groups; } else { - _list.addAll(list); + _list!.addAll(list); _users.addAll(users); _groups.addAll(groups); } @@ -157,7 +157,7 @@ class PostsListWidgetState extends SafeState { void _registerRequiredPosts() async { if (_list == null) return; - final missing = _list + final missing = _list! .where((f) => !_registeredPosts.contains(f.id)) .map((f) => f.id) .toSet(); @@ -192,7 +192,7 @@ class PostsListWidgetState extends SafeState { return Center( child: Padding( padding: const EdgeInsets.all(8.0), - child: Text(tr("There is no post to display here yet.")), + child: Text(tr("There is no post to display here yet.")!), ), ); } @@ -205,7 +205,7 @@ class PostsListWidgetState extends SafeState { Widget _buildListView() { return ListView.builder( // We use max function here to display to post notice in case there are not posts to display but there are custom widgets... - itemCount: max(_list.length, 1) + _numberTopWidgets, + itemCount: max(_list!.length, 1) + _numberTopWidgets, itemBuilder: _buildItem, controller: _scrollController, @@ -215,20 +215,20 @@ class PostsListWidgetState extends SafeState { Widget _buildColumn() { return Column( children: List.generate( - _list.length, + _list!.length, (i) => _buildItem(null, i), ), ); } - Widget _buildItem(BuildContext context, int index) { - if (index < _numberTopWidgets) return widget.topWidgets[index]; + Widget _buildItem(BuildContext? context, int index) { + if (index < _numberTopWidgets) return widget.topWidgets![index]; // Show no posts notice if required - if (_list.length == 0) return _buildNoPostNotice(); + if (_list!.length == 0) return _buildNoPostNotice(); return PostTile( - post: _list[index - _numberTopWidgets], + post: _list![index - _numberTopWidgets], usersInfo: _users, groupsInfo: _groups, onDeletedPost: _removePost, @@ -241,7 +241,7 @@ class PostsListWidgetState extends SafeState { Widget build(BuildContext context) { if (_error == ErrorLevel.MAJOR) return _buildErrorCard(); if (_list == null) return buildCenteredProgressBar(); - if (_list.length == 0 && _numberTopWidgets == 0) + if (_list!.length == 0 && _numberTopWidgets == 0) return _buildNoPostNotice(); if (!widget.buildListView) return _buildColumn(); @@ -250,7 +250,7 @@ class PostsListWidgetState extends SafeState { return _buildListViewWithRefreshIndicator(); } - void _removePost(Post post) => setState(() => _list.remove(post)); + void _removePost(Post post) => setState(() => _list!.remove(post)); void reachedPostsBottom() { if (widget.getOlder != null) loadPostsList(getOlder: true); @@ -261,15 +261,14 @@ class PostsListWidgetState extends SafeState { if (_list == null) return; try { - final p = _list.singleWhere((p) => p.id == c.postID, orElse: () => null); - - if (p == null) return; + // This command will throw if post could not be found + final Post p = _list!.singleWhere((p) => p.id == c.postID); if (!_users.hasUser(c.userID)) _users.add(await UsersHelper().getSingleWithThrow(c.userID)); setState(() { - p.comments.add(c); + p.comments!.add(c); }); } catch (e, stack) { print("$e\n$stack"); @@ -281,22 +280,20 @@ class PostsListWidgetState extends SafeState { if (_list == null) return; try { - final p = _list.singleWhere((p) => p.id == c.postID, orElse: () => null); + final Post p = _list!.singleWhere((p) => p.id == c.postID); - if (p == null) return; + final index = p.comments!.indexWhere((d) => d.id == c.id); - final index = p.comments.indexWhere((d) => d.id == c.id); - - if (index > -1) p.comments[index] = c; + if (index > -1) p.comments![index] = c; } catch (e, stack) { print("$e\n$stack"); } } /// Remove a comment from the list - void _removeComment(int commentID) { + void _removeComment(int? commentID) { if (_list == null) return; - _list.forEach((p) => p.comments.removeWhere((c) => c.id == commentID)); + _list!.forEach((p) => p.comments!.removeWhere((c) => c.id == commentID)); } } diff --git a/lib/ui/widgets/scroll_watcher.dart b/lib/ui/widgets/scroll_watcher.dart index 42e2256..be76ba8 100644 --- a/lib/ui/widgets/scroll_watcher.dart +++ b/lib/ui/widgets/scroll_watcher.dart @@ -9,7 +9,7 @@ typedef OnReachBottomCallback = void Function(); class ScrollWatcher extends ScrollController { // Callbacks - OnReachBottomCallback onReachBottom; + OnReachBottomCallback? onReachBottom; ScrollWatcher({this.onReachBottom}) { addListener(_updatePosition); @@ -21,7 +21,7 @@ class ScrollWatcher extends ScrollController { // Refresh bottom position if(position.pixels.floor() == position.maxScrollExtent.floor()) - onReachBottom(); + onReachBottom!(); } } \ No newline at end of file diff --git a/lib/ui/widgets/settings/multi_choices_settings_tile.dart b/lib/ui/widgets/settings/multi_choices_settings_tile.dart index 9c79fd5..e6ef1ec 100644 --- a/lib/ui/widgets/settings/multi_choices_settings_tile.dart +++ b/lib/ui/widgets/settings/multi_choices_settings_tile.dart @@ -11,15 +11,15 @@ class MultiChoicesSettingsTile extends SettingsTile { final List> choices; final T currentValue; final Function(T) onChanged; - final Widget leading; - final Widget trailing; + final Widget? leading; + final Widget? trailing; MultiChoicesSettingsTile({ - Key key, - @required this.title, - @required this.choices, - @required this.currentValue, - @required this.onChanged, + Key? key, + required this.title, + required this.choices, + required this.currentValue, + required this.onChanged, this.leading, this.trailing, }) : assert(title != null), diff --git a/lib/ui/widgets/settings/text_settings_edit_tile.dart b/lib/ui/widgets/settings/text_settings_edit_tile.dart index 7fe3d0f..a4c5486 100644 --- a/lib/ui/widgets/settings/text_settings_edit_tile.dart +++ b/lib/ui/widgets/settings/text_settings_edit_tile.dart @@ -18,15 +18,15 @@ class TextEditSettingsTile extends SettingsTile { final bool Function(String) checkInput; final bool allowEmptyValues; final int maxLines; - final int maxLength; + final int? maxLength; bool get readOnly => onChanged == null; TextEditSettingsTile({ - Key key, - @required this.title, - @required this.currValue, - @required this.onChanged, + Key? key, + required this.title, + required this.currValue, + required this.onChanged, this.checkInput = _defaultCheck, this.allowEmptyValues = false, this.maxLength, @@ -55,7 +55,7 @@ class TextEditSettingsTile extends SettingsTile { initialValue: currValue, label: title, checkInput: checkInput, - errorMessage: tr("Invalid value!"), + errorMessage: tr("Invalid value!")!, canBeEmpty: allowEmptyValues, maxLines: maxLines, maxLength: maxLength, diff --git a/lib/ui/widgets/status_widget.dart b/lib/ui/widgets/status_widget.dart index b84f953..a0f7a6e 100644 --- a/lib/ui/widgets/status_widget.dart +++ b/lib/ui/widgets/status_widget.dart @@ -15,8 +15,8 @@ class StatusWidget extends StatefulWidget { final Widget Function(BuildContext) child; const StatusWidget({ - Key key, - @required this.child, + Key? key, + required this.child, }) : assert(child != null), super(key: key); @@ -25,8 +25,8 @@ class StatusWidget extends StatefulWidget { } class StatusWidgetState extends SafeState { - int unreadNotifications = 0; - int unreadConversations = 0; + int? unreadNotifications = 0; + int? unreadConversations = 0; Future init() async { try { @@ -52,7 +52,7 @@ class StatusWidgetState extends SafeState { } /// Find an ancestor of this object - static StatusWidgetState of(BuildContext c) => + static StatusWidgetState? of(BuildContext c) => c.findAncestorStateOfType(); @override diff --git a/lib/ui/widgets/survey_widget.dart b/lib/ui/widgets/survey_widget.dart index 48e9468..ba1cb7a 100644 --- a/lib/ui/widgets/survey_widget.dart +++ b/lib/ui/widgets/survey_widget.dart @@ -16,9 +16,9 @@ class SurveyWidget extends StatefulWidget { final Function(Survey) onUpdated; const SurveyWidget({ - Key key, - @required this.survey, - @required this.onUpdated, + Key? key, + required this.survey, + required this.onUpdated, }) : assert(survey != null), assert(onUpdated != null), super(key: key); @@ -74,12 +74,12 @@ class _SurveyWidgetState extends SafeState { Flexible( child: Text( tr("Your response: %response%", - args: {"response": survey.userResponse.name}), + args: {"response": survey.userResponse!.name})!, textAlign: TextAlign.center, ), ), MaterialButton( - child: Text(tr("Cancel").toUpperCase()), + child: Text(tr("Cancel")!.toUpperCase()), onPressed: _cancelUserResponse, ) ], @@ -96,7 +96,7 @@ class _SurveyWidgetState extends SafeState { if (!await _helper.cancelResponse(survey)) { showSimpleSnack( - context, tr("Could not cancel your response to the survey !")); + context, tr("Could not cancel your response to the survey !")!); return; } @@ -110,7 +110,7 @@ class _SurveyWidgetState extends SafeState { constraints: BoxConstraints(maxWidth: 300), child: DropdownButton( isExpanded: true, - hint: Text(tr("Respond to survey")), + hint: Text(tr("Respond to survey")!), items: survey.choices .map( (f) => DropdownMenuItem( @@ -128,7 +128,7 @@ class _SurveyWidgetState extends SafeState { padding: const EdgeInsets.all(8.0), child: InkWell( onTap: _createNewChoices, - child: Text(tr("Create a new choice")), + child: Text(tr("Create a new choice")!), ), ); @@ -136,7 +136,7 @@ class _SurveyWidgetState extends SafeState { padding: const EdgeInsets.all(8.0), child: InkWell( onTap: _blockNewChoices, - child: Text(tr("Block the creation of new responses")), + child: Text(tr("Block the creation of new responses")!), ), ); @@ -149,16 +149,16 @@ class _SurveyWidgetState extends SafeState { Widget _buildNoResponseNotice() { return Padding( padding: const EdgeInsets.all(16.0), - child: Text(tr("No response yet to this survey.")), + child: Text(tr("No response yet to this survey.")!), ); } /// Respond to survey - Future _respondToSurvey(SurveyChoice choice) async { + Future _respondToSurvey(SurveyChoice? choice) async { // Send the response to the server - if (!await _helper.respondToSurvey(survey: survey, choice: choice)) + if (!await _helper.respondToSurvey(survey: survey, choice: choice!)) return showSimpleSnack( - context, tr("Could not send your response to the survey!")); + context, tr("Could not send your response to the survey!")!); setState(() { survey.setUserResponse(choice); @@ -178,10 +178,10 @@ class _SurveyWidgetState extends SafeState { try { final newChoice = await askUserString( context: context, - title: tr("New choice"), - message: tr("Please specify the new choice for the survey"), + title: tr("New choice")!, + message: tr("Please specify the new choice for the survey")!, defaultValue: "", - hint: tr("New choice..."), + hint: tr("New choice...")!, maxLength: 50, ); @@ -193,7 +193,7 @@ class _SurveyWidgetState extends SafeState { } catch (e, s) { print("Could not create new survey choice! $e\n$s"); showSimpleSnack( - context, tr("Could not create a new choice for this survey!")); + context, tr("Could not create a new choice for this survey!")!); } } @@ -210,7 +210,7 @@ class _SurveyWidgetState extends SafeState { } catch (e, s) { print("Could not block the creation of new choices! $e\n$s"); showSimpleSnack( - context, tr("Could not block the creation of new choices!")); + context, tr("Could not block the creation of new choices!")!); } } } diff --git a/lib/ui/widgets/tab_transition_widget.dart b/lib/ui/widgets/tab_transition_widget.dart index f06be52..14e95b6 100644 --- a/lib/ui/widgets/tab_transition_widget.dart +++ b/lib/ui/widgets/tab_transition_widget.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; class TabTransitionWidget extends StatefulWidget { final Widget child; - const TabTransitionWidget(this.child, {Key key}) + const TabTransitionWidget(this.child, {Key? key}) : assert(child != null), super(key: key); diff --git a/lib/ui/widgets/tablet_mode/appbar_custom_dropdown_widget.dart b/lib/ui/widgets/tablet_mode/appbar_custom_dropdown_widget.dart index c34d014..7b086df 100644 --- a/lib/ui/widgets/tablet_mode/appbar_custom_dropdown_widget.dart +++ b/lib/ui/widgets/tablet_mode/appbar_custom_dropdown_widget.dart @@ -14,10 +14,10 @@ class AppBarCustomDropDownWidget extends StatefulWidget { final Widget Function(BuildContext) onBuildOverlay; const AppBarCustomDropDownWidget({ - Key key, - @required this.icon, - @required this.notificationsBadge, - @required this.onBuildOverlay, + Key? key, + required this.icon, + required this.notificationsBadge, + required this.onBuildOverlay, }) : assert(icon != null), assert(notificationsBadge != null), assert(onBuildOverlay != null), @@ -46,7 +46,7 @@ class AppBarCustomDropDownWidgetState setState(() => _visible = !_visible); if (_visible) { - RenderBox renderBox = context.findRenderObject(); + RenderBox renderBox = context.findRenderObject() as RenderBox; final size = renderBox.size; final offset = renderBox.localToGlobal(Offset(size.width, size.height)); @@ -68,10 +68,10 @@ class _AppBarCustomPopupRoute extends PopupRoute { final void Function() onDispose; _AppBarCustomPopupRoute({ - @required this.showContext, - @required this.onBuild, - @required this.offset, - @required this.onDispose, + required this.showContext, + required this.onBuild, + required this.offset, + required this.onDispose, }); @override @@ -82,7 +82,7 @@ class _AppBarCustomPopupRoute extends PopupRoute { } @override - Color get barrierColor => null; + Color? get barrierColor => null; @override bool get barrierDismissible => true; @@ -116,10 +116,10 @@ class _AppBarCustomPopupRoute extends PopupRoute { } class _PopupContentBody extends StatelessWidget { - final Widget Function(BuildContext) onBuild; - final Offset offset; + final Widget Function(BuildContext)? onBuild; + final Offset? offset; - const _PopupContentBody({Key key, this.onBuild, this.offset}) + const _PopupContentBody({Key? key, this.onBuild, this.offset}) : super(key: key); @override @@ -132,12 +132,12 @@ class _PopupContentBody extends StatelessWidget { child: Container(color: Color(0x55000000)), ), Positioned( - left: offset.dx - _overlay_w + 4, - top: offset.dy - 4, + left: offset!.dx - _overlay_w + 4, + top: offset!.dy - 4, width: _overlay_w, height: _overlay_h, child: Scaffold( - body: Card(child: onBuild(context)), + body: Card(child: onBuild!(context)), backgroundColor: Colors.transparent, ), ) diff --git a/lib/ui/widgets/tablet_mode/calls/call_window_widget.dart b/lib/ui/widgets/tablet_mode/calls/call_window_widget.dart index f7744b2..a2e1531 100644 --- a/lib/ui/widgets/tablet_mode/calls/call_window_widget.dart +++ b/lib/ui/widgets/tablet_mode/calls/call_window_widget.dart @@ -15,9 +15,9 @@ class CallWindowWidget extends StatefulWidget { final void Function() onClose; const CallWindowWidget({ - Key key, - @required this.convID, - @required this.onClose, + Key? key, + required this.convID, + required this.onClose, }) : assert(convID != null), assert(onClose != null), super(key: key); @@ -27,7 +27,7 @@ class CallWindowWidget extends StatefulWidget { } class _CallWindowWidgetState extends State { - double _left, _top; + double? _left, _top; var _fullScreen = false; @@ -71,7 +71,7 @@ class _CallWindowWidgetState extends State { height: 30, appBar: AppBar( backgroundColor: Colors.black, - title: Text(convName == null ? tr("Loading...") : convName), + title: Text(convName == null ? tr("Loading...")! : convName), actions: [ // Go full screen IconButton( @@ -98,9 +98,9 @@ class _CallWindowWidgetState extends State { void _moveEnd(DraggableDetails details) { // Determine the limits of containing stack RenderBox renderBox = context - .findAncestorStateOfType() + .findAncestorStateOfType()! .context - .findRenderObject(); + .findRenderObject() as RenderBox; final size = renderBox.size; final offset = renderBox.localToGlobal(Offset.zero); @@ -109,13 +109,13 @@ class _CallWindowWidgetState extends State { _left = details.offset.dx - offset.dx; // Force the window to appear completely on the screen - if (_top + _WindowSize.height >= size.height) + if (_top! + _WindowSize.height >= size.height) _top = size.height - _WindowSize.height; - if (_left + _WindowSize.width >= size.width) + if (_left! + _WindowSize.width >= size.width) _left = size.width - _WindowSize.width; - if (_top < 0) _top = 0; - if (_left < 0) _left = 0; + if (_top! < 0) _top = 0; + if (_left! < 0) _left = 0; setState(() {}); } diff --git a/lib/ui/widgets/tablet_mode/calls/calls_area.dart b/lib/ui/widgets/tablet_mode/calls/calls_area.dart index d86a5ea..3168d33 100644 --- a/lib/ui/widgets/tablet_mode/calls/calls_area.dart +++ b/lib/ui/widgets/tablet_mode/calls/calls_area.dart @@ -6,7 +6,7 @@ import 'package:flutter/material.dart'; /// @author Pierre Hubert class CallsArea extends StatefulWidget { - const CallsArea({Key key}) : super(key: key); + const CallsArea({Key? key}) : super(key: key); @override CallsAreaState createState() => CallsAreaState(); diff --git a/lib/ui/widgets/tablet_mode/conversations/conversation_window.dart b/lib/ui/widgets/tablet_mode/conversations/conversation_window.dart index 4506b7d..ec0a48a 100644 --- a/lib/ui/widgets/tablet_mode/conversations/conversation_window.dart +++ b/lib/ui/widgets/tablet_mode/conversations/conversation_window.dart @@ -24,9 +24,9 @@ class ConversationWindow extends StatefulWidget { final Function() onClose; const ConversationWindow({ - Key key, - @required this.convID, - @required this.onClose, + Key? key, + required this.convID, + required this.onClose, }) : assert(convID != null), assert(onClose != null), super(key: key); @@ -36,8 +36,8 @@ class ConversationWindow extends StatefulWidget { } class _ConversationWindowState extends SafeState { - Conversation _conversation; - String _convTitle; + Conversation? _conversation; + late String _convTitle; bool _error = false; bool _collapsed = false; bool _hasNewMessages = false; @@ -71,7 +71,7 @@ class _ConversationWindowState extends SafeState { } catch (e, s) { _setError(true); print("Could not refresh the list of conversations! $e\n$s"); - showSimpleSnack(context, tr("Could not load conversation information!")); + showSimpleSnack(context, tr("Could not load conversation information!")!); } } @@ -92,7 +92,7 @@ class _ConversationWindowState extends SafeState { if (_error) return ConversationWindowContainer( icon: Icon(Icons.error), - title: Text(tr("Error")), + title: Text(tr("Error")!), onClose: widget.onClose, onToggleCollapse: _toggleVisibility, isCollapsed: _collapsed, @@ -100,7 +100,7 @@ class _ConversationWindowState extends SafeState { actions: [ ElevatedButton( onPressed: _refresh, - child: Text(tr("Try again").toUpperCase()), + child: Text(tr("Try again")!.toUpperCase()), ) ]), ); @@ -109,7 +109,7 @@ class _ConversationWindowState extends SafeState { if (_conversation == null) return ConversationWindowContainer( icon: Icon(Icons.message), - title: Text(tr("Loading...")), + title: Text(tr("Loading...")!), onClose: widget.onClose, onToggleCollapse: _toggleVisibility, isCollapsed: _collapsed, @@ -123,7 +123,7 @@ class _ConversationWindowState extends SafeState { onClose: widget.onClose, onToggleCollapse: _toggleVisibility, isCollapsed: _collapsed, - action: (_conversation.callCapabilities != CallCapabilities.NONE + action: (_conversation!.callCapabilities != CallCapabilities.NONE ? [IconButton(icon: Icon(Icons.call), onPressed: _startCall)] : []) ..addAll([ @@ -131,19 +131,19 @@ class _ConversationWindowState extends SafeState { itemBuilder: (c) => [ // Show in full screen PopupMenuItem( - child: Text(tr("Open in full screen")), + child: Text(tr("Open in full screen")!), value: _Actions.OPEN_FULL_SCREEN, ), // Show the list of members PopupMenuItem( - child: Text(tr("Members")), + child: Text(tr("Members")!), value: _Actions.OPEN_MEMBERS, ), // Show conversation settings PopupMenuItem( - child: Text(tr("Settings")), + child: Text(tr("Settings")!), value: _Actions.OPEN_SETTINGS, ) ], @@ -174,8 +174,8 @@ class _ConversationWindowState extends SafeState { } void _openFullScreen() { - MainController.of(context) - .openConversation(_conversation, fullScreen: true); + MainController.of(context)! + .openConversation(_conversation!, fullScreen: true); widget.onClose(); } @@ -189,5 +189,5 @@ class _ConversationWindowState extends SafeState { _refresh(); } - void _startCall() => MainController.of(context).startCall(_convID); + void _startCall() => MainController.of(context)!.startCall(_convID); } diff --git a/lib/ui/widgets/tablet_mode/conversations/conversation_window_container.dart b/lib/ui/widgets/tablet_mode/conversations/conversation_window_container.dart index 2afa852..4e662b7 100644 --- a/lib/ui/widgets/tablet_mode/conversations/conversation_window_container.dart +++ b/lib/ui/widgets/tablet_mode/conversations/conversation_window_container.dart @@ -8,24 +8,24 @@ import 'package:flutter/material.dart'; /// @author Pierre Hubert class ConversationWindowContainer extends StatelessWidget { - final Color appBarBgColor; - final Widget icon; + final Color? appBarBgColor; + final Widget? icon; final Widget title; final void Function() onClose; final void Function() onToggleCollapse; final bool isCollapsed; final Widget body; - final List action; + final List? action; const ConversationWindowContainer({ - Key key, + Key? key, this.appBarBgColor, this.icon, - @required this.title, - @required this.onClose, - @required this.body, - @required this.onToggleCollapse, - @required this.isCollapsed, + required this.title, + required this.onClose, + required this.body, + required this.onToggleCollapse, + required this.isCollapsed, this.action, }) : assert(title != null), assert(onClose != null), @@ -47,7 +47,7 @@ class ConversationWindowContainer extends StatelessWidget { backgroundColor: appBarBgColor, leading: icon, title: GestureDetector(child: title, onTap: onToggleCollapse), - actions: (action == null ? [] : action) + actions: action ?? [] ..add( IconButton(icon: Icon(Icons.close), onPressed: onClose), ), diff --git a/lib/ui/widgets/tablet_mode/conversations/conversations_area_widget.dart b/lib/ui/widgets/tablet_mode/conversations/conversations_area_widget.dart index 5e35ecb..e1aaae9 100644 --- a/lib/ui/widgets/tablet_mode/conversations/conversations_area_widget.dart +++ b/lib/ui/widgets/tablet_mode/conversations/conversations_area_widget.dart @@ -9,14 +9,14 @@ import 'package:flutter/material.dart'; /// @author Pierre class ConversationsAreaWidget extends StatefulWidget { - const ConversationsAreaWidget({Key key}) : super(key: key); + const ConversationsAreaWidget({Key? key}) : super(key: key); @override ConversationsAreaWidgetState createState() => ConversationsAreaWidgetState(); } class ConversationsAreaWidgetState extends State { - final _openConversations = Map(); + final _openConversations = Map(); @override Widget build(BuildContext context) { @@ -31,17 +31,17 @@ class ConversationsAreaWidgetState extends State { Widget _buildOpenButton() => OpenConversationButton(); /// Open a new conversation - void openConversations(int convID) { + void openConversations(int? convID) { if (!_openConversations.containsKey(convID)) setState(() => _openConversations[convID] = UniqueKey()); } - MapEntry _conversationWindow(int convID, UniqueKey key) => + MapEntry _conversationWindow(int? convID, UniqueKey key) => MapEntry( convID, ConversationWindow( key: key, - convID: convID, + convID: convID!, onClose: () => setState(() => _openConversations.remove(convID)), ), ); diff --git a/lib/ui/widgets/tablet_mode/current_user_panel.dart b/lib/ui/widgets/tablet_mode/current_user_panel.dart index 4472c8a..b06127f 100644 --- a/lib/ui/widgets/tablet_mode/current_user_panel.dart +++ b/lib/ui/widgets/tablet_mode/current_user_panel.dart @@ -17,7 +17,7 @@ class CurrentUserPanel extends StatefulWidget { } class _CurrentUserPanelState extends SafeState { - User _user; + User? _user; Future _refresh() async { try { @@ -49,12 +49,12 @@ class _CurrentUserPanelState extends SafeState { if (_user == null) return buildCenteredProgressBar(); return ListTile( - onTap: () => MainController.of(context).openCurrentUserPage(), + onTap: () => MainController.of(context)!.openCurrentUserPage(), leading: AccountImageWidget( - user: _user, + user: _user!, width: 50, ), - title: Text(_user.displayName), + title: Text(_user!.displayName), ); } } diff --git a/lib/ui/widgets/tablet_mode/global_search_field.dart b/lib/ui/widgets/tablet_mode/global_search_field.dart index 464003b..e71f44d 100644 --- a/lib/ui/widgets/tablet_mode/global_search_field.dart +++ b/lib/ui/widgets/tablet_mode/global_search_field.dart @@ -36,9 +36,9 @@ class _GlobalSearchFieldState extends State { final _controller = TextEditingController(); - _SearchResults _searchResultsList; + _SearchResults? _searchResultsList; - OverlayEntry _overlayEntry; + OverlayEntry? _overlayEntry; @override void initState() { @@ -96,29 +96,29 @@ class _GlobalSearchFieldState extends State { _searchResultsList = _SearchResults(results, users, groups); - if (_overlayEntry != null) _overlayEntry.markNeedsBuild(); + if (_overlayEntry != null) _overlayEntry!.markNeedsBuild(); } catch (e, s) { print("Could not perform search! $e\n$s"); - showSimpleSnack(context, tr("Could not perform search!")); + showSimpleSnack(context, tr("Could not perform search!")!); } } void _showOverlay() { if (_overlayEntry == null) { _overlayEntry = _createOverlayEntry(); - Overlay.of(context).insert(_overlayEntry); + Overlay.of(context)!.insert(_overlayEntry!); } } void _removeOverlay() { if (_overlayEntry != null) { - _overlayEntry.remove(); + _overlayEntry!.remove(); _overlayEntry = null; } } OverlayEntry _createOverlayEntry() { - RenderBox renderBox = context.findRenderObject(); + RenderBox renderBox = context.findRenderObject() as RenderBox; var size = renderBox.size; var offset = renderBox.localToGlobal(Offset.zero); @@ -140,13 +140,13 @@ class _GlobalSearchFieldState extends State { } class _SearchResultsWidget extends StatelessWidget { - final _SearchResults results; + final _SearchResults? results; final Function() onTap; const _SearchResultsWidget({ - Key key, - @required this.results, - @required this.onTap, + Key? key, + required this.results, + required this.onTap, }) : assert(onTap != null), super(key: key); @@ -155,32 +155,32 @@ class _SearchResultsWidget extends StatelessWidget { if (results == null) return Container(); return ListView.builder( itemBuilder: _builder, - itemCount: results.list.length, + itemCount: results!.list.length, ); } Widget _builder(BuildContext context, int index) { - final res = results.list[index]; + final SearchResult res = results!.list[index]; switch (res.kind) { case SearchResultKind.USER: - final user = results.users.getUser(res.id); + final user = results!.users.getUser(res.id); return ListTile( leading: AccountImageWidget(user: user), title: Text(user.displayName), onTap: () { - MainController.of(context).openUserPage(user.id); + MainController.of(context)!.openUserPage(user.id!); onTap(); }, ); case SearchResultKind.GROUP: - final group = results.groups.getGroup(res.id); + final group = results!.groups.getGroup(res.id)!; return ListTile( leading: GroupIcon(group: group), title: Text(group.displayName), onTap: () { - MainController.of(context).openGroup(group.id); + MainController.of(context)!.openGroup(group.id); onTap(); }, ); diff --git a/lib/ui/widgets/tablet_mode/memberships_panel.dart b/lib/ui/widgets/tablet_mode/memberships_panel.dart index e4879ab..e567dee 100644 --- a/lib/ui/widgets/tablet_mode/memberships_panel.dart +++ b/lib/ui/widgets/tablet_mode/memberships_panel.dart @@ -29,8 +29,8 @@ class MembershipsPanel extends StatefulWidget { final PageInfo currentPage; const MembershipsPanel({ - Key key, - @required this.currentPage, + Key? key, + required this.currentPage, }) : assert(currentPage != null), super(key: key); @@ -42,9 +42,9 @@ const _MembershipIconsWidth = 30.0; class _MembershipsPanelState extends SafeState { final _refreshKey = GlobalKey(); - MembershipList _membershipList; - UsersList _usersList; - GroupsList _groupsList; + MembershipList? _membershipList; + UsersList? _usersList; + late GroupsList _groupsList; Future _refresh() async { try { @@ -87,13 +87,13 @@ class _MembershipsPanelState extends SafeState { iconColor: IconTheme.of(context).color, child: ListView.builder( itemBuilder: _buildMembershipTile, - itemCount: _membershipList.length, + itemCount: _membershipList!.length, ), ); } Widget _buildMembershipTile(BuildContext context, int index) { - final membership = _membershipList[index]; + final Membership membership = _membershipList![index]!; switch (membership.type) { case MembershipType.FRIEND: @@ -111,17 +111,19 @@ class _MembershipsPanelState extends SafeState { // TODO : add private messages icon support Widget _buildFriendMembership(Membership membership) { - final user = _usersList.getUser(membership.friend.id); - final connected = membership.friend.isConnected; + final user = _usersList!.getUser(membership.friend!.id); + final connected = membership.friend!.isConnected; Widget subtitle; - if (!membership.friend.accepted) { + final friend = membership.friend!; + + if (!friend.accepted) { subtitle = RichText( text: TextSpan(children: [ WidgetSpan( child: _RespondFriendshipRequestButton( - friend: membership.friend, + friend: friend, accept: true, text: tr("Accept"), color: Colors.green, @@ -130,7 +132,7 @@ class _MembershipsPanelState extends SafeState { TextSpan(text: " "), WidgetSpan( child: _RespondFriendshipRequestButton( - friend: membership.friend, + friend: friend, accept: false, text: tr("Reject"), color: Colors.red, @@ -139,7 +141,9 @@ class _MembershipsPanelState extends SafeState { ])); } else subtitle = Text( - connected ? tr("Online") : diffTimeFromNowToStr(membership.lastActive), + connected + ? tr("Online")! + : diffTimeFromNowToStr(membership.lastActive!)!, style: TextStyle(color: connected ? Colors.green : null), ); @@ -152,13 +156,13 @@ class _MembershipsPanelState extends SafeState { leading: AccountImageWidget(user: user, width: _MembershipIconsWidth), title: Text(user.displayName), subtitle: subtitle, - onTap: () => MainController.of(context).openUserPage(user.id), + onTap: () => MainController.of(context)!.openUserPage(user.id!), ), ); } Widget _buildGroupMembership(Membership membership) { - final group = _groupsList.getGroup(membership.groupID); + final group = _groupsList.getGroup(membership.groupID)!; return Container( color: widget.currentPage.type == PageType.GROUP_PAGE && @@ -167,11 +171,11 @@ class _MembershipsPanelState extends SafeState { : null, child: Column( children: [_buildMainGroupInformationTile(membership, group)] - ..addAll(_membershipList + ..addAll(_membershipList! .getGroupConversations(group.id) .map((e) => Padding( padding: const EdgeInsets.only(left: 30.0), - child: _buildConversationMembership(e, true), + child: _buildConversationMembership(e!, true), )) .toList()), ), @@ -183,11 +187,11 @@ class _MembershipsPanelState extends SafeState { if (!group.isAtLeastMember) { subtitle = GroupMembershipWidget( group: group, - onUpdated: () => _refreshKey.currentState.show(), + onUpdated: () => _refreshKey.currentState!.show(), onError: _onGroupMembershipUpdateError, ); } else { - subtitle = Text(diffTimeFromNowToStr(membership.lastActive)); + subtitle = Text(diffTimeFromNowToStr(membership.lastActive!)!); } // Main group information return ListTile( @@ -197,17 +201,17 @@ class _MembershipsPanelState extends SafeState { ), title: Text(group.displayName), subtitle: subtitle, - onTap: () => MainController.of(context).openGroup(group.id), + onTap: () => MainController.of(context)!.openGroup(group.id), ); } Widget _buildConversationMembership(Membership membership, [bool allowGroup = false]) { - final conversation = membership.conversation; + final conversation = membership.conversation!; if (conversation.isGroupConversation && !allowGroup) return Container(); - Color color; + Color? color; if (conversation.isHavingCall) color = Color(0xFF815d1d); else if (widget.currentPage.type == PageType.CONVERSATION_PAGE && @@ -221,7 +225,7 @@ class _MembershipsPanelState extends SafeState { dense: true, leading: ConversationImageWidget( conversation: conversation, - users: _usersList, + users: _usersList!, noUserImage: conversation.isGroupConversation, ), title: Row( @@ -233,20 +237,20 @@ class _MembershipsPanelState extends SafeState { SizedBox(width: 5), Expanded( child: Text(ConversationsHelper.getConversationName( - conversation, _usersList)), + conversation, _usersList)!), ), ], ), - subtitle: Text(diffTimeFromNowToStr(membership.lastActive) + - (conversation.isHavingCall ? "\n" + tr("Ongoing call") : "")), - onTap: () => MainController.of(context) + 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), + MainController.of(context)!.startCall(conversation.id!), ) : null, ), @@ -269,43 +273,43 @@ class _MembershipsPanelState extends SafeState { if (accept) f.accepted = true; else - _membershipList.removeFriend(f.id); + _membershipList!.removeFriend(f.id); }); - _refreshKey.currentState.show(); + _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!")); + 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(); + 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 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, + 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)), + child: Text(text!, style: TextStyle(color: color)), ); } } diff --git a/lib/ui/widgets/tablet_mode/tablet_appbar_widget.dart b/lib/ui/widgets/tablet_mode/tablet_appbar_widget.dart index 113a6d1..a689352 100644 --- a/lib/ui/widgets/tablet_mode/tablet_appbar_widget.dart +++ b/lib/ui/widgets/tablet_mode/tablet_appbar_widget.dart @@ -63,12 +63,12 @@ class _ComunicTabletAppBarWidgetState return AppBar( title: GestureDetector( child: Text("Comunic"), - onTap: () => MainController.of(context).openLatestPostsPage()), + onTap: () => MainController.of(context)!.openLatestPostsPage()), actions: [ AppBarCustomDropDownWidget( key: notificationsDropdownKey, icon: Icon(Icons.notifications), - notificationsBadge: _unreadNotifications.notifications, + notificationsBadge: _unreadNotifications.notifications!, onBuildOverlay: (c) => Padding( padding: const EdgeInsets.all(8.0), child: NotificationsScreen(useSmallDeleteButton: true), @@ -77,7 +77,7 @@ class _ComunicTabletAppBarWidgetState AppBarCustomDropDownWidget( key: conversationsDropdownKey, icon: Icon(Icons.message), - notificationsBadge: _unreadNotifications.conversations, + notificationsBadge: _unreadNotifications.conversations!, onBuildOverlay: (c) => Padding( padding: const EdgeInsets.all(8.0), child: UnreadConversationsScreen(), @@ -88,29 +88,29 @@ class _ComunicTabletAppBarWidgetState itemBuilder: (c) => [ // Get groups _MainMenuItem( - label: tr("Groups"), + label: tr("Groups")!, icon: Icons.group, - onTap: () => MainController.of(context).openGroupsListPage()), + onTap: () => MainController.of(context)!.openGroupsListPage()), // Toggle dark theme _MainMenuItem( - label: tr("Night mode"), - icon: preferences().preferences.enableDarkMode + label: tr("Night mode")!, + icon: preferences()!.preferences.enableDarkMode ? Icons.brightness_2 : Icons.wb_sunny, onTap: _toggleDarkMode), // Open settings _MainMenuItem( - label: tr("Settings"), + label: tr("Settings")!, icon: Icons.settings, - onTap: () => MainController.of(context).openSettings()), + onTap: () => MainController.of(context)!.openSettings()), // Sign out _MainMenuItem( - label: tr("Sign out"), + label: tr("Sign out")!, icon: Icons.power_settings_new, - onTap: () => MainController.of(context).requestLogout()), + onTap: () => MainController.of(context)!.requestLogout()), ], onSelected: (v) => v(), ), @@ -120,9 +120,9 @@ class _ComunicTabletAppBarWidgetState /// Toggle dark mode void _toggleDarkMode() async { - final prefs = preferences().preferences; + final prefs = preferences()!.preferences; prefs.enableDarkMode = !prefs.enableDarkMode; - await preferences().setPreferences(prefs); + await preferences()!.setPreferences(prefs); applyNewThemeSettings(context); } @@ -136,9 +136,9 @@ class _MainMenuItem extends PopupMenuEntry<_MenuItemCallback> { final _MenuItemCallback onTap; const _MainMenuItem({ - @required this.label, - @required this.icon, - @required this.onTap, + required this.label, + required this.icon, + required this.onTap, }) : assert(label != null), assert(icon != null), assert(onTap != null); @@ -150,7 +150,7 @@ class _MainMenuItem extends PopupMenuEntry<_MenuItemCallback> { double get height => kMinInteractiveDimension; @override - bool represents(_MenuItemCallback value) => onTap == value; + bool represents(_MenuItemCallback? value) => onTap == value; } class __MainMenuItemState extends State<_MainMenuItem> { diff --git a/lib/ui/widgets/tablet_mode/user_page_tablet.dart b/lib/ui/widgets/tablet_mode/user_page_tablet.dart index 3df884f..cdcc30c 100644 --- a/lib/ui/widgets/tablet_mode/user_page_tablet.dart +++ b/lib/ui/widgets/tablet_mode/user_page_tablet.dart @@ -23,14 +23,14 @@ import 'package:flutter/material.dart'; class UserPageTablet extends StatefulWidget { final AdvancedUserInfo userInfo; - final FriendStatus friendshipStatus; + final FriendStatus? friendshipStatus; final void Function() onNeedRefresh; const UserPageTablet({ - Key key, - @required this.userInfo, - @required this.friendshipStatus, - @required this.onNeedRefresh, + Key? key, + required this.userInfo, + required this.friendshipStatus, + required this.onNeedRefresh, }) : assert(userInfo != null), assert(onNeedRefresh != null), super(key: key); @@ -106,7 +106,7 @@ class _UserPageTabletState extends State { _isCurrentUser ? Container() : FriendshipStatusWidget( - status: widget.friendshipStatus, + status: widget.friendshipStatus!, onFriendshipUpdated: widget.onNeedRefresh, ) ], @@ -124,7 +124,7 @@ class _UserPageTabletState extends State { _userInfo.isFriendsListPublic ? Expanded( child: OutlinedButton.icon( - onPressed: () => MainController.of(context) + onPressed: () => MainController.of(context)! .openUserFriendsList(_userInfo.id), icon: Icon(Icons.group), label: Text("${_userInfo.numberFriends}"), @@ -153,7 +153,7 @@ class _UserPageTabletState extends State { // User membership _AboutUserEntry( icon: Icons.access_time, - title: tr("Membership"), + title: tr("Membership")!, value: tr("Member for %t%", args: { "t": diffTimeFromNowToStr(_userInfo.accountCreationTime) })), @@ -161,7 +161,7 @@ class _UserPageTabletState extends State { // User public note _AboutUserEntry( icon: Icons.note, - title: tr("Note"), + title: tr("Note")!, value: _userInfo.publicNote, visible: _userInfo.hasPublicNote, parsed: true, @@ -170,7 +170,7 @@ class _UserPageTabletState extends State { // User email address _AboutUserEntry( icon: Icons.mail_outline, - title: tr("Email address"), + title: tr("Email address")!, value: _userInfo.emailAddress, visible: _userInfo.emailAddress != null, ), @@ -178,7 +178,7 @@ class _UserPageTabletState extends State { // Location _AboutUserEntry( icon: Icons.location_on, - title: tr("Location"), + title: tr("Location")!, value: _userInfo.location, visible: _userInfo.location != null, ), @@ -186,7 +186,7 @@ class _UserPageTabletState extends State { // User website _AboutUserEntry( icon: Icons.link, - title: tr("Website"), + title: tr("Website")!, value: _userInfo.personalWebsite, visible: _userInfo.hasPersonalWebsite, parsed: true, @@ -197,9 +197,9 @@ class _UserPageTabletState extends State { } class _LeftPaneContainer extends StatelessWidget { - final Widget child; + final Widget? child; - const _LeftPaneContainer({Key key, this.child}) : super(key: key); + const _LeftPaneContainer({Key? key, this.child}) : super(key: key); @override Widget build(BuildContext context) { @@ -218,7 +218,7 @@ class _LeftPaneContainer extends StatelessWidget { class _MainCardSpacer extends StatelessWidget { final bool visible; - const _MainCardSpacer({this.visible = true, Key key}) + const _MainCardSpacer({this.visible = true, Key? key}) : assert(visible != null), super(key: key); @@ -230,15 +230,15 @@ class _MainCardSpacer extends StatelessWidget { class _AboutUserEntry extends StatelessWidget { final IconData icon; final String title; - final String value; + final String? value; final bool visible; final bool parsed; const _AboutUserEntry({ - Key key, - @required this.icon, - @required this.title, - @required this.value, + Key? key, + required this.icon, + required this.title, + required this.value, this.visible = true, this.parsed = false, }) : assert(icon != null), @@ -268,7 +268,7 @@ class _AboutUserEntry extends StatelessWidget { content: DisplayedString(value), style: TextStyle(), ) - : Text(value), + : Text(value!), dense: true, ); } diff --git a/lib/ui/widgets/text_rich_content_widget.dart b/lib/ui/widgets/text_rich_content_widget.dart index 41f1caf..7f841d5 100644 --- a/lib/ui/widgets/text_rich_content_widget.dart +++ b/lib/ui/widgets/text_rich_content_widget.dart @@ -11,8 +11,8 @@ import 'package:url_launcher/url_launcher.dart'; /// @author Pierre HUBERT class TextRichContentWidget extends StatelessWidget { - final TextAlign textAlign; - final TextStyle style; + final TextAlign? textAlign; + final TextStyle? style; final String text; TextRichContentWidget( @@ -22,7 +22,7 @@ class TextRichContentWidget extends StatelessWidget { }) : assert(text != null); /// Parse the text and return it as a list of span elements - static List _parse(String text, TextStyle style) { + static List _parse(String text, TextStyle? style) { if (style == null) style = TextStyle(); List list = []; @@ -37,7 +37,7 @@ class TextRichContentWidget extends StatelessWidget { // Add link list.add(TextSpan( - style: style.copyWith(color: Colors.indigo), + style: style!.copyWith(color: Colors.indigo), text: s, recognizer: TapGestureRecognizer() ..onTap = () { @@ -63,6 +63,6 @@ class TextRichContentWidget extends StatelessWidget { @override Widget build(BuildContext context) { return RichText( - textAlign: textAlign, text: TextSpan(children: _parse(text, style))); + textAlign: textAlign!, text: TextSpan(children: _parse(text, style))); } } diff --git a/lib/ui/widgets/text_widget.dart b/lib/ui/widgets/text_widget.dart index a0a6db8..f489eeb 100644 --- a/lib/ui/widgets/text_widget.dart +++ b/lib/ui/widgets/text_widget.dart @@ -13,13 +13,13 @@ import 'package:url_launcher/url_launcher.dart'; class TextWidget extends StatelessWidget { final DisplayedString content; final bool parseBBcode; - final TextStyle style; + final TextStyle? style; final TextAlign textAlign; final Color linksColor; const TextWidget({ - Key key, - @required this.content, + Key? key, + required this.content, this.parseBBcode = false, this.textAlign = TextAlign.start, this.style, @@ -35,7 +35,7 @@ class TextWidget extends StatelessWidget { var usedStyle = style == null ? Theme.of(context).textTheme.bodyText2 : style; - var content = this.content.parsedString; + var content = this.content.parsedString!; /*// Parse BBcode if (parseBBcode) @@ -53,7 +53,7 @@ class TextWidget extends StatelessWidget { /// Sub parse function List _parseLinks( - BuildContext context, String text, TextStyle style) { + BuildContext context, String text, TextStyle? style) { var buff = StringBuffer(); final list = []; @@ -79,7 +79,7 @@ class TextWidget extends StatelessWidget { child: InkWell( child: Text( word, - style: style.copyWith(color: linksColor), + style: style!.copyWith(color: linksColor), ), onTap: () => launch(word), ), @@ -98,7 +98,7 @@ class TextWidget extends StatelessWidget { child: InkWell( child: Text( word, - style: style.copyWith(color: linksColor), + style: style!.copyWith(color: linksColor), ), onTap: () => openVirtualDirectory(context, word), ), diff --git a/lib/ui/widgets/tour/account_image_tour_pane.dart b/lib/ui/widgets/tour/account_image_tour_pane.dart index 0779326..612a2ec 100644 --- a/lib/ui/widgets/tour/account_image_tour_pane.dart +++ b/lib/ui/widgets/tour/account_image_tour_pane.dart @@ -9,11 +9,11 @@ class AccountImageTourPane extends PresentationPane { final Function(BuildContext) onUpdated; AccountImageTourPane({ - @required User user, - @required this.onUpdated, + required User user, + required this.onUpdated, }) : super( iconWidget: AccountImageWidget(user: user, width: 50), - title: tr("Account image"), + title: tr("Account image")!, text: "${tr("Account images allow to quickly recognize people.")}\n\n${tr("You can decide to define one now!")}", actionTitle: tr("Upload an account image"), diff --git a/lib/ui/widgets/tour/first_pane.dart b/lib/ui/widgets/tour/first_pane.dart index 6b23fb7..b8f4a83 100644 --- a/lib/ui/widgets/tour/first_pane.dart +++ b/lib/ui/widgets/tour/first_pane.dart @@ -8,10 +8,10 @@ import 'package:flutter/material.dart'; /// @author Pierre Hubert class FirstTourPane extends StatelessWidget { - final String msgOne; - final String msgTwo; + final String? msgOne; + final String? msgTwo; - const FirstTourPane({Key key, this.msgOne, this.msgTwo}) : super(key: key); + const FirstTourPane({Key? key, this.msgOne, this.msgTwo}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/ui/widgets/tour/fixed_tour_size_text_area.dart b/lib/ui/widgets/tour/fixed_tour_size_text_area.dart index c7d34bb..ea3b1ca 100644 --- a/lib/ui/widgets/tour/fixed_tour_size_text_area.dart +++ b/lib/ui/widgets/tour/fixed_tour_size_text_area.dart @@ -4,13 +4,13 @@ import 'package:flutter/material.dart'; class FixedTourSizeTextArea extends StatelessWidget { - final String text; + final String? text; const FixedTourSizeTextArea(this.text); @override Widget build(BuildContext context) => ConstrainedBox( constraints: BoxConstraints(maxWidth: 300), - child: Text(text, textAlign: TextAlign.justify), + child: Text(text!, textAlign: TextAlign.justify), ); } diff --git a/lib/ui/widgets/tour/last_pane.dart b/lib/ui/widgets/tour/last_pane.dart index 54e3ea8..6780596 100644 --- a/lib/ui/widgets/tour/last_pane.dart +++ b/lib/ui/widgets/tour/last_pane.dart @@ -10,7 +10,7 @@ class LastTourPane extends StatelessWidget { Widget build(BuildContext context) { return Center( child: Text( - tr("The application is yours"), + tr("The application is yours")!, style: TextStyle(fontSize: 25), ), ); diff --git a/lib/ui/widgets/tour/presentation_pane.dart b/lib/ui/widgets/tour/presentation_pane.dart index 9e8abd0..5ef974d 100644 --- a/lib/ui/widgets/tour/presentation_pane.dart +++ b/lib/ui/widgets/tour/presentation_pane.dart @@ -5,22 +5,22 @@ import 'package:comunic/ui/widgets/tour/fixed_tour_size_text_area.dart'; import 'package:flutter/material.dart'; class PresentationPane extends StatelessWidget { - final IconData icon; - final Widget iconWidget; + final IconData? icon; + final Widget? iconWidget; final String title; - final String text; - final Function(BuildContext) child; - final String actionTitle; - final Function(BuildContext) onActionTap; + final String? text; + final Function(BuildContext)? child; + final String? actionTitle; + final Function(BuildContext)? onActionTap; final bool canGoNext; - final Future Function(BuildContext) onTapNext; + final Future Function(BuildContext)? onTapNext; final bool visible; const PresentationPane({ - Key key, + Key? key, this.icon, this.iconWidget, - @required this.title, + required this.title, this.text, this.child, this.actionTitle, @@ -41,7 +41,7 @@ class PresentationPane extends StatelessWidget { return Column( children: [ Spacer(flex: 3), - icon != null ? Icon(icon, color: Colors.white, size: 50) : iconWidget, + icon != null ? Icon(icon, color: Colors.white, size: 50) : iconWidget!, Spacer(flex: 1), Text( title, @@ -52,9 +52,9 @@ class PresentationPane extends StatelessWidget { Spacer(flex: 1), _hasAction ? OutlinedButton( - onPressed: () => onActionTap(context), + onPressed: () => onActionTap!(context), child: Text( - actionTitle, + actionTitle!, style: TextStyle(color: Colors.white), ), ) @@ -72,7 +72,7 @@ class PresentationPane extends StatelessWidget { return Column( children: [ Spacer(flex: 1), - icon != null ? Icon(icon, color: Colors.white, size: 50) : iconWidget, + icon != null ? Icon(icon, color: Colors.white, size: 50) : iconWidget!, Spacer(flex: 1), Text( title, @@ -81,7 +81,7 @@ class PresentationPane extends StatelessWidget { Spacer(flex: 1), ConstrainedBox( constraints: BoxConstraints(maxHeight: 300), - child: SingleChildScrollView(child: child(context))), + child: SingleChildScrollView(child: child!(context))), Spacer(flex: 1), ], ); diff --git a/lib/ui/widgets/tour/tour_notifications_pane.dart b/lib/ui/widgets/tour/tour_notifications_pane.dart index b3f85fc..9efac54 100644 --- a/lib/ui/widgets/tour/tour_notifications_pane.dart +++ b/lib/ui/widgets/tour/tour_notifications_pane.dart @@ -11,24 +11,24 @@ import 'package:flutter/material.dart'; class TourNotificationsPane extends PresentationPane { TourNotificationsPane({ - Key key, - @required + Key? key, + required GlobalKey pushNotificationsKey, - @required Function() onConfigured, - @required Function() onChanged, - @required bool visible, + required Function() onConfigured, + required Function() onChanged, + required bool visible, }) : assert(pushNotificationsKey != null), super( icon: Icons.notifications, - title: tr("Push notifications"), + title: tr("Push notifications")!, child: (c) => PushNotificationsConfigurationWidget( key: pushNotificationsKey, onConfigured: onConfigured, onChanged: onChanged, ), canGoNext: pushNotificationsKey?.currentState?.canSubmit ?? false, - onTapNext: (c) => pushNotificationsKey.currentState.submit(), + onTapNext: (c) => pushNotificationsKey.currentState!.submit(), visible: visible, ); } diff --git a/lib/ui/widgets/user_writing_in_conv_notifier.dart b/lib/ui/widgets/user_writing_in_conv_notifier.dart index 118d66b..e3b0e77 100644 --- a/lib/ui/widgets/user_writing_in_conv_notifier.dart +++ b/lib/ui/widgets/user_writing_in_conv_notifier.dart @@ -14,7 +14,7 @@ import 'package:flutter/material.dart'; class UserWritingInConvNotifier extends StatefulWidget { final int convID; - const UserWritingInConvNotifier({Key key, @required this.convID}) + const UserWritingInConvNotifier({Key? key, required this.convID}) : assert(convID != null), super(key: key); @@ -52,14 +52,14 @@ class _UserWritingInConvNotifierState child: Align( alignment: Alignment.centerLeft, child: Text( - writingText, + writingText!, style: TextStyle(fontSize: 10), textAlign: TextAlign.justify, ), ), ); - String get writingText { + String? get writingText { if (_list.isEmpty) return ""; final users = _list.toSet().map((e) => _usersInfo.getUser(e)).toList(); @@ -73,11 +73,11 @@ class _UserWritingInConvNotifierState }); } - void _handleEvent(int userID) async { + void _handleEvent(int? userID) async { setState(() => this._list.add(userID)); await Future.delayed( - Duration(seconds: srvConfig.conversationsPolicy.writingEventLifetime)); + Duration(seconds: srvConfig!.conversationsPolicy.writingEventLifetime)); setState(() => this._list.removeAt(0)); } diff --git a/lib/utils/account_utils.dart b/lib/utils/account_utils.dart index f9d28f0..a81e358 100644 --- a/lib/utils/account_utils.dart +++ b/lib/utils/account_utils.dart @@ -5,6 +5,6 @@ import 'package:comunic/helpers/account_helper.dart'; /// @author Pierre HUBERT /// Get the ID of the current user -int userID() { +int? userID() { return AccountHelper.getCurrentUserID(); } \ No newline at end of file diff --git a/lib/utils/api_utils.dart b/lib/utils/api_utils.dart index 13b8dbf..815b1cb 100644 --- a/lib/utils/api_utils.dart +++ b/lib/utils/api_utils.dart @@ -3,8 +3,8 @@ /// @author Pierre Hubert /// Casting helper -T cast(dynamic val) => val is T ? val : null; +T? cast(dynamic val) => val is T ? val : null; /// Turn null and "null" into "" -String nullToEmpty(String input) => +String nullToEmpty(String? input) => input == null || input == "null" ? "" : input; diff --git a/lib/utils/bbcode_parser.dart b/lib/utils/bbcode_parser.dart index cdbe480..1b3e743 100644 --- a/lib/utils/bbcode_parser.dart +++ b/lib/utils/bbcode_parser.dart @@ -6,33 +6,33 @@ import 'package:flutter/material.dart'; /// This callback return null if the text has to be left as is or a TextSpan /// if it has been sub parsed... -typedef ParseCallBack = List Function(TextStyle, String); +typedef ParseCallBack = List Function(TextStyle, String?); class BBCodeParsedWidget extends StatelessWidget { - final _Element _content; - final ParseCallBack parseCallback; + final _Element? _content; + final ParseCallBack? parseCallback; - BBCodeParsedWidget({@required String text, this.parseCallback}) + BBCodeParsedWidget({required String text, this.parseCallback}) : assert(text != null), _content = _parse(text); _printRecur(_Element el, {int pos = 0}) { String str; str = "".padLeft(pos, "*"); - if (el.text != null) print(str + el.text); - el.children.forEach((f) => _printRecur(f, pos: pos + 1)); + if (el.text != null) print(str + el.text!); + el.children.forEach((f) => _printRecur(f!, pos: pos + 1)); } @override Widget build(BuildContext context) { - _printRecur(_content); + _printRecur(_content!); return RichText( - text: _content.toTextSpan(context, parseCallback), + text: _content!.toTextSpan(context, parseCallback), ); } /// Initialize parsing - static _Element _parse(String text) { + static _Element? _parse(String text) { try { return _parseRecur( text: text, @@ -48,19 +48,19 @@ class BBCodeParsedWidget extends StatelessWidget { /// Recursive parsing static _ElementRecur _parseRecur({ - @required String text, - @required _ElementStyle style, - @required int pos, - String parentTag, + required String text, + required _ElementStyle style, + required int pos, + String? parentTag, }) { _Element el = _Element(style: style.clone()); - int lastBeginPos = pos; + int? lastBeginPos = pos; int childNumber = 0; bool stop = false; - while (!stop && pos < text.length) { + while (!stop && pos! < text.length) { //Go to next stop - while (!stop && pos < text.length) { + while (!stop && pos! < text.length) { if (text[pos] == '[') break; pos++; } @@ -68,7 +68,7 @@ class BBCodeParsedWidget extends StatelessWidget { //Check for text with default style to apply if (lastBeginPos != pos) el.children.add(_Element( - style: style.clone(), text: text.substring(lastBeginPos, pos))); + style: style.clone(), text: text.substring(lastBeginPos!, pos))); //Check if the [ tag is alone if (pos == text.length) @@ -89,7 +89,7 @@ class BBCodeParsedWidget extends StatelessWidget { // Prepare tag detection final closeBrace = text.indexOf("]", pos); String tag = text.substring(pos + 1, closeBrace); - String arg; + String? arg; final newStyle = style.clone(); //Check for argument @@ -126,7 +126,7 @@ class BBCodeParsedWidget extends StatelessWidget { } /// Pre-parse tag - static void _preParseTag(String tag, _ElementStyle style, [String arg]) { + static void _preParseTag(String tag, _ElementStyle style, [String? arg]) { switch (tag) { // Bold case "b": @@ -153,9 +153,9 @@ class BBCodeParsedWidget extends StatelessWidget { assert(arg != null); style.color = Color.fromARGB( 255, - int.tryParse(arg.substring(1, 3), radix: 16), - int.tryParse(arg.substring(3, 5), radix: 16), - int.tryParse(arg.substring(5, 7), radix: 16), + int.tryParse(arg!.substring(1, 3), radix: 16)!, + int.tryParse(arg.substring(3, 5), radix: 16)!, + int.tryParse(arg.substring(5, 7), radix: 16)!, ); break; @@ -167,18 +167,18 @@ class BBCodeParsedWidget extends StatelessWidget { } /// Post-parse tag - static void _postParseTag(String tag, _Element el, - {String arg, String parentTag, int childNumber}) { + static void _postParseTag(String tag, _Element? el, + {String? arg, String? parentTag, int? childNumber}) { // List container if (tag == "ul" || tag == "ol") - el.children.insert(0, _Element(style: el.style, text: "\n")); + el!.children.insert(0, _Element(style: el.style, text: "\n")); // List children if (tag == "li") { - el.children.add(_Element(style: el.style, text: "\n")); + el!.children.add(_Element(style: el.style, text: "\n")); if (parentTag == "ol") el.children.insert( - 0, _Element(style: el.style, text: " ${childNumber + 1}. ")); + 0, _Element(style: el.style, text: " ${childNumber! + 1}. ")); else el.children.insert(0, _Element(style: el.style, text: " \u2022 ")); } @@ -187,20 +187,20 @@ class BBCodeParsedWidget extends StatelessWidget { /// An element's style class _ElementStyle { - TextDecoration decoration; - FontWeight fontWeight; - FontStyle fontStyle; - Color color; + TextDecoration? decoration; + FontWeight? fontWeight; + FontStyle? fontStyle; + Color? color; /// Generate an empty style _ElementStyle.empty(); /// Construct an instance of this element _ElementStyle( - {@required this.decoration, - @required this.fontWeight, - @required this.fontStyle, - @required this.color}); + {required this.decoration, + required this.fontWeight, + required this.fontStyle, + required this.color}); /// Clone this style _ElementStyle clone() { @@ -213,7 +213,7 @@ class _ElementStyle { /// Generate corresponding TextStyle TextStyle toTextStyle(BuildContext context) { - return Theme.of(context).textTheme.bodyText2.copyWith( + return Theme.of(context).textTheme.bodyText2!.copyWith( decoration: decoration, fontWeight: fontWeight, fontStyle: fontStyle, @@ -224,14 +224,14 @@ class _ElementStyle { /// An element class _Element { /// Note : if text is not null, children must be empty !!! - String text; + String? text; final _ElementStyle style; - final List<_Element> children = []; + final List<_Element?> children = []; - _Element({@required this.style, this.text}); + _Element({required this.style, this.text}); /// Turn this element into a TextSpan - TextSpan toTextSpan(BuildContext context, ParseCallBack parseCallback) { + TextSpan toTextSpan(BuildContext context, ParseCallBack? parseCallback) { assert(text == null || children.length == 0); final generatedStyle = this.style.toTextStyle(context); @@ -250,14 +250,14 @@ class _Element { text: text, style: generatedStyle, children: - children.map((f) => f.toTextSpan(context, parseCallback)).toList(), + children.map((f) => f!.toTextSpan(context, parseCallback)).toList(), ); } } class _ElementRecur { - final _Element el; + final _Element? el; final int finalPos; - const _ElementRecur({this.el, this.finalPos}); + const _ElementRecur({this.el, required this.finalPos}); } diff --git a/lib/utils/clipboard_utils.dart b/lib/utils/clipboard_utils.dart index 9aff4ad..4edb2bf 100644 --- a/lib/utils/clipboard_utils.dart +++ b/lib/utils/clipboard_utils.dart @@ -10,5 +10,5 @@ import 'intl_utils.dart'; void copyToClipboard(BuildContext context, String content) { FlutterClipboard.copy(content); - snack(context, tr("'%1%' copied to clipboard!", args: {"1": content})); + snack(context, tr("'%1%' copied to clipboard!", args: {"1": content})!); } diff --git a/lib/utils/color_utils.dart b/lib/utils/color_utils.dart index 5e14281..329cfad 100644 --- a/lib/utils/color_utils.dart +++ b/lib/utils/color_utils.dart @@ -4,7 +4,7 @@ import 'dart:ui'; /// /// @author Pierre Hubert -String colorToHex(Color color) { +String colorToHex(Color? color) { if (color == null) return ""; return (color.red.toRadixString(16).padLeft(2, '0') + diff --git a/lib/utils/conversations_utils.dart b/lib/utils/conversations_utils.dart index d23db9a..53d1f05 100644 --- a/lib/utils/conversations_utils.dart +++ b/lib/utils/conversations_utils.dart @@ -9,17 +9,17 @@ import 'package:flutter/material.dart'; /// @author Pierre HUBERT /// Open a private conversation with a given [userID] -Future openPrivateConversation(BuildContext context, int userID) async { +Future openPrivateConversation(BuildContext context, int? userID) async { try { final convID = await ConversationsHelper().getPrivate(userID); // Open the conversation - MainController.of(context).openConversationById(convID); + MainController.of(context)!.openConversationById(convID); return true; } catch (e, s) { print("Failed to find private conversation! $e => $s"); - showSimpleSnack(context, tr("Could not find a private conversation!")); + showSimpleSnack(context, tr("Could not find a private conversation!")!); return false; } } diff --git a/lib/utils/date_utils.dart b/lib/utils/date_utils.dart index a32b4c8..4d3ef59 100644 --- a/lib/utils/date_utils.dart +++ b/lib/utils/date_utils.dart @@ -10,7 +10,7 @@ int time() { return (DateTime.now().millisecondsSinceEpoch / 1000).floor(); } -String diffTimeToStr(int amount) { +String? diffTimeToStr(int amount) { if (amount < 0) amount = 0; // Seconds @@ -45,7 +45,7 @@ String diffTimeToStr(int amount) { : tr("%years% years", args: {"years": years.toString()}); } -String diffTimeFromNowToStr(int date) { +String? diffTimeFromNowToStr(int date) { return diffTimeToStr(time() - date); } @@ -59,7 +59,7 @@ String formatDuration(Duration d) => "${d.inMinutes < 10 ? "0" + d.inMinutes.toString() : d.inMinutes.toString()}:${d.inSeconds % 60 < 10 ? "0" + (d.inSeconds % 60).toString() : (d.inSeconds % 60).toString()}"; /// Compare two [DateTime] on their date -bool isSameDate(DateTime one, DateTime other) { +bool isSameDate(DateTime one, DateTime? other) { if (other == null) return false; return one.year == other.year && one.month == other.month && diff --git a/lib/utils/files_utils.dart b/lib/utils/files_utils.dart index 16b45a7..cfcce6f 100644 --- a/lib/utils/files_utils.dart +++ b/lib/utils/files_utils.dart @@ -16,8 +16,8 @@ import '../ui/dialogs/pick_file_dialog.dart'; /// Ask the user to choose an image, either from the gallery or using the camera /// /// Throws an exception null in case of failure -Future pickImage(BuildContext context, - {CropAspectRatio aspectRatio}) async { +Future pickImage(BuildContext context, + {CropAspectRatio? aspectRatio}) async { return await showPickFileDialog( context: context, allowedMimeTypes: ["image/png", "image/jpeg", "image/gif"], diff --git a/lib/utils/identicon_utils.dart b/lib/utils/identicon_utils.dart index 878fb37..923b22b 100644 --- a/lib/utils/identicon_utils.dart +++ b/lib/utils/identicon_utils.dart @@ -10,11 +10,10 @@ import 'package:random_string/random_string.dart'; /// /// @author Pierre Hubert - // Based on https://stackoverflow.com/a/63215502/3781411 Future svgToPng(BuildContext context, String svgString, - {int svgWidth, int svgHeight}) async { - DrawableRoot svgDrawableRoot = await svg.fromSvgString(svgString, null); + {int? svgWidth, int? svgHeight}) async { + DrawableRoot svgDrawableRoot = await svg.fromSvgString(svgString, "svg"); // to have a nice rendering it is important to have the exact original height and width, // the easier way to retrieve it is directly from the svg string @@ -40,7 +39,7 @@ Future svgToPng(BuildContext context, String svgString, // Convert to ui.Image. toImage() takes width and height as parameters // you need to find the best size to suit your needs and take into account the screen DPI final image = await picture.toImage(width.toInt(), height.toInt()); - ByteData bytes = await image.toByteData(format: ImageByteFormat.png); + ByteData bytes = (await image.toByteData(format: ImageByteFormat.png))!; return bytes.buffer.asUint8List(); } diff --git a/lib/utils/input_utils.dart b/lib/utils/input_utils.dart index dda67da..9deb845 100644 --- a/lib/utils/input_utils.dart +++ b/lib/utils/input_utils.dart @@ -12,7 +12,7 @@ bool legacyValidatePassword(String s) => s.length > 3; bool validateEmail(String value) { Pattern pattern = r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'; - RegExp regex = new RegExp(pattern); + RegExp regex = new RegExp(pattern as String); return regex.hasMatch(value); } diff --git a/lib/utils/intl_utils.dart b/lib/utils/intl_utils.dart index 85e045e..f0543f3 100644 --- a/lib/utils/intl_utils.dart +++ b/lib/utils/intl_utils.dart @@ -8,8 +8,8 @@ import 'package:intl/intl_standalone.dart'; /// /// @author Pierre HUBERT -String _currLang; -Map> translations; +String? _currLang; +late Map> translations; /// Initialize translations system /// @@ -35,22 +35,22 @@ Future initTranslations() async { /// /// Then apply the list of [args] to the string, each argument name is /// surrounded by '%' -String tr(String string, {Map args}) { +String? tr(String? string, {Map? args}) { // Check if a translation is available if (_currLang != null && translations.containsKey(_currLang) && - translations[_currLang].containsKey(string)) - string = translations[_currLang][string]; + translations[_currLang!]!.containsKey(string)) + string = translations[_currLang!]![string!]; //Apply arguments if (args != null) - args.forEach((key, value) => string = string.replaceAll("%$key%", value)); + args.forEach((key, value) => string = string!.replaceAll("%$key%", value!)); return string; } /// Get current lang, in format aa_BB -String/*!*/ get lang => _currLang != null ? _currLang : "en_US"; +String get lang => _currLang != null ? _currLang! : "en_US"; /// Get short lang format, in format aa diff --git a/lib/utils/navigation_utils.dart b/lib/utils/navigation_utils.dart index 5aee510..2babc41 100644 --- a/lib/utils/navigation_utils.dart +++ b/lib/utils/navigation_utils.dart @@ -11,20 +11,20 @@ import 'package:flutter/material.dart'; /// Pop a page void popPage(BuildContext context) { - MainController.of(context).popPage(); + MainController.of(context)!.popPage(); } /// Open the page of a user -void openUserPage({@required int userID, @required BuildContext context}) { +void openUserPage({required int userID, required BuildContext context}) { assert(userID != null); assert(context != null); - MainController.of(context).openUserPage(userID); + MainController.of(context)!.openUserPage(userID); } /// Open a post in full screen void openPostFullScreen(int postID, BuildContext context) { - MainController.of(context).push(SinglePostRoute(postID: postID)); + MainController.of(context)!.push(SinglePostRoute(postID: postID)); } /// Open a virtual directory @@ -36,22 +36,22 @@ void openVirtualDirectory(BuildContext context, String directory) async { switch (result.type) { case VirtualDirectoryType.USER: - openUserPage(context: context, userID: result.id); + openUserPage(context: context, userID: result.id!); break; case VirtualDirectoryType.GROUP: - MainController.of(context).openGroup(result.id); + MainController.of(context)!.openGroup(result.id!); break; case VirtualDirectoryType.NONE: await showDialog( context: context, builder: (c) => AlertDialog( - title: Text(tr("Error")), - content: Text(tr("Could not find related resource!")), + title: Text(tr("Error")!), + content: Text(tr("Could not find related resource!")!), actions: [ MaterialButton( - child: Text(tr("OK")), + child: Text(tr("OK")!), onPressed: () => Navigator.of(c).pop(), ) ], @@ -61,6 +61,6 @@ void openVirtualDirectory(BuildContext context, String directory) async { } catch (e, stack) { print(e); print(stack); - showSimpleSnack(context, tr("Could not search virtual directory!")); + showSimpleSnack(context, tr("Could not search virtual directory!")!); } } diff --git a/lib/utils/ui_utils.dart b/lib/utils/ui_utils.dart index 7eb9827..1f081bd 100644 --- a/lib/utils/ui_utils.dart +++ b/lib/utils/ui_utils.dart @@ -23,7 +23,7 @@ Widget buildCenteredProgressBar() { /// Build and return a full loading page Widget buildLoadingPage({ bool showAppBar = false, - String routeTitle, + String? routeTitle, }) { return Scaffold( appBar: showAppBar @@ -36,8 +36,8 @@ Widget buildLoadingPage({ } /// Build and return an error card -Widget buildErrorCard(String message, - {List actions, bool hide = false}) { +Widget buildErrorCard(String? message, + {List? actions, bool hide = false}) { if (hide) return Container(); return Theme( @@ -59,7 +59,7 @@ Widget buildErrorCard(String message, ), Flexible( child: Text( - message, + message!, maxLines: null, ), ), @@ -74,9 +74,9 @@ Widget buildErrorCard(String message, } /// Show an image with a given [url] in full screen -void showImageFullScreen(BuildContext context, String url) { +void showImageFullScreen(BuildContext context, String? url) { Navigator.of(context).push(MaterialPageRoute(builder: (c) { - return FullScreenImageRoute(url); + return FullScreenImageRoute(url!); })); } @@ -92,12 +92,12 @@ void snack(BuildContext context, String message) { /// Show an alert dialog to ask the user to enter a string /// /// Returns entered string if the dialog is confirmed, null else -Future askUserString({ - @required BuildContext context, - @required String title, - @required String message, - @required String defaultValue, - @required String hint, +Future askUserString({ + required BuildContext context, + required String title, + required String message, + required String defaultValue, + required String hint, int maxLength = 200, int minLength = 1, }) async { @@ -135,13 +135,13 @@ class _InputTextDialog extends StatefulWidget { final String hint; const _InputTextDialog({ - Key key, - @required this.title, - @required this.message, - @required this.controller, - @required this.maxLength, - @required this.minLength, - @required this.hint, + Key? key, + required this.title, + required this.message, + required this.controller, + required this.maxLength, + required this.minLength, + required this.hint, }) : super(key: key); @override @@ -172,11 +172,11 @@ class __InputTextDialogState extends State<_InputTextDialog> { ), actions: [ TextButton( - child: Text(tr("Cancel").toUpperCase()), + child: Text(tr("Cancel")!.toUpperCase()), onPressed: () => Navigator.pop(c, false), ), TextButton( - child: Text(tr("OK")), + child: Text(tr("OK")!), onPressed: widget.controller.text.length >= widget.minLength ? () => Navigator.pop(c, true) : null, @@ -189,9 +189,9 @@ class __InputTextDialogState extends State<_InputTextDialog> { /// /// Return value of this function is never null Future showConfirmDialog({ - @required BuildContext context, - String title, - @required String message, + required BuildContext context, + String? title, + required String? message, }) async { if (title == null) title = tr("Confirm operation"); @@ -202,17 +202,17 @@ Future showConfirmDialog({ final result = await showDialog( context: ctx, builder: (c) => AlertDialog( - title: Text(title), - content: Text(message), + title: Text(title!), + content: Text(message!), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), - child: Text(tr("Cancel").toUpperCase()), + child: Text(tr("Cancel")!.toUpperCase()), ), TextButton( onPressed: () => Navigator.pop(context, true), child: Text( - tr("Confirm").toUpperCase(), + tr("Confirm")!.toUpperCase(), style: TextStyle(color: Colors.red), ), ), @@ -224,15 +224,15 @@ Future showConfirmDialog({ /// Show a simple alert dialog Future showAlert({ - @required BuildContext context, - @required String message, - String title, + required BuildContext context, + required String? message, + String? title, }) async => await showDialog( context: context, builder: (c) => AlertDialog( title: title == null ? null : Text(title), - content: Text(message), + content: Text(message!), actions: [CancelDialogButton()], )); @@ -240,28 +240,28 @@ Future showAlert({ /// text has already been entered by the user Widget smartInputCounterWidgetBuilder( BuildContext context, { - @required int currentLength, - @required int maxLength, - @required bool isFocused, + required int currentLength, + required int? maxLength, + required bool isFocused, }) => currentLength > 0 ? Text("$currentLength/$maxLength") : Container(); /// Parse an HTML String to decode special characters -String htmlDecodeCharacters(String input) { +String htmlDecodeCharacters(String? input) { if (input == null || input == "") return ""; - return parse(input).documentElement.text; + return parse(input).documentElement!.text; } const darkAccentColor = Colors.white70; const darkerAccentColor = Colors.white30; /// Check out whether dark theme is enabled or not -bool darkTheme() => preferences().getBool(PreferencesKeyList.ENABLE_DARK_THEME); +bool darkTheme() => preferences()!.getBool(PreferencesKeyList.ENABLE_DARK_THEME); /// Check out whether we use tablet mode or not bool isTablet(BuildContext context) => - !preferences().getBool(PreferencesKeyList.FORCE_MOBILE_MODE) && + !preferences()!.getBool(PreferencesKeyList.FORCE_MOBILE_MODE) && MediaQuery.of(context).size.width >= 1024; /// Show about Comunic dialog @@ -272,7 +272,7 @@ void showAboutAppDialog(BuildContext context) { children: [ Text( tr(config().appQuickDescription) ?? - tr("Comunic is a free and OpenSource social network that respect your privacy."), + tr("Comunic is a free and OpenSource social network that respect your privacy.")!, textAlign: TextAlign.center, ), SizedBox( @@ -287,7 +287,7 @@ void showAboutAppDialog(BuildContext context) { /// Apply new theme settings void applyNewThemeSettings(BuildContext context) => - context.findAncestorStateOfType().refresh(); + context.findAncestorStateOfType()!.refresh(); /// Parse emojies String parseEmojies(String input) => EmojiParser().emojify(input); diff --git a/lib/utils/video_utils.dart b/lib/utils/video_utils.dart index 074caa2..4fc393a 100644 --- a/lib/utils/video_utils.dart +++ b/lib/utils/video_utils.dart @@ -2,7 +2,6 @@ import 'dart:io'; import 'package:comunic/models/api_request.dart'; import 'package:comunic/utils/log_utils.dart'; -import 'package:flutter/material.dart'; import 'package:video_thumbnail/video_thumbnail.dart'; import 'files_utils.dart'; @@ -12,16 +11,16 @@ import 'files_utils.dart'; /// @author Pierre Hubert /// Generate a thumbnail for a video. In case of failure, return null -Future generateVideoThumbnail({ - @required BytesFile videoFile, - int maxWidth, +Future generateVideoThumbnail({ + required BytesFile videoFile, + required int maxWidth, }) async { - File file; + File? file; try { file = await generateTemporaryFile(); - await file.writeAsBytes(videoFile.bytes); + await file.writeAsBytes(videoFile.bytes!); return BytesFile( "thumb.png", diff --git a/pubspec.lock b/pubspec.lock index c030f89..b25d363 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -93,7 +93,7 @@ packages: source: hosted version: "1.1.0" collection: - dependency: transitive + dependency: "direct main" description: name: collection url: "https://pub.dartlang.org" diff --git a/pubspec.yaml b/pubspec.yaml index 2837a23..20bd735 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -14,7 +14,7 @@ description: Comunic client version: 1.1.11+18 environment: - sdk: ">=2.7.0 <3.0.0" + sdk: '>=2.12.0 <3.0.0' dependencies: flutter: @@ -135,6 +135,7 @@ dependencies: # Forez presence table_calendar: ^3.0.4 + collection: ^1.15.0-nullsafety.4 dev_dependencies: flutter_test: