From 3f10c0bae65db5c5ae0f414251b250c824ec76b3 Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Fri, 19 Nov 2021 20:28:17 +0100 Subject: [PATCH 1/2] refactor: Make layouts null safe --- lib/widgets/layouts/empty_page.dart | 4 ++- lib/widgets/layouts/loading_view.dart | 31 ++++++++++------------ lib/widgets/layouts/max_width_body.dart | 6 +++-- lib/widgets/layouts/one_page_card.dart | 6 +++-- lib/widgets/layouts/side_view_layout.dart | 7 +++-- lib/widgets/layouts/two_column_layout.dart | 9 ++++--- 6 files changed, 36 insertions(+), 27 deletions(-) diff --git a/lib/widgets/layouts/empty_page.dart b/lib/widgets/layouts/empty_page.dart index fe56dde1..b7265a50 100644 --- a/lib/widgets/layouts/empty_page.dart +++ b/lib/widgets/layouts/empty_page.dart @@ -1,3 +1,5 @@ +//@dart=2.12 + import 'dart:math'; import 'package:flutter/material.dart'; @@ -5,7 +7,7 @@ import 'package:flutter/material.dart'; class EmptyPage extends StatelessWidget { final bool loading; static const double _width = 200; - const EmptyPage({this.loading = false, Key key}) : super(key: key); + const EmptyPage({this.loading = false, Key? key}) : super(key: key); @override Widget build(BuildContext context) { final _width = min(MediaQuery.of(context).size.width, EmptyPage._width); diff --git a/lib/widgets/layouts/loading_view.dart b/lib/widgets/layouts/loading_view.dart index 571b596e..45e55cc5 100644 --- a/lib/widgets/layouts/loading_view.dart +++ b/lib/widgets/layouts/loading_view.dart @@ -1,3 +1,5 @@ +//@dart=2.12 + import 'package:flutter/material.dart'; import 'package:matrix/matrix.dart'; @@ -7,26 +9,21 @@ import 'package:fluffychat/widgets/layouts/empty_page.dart'; import 'package:fluffychat/widgets/matrix.dart'; class LoadingView extends StatelessWidget { - const LoadingView({Key key}) : super(key: key); + const LoadingView({Key? key}) : super(key: key); @override Widget build(BuildContext context) { - if (Matrix.of(context) - .widget - .clients - .every((client) => client.loginState != null)) { - WidgetsBinding.instance.addPostFrameCallback( - (_) => VRouter.of(context).to( - Matrix.of(context) - .widget - .clients - .any((client) => client.loginState == LoginState.loggedIn) - ? '/rooms' - : '/home', - queryParameters: VRouter.of(context).queryParameters, - ), - ); - } + WidgetsBinding.instance?.addPostFrameCallback( + (_) => VRouter.of(context).to( + Matrix.of(context) + .widget + .clients + .any((client) => client.loginState == LoginState.loggedIn) + ? '/rooms' + : '/home', + queryParameters: VRouter.of(context).queryParameters, + ), + ); return const EmptyPage(loading: true); } } diff --git a/lib/widgets/layouts/max_width_body.dart b/lib/widgets/layouts/max_width_body.dart index b05f5ddc..f6a963e7 100644 --- a/lib/widgets/layouts/max_width_body.dart +++ b/lib/widgets/layouts/max_width_body.dart @@ -1,9 +1,11 @@ +//@dart=2.12 + import 'dart:math'; import 'package:flutter/material.dart'; class MaxWidthBody extends StatelessWidget { - final Widget child; + final Widget? child; final double maxWidth; final bool withScrolling; @@ -11,7 +13,7 @@ class MaxWidthBody extends StatelessWidget { this.child, this.maxWidth = 600, this.withScrolling = false, - Key key, + Key? key, }) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/widgets/layouts/one_page_card.dart b/lib/widgets/layouts/one_page_card.dart index 78ae7104..130c1cb0 100644 --- a/lib/widgets/layouts/one_page_card.dart +++ b/lib/widgets/layouts/one_page_card.dart @@ -1,3 +1,5 @@ +//@dart=2.12 + import 'dart:math'; import 'package:flutter/material.dart'; @@ -8,14 +10,14 @@ import 'package:fluffychat/widgets/matrix.dart'; class OnePageCard extends StatelessWidget { final Widget child; - const OnePageCard({Key key, this.child}) : super(key: key); + const OnePageCard({Key? key, required this.child}) : super(key: key); static const int alpha = 12; static num breakpoint = FluffyThemes.columnWidth * 2; @override Widget build(BuildContext context) { final horizontalPadding = - max((MediaQuery.of(context).size.width - 600) / 2, 24); + max((MediaQuery.of(context).size.width - 600) / 2, 24); return MediaQuery.of(context).size.width <= breakpoint || Matrix.of(context).client.isLogged() ? child diff --git a/lib/widgets/layouts/side_view_layout.dart b/lib/widgets/layouts/side_view_layout.dart index a38ab724..f54db182 100644 --- a/lib/widgets/layouts/side_view_layout.dart +++ b/lib/widgets/layouts/side_view_layout.dart @@ -1,3 +1,5 @@ +//@dart=2.12 + import 'package:flutter/material.dart'; import 'package:vrouter/vrouter.dart'; @@ -6,15 +8,16 @@ import 'package:fluffychat/config/themes.dart'; class SideViewLayout extends StatelessWidget { final Widget mainView; - final Widget sideView; + final Widget? sideView; - const SideViewLayout({Key key, @required this.mainView, this.sideView}) + const SideViewLayout({Key? key, required this.mainView, this.sideView}) : super(key: key); @override Widget build(BuildContext context) { var currentUrl = Uri.decodeFull(VRouter.of(context).url); if (!currentUrl.endsWith('/')) currentUrl += '/'; final hideSideView = currentUrl.split('/').length == 4; + final sideView = this.sideView; return sideView == null ? mainView : MediaQuery.of(context).size.width < FluffyThemes.columnWidth * 3.5 && diff --git a/lib/widgets/layouts/two_column_layout.dart b/lib/widgets/layouts/two_column_layout.dart index 3a25c60d..343399cd 100644 --- a/lib/widgets/layouts/two_column_layout.dart +++ b/lib/widgets/layouts/two_column_layout.dart @@ -1,3 +1,4 @@ +//@dart=2.12 import 'package:flutter/material.dart'; import 'package:fluffychat/config/themes.dart'; @@ -6,9 +7,11 @@ class TwoColumnLayout extends StatelessWidget { final Widget mainView; final Widget sideView; - const TwoColumnLayout( - {Key key, @required this.mainView, @required this.sideView}) - : super(key: key); + const TwoColumnLayout({ + Key? key, + required this.mainView, + required this.sideView, + }) : super(key: key); @override Widget build(BuildContext context) { if (MediaQuery.of(context).size.width <= FluffyThemes.columnWidth * 2) { From b73c6982a627d412bd2f00aa3be4c8e5cd1ab56a Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Fri, 19 Nov 2021 20:38:16 +0100 Subject: [PATCH 2/2] refactor: Make more widgets null safe --- lib/widgets/adaptive_flat_button.dart | 10 ++++++---- lib/widgets/avatar.dart | 23 +++++++++++++--------- lib/widgets/chat_settings_popup_menu.dart | 22 +++++++++++---------- lib/widgets/connection_status_header.dart | 15 ++++++++------ lib/widgets/contacts_list.dart | 21 +++++++++++--------- lib/widgets/layouts/two_column_layout.dart | 1 + 6 files changed, 54 insertions(+), 38 deletions(-) diff --git a/lib/widgets/adaptive_flat_button.dart b/lib/widgets/adaptive_flat_button.dart index e88200f4..0853184a 100644 --- a/lib/widgets/adaptive_flat_button.dart +++ b/lib/widgets/adaptive_flat_button.dart @@ -1,3 +1,5 @@ +//@dart=2.12 + import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -5,12 +7,12 @@ import 'package:fluffychat/utils/platform_infos.dart'; class AdaptiveFlatButton extends StatelessWidget { final String label; - final Color textColor; - final Function onPressed; + final Color? textColor; + final void Function()? onPressed; const AdaptiveFlatButton({ - Key key, - @required this.label, + Key? key, + required this.label, this.textColor, this.onPressed, }) : super(key: key); diff --git a/lib/widgets/avatar.dart b/lib/widgets/avatar.dart index 7b06ad26..8d33c286 100644 --- a/lib/widgets/avatar.dart +++ b/lib/widgets/avatar.dart @@ -1,3 +1,5 @@ +//@dart=2.12 + import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -8,12 +10,12 @@ import 'package:fluffychat/utils/string_color.dart'; import 'matrix.dart'; class Avatar extends StatelessWidget { - final Uri mxContent; - final String name; + final Uri? mxContent; + final String? name; final double size; - final Function onTap; + final void Function()? onTap; static const double defaultSize = 44; - final Client client; + final Client? client; final double fontSize; const Avatar( @@ -23,7 +25,7 @@ class Avatar extends StatelessWidget { this.onTap, this.client, this.fontSize = 18, - Key key, + Key? key, }) : super(key: key); @override @@ -34,10 +36,13 @@ class Avatar extends StatelessWidget { height: size * MediaQuery.of(context).devicePixelRatio, ); var fallbackLetters = '@'; - if ((name?.runes?.length ?? 0) >= 2) { - fallbackLetters = String.fromCharCodes(name.runes, 0, 2); - } else if ((name?.runes?.length ?? 0) == 1) { - fallbackLetters = name; + final name = this.name; + if (name != null) { + if (name.runes.length >= 2) { + fallbackLetters = String.fromCharCodes(name.runes, 0, 2); + } else if (name.runes.length == 1) { + fallbackLetters = name; + } } final noPic = mxContent == null || mxContent.toString().isEmpty || diff --git a/lib/widgets/chat_settings_popup_menu.dart b/lib/widgets/chat_settings_popup_menu.dart index 26b362d2..3319bee2 100644 --- a/lib/widgets/chat_settings_popup_menu.dart +++ b/lib/widgets/chat_settings_popup_menu.dart @@ -1,3 +1,5 @@ +//@dart=2.12 + import 'dart:async'; import 'package:flutter/material.dart'; @@ -13,7 +15,7 @@ import 'matrix.dart'; class ChatSettingsPopupMenu extends StatefulWidget { final Room room; final bool displayChatDetails; - const ChatSettingsPopupMenu(this.room, this.displayChatDetails, {Key key}) + const ChatSettingsPopupMenu(this.room, this.displayChatDetails, {Key? key}) : super(key: key); @override @@ -21,7 +23,7 @@ class ChatSettingsPopupMenu extends StatefulWidget { } class _ChatSettingsPopupMenuState extends State { - StreamSubscription notificationChangeSub; + StreamSubscription? notificationChangeSub; @override void dispose() { @@ -37,7 +39,7 @@ class _ChatSettingsPopupMenuState extends State { .stream .where((u) => u.type == 'm.push_rules') .listen( - (u) => setState(() => null), + (u) => setState(() {}), ); final items = >[ widget.room.pushRuleState == PushRuleState.notify @@ -47,7 +49,7 @@ class _ChatSettingsPopupMenuState extends State { children: [ const Icon(Icons.notifications_off_outlined), const SizedBox(width: 12), - Text(L10n.of(context).muteChat), + Text(L10n.of(context)!.muteChat), ], ), ) @@ -57,7 +59,7 @@ class _ChatSettingsPopupMenuState extends State { children: [ const Icon(Icons.notifications_on_outlined), const SizedBox(width: 12), - Text(L10n.of(context).unmuteChat), + Text(L10n.of(context)!.unmuteChat), ], ), ), @@ -67,7 +69,7 @@ class _ChatSettingsPopupMenuState extends State { children: [ const Icon(Icons.delete_outlined), const SizedBox(width: 12), - Text(L10n.of(context).leave), + Text(L10n.of(context)!.leave), ], ), ), @@ -81,7 +83,7 @@ class _ChatSettingsPopupMenuState extends State { children: [ const Icon(Icons.info_outline_rounded), const SizedBox(width: 12), - Text(L10n.of(context).chatDetails), + Text(L10n.of(context)!.chatDetails), ], ), ), @@ -94,9 +96,9 @@ class _ChatSettingsPopupMenuState extends State { final confirmed = await showOkCancelAlertDialog( useRootNavigator: false, context: context, - title: L10n.of(context).areYouSure, - okLabel: L10n.of(context).ok, - cancelLabel: L10n.of(context).cancel, + title: L10n.of(context)!.areYouSure, + okLabel: L10n.of(context)!.ok, + cancelLabel: L10n.of(context)!.cancel, ); if (confirmed == OkCancelResult.ok) { final success = await showFutureLoadingDialog( diff --git a/lib/widgets/connection_status_header.dart b/lib/widgets/connection_status_header.dart index a6c73a4d..b752a0b5 100644 --- a/lib/widgets/connection_status_header.dart +++ b/lib/widgets/connection_status_header.dart @@ -1,3 +1,5 @@ +//@dart=2.12 + import 'dart:async'; import 'package:flutter/material.dart'; @@ -9,15 +11,15 @@ import '../utils/localized_exception_extension.dart'; import 'matrix.dart'; class ConnectionStatusHeader extends StatefulWidget { - const ConnectionStatusHeader({Key key}) : super(key: key); + const ConnectionStatusHeader({Key? key}) : super(key: key); @override _ConnectionStatusHeaderState createState() => _ConnectionStatusHeaderState(); } class _ConnectionStatusHeaderState extends State { - StreamSubscription _onSyncSub; - StreamSubscription _onSyncErrorSub; + StreamSubscription? _onSyncSub; + StreamSubscription? _onSyncErrorSub; bool get _connected => DateTime.now().millisecondsSinceEpoch - _lastSyncReceived.millisecondsSinceEpoch < @@ -82,14 +84,15 @@ extension on SyncStatusUpdate { String toLocalizedString(BuildContext context) { switch (status) { case SyncStatus.waitingForResponse: - return L10n.of(context).loadingPleaseWait; + return L10n.of(context)!.loadingPleaseWait; case SyncStatus.error: - return (error.exception as Object).toLocalizedString(context); + return ((error?.exception ?? Object()) as Object) + .toLocalizedString(context); case SyncStatus.processing: case SyncStatus.cleaningUp: case SyncStatus.finished: default: - return L10n.of(context).synchronizingPleaseWait; + return L10n.of(context)!.synchronizingPleaseWait; } } } diff --git a/lib/widgets/contacts_list.dart b/lib/widgets/contacts_list.dart index 410163a4..b7a4f942 100644 --- a/lib/widgets/contacts_list.dart +++ b/lib/widgets/contacts_list.dart @@ -1,3 +1,5 @@ +//@dart=2.12 + import 'dart:async'; import 'package:flutter/material.dart'; @@ -14,15 +16,15 @@ class ContactsList extends StatefulWidget { final TextEditingController searchController; const ContactsList({ - Key key, - @required this.searchController, + Key? key, + required this.searchController, }) : super(key: key); @override _ContactsState createState() => _ContactsState(); } class _ContactsState extends State { - StreamSubscription _onSync; + StreamSubscription? _onSync; @override void dispose() { @@ -31,11 +33,11 @@ class _ContactsState extends State { } DateTime _lastSetState = DateTime.now(); - Timer _coolDown; + Timer? _coolDown; void _updateView() { _lastSetState = DateTime.now(); - setState(() => null); + setState(() {}); } @override @@ -68,15 +70,16 @@ class _ContactsState extends State { class _ContactListTile extends StatelessWidget { final Presence contact; - const _ContactListTile({Key key, @required this.contact}) : super(key: key); + const _ContactListTile({Key? key, required this.contact}) : super(key: key); @override Widget build(BuildContext context) { return FutureBuilder( future: Matrix.of(context).client.getProfileFromUserId(contact.senderId), builder: (context, snapshot) { - final displayname = - snapshot.data?.displayName ?? contact.senderId.localpart; + final displayname = snapshot.data?.displayName ?? + contact.senderId.localpart ?? + 'No valid MXID'; final avatarUrl = snapshot.data?.avatarUrl; return ListTile( leading: SizedBox( @@ -108,7 +111,7 @@ class _ContactListTile extends StatelessWidget { 'rooms', Matrix.of(context) .client - .getDirectChatFromUserId(contact.senderId) + .getDirectChatFromUserId(contact.senderId)! ]), ); }); diff --git a/lib/widgets/layouts/two_column_layout.dart b/lib/widgets/layouts/two_column_layout.dart index 343399cd..649e3560 100644 --- a/lib/widgets/layouts/two_column_layout.dart +++ b/lib/widgets/layouts/two_column_layout.dart @@ -1,4 +1,5 @@ //@dart=2.12 + import 'package:flutter/material.dart'; import 'package:fluffychat/config/themes.dart';