mirror of
https://gitlab.com/comunic/comunicmobile
synced 2025-06-20 00:35:17 +00:00
Start to fix null safety migration errors
This commit is contained in:
@ -18,9 +18,9 @@ class ConversationMessageStatsRoute extends StatefulWidget {
|
||||
final ConversationMessage message;
|
||||
|
||||
const ConversationMessageStatsRoute({
|
||||
Key key,
|
||||
@required this.conv,
|
||||
@required this.message,
|
||||
Key? key,
|
||||
required this.conv,
|
||||
required this.message,
|
||||
}) : assert(conv != null),
|
||||
assert(message != null),
|
||||
super(key: key);
|
||||
@ -32,7 +32,7 @@ class ConversationMessageStatsRoute extends StatefulWidget {
|
||||
|
||||
class _ConversationMessageStatsRouteState
|
||||
extends State<ConversationMessageStatsRoute> {
|
||||
UsersList _users;
|
||||
late UsersList _users;
|
||||
|
||||
Future<void> _init() async {
|
||||
_users = await UsersHelper()
|
||||
@ -43,23 +43,23 @@ class _ConversationMessageStatsRouteState
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(tr("Message statistics")),
|
||||
title: Text(tr("Message statistics")!),
|
||||
leading: IconButton(
|
||||
icon: Icon(Icons.close),
|
||||
onPressed: () => MainController.of(context).popPage(),
|
||||
onPressed: () => MainController.of(context)!.popPage(),
|
||||
),
|
||||
),
|
||||
body: AsyncScreenWidget(
|
||||
onReload: _init,
|
||||
onBuild: _buildScreen,
|
||||
errorMessage: tr("Failed to load message information!")),
|
||||
errorMessage: tr("Failed to load message information!")!),
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> get _firstItems => [
|
||||
ListTile(
|
||||
leading: Icon(Icons.access_time_rounded),
|
||||
title: Text(tr("Created on")),
|
||||
title: Text(tr("Created on")!),
|
||||
subtitle: Text(dateTimeToString(widget.message.date)),
|
||||
),
|
||||
ListTile(
|
||||
@ -67,17 +67,17 @@ class _ConversationMessageStatsRouteState
|
||||
user: _users.getUser(widget.message.userID),
|
||||
),
|
||||
title: Text(_users.getUser(widget.message.userID).fullName),
|
||||
subtitle: Text(tr("Creator")),
|
||||
subtitle: Text(tr("Creator")!),
|
||||
),
|
||||
];
|
||||
|
||||
Widget _buildScreen() => ListView.builder(
|
||||
itemCount: _firstItems.length + widget.conv.members.length,
|
||||
itemCount: _firstItems.length + widget.conv.members!.length,
|
||||
itemBuilder: (c, i) {
|
||||
final firstItems = _firstItems;
|
||||
if (i < firstItems.length) return firstItems[i];
|
||||
|
||||
final convMember = widget.conv.members[i - firstItems.length];
|
||||
final convMember = widget.conv.members![i - firstItems.length];
|
||||
|
||||
if (convMember.userID == widget.message.userID) return Container();
|
||||
|
||||
@ -86,9 +86,9 @@ class _ConversationMessageStatsRouteState
|
||||
user: _users.getUser(convMember.userID),
|
||||
),
|
||||
title: Text(_users.getUser(convMember.userID).fullName),
|
||||
subtitle: Text(convMember.lastMessageSeen < widget.message.id
|
||||
? tr("Message not seen yet")
|
||||
: tr("Message seen")),
|
||||
subtitle: Text(convMember.lastMessageSeen < widget.message.id!
|
||||
? tr("Message not seen yet")!
|
||||
: tr("Message seen")!),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -19,8 +19,8 @@ class ConversationRoute extends StatefulWidget {
|
||||
final int conversationID;
|
||||
|
||||
const ConversationRoute({
|
||||
Key key,
|
||||
@required this.conversationID,
|
||||
Key? key,
|
||||
required this.conversationID,
|
||||
}) : assert(conversationID != null),
|
||||
super(key: key);
|
||||
|
||||
@ -30,9 +30,9 @@ class ConversationRoute extends StatefulWidget {
|
||||
|
||||
class _ConversationRouteState extends SafeState<ConversationRoute> {
|
||||
final ConversationsHelper _conversationsHelper = ConversationsHelper();
|
||||
Conversation _conversation;
|
||||
UsersList _users;
|
||||
String _conversationName;
|
||||
Conversation? _conversation;
|
||||
UsersList? _users;
|
||||
String? _conversationName;
|
||||
bool _error = false;
|
||||
|
||||
setError(bool err) => setState(() => _error = err);
|
||||
@ -50,10 +50,10 @@ class _ConversationRouteState extends SafeState<ConversationRoute> {
|
||||
_conversation = await _conversationsHelper
|
||||
.getSingle(widget.conversationID, force: true);
|
||||
|
||||
_users = await UsersHelper().getList(_conversation.membersID);
|
||||
_users = await UsersHelper().getList(_conversation!.membersID);
|
||||
|
||||
final conversationName =
|
||||
ConversationsHelper.getConversationName(_conversation, _users);
|
||||
ConversationsHelper.getConversationName(_conversation!, _users);
|
||||
|
||||
if (!this.mounted) return null;
|
||||
|
||||
@ -65,7 +65,7 @@ class _ConversationRouteState extends SafeState<ConversationRoute> {
|
||||
}
|
||||
|
||||
void _openSettings() =>
|
||||
MainController.of(context).openConversationSettingsRoute(_conversation);
|
||||
MainController.of(context)!.openConversationSettingsRoute(_conversation!);
|
||||
|
||||
Widget _buildRouteBody() {
|
||||
//Handle errors
|
||||
@ -76,7 +76,7 @@ class _ConversationRouteState extends SafeState<ConversationRoute> {
|
||||
TextButton(
|
||||
onPressed: _loadConversation,
|
||||
child: Text(
|
||||
tr("Try again").toUpperCase(),
|
||||
tr("Try again")!.toUpperCase(),
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
),
|
||||
@ -101,19 +101,19 @@ class _ConversationRouteState extends SafeState<ConversationRoute> {
|
||||
? (_conversation == null || _users == null
|
||||
? null
|
||||
: ConversationImageWidget(
|
||||
conversation: _conversation, users: _users))
|
||||
conversation: _conversation!, users: _users!))
|
||||
: ComunicBackButton(),
|
||||
title: Text(
|
||||
_conversationName == null ? tr("Loading") : _conversationName,
|
||||
_conversationName == null ? tr("Loading")! : _conversationName!,
|
||||
),
|
||||
actions: <Widget>[
|
||||
// Start call (if possible)
|
||||
_conversation == null ||
|
||||
_conversation.callCapabilities == CallCapabilities.NONE
|
||||
_conversation!.callCapabilities == CallCapabilities.NONE
|
||||
? Container()
|
||||
: IconButton(
|
||||
icon: Icon(Icons.phone),
|
||||
onPressed: () => MainController.of(context)
|
||||
onPressed: () => MainController.of(context)!
|
||||
.startCall(widget.conversationID),
|
||||
),
|
||||
|
||||
|
@ -15,7 +15,7 @@ class CreateAccountRoute extends StatelessWidget {
|
||||
return LoginRouteContainer(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(tr("Create an account")),
|
||||
title: Text(tr("Create an account")!),
|
||||
),
|
||||
body: _CreateAccountRouteBody(),
|
||||
),
|
||||
@ -38,12 +38,12 @@ class __CreateAccountRouteBodyState extends State<_CreateAccountRouteBody> {
|
||||
await showCupertinoDialog(
|
||||
context: context,
|
||||
builder: (c) => CupertinoAlertDialog(
|
||||
title: Text(tr("Account created")),
|
||||
title: Text(tr("Account created")!),
|
||||
content: Text(tr(
|
||||
"Your account has been successfully created. You can now login to start to use it.")),
|
||||
"Your account has been successfully created. You can now login to start to use it.")!),
|
||||
actions: <Widget>[
|
||||
CupertinoButton(
|
||||
child: Text(tr("Login")), onPressed: () => Navigator.of(c).pop())
|
||||
child: Text(tr("Login")!), onPressed: () => Navigator.of(c).pop())
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -16,16 +16,16 @@ import 'package:flutter/material.dart';
|
||||
|
||||
/// Show presence settings route
|
||||
Future<void> showPresenceSettingsRoute(
|
||||
BuildContext context, int groupID) async =>
|
||||
BuildContext context, int? groupID) async =>
|
||||
await Navigator.push(context,
|
||||
MaterialPageRoute(builder: (c) => PresenceSettings(groupID: groupID)));
|
||||
MaterialPageRoute(builder: (c) => PresenceSettings(groupID: groupID!)));
|
||||
|
||||
class PresenceSettings extends StatefulWidget {
|
||||
final int groupID;
|
||||
|
||||
const PresenceSettings({
|
||||
Key key,
|
||||
@required this.groupID,
|
||||
Key? key,
|
||||
required this.groupID,
|
||||
}) : assert(groupID != null),
|
||||
super(key: key);
|
||||
|
||||
@ -34,7 +34,7 @@ class PresenceSettings extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _PresenceSettingsState extends State<PresenceSettings> {
|
||||
PresenceSet _currPresences;
|
||||
late PresenceSet _currPresences;
|
||||
|
||||
Future<void> _load() async {
|
||||
await ForezPresenceHelper.refreshCache(widget.groupID);
|
||||
@ -46,12 +46,12 @@ class _PresenceSettingsState extends State<PresenceSettings> {
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(tr("Presence settings")),
|
||||
title: Text(tr("Presence settings")!),
|
||||
),
|
||||
body: AsyncScreenWidget(
|
||||
onReload: _load,
|
||||
onBuild: _buildScreen,
|
||||
errorMessage: tr("Failed to load data!"),
|
||||
errorMessage: tr("Failed to load data!")!,
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -61,7 +61,7 @@ class _PresenceSettingsState extends State<PresenceSettings> {
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
tr("Please click on the day you will be in the plain, so that everyone gets informed ! ;)"),
|
||||
tr("Please click on the day you will be in the plain, so that everyone gets informed ! ;)")!,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
@ -85,7 +85,7 @@ class _PresenceSettingsState extends State<PresenceSettings> {
|
||||
} catch (e, s) {
|
||||
logError(e, s);
|
||||
_currPresences.toggleDate(dt, userID());
|
||||
snack(context, tr("Failed to update information!"));
|
||||
snack(context, tr("Failed to update information!")!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ class ForgotPasswordRoute extends StatelessWidget {
|
||||
return LoginRouteContainer(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(tr("Password forgotten")),
|
||||
title: Text(tr("Password forgotten")!),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
@ -45,7 +45,7 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> {
|
||||
var _loading = false;
|
||||
|
||||
/// Step 1 - check email address
|
||||
String _emailAddress;
|
||||
String? _emailAddress;
|
||||
final _emailController = TextEditingController();
|
||||
|
||||
String get _inputEmail => _emailController.text;
|
||||
@ -54,14 +54,14 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> {
|
||||
_inputEmail.isNotEmpty && validateEmail(_inputEmail);
|
||||
|
||||
/// Step 2 - Offer options
|
||||
bool _hasSecurityQuestions;
|
||||
bool? _hasSecurityQuestions;
|
||||
|
||||
var _selectedOption = _SelectedOption.NONE;
|
||||
|
||||
void _setLoading(bool loading) => setState(() => _loading = loading);
|
||||
|
||||
/// Step 3b - Answer security questions
|
||||
List<String> _questions;
|
||||
List<String>? _questions;
|
||||
var _questionsControllers = <TextEditingController>[];
|
||||
|
||||
List<String> get _answers =>
|
||||
@ -90,7 +90,7 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Text(tr("Please enter your email address to reset your password:")),
|
||||
Text(tr("Please enter your email address to reset your password:")!),
|
||||
TextField(
|
||||
controller: _emailController,
|
||||
onChanged: (s) => setState(() {}),
|
||||
@ -120,9 +120,9 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> {
|
||||
_setLoading(true);
|
||||
|
||||
// Check if email address exists or not
|
||||
if (!await AccountHelper.existsMailAccount(_inputEmail)) {
|
||||
if (!await AccountHelper.existsMailAccount(_inputEmail) ) {
|
||||
_setLoading(false);
|
||||
showSimpleSnack(context, tr("Specified email address was not found!"));
|
||||
showSimpleSnack(context, tr("Specified email address was not found!")!);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -135,7 +135,7 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> {
|
||||
} catch (e, s) {
|
||||
print("Could not check given email! $e\n$s");
|
||||
showSimpleSnack(context,
|
||||
tr("An error occurred while checking your recovery options !"));
|
||||
tr("An error occurred while checking your recovery options !")!);
|
||||
_setLoading(false);
|
||||
}
|
||||
}
|
||||
@ -145,19 +145,19 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
Text(tr("Here are your options to reset your account:")),
|
||||
Text(tr("Here are your options to reset your account:")!),
|
||||
_Spacer(),
|
||||
OutlinedButton.icon(
|
||||
onPressed: _openSendEmailDialog,
|
||||
icon: Icon(Icons.email),
|
||||
label: Flexible(
|
||||
child: Text(tr("Send us an email to ask for help")))),
|
||||
_Spacer(visible: _hasSecurityQuestions),
|
||||
_hasSecurityQuestions
|
||||
child: Text(tr("Send us an email to ask for help")!))),
|
||||
_Spacer(visible: _hasSecurityQuestions!),
|
||||
_hasSecurityQuestions!
|
||||
? OutlinedButton.icon(
|
||||
onPressed: _loadSecurityQuestions,
|
||||
icon: Icon(Icons.help_outline),
|
||||
label: Text(tr("Answer your security questions")),
|
||||
label: Text(tr("Answer your security questions")!),
|
||||
)
|
||||
: Container(),
|
||||
],
|
||||
@ -169,7 +169,7 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> {
|
||||
context: context,
|
||||
builder: (c) => AlertDialog(
|
||||
title: Text("Contact us"),
|
||||
content: Text(tr("You can reach us at contact@communiquons.org")),
|
||||
content: Text(tr("You can reach us at contact@communiquons.org")!),
|
||||
actions: <Widget>[CancelDialogButton()],
|
||||
));
|
||||
}
|
||||
@ -181,11 +181,11 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> {
|
||||
_questions = await AccountHelper.getSecurityQuestions(_emailAddress);
|
||||
|
||||
_questionsControllers =
|
||||
List.generate(_questions.length, (i) => TextEditingController());
|
||||
List.generate(_questions!.length, (i) => TextEditingController());
|
||||
_selectedOption = _SelectedOption.SECURITY_QUESTIONS;
|
||||
} catch (e, s) {
|
||||
print("Could not load security questions! $e\n$s");
|
||||
showSimpleSnack(context, tr("Could not load your security questions!"));
|
||||
showSimpleSnack(context, tr("Could not load your security questions!")!);
|
||||
}
|
||||
_setLoading(false);
|
||||
}
|
||||
@ -196,20 +196,20 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[]
|
||||
..add(Text(tr("Please answer now your security questions:")))
|
||||
..add(Text(tr("Please answer now your security questions:")!))
|
||||
..add(_Spacer())
|
||||
..addAll(List.generate(_questions.length, _buildSecurityQuestionField))
|
||||
..addAll(List.generate(_questions!.length, _buildSecurityQuestionField))
|
||||
..add(_Spacer())
|
||||
..add(OutlinedButton(
|
||||
onPressed: _canSubmitAnswers ? _submitSecurityAnswers : null,
|
||||
child: Text(tr("Submit")),
|
||||
child: Text(tr("Submit")!),
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSecurityQuestionField(int id) => Column(
|
||||
children: <Widget>[
|
||||
Text(_questions[id]),
|
||||
Text(_questions![id]),
|
||||
TextField(
|
||||
controller: _questionsControllers[id],
|
||||
onChanged: (s) => setState(() {}),
|
||||
@ -234,20 +234,20 @@ class _ResetPasswordBodyState extends SafeState<_ResetPasswordBody> {
|
||||
} catch (e, s) {
|
||||
print("Could not submit security answers! $e\n$s");
|
||||
showSimpleSnack(
|
||||
context, tr("Could not validate these security answers!"));
|
||||
context, tr("Could not validate these security answers!")!);
|
||||
}
|
||||
_setLoading(false);
|
||||
}
|
||||
|
||||
/// Call this method whenever the user managed to get a password reset token
|
||||
void _useResetToken(String token) => Navigator.of(context).pushReplacement(
|
||||
MaterialPageRoute(builder: (c) => PasswordResetRoute(token: token)));
|
||||
void _useResetToken(String? token) => Navigator.of(context).pushReplacement(
|
||||
MaterialPageRoute(builder: (c) => PasswordResetRoute(token: token!)));
|
||||
}
|
||||
|
||||
class _Spacer extends StatelessWidget {
|
||||
final bool visible;
|
||||
|
||||
const _Spacer({Key key, this.visible = true})
|
||||
const _Spacer({Key? key, this.visible = true})
|
||||
: assert(visible != null),
|
||||
super(key: key);
|
||||
|
||||
|
@ -22,7 +22,7 @@ class _FullScreenImageRouteState extends State<FullScreenImageRoute> {
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(tr("Image")),
|
||||
title: Text(tr("Image")!),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: Icon(Icons.launch), onPressed: () => launch(widget.url))
|
||||
|
@ -18,18 +18,16 @@ import '../../utils/files_utils.dart';
|
||||
///
|
||||
/// Return original image in case of error / if the user did not crop the image
|
||||
Future<BytesFile> showImageCropper(BuildContext context, BytesFile source,
|
||||
{CropAspectRatio aspectRatio}) async {
|
||||
assert(context != null);
|
||||
assert(source != null);
|
||||
{CropAspectRatio? aspectRatio}) async {
|
||||
|
||||
File file;
|
||||
File cropped;
|
||||
File? file;
|
||||
File? cropped;
|
||||
|
||||
try {
|
||||
file = await generateTemporaryFile();
|
||||
await file.writeAsBytes(source.bytes);
|
||||
await file.writeAsBytes(source.bytes!);
|
||||
|
||||
File cropped = await ImageCropper().cropImage(
|
||||
File? cropped = await ImageCropper().cropImage(
|
||||
sourcePath: file.absolute.path,
|
||||
compressFormat: ImageCompressFormat.png,
|
||||
aspectRatio: aspectRatio,
|
||||
@ -40,12 +38,12 @@ Future<BytesFile> showImageCropper(BuildContext context, BytesFile source,
|
||||
),
|
||||
);
|
||||
|
||||
if (cropped == null) return null;
|
||||
if (cropped == null) return source;
|
||||
|
||||
return BytesFile("cropped.png", await cropped.readAsBytes());
|
||||
} catch (e, s) {
|
||||
logError(e, s);
|
||||
snack(context, tr("Failed to execute image cropper!"));
|
||||
snack(context, tr("Failed to execute image cropper!")!);
|
||||
return source;
|
||||
} finally {
|
||||
if (file != null && await file.exists()) file.delete();
|
||||
|
@ -25,7 +25,7 @@ class _LoginRouteState extends State<LoginRoute> {
|
||||
return LoginRouteContainer(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(tr("Login to Comunic")),
|
||||
title: Text(tr("Login to Comunic")!),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
@ -44,7 +44,7 @@ class _LoginRouteState extends State<LoginRoute> {
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.help),
|
||||
title: Text(tr("Password forgotten")),
|
||||
title: Text(tr("Password forgotten")!),
|
||||
onTap: _openResetPasswordPage,
|
||||
)
|
||||
],
|
||||
|
@ -50,7 +50,7 @@ abstract class MainController extends State<MainRoute> {
|
||||
int get numberOfPages => _pagesStack.length;
|
||||
|
||||
/// Get current instance of Home controller
|
||||
static MainController of(BuildContext context) {
|
||||
static MainController? of(BuildContext context) {
|
||||
assert(context != null); // A future implementation might need context again
|
||||
return mainControllerKey.currentState;
|
||||
}
|
||||
@ -75,7 +75,7 @@ abstract class MainController extends State<MainRoute> {
|
||||
|
||||
/// Pop until main route is reached
|
||||
void popUntilMainRoute() => Navigator.of(context).popUntil((settings) =>
|
||||
ModalRoute.of(context).isCurrent || !ModalRoute.of(context).isActive);
|
||||
ModalRoute.of(context)!.isCurrent || !ModalRoute.of(context)!.isActive);
|
||||
|
||||
/// Go to the previous page (use for [WillPop] widget)
|
||||
@protected
|
||||
@ -109,13 +109,13 @@ abstract class MainController extends State<MainRoute> {
|
||||
pushPage(PageInfo(child: UserAccessDeniedScreen(userID: userID)));
|
||||
|
||||
/// Open current user page
|
||||
void openCurrentUserPage() => this.openUserPage(userID());
|
||||
void openCurrentUserPage() => this.openUserPage(userID()!);
|
||||
|
||||
/// Open a specific group page specified by its [groupID]
|
||||
///
|
||||
/// [conversationID] is an optional parameter specifying a conversation
|
||||
/// that should be opened instead of posts thread
|
||||
void openGroup(int groupID, {int conversationID}) => pushPage(PageInfo(
|
||||
void openGroup(int groupID, {int? conversationID}) => pushPage(PageInfo(
|
||||
type: PageType.GROUP_PAGE,
|
||||
child: GroupPageScreen(
|
||||
groupID: groupID,
|
||||
@ -137,10 +137,10 @@ abstract class MainController extends State<MainRoute> {
|
||||
void openGroupsListPage() => pushPage(PageInfo(child: GroupsListScreen()));
|
||||
|
||||
/// Display the list of friends of a user
|
||||
void openUserFriendsList(int id) {
|
||||
void openUserFriendsList(int? id) {
|
||||
if (id != userID())
|
||||
pushPage(PageInfo(
|
||||
child: OtherUserFriendsListScreen(userID: id),
|
||||
child: OtherUserFriendsListScreen(userID: id!),
|
||||
canShowAsDialog: true,
|
||||
));
|
||||
else
|
||||
@ -156,9 +156,9 @@ abstract class MainController extends State<MainRoute> {
|
||||
/// Open a conversation in its context (in group page for group conversations)
|
||||
void openConversation(Conversation conv, {fullScreen: false}) {
|
||||
if (conv.isGroupConversation)
|
||||
openGroup(conv.groupID, conversationID: conv.id);
|
||||
openGroup(conv.groupID!, conversationID: conv.id);
|
||||
else
|
||||
openConversationById(conv.id, fullScreen: fullScreen);
|
||||
openConversationById(conv.id!, fullScreen: fullScreen);
|
||||
}
|
||||
|
||||
/// Open a conversation
|
||||
@ -173,7 +173,7 @@ abstract class MainController extends State<MainRoute> {
|
||||
/// Open conversation settings route
|
||||
void openConversationSettingsRoute(Conversation conv) => pushPage(PageInfo(
|
||||
child: UpdateConversationRoute(
|
||||
conversationID: conv.id,
|
||||
conversationID: conv.id!,
|
||||
),
|
||||
canShowAsDialog: true,
|
||||
hideNavBar: true,
|
||||
@ -215,7 +215,7 @@ abstract class MainController extends State<MainRoute> {
|
||||
///
|
||||
/// If the current route is not the main route, we pop one page
|
||||
void popPage() {
|
||||
if (!ModalRoute.of(context).isCurrent)
|
||||
if (!ModalRoute.of(context)!.isCurrent)
|
||||
Navigator.of(context).pop();
|
||||
else
|
||||
doPopPage();
|
||||
|
@ -18,7 +18,7 @@ enum PageType {
|
||||
class PageInfo {
|
||||
final PageType type;
|
||||
final Widget child;
|
||||
final int id;
|
||||
final int? id;
|
||||
final bool hideNavBar;
|
||||
final bool canShowAsDialog;
|
||||
|
||||
@ -27,7 +27,7 @@ class PageInfo {
|
||||
|
||||
PageInfo({
|
||||
this.type = PageType.OTHER_PAGE,
|
||||
@required this.child,
|
||||
required this.child,
|
||||
this.id,
|
||||
this.hideNavBar = false,
|
||||
this.canShowAsDialog = false,
|
||||
|
@ -10,7 +10,7 @@ import 'package:flutter/material.dart';
|
||||
/// @author Pierre HUBERT
|
||||
|
||||
class SmartphoneMainRoute extends StatefulWidget implements MainRoute {
|
||||
const SmartphoneMainRoute({Key key}) : super(key: key);
|
||||
const SmartphoneMainRoute({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _MainRouteState();
|
||||
|
@ -19,7 +19,7 @@ import 'package:flutter/material.dart';
|
||||
const _SideBarSize = 300.0;
|
||||
|
||||
class TabletRoute extends StatefulWidget implements MainRoute {
|
||||
const TabletRoute({Key key}) : super(key: key);
|
||||
const TabletRoute({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_TabletRouteState createState() => _TabletRouteState();
|
||||
@ -37,7 +37,7 @@ class _TabletRouteState extends MainController {
|
||||
return WillPopScope(
|
||||
onWillPop: willPop,
|
||||
child: Scaffold(
|
||||
appBar: _buildAppBar(),
|
||||
appBar: _buildAppBar() as PreferredSizeWidget?,
|
||||
body: _buildBody(),
|
||||
),
|
||||
);
|
||||
@ -105,14 +105,14 @@ class _TabletRouteState extends MainController {
|
||||
}
|
||||
|
||||
@override
|
||||
void openConversationById(int convID, {fullScreen = false}) {
|
||||
void openConversationById(int? convID, {fullScreen = false}) {
|
||||
if (!fullScreen) {
|
||||
popUntilMainRoute();
|
||||
_conversationsKey.currentState.openConversations(convID);
|
||||
_conversationsKey.currentState!.openConversations(convID);
|
||||
} else
|
||||
super.openConversationById(convID, fullScreen: fullScreen);
|
||||
super.openConversationById(convID!, fullScreen: fullScreen);
|
||||
}
|
||||
|
||||
@override
|
||||
void startCall(int convID) => _callsKey.currentState.openCall(convID);
|
||||
void startCall(int convID) => _callsKey.currentState!.openCall(convID);
|
||||
}
|
||||
|
@ -17,8 +17,8 @@ class PasswordResetRoute extends StatelessWidget {
|
||||
final String token;
|
||||
|
||||
const PasswordResetRoute({
|
||||
Key key,
|
||||
@required this.token,
|
||||
Key? key,
|
||||
required this.token,
|
||||
}) : assert(token != null),
|
||||
super(key: key);
|
||||
|
||||
@ -27,7 +27,7 @@ class PasswordResetRoute extends StatelessWidget {
|
||||
return LoginRouteContainer(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(tr("Change your password")),
|
||||
title: Text(tr("Change your password")!),
|
||||
),
|
||||
body: _PasswordResetBody(token: token),
|
||||
),
|
||||
@ -38,7 +38,7 @@ class PasswordResetRoute extends StatelessWidget {
|
||||
class _PasswordResetBody extends StatefulWidget {
|
||||
final String token;
|
||||
|
||||
const _PasswordResetBody({Key key, @required this.token})
|
||||
const _PasswordResetBody({Key? key, required this.token})
|
||||
: assert(token != null),
|
||||
super(key: key);
|
||||
|
||||
@ -52,7 +52,7 @@ class __PasswordResetBodyState extends SafeState<_PasswordResetBody> {
|
||||
final _key = GlobalKey<AsyncScreenWidgetState>();
|
||||
|
||||
var _status = _Status.BEFORE_CHANGE;
|
||||
ResCheckPasswordToken _tokenInfo;
|
||||
late ResCheckPasswordToken _tokenInfo;
|
||||
|
||||
void _setStatus(_Status s) => setState(() => _status = s);
|
||||
|
||||
@ -68,7 +68,7 @@ class __PasswordResetBodyState extends SafeState<_PasswordResetBody> {
|
||||
onReload: _validateToken, // The first time, we validate the token
|
||||
onBuild: _buildBody,
|
||||
errorMessage: tr(
|
||||
"Could not validate your password reset token! Maybe it has expired now..."),
|
||||
"Could not validate your password reset token! Maybe it has expired now...")!,
|
||||
);
|
||||
}
|
||||
|
||||
@ -79,10 +79,10 @@ class __PasswordResetBodyState extends SafeState<_PasswordResetBody> {
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Text(tr("You can choose a new password.")),
|
||||
Text(tr("You can choose a new password.")!),
|
||||
OutlinedButton(
|
||||
onPressed: _changePassword,
|
||||
child: Text(tr("Choose a new password")),
|
||||
child: Text(tr("Choose a new password")!),
|
||||
)
|
||||
],
|
||||
));
|
||||
@ -97,12 +97,12 @@ class __PasswordResetBodyState extends SafeState<_PasswordResetBody> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
tr("Congratulations! Your password has now been successfully changed!"),
|
||||
tr("Congratulations! Your password has now been successfully changed!")!,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
OutlinedButton(
|
||||
onPressed: _quitScreen,
|
||||
child: Text(tr("Login")),
|
||||
child: Text(tr("Login")!),
|
||||
)
|
||||
],
|
||||
));
|
||||
@ -130,10 +130,10 @@ class __PasswordResetBodyState extends SafeState<_PasswordResetBody> {
|
||||
_setStatus(_Status.AFTER_CHANGE);
|
||||
} catch (e, s) {
|
||||
print("Could not change user password! $e\n$s");
|
||||
showSimpleSnack(context, tr("Could not change your password!"));
|
||||
showSimpleSnack(context, tr("Could not change your password!")!);
|
||||
|
||||
// We start everything again
|
||||
_key.currentState.refresh();
|
||||
_key.currentState!.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,9 +52,9 @@ class _PushNotificationsConfigurationRouteState
|
||||
Spacer(),
|
||||
OutlinedButton(
|
||||
onPressed: _key?.currentState?.canSubmit ?? false
|
||||
? _key.currentState.submit
|
||||
? _key.currentState!.submit
|
||||
: null,
|
||||
child: Text(tr("Configure").toUpperCase()),
|
||||
child: Text(tr("Configure")!.toUpperCase()),
|
||||
style: OutlinedButton.styleFrom(primary: Colors.white)),
|
||||
Spacer(),
|
||||
],
|
||||
@ -69,9 +69,9 @@ class PushNotificationsConfigurationWidget extends StatefulWidget {
|
||||
final Function() onChanged;
|
||||
|
||||
const PushNotificationsConfigurationWidget({
|
||||
Key key,
|
||||
@required this.onConfigured,
|
||||
@required this.onChanged,
|
||||
Key? key,
|
||||
required this.onConfigured,
|
||||
required this.onChanged,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@ -81,7 +81,7 @@ class PushNotificationsConfigurationWidget extends StatefulWidget {
|
||||
|
||||
class PushNotificationsConfigurationWidgetState
|
||||
extends State<PushNotificationsConfigurationWidget> {
|
||||
PushNotificationsStatus currStatus;
|
||||
PushNotificationsStatus? currStatus;
|
||||
|
||||
bool get canSubmit =>
|
||||
(currStatus ?? PushNotificationsStatus.UNDEFINED) !=
|
||||
@ -92,7 +92,7 @@ class PushNotificationsConfigurationWidgetState
|
||||
currStatus = await PushNotificationsHelper.getLocalStatus();
|
||||
|
||||
if (currStatus == PushNotificationsStatus.UNDEFINED &&
|
||||
srvConfig.notificationsPolicy.hasFirebase)
|
||||
srvConfig!.notificationsPolicy.hasFirebase)
|
||||
currStatus = PushNotificationsStatus.FIREBASE;
|
||||
|
||||
widget.onChanged();
|
||||
@ -103,7 +103,7 @@ class PushNotificationsConfigurationWidgetState
|
||||
return AsyncScreenWidget(
|
||||
onReload: _refresh,
|
||||
onBuild: _buildForm,
|
||||
errorMessage: tr("Failed to load push notifications settings!"),
|
||||
errorMessage: tr("Failed to load push notifications settings!")!,
|
||||
);
|
||||
}
|
||||
|
||||
@ -114,16 +114,16 @@ class PushNotificationsConfigurationWidgetState
|
||||
Text(
|
||||
tr("%app% can send push notifications to your device.", args: {
|
||||
"app": config().appName,
|
||||
}),
|
||||
})!,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
_NotificationOption(
|
||||
title: tr("Use Google services (recommended)"),
|
||||
title: tr("Use Google services (recommended)")!,
|
||||
description: tr("Save your battery life."),
|
||||
option: PushNotificationsStatus.FIREBASE,
|
||||
current: currStatus,
|
||||
available: srvConfig.notificationsPolicy.hasFirebase,
|
||||
current: currStatus!,
|
||||
available: srvConfig!.notificationsPolicy.hasFirebase,
|
||||
onChanged: (s) {
|
||||
setState(() => currStatus = s);
|
||||
if (widget.onChanged != null) widget.onChanged();
|
||||
@ -131,13 +131,13 @@ class PushNotificationsConfigurationWidgetState
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
_NotificationOption(
|
||||
title: tr("Use independent notifications service"),
|
||||
title: tr("Use independent notifications service")!,
|
||||
description: tr(
|
||||
"Protect more your privacy, but drains battery and is less reliable."),
|
||||
option: PushNotificationsStatus.INDEPENDENT,
|
||||
current: currStatus,
|
||||
current: currStatus!,
|
||||
available:
|
||||
srvConfig.notificationsPolicy.hasIndependent && isAndroid,
|
||||
srvConfig!.notificationsPolicy.hasIndependent && isAndroid,
|
||||
onChanged: (s) {
|
||||
setState(() => currStatus = s);
|
||||
if (widget.onChanged != null) widget.onChanged();
|
||||
@ -145,9 +145,9 @@ class PushNotificationsConfigurationWidgetState
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
_NotificationOption(
|
||||
title: tr("Do not send notification"),
|
||||
title: tr("Do not send notification")!,
|
||||
option: PushNotificationsStatus.DISABLED,
|
||||
current: currStatus,
|
||||
current: currStatus!,
|
||||
available: true,
|
||||
onChanged: (s) {
|
||||
setState(() => currStatus = s);
|
||||
@ -181,20 +181,20 @@ class PushNotificationsConfigurationWidgetState
|
||||
|
||||
class _NotificationOption extends StatelessWidget {
|
||||
final String title;
|
||||
final String description;
|
||||
final String? description;
|
||||
final PushNotificationsStatus option;
|
||||
final PushNotificationsStatus current;
|
||||
final bool available;
|
||||
final Function(PushNotificationsStatus) onChanged;
|
||||
final Function(PushNotificationsStatus?) onChanged;
|
||||
|
||||
const _NotificationOption({
|
||||
Key key,
|
||||
@required this.title,
|
||||
Key? key,
|
||||
required this.title,
|
||||
this.description,
|
||||
@required this.option,
|
||||
@required this.current,
|
||||
@required this.available,
|
||||
@required this.onChanged,
|
||||
required this.option,
|
||||
required this.current,
|
||||
required this.available,
|
||||
required this.onChanged,
|
||||
}) : assert(title != null),
|
||||
assert(option != null),
|
||||
assert(current != null),
|
||||
@ -219,7 +219,7 @@ class _NotificationOption extends StatelessWidget {
|
||||
title: Text(title, style: TextStyle(color: Colors.white)),
|
||||
subtitle: description == null
|
||||
? null
|
||||
: Text(description, style: TextStyle(color: Colors.white)),
|
||||
: Text(description!, style: TextStyle(color: Colors.white)),
|
||||
contentPadding: EdgeInsets.all(0),
|
||||
onTap: () => onChanged(option),
|
||||
),
|
||||
|
@ -24,16 +24,16 @@ class AboutApplicationSettings extends StatelessWidget {
|
||||
tiles: [
|
||||
SettingsTile(
|
||||
title: tr("Privacy policy"),
|
||||
onPressed: (c) => launch(srvConfig.privacyPolicyURL),
|
||||
onPressed: (c) => launch(srvConfig!.privacyPolicyURL),
|
||||
),
|
||||
SettingsTile(
|
||||
title: tr("Terms of Use"),
|
||||
onPressed: (c) => launch(srvConfig.termsURL),
|
||||
onPressed: (c) => launch(srvConfig!.termsURL),
|
||||
),
|
||||
SettingsTile(
|
||||
title: tr("Contact us"),
|
||||
subtitle: srvConfig.contactEmail,
|
||||
trailing: CopyIcon(srvConfig.contactEmail),
|
||||
subtitle: srvConfig!.contactEmail,
|
||||
trailing: CopyIcon(srvConfig!.contactEmail),
|
||||
),
|
||||
SettingsTile(
|
||||
title: tr("About this application"),
|
||||
|
@ -30,7 +30,7 @@ class AccountImageSettingsScreen extends StatefulWidget {
|
||||
|
||||
class _AccountImageSettingsScreenState
|
||||
extends State<AccountImageSettingsScreen> {
|
||||
AccountImageSettings _settings;
|
||||
late AccountImageSettings _settings;
|
||||
|
||||
final _key = GlobalKey<AsyncScreenWidgetState>();
|
||||
|
||||
@ -49,7 +49,7 @@ class _AccountImageSettingsScreenState
|
||||
onReload: () async =>
|
||||
_settings = await SettingsHelper.getAccountImageSettings(),
|
||||
onBuild: () => _buildLayout(),
|
||||
errorMessage: tr("Could not get account image settings!"),
|
||||
errorMessage: tr("Could not get account image settings!")!,
|
||||
);
|
||||
}
|
||||
|
||||
@ -96,19 +96,19 @@ class _AccountImageSettingsScreenState
|
||||
[
|
||||
MultiChoiceEntry(
|
||||
id: AccountImageVisibilityLevels.EVERYONE,
|
||||
title: tr("Everyone"),
|
||||
title: tr("Everyone")!,
|
||||
subtitle: tr(
|
||||
"Your account image is visible by everyone, including users external to Comunic."),
|
||||
),
|
||||
MultiChoiceEntry(
|
||||
id: AccountImageVisibilityLevels.COMUNIC_USERS,
|
||||
title: tr("Connected users"),
|
||||
title: tr("Connected users")!,
|
||||
subtitle: tr(
|
||||
"Your account image is visible only to connected Comunic users."),
|
||||
),
|
||||
MultiChoiceEntry(
|
||||
id: AccountImageVisibilityLevels.FRIENDS_ONLY,
|
||||
title: tr("My friends"),
|
||||
title: tr("My friends")!,
|
||||
subtitle: tr("Your account image is visible only by your friends."),
|
||||
),
|
||||
];
|
||||
@ -139,14 +139,14 @@ class _AccountImageSettingsScreenState
|
||||
|
||||
// Change account image visibility
|
||||
MultiChoicesSettingsTile(
|
||||
title: tr("Account image visibility"),
|
||||
title: tr("Account image visibility")!,
|
||||
choices: _visibilityLevels,
|
||||
currentValue: _settings.visibility,
|
||||
onChanged: (newLevel) async {
|
||||
onChanged: (dynamic newLevel) async {
|
||||
if (!await SettingsHelper.setAccountImageVisibilityLevel(newLevel))
|
||||
showSimpleSnack(context,
|
||||
tr("Could not update account image visibility level!"));
|
||||
_key.currentState.refresh();
|
||||
tr("Could not update account image visibility level!")!);
|
||||
_key.currentState!.refresh();
|
||||
}),
|
||||
|
||||
// Delete account image
|
||||
@ -160,7 +160,7 @@ class _AccountImageSettingsScreenState
|
||||
/// Upload a new account image
|
||||
void _uploadAccountImage() async {
|
||||
await uploadNewAccountImage(context);
|
||||
_key.currentState.refresh();
|
||||
_key.currentState!.refresh();
|
||||
}
|
||||
|
||||
/// Generate a random account image
|
||||
@ -170,11 +170,11 @@ class _AccountImageSettingsScreenState
|
||||
|
||||
if (!await SettingsHelper.uploadAccountImageFromMemory(bytes)) {
|
||||
showSimpleSnack(
|
||||
context, tr("Could not upload your generated account image!"));
|
||||
context, tr("Could not upload your generated account image!")!);
|
||||
return;
|
||||
}
|
||||
|
||||
_key.currentState.refresh();
|
||||
_key.currentState!.refresh();
|
||||
}
|
||||
|
||||
/// Delete user account image
|
||||
@ -185,11 +185,11 @@ class _AccountImageSettingsScreenState
|
||||
return;
|
||||
|
||||
if (!await SettingsHelper.deleteAccountImage()) {
|
||||
showSimpleSnack(context, tr("Could not delete user account image!"));
|
||||
showSimpleSnack(context, tr("Could not delete user account image!")!);
|
||||
return;
|
||||
}
|
||||
|
||||
_key.currentState.refresh();
|
||||
_key.currentState!.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,6 +203,6 @@ Future<void> uploadNewAccountImage(BuildContext context) async {
|
||||
await SettingsHelper.uploadAccountImage(image);
|
||||
} catch (e, s) {
|
||||
logError(e, s);
|
||||
snack(context, tr("Failed to upload new account image!"));
|
||||
snack(context, tr("Failed to upload new account image!")!);
|
||||
}
|
||||
}
|
||||
|
@ -25,9 +25,9 @@ class AccountPrivacySettings extends StatefulWidget {
|
||||
|
||||
class _AccountPrivacySettingsState extends State<AccountPrivacySettings> {
|
||||
final _key = GlobalKey<AsyncScreenWidgetState>();
|
||||
ServerConfig _serverConfig;
|
||||
DataConservationPolicySettings _userSettings;
|
||||
String _cachedPassword;
|
||||
ServerConfig? _serverConfig;
|
||||
late DataConservationPolicySettings _userSettings;
|
||||
String? _cachedPassword;
|
||||
|
||||
Future<void> _loadSettings() async {
|
||||
_serverConfig = ServerConfigurationHelper.config;
|
||||
@ -59,68 +59,68 @@ class _AccountPrivacySettingsState extends State<AccountPrivacySettings> {
|
||||
)
|
||||
])
|
||||
]),
|
||||
errorMessage: tr("Failed to load privacy settings!"),
|
||||
errorMessage: tr("Failed to load privacy settings!")!,
|
||||
);
|
||||
}
|
||||
|
||||
List<SettingsTile> get _dataConservationPolicyTiles => [
|
||||
DataConservationPolicyTile(
|
||||
value: _userSettings.notificationLifetime,
|
||||
title: tr("Automatically delete unread notifications after"),
|
||||
title: tr("Automatically delete unread notifications after")!,
|
||||
onChange: (val) {
|
||||
_userSettings.notificationLifetime = val;
|
||||
_updateDataConservationPolicy();
|
||||
},
|
||||
minValue:
|
||||
_serverConfig.dataConservationPolicy.minNotificationLifetime,
|
||||
_serverConfig!.dataConservationPolicy.minNotificationLifetime,
|
||||
),
|
||||
DataConservationPolicyTile(
|
||||
value: _userSettings.commentsLifetime,
|
||||
title: tr("Automatically delete your comments after"),
|
||||
title: tr("Automatically delete your comments after")!,
|
||||
onChange: (val) {
|
||||
_userSettings.commentsLifetime = val;
|
||||
_updateDataConservationPolicy();
|
||||
},
|
||||
minValue: _serverConfig.dataConservationPolicy.minCommentsLifetime,
|
||||
minValue: _serverConfig!.dataConservationPolicy.minCommentsLifetime,
|
||||
),
|
||||
DataConservationPolicyTile(
|
||||
value: _userSettings.postsLifetime,
|
||||
title: tr("Automatically delete your posts after"),
|
||||
title: tr("Automatically delete your posts after")!,
|
||||
onChange: (val) {
|
||||
_userSettings.postsLifetime = val;
|
||||
_updateDataConservationPolicy();
|
||||
},
|
||||
minValue: _serverConfig.dataConservationPolicy.minPostsLifetime,
|
||||
minValue: _serverConfig!.dataConservationPolicy.minPostsLifetime,
|
||||
),
|
||||
DataConservationPolicyTile(
|
||||
value: _userSettings.conversationMessagesLifetime,
|
||||
title: tr("Automatically delete your conversation messages after"),
|
||||
title: tr("Automatically delete your conversation messages after")!,
|
||||
onChange: (val) {
|
||||
_userSettings.conversationMessagesLifetime = val;
|
||||
_updateDataConservationPolicy();
|
||||
},
|
||||
minValue: _serverConfig
|
||||
minValue: _serverConfig!
|
||||
.dataConservationPolicy.minConversationMessagesLifetime,
|
||||
),
|
||||
DataConservationPolicyTile(
|
||||
value: _userSettings.likesLifetime,
|
||||
title: tr("Automatically delete your likes after"),
|
||||
title: tr("Automatically delete your likes after")!,
|
||||
onChange: (val) {
|
||||
_userSettings.likesLifetime = val;
|
||||
_updateDataConservationPolicy();
|
||||
},
|
||||
minValue: _serverConfig.dataConservationPolicy.minLikesLifetime,
|
||||
minValue: _serverConfig!.dataConservationPolicy.minLikesLifetime,
|
||||
),
|
||||
DataConservationPolicyTile(
|
||||
value: _userSettings.inactiveAccountLifeTime,
|
||||
title: tr(
|
||||
"Automatically delete your account if you have been inactive for"),
|
||||
"Automatically delete your account if you have been inactive for")!,
|
||||
onChange: (val) {
|
||||
_userSettings.inactiveAccountLifeTime = val;
|
||||
_updateDataConservationPolicy();
|
||||
},
|
||||
minValue:
|
||||
_serverConfig.dataConservationPolicy.minInactiveAccountLifetime,
|
||||
_serverConfig!.dataConservationPolicy.minInactiveAccountLifetime,
|
||||
),
|
||||
];
|
||||
|
||||
@ -132,11 +132,11 @@ class _AccountPrivacySettingsState extends State<AccountPrivacySettings> {
|
||||
await SettingsHelper.setDataConservationPolicy(
|
||||
_cachedPassword, _userSettings);
|
||||
|
||||
_key.currentState.refresh();
|
||||
_key.currentState!.refresh();
|
||||
} catch (e, s) {
|
||||
print("Could not update data conservation policy! $e\n$s");
|
||||
showSimpleSnack(
|
||||
context, tr("Failed to update data conservation policy!"));
|
||||
context, tr("Failed to update data conservation policy!")!);
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,22 +164,22 @@ class _AccountPrivacySettingsState extends State<AccountPrivacySettings> {
|
||||
await AccountHelper.deleteAccount(password);
|
||||
} catch (e, stack) {
|
||||
print("Could not delete user account! $e\n$stack");
|
||||
showSimpleSnack(context, tr("Could not delete your account!"));
|
||||
showSimpleSnack(context, tr("Could not delete your account!")!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DataConservationPolicyTile extends SettingsTile {
|
||||
final int value;
|
||||
final int? value;
|
||||
final String title;
|
||||
final Function(int) onChange;
|
||||
final int minValue;
|
||||
|
||||
DataConservationPolicyTile({
|
||||
@required this.value,
|
||||
@required this.title,
|
||||
@required this.onChange,
|
||||
@required this.minValue,
|
||||
required this.value,
|
||||
required this.title,
|
||||
required this.onChange,
|
||||
required this.minValue,
|
||||
}) : assert(title != null),
|
||||
assert(onChange != null),
|
||||
assert(minValue != null);
|
||||
@ -203,59 +203,59 @@ class DataConservationPolicyTile extends SettingsTile {
|
||||
int get _roundValue {
|
||||
if (this.value == null) return 0;
|
||||
|
||||
return _choices.firstWhere((element) => element.id >= this.value).id;
|
||||
return _choices.firstWhere((element) => element.id >= this.value!).id;
|
||||
}
|
||||
|
||||
List<MultiChoiceEntry<int>> get _choices => [
|
||||
MultiChoiceEntry(id: 0, title: tr("Never"), hidden: false),
|
||||
MultiChoiceEntry(id: 0, title: tr("Never")!, hidden: false),
|
||||
MultiChoiceEntry(
|
||||
id: _day * 7,
|
||||
title: tr("7 days"),
|
||||
title: tr("7 days")!,
|
||||
hidden: _day * 7 < minValue,
|
||||
),
|
||||
MultiChoiceEntry(
|
||||
id: _day * 15,
|
||||
title: tr("15 days"),
|
||||
title: tr("15 days")!,
|
||||
hidden: _day * 15 < minValue,
|
||||
),
|
||||
MultiChoiceEntry(
|
||||
id: _month,
|
||||
title: tr("1 month"),
|
||||
title: tr("1 month")!,
|
||||
hidden: _month < minValue,
|
||||
),
|
||||
MultiChoiceEntry(
|
||||
id: _month * 3,
|
||||
title: tr("3 months"),
|
||||
title: tr("3 months")!,
|
||||
hidden: _month * 3 < minValue,
|
||||
),
|
||||
MultiChoiceEntry(
|
||||
id: _month * 6,
|
||||
title: tr("6 months"),
|
||||
title: tr("6 months")!,
|
||||
hidden: _month * 6 < minValue,
|
||||
),
|
||||
MultiChoiceEntry(
|
||||
id: _year,
|
||||
title: tr("1 year"),
|
||||
title: tr("1 year")!,
|
||||
hidden: _year < minValue,
|
||||
),
|
||||
MultiChoiceEntry(
|
||||
id: _year * 2,
|
||||
title: tr("2 years"),
|
||||
title: tr("2 years")!,
|
||||
hidden: _year * 5 < minValue,
|
||||
),
|
||||
MultiChoiceEntry(
|
||||
id: _year * 5,
|
||||
title: tr("5 years"),
|
||||
title: tr("5 years")!,
|
||||
hidden: _year * 5 < minValue,
|
||||
),
|
||||
MultiChoiceEntry(
|
||||
id: _year * 10,
|
||||
title: tr("10 years"),
|
||||
title: tr("10 years")!,
|
||||
hidden: _year * 10 < minValue,
|
||||
),
|
||||
MultiChoiceEntry(
|
||||
id: _year * 50,
|
||||
title: tr("50 years"),
|
||||
title: tr("50 years")!,
|
||||
hidden: _year * 50 < minValue,
|
||||
),
|
||||
];
|
||||
@ -265,18 +265,18 @@ class _LastChanceDeleteAccountDialog extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CupertinoAlertDialog(
|
||||
title: Text(tr("Delete your account")),
|
||||
title: Text(tr("Delete your account")!),
|
||||
content: Text(tr(
|
||||
"Let us ask you one last time. Do you really want to delete your account? If you decide to do so, your data will be permanently removed from our servers, so we will not be able to recover your account. If you decide to proceed, the deletion process will start immediatly and you will automatically get disconnected from your account.")),
|
||||
"Let us ask you one last time. Do you really want to delete your account? If you decide to do so, your data will be permanently removed from our servers, so we will not be able to recover your account. If you decide to proceed, the deletion process will start immediatly and you will automatically get disconnected from your account.")!),
|
||||
actions: <Widget>[
|
||||
CupertinoDialogAction(
|
||||
isDefaultAction: true,
|
||||
child: Text(tr("Cancel")),
|
||||
child: Text(tr("Cancel")!),
|
||||
onPressed: () => Navigator.of(context).pop(false),
|
||||
),
|
||||
CupertinoDialogAction(
|
||||
isDestructiveAction: true,
|
||||
child: Text(tr("Confirm")),
|
||||
child: Text(tr("Confirm")!),
|
||||
onPressed: () => Navigator.of(context).pop(true),
|
||||
),
|
||||
],
|
||||
|
@ -86,10 +86,10 @@ class _AccountSecuritySettingsScreenState
|
||||
await SettingsHelper.changePassword(currPassword, newPassword);
|
||||
|
||||
showSimpleSnack(
|
||||
context, tr("Your password has been successfully changed!"));
|
||||
context, tr("Your password has been successfully changed!")!);
|
||||
} catch (e, stack) {
|
||||
print("Could not update current user password! $e\n$stack");
|
||||
showSimpleSnack(context, tr("Could not update password!"));
|
||||
showSimpleSnack(context, tr("Could not update password!")!);
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,10 +111,10 @@ class _AccountSecuritySettingsScreenState
|
||||
await SettingsHelper.setSecuritySettings(password, newSettings);
|
||||
|
||||
showSimpleSnack(context,
|
||||
tr("You security questions have been successfully updated!"));
|
||||
tr("You security questions have been successfully updated!")!);
|
||||
} catch (e, stack) {
|
||||
print("Could not update security questions!$e\n$stack");
|
||||
showSimpleSnack(context, tr("Could not update security questions!"));
|
||||
showSimpleSnack(context, tr("Could not update security questions!")!);
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,7 +131,7 @@ class _AccountSecuritySettingsScreenState
|
||||
} catch (e, stack) {
|
||||
print("Could not disconnect user on all devices! $e\n$stack");
|
||||
showSimpleSnack(
|
||||
context, tr("Could not disconnect you from all your devices!"));
|
||||
context, tr("Could not disconnect you from all your devices!")!);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -139,7 +139,7 @@ class _AccountSecuritySettingsScreenState
|
||||
class _SecurityQuestionsDialog extends StatefulWidget {
|
||||
final SecuritySettings settings;
|
||||
|
||||
const _SecurityQuestionsDialog({Key key, @required this.settings})
|
||||
const _SecurityQuestionsDialog({Key? key, required this.settings})
|
||||
: assert(settings != null),
|
||||
super(key: key);
|
||||
|
||||
@ -149,10 +149,10 @@ class _SecurityQuestionsDialog extends StatefulWidget {
|
||||
}
|
||||
|
||||
class __SecurityQuestionsDialogState extends State<_SecurityQuestionsDialog> {
|
||||
TextEditingController _controllerQuestion1;
|
||||
TextEditingController _controllerAnswer1;
|
||||
TextEditingController _controllerQuestion2;
|
||||
TextEditingController _controllerAnswer2;
|
||||
late TextEditingController _controllerQuestion1;
|
||||
late TextEditingController _controllerAnswer1;
|
||||
late TextEditingController _controllerQuestion2;
|
||||
late TextEditingController _controllerAnswer2;
|
||||
|
||||
SecuritySettings get _newSettings => SecuritySettings(
|
||||
securityQuestion1: _controllerQuestion1.text,
|
||||
@ -177,16 +177,16 @@ class __SecurityQuestionsDialogState extends State<_SecurityQuestionsDialog> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text(tr("Update security questions")),
|
||||
title: Text(tr("Update security questions")!),
|
||||
content: AutoSizeDialogContentWidget(child: _buildContent()),
|
||||
actions: <Widget>[
|
||||
MaterialButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(tr("Cancel").toUpperCase()),
|
||||
child: Text(tr("Cancel")!.toUpperCase()),
|
||||
),
|
||||
MaterialButton(
|
||||
onPressed: () => Navigator.of(context).pop(_newSettings),
|
||||
child: Text(tr("Update").toUpperCase()),
|
||||
child: Text(tr("Update")!.toUpperCase()),
|
||||
)
|
||||
],
|
||||
);
|
||||
@ -196,7 +196,7 @@ class __SecurityQuestionsDialogState extends State<_SecurityQuestionsDialog> {
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
Text(tr(
|
||||
"Note: Your two questions and answers MUST be completed in order to be able to recover your account using your security questions!")),
|
||||
"Note: Your two questions and answers MUST be completed in order to be able to recover your account using your security questions!")!),
|
||||
_buildTextField(
|
||||
controller: _controllerQuestion1, label: tr("Question 1")),
|
||||
_buildTextField(controller: _controllerAnswer1, label: tr("Answer 1")),
|
||||
@ -208,8 +208,8 @@ class __SecurityQuestionsDialogState extends State<_SecurityQuestionsDialog> {
|
||||
}
|
||||
|
||||
Widget _buildTextField({
|
||||
@required TextEditingController controller,
|
||||
@required String label,
|
||||
required TextEditingController controller,
|
||||
required String? label,
|
||||
}) {
|
||||
return TextField(
|
||||
controller: controller,
|
||||
|
@ -27,10 +27,10 @@ class _SettingsSection {
|
||||
final Widget Function() onBuild;
|
||||
|
||||
const _SettingsSection({
|
||||
@required this.title,
|
||||
@required this.subtitle,
|
||||
@required this.icon,
|
||||
@required this.onBuild,
|
||||
required this.title,
|
||||
required this.subtitle,
|
||||
required this.icon,
|
||||
required this.onBuild,
|
||||
}) : assert(title != null),
|
||||
assert(subtitle != null),
|
||||
assert(icon != null),
|
||||
@ -42,14 +42,14 @@ class AccountSettingsRoute extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(tr("Settings")),
|
||||
title: Text(tr("Settings")!),
|
||||
actions: [
|
||||
PopupMenuButton<_MainMenuActions>(
|
||||
onSelected: (v) => _doPopupMenuAction(context, v),
|
||||
itemBuilder: (c) => [
|
||||
PopupMenuItem(
|
||||
value: _MainMenuActions.SHOW_TOUR,
|
||||
child: Text(tr("See the tour again")),
|
||||
child: Text(tr("See the tour again")!),
|
||||
),
|
||||
]),
|
||||
],
|
||||
@ -74,7 +74,7 @@ class _AccountSettingsBody extends StatefulWidget {
|
||||
}
|
||||
|
||||
class __AccountSettingsBodyState extends State<_AccountSettingsBody> {
|
||||
_SettingsSection _currentSection;
|
||||
late _SettingsSection _currentSection;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -87,64 +87,64 @@ class __AccountSettingsBodyState extends State<_AccountSettingsBody> {
|
||||
/// The list of settings sections
|
||||
List<_SettingsSection> get _sections => [
|
||||
_SettingsSection(
|
||||
title: tr("General settings"),
|
||||
subtitle: tr("Configure the main settings of your account"),
|
||||
title: tr("General settings")!,
|
||||
subtitle: tr("Configure the main settings of your account")!,
|
||||
icon: Icons.settings,
|
||||
onBuild: () => GeneralAccountSettingsScreen(),
|
||||
),
|
||||
|
||||
// Emoticons
|
||||
_SettingsSection(
|
||||
title: tr("Custom emojis"),
|
||||
subtitle: tr("Set your own emoticon shorcuts"),
|
||||
title: tr("Custom emojis")!,
|
||||
subtitle: tr("Set your own emoticon shorcuts")!,
|
||||
icon: Icons.insert_emoticon,
|
||||
onBuild: () => CustomEmojisAccountSettings(),
|
||||
),
|
||||
|
||||
// Account image
|
||||
_SettingsSection(
|
||||
title: tr("Account image"),
|
||||
subtitle: tr("Customize your account image"),
|
||||
title: tr("Account image")!,
|
||||
subtitle: tr("Customize your account image")!,
|
||||
icon: Icons.account_circle,
|
||||
onBuild: () => AccountImageSettingsScreen(),
|
||||
),
|
||||
|
||||
// Notifications settings
|
||||
_SettingsSection(
|
||||
title: tr("Notifications"),
|
||||
subtitle: tr("Choose the notifications you receive on your phone"),
|
||||
title: tr("Notifications")!,
|
||||
subtitle: tr("Choose the notifications you receive on your phone")!,
|
||||
icon: Icons.notifications,
|
||||
onBuild: () => NotificationsSettingsScreen(),
|
||||
),
|
||||
|
||||
// Security settings
|
||||
_SettingsSection(
|
||||
title: tr("Security"),
|
||||
subtitle: tr("Manage security options of your account"),
|
||||
title: tr("Security")!,
|
||||
subtitle: tr("Manage security options of your account")!,
|
||||
icon: Icons.lock,
|
||||
onBuild: () => AccountSecuritySettingsScreen(),
|
||||
),
|
||||
|
||||
// Privacy settings
|
||||
_SettingsSection(
|
||||
title: tr("Privacy"),
|
||||
subtitle: tr("Here you can make actions to protect your privacy"),
|
||||
title: tr("Privacy")!,
|
||||
subtitle: tr("Here you can make actions to protect your privacy")!,
|
||||
icon: Icons.security,
|
||||
onBuild: () => AccountPrivacySettings(),
|
||||
),
|
||||
|
||||
// Application settings
|
||||
_SettingsSection(
|
||||
title: tr("Application settings"),
|
||||
subtitle: tr("Manage local application settings"),
|
||||
title: tr("Application settings")!,
|
||||
subtitle: tr("Manage local application settings")!,
|
||||
icon: Icons.smartphone,
|
||||
onBuild: () => ApplicationSettings(),
|
||||
),
|
||||
|
||||
// About settings
|
||||
_SettingsSection(
|
||||
title: tr("About this application"),
|
||||
subtitle: tr("Learn more about us"),
|
||||
title: tr("About this application")!,
|
||||
subtitle: tr("Learn more about us")!,
|
||||
icon: Icons.info,
|
||||
onBuild: () => AboutApplicationSettings(),
|
||||
),
|
||||
|
@ -17,7 +17,7 @@ class ApplicationSettings extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _ApplicationSettingsState extends State<ApplicationSettings> {
|
||||
PreferencesHelper _preferencesHelper;
|
||||
PreferencesHelper? _preferencesHelper;
|
||||
|
||||
Future<void> _refresh() async {
|
||||
_preferencesHelper = await PreferencesHelper.getInstance();
|
||||
@ -27,7 +27,7 @@ class _ApplicationSettingsState extends State<ApplicationSettings> {
|
||||
Widget build(BuildContext context) => AsyncScreenWidget(
|
||||
onReload: _refresh,
|
||||
onBuild: _buildSections,
|
||||
errorMessage: tr("Could not load settings!"));
|
||||
errorMessage: tr("Could not load settings!")!);
|
||||
|
||||
Widget _buildSections() {
|
||||
return SettingsList(
|
||||
@ -89,17 +89,17 @@ class _ApplicationSettingsState extends State<ApplicationSettings> {
|
||||
|
||||
class _PreferencesSettingsTile extends SettingsTile {
|
||||
final PreferencesKeyList preferencesKey;
|
||||
final String title;
|
||||
final String subtitle;
|
||||
final String? title;
|
||||
final String? subtitle;
|
||||
final Function onChange;
|
||||
final PreferencesHelper helper;
|
||||
final PreferencesHelper? helper;
|
||||
|
||||
_PreferencesSettingsTile({
|
||||
@required this.preferencesKey,
|
||||
@required this.title,
|
||||
@required this.subtitle,
|
||||
@required this.onChange,
|
||||
@required this.helper,
|
||||
required this.preferencesKey,
|
||||
required this.title,
|
||||
required this.subtitle,
|
||||
required this.onChange,
|
||||
required this.helper,
|
||||
});
|
||||
|
||||
@override
|
||||
@ -108,14 +108,14 @@ class _PreferencesSettingsTile extends SettingsTile {
|
||||
title: title,
|
||||
subtitle: subtitle,
|
||||
onToggle: _doChange,
|
||||
switchValue: helper.getBool(preferencesKey),
|
||||
switchValue: helper!.getBool(preferencesKey),
|
||||
titleMaxLines: 2,
|
||||
subtitleMaxLines: 4,
|
||||
);
|
||||
}
|
||||
|
||||
void _doChange(bool value) async {
|
||||
await helper.setBool(preferencesKey, value);
|
||||
await helper!.setBool(preferencesKey, value);
|
||||
onChange();
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ class CustomEmojisAccountSettings extends StatefulWidget {
|
||||
|
||||
class _CustomEmojisAccountSettingsState
|
||||
extends State<CustomEmojisAccountSettings> {
|
||||
User _user;
|
||||
late User _user;
|
||||
|
||||
final _key = GlobalKey<AsyncScreenWidgetState>();
|
||||
|
||||
@ -45,7 +45,7 @@ class _CustomEmojisAccountSettingsState
|
||||
key: _key,
|
||||
onReload: _reload,
|
||||
onBuild: _buildSettings,
|
||||
errorMessage: tr("Could not refresh user information!"),
|
||||
errorMessage: tr("Could not refresh user information!")!,
|
||||
showOldDataWhileUpdating: true,
|
||||
);
|
||||
}
|
||||
@ -63,8 +63,8 @@ class _CustomEmojisAccountSettingsState
|
||||
return ListView(
|
||||
children: _user.customEmojies
|
||||
.map((u) => ListTile(
|
||||
leading: NetworkImageWidget(url: u.url, width: 50),
|
||||
title: Text(u.shortcut),
|
||||
leading: NetworkImageWidget(url: u.url!, width: 50),
|
||||
title: Text(u.shortcut!),
|
||||
trailing: IconButton(
|
||||
icon: Icon(Icons.delete),
|
||||
onPressed: () => _deleteEmoji(u)),
|
||||
@ -98,10 +98,10 @@ class _CustomEmojisAccountSettingsState
|
||||
await SettingsHelper.uploadNewCustomEmoji(newEmoji);
|
||||
} catch (e, stack) {
|
||||
print("Could not add a new emoji: $e\n$stack");
|
||||
showSimpleSnack(context, tr("Could not upload emoji!"));
|
||||
showSimpleSnack(context, tr("Could not upload emoji!")!);
|
||||
}
|
||||
|
||||
_key.currentState.refresh();
|
||||
_key.currentState!.refresh();
|
||||
}
|
||||
|
||||
/// Ask for confirmation before deleting permanently an emoji
|
||||
@ -115,10 +115,10 @@ class _CustomEmojisAccountSettingsState
|
||||
await SettingsHelper.deleteCustomEmoji(u.id);
|
||||
} catch (e, stack) {
|
||||
print("Could not delete custom emoji! $e\n$stack");
|
||||
showSimpleSnack(context, tr("Could not delete custom emoji!"));
|
||||
showSimpleSnack(context, tr("Could not delete custom emoji!")!);
|
||||
}
|
||||
|
||||
_key.currentState.refresh();
|
||||
_key.currentState!.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,8 +127,8 @@ class _NewCustomEmojiDialog extends StatefulWidget {
|
||||
final CustomEmojiesList currentList;
|
||||
|
||||
const _NewCustomEmojiDialog({
|
||||
Key key,
|
||||
@required this.currentList,
|
||||
Key? key,
|
||||
required this.currentList,
|
||||
}) : assert(currentList != null),
|
||||
super(key: key);
|
||||
|
||||
@ -138,7 +138,7 @@ class _NewCustomEmojiDialog extends StatefulWidget {
|
||||
|
||||
class _NewCustomEmojiDialogState extends State<_NewCustomEmojiDialog> {
|
||||
final _controller = TextEditingController();
|
||||
BytesFile _file;
|
||||
BytesFile? _file;
|
||||
|
||||
bool get _hasImage => _file != null;
|
||||
|
||||
@ -151,12 +151,12 @@ class _NewCustomEmojiDialogState extends State<_NewCustomEmojiDialog> {
|
||||
|
||||
bool get _valid => _hasImage && _shortcutValid;
|
||||
|
||||
NewEmoji get _emoji => NewEmoji(shortcut: _shortcut, image: _file);
|
||||
NewEmoji get _emoji => NewEmoji(shortcut: _shortcut, image: _file!);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text(tr("Add new emoji")),
|
||||
title: Text(tr("Add new emoji")!),
|
||||
content: ConstrainedBox(
|
||||
constraints:
|
||||
BoxConstraints(maxHeight: MediaQuery.of(context).size.height - 50),
|
||||
@ -167,11 +167,11 @@ class _NewCustomEmojiDialogState extends State<_NewCustomEmojiDialog> {
|
||||
actions: <Widget>[
|
||||
MaterialButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(tr("Cancel").toUpperCase()),
|
||||
child: Text(tr("Cancel")!.toUpperCase()),
|
||||
),
|
||||
MaterialButton(
|
||||
onPressed: _valid ? () => Navigator.of(context).pop(_emoji) : null,
|
||||
child: Text(tr("Add").toUpperCase()),
|
||||
child: Text(tr("Add")!.toUpperCase()),
|
||||
),
|
||||
],
|
||||
);
|
||||
@ -194,7 +194,7 @@ class _NewCustomEmojiDialogState extends State<_NewCustomEmojiDialog> {
|
||||
),
|
||||
MaterialButton(
|
||||
onPressed: _pickImage,
|
||||
child: Text(_hasImage ? tr("Replace image") : tr("Add image")),
|
||||
child: Text(_hasImage ? tr("Replace image")! : tr("Add image")!),
|
||||
)
|
||||
],
|
||||
);
|
||||
@ -211,7 +211,7 @@ class _NewCustomEmojiDialogState extends State<_NewCustomEmojiDialog> {
|
||||
});
|
||||
} catch (e, stack) {
|
||||
print("Could not pick an image! $e\n$stack");
|
||||
snack(context, tr("Failed to pick an image!"));
|
||||
snack(context, tr("Failed to pick an image!")!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ class GeneralAccountSettingsScreen extends StatefulWidget {
|
||||
|
||||
class _GeneralAccountSettingsScreenState
|
||||
extends State<GeneralAccountSettingsScreen> {
|
||||
GeneralSettings _settings;
|
||||
late GeneralSettings _settings;
|
||||
|
||||
final _key = GlobalKey<AsyncScreenWidgetState>();
|
||||
|
||||
@ -47,7 +47,7 @@ class _GeneralAccountSettingsScreenState
|
||||
onReload: () async =>
|
||||
_settings = await SettingsHelper.getGeneralSettings(),
|
||||
onBuild: _buildSettings,
|
||||
errorMessage: tr("Could not load general settings!"),
|
||||
errorMessage: tr("Could not load general settings!")!,
|
||||
showOldDataWhileUpdating: true,
|
||||
);
|
||||
}
|
||||
@ -81,28 +81,28 @@ class _GeneralAccountSettingsScreenState
|
||||
|
||||
// First name
|
||||
TextEditSettingsTile(
|
||||
title: tr("First name"),
|
||||
title: tr("First name")!,
|
||||
currValue: _settings.firstName,
|
||||
onChanged: (s) {
|
||||
_settings.firstName = s;
|
||||
_updateSettings();
|
||||
},
|
||||
maxLength: srvConfig.accountInformationPolicy.maxFirstNameLength,
|
||||
maxLength: srvConfig!.accountInformationPolicy.maxFirstNameLength,
|
||||
checkInput: (s) =>
|
||||
s.length >= srvConfig.accountInformationPolicy.minFirstNameLength,
|
||||
s.length >= srvConfig!.accountInformationPolicy.minFirstNameLength,
|
||||
),
|
||||
|
||||
// Last name
|
||||
TextEditSettingsTile(
|
||||
title: tr("Last name"),
|
||||
title: tr("Last name")!,
|
||||
currValue: _settings.lastName,
|
||||
onChanged: (s) {
|
||||
_settings.lastName = s;
|
||||
_updateSettings();
|
||||
},
|
||||
maxLength: srvConfig.accountInformationPolicy.maxLastNameLength,
|
||||
maxLength: srvConfig!.accountInformationPolicy.maxLastNameLength,
|
||||
checkInput: (s) =>
|
||||
s.length >= srvConfig.accountInformationPolicy.minLastNameLength,
|
||||
s.length >= srvConfig!.accountInformationPolicy.minLastNameLength,
|
||||
),
|
||||
|
||||
// Emails settings
|
||||
@ -121,15 +121,15 @@ class _GeneralAccountSettingsScreenState
|
||||
List<MultiChoiceEntry> get _visibilityChoices => [
|
||||
MultiChoiceEntry(
|
||||
id: UserPageVisibility.PRIVATE,
|
||||
title: tr("Private"),
|
||||
title: tr("Private")!,
|
||||
subtitle: tr("Private, accessible only to your friends")),
|
||||
MultiChoiceEntry(
|
||||
id: UserPageVisibility.PUBLIC,
|
||||
title: tr("Public"),
|
||||
title: tr("Public")!,
|
||||
subtitle: tr("Public, accessible to all Comunic members")),
|
||||
MultiChoiceEntry(
|
||||
id: UserPageVisibility.OPEN,
|
||||
title: tr("Open"),
|
||||
title: tr("Open")!,
|
||||
subtitle:
|
||||
tr("Accessible to everyone, including non-Comunic users")),
|
||||
];
|
||||
@ -139,10 +139,10 @@ class _GeneralAccountSettingsScreenState
|
||||
return [
|
||||
// Page visibility
|
||||
MultiChoicesSettingsTile(
|
||||
title: tr("Page visibility"),
|
||||
title: tr("Page visibility")!,
|
||||
choices: _visibilityChoices,
|
||||
currentValue: _settings.pageVisibility,
|
||||
onChanged: (v) {
|
||||
onChanged: (dynamic v) {
|
||||
_settings.pageVisibility = v;
|
||||
_updateSettings();
|
||||
}),
|
||||
@ -191,7 +191,7 @@ class _GeneralAccountSettingsScreenState
|
||||
|
||||
// Personal website
|
||||
TextEditSettingsTile(
|
||||
title: tr("Personal website URL (optional)"),
|
||||
title: tr("Personal website URL (optional)")!,
|
||||
currValue: _settings.personalWebsite,
|
||||
onChanged: (v) {
|
||||
_settings.personalWebsite = v;
|
||||
@ -203,19 +203,19 @@ class _GeneralAccountSettingsScreenState
|
||||
|
||||
// Location
|
||||
TextEditSettingsTile(
|
||||
title: tr("Location (optional)"),
|
||||
title: tr("Location (optional)")!,
|
||||
currValue: _settings.location ?? "",
|
||||
onChanged: (v) {
|
||||
_settings.location = v;
|
||||
_updateSettings();
|
||||
},
|
||||
maxLength: srvConfig.accountInformationPolicy.maxLocationLength,
|
||||
maxLength: srvConfig!.accountInformationPolicy.maxLocationLength,
|
||||
allowEmptyValues: true,
|
||||
),
|
||||
|
||||
// Public notes
|
||||
TextEditSettingsTile(
|
||||
title: tr("Public note (optional)"),
|
||||
title: tr("Public note (optional)")!,
|
||||
currValue: _settings.publicNote,
|
||||
onChanged: (v) {
|
||||
_settings.publicNote = v;
|
||||
@ -235,7 +235,7 @@ class _GeneralAccountSettingsScreenState
|
||||
context: context,
|
||||
initialDirectory: _settings.virtualDirectory,
|
||||
type: VirtualDirectoryTargetType.USER,
|
||||
id: userID());
|
||||
id: userID()!);
|
||||
|
||||
if (dir == null) return;
|
||||
|
||||
@ -252,8 +252,8 @@ class _GeneralAccountSettingsScreenState
|
||||
await SettingsHelper.updateGeneralSettings(_settings);
|
||||
} catch (e, stack) {
|
||||
print("Error while updating settings! $e/n$stack");
|
||||
showSimpleSnack(context, tr("Could not update general settings!"));
|
||||
showSimpleSnack(context, tr("Could not update general settings!")!);
|
||||
}
|
||||
_key.currentState.refresh();
|
||||
_key.currentState!.refresh();
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,8 @@ class _NotificationsSettingsScreenState
|
||||
extends State<NotificationsSettingsScreen> {
|
||||
final key = GlobalKey<AsyncScreenWidgetState>();
|
||||
|
||||
NotificationsSettings _settings;
|
||||
PushNotificationsStatus _pushNotificationsStatus;
|
||||
late NotificationsSettings _settings;
|
||||
PushNotificationsStatus? _pushNotificationsStatus;
|
||||
|
||||
Future<void> _loadSettings() async {
|
||||
_settings = await SettingsHelper.getNotificationsSettings();
|
||||
@ -37,7 +37,7 @@ class _NotificationsSettingsScreenState
|
||||
key: key,
|
||||
onReload: _loadSettings,
|
||||
onBuild: _buildScreen,
|
||||
errorMessage: tr("Failed to load notifications settings!"),
|
||||
errorMessage: tr("Failed to load notifications settings!")!,
|
||||
);
|
||||
|
||||
Widget _buildScreen() => SettingsList(sections: [
|
||||
@ -81,7 +81,7 @@ class _NotificationsSettingsScreenState
|
||||
setState(() {});
|
||||
} catch (e, s) {
|
||||
logError(e, s);
|
||||
snack(context, tr("Failed to update settings!"));
|
||||
snack(context, tr("Failed to update settings!")!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,8 +12,8 @@ class SinglePostRoute extends StatelessWidget {
|
||||
final int postID;
|
||||
|
||||
const SinglePostRoute({
|
||||
Key key,
|
||||
@required this.postID,
|
||||
Key? key,
|
||||
required this.postID,
|
||||
}) : assert(postID != null),
|
||||
super(key: key);
|
||||
|
||||
@ -21,7 +21,7 @@ class SinglePostRoute extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(tr("Post")),
|
||||
title: Text(tr("Post")!),
|
||||
),
|
||||
body: _SinglePostRouteBody(postID: postID),
|
||||
);
|
||||
@ -32,8 +32,8 @@ class _SinglePostRouteBody extends StatefulWidget {
|
||||
final int postID;
|
||||
|
||||
const _SinglePostRouteBody({
|
||||
Key key,
|
||||
@required this.postID,
|
||||
Key? key,
|
||||
required this.postID,
|
||||
}) : assert(postID != null),
|
||||
super(key: key);
|
||||
|
||||
@ -42,7 +42,7 @@ class _SinglePostRouteBody extends StatefulWidget {
|
||||
}
|
||||
|
||||
class __SinglePostRouteBodyState extends State<_SinglePostRouteBody> {
|
||||
Future<PostsList> _getPost() async {
|
||||
Future<PostsList?> _getPost() async {
|
||||
try {
|
||||
return PostsList()..add(await PostsHelper().getSingle(widget.postID));
|
||||
} on Exception catch (e) {
|
||||
|
@ -40,7 +40,7 @@ class TourRouteState extends State<TourRoute> {
|
||||
|
||||
final Map<int, GlobalKey> pubKeys = Map();
|
||||
|
||||
User currUser;
|
||||
late User currUser;
|
||||
|
||||
int _defaultIndex = 0;
|
||||
|
||||
@ -57,7 +57,7 @@ class TourRouteState extends State<TourRoute> {
|
||||
areNotificationsConfigured = true;
|
||||
|
||||
// Attempt to automatically register to FCM
|
||||
else if (srvConfig.notificationsPolicy.hasFirebase) {
|
||||
else if (srvConfig!.notificationsPolicy.hasFirebase) {
|
||||
try {
|
||||
await PushNotificationsHelper.configure(
|
||||
context, PushNotificationsStatus.FIREBASE);
|
||||
@ -71,12 +71,12 @@ class TourRouteState extends State<TourRoute> {
|
||||
void rebuild() => setState(() {});
|
||||
|
||||
void setStateKeepCurrentIndex(BuildContext cxt) async {
|
||||
_defaultIndex = DefaultTabController.of(cxt).index;
|
||||
await _key.currentState.refresh();
|
||||
_defaultIndex = DefaultTabController.of(cxt)!.index;
|
||||
await _key.currentState!.refresh();
|
||||
}
|
||||
|
||||
List<Widget> get _list => (config().toursEntriesBuilder != null
|
||||
? config().toursEntriesBuilder(this)
|
||||
? config().toursEntriesBuilder!(this)
|
||||
: [
|
||||
FirstTourPane(),
|
||||
|
||||
@ -96,25 +96,25 @@ class TourRouteState extends State<TourRoute> {
|
||||
|
||||
PresentationPane(
|
||||
icon: Icons.group_add,
|
||||
title: tr("Friends"),
|
||||
title: tr("Friends")!,
|
||||
text:
|
||||
"${tr("You can search the people you know and ask them to become your friends!")}\n\n${tr("This will help you to reach them to exchange information!")}",
|
||||
),
|
||||
PresentationPane(
|
||||
icon: Icons.question_answer,
|
||||
title: tr("Conversations"),
|
||||
title: tr("Conversations")!,
|
||||
text:
|
||||
"${tr("With Comunic, you can have conversations with all your friends.")}\n\n${tr("It is also possible to make video calls!")}",
|
||||
),
|
||||
PresentationPane(
|
||||
icon: Icons.group,
|
||||
title: tr("Groups"),
|
||||
title: tr("Groups")!,
|
||||
text:
|
||||
"${tr("You can join groups where people share the same interests as you!")}\n\n${tr("It is also easy to create your own groups!")}",
|
||||
),
|
||||
PresentationPane(
|
||||
icon: Icons.lock,
|
||||
title: tr("Privacy"),
|
||||
title: tr("Privacy")!,
|
||||
text:
|
||||
"${tr("Your data is YOUR DATA. We will never use it or sell it.")}\n\n${tr("If you do not trust us, you can always check out our source code to verify it!")}",
|
||||
),
|
||||
@ -135,7 +135,7 @@ class TourRouteState extends State<TourRoute> {
|
||||
child: AsyncScreenWidget(
|
||||
key: _key,
|
||||
onReload: _init,
|
||||
errorMessage: tr("Failed to load tour!"),
|
||||
errorMessage: tr("Failed to load tour!")!,
|
||||
onBuild: () => DefaultTabController(
|
||||
initialIndex: _defaultIndex,
|
||||
length: _list.length,
|
||||
@ -150,22 +150,22 @@ class TourRouteState extends State<TourRoute> {
|
||||
}
|
||||
|
||||
class _RouteBody extends StatefulWidget {
|
||||
final List<Widget> panes;
|
||||
final List<Widget>? panes;
|
||||
|
||||
const _RouteBody({Key key, this.panes}) : super(key: key);
|
||||
const _RouteBody({Key? key, this.panes}) : super(key: key);
|
||||
|
||||
@override
|
||||
__RouteBodyState createState() => __RouteBodyState();
|
||||
}
|
||||
|
||||
class __RouteBodyState extends State<_RouteBody> {
|
||||
TabController _controller;
|
||||
TabController? _controller;
|
||||
|
||||
bool get _isLastPane => _controller.index >= widget.panes.length - 1;
|
||||
bool get _isLastPane => _controller!.index >= widget.panes!.length - 1;
|
||||
|
||||
PresentationPane get _currPane =>
|
||||
widget.panes[_controller.index] is PresentationPane
|
||||
? widget.panes[_controller.index]
|
||||
PresentationPane? get _currPane =>
|
||||
widget.panes![_controller!.index] is PresentationPane
|
||||
? widget.panes![_controller!.index] as PresentationPane?
|
||||
: null;
|
||||
|
||||
bool get _canGoNext => _currPane?.canGoNext ?? true;
|
||||
@ -184,7 +184,7 @@ class __RouteBodyState extends State<_RouteBody> {
|
||||
|
||||
void _updateController() {
|
||||
_controller = DefaultTabController.of(context);
|
||||
_controller.addListener(() => setState(() {}));
|
||||
_controller!.addListener(() => setState(() {}));
|
||||
}
|
||||
|
||||
@override
|
||||
@ -195,7 +195,7 @@ class __RouteBodyState extends State<_RouteBody> {
|
||||
Spacer(flex: 1),
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
children: widget.panes,
|
||||
children: widget.panes!,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
),
|
||||
flex: 10),
|
||||
@ -204,7 +204,7 @@ class __RouteBodyState extends State<_RouteBody> {
|
||||
Spacer(flex: 1),
|
||||
OutlinedButton(
|
||||
onPressed: _canGoNext ? _nextOrFinish : null,
|
||||
child: Text(!_isLastPane ? tr("Next") : tr("Let's go!")),
|
||||
child: Text(!_isLastPane ? tr("Next")! : tr("Let's go!")!),
|
||||
),
|
||||
Spacer(flex: 1),
|
||||
],
|
||||
@ -212,17 +212,17 @@ class __RouteBodyState extends State<_RouteBody> {
|
||||
);
|
||||
|
||||
void _nextOrFinish() async {
|
||||
if (_controller.indexIsChanging) return;
|
||||
if (_controller!.indexIsChanging) return;
|
||||
|
||||
if (!_isLastPane) {
|
||||
// Check if the next click has to be captured
|
||||
if (_currPane?.onTapNext != null) {
|
||||
if (!await _currPane.onTapNext(context)) return;
|
||||
if (!await _currPane!.onTapNext!(context)) return;
|
||||
}
|
||||
|
||||
_controller.animateTo(_controller.index + 1);
|
||||
_controller!.animateTo(_controller!.index + 1);
|
||||
} else {
|
||||
(await PreferencesHelper.getInstance())
|
||||
(await PreferencesHelper.getInstance())!
|
||||
.setBool(PreferencesKeyList.IS_TOUR_SEEN, true);
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import 'package:flutter/material.dart';
|
||||
class UpdateConversationRoute extends StatefulWidget {
|
||||
final int conversationID;
|
||||
|
||||
const UpdateConversationRoute({Key key, this.conversationID})
|
||||
const UpdateConversationRoute({Key? key, required this.conversationID})
|
||||
: assert(conversationID != null),
|
||||
super(key: key);
|
||||
|
||||
|
@ -13,8 +13,8 @@ class VideoPlayerRoute extends StatefulWidget {
|
||||
final String url;
|
||||
|
||||
const VideoPlayerRoute({
|
||||
Key key,
|
||||
@required this.url,
|
||||
Key? key,
|
||||
required this.url,
|
||||
}) : assert(url != null),
|
||||
super(key: key);
|
||||
|
||||
@ -23,16 +23,16 @@ class VideoPlayerRoute extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _VideoPlayerRouteState extends State<VideoPlayerRoute> {
|
||||
VideoPlayerController _videoPlayerController;
|
||||
ChewieController _chewieController;
|
||||
VideoPlayerController? _videoPlayerController;
|
||||
ChewieController? _chewieController;
|
||||
|
||||
Future<void> _initialize() async {
|
||||
_videoPlayerController = VideoPlayerController.network(widget.url);
|
||||
|
||||
await _videoPlayerController.initialize();
|
||||
await _videoPlayerController!.initialize();
|
||||
|
||||
_chewieController = ChewieController(
|
||||
videoPlayerController: _videoPlayerController,
|
||||
videoPlayerController: _videoPlayerController!,
|
||||
looping: false,
|
||||
allowFullScreen: true,
|
||||
allowMuting: true,
|
||||
@ -42,8 +42,8 @@ class _VideoPlayerRouteState extends State<VideoPlayerRoute> {
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
if (_videoPlayerController != null) _videoPlayerController.dispose();
|
||||
if (_chewieController != null) _chewieController.dispose();
|
||||
if (_videoPlayerController != null) _videoPlayerController!.dispose();
|
||||
if (_chewieController != null) _chewieController!.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@ -61,8 +61,8 @@ class _VideoPlayerRouteState extends State<VideoPlayerRoute> {
|
||||
Widget _buildBody() => AsyncScreenWidget(
|
||||
onReload: _initialize,
|
||||
onBuild: _showBody,
|
||||
errorMessage: tr("Failed to initialize video!"),
|
||||
errorMessage: tr("Failed to initialize video!")!,
|
||||
);
|
||||
|
||||
Widget _showBody() => Chewie(controller: _chewieController);
|
||||
Widget _showBody() => Chewie(controller: _chewieController!);
|
||||
}
|
||||
|
@ -32,12 +32,12 @@ class _WelcomeRouteState extends State<WelcomeRoute> {
|
||||
children: <Widget>[
|
||||
ListTile(
|
||||
leading: Icon(Icons.login, color: Colors.white),
|
||||
title: Text(tr("Login")),
|
||||
title: Text(tr("Login")!),
|
||||
onTap: _openLoginPage,
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.person_add_alt_1, color: Colors.white),
|
||||
title: Text(tr("Join the network")),
|
||||
title: Text(tr("Join the network")!),
|
||||
onTap: _openCreateAccountPage,
|
||||
)
|
||||
],
|
||||
|
Reference in New Issue
Block a user