1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2025-06-20 08:45:17 +00:00

Start to fix null safety migration errors

This commit is contained in:
2022-03-10 19:39:57 +01:00
parent ab2c5da0da
commit 3a997cdc56
258 changed files with 2879 additions and 2912 deletions

View File

@ -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<FriendshipStatusWidget> {
// 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<FriendshipStatusWidget> {
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<FriendshipStatusWidget> {
children: <Widget>[
ElevatedButton(
child: Text(
tr("Accept request").toUpperCase(),
tr("Accept request")!.toUpperCase(),
style: WhiteTextColorStyle,
),
style: ButtonStyle(
@ -84,7 +84,7 @@ class _FriendshipStatusWidgetState extends State<FriendshipStatusWidget> {
),
ElevatedButton(
child: Text(
tr("Reject request").toUpperCase(),
tr("Reject request")!.toUpperCase(),
style: WhiteTextColorStyle,
),
style: ButtonStyle(
@ -98,7 +98,7 @@ class _FriendshipStatusWidgetState extends State<FriendshipStatusWidget> {
// 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<FriendshipStatusWidget> {
setSentRequest(true);
if (!await func())
showSimpleSnack(context, tr("Could not update your membership!"));
showSimpleSnack(context, tr("Could not update your membership!")!);
widget.onFriendshipUpdated();
}

View File

@ -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,

View File

@ -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<AsyncScreenWidget> {
MaterialButton(
textColor: Colors.white,
onPressed: () => refresh(),
child: Text(tr("Try again").toUpperCase()),
child: Text(tr("Try again")!.toUpperCase()),
)
]);

View File

@ -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<BannerWidget> {
Timer _timer;
Timer? _timer;
bool get _shouldShowBanner => showBanner && !_bannerDismissed;
@ -26,22 +26,22 @@ class _BannerWidgetState extends State<BannerWidget> {
}
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<BannerWidget> {
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<BannerWidget> {
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<BannerWidget> {
}
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),

View File

@ -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<ConversationFileWidget> {
: 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<ConversationFileWidget> {
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<ConversationFileWidget> {
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<ConversationFileWidget> {
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!);
}
}
}

View File

@ -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),

View File

@ -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})!);
},
);
}

View File

@ -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<CountdownWidget> {
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<CountdownWidget> {
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(remainingTimeStr),
child: Text(remainingTimeStr!),
),
Padding(
padding: const EdgeInsets.all(8.0),

View File

@ -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<CreateAccountWidget> {
final _emailController = TextEditingController();
final _passwordInputKey = GlobalKey<NewPasswordInputWidgetState>();
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<CreateAccountWidget> {
_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<CreateAccountWidget> {
// 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<CreateAccountWidget> {
// 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<CreateAccountWidget> {
// 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<CreateAccountWidget> {
// 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<CreateAccountWidget> {
// 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<CreateAccountWidget> {
// 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<CreateAccountWidget> {
Center(
child: ElevatedButton(
onPressed: _submitForm,
child: Text(tr("Create account")),
child: Text(tr("Create account")!),
),
),
],
@ -211,7 +211,7 @@ class _CreateAccountWidgetState extends State<CreateAccountWidget> {
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<CreateAccountWidget> {
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: <Widget>[
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,

View File

@ -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();

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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,
);
}

View File

@ -10,9 +10,9 @@ class ConfirmDialogButton<T> 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<T> 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,
);
}

View File

@ -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<PresenceCalendarWidget> {
var selectedDay = DateTime.now();
DateTime? selectedDay = DateTime.now();
@override
void didUpdateWidget(covariant PresenceCalendarWidget oldWidget) {
@ -63,7 +63,7 @@ class _PresenceCalendarWidgetState extends State<PresenceCalendarWidget> {
),
onDaySelected: _selectedDay,
availableCalendarFormats: const {CalendarFormat.month: "Mois"},
focusedDay: selectedDay,
focusedDay: selectedDay!,
onPageChanged: (s) {
setState(() {
selectedDay = s;
@ -129,21 +129,21 @@ class _PresenceCalendarWidgetState extends State<PresenceCalendarWidget> {
}
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,

View File

@ -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<GroupFollowingWidget> {
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<GroupFollowingWidget> {
/// 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;
}

View File

@ -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),

View File

@ -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<GroupMembershipWidget> {
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<GroupMembershipWidget> {
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<GroupMembershipWidget> {
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<GroupMembershipWidget> {
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<GroupMembershipWidget> {
/// 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<GroupMembershipWidget> {
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<GroupMembershipWidget> {
/// 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!();
}
}
}

View File

@ -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),

View File

@ -69,7 +69,7 @@ class _InitializeWidgetState extends SafeState<InitializeWidget> {
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<InitializeWidget> {
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<InitializeWidget> {
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<InitializeWidget> {
),
!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<InitializeWidget> {
children: <Widget>[
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<InitializeWidget> {
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);
}
}

View File

@ -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<LikeWidget> {
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<LikeWidget> {
SizedBox(
width: 8.0,
),
Text(_likeString),
Text(_likeString!),
],
),
),

View File

@ -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(

View File

@ -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,

View File

@ -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),

View File

@ -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<LoginWidget> {
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<LoginWidget> {
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<LoginWidget> {
child: _loading
? CircularProgressIndicator()
: ElevatedButton(
child: Text(tr("Sign in")),
child: Text(tr("Sign in")!),
onPressed: _canSubmit ? () => _submitForm(context) : null,
),
),

View File

@ -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<ComunicMobileAppBar> {
}
/// 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<ComunicMobileAppBar> {
);
}
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(

View File

@ -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<UserMobilePage>
with SingleTickerProviderStateMixin {
TabController _tabController;
TabController? _tabController;
List<UserPageTab> 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<UserMobilePage>
// 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<UserMobilePage>
@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),

View File

@ -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) {

View File

@ -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<NewPasswordInputWidget> {
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<NewPasswordInputWidget> {
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<NewPasswordInputWidget> {
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!");
}

View File

@ -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<PickUserWidget> {
// 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<PickUserWidget> {
}
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<PickUserWidget> {
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<PickUserWidget> {
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<void> _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<PickUserWidget> {
_suggestions = results;
if (_overlayEntry != null)
_overlayEntry.markNeedsBuild();
_overlayEntry!.markNeedsBuild();
else
_showOverlay();
}

View File

@ -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);

View File

@ -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<PostCreateFormWidget> {
// Class members
bool _isCreating = false;
final TextEditingController _postTextController = TextEditingController();
PostVisibilityLevel _postVisibilityLevel;
BytesFile _postImage;
String _postURL;
List<int> _postPDF;
DateTime _timeEnd;
NewSurvey _postSurvey;
String _youtubeID;
PostVisibilityLevel? _postVisibilityLevel;
BytesFile? _postImage;
String? _postURL;
List<int>? _postPDF;
DateTime? _timeEnd;
NewSurvey? _postSurvey;
String? _youtubeID;
bool get hasImage => _postImage != null;
@ -184,7 +184,7 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
// 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<PostCreateFormWidget> {
_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<PostCreateFormWidget> {
Future<void> _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<PostCreateFormWidget> {
});
} 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<PostCreateFormWidget> {
});
} 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<PostCreateFormWidget> {
Future<void> _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<PostCreateFormWidget> {
/// Submit new post
Future<void> _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<PostCreateFormWidget> {
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<PostCreateFormWidget> {
));
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<PostCreateFormWidget> {
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),

View File

@ -24,18 +24,18 @@ import 'package:flutter/material.dart';
/// @author Pierre HUBERT
class PostsListWidget extends StatefulWidget {
final List<Widget> topWidgets;
final Future<PostsList> Function() getPostsList;
final Future<PostsList> Function(int from) getOlder;
final List<Widget>? topWidgets;
final Future<PostsList?> Function() getPostsList;
final Future<PostsList?> 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<PostsListWidget> {
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<PostsListWidget> {
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<PostsListWidget> {
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<PostsListWidget> {
_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<PostsListWidget> {
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<PostsListWidget> {
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<PostsListWidget> {
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<PostsListWidget> {
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<PostsListWidget> {
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<PostsListWidget> {
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<PostsListWidget> {
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<PostsListWidget> {
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));
}
}

View File

@ -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!();
}
}

View File

@ -11,15 +11,15 @@ class MultiChoicesSettingsTile<T> extends SettingsTile {
final List<MultiChoiceEntry<T>> 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),

View File

@ -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,

View File

@ -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<StatusWidget> {
int unreadNotifications = 0;
int unreadConversations = 0;
int? unreadNotifications = 0;
int? unreadConversations = 0;
Future<void> init() async {
try {
@ -52,7 +52,7 @@ class StatusWidgetState extends SafeState<StatusWidget> {
}
/// Find an ancestor of this object
static StatusWidgetState of(BuildContext c) =>
static StatusWidgetState? of(BuildContext c) =>
c.findAncestorStateOfType<StatusWidgetState>();
@override

View File

@ -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<SurveyWidget> {
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<SurveyWidget> {
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<SurveyWidget> {
constraints: BoxConstraints(maxWidth: 300),
child: DropdownButton<SurveyChoice>(
isExpanded: true,
hint: Text(tr("Respond to survey")),
hint: Text(tr("Respond to survey")!),
items: survey.choices
.map(
(f) => DropdownMenuItem<SurveyChoice>(
@ -128,7 +128,7 @@ class _SurveyWidgetState extends SafeState<SurveyWidget> {
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<SurveyWidget> {
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<SurveyWidget> {
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<void> _respondToSurvey(SurveyChoice choice) async {
Future<void> _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<SurveyWidget> {
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<SurveyWidget> {
} 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<SurveyWidget> {
} 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!")!);
}
}
}

View File

@ -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);

View File

@ -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,
),
)

View File

@ -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<CallWindowWidget> {
double _left, _top;
double? _left, _top;
var _fullScreen = false;
@ -71,7 +71,7 @@ class _CallWindowWidgetState extends State<CallWindowWidget> {
height: 30,
appBar: AppBar(
backgroundColor: Colors.black,
title: Text(convName == null ? tr("Loading...") : convName),
title: Text(convName == null ? tr("Loading...")! : convName),
actions: <Widget>[
// Go full screen
IconButton(
@ -98,9 +98,9 @@ class _CallWindowWidgetState extends State<CallWindowWidget> {
void _moveEnd(DraggableDetails details) {
// Determine the limits of containing stack
RenderBox renderBox = context
.findAncestorStateOfType<CallsAreaState>()
.findAncestorStateOfType<CallsAreaState>()!
.context
.findRenderObject();
.findRenderObject() as RenderBox;
final size = renderBox.size;
final offset = renderBox.localToGlobal(Offset.zero);
@ -109,13 +109,13 @@ class _CallWindowWidgetState extends State<CallWindowWidget> {
_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(() {});
}

View File

@ -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();

View File

@ -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<ConversationWindow> {
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<ConversationWindow> {
} 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<ConversationWindow> {
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<ConversationWindow> {
actions: [
ElevatedButton(
onPressed: _refresh,
child: Text(tr("Try again").toUpperCase()),
child: Text(tr("Try again")!.toUpperCase()),
)
]),
);
@ -109,7 +109,7 @@ class _ConversationWindowState extends SafeState<ConversationWindow> {
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<ConversationWindow> {
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(<Widget>[
@ -131,19 +131,19 @@ class _ConversationWindowState extends SafeState<ConversationWindow> {
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<ConversationWindow> {
}
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<ConversationWindow> {
_refresh();
}
void _startCall() => MainController.of(context).startCall(_convID);
void _startCall() => MainController.of(context)!.startCall(_convID);
}

View File

@ -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<Widget> action;
final List<Widget>? 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),
),

View File

@ -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<ConversationsAreaWidget> {
final _openConversations = Map<int, UniqueKey>();
final _openConversations = Map<int?, UniqueKey>();
@override
Widget build(BuildContext context) {
@ -31,17 +31,17 @@ class ConversationsAreaWidgetState extends State<ConversationsAreaWidget> {
Widget _buildOpenButton() => OpenConversationButton();
/// Open a new conversation
void openConversations(int convID) {
void openConversations(int? convID) {
if (!_openConversations.containsKey(convID))
setState(() => _openConversations[convID] = UniqueKey());
}
MapEntry<int, Widget> _conversationWindow(int convID, UniqueKey key) =>
MapEntry<int?, Widget> _conversationWindow(int? convID, UniqueKey key) =>
MapEntry(
convID,
ConversationWindow(
key: key,
convID: convID,
convID: convID!,
onClose: () => setState(() => _openConversations.remove(convID)),
),
);

View File

@ -17,7 +17,7 @@ class CurrentUserPanel extends StatefulWidget {
}
class _CurrentUserPanelState extends SafeState<CurrentUserPanel> {
User _user;
User? _user;
Future<void> _refresh() async {
try {
@ -49,12 +49,12 @@ class _CurrentUserPanelState extends SafeState<CurrentUserPanel> {
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),
);
}
}

View File

@ -36,9 +36,9 @@ class _GlobalSearchFieldState extends State<GlobalSearchField> {
final _controller = TextEditingController();
_SearchResults _searchResultsList;
_SearchResults? _searchResultsList;
OverlayEntry _overlayEntry;
OverlayEntry? _overlayEntry;
@override
void initState() {
@ -96,29 +96,29 @@ class _GlobalSearchFieldState extends State<GlobalSearchField> {
_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<GlobalSearchField> {
}
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();
},
);

View File

@ -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<MembershipsPanel> {
final _refreshKey = GlobalKey<RefreshIndicatorState>();
MembershipList _membershipList;
UsersList _usersList;
GroupsList _groupsList;
MembershipList? _membershipList;
UsersList? _usersList;
late GroupsList _groupsList;
Future<void> _refresh() async {
try {
@ -87,13 +87,13 @@ class _MembershipsPanelState extends SafeState<MembershipsPanel> {
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<MembershipsPanel> {
// 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<MembershipsPanel> {
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<MembershipsPanel> {
]));
} 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<MembershipsPanel> {
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<MembershipsPanel> {
: 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<MembershipsPanel> {
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<MembershipsPanel> {
),
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<MembershipsPanel> {
dense: true,
leading: ConversationImageWidget(
conversation: conversation,
users: _usersList,
users: _usersList!,
noUserImage: conversation.isGroupConversation,
),
title: Row(
@ -233,20 +237,20 @@ class _MembershipsPanelState extends SafeState<MembershipsPanel> {
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<MembershipsPanel> {
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)),
);
}
}

View File

@ -63,12 +63,12 @@ class _ComunicTabletAppBarWidgetState
return AppBar(
title: GestureDetector(
child: Text("Comunic"),
onTap: () => MainController.of(context).openLatestPostsPage()),
onTap: () => MainController.of(context)!.openLatestPostsPage()),
actions: <Widget>[
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> {

View File

@ -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<UserPageTablet> {
_isCurrentUser
? Container()
: FriendshipStatusWidget(
status: widget.friendshipStatus,
status: widget.friendshipStatus!,
onFriendshipUpdated: widget.onNeedRefresh,
)
],
@ -124,7 +124,7 @@ class _UserPageTabletState extends State<UserPageTablet> {
_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<UserPageTablet> {
// 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<UserPageTablet> {
// 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<UserPageTablet> {
// 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<UserPageTablet> {
// 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<UserPageTablet> {
// 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<UserPageTablet> {
}
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,
);
}

View File

@ -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<TextSpan> _parse(String text, TextStyle style) {
static List<TextSpan> _parse(String text, TextStyle? style) {
if (style == null) style = TextStyle();
List<TextSpan> 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)));
}
}

View File

@ -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<InlineSpan> _parseLinks(
BuildContext context, String text, TextStyle style) {
BuildContext context, String text, TextStyle? style) {
var buff = StringBuffer();
final list = <InlineSpan>[];
@ -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),
),

View File

@ -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"),

View File

@ -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) {

View File

@ -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),
);
}

View File

@ -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),
),
);

View File

@ -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<bool> Function(BuildContext) onTapNext;
final Future<bool> 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: <Widget>[
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: <Widget>[
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),
],
);

View File

@ -11,24 +11,24 @@ import 'package:flutter/material.dart';
class TourNotificationsPane extends PresentationPane {
TourNotificationsPane({
Key key,
@required
Key? key,
required
GlobalKey<PushNotificationsConfigurationWidgetState>
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,
);
}

View File

@ -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));
}