mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-12-25 04:18:51 +00:00
Start to fix null safety migration errors
This commit is contained in:
parent
ab2c5da0da
commit
3a997cdc56
@ -8,16 +8,16 @@ import 'package:comunic/models/advanced_group_info.dart';
|
||||
///
|
||||
/// @author Pierre Hubert
|
||||
|
||||
AdvancedGroupInfo _forezGroup;
|
||||
AdvancedGroupInfo? _forezGroup;
|
||||
|
||||
class ForezGroupHelper {
|
||||
static Future<void> setId(int groupID) async {
|
||||
(await PreferencesHelper.getInstance())
|
||||
(await PreferencesHelper.getInstance())!
|
||||
.setInt(PreferencesKeyList.FOREZ_GROUP, groupID);
|
||||
}
|
||||
|
||||
static Future<int> getId() async {
|
||||
return (await PreferencesHelper.getInstance())
|
||||
static Future<int?> getId() async {
|
||||
return (await PreferencesHelper.getInstance())!
|
||||
.getInt(PreferencesKeyList.FOREZ_GROUP);
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ class ForezGroupHelper {
|
||||
_forezGroup = res.info;
|
||||
}
|
||||
|
||||
static AdvancedGroupInfo getGroup() => _forezGroup;
|
||||
static AdvancedGroupInfo? getGroup() => _forezGroup;
|
||||
}
|
||||
|
||||
AdvancedGroupInfo get forezGroup => ForezGroupHelper.getGroup();
|
||||
AdvancedGroupInfo? get forezGroup => ForezGroupHelper.getGroup();
|
||||
|
@ -11,10 +11,10 @@ import 'package:flutter/material.dart';
|
||||
|
||||
class ForezConfig extends Config {
|
||||
ForezConfig({
|
||||
@required String apiServerName,
|
||||
@required String apiServerUri,
|
||||
@required bool apiServerSecure,
|
||||
@required String clientName,
|
||||
required String apiServerName,
|
||||
required String apiServerUri,
|
||||
required bool apiServerSecure,
|
||||
required String clientName,
|
||||
}) : super(
|
||||
apiServerName: apiServerName,
|
||||
apiServerUri: apiServerUri,
|
||||
|
@ -11,7 +11,7 @@ import 'package:comunic/models/config.dart';
|
||||
/// Fix HTTPS issue
|
||||
class MyHttpOverride extends HttpOverrides {
|
||||
@override
|
||||
HttpClient createHttpClient(SecurityContext context) {
|
||||
HttpClient createHttpClient(SecurityContext? context) {
|
||||
return super.createHttpClient(context)
|
||||
..badCertificateCallback = (cert, host, port) {
|
||||
return host == "devweb.local"; // Forcefully trust local website
|
||||
|
@ -29,7 +29,7 @@ List<Widget> buildTour(TourRouteState state) {
|
||||
msgTwo: tr("Let's first join a Forez group!"),
|
||||
),
|
||||
JoinForezGroupPane(
|
||||
key: state.pubKeys[_JOIN_GROUP_KEY_ID],
|
||||
key: state.pubKeys[_JOIN_GROUP_KEY_ID] as GlobalKey<JoinGroupPaneBodyState>?,
|
||||
onUpdated: () => state.rebuild(),
|
||||
),
|
||||
FirstTourPane(
|
||||
@ -51,7 +51,7 @@ List<Widget> buildTour(TourRouteState state) {
|
||||
// Forez specific features
|
||||
PresentationPane(
|
||||
icon: Icons.calendar_today,
|
||||
title: tr("Presence in Forez"),
|
||||
title: tr("Presence in Forez")!,
|
||||
text: tr(
|
||||
"Easily specify the days you are in Forez plain, so that everyone can know it!"),
|
||||
actionTitle: tr("Do it now!"),
|
||||
@ -62,7 +62,7 @@ List<Widget> buildTour(TourRouteState state) {
|
||||
// Chat pane
|
||||
PresentationPane(
|
||||
icon: Icons.question_answer,
|
||||
title: tr("Conversations"),
|
||||
title: tr("Conversations")!,
|
||||
text: tr(
|
||||
"#Forez now integrates the conversation system of Comunic, so you have access both to public and private conversations!"),
|
||||
),
|
||||
|
@ -16,17 +16,17 @@ import 'package:flutter/material.dart';
|
||||
|
||||
class JoinForezGroupPane extends PresentationPane {
|
||||
JoinForezGroupPane({
|
||||
@required Function() onUpdated,
|
||||
@required GlobalKey<JoinGroupPaneBodyState> key,
|
||||
required Function() onUpdated,
|
||||
required GlobalKey<JoinGroupPaneBodyState>? key,
|
||||
}) : super(
|
||||
icon: Icons.login,
|
||||
title: tr("Join a Forez group"),
|
||||
title: tr("Join a Forez group")!,
|
||||
child: (c) => _JoinGroupPaneBody(
|
||||
key: key,
|
||||
onUpdated: onUpdated,
|
||||
),
|
||||
canGoNext: key?.currentState?.canGoNext ?? false,
|
||||
onTapNext: (c) => key.currentState.validateChoice(),
|
||||
onTapNext: (c) => key!.currentState!.validateChoice(),
|
||||
);
|
||||
}
|
||||
|
||||
@ -34,8 +34,8 @@ class _JoinGroupPaneBody extends StatefulWidget {
|
||||
final Function() onUpdated;
|
||||
|
||||
const _JoinGroupPaneBody({
|
||||
Key key,
|
||||
@required this.onUpdated,
|
||||
Key? key,
|
||||
required this.onUpdated,
|
||||
}) : assert(onUpdated != null),
|
||||
super(key: key);
|
||||
|
||||
@ -46,10 +46,10 @@ class _JoinGroupPaneBody extends StatefulWidget {
|
||||
class JoinGroupPaneBodyState extends State<_JoinGroupPaneBody> {
|
||||
final _key = GlobalKey<AsyncScreenWidgetState>();
|
||||
|
||||
List<Group> _groups;
|
||||
int _currChoice;
|
||||
late List<Group> _groups;
|
||||
int? _currChoice;
|
||||
|
||||
bool get canGoNext => _currChoice != null && _currChoice > 0;
|
||||
bool get canGoNext => _currChoice != null && _currChoice! > 0;
|
||||
|
||||
Group get _currGroup => _groups.firstWhere((e) => e.id == _currChoice);
|
||||
|
||||
@ -65,17 +65,17 @@ class JoinGroupPaneBodyState extends State<_JoinGroupPaneBody> {
|
||||
key: _key,
|
||||
onReload: _load,
|
||||
onBuild: onBuild,
|
||||
errorMessage: tr("Failed to load the list of Forez groups!"));
|
||||
errorMessage: tr("Failed to load the list of Forez groups!")!);
|
||||
|
||||
Widget onBuild() => ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: 300),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(tr("Please choose now the Forez group you want to join...")),
|
||||
Text(tr("Please choose now the Forez group you want to join...")!),
|
||||
]..addAll(_groups.map((e) => RadioListTile(
|
||||
value: e.id,
|
||||
groupValue: _currChoice,
|
||||
onChanged: (v) => setState(() => _currChoice = e.id),
|
||||
onChanged: (dynamic v) => setState(() => _currChoice = e.id),
|
||||
title: Text(e.name),
|
||||
subtitle: Text(e.membershipText),
|
||||
))),
|
||||
@ -112,7 +112,7 @@ class JoinGroupPaneBodyState extends State<_JoinGroupPaneBody> {
|
||||
await alert(context,
|
||||
"${tr("You can not access this group yet, please wait for a member of the group to accept your request.")}\n${tr("Hopefully this will not be too long.")}\n${tr("Please check back soon!")}");
|
||||
|
||||
_key.currentState.refresh();
|
||||
_key.currentState!.refresh();
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -121,8 +121,8 @@ class JoinGroupPaneBodyState extends State<_JoinGroupPaneBody> {
|
||||
return true;
|
||||
} catch (e, s) {
|
||||
logError(e, s);
|
||||
snack(context, tr("Failed to register to group!"));
|
||||
_key.currentState.refresh();
|
||||
snack(context, tr("Failed to register to group!")!);
|
||||
_key.currentState!.refresh();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,8 @@ class ForezMemberProfileRoute extends StatefulWidget {
|
||||
final int userID;
|
||||
|
||||
const ForezMemberProfileRoute({
|
||||
Key key,
|
||||
@required this.userID,
|
||||
Key? key,
|
||||
required this.userID,
|
||||
}) : assert(userID != null),
|
||||
super(key: key);
|
||||
|
||||
@ -39,13 +39,13 @@ class _ForezMemberProfileRouteState extends State<ForezMemberProfileRoute> {
|
||||
|
||||
final _key = GlobalKey<AsyncScreenWidgetState>();
|
||||
|
||||
AdvancedUserInfo _user;
|
||||
PresenceSet _presence;
|
||||
late AdvancedUserInfo _user;
|
||||
late PresenceSet _presence;
|
||||
|
||||
Future<void> _load() async {
|
||||
_user = await ForezGroupsHelper.getMemberInfo(forezGroup.id, widget.userID);
|
||||
_user = await ForezGroupsHelper.getMemberInfo(forezGroup!.id, widget.userID);
|
||||
_presence =
|
||||
await ForezPresenceHelper.getForUser(forezGroup.id, widget.userID);
|
||||
await ForezPresenceHelper.getForUser(forezGroup!.id, widget.userID);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -56,25 +56,25 @@ class _ForezMemberProfileRouteState extends State<ForezMemberProfileRoute> {
|
||||
loadingWidget: _buildLoading(),
|
||||
errorWidget: _buildError(),
|
||||
errorMessage: tr(
|
||||
"Failed to load user information, maybe it is not a Forez member yet?"));
|
||||
"Failed to load user information, maybe it is not a Forez member yet?")!);
|
||||
|
||||
Widget _buildLoading() => Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(tr("Loading...")),
|
||||
title: Text(tr("Loading...")!),
|
||||
),
|
||||
body: buildCenteredProgressBar(),
|
||||
);
|
||||
|
||||
Widget _buildError() => Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(tr("Error")),
|
||||
title: Text(tr("Error")!),
|
||||
),
|
||||
body: buildErrorCard(
|
||||
tr("Failed to load user information, maybe it is not a Forez member yet?"),
|
||||
actions: [
|
||||
MaterialButton(
|
||||
onPressed: () => _key.currentState.refresh(),
|
||||
child: Text(tr("Try again")),
|
||||
onPressed: () => _key.currentState!.refresh(),
|
||||
child: Text(tr("Try again")!),
|
||||
textColor: Colors.white,
|
||||
)
|
||||
]),
|
||||
@ -101,7 +101,7 @@ class _ForezMemberProfileRouteState extends State<ForezMemberProfileRoute> {
|
||||
? Container()
|
||||
: CachedNetworkImage(
|
||||
fit: BoxFit.cover,
|
||||
imageUrl: _user.accountImageURL,
|
||||
imageUrl: _user.accountImageURL!,
|
||||
height: _appBarHeight,
|
||||
),
|
||||
// This gradient ensures that the toolbar icons are distinct
|
||||
@ -135,7 +135,7 @@ class _ForezMemberProfileRouteState extends State<ForezMemberProfileRoute> {
|
||||
: ListTile(
|
||||
leading: Icon(Icons.note),
|
||||
title: TextWidget(content: DisplayedString(_user.publicNote)),
|
||||
subtitle: Text(tr("Note")),
|
||||
subtitle: Text(tr("Note")!),
|
||||
),
|
||||
|
||||
// Email address
|
||||
@ -143,9 +143,9 @@ class _ForezMemberProfileRouteState extends State<ForezMemberProfileRoute> {
|
||||
? Container()
|
||||
: ListTile(
|
||||
leading: Icon(Icons.email),
|
||||
title: Text(_user.emailAddress),
|
||||
subtitle: Text(tr("Email address")),
|
||||
trailing: CopyIcon(_user.emailAddress),
|
||||
title: Text(_user.emailAddress!),
|
||||
subtitle: Text(tr("Email address")!),
|
||||
trailing: CopyIcon(_user.emailAddress!),
|
||||
),
|
||||
|
||||
// Location
|
||||
@ -153,9 +153,9 @@ class _ForezMemberProfileRouteState extends State<ForezMemberProfileRoute> {
|
||||
? Container()
|
||||
: ListTile(
|
||||
leading: Icon(Icons.location_on),
|
||||
title: Text(_user.location),
|
||||
subtitle: Text(tr("Location")),
|
||||
trailing: CopyIcon(_user.location),
|
||||
title: Text(_user.location!),
|
||||
subtitle: Text(tr("Location")!),
|
||||
trailing: CopyIcon(_user.location!),
|
||||
),
|
||||
|
||||
// Website
|
||||
@ -164,7 +164,7 @@ class _ForezMemberProfileRouteState extends State<ForezMemberProfileRoute> {
|
||||
: ListTile(
|
||||
leading: Icon(Icons.link),
|
||||
title: Text(_user.personalWebsite),
|
||||
subtitle: Text(tr("Website")),
|
||||
subtitle: Text(tr("Website")!),
|
||||
trailing: IconButton(
|
||||
icon: Icon(Icons.open_in_new),
|
||||
onPressed: () => launch(_user.personalWebsite),
|
||||
@ -174,10 +174,10 @@ class _ForezMemberProfileRouteState extends State<ForezMemberProfileRoute> {
|
||||
Divider(),
|
||||
ListTile(
|
||||
leading: Icon(Icons.calendar_today),
|
||||
title: Text(tr("Presence in Forez")),
|
||||
title: Text(tr("Presence in Forez")!),
|
||||
subtitle: Text(_presence.containsDate(DateTime.now())
|
||||
? tr("Present today")
|
||||
: tr("Absent")),
|
||||
? tr("Present today")!
|
||||
: tr("Absent")!),
|
||||
),
|
||||
PresenceCalendarWidget(presenceSet: _presence),
|
||||
Divider(),
|
||||
|
@ -21,7 +21,7 @@ import 'package:flutter/material.dart';
|
||||
/// @author Pierre Hubert
|
||||
|
||||
class ForezRoute extends StatefulWidget implements MainRoute {
|
||||
const ForezRoute({Key key}) : super(key: key);
|
||||
const ForezRoute({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _MainRouteState();
|
||||
@ -40,7 +40,7 @@ class _MainRouteState extends MainController {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (forezGroup == null) return Text(tr("Missing Forez group!"));
|
||||
if (forezGroup == null) return Text(tr("Missing Forez group!")!);
|
||||
|
||||
return StatusWidget(
|
||||
child: (c) => SafeArea(
|
||||
@ -67,11 +67,11 @@ class _MainRouteState extends MainController {
|
||||
@override
|
||||
void openConversation(Conversation conv, {fullScreen: false}) {
|
||||
// Forcefully open conversations in a "normal" way (do not display groups)
|
||||
openConversationById(conv.id, fullScreen: fullScreen);
|
||||
openConversationById(conv.id!, fullScreen: fullScreen);
|
||||
}
|
||||
|
||||
@override
|
||||
void openGroup(int groupID, {int conversationID}) => _unsupportedFeature();
|
||||
void openGroup(int groupID, {int? conversationID}) => _unsupportedFeature();
|
||||
|
||||
@override
|
||||
void openUserPage(int userID) => pushPage(PageInfo(
|
||||
@ -92,7 +92,7 @@ class _MainRouteState extends MainController {
|
||||
enum _PopupMenuItems { ACTION_SETTINGS, ACTION_SIGN_OUT }
|
||||
|
||||
class ForezRouteBody extends StatefulWidget {
|
||||
ForezRouteBody({Key key}) : super(key: key);
|
||||
ForezRouteBody({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ForezRouteBodyState createState() => _ForezRouteBodyState();
|
||||
@ -112,7 +112,7 @@ class _ForezRouteBodyState extends SafeState<ForezRouteBody> {
|
||||
length: _tabs.length,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(forezGroup.name),
|
||||
title: Text(forezGroup!.name),
|
||||
actions: <Widget>[_buildPopupMenuButton()],
|
||||
bottom: TabBar(tabs: _tabs),
|
||||
),
|
||||
@ -129,11 +129,11 @@ class _ForezRouteBodyState extends SafeState<ForezRouteBody> {
|
||||
Widget _buildPopupMenuButton() => PopupMenuButton<_PopupMenuItems>(
|
||||
itemBuilder: (c) => [
|
||||
PopupMenuItem(
|
||||
child: Text(tr("Settings")),
|
||||
child: Text(tr("Settings")!),
|
||||
value: _PopupMenuItems.ACTION_SETTINGS,
|
||||
),
|
||||
PopupMenuItem(
|
||||
child: Text(tr("Sign out")),
|
||||
child: Text(tr("Sign out")!),
|
||||
value: _PopupMenuItems.ACTION_SIGN_OUT,
|
||||
),
|
||||
],
|
||||
@ -143,10 +143,10 @@ class _ForezRouteBodyState extends SafeState<ForezRouteBody> {
|
||||
void _onMenuSelection(_PopupMenuItems value) {
|
||||
switch (value) {
|
||||
case _PopupMenuItems.ACTION_SETTINGS:
|
||||
MainController.of(context).openSettings();
|
||||
MainController.of(context)!.openSettings();
|
||||
break;
|
||||
case _PopupMenuItems.ACTION_SIGN_OUT:
|
||||
MainController.of(context).requestLogout();
|
||||
MainController.of(context)!.requestLogout();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -155,29 +155,29 @@ class _ForezRouteBodyState extends SafeState<ForezRouteBody> {
|
||||
// Posts tab
|
||||
_Tab(
|
||||
icon: Icons.auto_stories,
|
||||
title: tr("Posts"),
|
||||
widget: () => GroupPostsSection(group: forezGroup),
|
||||
title: tr("Posts")!,
|
||||
widget: () => GroupPostsSection(group: forezGroup!),
|
||||
),
|
||||
|
||||
// Presence tab
|
||||
_Tab(
|
||||
icon: Icons.calendar_today,
|
||||
title: tr("Presence"),
|
||||
widget: () => ForezPresenceSection(groupID: forezGroup.id),
|
||||
title: tr("Presence")!,
|
||||
widget: () => ForezPresenceSection(groupID: forezGroup!.id),
|
||||
),
|
||||
|
||||
// Conversations tab
|
||||
_Tab(
|
||||
icon: Icons.question_answer,
|
||||
title: tr("Conversations"),
|
||||
title: tr("Conversations")!,
|
||||
widget: () => ConversationsListScreen(),
|
||||
isUnread: (c) => StatusWidgetState.of(c).unreadConversations > 0,
|
||||
isUnread: (c) => StatusWidgetState.of(c)!.unreadConversations! > 0,
|
||||
),
|
||||
|
||||
// Directory tab
|
||||
_Tab(
|
||||
icon: Icons.import_contacts,
|
||||
title: tr("Directory"),
|
||||
title: tr("Directory")!,
|
||||
widget: () => ForezDirectoryScreen(),
|
||||
),
|
||||
];
|
||||
@ -203,12 +203,12 @@ class _Tab {
|
||||
final IconData icon;
|
||||
final String title;
|
||||
final Widget Function() widget;
|
||||
final bool Function(BuildContext) isUnread;
|
||||
final bool Function(BuildContext)? isUnread;
|
||||
|
||||
const _Tab({
|
||||
@required this.icon,
|
||||
@required this.title,
|
||||
@required this.widget,
|
||||
required this.icon,
|
||||
required this.title,
|
||||
required this.widget,
|
||||
this.isUnread,
|
||||
}) : assert(icon != null),
|
||||
assert(title != null),
|
||||
|
@ -7,18 +7,18 @@ import 'package:flutter/material.dart';
|
||||
///
|
||||
/// @author Pierre Hubert
|
||||
|
||||
Future<User> searchUser(BuildContext context, UsersList users) async {
|
||||
return await showSearch<User>(
|
||||
Future<User?> searchUser(BuildContext context, UsersList users) async {
|
||||
return await showSearch<User?>(
|
||||
context: context, delegate: _SearchDelegate(users));
|
||||
}
|
||||
|
||||
class _SearchDelegate extends SearchDelegate<User> {
|
||||
class _SearchDelegate extends SearchDelegate<User?> {
|
||||
final UsersList _usersList;
|
||||
|
||||
_SearchDelegate(this._usersList) : assert(_usersList != null);
|
||||
|
||||
@override
|
||||
List<Widget> buildActions(BuildContext context) => null;
|
||||
List<Widget>? buildActions(BuildContext context) => null;
|
||||
|
||||
@override
|
||||
Widget buildLeading(BuildContext context) => IconButton(
|
||||
@ -28,7 +28,7 @@ class _SearchDelegate extends SearchDelegate<User> {
|
||||
|
||||
@override
|
||||
Widget buildSuggestions(BuildContext context) {
|
||||
final list = _usersList
|
||||
final List<User> list = _usersList
|
||||
.where((element) =>
|
||||
element.fullName.toLowerCase().contains(query.toLowerCase()))
|
||||
.toList();
|
||||
|
@ -35,11 +35,11 @@ class ForezDirectoryScreen extends StatefulWidget {
|
||||
class _ForezDirectoryScreenState extends State<ForezDirectoryScreen> {
|
||||
final _key = GlobalKey<AsyncScreenWidgetState>();
|
||||
|
||||
UsersList _users;
|
||||
GroupMembersList _members;
|
||||
late UsersList _users;
|
||||
late GroupMembersList _members;
|
||||
|
||||
Future<void> _load() async {
|
||||
_members = await GroupsHelper.getMembersList(forezGroup.id);
|
||||
_members = await GroupsHelper.getMembersList(forezGroup!.id);
|
||||
_users = await UsersHelper().getListWithThrow(_members.usersID);
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ class _ForezDirectoryScreenState extends State<ForezDirectoryScreen> {
|
||||
AsyncScreenWidget(
|
||||
onReload: _load,
|
||||
onBuild: onBuild,
|
||||
errorMessage: tr("Failed to load members list!"),
|
||||
errorMessage: tr("Failed to load members list!")!,
|
||||
key: _key,
|
||||
),
|
||||
Positioned(
|
||||
@ -88,13 +88,13 @@ class _ForezDirectoryScreenState extends State<ForezDirectoryScreen> {
|
||||
"Do you really want to cancel the invitation sent to %u%?",
|
||||
args: {"u": user.fullName}))) return;
|
||||
|
||||
await GroupsHelper.cancelInvitation(forezGroup.id, user.id);
|
||||
_key.currentState.refresh();
|
||||
await GroupsHelper.cancelInvitation(forezGroup!.id, user.id);
|
||||
_key.currentState!.refresh();
|
||||
break;
|
||||
|
||||
case _PopupMenuActions.ACCEPT_REQUEST:
|
||||
await GroupsHelper.respondRequest(forezGroup.id, user.id, true);
|
||||
_key.currentState.refresh();
|
||||
await GroupsHelper.respondRequest(forezGroup!.id, user.id, true);
|
||||
_key.currentState!.refresh();
|
||||
break;
|
||||
|
||||
case _PopupMenuActions.REJECT_REQUEST:
|
||||
@ -104,13 +104,13 @@ class _ForezDirectoryScreenState extends State<ForezDirectoryScreen> {
|
||||
"Do you really want to reject the request of %u% to join the Forez group?",
|
||||
args: {"u": user.fullName}))) return;
|
||||
|
||||
await GroupsHelper.respondRequest(forezGroup.id, user.id, false);
|
||||
_key.currentState.refresh();
|
||||
await GroupsHelper.respondRequest(forezGroup!.id, user.id, false);
|
||||
_key.currentState!.refresh();
|
||||
break;
|
||||
}
|
||||
} catch (e, s) {
|
||||
logError(e, s);
|
||||
snack(context, tr("Error while processing action!"));
|
||||
snack(context, tr("Error while processing action!")!);
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,7 +125,7 @@ class _ForezDirectoryScreenState extends State<ForezDirectoryScreen> {
|
||||
}
|
||||
|
||||
void _openUserProfile(User user) =>
|
||||
MainController.of(context).openUserPage(user.id);
|
||||
MainController.of(context)!.openUserPage(user.id!);
|
||||
}
|
||||
|
||||
class _ForezMemberTile extends StatelessWidget {
|
||||
@ -135,11 +135,11 @@ class _ForezMemberTile extends StatelessWidget {
|
||||
final Function(User) onTap;
|
||||
|
||||
const _ForezMemberTile({
|
||||
Key key,
|
||||
@required this.user,
|
||||
@required this.member,
|
||||
@required this.selectedAction,
|
||||
@required this.onTap,
|
||||
Key? key,
|
||||
required this.user,
|
||||
required this.member,
|
||||
required this.selectedAction,
|
||||
required this.onTap,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@ -147,7 +147,7 @@ class _ForezMemberTile extends StatelessWidget {
|
||||
leading: AccountImageWidget(user: user),
|
||||
title: Text(user.fullName),
|
||||
subtitle: Text(member.membershipText),
|
||||
trailing: !member.isAtLeastMember && forezGroup.isAtLeastModerator
|
||||
trailing: !member.isAtLeastMember && forezGroup!.isAtLeastModerator
|
||||
? (member.isInvited
|
||||
? _buildInvitedButton()
|
||||
: _buildRequestedButton())
|
||||
@ -155,7 +155,7 @@ class _ForezMemberTile extends StatelessWidget {
|
||||
onTap: member.isAtLeastMember ? () => onTap(user) : null,
|
||||
);
|
||||
|
||||
Widget _buildConversationButton() => user.id == userID()
|
||||
Widget? _buildConversationButton() => user.id == userID()
|
||||
? null
|
||||
: IconButton(
|
||||
icon: Icon(Icons.message),
|
||||
@ -201,12 +201,12 @@ class _MembershipButton extends StatelessWidget {
|
||||
final IconData icon;
|
||||
|
||||
const _MembershipButton({
|
||||
Key key,
|
||||
@required this.user,
|
||||
@required this.action,
|
||||
@required this.onTap,
|
||||
@required this.color,
|
||||
@required this.icon,
|
||||
Key? key,
|
||||
required this.user,
|
||||
required this.action,
|
||||
required this.onTap,
|
||||
required this.color,
|
||||
required this.icon,
|
||||
}) : assert(user != null),
|
||||
assert(action != null),
|
||||
assert(onTap != null),
|
||||
|
@ -26,14 +26,14 @@ enum CreateAccountResult {
|
||||
|
||||
class AccountHelper {
|
||||
// Current user ID
|
||||
static int _currentUserID = -1;
|
||||
static int? _currentUserID = -1;
|
||||
|
||||
/// Checkout whether current user is signed in or not
|
||||
///
|
||||
/// Warning : This method MUST BE CALLED AT LEAST ONCE AFTER APP START !!!
|
||||
Future<bool> signedIn() async {
|
||||
bool signedIn =
|
||||
(await PreferencesHelper.getInstance()).getLoginToken() != null;
|
||||
(await PreferencesHelper.getInstance())!.getLoginToken() != null;
|
||||
|
||||
// Load current user ID for later use
|
||||
if (signedIn && _currentUserID == -1) await _loadCurrentUserID();
|
||||
@ -56,8 +56,8 @@ class AccountHelper {
|
||||
else if (response.code != 200) return AuthResult.NETWORK_ERROR;
|
||||
|
||||
// Save login token
|
||||
await (await PreferencesHelper.getInstance())
|
||||
.setLoginToken(response.getObject()["token"]);
|
||||
await (await PreferencesHelper.getInstance())!
|
||||
.setLoginToken(response.getObject()!["token"]);
|
||||
|
||||
// Get current user ID
|
||||
final userID = await _downloadCurrentUserID();
|
||||
@ -67,7 +67,7 @@ class AccountHelper {
|
||||
}
|
||||
|
||||
// Save current user ID
|
||||
final preferences = await PreferencesHelper.getInstance();
|
||||
final preferences = await (PreferencesHelper.getInstance());
|
||||
await preferences.setInt(PreferencesKeyList.USER_ID, userID);
|
||||
_currentUserID = userID;
|
||||
|
||||
@ -130,27 +130,27 @@ class AccountHelper {
|
||||
.getObject()["exists"];
|
||||
|
||||
/// Get current user email address
|
||||
static Future<String> getCurrentAccountEmailAddress() async =>
|
||||
static Future<String?> getCurrentAccountEmailAddress() async =>
|
||||
(await APIRequest.withLogin("account/mail")
|
||||
.execWithThrowGetObject())["mail"];
|
||||
.execWithThrowGetObject())!["mail"];
|
||||
|
||||
/// Check out whether security questions have been set for an account or not
|
||||
///
|
||||
/// Throws in case of failure
|
||||
static Future<bool> hasSecurityQuestions(String email) async =>
|
||||
static Future<bool?> hasSecurityQuestions(String email) async =>
|
||||
(await APIRequest.withoutLogin("account/has_security_questions")
|
||||
.addString("email", email)
|
||||
.execWithThrow())
|
||||
.getObject()["defined"];
|
||||
.getObject()!["defined"];
|
||||
|
||||
/// Get the security questions of the user
|
||||
///
|
||||
/// Throws in case of failure
|
||||
static Future<List<String>> getSecurityQuestions(String email) async =>
|
||||
static Future<List<String>?> getSecurityQuestions(String? email) async =>
|
||||
((await APIRequest.withoutLogin("account/get_security_questions")
|
||||
.addString("email", email)
|
||||
.execWithThrow())
|
||||
.getObject()["questions"])
|
||||
.getObject()!["questions"])
|
||||
.cast<String>();
|
||||
|
||||
/// Validate given security answers
|
||||
@ -158,14 +158,14 @@ class AccountHelper {
|
||||
/// Throws an [Exception] in case of failure
|
||||
///
|
||||
/// Returns a password reset token in case of success
|
||||
static Future<String> checkAnswers(
|
||||
String email, List<String> answers) async =>
|
||||
static Future<String?> checkAnswers(
|
||||
String? email, List<String> answers) async =>
|
||||
(await APIRequest.withoutLogin("account/check_security_answers")
|
||||
.addString("email", email)
|
||||
.addString("answers",
|
||||
answers.map((f) => Uri.encodeComponent(f)).join("&"))
|
||||
.execWithThrow())
|
||||
.getObject()["reset_token"];
|
||||
.getObject()!["reset_token"];
|
||||
|
||||
/// Check a password reset token
|
||||
///
|
||||
@ -195,25 +195,26 @@ class AccountHelper {
|
||||
.execWithThrow();
|
||||
|
||||
/// Get current user ID from the server
|
||||
Future<int> _downloadCurrentUserID() async {
|
||||
Future<int?> _downloadCurrentUserID() async {
|
||||
final response = await APIRequest.withLogin("account/id").exec();
|
||||
|
||||
if (response.code != 200) return null;
|
||||
|
||||
return response.getObject()["userID"];
|
||||
return response.getObject()!["userID"];
|
||||
}
|
||||
|
||||
/// Get the ID of the currently signed in user
|
||||
Future<void> _loadCurrentUserID() async {
|
||||
final preferences = await PreferencesHelper.getInstance();
|
||||
final preferences =
|
||||
await PreferencesHelper.getInstance();
|
||||
_currentUserID = preferences.getInt(PreferencesKeyList.USER_ID);
|
||||
}
|
||||
|
||||
/// Check if current user ID is loaded or not
|
||||
static bool get isUserIDLoaded => _currentUserID > 0;
|
||||
static bool get isUserIDLoaded => _currentUserID! > 0;
|
||||
|
||||
/// Get the ID of the currently signed in user
|
||||
static int getCurrentUserID() {
|
||||
static int? getCurrentUserID() {
|
||||
if (_currentUserID == -1) throw "Current user ID has not been loaded yet!";
|
||||
return _currentUserID;
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ class APIHelper {
|
||||
|
||||
//Add user token (if required)
|
||||
if (request.needLogin) {
|
||||
final token = (await PreferencesHelper.getInstance()).getLoginToken();
|
||||
final token = (await PreferencesHelper.getInstance())!.getLoginToken();
|
||||
|
||||
if (token == null) {
|
||||
EventsHelper.emit(InvalidLoginTokensEvent());
|
||||
@ -41,13 +41,13 @@ class APIHelper {
|
||||
else
|
||||
url = Uri.https(config().apiServerName, path);
|
||||
|
||||
final data = FormData.fromMap(request.args);
|
||||
final data = FormData.fromMap(request.args!);
|
||||
|
||||
// Process files (if required)
|
||||
if (multipart) {
|
||||
// Process filesystem files
|
||||
for (final key in request.files.keys) {
|
||||
var v = request.files[key];
|
||||
var v = request.files[key]!;
|
||||
data.files.add(MapEntry(
|
||||
key,
|
||||
await MultipartFile.fromFile(v.path,
|
||||
@ -56,11 +56,11 @@ class APIHelper {
|
||||
|
||||
// Process in-memory files
|
||||
for (final key in request.bytesFiles.keys) {
|
||||
var v = request.bytesFiles[key];
|
||||
var v = request.bytesFiles[key]!;
|
||||
data.files.add(MapEntry(
|
||||
key,
|
||||
MultipartFile.fromBytes(
|
||||
v.bytes,
|
||||
v.bytes!,
|
||||
filename: v.filename.split("/").last,
|
||||
contentType: v.type,
|
||||
)));
|
||||
@ -85,9 +85,9 @@ class APIHelper {
|
||||
EventsHelper.emit(InvalidLoginTokensEvent());
|
||||
|
||||
if (response.statusCode != HttpStatus.ok)
|
||||
return APIResponse(response.statusCode, response.data);
|
||||
return APIResponse(response.statusCode!, response.data);
|
||||
|
||||
return APIResponse(response.statusCode, response.data);
|
||||
return APIResponse(response.statusCode!, response.data);
|
||||
} catch (e, stack) {
|
||||
print(e.toString());
|
||||
print("Could not execute a request!");
|
||||
|
@ -39,12 +39,12 @@ class CallsHelper {
|
||||
.cast<CallMember>());
|
||||
|
||||
/// Request an offer to access another peer's stream
|
||||
static Future<void> requestOffer(int callID, int peerID) async =>
|
||||
static Future<void> requestOffer(int callID, int? peerID) async =>
|
||||
await ws("calls/request_offer", {"callID": callID, "peerID": peerID});
|
||||
|
||||
/// Send a Session Description message to the server
|
||||
static Future<void> sendSessionDescription(
|
||||
int callID, int peerID, RTCSessionDescription sdp) async =>
|
||||
int callID, int? peerID, RTCSessionDescription sdp) async =>
|
||||
await ws("calls/signal", {
|
||||
"callID": callID,
|
||||
"peerID": peerID,
|
||||
@ -54,7 +54,7 @@ class CallsHelper {
|
||||
|
||||
/// Send an IceCandidate
|
||||
static Future<void> sendIceCandidate(
|
||||
int callID, int peerID, RTCIceCandidate candidate) async =>
|
||||
int callID, int? peerID, RTCIceCandidate candidate) async =>
|
||||
await ws("calls/signal", {
|
||||
"callID": callID,
|
||||
"peerID": peerID,
|
||||
|
@ -27,7 +27,7 @@ class CommentsHelper {
|
||||
}
|
||||
|
||||
/// Get a single comment from the server, specified by its [id]
|
||||
Future<Comment> getSingle(int id) async {
|
||||
Future<Comment?> getSingle(int id) async {
|
||||
final response = await APIRequest(
|
||||
uri: "comments/get_single",
|
||||
needLogin: true,
|
||||
@ -39,7 +39,7 @@ class CommentsHelper {
|
||||
}
|
||||
|
||||
/// Update comment content
|
||||
Future<bool> updateContent(int id, String newContent) async {
|
||||
Future<bool> updateContent(int id, String? newContent) async {
|
||||
return (await APIRequest(uri: "comments/edit", needLogin: true, args: {
|
||||
"commentID": id.toString(),
|
||||
"content": newContent,
|
||||
|
@ -21,7 +21,6 @@ import 'package:comunic/utils/account_utils.dart';
|
||||
import 'package:comunic/utils/color_utils.dart';
|
||||
import 'package:comunic/utils/dart_color.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
/// Conversation helper
|
||||
///
|
||||
@ -47,13 +46,13 @@ class ConversationsHelper {
|
||||
.addBool("canEveryoneAddMembers", settings.canEveryoneAddMembers)
|
||||
.execWithThrow();
|
||||
|
||||
return response.getObject()["conversationID"];
|
||||
return response.getObject()!["conversationID"];
|
||||
}
|
||||
|
||||
/// Add a member to a conversation.
|
||||
///
|
||||
/// Throws in case of failure
|
||||
static Future<void> addMember(int convID, int userID) async =>
|
||||
static Future<void> addMember(int? convID, int? userID) async =>
|
||||
await APIRequest.withLogin("conversations/addMember")
|
||||
.addInt("convID", convID)
|
||||
.addInt("userID", userID)
|
||||
@ -62,7 +61,7 @@ class ConversationsHelper {
|
||||
/// Remove a member from a conversation.
|
||||
///
|
||||
/// Throws in case of failure
|
||||
static Future<void> removeMember(int convID, int userID) async =>
|
||||
static Future<void> removeMember(int? convID, int? userID) async =>
|
||||
await APIRequest.withLogin("conversations/removeMember")
|
||||
.addInt("convID", convID)
|
||||
.addInt("userID", userID)
|
||||
@ -71,7 +70,7 @@ class ConversationsHelper {
|
||||
/// Update admin status of a user in a conversation
|
||||
///
|
||||
/// Throws in case of failure
|
||||
static Future<void> setAdmin(int/*!*/ convID, int/*!*/ userID, bool admin) async =>
|
||||
static Future<void> setAdmin(int convID, int userID, bool admin) async =>
|
||||
await APIRequest.withLogin("conversations/setAdmin")
|
||||
.addInt("convID", convID)
|
||||
.addInt("userID", userID)
|
||||
@ -91,7 +90,7 @@ class ConversationsHelper {
|
||||
if (settings.isComplete)
|
||||
request
|
||||
.addString("name", settings.name ?? "")
|
||||
.addBool("canEveryoneAddMembers", settings.canEveryoneAddMembers)
|
||||
.addBool("canEveryoneAddMembers", settings.canEveryoneAddMembers!)
|
||||
.addString("color", colorToHex(settings.color));
|
||||
|
||||
await request.execWithThrow();
|
||||
@ -104,7 +103,7 @@ class ConversationsHelper {
|
||||
/// Set a new conversation logo
|
||||
///
|
||||
/// Throws in case of failure
|
||||
static Future<void> changeImage(int convID, BytesFile file) async =>
|
||||
static Future<void> changeImage(int? convID, BytesFile file) async =>
|
||||
await APIRequest.withLogin("conversations/change_image")
|
||||
.addInt("convID", convID)
|
||||
.addBytesFile("file", file)
|
||||
@ -113,13 +112,13 @@ class ConversationsHelper {
|
||||
/// Remove conversation logo
|
||||
///
|
||||
/// Throws in case of failure
|
||||
static Future<void> removeLogo(int convID) async =>
|
||||
static Future<void> removeLogo(int? convID) async =>
|
||||
await APIRequest.withLogin("conversations/delete_image")
|
||||
.addInt("convID", convID)
|
||||
.execWithThrow();
|
||||
|
||||
/// Delete a conversation specified by its [id]
|
||||
Future<void> deleteConversation(int id) async =>
|
||||
Future<void> deleteConversation(int? id) async =>
|
||||
await APIRequest.withLogin("conversations/delete")
|
||||
.addInt("conversationID", id)
|
||||
.execWithThrow();
|
||||
@ -132,7 +131,7 @@ class ConversationsHelper {
|
||||
await APIRequest.withLogin("conversations/getList").execWithThrow();
|
||||
|
||||
ConversationsList list = ConversationsList();
|
||||
response.getArray().forEach((f) => list.add(apiToConversation(f)));
|
||||
response.getArray()!.forEach((f) => list.add(apiToConversation(f)));
|
||||
|
||||
// Update the database
|
||||
await ConversationsSerializationHelper().setList(list);
|
||||
@ -148,13 +147,13 @@ class ConversationsHelper {
|
||||
}
|
||||
|
||||
/// Get information about a single conversation specified by its [id]
|
||||
Future<Conversation> _downloadSingle(int id) async {
|
||||
Future<Conversation> _downloadSingle(int? id) async {
|
||||
final response = await APIRequest(
|
||||
uri: "conversations/get_single",
|
||||
needLogin: true,
|
||||
args: {"conversationID": id.toString()}).execWithThrow();
|
||||
|
||||
final conversation = apiToConversation(response.getObject());
|
||||
final conversation = apiToConversation(response.getObject()!);
|
||||
|
||||
await ConversationsSerializationHelper()
|
||||
.insertOrReplaceElement((c) => c.id == conversation.id, conversation);
|
||||
@ -167,7 +166,7 @@ class ConversationsHelper {
|
||||
/// case of failure
|
||||
///
|
||||
/// Return value of this method is never null.
|
||||
Future<Conversation> getSingle(int id, {bool force = false}) async {
|
||||
Future<Conversation> getSingle(int? id, {bool force = false}) async {
|
||||
if (force ||
|
||||
!await ConversationsSerializationHelper().any((c) => c.id == id))
|
||||
return await _downloadSingle(id);
|
||||
@ -178,19 +177,19 @@ class ConversationsHelper {
|
||||
/// Get the name of a [conversation]. This requires information
|
||||
/// about the users of this conversation
|
||||
static String getConversationName(
|
||||
Conversation conversation, UsersList users) {
|
||||
if (conversation.hasName) return conversation.name;
|
||||
Conversation conversation, UsersList? users) {
|
||||
if (conversation.hasName) return conversation.name!;
|
||||
|
||||
String name = "";
|
||||
int count = 0;
|
||||
for (int i = 0; i < 3 && i < conversation.members.length; i++)
|
||||
if (conversation.members[i].userID != userID()) {
|
||||
for (int i = 0; i < 3 && i < conversation.members!.length; i++)
|
||||
if (conversation.members![i].userID != userID()) {
|
||||
name += (count > 0 ? ", " : "") +
|
||||
users.getUser(conversation.members[i].userID).fullName;
|
||||
users!.getUser(conversation.members![i].userID).fullName;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (conversation.members.length > 3) name += ", ...";
|
||||
if (conversation.members!.length > 3) name += ", ...";
|
||||
|
||||
return name;
|
||||
}
|
||||
@ -200,7 +199,7 @@ class ConversationsHelper {
|
||||
/// true
|
||||
///
|
||||
/// Throws an exception in case of failure
|
||||
Future<int> getPrivate(int userID, {bool allowCreate = true}) async {
|
||||
Future<int> getPrivate(int? userID, {bool allowCreate = true}) async {
|
||||
final response = await APIRequest(
|
||||
uri: "conversations/getPrivate",
|
||||
needLogin: true,
|
||||
@ -211,7 +210,7 @@ class ConversationsHelper {
|
||||
).execWithThrow();
|
||||
|
||||
// Get and return conversation ID
|
||||
return int.parse(response.getObject()["conversationsID"][0].toString());
|
||||
return int.parse(response.getObject()!["conversationsID"][0].toString());
|
||||
}
|
||||
|
||||
/// Asynchronously get the name of the conversation
|
||||
@ -222,7 +221,7 @@ class ConversationsHelper {
|
||||
/// Throws an exception in case of failure
|
||||
static Future<String> getConversationNameAsync(
|
||||
Conversation conversation) async {
|
||||
if (conversation.hasName) return conversation.name;
|
||||
if (conversation.hasName) return conversation.name!;
|
||||
|
||||
//Get information about the members of the conversation
|
||||
final members = await UsersHelper().getList(conversation.membersID);
|
||||
@ -273,7 +272,7 @@ class ConversationsHelper {
|
||||
|
||||
// Parse the response of the server
|
||||
ConversationMessagesList list = ConversationMessagesList();
|
||||
response.getArray().forEach((f) {
|
||||
response.getArray()!.forEach((f) {
|
||||
list.add(
|
||||
apiToConversationMessage(f),
|
||||
);
|
||||
@ -294,7 +293,7 @@ class ConversationsHelper {
|
||||
/// Throws an exception in case of failure
|
||||
Future<ConversationMessagesList> _downloadNewMessagesSingle(
|
||||
int conversationID,
|
||||
{int lastMessageID = 0}) async {
|
||||
{int? lastMessageID = 0}) async {
|
||||
// Execute the request on the server
|
||||
final response = await APIRequest(
|
||||
uri: "conversations/refresh_single",
|
||||
@ -311,8 +310,8 @@ class ConversationsHelper {
|
||||
///
|
||||
/// Throws in case of failure
|
||||
Future<ConversationMessagesList> getOlderMessages({
|
||||
@required int conversationID,
|
||||
@required int oldestMessagesID,
|
||||
required int conversationID,
|
||||
required int? oldestMessagesID,
|
||||
int limit = 15,
|
||||
}) async {
|
||||
// Perform the request online
|
||||
@ -334,8 +333,8 @@ class ConversationsHelper {
|
||||
///
|
||||
/// Throws in case of failure
|
||||
Future<ConversationMessagesList> getNewMessages(
|
||||
{@required int conversationID,
|
||||
int lastMessageID = 0,
|
||||
{required int conversationID,
|
||||
int? lastMessageID = 0,
|
||||
bool online = true}) async {
|
||||
if (online)
|
||||
return await _downloadNewMessagesSingle(conversationID,
|
||||
@ -348,8 +347,8 @@ class ConversationsHelper {
|
||||
/// Send a new message to the server
|
||||
Future<SendMessageResult> sendMessage(
|
||||
NewConversationMessage message, {
|
||||
ProgressCallback sendProgress,
|
||||
CancelToken cancelToken,
|
||||
ProgressCallback? sendProgress,
|
||||
CancelToken? cancelToken,
|
||||
}) async {
|
||||
final request = APIRequest.withLogin("conversations/sendMessage")
|
||||
.addInt("conversationID", message.conversationID)
|
||||
@ -388,7 +387,7 @@ class ConversationsHelper {
|
||||
await ConversationsMessagesSerializationHelper(msg.convID).remove(msg);
|
||||
|
||||
/// Update a message content
|
||||
Future<bool> updateMessage(int id, String newContent) async {
|
||||
Future<bool> updateMessage(int? id, String newContent) async {
|
||||
final response = await APIRequest(
|
||||
uri: "conversations/updateMessage",
|
||||
needLogin: true,
|
||||
@ -400,7 +399,7 @@ class ConversationsHelper {
|
||||
}
|
||||
|
||||
/// Delete permanently a message specified by its [id]
|
||||
Future<bool> deleteMessage(int id) async {
|
||||
Future<bool> deleteMessage(int? id) async {
|
||||
// Delete the message online
|
||||
final response = await APIRequest(
|
||||
uri: "conversations/deleteMessage",
|
||||
@ -418,7 +417,7 @@ class ConversationsHelper {
|
||||
static Future<UnreadConversationsList> getListUnread() async {
|
||||
final list = (await APIRequest.withLogin("conversations/get_list_unread")
|
||||
.execWithThrow())
|
||||
.getArray();
|
||||
.getArray()!;
|
||||
|
||||
return UnreadConversationsList()
|
||||
..addAll(list.map((f) => UnreadConversation(
|
||||
@ -431,7 +430,7 @@ class ConversationsHelper {
|
||||
/// conversation through WebSocket
|
||||
Future<void> registerConversationEvents(int id) async {
|
||||
if (_registeredConversations.containsKey(id))
|
||||
_registeredConversations[id]++;
|
||||
_registeredConversations.update(id, (value) => value + 1);
|
||||
else {
|
||||
_registeredConversations[id] = 1;
|
||||
await ws("\$main/register_conv", {"convID": id});
|
||||
@ -442,16 +441,16 @@ class ConversationsHelper {
|
||||
Future<void> unregisterConversationEvents(int id) async {
|
||||
if (!_registeredConversations.containsKey(id)) return;
|
||||
|
||||
_registeredConversations[id]--;
|
||||
_registeredConversations.update(id, (value) => value - 1);
|
||||
|
||||
if (_registeredConversations[id] <= 0) {
|
||||
if (_registeredConversations[id]! <= 0) {
|
||||
_registeredConversations.remove(id);
|
||||
await ws("\$main/unregister_conv", {"convID": id});
|
||||
}
|
||||
}
|
||||
|
||||
/// Send a notification to inform that the user is writing a message
|
||||
static Future<void> sendWritingEvent(int convID) async =>
|
||||
static Future<void> sendWritingEvent(int? convID) async =>
|
||||
await ws("conversations/is_writing", {"convID": convID});
|
||||
|
||||
/// Turn an API response into a ConversationMessage object
|
||||
|
@ -9,11 +9,11 @@ import 'package:sqflite/sqflite.dart';
|
||||
/// @author Pierre HUBERT
|
||||
|
||||
abstract class DatabaseHelper {
|
||||
static Database _db;
|
||||
static Database? _db;
|
||||
|
||||
/// Open the database
|
||||
static Future<void> open() async {
|
||||
if (_db != null && _db.isOpen) return;
|
||||
if (_db != null && _db!.isOpen) return;
|
||||
|
||||
var databasePath = await getDatabasesPath();
|
||||
_db = await openDatabase(
|
||||
@ -24,7 +24,7 @@ abstract class DatabaseHelper {
|
||||
}
|
||||
|
||||
/// Get a database instance
|
||||
static Future<Database> get() async {
|
||||
static Future<Database?> get() async {
|
||||
await open();
|
||||
return _db;
|
||||
}
|
||||
|
@ -18,12 +18,12 @@ abstract class ModelDatabaseHelper<T extends CacheModel> {
|
||||
|
||||
/// Insert an entry in the database
|
||||
Future<void> _insertDB(T el) async {
|
||||
await (await DatabaseHelper.get()).insert(tableName(), el.toMap());
|
||||
await (await DatabaseHelper.get())!.insert(tableName(), el.toMap());
|
||||
}
|
||||
|
||||
/// Update an element in the database
|
||||
Future<void> _updateDB(T el) async {
|
||||
await (await DatabaseHelper.get()).update(
|
||||
await (await DatabaseHelper.get())!.update(
|
||||
tableName(),
|
||||
el.toMap(),
|
||||
where: "${BaseTableContract.C_ID} = ?",
|
||||
@ -34,14 +34,14 @@ abstract class ModelDatabaseHelper<T extends CacheModel> {
|
||||
/// Get an element from the database with a specified [id]
|
||||
///
|
||||
/// Returns null if none found
|
||||
Future<T> get(int id) async {
|
||||
List<Map> maps = await (await DatabaseHelper.get()).query(
|
||||
Future<T?> get(int id) async {
|
||||
List<Map> maps = await (await DatabaseHelper.get())!.query(
|
||||
tableName(),
|
||||
where: '${BaseTableContract.C_ID} = ?',
|
||||
whereArgs: [id],
|
||||
);
|
||||
|
||||
if (maps.length > 0) return initializeFromMap(maps[0]);
|
||||
if (maps.length > 0) return initializeFromMap(maps[0] as Map<String, dynamic>);
|
||||
|
||||
return null;
|
||||
}
|
||||
@ -50,7 +50,7 @@ abstract class ModelDatabaseHelper<T extends CacheModel> {
|
||||
///
|
||||
/// Return true if at least one entry was deleted / false else
|
||||
Future<bool> delete(int id) async {
|
||||
return await (await DatabaseHelper.get()).delete(
|
||||
return await (await DatabaseHelper.get())!.delete(
|
||||
tableName(),
|
||||
where: '${BaseTableContract.C_ID} = ?',
|
||||
whereArgs: [id],
|
||||
@ -59,22 +59,22 @@ abstract class ModelDatabaseHelper<T extends CacheModel> {
|
||||
|
||||
/// Get all the entries from the table
|
||||
Future<List<T>> getAll() async {
|
||||
List<Map> maps = await (await DatabaseHelper.get()).query(tableName());
|
||||
return maps.map((f) => initializeFromMap(f)).toList();
|
||||
List<Map> maps = await (await DatabaseHelper.get())!.query(tableName());
|
||||
return maps.map((f) => initializeFromMap(f as Map<String, dynamic>)).toList();
|
||||
}
|
||||
|
||||
/// Get some entries from the table based on some conditions
|
||||
Future<List<T>> getMultiple(
|
||||
{bool distinct,
|
||||
List<String> columns,
|
||||
String where,
|
||||
List<dynamic> whereArgs,
|
||||
String groupBy,
|
||||
String having,
|
||||
String orderBy,
|
||||
int limit,
|
||||
int offset}) async {
|
||||
List<Map> maps = await (await DatabaseHelper.get()).query(
|
||||
{bool? distinct,
|
||||
List<String>? columns,
|
||||
String? where,
|
||||
List<dynamic>? whereArgs,
|
||||
String? groupBy,
|
||||
String? having,
|
||||
String? orderBy,
|
||||
int? limit,
|
||||
int? offset}) async {
|
||||
List<Map> maps = await (await DatabaseHelper.get())!.query(
|
||||
tableName(),
|
||||
distinct: distinct,
|
||||
columns: columns,
|
||||
@ -86,12 +86,12 @@ abstract class ModelDatabaseHelper<T extends CacheModel> {
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
);
|
||||
return maps.map((f) => initializeFromMap(f)).toList();
|
||||
return maps.map((f) => initializeFromMap(f as Map<String, dynamic>)).toList();
|
||||
}
|
||||
|
||||
/// Empty the table
|
||||
Future<void> clearTable() async {
|
||||
await (await DatabaseHelper.get()).execute("DELETE FROM ${tableName()}");
|
||||
await (await DatabaseHelper.get())!.execute("DELETE FROM ${tableName()}");
|
||||
}
|
||||
|
||||
/// Check out whether an element specified with its [id] is present
|
||||
|
@ -17,14 +17,14 @@ class WSClosedEvent {}
|
||||
|
||||
/// New number of notifications
|
||||
class NewNumberNotifsEvent {
|
||||
final int newNum;
|
||||
final int? newNum;
|
||||
|
||||
NewNumberNotifsEvent(this.newNum);
|
||||
}
|
||||
|
||||
/// New number of unread conversations
|
||||
class NewNumberUnreadConversations {
|
||||
final int newNum;
|
||||
final int? newNum;
|
||||
|
||||
NewNumberUnreadConversations(this.newNum);
|
||||
}
|
||||
@ -45,15 +45,15 @@ class UpdatedCommentEvent {
|
||||
|
||||
/// Deleted comment
|
||||
class DeletedCommentEvent {
|
||||
final int commentID;
|
||||
final int? commentID;
|
||||
|
||||
DeletedCommentEvent(this.commentID);
|
||||
}
|
||||
|
||||
/// Writing message in conversation event
|
||||
class WritingMessageInConversationEvent {
|
||||
final int convID;
|
||||
final int userID;
|
||||
final int? convID;
|
||||
final int? userID;
|
||||
|
||||
WritingMessageInConversationEvent(this.convID, this.userID);
|
||||
}
|
||||
@ -81,31 +81,31 @@ class DeletedConversationMessageEvent {
|
||||
|
||||
/// Remove user from conversation
|
||||
class RemovedUserFromConversationEvent {
|
||||
final int convID;
|
||||
final int userID;
|
||||
final int? convID;
|
||||
final int? userID;
|
||||
|
||||
RemovedUserFromConversationEvent(this.convID, this.userID);
|
||||
}
|
||||
|
||||
/// Deleted conversation
|
||||
class DeletedConversationEvent {
|
||||
final int convID;
|
||||
final int? convID;
|
||||
|
||||
DeletedConversationEvent(this.convID);
|
||||
}
|
||||
|
||||
/// User joined call event
|
||||
class UserJoinedCallEvent {
|
||||
final int callID;
|
||||
final int userID;
|
||||
final int? callID;
|
||||
final int? userID;
|
||||
|
||||
UserJoinedCallEvent(this.callID, this.userID);
|
||||
}
|
||||
|
||||
/// User left call event
|
||||
class UserLeftCallEvent {
|
||||
final int callID;
|
||||
final int userID;
|
||||
final int? callID;
|
||||
final int? userID;
|
||||
|
||||
UserLeftCallEvent(this.callID, this.userID);
|
||||
}
|
||||
@ -114,12 +114,12 @@ class UserLeftCallEvent {
|
||||
class NewCallSignalEvent {
|
||||
final int callID;
|
||||
final int peerID;
|
||||
final RTCSessionDescription sessionDescription;
|
||||
final RTCIceCandidate candidate;
|
||||
final RTCSessionDescription? sessionDescription;
|
||||
final RTCIceCandidate? candidate;
|
||||
|
||||
const NewCallSignalEvent({
|
||||
this.callID,
|
||||
this.peerID,
|
||||
required this.callID,
|
||||
required this.peerID,
|
||||
this.sessionDescription,
|
||||
this.candidate,
|
||||
}) : assert(callID != null),
|
||||
@ -129,23 +129,23 @@ class NewCallSignalEvent {
|
||||
|
||||
/// Call peer ready event
|
||||
class CallPeerReadyEvent {
|
||||
final int callID;
|
||||
final int peerID;
|
||||
final int? callID;
|
||||
final int? peerID;
|
||||
|
||||
CallPeerReadyEvent(this.callID, this.peerID);
|
||||
}
|
||||
|
||||
/// Call peer interrupted streaming event
|
||||
class CallPeerInterruptedStreamingEvent {
|
||||
final int callID;
|
||||
final int peerID;
|
||||
final int? callID;
|
||||
final int? peerID;
|
||||
|
||||
CallPeerInterruptedStreamingEvent(this.callID, this.peerID);
|
||||
}
|
||||
|
||||
/// Call closed event
|
||||
class CallClosedEvent {
|
||||
final int callID;
|
||||
final int? callID;
|
||||
|
||||
CallClosedEvent(this.callID);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ class FirebaseMessagingHelper {
|
||||
}
|
||||
|
||||
/// Get a Firebase access token
|
||||
static Future<String> getToken() async {
|
||||
static Future<String?> getToken() async {
|
||||
return await FirebaseMessaging.instance.getToken();
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import 'package:comunic/models/group.dart';
|
||||
class ForezGroupsHelper {
|
||||
static Future<List<Group>> getForezGroups() async {
|
||||
return (await APIRequest.withLogin("forez/get_groups").execWithThrow())
|
||||
.getArray()
|
||||
.getArray()!
|
||||
.cast<Map<String, dynamic>>()
|
||||
.map(GroupsHelper.getGroupFromAPI)
|
||||
.toList();
|
||||
@ -21,10 +21,10 @@ class ForezGroupsHelper {
|
||||
///
|
||||
/// This methods throws an exception in case of failure
|
||||
static Future<AdvancedUserInfo> getMemberInfo(int groupID, int userID) async {
|
||||
final response = await APIRequest.withLogin("forez/get_member_info")
|
||||
final response = await (APIRequest.withLogin("forez/get_member_info")
|
||||
.addInt("group", groupID)
|
||||
.addInt("user", userID)
|
||||
.execWithThrowGetObject();
|
||||
.execWithThrowGetObject());
|
||||
|
||||
return UsersHelper.apiToAdvancedUserInfo(response);
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ import 'package:comunic/models/forez_presence.dart';
|
||||
///
|
||||
/// @author Pierre Hubert
|
||||
|
||||
int _cachedGroup;
|
||||
PresenceSet _cache;
|
||||
int? _cachedGroup;
|
||||
PresenceSet? _cache;
|
||||
|
||||
class ForezPresenceHelper {
|
||||
/// Refresh presence cache
|
||||
@ -40,16 +40,16 @@ class ForezPresenceHelper {
|
||||
/// Get the presences of a given user
|
||||
///
|
||||
/// Throws in case of failure
|
||||
static Future<PresenceSet> getForUser(int groupID, int userID) async {
|
||||
static Future<PresenceSet> getForUser(int groupID, int? userID) async {
|
||||
await _checkCache(groupID);
|
||||
|
||||
return _cache.getForUser(userID);
|
||||
return _cache!.getForUser(userID);
|
||||
}
|
||||
|
||||
/// Get all the available presences
|
||||
///
|
||||
/// Throws in case of failure
|
||||
static Future<PresenceSet> getAll(int groupID) async {
|
||||
static Future<PresenceSet?> getAll(int groupID) async {
|
||||
await _checkCache(groupID);
|
||||
return _cache;
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ import 'package:comunic/lists/friends_list.dart';
|
||||
import 'package:comunic/models/api_request.dart';
|
||||
import 'package:comunic/models/friend.dart';
|
||||
import 'package:comunic/models/friend_status.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
/// Friends helper
|
||||
///
|
||||
@ -16,7 +15,7 @@ class FriendsHelper {
|
||||
///
|
||||
/// Returns the list of friends in case of success, or null if an error
|
||||
/// occurred
|
||||
Future<FriendsList> _downloadList() async {
|
||||
Future<FriendsList?> _downloadList() async {
|
||||
final response = await APIRequest(
|
||||
uri: "friends/getList",
|
||||
needLogin: true,
|
||||
@ -30,7 +29,7 @@ class FriendsHelper {
|
||||
// Parse and return the list of friends
|
||||
FriendsList list = FriendsList()
|
||||
..addAll(response
|
||||
.getArray()
|
||||
.getArray()!
|
||||
.cast<Map<String, dynamic>>()
|
||||
.map(apiToFriend)
|
||||
.toList());
|
||||
@ -54,7 +53,7 @@ class FriendsHelper {
|
||||
}
|
||||
|
||||
/// Get the list, either from an online or an offline source
|
||||
Future<FriendsList> getList({@required bool online}) async {
|
||||
Future<FriendsList?> getList({required bool online}) async {
|
||||
if (online)
|
||||
return await _downloadList();
|
||||
else
|
||||
@ -108,7 +107,7 @@ class FriendsHelper {
|
||||
if (response.code != 200)
|
||||
throw Exception("Could not get friendship status!");
|
||||
|
||||
final obj = response.getObject();
|
||||
final obj = response.getObject()!;
|
||||
|
||||
return FriendStatus(
|
||||
userID: userID,
|
||||
@ -132,7 +131,7 @@ class FriendsHelper {
|
||||
if (response.code != 200)
|
||||
throw new Exception("Could not get the list of friends of this user!");
|
||||
|
||||
return Set<int>.from(response.getArray());
|
||||
return Set<int>.from(response.getArray()!);
|
||||
}
|
||||
|
||||
/// Send a friendship request to a specified user
|
||||
|
@ -49,7 +49,7 @@ enum GetAdvancedInfoStatus { SUCCESS, ACCESS_DENIED }
|
||||
|
||||
class GetAdvancedInfoResult {
|
||||
final GetAdvancedInfoStatus status;
|
||||
final AdvancedGroupInfo info;
|
||||
final AdvancedGroupInfo? info;
|
||||
|
||||
GetAdvancedInfoResult(this.status, this.info) : assert(status != null);
|
||||
}
|
||||
@ -57,7 +57,7 @@ class GetAdvancedInfoResult {
|
||||
/// Groups helper
|
||||
class GroupsHelper {
|
||||
/// Download a list of groups information from the server
|
||||
Future<GroupsList> _downloadList(Set<int> groups) async {
|
||||
Future<GroupsList?> _downloadList(Set<int?> groups) async {
|
||||
final response = await APIRequest(
|
||||
uri: "groups/get_multiple_info",
|
||||
needLogin: true,
|
||||
@ -69,7 +69,7 @@ class GroupsHelper {
|
||||
final list = GroupsList();
|
||||
|
||||
response
|
||||
.getObject()
|
||||
.getObject()!
|
||||
.forEach((k, d) => list[int.parse(k)] = getGroupFromAPI(d));
|
||||
|
||||
return list;
|
||||
@ -77,7 +77,7 @@ class GroupsHelper {
|
||||
|
||||
/// Get a list of groups from the server. In case of error, this method throws
|
||||
/// an exception
|
||||
Future<GroupsList> getListOrThrow(Set<int> groups,
|
||||
Future<GroupsList> getListOrThrow(Set<int?> groups,
|
||||
{bool force = false}) async {
|
||||
final list = await getList(groups, force: force);
|
||||
|
||||
@ -87,11 +87,11 @@ class GroupsHelper {
|
||||
}
|
||||
|
||||
/// Get a list of groups from the server
|
||||
Future<GroupsList> getList(Set<int> groups, {bool force = false}) async {
|
||||
Future<GroupsList?> getList(Set<int?> groups, {bool force = false}) async {
|
||||
final list = GroupsList();
|
||||
|
||||
// Check which groups information to download
|
||||
final toDownload = Set<int>();
|
||||
final toDownload = Set<int?>();
|
||||
groups.forEach((groupID) {
|
||||
if (!force && _groupsListCache.containsKey(groupID))
|
||||
list[groupID] = _groupsListCache[groupID];
|
||||
@ -122,10 +122,10 @@ class GroupsHelper {
|
||||
}
|
||||
|
||||
/// Get the list of groups of a user
|
||||
Future<Set<int>> getListUser() async =>
|
||||
Future<Set<int?>> getListUser() async =>
|
||||
(await APIRequest(uri: "groups/get_my_list", needLogin: true).exec())
|
||||
.assertOk()
|
||||
.getArray()
|
||||
.getArray()!
|
||||
.map((f) => cast<int>(f))
|
||||
.toSet();
|
||||
|
||||
@ -142,7 +142,7 @@ class GroupsHelper {
|
||||
|
||||
/// Perform a simple membership request
|
||||
static Future<bool> _simpleMembershipRequest(int groupID, String uri,
|
||||
{Map<String, String> args}) async =>
|
||||
{Map<String, String>? args}) async =>
|
||||
(await (APIRequest.withLogin(uri)
|
||||
..addInt("id", groupID)
|
||||
..addArgs(args == null ? Map() : args))
|
||||
@ -176,7 +176,7 @@ class GroupsHelper {
|
||||
.isOK;
|
||||
|
||||
/// Get advanced information about the user
|
||||
Future<GetAdvancedInfoResult> getAdvancedInfo(int groupID) async {
|
||||
Future<GetAdvancedInfoResult> getAdvancedInfo(int? groupID) async {
|
||||
// Get advanced information about the user
|
||||
final result =
|
||||
await (APIRequest(uri: "groups/get_advanced_info", needLogin: true)
|
||||
@ -189,7 +189,7 @@ class GroupsHelper {
|
||||
|
||||
case 200:
|
||||
return GetAdvancedInfoResult(GetAdvancedInfoStatus.SUCCESS,
|
||||
_getAdvancedGroupInfoFromAPI(result.getObject()));
|
||||
_getAdvancedGroupInfoFromAPI(result.getObject()!));
|
||||
|
||||
default:
|
||||
throw Exception("Could not get advanced group information!");
|
||||
@ -202,7 +202,7 @@ class GroupsHelper {
|
||||
/// change in the future
|
||||
///
|
||||
/// Throws in case of error
|
||||
Future<AdvancedGroupInfo> getSettings(int groupID) async {
|
||||
Future<AdvancedGroupInfo?> getSettings(int groupID) async {
|
||||
final groupInfo = await getAdvancedInfo(groupID);
|
||||
|
||||
if (groupInfo.status != GetAdvancedInfoStatus.SUCCESS)
|
||||
@ -239,7 +239,7 @@ class GroupsHelper {
|
||||
"posts_level",
|
||||
invertMap(
|
||||
_APIGroupsPostsCreationLevelsMap)[settings.postCreationLevel])
|
||||
.addBool("is_members_list_public", settings.isMembersListPublic)
|
||||
.addBool("is_members_list_public", settings.isMembersListPublic!)
|
||||
.addString("description", settings.description)
|
||||
.addString("url", settings.url)
|
||||
.execWithThrow();
|
||||
@ -248,7 +248,7 @@ class GroupsHelper {
|
||||
/// Upload a new logo
|
||||
///
|
||||
/// Throws in case of failure
|
||||
static Future<void> uploadNewLogo(int groupID, Uint8List bytes) async =>
|
||||
static Future<void> uploadNewLogo(int groupID, Uint8List? bytes) async =>
|
||||
await APIRequest(uri: "groups/upload_logo", needLogin: true)
|
||||
.addInt("id", groupID)
|
||||
.addBytesFile("logo", BytesFile("logo.png", bytes))
|
||||
@ -279,7 +279,7 @@ class GroupsHelper {
|
||||
..addAll((await APIRequest(uri: "groups/get_members", needLogin: true)
|
||||
.addInt("id", groupID)
|
||||
.execWithThrow())
|
||||
.getArray()
|
||||
.getArray()!
|
||||
.map((f) => _apiToGroupMembership(f))
|
||||
.toList());
|
||||
|
||||
@ -295,7 +295,7 @@ class GroupsHelper {
|
||||
/// Cancel a group membership invitation
|
||||
///
|
||||
/// Throws an exception in case of failure
|
||||
static Future<void> cancelInvitation(int groupID, int userID) async =>
|
||||
static Future<void> cancelInvitation(int groupID, int? userID) async =>
|
||||
await APIRequest.withLogin("groups/cancel_invitation")
|
||||
.addInt("groupID", groupID)
|
||||
.addInt("userID", userID)
|
||||
@ -305,7 +305,7 @@ class GroupsHelper {
|
||||
///
|
||||
/// Throws an exception in case of failure
|
||||
static Future<void> respondRequest(
|
||||
int groupID, int userID, bool accept) async =>
|
||||
int groupID, int? userID, bool accept) async =>
|
||||
await APIRequest.withLogin("groups/respond_request")
|
||||
.addInt("groupID", groupID)
|
||||
.addInt("userID", userID)
|
||||
@ -351,7 +351,7 @@ class GroupsHelper {
|
||||
///
|
||||
/// Throws in case of failure
|
||||
static Future<void> setConversationVisibility(
|
||||
int convID, GroupMembershipLevel newLevel) async =>
|
||||
int? convID, GroupMembershipLevel? newLevel) async =>
|
||||
await APIRequest.withLogin("groups/set_conversation_visibility")
|
||||
.addInt("conv_id", convID)
|
||||
.addString(
|
||||
@ -364,7 +364,7 @@ class GroupsHelper {
|
||||
/// Delete a group's conversation
|
||||
///
|
||||
/// Throws in case of failure
|
||||
static Future<void> deleteConversation(int convID) async =>
|
||||
static Future<void> deleteConversation(int? convID) async =>
|
||||
await APIRequest.withLogin("groups/delete_conversation")
|
||||
.addInt("conv_id", convID)
|
||||
.execWithThrow();
|
||||
@ -376,11 +376,11 @@ class GroupsHelper {
|
||||
name: map["name"],
|
||||
iconURL: map["icon_url"],
|
||||
numberMembers: map["number_members"],
|
||||
membershipLevel: APIGroupsMembershipLevelsMap[map["membership"]],
|
||||
visibilityLevel: _APIGroupsVisibilityLevelsMap[map["visibility"]],
|
||||
membershipLevel: APIGroupsMembershipLevelsMap[map["membership"]]!,
|
||||
visibilityLevel: _APIGroupsVisibilityLevelsMap[map["visibility"]]!,
|
||||
registrationLevel:
|
||||
_APIGroupsRegistrationLevelsMap[map["registration_level"]],
|
||||
postCreationLevel: _APIGroupsPostsCreationLevelsMap[map["posts_level"]],
|
||||
_APIGroupsRegistrationLevelsMap[map["registration_level"]]!,
|
||||
postCreationLevel: _APIGroupsPostsCreationLevelsMap[map["posts_level"]]!,
|
||||
virtualDirectory: nullToEmpty(map["virtual_directory"]),
|
||||
following: map["following"]);
|
||||
}
|
||||
@ -392,11 +392,11 @@ class GroupsHelper {
|
||||
name: map["name"],
|
||||
iconURL: map["icon_url"],
|
||||
numberMembers: map["number_members"],
|
||||
membershipLevel: APIGroupsMembershipLevelsMap[map["membership"]],
|
||||
visibilityLevel: _APIGroupsVisibilityLevelsMap[map["visibility"]],
|
||||
membershipLevel: APIGroupsMembershipLevelsMap[map["membership"]]!,
|
||||
visibilityLevel: _APIGroupsVisibilityLevelsMap[map["visibility"]]!,
|
||||
registrationLevel:
|
||||
_APIGroupsRegistrationLevelsMap[map["registration_level"]],
|
||||
postCreationLevel: _APIGroupsPostsCreationLevelsMap[map["posts_level"]],
|
||||
_APIGroupsRegistrationLevelsMap[map["registration_level"]]!,
|
||||
postCreationLevel: _APIGroupsPostsCreationLevelsMap[map["posts_level"]]!,
|
||||
isMembersListPublic: map["is_members_list_public"],
|
||||
virtualDirectory: nullToEmpty(map["virtual_directory"]),
|
||||
following: map["following"],
|
||||
@ -418,6 +418,6 @@ class GroupsHelper {
|
||||
userID: row["user_id"],
|
||||
groupID: row["group_id"],
|
||||
timeCreate: row["time_create"],
|
||||
level: APIGroupsMembershipLevelsMap[row["level"]],
|
||||
level: APIGroupsMembershipLevelsMap[row["level"]]!,
|
||||
);
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ class IndependentPushNotificationsHelper {
|
||||
}
|
||||
|
||||
/// Configure independent push notification services with a pull URL
|
||||
static Future<void> configure(String wsURL) async {
|
||||
static Future<void> configure(String? wsURL) async {
|
||||
await platform.invokeMethod("configure", wsURL);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
import 'package:comunic/enums/likes_type.dart';
|
||||
import 'package:comunic/helpers/websocket_helper.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
/// Likes helper
|
||||
///
|
||||
@ -16,9 +15,9 @@ const LikesAPIMap = {
|
||||
class LikesHelper {
|
||||
/// Update liking status of an element
|
||||
Future<void> setLiking({
|
||||
@required LikesType type,
|
||||
@required bool like,
|
||||
@required int id,
|
||||
required LikesType type,
|
||||
required bool like,
|
||||
required int id,
|
||||
}) async {
|
||||
return (await ws("likes/update", {
|
||||
"type": LikesAPIMap[type],
|
||||
|
@ -55,7 +55,7 @@ class NotificationsHelper {
|
||||
await APIRequest(uri: "notifications/count_all_news", needLogin: true)
|
||||
.exec();
|
||||
|
||||
final content = response.assertOk().getObject();
|
||||
final content = response.assertOk().getObject()!;
|
||||
|
||||
return CountUnreadNotifications(
|
||||
notifications: content["notifications"],
|
||||
@ -75,15 +75,15 @@ class NotificationsHelper {
|
||||
// Parse the list of notifications
|
||||
return NotificationsList()
|
||||
..addAll(response
|
||||
.getArray()
|
||||
.getArray()!
|
||||
.map((f) => Notification(
|
||||
id: f["id"],
|
||||
timeCreate: f["time_create"],
|
||||
seen: f["seen"],
|
||||
fromUser: f["from_user_id"],
|
||||
onElemId: f["on_elem_id"],
|
||||
onElemType: _NotificationElementTypeAPImapping[f["on_elem_type"]],
|
||||
type: _NotificationsTypeAPImapping[f["type"]],
|
||||
onElemType: _NotificationElementTypeAPImapping[f["on_elem_type"]]!,
|
||||
type: _NotificationsTypeAPImapping[f["type"]]!,
|
||||
fromContainerId: f["from_container_id"],
|
||||
fromContainerType: f["from_container_type"] == ""
|
||||
? null
|
||||
|
@ -55,7 +55,7 @@ class PostsHelper {
|
||||
|
||||
/// Get the list of latest posts. Return the list of posts or null in case of
|
||||
/// failure
|
||||
Future<PostsList> getLatest({int from = 0}) async {
|
||||
Future<PostsList?> getLatest({int from = 0}) async {
|
||||
final response =
|
||||
await APIRequest(uri: "posts/get_latest", needLogin: true, args: {
|
||||
"include_groups": true.toString(),
|
||||
@ -66,7 +66,8 @@ class PostsHelper {
|
||||
|
||||
try {
|
||||
// Parse & return the list of posts
|
||||
return PostsList()..addAll(response.getArray().map((f) => _apiToPost(f)));
|
||||
return PostsList()
|
||||
..addAll(response.getArray()!.map((f) => _apiToPost(f)));
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
return null;
|
||||
@ -74,7 +75,7 @@ class PostsHelper {
|
||||
}
|
||||
|
||||
/// Get the list of posts of a user
|
||||
Future<PostsList> getUserPosts(int userID, {int from = 0}) async {
|
||||
Future<PostsList?> getUserPosts(int? userID, {int from = 0}) async {
|
||||
final response = await (APIRequest(uri: "posts/get_user", needLogin: true)
|
||||
..addInt("userID", userID)
|
||||
..addInt("startFrom", from == 0 ? 0 : from - 1))
|
||||
@ -84,7 +85,8 @@ class PostsHelper {
|
||||
|
||||
try {
|
||||
// Parse & return the list of posts
|
||||
return PostsList()..addAll(response.getArray().map((f) => _apiToPost(f)));
|
||||
return PostsList()
|
||||
..addAll(response.getArray()!.map((f) => _apiToPost(f)));
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
return null;
|
||||
@ -92,7 +94,7 @@ class PostsHelper {
|
||||
}
|
||||
|
||||
/// Get the list of posts of a group
|
||||
Future<PostsList> getGroupPosts(int groupID, {int from = 0}) async {
|
||||
Future<PostsList?> getGroupPosts(int groupID, {int from = 0}) async {
|
||||
final response = await (APIRequest(uri: "posts/get_group", needLogin: true)
|
||||
..addInt("groupID", groupID)
|
||||
..addInt("startFrom", from == 0 ? 0 : from - 1))
|
||||
@ -102,7 +104,8 @@ class PostsHelper {
|
||||
|
||||
try {
|
||||
// Parse & return the list of posts
|
||||
return PostsList()..addAll(response.getArray().map((f) => _apiToPost(f)));
|
||||
return PostsList()
|
||||
..addAll(response.getArray()!.map((f) => _apiToPost(f)));
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
return null;
|
||||
@ -120,7 +123,7 @@ class PostsHelper {
|
||||
if (!response.isOK)
|
||||
throw Exception("Could not get information about the post!");
|
||||
|
||||
return _apiToPost(response.getObject());
|
||||
return _apiToPost(response.getObject()!);
|
||||
}
|
||||
|
||||
/// Create a new post
|
||||
@ -158,13 +161,14 @@ class PostsHelper {
|
||||
|
||||
case PostKind.COUNTDOWN:
|
||||
request.addInt(
|
||||
"time-end", (post.timeEnd.millisecondsSinceEpoch / 1000).floor());
|
||||
"time-end", (post.timeEnd!.millisecondsSinceEpoch / 1000).floor());
|
||||
break;
|
||||
|
||||
case PostKind.SURVEY:
|
||||
request.addString("question", post.survey.question);
|
||||
request.addString("answers", post.survey.answers.join("<>"));
|
||||
request.addBool("allowNewAnswers", post.survey.allowNewChoicesCreation);
|
||||
request.addString("question", post.survey!.question);
|
||||
request.addString("answers", post.survey!.answers.join("<>"));
|
||||
request.addBool(
|
||||
"allowNewAnswers", post.survey!.allowNewChoicesCreation);
|
||||
break;
|
||||
|
||||
case PostKind.YOUTUBE:
|
||||
@ -221,7 +225,7 @@ class PostsHelper {
|
||||
/// Register to a post events
|
||||
Future<void> registerPostEvents(int id) async {
|
||||
if (_registeredPosts.containsKey(id))
|
||||
_registeredPosts[id]++;
|
||||
_registeredPosts.update(id, (v) => v + 1);
|
||||
else {
|
||||
_registeredPosts[id] = 1;
|
||||
await ws("\$main/register_post", {"postID": id});
|
||||
@ -232,9 +236,9 @@ class PostsHelper {
|
||||
Future<void> unregisterPostEvents(int id) async {
|
||||
if (!_registeredPosts.containsKey(id)) return;
|
||||
|
||||
_registeredPosts[id]--;
|
||||
_registeredPosts.update(id, (v) => v - 1);
|
||||
|
||||
if (_registeredPosts[id] <= 0) {
|
||||
if (_registeredPosts[id]! <= 0) {
|
||||
_registeredPosts.remove(id);
|
||||
await ws("\$main/unregister_post", {"postID": id});
|
||||
}
|
||||
@ -242,14 +246,14 @@ class PostsHelper {
|
||||
|
||||
/// Turn an API entry into a [Post] object
|
||||
Post _apiToPost(Map<String, dynamic> map) {
|
||||
final postKind = _APIPostsKindsMap[map["kind"]];
|
||||
final postKind = _APIPostsKindsMap[map["kind"]]!;
|
||||
|
||||
// Parse comments
|
||||
CommentsList comments;
|
||||
CommentsList? comments;
|
||||
if (map["comments"] != null) {
|
||||
comments = CommentsList();
|
||||
map["comments"]
|
||||
.forEach((v) => comments.add(CommentsHelper.apiToComment(v)));
|
||||
.forEach((v) => comments!.add(CommentsHelper.apiToComment(v)));
|
||||
}
|
||||
|
||||
final survey = postKind == PostKind.SURVEY
|
||||
@ -263,7 +267,7 @@ class PostsHelper {
|
||||
groupID: map["group_id"],
|
||||
timeSent: map["post_time"],
|
||||
content: DisplayedString(map["content"]),
|
||||
visibilityLevel: _APIPostsVisibilityLevelMap[map["visibility_level"]],
|
||||
visibilityLevel: _APIPostsVisibilityLevelMap[map["visibility_level"]]!,
|
||||
kind: postKind,
|
||||
fileSize: map["file_size"],
|
||||
fileType: map["file_type"],
|
||||
@ -276,7 +280,7 @@ class PostsHelper {
|
||||
linkImage: map["link_image"],
|
||||
likes: map["likes"],
|
||||
userLike: map["userlike"],
|
||||
access: _APIUserAccessMap[map["user_access"]],
|
||||
access: _APIUserAccessMap[map["user_access"]]!,
|
||||
comments: comments,
|
||||
survey: survey);
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ const _PreferenceKeysName = {
|
||||
};
|
||||
|
||||
class PreferencesHelper {
|
||||
static PreferencesHelper _instance;
|
||||
static PreferencesHelper? _instance;
|
||||
|
||||
static Future<PreferencesHelper> getInstance() async {
|
||||
if (_instance == null) {
|
||||
@ -38,10 +38,10 @@ class PreferencesHelper {
|
||||
await _init();
|
||||
}
|
||||
|
||||
return _instance;
|
||||
return _instance!;
|
||||
}
|
||||
|
||||
static SharedPreferences _sharedPreferences;
|
||||
static late SharedPreferences _sharedPreferences;
|
||||
|
||||
PreferencesHelper._();
|
||||
|
||||
@ -50,7 +50,7 @@ class PreferencesHelper {
|
||||
}
|
||||
|
||||
/// Set new login tokens
|
||||
Future<void> setLoginToken(String token) async {
|
||||
Future<void> setLoginToken(String? token) async {
|
||||
if (token != null)
|
||||
await setString(PreferencesKeyList.LOGIN_TOKEN, token);
|
||||
else
|
||||
@ -58,7 +58,7 @@ class PreferencesHelper {
|
||||
}
|
||||
|
||||
/// Get current [LoginTokens]. Returns null if none or in case of failure
|
||||
String getLoginToken() {
|
||||
String? getLoginToken() {
|
||||
try {
|
||||
final string = getString(PreferencesKeyList.LOGIN_TOKEN);
|
||||
return string;
|
||||
@ -69,35 +69,35 @@ class PreferencesHelper {
|
||||
}
|
||||
|
||||
bool containsKey(PreferencesKeyList key) {
|
||||
return _sharedPreferences.containsKey(_PreferenceKeysName[key]);
|
||||
return _sharedPreferences.containsKey(_PreferenceKeysName[key]!);
|
||||
}
|
||||
|
||||
Future<bool> removeKey(PreferencesKeyList key) async {
|
||||
return await _sharedPreferences.remove(_PreferenceKeysName[key]);
|
||||
return await _sharedPreferences.remove(_PreferenceKeysName[key]!);
|
||||
}
|
||||
|
||||
Future<bool> setString(PreferencesKeyList key, String value) async {
|
||||
return await _sharedPreferences.setString(_PreferenceKeysName[key], value);
|
||||
return await _sharedPreferences.setString(_PreferenceKeysName[key]!, value);
|
||||
}
|
||||
|
||||
String getString(PreferencesKeyList key) {
|
||||
return _sharedPreferences.getString(_PreferenceKeysName[key]);
|
||||
String? getString(PreferencesKeyList key) {
|
||||
return _sharedPreferences.getString(_PreferenceKeysName[key]!);
|
||||
}
|
||||
|
||||
Future<bool> setBool(PreferencesKeyList key, bool value) async {
|
||||
return await _sharedPreferences.setBool(_PreferenceKeysName[key], value);
|
||||
return await _sharedPreferences.setBool(_PreferenceKeysName[key]!, value);
|
||||
}
|
||||
|
||||
Future<bool> setInt(PreferencesKeyList key, int value) async {
|
||||
return await _sharedPreferences.setInt(_PreferenceKeysName[key], value);
|
||||
return await _sharedPreferences.setInt(_PreferenceKeysName[key]!, value);
|
||||
}
|
||||
|
||||
int getInt(PreferencesKeyList key) {
|
||||
return _sharedPreferences.getInt(_PreferenceKeysName[key]);
|
||||
int? getInt(PreferencesKeyList key) {
|
||||
return _sharedPreferences.getInt(_PreferenceKeysName[key]!);
|
||||
}
|
||||
|
||||
bool getBool(PreferencesKeyList key, {bool alternative = false}) {
|
||||
final v = _sharedPreferences.getBool(_PreferenceKeysName[key]);
|
||||
final v = _sharedPreferences.getBool(_PreferenceKeysName[key]!);
|
||||
return v == null ? alternative : v;
|
||||
}
|
||||
|
||||
@ -115,7 +115,7 @@ class PreferencesHelper {
|
||||
}
|
||||
}
|
||||
|
||||
PreferencesHelper preferences() {
|
||||
PreferencesHelper? preferences() {
|
||||
if (PreferencesHelper._instance == null)
|
||||
throw Exception("Try to get preference before their initialization!");
|
||||
|
||||
|
@ -21,14 +21,14 @@ const _PushNotificationsAPIMap = {
|
||||
|
||||
class PushNotificationsHelper {
|
||||
/// Get cached status of push notifications
|
||||
static Future<PushNotificationsStatus> getLocalStatus() async {
|
||||
static Future<PushNotificationsStatus?> getLocalStatus() async {
|
||||
final pref = await PreferencesHelper.getInstance();
|
||||
|
||||
if (!pref.containsKey(PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS))
|
||||
return PushNotificationsStatus.UNDEFINED;
|
||||
|
||||
return _PushNotificationsAPIMap[
|
||||
pref.getString(PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS)];
|
||||
pref.getString(PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS)!];
|
||||
}
|
||||
|
||||
/// Refresh local status with information from server
|
||||
@ -47,13 +47,13 @@ class PushNotificationsHelper {
|
||||
response["independent_push_url"]);
|
||||
}
|
||||
|
||||
await (await PreferencesHelper.getInstance()).setString(
|
||||
await (await PreferencesHelper.getInstance())!.setString(
|
||||
PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS, response["status"]);
|
||||
}
|
||||
|
||||
/// Clear local push notifications status
|
||||
static Future<void> clearLocalStatus() async {
|
||||
await (await PreferencesHelper.getInstance())
|
||||
await (await PreferencesHelper.getInstance())!
|
||||
.removeKey(PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS);
|
||||
|
||||
// Stop local refresh notification refresh
|
||||
@ -62,8 +62,8 @@ class PushNotificationsHelper {
|
||||
|
||||
/// Configure push notifications
|
||||
static Future<void> configure(
|
||||
BuildContext context, PushNotificationsStatus newStatus) async {
|
||||
String firebaseToken = "";
|
||||
BuildContext context, PushNotificationsStatus? newStatus) async {
|
||||
String? firebaseToken = "";
|
||||
switch (newStatus) {
|
||||
case PushNotificationsStatus.DISABLED:
|
||||
break;
|
||||
@ -90,8 +90,8 @@ class PushNotificationsHelper {
|
||||
|
||||
/// Set new push notification status on the server
|
||||
static Future<void> setNewStatus(
|
||||
PushNotificationsStatus newStatus, {
|
||||
String firebaseToken = "",
|
||||
PushNotificationsStatus? newStatus, {
|
||||
String? firebaseToken = "",
|
||||
}) async =>
|
||||
await APIRequest.withLogin("push_notifications/configure")
|
||||
.addString(
|
||||
@ -104,6 +104,6 @@ class PushNotificationsHelper {
|
||||
|
||||
/// Is true if possible if push notifications are configurable
|
||||
static bool get arePushNotificationsAvailable =>
|
||||
srvConfig.notificationsPolicy.hasFirebase ||
|
||||
(isAndroid && srvConfig.notificationsPolicy.hasIndependent);
|
||||
srvConfig!.notificationsPolicy.hasFirebase ||
|
||||
(isAndroid && srvConfig!.notificationsPolicy.hasIndependent);
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ class SearchHelper {
|
||||
/// Search for user. This method returns information about the target users
|
||||
///
|
||||
/// Returns information about the target users or null if an error occurred
|
||||
Future<UsersList> searchUser(String query) async {
|
||||
Future<UsersList?> searchUser(String query) async {
|
||||
// Execute the query on the server
|
||||
final response = await APIRequest(
|
||||
uri: "user/search", needLogin: true, args: {"query": query}).exec();
|
||||
@ -21,7 +21,7 @@ class SearchHelper {
|
||||
if (response.code != 200) return null;
|
||||
|
||||
return await UsersHelper()
|
||||
.getUsersInfo(response.getArray().map((f) => cast<int>(f)).toList());
|
||||
.getUsersInfo(response.getArray()!.map((f) => cast<int>(f)).toList());
|
||||
}
|
||||
|
||||
/// Perform a global search
|
||||
@ -31,7 +31,7 @@ class SearchHelper {
|
||||
|
||||
result.assertOk();
|
||||
|
||||
return SearchResultsList()..addAll(result.getArray().map((f) {
|
||||
return SearchResultsList()..addAll(result.getArray()!.map((f) {
|
||||
switch (f["kind"]) {
|
||||
case "user":
|
||||
return SearchResult(id: f["id"], kind: SearchResultKind.USER);
|
||||
|
@ -17,7 +17,7 @@ abstract class SerializableElement<T> extends Comparable<T> {
|
||||
|
||||
abstract class BaseSerializationHelper<T extends SerializableElement> {
|
||||
/// List cache
|
||||
List<T> _cache;
|
||||
List<T>? _cache;
|
||||
|
||||
/// The name of the type of data to serialise
|
||||
String get type;
|
||||
@ -48,12 +48,15 @@ abstract class BaseSerializationHelper<T extends SerializableElement> {
|
||||
try {
|
||||
final file = await _getFilePath();
|
||||
|
||||
if (!await file.exists()) return _cache = [];
|
||||
if (!await file.exists()) {
|
||||
_cache = [];
|
||||
return;
|
||||
}
|
||||
|
||||
final List<dynamic> json = jsonDecode(await file.readAsString());
|
||||
_cache = json.cast<Map<String, dynamic>>().map(parse).toList();
|
||||
|
||||
_cache.sort();
|
||||
_cache!.sort();
|
||||
} catch (e, s) {
|
||||
logError(e, s);
|
||||
print("Failed to read serialized data!");
|
||||
@ -67,8 +70,10 @@ abstract class BaseSerializationHelper<T extends SerializableElement> {
|
||||
|
||||
try {
|
||||
final file = await _getFilePath();
|
||||
await file.writeAsString(jsonEncode(
|
||||
_cache.map((e) => e.toJson()).toList().cast<Map<String, dynamic>>()));
|
||||
await file.writeAsString(jsonEncode(_cache!
|
||||
.map((e) => e.toJson())
|
||||
.toList()
|
||||
.cast<Map<String, dynamic>>()));
|
||||
} catch (e, s) {
|
||||
print("Failed to write file!");
|
||||
logError(e, s);
|
||||
@ -78,7 +83,7 @@ abstract class BaseSerializationHelper<T extends SerializableElement> {
|
||||
/// Get the current list of elements
|
||||
Future<List<T>> getList() async {
|
||||
await _loadCache();
|
||||
return List.from(_cache);
|
||||
return List.from(_cache!);
|
||||
}
|
||||
|
||||
/// Set a new list of conversations
|
||||
@ -90,23 +95,23 @@ abstract class BaseSerializationHelper<T extends SerializableElement> {
|
||||
/// Insert new element
|
||||
Future<void> insert(T el) async {
|
||||
await _loadCache();
|
||||
_cache.add(el);
|
||||
_cache.sort();
|
||||
_cache!.add(el);
|
||||
_cache!.sort();
|
||||
await _saveCache();
|
||||
}
|
||||
|
||||
/// Insert new element
|
||||
Future<void> insertMany(List<T> els) async {
|
||||
await _loadCache();
|
||||
_cache.addAll(els);
|
||||
_cache.sort();
|
||||
_cache!.addAll(els);
|
||||
_cache!.sort();
|
||||
await _saveCache();
|
||||
}
|
||||
|
||||
/// Check if any entry in the last match the predicate
|
||||
Future<bool> any(bool isContained(T t)) async {
|
||||
await _loadCache();
|
||||
return _cache.any((element) => isContained(element));
|
||||
return _cache!.any((element) => isContained(element));
|
||||
}
|
||||
|
||||
Future<bool> has(T el) => any((t) => t == el);
|
||||
@ -114,7 +119,7 @@ abstract class BaseSerializationHelper<T extends SerializableElement> {
|
||||
/// Check if any entry in the last match the predicate
|
||||
Future<T> first(bool filter(T t)) async {
|
||||
await _loadCache();
|
||||
return _cache.firstWhere((element) => filter(element));
|
||||
return _cache!.firstWhere((element) => filter(element));
|
||||
}
|
||||
|
||||
/// Replace an element with another one
|
||||
@ -122,10 +127,10 @@ abstract class BaseSerializationHelper<T extends SerializableElement> {
|
||||
await _loadCache();
|
||||
|
||||
// Insert or replace the element
|
||||
_cache = _cache.where((element) => !isToReplace(element)).toList();
|
||||
_cache.add(newEl);
|
||||
_cache = _cache!.where((element) => !isToReplace(element)).toList();
|
||||
_cache!.add(newEl);
|
||||
|
||||
_cache.sort();
|
||||
_cache!.sort();
|
||||
await _saveCache();
|
||||
}
|
||||
|
||||
@ -133,8 +138,8 @@ abstract class BaseSerializationHelper<T extends SerializableElement> {
|
||||
Future<void> insertOrReplaceElements(List<T> list) async {
|
||||
await _loadCache();
|
||||
|
||||
_cache.removeWhere((element) => list.any((newEl) => element == newEl));
|
||||
_cache.addAll(list);
|
||||
_cache!.removeWhere((element) => list.any((newEl) => element == newEl));
|
||||
_cache!.addAll(list);
|
||||
|
||||
await _saveCache();
|
||||
}
|
||||
@ -142,7 +147,7 @@ abstract class BaseSerializationHelper<T extends SerializableElement> {
|
||||
/// Remove elements
|
||||
Future<void> removeElement(bool isToRemove(T t)) async {
|
||||
await _loadCache();
|
||||
_cache.removeWhere((element) => isToRemove(element));
|
||||
_cache!.removeWhere((element) => isToRemove(element));
|
||||
await _saveCache();
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ import 'package:comunic/models/conversation_message.dart';
|
||||
///
|
||||
/// @author Pierre Hubert
|
||||
|
||||
HashMap<int, ConversationsMessagesSerializationHelper> _instances;
|
||||
HashMap<int?, ConversationsMessagesSerializationHelper>? _instances;
|
||||
|
||||
class ConversationsMessagesSerializationHelper
|
||||
extends BaseSerializationHelper<ConversationMessage> {
|
||||
@ -18,13 +18,13 @@ class ConversationsMessagesSerializationHelper
|
||||
: convID = convID,
|
||||
assert(convID != null);
|
||||
|
||||
factory ConversationsMessagesSerializationHelper(int convID) {
|
||||
factory ConversationsMessagesSerializationHelper(int? convID) {
|
||||
if (_instances == null) _instances = HashMap();
|
||||
|
||||
if (!_instances.containsKey(convID))
|
||||
_instances[convID] = ConversationsMessagesSerializationHelper._(convID);
|
||||
if (!_instances!.containsKey(convID))
|
||||
_instances![convID] = ConversationsMessagesSerializationHelper._(convID!);
|
||||
|
||||
return _instances[convID];
|
||||
return _instances![convID]!;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -28,5 +28,5 @@ class ConversationsSerializationHelper
|
||||
ConversationsList()..addAll(await super.getList());
|
||||
|
||||
/// Get a conversation
|
||||
Future<Conversation> get(int id) => first((t) => t.id == id);
|
||||
Future<Conversation> get(int? id) => first((t) => t.id == id);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import 'package:comunic/models/user.dart';
|
||||
///
|
||||
/// @author Pierre Hubert
|
||||
|
||||
UsersListSerialisationHelper _singleton;
|
||||
UsersListSerialisationHelper? _singleton;
|
||||
|
||||
class UsersListSerialisationHelper extends BaseSerializationHelper<User> {
|
||||
UsersListSerialisationHelper._();
|
||||
@ -13,7 +13,7 @@ class UsersListSerialisationHelper extends BaseSerializationHelper<User> {
|
||||
factory UsersListSerialisationHelper() {
|
||||
if (_singleton == null) _singleton = UsersListSerialisationHelper._();
|
||||
|
||||
return _singleton;
|
||||
return _singleton!;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -23,6 +23,6 @@ class UsersListSerialisationHelper extends BaseSerializationHelper<User> {
|
||||
User parse(Map<String, dynamic> m) => User.fromJson(m);
|
||||
|
||||
/// Remove a user by its ID
|
||||
Future<void> removeUserByID(int userID) =>
|
||||
Future<void> removeUserByID(int? userID) =>
|
||||
removeElement((t) => t.id == userID);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import 'package:version/version.dart';
|
||||
/// @author Pierre Hubert
|
||||
|
||||
class ServerConfigurationHelper {
|
||||
static ServerConfig _config;
|
||||
static ServerConfig? _config;
|
||||
|
||||
/// Make sure the configuration has been correctly loaded
|
||||
static Future<void> ensureLoaded() async {
|
||||
@ -15,7 +15,7 @@ class ServerConfigurationHelper {
|
||||
|
||||
final response =
|
||||
(await APIRequest.withoutLogin("server/config").execWithThrow())
|
||||
.getObject();
|
||||
.getObject()!;
|
||||
|
||||
final banner = response["banner"];
|
||||
final pushNotificationsPolicy = response["push_notifications"];
|
||||
@ -97,7 +97,7 @@ class ServerConfigurationHelper {
|
||||
}
|
||||
|
||||
/// Get current server configuration, throwing if it is not loaded yet
|
||||
static ServerConfig get config {
|
||||
static ServerConfig? get config {
|
||||
if (_config == null)
|
||||
throw Exception(
|
||||
"Trying to access server configuration but it is not loaded yet!");
|
||||
@ -107,6 +107,6 @@ class ServerConfigurationHelper {
|
||||
}
|
||||
|
||||
/// Shortcut for server configuration
|
||||
ServerConfig get srvConfig => ServerConfigurationHelper.config;
|
||||
ServerConfig? get srvConfig => ServerConfigurationHelper.config;
|
||||
|
||||
bool get showBanner => srvConfig.banner != null && srvConfig.banner.visible;
|
||||
bool get showBanner => srvConfig!.banner != null && srvConfig!.banner!.visible;
|
@ -25,7 +25,7 @@ class SettingsHelper {
|
||||
final response =
|
||||
(await APIRequest(uri: "settings/get_general", needLogin: true).exec())
|
||||
.assertOk()
|
||||
.getObject();
|
||||
.getObject()!;
|
||||
|
||||
return GeneralSettings(
|
||||
email: response["email"],
|
||||
@ -88,13 +88,13 @@ class SettingsHelper {
|
||||
(await APIRequest(uri: "settings/get_account_image", needLogin: true)
|
||||
.exec())
|
||||
.assertOk()
|
||||
.getObject();
|
||||
.getObject()!;
|
||||
|
||||
return AccountImageSettings(
|
||||
hasImage: response["has_image"],
|
||||
imageURL: response["image_url"],
|
||||
visibility:
|
||||
_APIAccountImageVisibilityAPILevels[response["visibility"]]);
|
||||
_APIAccountImageVisibilityAPILevels[response["visibility"]]!);
|
||||
}
|
||||
|
||||
/// Upload a new account image
|
||||
@ -143,7 +143,7 @@ class SettingsHelper {
|
||||
/// Delete a custom emoji
|
||||
///
|
||||
/// Throws in case of failure
|
||||
static Future<void> deleteCustomEmoji(int emojiID) async =>
|
||||
static Future<void> deleteCustomEmoji(int? emojiID) async =>
|
||||
(await APIRequest(uri: "settings/delete_custom_emoji", needLogin: true)
|
||||
.addInt("emojiID", emojiID)
|
||||
.exec())
|
||||
@ -175,7 +175,7 @@ class SettingsHelper {
|
||||
(await APIRequest(uri: "settings/get_security", needLogin: true)
|
||||
.addString("password", password)
|
||||
.execWithThrow())
|
||||
.getObject();
|
||||
.getObject()!;
|
||||
|
||||
return SecuritySettings(
|
||||
securityQuestion1: response["security_question_1"],
|
||||
@ -207,7 +207,7 @@ class SettingsHelper {
|
||||
final response =
|
||||
(await APIRequest.withLogin("settings/get_data_conservation_policy")
|
||||
.execWithThrow())
|
||||
.getObject();
|
||||
.getObject()!;
|
||||
|
||||
return DataConservationPolicySettings(
|
||||
inactiveAccountLifeTime: response["inactive_account_lifetime"],
|
||||
@ -223,7 +223,7 @@ class SettingsHelper {
|
||||
///
|
||||
/// Throws in case of failure
|
||||
static Future<void> setDataConservationPolicy(
|
||||
String password, DataConservationPolicySettings newSettings) async {
|
||||
String? password, DataConservationPolicySettings newSettings) async {
|
||||
await APIRequest(
|
||||
uri: "settings/set_data_conservation_policy", needLogin: true)
|
||||
.addString("password", password)
|
||||
|
@ -1,7 +1,6 @@
|
||||
import 'package:comunic/models/api_request.dart';
|
||||
import 'package:comunic/models/survey.dart';
|
||||
import 'package:comunic/models/survey_choice.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
/// Survey helper
|
||||
///
|
||||
@ -13,7 +12,7 @@ class SurveyHelper {
|
||||
apiToSurvey((await APIRequest.withLogin("surveys/get_info")
|
||||
.addInt("postID", postID)
|
||||
.execWithThrow())
|
||||
.getObject());
|
||||
.getObject()!);
|
||||
|
||||
/// Cancel the response of a user to a survey
|
||||
Future<bool> cancelResponse(Survey survey) async {
|
||||
@ -26,7 +25,7 @@ class SurveyHelper {
|
||||
|
||||
/// Send the response of a user to a survey
|
||||
Future<bool> respondToSurvey(
|
||||
{@required Survey survey, @required SurveyChoice choice}) async {
|
||||
{required Survey survey, required SurveyChoice choice}) async {
|
||||
assert(survey != null);
|
||||
assert(choice != null);
|
||||
|
||||
|
@ -31,7 +31,7 @@ class UsersHelper {
|
||||
///
|
||||
/// Return the list of users information in case of success, null in case of
|
||||
/// failure
|
||||
Future<UsersList> _downloadInfo(List<int> users) async {
|
||||
Future<UsersList?> _downloadInfo(List<int?> users) async {
|
||||
// Execute the request
|
||||
final response = await APIRequest(
|
||||
uri: "user/getInfoMultiple",
|
||||
@ -42,7 +42,7 @@ class UsersHelper {
|
||||
if (response.code != 200) return null;
|
||||
|
||||
final list = UsersList();
|
||||
response.getObject().forEach(
|
||||
response.getObject()!.forEach(
|
||||
(k, v) => list.add(
|
||||
User(
|
||||
id: v["userID"],
|
||||
@ -69,7 +69,7 @@ class UsersHelper {
|
||||
|
||||
/// Get users information from a given [Set]. Throws an exception in case
|
||||
/// of failure
|
||||
Future<UsersList> getListWithThrow(Set<int> users,
|
||||
Future<UsersList> getListWithThrow(Set<int?> users,
|
||||
{bool forceDownload = false}) async {
|
||||
final list =
|
||||
await getUsersInfo(users.toList(), forceDownload: forceDownload);
|
||||
@ -82,16 +82,16 @@ class UsersHelper {
|
||||
}
|
||||
|
||||
/// Get information about a single user. Throws in case of failure
|
||||
Future<User> getSingleWithThrow(int user,
|
||||
Future<User> getSingleWithThrow(int? user,
|
||||
{bool forceDownload = false}) async {
|
||||
return (await getListWithThrow(Set<int>()..add(user),
|
||||
return (await getListWithThrow(Set<int?>()..add(user),
|
||||
forceDownload: forceDownload))[0];
|
||||
}
|
||||
|
||||
/// Get users information from a given [Set]
|
||||
///
|
||||
/// Throws in case of failure
|
||||
Future<UsersList> getList(Set<int> users,
|
||||
Future<UsersList> getList(Set<int?> users,
|
||||
{bool forceDownload = false}) async {
|
||||
final list = await getUsersInfo(users.toList());
|
||||
|
||||
@ -104,13 +104,13 @@ class UsersHelper {
|
||||
///
|
||||
/// If [forceDownload] is set to true, the data will always be retrieved from
|
||||
/// the server, otherwise cached data will be used if available
|
||||
Future<UsersList> getUsersInfo(List<int> users,
|
||||
Future<UsersList?> getUsersInfo(List<int?> users,
|
||||
{bool forceDownload = false}) async {
|
||||
List<int> toDownload = [];
|
||||
List<int?> toDownload = [];
|
||||
UsersList list = UsersList();
|
||||
|
||||
// Check cache
|
||||
for (int userID in users) {
|
||||
for (int? userID in users) {
|
||||
if (!forceDownload &&
|
||||
await UsersListSerialisationHelper().any((u) => u.id == userID))
|
||||
list.add(
|
||||
@ -151,7 +151,7 @@ class UsersHelper {
|
||||
throw new GetUserAdvancedUserError(cause);
|
||||
}
|
||||
|
||||
return apiToAdvancedUserInfo(response.getObject());
|
||||
return apiToAdvancedUserInfo(response.getObject()!);
|
||||
}
|
||||
|
||||
/// Parse the list of custom emojies
|
||||
|
@ -7,15 +7,15 @@ import 'package:version/version.dart';
|
||||
/// @author Pierre Hubert
|
||||
|
||||
class VersionHelper {
|
||||
static PackageInfo _info;
|
||||
static PackageInfo? _info;
|
||||
|
||||
static Future<void> ensureLoaded() async {
|
||||
if (!isWeb) _info = await PackageInfo.fromPlatform();
|
||||
}
|
||||
|
||||
/// Get current version information
|
||||
static PackageInfo get info => _info;
|
||||
static PackageInfo? get info => _info;
|
||||
|
||||
/// Get current application version, in parsed format
|
||||
static Version get version => Version.parse(info.version);
|
||||
static Version get version => Version.parse(info!.version);
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'package:comunic/models/api_request.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Virtual directory helper
|
||||
///
|
||||
@ -9,10 +8,10 @@ enum VirtualDirectoryType { USER, GROUP, NONE }
|
||||
|
||||
class VirtualDirectoryResult {
|
||||
final VirtualDirectoryType type;
|
||||
final int id;
|
||||
final int? id;
|
||||
|
||||
const VirtualDirectoryResult({
|
||||
@required this.type,
|
||||
required this.type,
|
||||
this.id,
|
||||
}) : assert(type != null);
|
||||
}
|
||||
@ -30,8 +29,8 @@ class VirtualDirectoryHelper {
|
||||
return VirtualDirectoryResult(type: VirtualDirectoryType.NONE);
|
||||
|
||||
case 200:
|
||||
final id = response.getObject()["id"];
|
||||
final kind = response.getObject()["kind"];
|
||||
final id = response.getObject()!["id"];
|
||||
final kind = response.getObject()!["kind"];
|
||||
switch (kind) {
|
||||
case "user":
|
||||
return VirtualDirectoryResult(
|
||||
|
@ -15,7 +15,7 @@ class WebAppHelper {
|
||||
static Future<MembershipList> getMemberships() async {
|
||||
final response =
|
||||
(await APIRequest.withLogin("webApp/getMemberships").execWithThrow())
|
||||
.getArray();
|
||||
.getArray()!;
|
||||
|
||||
return MembershipList()
|
||||
..addAll(response
|
||||
@ -26,7 +26,7 @@ class WebAppHelper {
|
||||
}
|
||||
|
||||
/// Turn an API entry into a membership entry
|
||||
static Membership _apiToMembership(Map<String, dynamic> entry) {
|
||||
static Membership? _apiToMembership(Map<String, dynamic> entry) {
|
||||
switch (entry["type"]) {
|
||||
case "conversation":
|
||||
return Membership.conversation(
|
||||
|
@ -15,7 +15,7 @@ import 'package:web_socket_channel/web_socket_channel.dart';
|
||||
/// @author Pierre Hubert
|
||||
|
||||
class WebSocketHelper {
|
||||
static WebSocketChannel _ws;
|
||||
static WebSocketChannel? _ws;
|
||||
|
||||
static int _counter = 0;
|
||||
|
||||
@ -23,14 +23,14 @@ class WebSocketHelper {
|
||||
|
||||
/// Check out whether we are currently connected to WebSocket or not
|
||||
static bool isConnected() {
|
||||
return _ws != null && _ws.closeCode == null;
|
||||
return _ws != null && _ws!.closeCode == null;
|
||||
}
|
||||
|
||||
/// Get WebSocket access token
|
||||
static Future<String> _getWsToken() async =>
|
||||
static Future<String?> _getWsToken() async =>
|
||||
(await APIRequest(uri: "ws/token", needLogin: true).exec())
|
||||
.assertOk()
|
||||
.getObject()["token"];
|
||||
.getObject()!["token"];
|
||||
|
||||
/// Connect to WebSocket
|
||||
static connect() async {
|
||||
@ -47,7 +47,7 @@ class WebSocketHelper {
|
||||
// Connect
|
||||
_ws = WebSocketChannel.connect(wsURI);
|
||||
|
||||
_ws.stream.listen(
|
||||
_ws!.stream.listen(
|
||||
// When we got data
|
||||
(data) {
|
||||
print("WS New data: $data");
|
||||
@ -75,7 +75,7 @@ class WebSocketHelper {
|
||||
|
||||
/// Close current WebSocket (if any)
|
||||
static close() {
|
||||
if (isConnected()) _ws.sink.close();
|
||||
if (isConnected()) _ws!.sink.close();
|
||||
}
|
||||
|
||||
/// Send a new message
|
||||
@ -93,7 +93,7 @@ class WebSocketHelper {
|
||||
|
||||
print("WS Send message: $msg");
|
||||
|
||||
_ws.sink.add(msg);
|
||||
_ws!.sink.add(msg);
|
||||
|
||||
_requests[id] = completer;
|
||||
return completer.future;
|
||||
@ -240,11 +240,11 @@ class WebSocketHelper {
|
||||
|
||||
// Handles errors
|
||||
if (msg.title != "success") {
|
||||
completer.completeError(Exception("Could not process request!"));
|
||||
completer!.completeError(Exception("Could not process request!"));
|
||||
return;
|
||||
}
|
||||
|
||||
completer.complete(msg.data);
|
||||
completer!.complete(msg.data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,4 +16,7 @@ class AbstractList<E> extends ListBase<E> {
|
||||
|
||||
@override
|
||||
void operator []=(int index, E value) => _list[index] = value;
|
||||
|
||||
@override
|
||||
void add(E element) => _list.add(element);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ class BaseSet<T> extends SetBase<T> {
|
||||
bool add(T value) => _set.add(value);
|
||||
|
||||
@override
|
||||
bool contains(Object element) => _set.contains(element);
|
||||
bool contains(Object? element) => _set.contains(element);
|
||||
|
||||
@override
|
||||
Iterator<T> get iterator => _set.iterator;
|
||||
@ -20,10 +20,10 @@ class BaseSet<T> extends SetBase<T> {
|
||||
int get length => _set.length;
|
||||
|
||||
@override
|
||||
T lookup(Object element) => _set.lookup(element);
|
||||
T? lookup(Object? element) => _set.lookup(element);
|
||||
|
||||
@override
|
||||
bool remove(Object value) => _set.remove(value);
|
||||
bool remove(Object? value) => _set.remove(value);
|
||||
|
||||
@override
|
||||
Set<T> toSet() => _set.toSet();
|
||||
|
@ -10,10 +10,10 @@ class CallMembersList extends AbstractList<CallMember> {
|
||||
Set<int> get usersID => this.map((f) => f.userID).toSet();
|
||||
|
||||
/// Remove a specific member from this list
|
||||
void removeUser(int userID) => this.removeWhere((f) => f.userID == userID);
|
||||
void removeUser(int? userID) => this.removeWhere((f) => f.userID == userID);
|
||||
|
||||
/// Get the connection of a specific user
|
||||
CallMember getUser(int userID) => this.firstWhere((f) => f.userID == userID);
|
||||
CallMember getUser(int? userID) => this.firstWhere((f) => f.userID == userID);
|
||||
|
||||
/// Extract ready peers from this list
|
||||
CallMembersList get readyPeers =>
|
||||
|
@ -1,31 +1,14 @@
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:comunic/lists/abstract_list.dart';
|
||||
import 'package:comunic/models/conversation_message.dart';
|
||||
|
||||
/// Conversations messages list
|
||||
///
|
||||
/// @author Pierre HUBERT
|
||||
|
||||
class ConversationMessagesList extends ListBase<ConversationMessage> {
|
||||
final List<ConversationMessage> _list = [];
|
||||
|
||||
set length(int v) => _list.length = v;
|
||||
|
||||
int get length => _list.length;
|
||||
|
||||
@override
|
||||
ConversationMessage operator [](int index) {
|
||||
return _list[index];
|
||||
}
|
||||
|
||||
@override
|
||||
void operator []=(int index, ConversationMessage value) {
|
||||
_list[index] = value;
|
||||
}
|
||||
|
||||
class ConversationMessagesList extends AbstractList<ConversationMessage> {
|
||||
/// Get the list of the users ID who own a message in this list
|
||||
Set<int> getUsersID() {
|
||||
final Set<int> users = Set();
|
||||
Set<int?> getUsersID() {
|
||||
final Set<int?> users = Set();
|
||||
|
||||
for (ConversationMessage message in this) users.addAll(message.usersID);
|
||||
|
||||
@ -33,18 +16,18 @@ class ConversationMessagesList extends ListBase<ConversationMessage> {
|
||||
}
|
||||
|
||||
/// Get the ID of the last message present in this list
|
||||
int get lastMessageID {
|
||||
int lastMessageID = 0;
|
||||
int? get lastMessageID {
|
||||
int? lastMessageID = 0;
|
||||
for (ConversationMessage message in this)
|
||||
if (message.id > lastMessageID) lastMessageID = message.id;
|
||||
if (message.id! > lastMessageID!) lastMessageID = message.id;
|
||||
return lastMessageID;
|
||||
}
|
||||
|
||||
/// Get the ID of the first message present in this list
|
||||
int get firstMessageID {
|
||||
int firstMessageID = this[0].id;
|
||||
int? get firstMessageID {
|
||||
int? firstMessageID = this[0].id;
|
||||
for (ConversationMessage message in this)
|
||||
if (message.id < firstMessageID) firstMessageID = message.id;
|
||||
if (message.id! < firstMessageID!) firstMessageID = message.id;
|
||||
return firstMessageID;
|
||||
}
|
||||
|
||||
@ -55,5 +38,5 @@ class ConversationMessagesList extends ListBase<ConversationMessage> {
|
||||
}
|
||||
|
||||
/// Remove a message from this list
|
||||
void removeMsg(int id) => removeWhere((f) => f.id == id);
|
||||
void removeMsg(int? id) => removeWhere((f) => f.id == id);
|
||||
}
|
||||
|
@ -22,12 +22,15 @@ class ConversationsList extends ListBase<Conversation> {
|
||||
/// Get the entire lists of users ID in this list
|
||||
Set<int> get allUsersID {
|
||||
final Set<int> list = Set();
|
||||
forEach((c) => c.members.forEach((member) => list.add(member.userID)));
|
||||
forEach((c) => c.members!.forEach((member) => list.add(member.userID)));
|
||||
return list;
|
||||
}
|
||||
|
||||
/// Get the entire lists of groups ID in this list
|
||||
Set<int> get allGroupsID => where((element) => element.isGroupConversation)
|
||||
Set<int?> get allGroupsID => where((element) => element.isGroupConversation)
|
||||
.map((e) => e.groupID)
|
||||
.toSet();
|
||||
|
||||
@override
|
||||
void add(Conversation element) => _list.add(element);
|
||||
}
|
||||
|
@ -7,8 +7,7 @@ import 'package:comunic/models/custom_emoji.dart';
|
||||
|
||||
class CustomEmojiesList extends AbstractList<CustomEmoji> {
|
||||
/// Check if an emoji, identified by its shortcut, is present in this list
|
||||
bool hasShortcut(String shortcut) =>
|
||||
firstWhere((f) => f.shortcut == shortcut, orElse: () => null) != null;
|
||||
bool hasShortcut(String shortcut) => any((f) => f.shortcut == shortcut);
|
||||
|
||||
/// Serialize this list
|
||||
List<Map<String, dynamic>> toSerializableList() =>
|
||||
|
@ -7,7 +7,7 @@ import 'package:comunic/models/forez_presence.dart';
|
||||
|
||||
class PresenceSet extends BaseSet<Presence> {
|
||||
/// Get the presence of a specific user
|
||||
PresenceSet getForUser(int userID) =>
|
||||
PresenceSet getForUser(int? userID) =>
|
||||
PresenceSet()..addAll(where((element) => element.userID == userID));
|
||||
|
||||
bool containsDate(DateTime dt) => any(
|
||||
@ -24,11 +24,11 @@ class PresenceSet extends BaseSet<Presence> {
|
||||
element.day == dt.day,
|
||||
);
|
||||
|
||||
void toggleDate(DateTime dt, int userID) {
|
||||
void toggleDate(DateTime dt, int? userID) {
|
||||
if (containsDate(dt))
|
||||
removeDate(dt);
|
||||
else
|
||||
add(Presence.fromDateTime(dt, userID));
|
||||
add(Presence.fromDateTime(dt, userID!));
|
||||
}
|
||||
|
||||
int countAtDate(DateTime dt) => where(
|
||||
|
@ -6,23 +6,23 @@ import 'package:comunic/models/group.dart';
|
||||
///
|
||||
/// @author Pierre HUBERT
|
||||
|
||||
class GroupsList extends MapBase<int, Group> {
|
||||
final Map<int, Group> _groups = Map();
|
||||
class GroupsList extends MapBase<int?, Group> {
|
||||
final Map<int?, Group?> _groups = Map();
|
||||
|
||||
@override
|
||||
Group operator [](Object key) => _groups[key];
|
||||
Group? operator [](Object? key) => _groups[key];
|
||||
|
||||
@override
|
||||
void operator []=(int key, Group value) => _groups[key] = value;
|
||||
void operator []=(int? key, Group? value) => _groups[key] = value;
|
||||
|
||||
@override
|
||||
void clear() => _groups.clear();
|
||||
|
||||
@override
|
||||
Iterable<int> get keys => _groups.keys;
|
||||
Iterable<int?> get keys => _groups.keys;
|
||||
|
||||
@override
|
||||
Group remove(Object key) => _groups.remove(key);
|
||||
Group? remove(Object? key) => _groups.remove(key);
|
||||
|
||||
Group getGroup(int id) => this[id];
|
||||
Group? getGroup(int? id) => this[id];
|
||||
}
|
||||
|
@ -5,20 +5,20 @@ import 'package:comunic/models/membership.dart';
|
||||
///
|
||||
/// @author Pierre Hubert
|
||||
|
||||
class MembershipList extends AbstractList<Membership> {
|
||||
class MembershipList extends AbstractList<Membership?> {
|
||||
/// Get the IDs of all the users included in some way in this list
|
||||
Set<int> get usersId {
|
||||
final s = Set<int>();
|
||||
Set<int?> get usersId {
|
||||
final s = Set<int?>();
|
||||
|
||||
forEach((m) {
|
||||
switch (m.type) {
|
||||
switch (m!.type) {
|
||||
case MembershipType.FRIEND:
|
||||
s.add(m.friend.id);
|
||||
s.add(m.friend!.id);
|
||||
break;
|
||||
case MembershipType.GROUP:
|
||||
break;
|
||||
case MembershipType.CONVERSATION:
|
||||
s.addAll(m.conversation.membersID);
|
||||
s.addAll(m.conversation!.membersID);
|
||||
break;
|
||||
}
|
||||
});
|
||||
@ -27,16 +27,16 @@ class MembershipList extends AbstractList<Membership> {
|
||||
}
|
||||
|
||||
/// Get the ID of the groups included in this list
|
||||
Set<int> get groupsId => where((f) => f.type == MembershipType.GROUP)
|
||||
.map((f) => f.groupID)
|
||||
Set<int?> get groupsId => where((f) => f!.type == MembershipType.GROUP)
|
||||
.map((f) => f!.groupID)
|
||||
.toSet();
|
||||
|
||||
/// Remove a friend membership from the list
|
||||
void removeFriend(int friendID) => remove(firstWhere(
|
||||
(f) => f.type == MembershipType.FRIEND && f.friend.id == friendID));
|
||||
(f) => f!.type == MembershipType.FRIEND && f.friend!.id == friendID));
|
||||
|
||||
/// Get the list of conversations of a group
|
||||
Set<Membership> getGroupConversations(int groupID) => where((element) =>
|
||||
element.type == MembershipType.CONVERSATION &&
|
||||
element.conversation.groupID == groupID).toSet();
|
||||
Set<Membership?> getGroupConversations(int groupID) => where((element) =>
|
||||
element!.type == MembershipType.CONVERSATION &&
|
||||
element.conversation!.groupID == groupID).toSet();
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ import 'package:comunic/models/notification.dart';
|
||||
class NotificationsList extends AbstractList<Notification> {
|
||||
/// Get the ID of all the users related to the notifications
|
||||
/// included in the list
|
||||
Set<int> get usersIds {
|
||||
final list = Set<int>();
|
||||
Set<int?> get usersIds {
|
||||
final list = Set<int?>();
|
||||
|
||||
forEach((n) {
|
||||
list.add(n.fromUser);
|
||||
@ -28,8 +28,8 @@ class NotificationsList extends AbstractList<Notification> {
|
||||
|
||||
/// Get the ID of all the groups related to the notifications
|
||||
/// included in the list
|
||||
Set<int> get groupsIds {
|
||||
final list = Set<int>();
|
||||
Set<int?> get groupsIds {
|
||||
final list = Set<int?>();
|
||||
|
||||
forEach((n) {
|
||||
if (n.onElemType == NotificationElementType.GROUP_PAGE)
|
||||
|
@ -22,23 +22,23 @@ class PostsList extends ListBase<Post> {
|
||||
void operator []=(int index, Post value) => _list[index] = value;
|
||||
|
||||
// Get the list of users ID in this set
|
||||
Set<int> get usersID {
|
||||
Set<int> set = Set();
|
||||
Set<int?> get usersID {
|
||||
Set<int?> set = Set();
|
||||
|
||||
forEach((p) {
|
||||
set.add(p.userID);
|
||||
|
||||
if (p.userPageID != null && p.userPageID > 0) set.add(p.userPageID);
|
||||
if (p.userPageID != null && p.userPageID! > 0) set.add(p.userPageID);
|
||||
|
||||
if (p.comments != null) set.addAll(p.comments.usersID);
|
||||
if (p.comments != null) set.addAll(p.comments!.usersID);
|
||||
});
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
/// Get the list of groups in this list of posts
|
||||
Set<int> get groupsID {
|
||||
Set<int> set = Set();
|
||||
Set<int?> get groupsID {
|
||||
Set<int?> set = Set();
|
||||
|
||||
forEach((p) {
|
||||
if (p.isGroupPost) set.add(p.groupID);
|
||||
|
@ -7,8 +7,8 @@ import 'package:comunic/models/unread_conversation.dart';
|
||||
|
||||
class UnreadConversationsList extends AbstractList<UnreadConversation> {
|
||||
/// Get the ID of the users included in this list
|
||||
Set<int> get usersID {
|
||||
final set = Set<int>();
|
||||
Set<int?> get usersID {
|
||||
final set = Set<int?>();
|
||||
forEach((element) {
|
||||
set.addAll(element.conv.membersID);
|
||||
set.addAll(element.message.usersID);
|
||||
@ -17,8 +17,8 @@ class UnreadConversationsList extends AbstractList<UnreadConversation> {
|
||||
}
|
||||
|
||||
/// Get the ID of the groups references ind this list
|
||||
Set<int> get groupsID {
|
||||
final set = Set<int>();
|
||||
Set<int?> get groupsID {
|
||||
final set = Set<int?>();
|
||||
forEach((element) {
|
||||
if (element.conv.isGroupConversation) set.add(element.conv.groupID);
|
||||
});
|
||||
|
@ -24,7 +24,7 @@ class UsersList extends ListBase<User> {
|
||||
}
|
||||
|
||||
/// Find a user with a specific ID
|
||||
User getUser(int userID) {
|
||||
User getUser(int? userID) {
|
||||
for (int i = 0; i < this.length; i++)
|
||||
if (this[i].id == userID) return this[i];
|
||||
|
||||
@ -32,8 +32,11 @@ class UsersList extends ListBase<User> {
|
||||
}
|
||||
|
||||
/// Check if the user is included in this list or not
|
||||
bool hasUser(int userID) => any((f) => f.id == userID);
|
||||
bool hasUser(int? userID) => any((f) => f.id == userID);
|
||||
|
||||
/// Get the list of users ID present in this list
|
||||
List<int> get usersID => List.generate(length, (i) => this[i].id);
|
||||
List<int?> get usersID => List.generate(length, (i) => this[i].id);
|
||||
|
||||
@override
|
||||
void add(User element) => _list.add(element);
|
||||
}
|
||||
|
@ -44,8 +44,8 @@ class ComunicApplication extends StatefulWidget {
|
||||
final PreferencesHelper preferences;
|
||||
|
||||
const ComunicApplication({
|
||||
Key key,
|
||||
@required this.preferences,
|
||||
Key? key,
|
||||
required this.preferences,
|
||||
}) : assert(preferences != null),
|
||||
super(key: key);
|
||||
|
||||
|
@ -11,7 +11,7 @@ import 'package:comunic/utils/flutter_utils.dart';
|
||||
/// Fix HTTPS issue
|
||||
class MyHttpOverride extends HttpOverrides {
|
||||
@override
|
||||
HttpClient createHttpClient(SecurityContext context) {
|
||||
HttpClient createHttpClient(SecurityContext? context) {
|
||||
return super.createHttpClient(context)
|
||||
..badCertificateCallback = (cert, host, port) {
|
||||
return host == "devweb.local"; // Forcefully trust local website
|
||||
|
@ -1,4 +1,4 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
|
||||
/// Account image settings
|
||||
///
|
||||
@ -7,14 +7,14 @@ import 'package:flutter/widgets.dart';
|
||||
enum AccountImageVisibilityLevels { EVERYONE, COMUNIC_USERS, FRIENDS_ONLY }
|
||||
|
||||
class AccountImageSettings {
|
||||
final bool/*!*/ hasImage;
|
||||
final String/*!*/ imageURL;
|
||||
final AccountImageVisibilityLevels/*!*/ visibility;
|
||||
final bool hasImage;
|
||||
final String imageURL;
|
||||
final AccountImageVisibilityLevels visibility;
|
||||
|
||||
const AccountImageSettings({
|
||||
@required this.hasImage,
|
||||
@required this.imageURL,
|
||||
@required this.visibility,
|
||||
required this.hasImage,
|
||||
required this.imageURL,
|
||||
required this.visibility,
|
||||
}) : assert(hasImage != null),
|
||||
assert(imageURL != null),
|
||||
assert(visibility != null);
|
||||
|
@ -1,7 +1,6 @@
|
||||
import 'package:comunic/enums/likes_type.dart';
|
||||
import 'package:comunic/models/conversation.dart';
|
||||
import 'package:comunic/models/like_element.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'group.dart';
|
||||
|
||||
@ -10,34 +9,34 @@ import 'group.dart';
|
||||
/// @author Pierre Hubert
|
||||
|
||||
class AdvancedGroupInfo extends Group implements LikeElement {
|
||||
bool isMembersListPublic;
|
||||
final int timeCreate;
|
||||
bool? isMembersListPublic;
|
||||
final int? timeCreate;
|
||||
String description;
|
||||
String url;
|
||||
int likes;
|
||||
bool userLike;
|
||||
List<Conversation> conversations;
|
||||
bool/*!*/ isForezGroup;
|
||||
List<Conversation>? conversations;
|
||||
bool isForezGroup;
|
||||
|
||||
AdvancedGroupInfo({
|
||||
@required int id,
|
||||
@required String name,
|
||||
@required String iconURL,
|
||||
@required int numberMembers,
|
||||
@required GroupMembershipLevel membershipLevel,
|
||||
@required GroupVisibilityLevel visibilityLevel,
|
||||
@required GroupRegistrationLevel registrationLevel,
|
||||
@required GroupPostCreationLevel postCreationLevel,
|
||||
@required String virtualDirectory,
|
||||
@required bool following,
|
||||
@required this.isMembersListPublic,
|
||||
@required this.timeCreate,
|
||||
@required this.description,
|
||||
@required this.url,
|
||||
@required this.likes,
|
||||
@required this.userLike,
|
||||
@required this.conversations,
|
||||
@required this.isForezGroup,
|
||||
required int id,
|
||||
required String name,
|
||||
required String iconURL,
|
||||
required int numberMembers,
|
||||
required GroupMembershipLevel membershipLevel,
|
||||
required GroupVisibilityLevel visibilityLevel,
|
||||
required GroupRegistrationLevel registrationLevel,
|
||||
required GroupPostCreationLevel postCreationLevel,
|
||||
required String virtualDirectory,
|
||||
required bool following,
|
||||
required this.isMembersListPublic,
|
||||
required this.timeCreate,
|
||||
required this.description,
|
||||
required this.url,
|
||||
required this.likes,
|
||||
required this.userLike,
|
||||
required this.conversations,
|
||||
required this.isForezGroup,
|
||||
}) : assert(isForezGroup != null),
|
||||
super(
|
||||
id: id,
|
||||
|
@ -3,42 +3,41 @@ import 'package:comunic/enums/user_page_visibility.dart';
|
||||
import 'package:comunic/lists/custom_emojies_list.dart';
|
||||
import 'package:comunic/models/like_element.dart';
|
||||
import 'package:comunic/models/user.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
/// Advanced user information
|
||||
///
|
||||
/// @author Pierre HUBERT
|
||||
|
||||
class AdvancedUserInfo extends User implements LikeElement {
|
||||
final String emailAddress;
|
||||
final String/*!*/ publicNote;
|
||||
final bool/*!*/ canPostTexts;
|
||||
final bool/*!*/ isFriendsListPublic;
|
||||
final int/*!*/ numberFriends;
|
||||
final int/*!*/ accountCreationTime;
|
||||
final String/*!*/ personalWebsite;
|
||||
final String location;
|
||||
bool/*!*/ userLike;
|
||||
int/*!*/ likes;
|
||||
final String? emailAddress;
|
||||
final String publicNote;
|
||||
final bool canPostTexts;
|
||||
final bool isFriendsListPublic;
|
||||
final int numberFriends;
|
||||
final int accountCreationTime;
|
||||
final String personalWebsite;
|
||||
final String? location;
|
||||
bool userLike;
|
||||
int likes;
|
||||
|
||||
AdvancedUserInfo({
|
||||
@required int id,
|
||||
@required String firstName,
|
||||
@required String lastName,
|
||||
@required UserPageVisibility pageVisibility,
|
||||
@required String virtualDirectory,
|
||||
@required String accountImageURL,
|
||||
@required CustomEmojiesList customEmojies,
|
||||
@required this.emailAddress,
|
||||
@required this.publicNote,
|
||||
@required this.canPostTexts,
|
||||
@required this.isFriendsListPublic,
|
||||
@required this.numberFriends,
|
||||
@required this.accountCreationTime,
|
||||
@required this.personalWebsite,
|
||||
@required this.location,
|
||||
@required this.userLike,
|
||||
@required this.likes,
|
||||
required int id,
|
||||
required String firstName,
|
||||
required String lastName,
|
||||
required UserPageVisibility pageVisibility,
|
||||
required String? virtualDirectory,
|
||||
required String accountImageURL,
|
||||
required CustomEmojiesList customEmojies,
|
||||
required this.emailAddress,
|
||||
required this.publicNote,
|
||||
required this.canPostTexts,
|
||||
required this.isFriendsListPublic,
|
||||
required this.numberFriends,
|
||||
required this.accountCreationTime,
|
||||
required this.personalWebsite,
|
||||
required this.location,
|
||||
required this.userLike,
|
||||
required this.likes,
|
||||
}) : assert(publicNote != null),
|
||||
assert(canPostTexts != null),
|
||||
assert(isFriendsListPublic != null),
|
||||
@ -60,9 +59,9 @@ class AdvancedUserInfo extends User implements LikeElement {
|
||||
|
||||
bool get hasPersonalWebsite => personalWebsite.isNotEmpty;
|
||||
|
||||
bool get hasEmailAddress => emailAddress != null && emailAddress.isNotEmpty;
|
||||
bool get hasEmailAddress => emailAddress != null && emailAddress!.isNotEmpty;
|
||||
|
||||
bool get hasLocation => location != null && location.isNotEmpty;
|
||||
bool get hasLocation => location != null && location!.isNotEmpty;
|
||||
|
||||
@override
|
||||
LikesType get likeType => LikesType.USER;
|
||||
|
@ -4,7 +4,6 @@ import 'package:comunic/helpers/api_helper.dart';
|
||||
import 'package:comunic/models/api_response.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:http_parser/http_parser.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
/// API Request model
|
||||
///
|
||||
@ -14,8 +13,8 @@ import 'package:meta/meta.dart';
|
||||
|
||||
class BytesFile {
|
||||
final String filename;
|
||||
final List<int> bytes;
|
||||
final MediaType type;
|
||||
final List<int>? bytes;
|
||||
final MediaType? type;
|
||||
|
||||
const BytesFile(
|
||||
this.filename,
|
||||
@ -25,15 +24,15 @@ class BytesFile {
|
||||
}
|
||||
|
||||
class APIRequest {
|
||||
final String/*!*/ uri;
|
||||
final bool/*!*/ needLogin;
|
||||
ProgressCallback progressCallback;
|
||||
CancelToken cancelToken;
|
||||
Map<String, String> args;
|
||||
final String uri;
|
||||
final bool needLogin;
|
||||
ProgressCallback? progressCallback;
|
||||
CancelToken? cancelToken;
|
||||
Map<String, String?>? args;
|
||||
Map<String, File> files = Map();
|
||||
Map<String, BytesFile> bytesFiles = Map();
|
||||
Map<String, BytesFile?> bytesFiles = Map();
|
||||
|
||||
APIRequest({@required this.uri, this.needLogin = false, this.args})
|
||||
APIRequest({required this.uri, this.needLogin = false, this.args})
|
||||
: assert(uri != null),
|
||||
assert(needLogin != null) {
|
||||
if (this.args == null) this.args = Map();
|
||||
@ -51,18 +50,18 @@ class APIRequest {
|
||||
if (args == null) this.args = Map();
|
||||
}
|
||||
|
||||
APIRequest addString(String name, String value) {
|
||||
args[name] = value;
|
||||
APIRequest addString(String name, String? value) {
|
||||
args![name] = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
APIRequest addInt(String name, int value) {
|
||||
args[name] = value.toString();
|
||||
APIRequest addInt(String name, int? value) {
|
||||
args![name] = value.toString();
|
||||
return this;
|
||||
}
|
||||
|
||||
APIRequest addBool(String name, bool value) {
|
||||
args[name] = value ? "true" : "false";
|
||||
args![name] = value ? "true" : "false";
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -71,12 +70,12 @@ class APIRequest {
|
||||
return this;
|
||||
}
|
||||
|
||||
APIRequest addBytesFile(String name, BytesFile file) {
|
||||
APIRequest addBytesFile(String name, BytesFile? file) {
|
||||
this.bytesFiles[name] = file;
|
||||
return this;
|
||||
}
|
||||
|
||||
void addArgs(Map<String, String> newArgs) => args.addAll(newArgs);
|
||||
void addArgs(Map<String, String> newArgs) => args!.addAll(newArgs);
|
||||
|
||||
/// Execute the request
|
||||
Future<APIResponse> exec() async => APIHelper().exec(this);
|
||||
|
@ -5,14 +5,14 @@ import 'dart:convert';
|
||||
/// @author Pierre HUBERT
|
||||
|
||||
class APIResponse {
|
||||
final int/*!*/ code;
|
||||
final String content;
|
||||
final int code;
|
||||
final String? content;
|
||||
|
||||
const APIResponse(this.code, this.content) : assert(code != null);
|
||||
const APIResponse(this.code, this.content);
|
||||
|
||||
List<dynamic> getArray() => jsonDecode(this.content);
|
||||
List<dynamic>? getArray() => jsonDecode(this.content!);
|
||||
|
||||
Map<String, dynamic> getObject() => jsonDecode(this.content);
|
||||
Map<String, dynamic> getObject() => jsonDecode(this.content!);
|
||||
|
||||
/// Check if the request is successful or not
|
||||
bool get isOK => code == 200;
|
||||
|
@ -1,18 +1,18 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
|
||||
/// Application settings
|
||||
///
|
||||
/// @author Pierre Hubert
|
||||
|
||||
class ApplicationPreferences {
|
||||
bool/*!*/ enableDarkMode;
|
||||
bool/*!*/ forceMobileMode;
|
||||
bool/*!*/ showPerformancesOverlay;
|
||||
bool enableDarkMode;
|
||||
bool forceMobileMode;
|
||||
bool showPerformancesOverlay;
|
||||
|
||||
ApplicationPreferences({
|
||||
@required this.enableDarkMode,
|
||||
@required this.forceMobileMode,
|
||||
@required this.showPerformancesOverlay,
|
||||
required this.enableDarkMode,
|
||||
required this.forceMobileMode,
|
||||
required this.showPerformancesOverlay,
|
||||
}) : assert(enableDarkMode != null),
|
||||
assert(forceMobileMode != null),
|
||||
assert(showPerformancesOverlay != null);
|
||||
|
@ -1,14 +1,14 @@
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
|
||||
/// Authentication details
|
||||
///
|
||||
/// @author Pierre HUBERT
|
||||
|
||||
class AuthenticationDetails {
|
||||
final String/*!*/ email;
|
||||
final String/*!*/ password;
|
||||
final String email;
|
||||
final String password;
|
||||
|
||||
const AuthenticationDetails({@required this.email, @required this.password})
|
||||
const AuthenticationDetails({required this.email, required this.password})
|
||||
: assert(email != null),
|
||||
assert(password != null);
|
||||
}
|
||||
|
@ -1,14 +1,13 @@
|
||||
import 'package:comunic/helpers/database/database_contract.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
/// Cache base model
|
||||
///
|
||||
/// @author Pierre HUBERT
|
||||
|
||||
abstract class CacheModel {
|
||||
final int/*!*/ id;
|
||||
final int id;
|
||||
|
||||
const CacheModel({@required this.id}) : assert(id != null);
|
||||
const CacheModel({required this.id}) : assert(id != null);
|
||||
|
||||
/// Initialize a CacheModel from a map
|
||||
CacheModel.fromMap(Map<String, dynamic> map)
|
||||
|
@ -1,14 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
/// Call configuration
|
||||
///
|
||||
/// @author Pierre Hubert
|
||||
|
||||
class CallConfig {
|
||||
final List<String>/*!*/ iceServers;
|
||||
final List<String> iceServers;
|
||||
|
||||
const CallConfig({
|
||||
@required this.iceServers,
|
||||
required this.iceServers,
|
||||
}) : assert(iceServers != null);
|
||||
|
||||
/// Turn this call configuration into the right for the WebRTC plugin
|
||||
|
@ -1,4 +1,3 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||
|
||||
/// Single call member information
|
||||
@ -8,16 +7,16 @@ import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||
enum MemberStatus { JOINED, READY }
|
||||
|
||||
class CallMember {
|
||||
final int/*!*/ userID;
|
||||
MemberStatus/*!*/ status;
|
||||
MediaStream stream;
|
||||
final int userID;
|
||||
MemberStatus status;
|
||||
MediaStream? stream;
|
||||
|
||||
CallMember({
|
||||
@required this.userID,
|
||||
required this.userID,
|
||||
this.status = MemberStatus.JOINED,
|
||||
}) : assert(userID != null),
|
||||
assert(status != null);
|
||||
|
||||
bool get hasVideoStream =>
|
||||
stream != null && stream.getVideoTracks().length > 0;
|
||||
stream != null && stream!.getVideoTracks().length > 0;
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ import 'package:comunic/enums/likes_type.dart';
|
||||
import 'package:comunic/models/displayed_content.dart';
|
||||
import 'package:comunic/models/like_element.dart';
|
||||
import 'package:comunic/utils/account_utils.dart' as account;
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
/// Comments
|
||||
///
|
||||
@ -11,24 +10,24 @@ import 'package:meta/meta.dart';
|
||||
/// @author Pierre HUBERT
|
||||
|
||||
class Comment implements LikeElement {
|
||||
final int/*!*/ id;
|
||||
final int/*!*/ userID;
|
||||
final int/*!*/ postID;
|
||||
final int/*!*/ timeSent;
|
||||
DisplayedString/*!*/ content;
|
||||
final String imageURL;
|
||||
int/*!*/ likes;
|
||||
bool/*!*/ userLike;
|
||||
final int id;
|
||||
final int userID;
|
||||
final int postID;
|
||||
final int timeSent;
|
||||
DisplayedString content;
|
||||
final String? imageURL;
|
||||
int likes;
|
||||
bool userLike;
|
||||
|
||||
Comment({
|
||||
@required this.id,
|
||||
@required this.userID,
|
||||
@required this.postID,
|
||||
@required this.timeSent,
|
||||
@required this.content,
|
||||
@required this.imageURL,
|
||||
@required this.likes,
|
||||
@required this.userLike,
|
||||
required this.id,
|
||||
required this.userID,
|
||||
required this.postID,
|
||||
required this.timeSent,
|
||||
required this.content,
|
||||
required this.imageURL,
|
||||
required this.likes,
|
||||
required this.userLike,
|
||||
}) : assert(id != null),
|
||||
assert(userID != null),
|
||||
assert(postID != null),
|
||||
|
@ -16,27 +16,27 @@ class Config {
|
||||
|
||||
// Theme customization
|
||||
final Color splashBackgroundColor;
|
||||
final Color primaryColor;
|
||||
final Color primaryColorDark;
|
||||
final Color? primaryColor;
|
||||
final Color? primaryColorDark;
|
||||
final String appName;
|
||||
final String appQuickDescription;
|
||||
final Color unreadConversationColor;
|
||||
final Color defaultConversationColor;
|
||||
final String? appQuickDescription;
|
||||
final Color? unreadConversationColor;
|
||||
final Color? defaultConversationColor;
|
||||
|
||||
// Entries for the welcome tour
|
||||
final TourEntriesBuilder toursEntriesBuilder;
|
||||
final TourEntriesBuilder? toursEntriesBuilder;
|
||||
|
||||
// Custom initialization
|
||||
final Future<void> Function() additionalLoading;
|
||||
final Future<void> Function()? additionalLoading;
|
||||
|
||||
// Custom main application route
|
||||
final Widget Function(BuildContext, GlobalKey) mainRouteBuilder;
|
||||
final Widget Function(BuildContext, GlobalKey)? mainRouteBuilder;
|
||||
|
||||
const Config({
|
||||
@required this.apiServerName,
|
||||
@required this.apiServerUri,
|
||||
@required this.apiServerSecure,
|
||||
@required this.clientName,
|
||||
required this.apiServerName,
|
||||
required this.apiServerUri,
|
||||
required this.apiServerSecure,
|
||||
required this.clientName,
|
||||
this.splashBackgroundColor = defaultColor,
|
||||
this.primaryColor,
|
||||
this.primaryColorDark,
|
||||
@ -55,9 +55,9 @@ class Config {
|
||||
assert(appName != null);
|
||||
|
||||
/// Get and set static configuration
|
||||
static Config/*?*/ _config;
|
||||
static Config? _config;
|
||||
|
||||
static Config get() {
|
||||
static Config? get() {
|
||||
return _config;
|
||||
}
|
||||
|
||||
@ -67,6 +67,6 @@ class Config {
|
||||
}
|
||||
|
||||
/// Get the current configuration of the application
|
||||
Config/*!*/ config() {
|
||||
return Config.get();
|
||||
Config config() {
|
||||
return Config.get()!;
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:collection/collection.dart' show IterableExtension;
|
||||
import 'package:comunic/helpers/serialization/base_serialization_helper.dart';
|
||||
import 'package:comunic/models/conversation_member.dart';
|
||||
import 'package:comunic/utils/account_utils.dart';
|
||||
@ -12,28 +13,28 @@ import 'group.dart';
|
||||
enum CallCapabilities { NONE, AUDIO, VIDEO }
|
||||
|
||||
class Conversation extends SerializableElement<Conversation> {
|
||||
final int id;
|
||||
final int lastActivity;
|
||||
final String name;
|
||||
final Color color;
|
||||
final String logoURL;
|
||||
final int groupID;
|
||||
final GroupMembershipLevel groupMinMembershipLevel;
|
||||
final List<ConversationMember> members;
|
||||
final bool canEveryoneAddMembers;
|
||||
final int? id;
|
||||
final int? lastActivity;
|
||||
final String? name;
|
||||
final Color? color;
|
||||
final String? logoURL;
|
||||
final int? groupID;
|
||||
final GroupMembershipLevel? groupMinMembershipLevel;
|
||||
final List<ConversationMember>? members;
|
||||
final bool? canEveryoneAddMembers;
|
||||
final CallCapabilities callCapabilities;
|
||||
final bool isHavingCall;
|
||||
|
||||
Conversation({
|
||||
/*required*/ @required this.id,
|
||||
/*required*/ @required this.lastActivity,
|
||||
@required this.name,
|
||||
@required this.color,
|
||||
@required this.logoURL,
|
||||
@required this.groupID,
|
||||
@required this.groupMinMembershipLevel,
|
||||
/*required*/ @required this.members,
|
||||
/*required*/ @required this.canEveryoneAddMembers,
|
||||
/*required*/ required int this.id,
|
||||
/*required*/ required int this.lastActivity,
|
||||
required this.name,
|
||||
required this.color,
|
||||
required this.logoURL,
|
||||
required this.groupID,
|
||||
required this.groupMinMembershipLevel,
|
||||
/*required*/ required List<ConversationMember> this.members,
|
||||
/*required*/ required bool this.canEveryoneAddMembers,
|
||||
this.callCapabilities = CallCapabilities.NONE,
|
||||
this.isHavingCall = false,
|
||||
}) : assert(id != null),
|
||||
@ -49,7 +50,7 @@ class Conversation extends SerializableElement<Conversation> {
|
||||
|
||||
/// Get current user membership
|
||||
ConversationMember get membership =>
|
||||
members.firstWhere((m) => m.userID == userID());
|
||||
members!.firstWhere((m) => m.userID == userID());
|
||||
|
||||
/// Check out whether current user of the application is an admin
|
||||
bool get isAdmin => membership.isAdmin;
|
||||
@ -61,17 +62,17 @@ class Conversation extends SerializableElement<Conversation> {
|
||||
bool get following => membership.following;
|
||||
|
||||
/// Get the list of members in the conversation
|
||||
Set<int> get membersID => members.map((e) => e.userID).toSet();
|
||||
Set<int?> get membersID => members!.map((e) => e.userID).toSet();
|
||||
|
||||
/// Get the list of admins in the conversation
|
||||
Set<int> get adminsID =>
|
||||
members.where((e) => e.isAdmin).map((e) => e.userID).toSet();
|
||||
Set<int?> get adminsID =>
|
||||
members!.where((e) => e.isAdmin).map((e) => e.userID).toSet();
|
||||
|
||||
/// Get the list of the OTHER members of the conversation (all except current user)
|
||||
Set<int> get otherMembersID => membersID..remove(userID());
|
||||
Set<int?> get otherMembersID => membersID..remove(userID());
|
||||
|
||||
/// Check if the last message has been seen or not
|
||||
bool get sawLastMessage => lastActivity <= membership.lastAccessTime;
|
||||
bool get sawLastMessage => lastActivity! <= membership.lastAccessTime;
|
||||
|
||||
/// Check out whether a conversation is managed or not
|
||||
bool get isManaged => isGroupConversation;
|
||||
@ -86,9 +87,8 @@ class Conversation extends SerializableElement<Conversation> {
|
||||
color = map["color"] == null ? null : Color(map["color"]),
|
||||
logoURL = map["logoURL"],
|
||||
groupID = map["groupID"],
|
||||
groupMinMembershipLevel = GroupMembershipLevel.values.firstWhere(
|
||||
(element) => element.toString() == map["groupMinMembershipLevel"],
|
||||
orElse: () => null),
|
||||
groupMinMembershipLevel = GroupMembershipLevel.values.firstWhereOrNull(
|
||||
(element) => element.toString() == map["groupMinMembershipLevel"]),
|
||||
lastActivity = map["lastActivity"],
|
||||
members = map["members"]
|
||||
.map((el) => ConversationMember.fromJSON(el))
|
||||
@ -109,13 +109,13 @@ class Conversation extends SerializableElement<Conversation> {
|
||||
"groupID": groupID,
|
||||
"groupMinMembershipLevel": groupMinMembershipLevel?.toString(),
|
||||
"lastActivity": lastActivity,
|
||||
"members": members.map((e) => e.toJson()).toList(),
|
||||
"members": members!.map((e) => e.toJson()).toList(),
|
||||
"canEveryoneAddMembers": canEveryoneAddMembers,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
int compareTo(Conversation other) {
|
||||
return other.lastActivity.compareTo(this.lastActivity);
|
||||
return other.lastActivity!.compareTo(this.lastActivity!);
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,22 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
|
||||
/// Conversation member
|
||||
///
|
||||
/// @author Pierre Hubert
|
||||
|
||||
class ConversationMember {
|
||||
final int/*!*/ userID;
|
||||
final int/*!*/ lastMessageSeen;
|
||||
final int/*!*/ lastAccessTime;
|
||||
final bool/*!*/ following;
|
||||
final bool/*!*/ isAdmin;
|
||||
final int userID;
|
||||
final int lastMessageSeen;
|
||||
final int lastAccessTime;
|
||||
final bool following;
|
||||
final bool isAdmin;
|
||||
|
||||
const ConversationMember({
|
||||
/*required*/ @required this.userID,
|
||||
/*required*/ @required this.lastMessageSeen,
|
||||
/*required*/ @required this.lastAccessTime,
|
||||
/*required*/ @required this.following,
|
||||
/*required*/ @required this.isAdmin,
|
||||
/*required*/ required this.userID,
|
||||
/*required*/ required this.lastMessageSeen,
|
||||
/*required*/ required this.lastAccessTime,
|
||||
/*required*/ required this.following,
|
||||
/*required*/ required this.isAdmin,
|
||||
}) : assert(userID != null),
|
||||
assert(lastMessageSeen != null),
|
||||
assert(lastAccessTime != null),
|
||||
|
@ -30,27 +30,27 @@ const _ConversationFileMimeTypeMapping = {
|
||||
};
|
||||
|
||||
class ConversationMessageFile {
|
||||
final String url;
|
||||
final int size;
|
||||
final String name;
|
||||
final String thumbnail;
|
||||
final String type;
|
||||
final String? url;
|
||||
final int? size;
|
||||
final String? name;
|
||||
final String? thumbnail;
|
||||
final String? type;
|
||||
|
||||
const ConversationMessageFile({
|
||||
@required this.url,
|
||||
@required this.size,
|
||||
@required this.name,
|
||||
@required this.thumbnail,
|
||||
@required this.type,
|
||||
required String this.url,
|
||||
required int this.size,
|
||||
required String this.name,
|
||||
required this.thumbnail,
|
||||
required String this.type,
|
||||
}) : assert(url != null),
|
||||
assert(size != null),
|
||||
assert(name != null),
|
||||
assert(type != null);
|
||||
|
||||
/// Get the type of file
|
||||
ConversationMessageFileType get fileType {
|
||||
ConversationMessageFileType? get fileType {
|
||||
if (type != null && _ConversationFileMimeTypeMapping.containsKey(type))
|
||||
return _ConversationFileMimeTypeMapping[type];
|
||||
return _ConversationFileMimeTypeMapping[type!];
|
||||
else
|
||||
return ConversationMessageFileType.OTHER;
|
||||
}
|
||||
@ -102,19 +102,19 @@ enum ConversationServerMessageType {
|
||||
|
||||
class ConversationServerMessage {
|
||||
final ConversationServerMessageType type;
|
||||
final int userID;
|
||||
final int userWhoAdded;
|
||||
final int userAdded;
|
||||
final int userWhoRemoved;
|
||||
final int userRemoved;
|
||||
final int? userID;
|
||||
final int? userWhoAdded;
|
||||
final int? userAdded;
|
||||
final int? userWhoRemoved;
|
||||
final int? userRemoved;
|
||||
|
||||
const ConversationServerMessage({
|
||||
@required this.type,
|
||||
@required this.userID,
|
||||
@required this.userWhoAdded,
|
||||
@required this.userAdded,
|
||||
@required this.userWhoRemoved,
|
||||
@required this.userRemoved,
|
||||
required this.type,
|
||||
required this.userID,
|
||||
required this.userWhoAdded,
|
||||
required this.userAdded,
|
||||
required this.userWhoRemoved,
|
||||
required this.userRemoved,
|
||||
}) : assert(type != null),
|
||||
assert(userID != null ||
|
||||
(type != ConversationServerMessageType.USER_CREATED_CONVERSATION &&
|
||||
@ -124,7 +124,7 @@ class ConversationServerMessage {
|
||||
assert((userWhoRemoved != null && userRemoved != null) ||
|
||||
type != ConversationServerMessageType.USER_REMOVED_ANOTHER_USER);
|
||||
|
||||
Set<int> get usersID {
|
||||
Set<int?> get usersID {
|
||||
switch (type) {
|
||||
case ConversationServerMessageType.USER_CREATED_CONVERSATION:
|
||||
case ConversationServerMessageType.USER_LEFT_CONV:
|
||||
@ -144,26 +144,26 @@ class ConversationServerMessage {
|
||||
throw Exception("Unsupported server message type!");
|
||||
}
|
||||
|
||||
String getText(UsersList list) {
|
||||
String? getText(UsersList? list) {
|
||||
switch (type) {
|
||||
case ConversationServerMessageType.USER_CREATED_CONVERSATION:
|
||||
return tr("%1% created the conversation",
|
||||
args: {"1": list.getUser(userID).fullName});
|
||||
args: {"1": list!.getUser(userID).fullName});
|
||||
|
||||
case ConversationServerMessageType.USER_ADDED_ANOTHER_USER:
|
||||
return tr("%1% added %2% to the conversation", args: {
|
||||
"1": list.getUser(userWhoAdded).fullName,
|
||||
"1": list!.getUser(userWhoAdded).fullName,
|
||||
"2": list.getUser(userAdded).fullName,
|
||||
});
|
||||
|
||||
case ConversationServerMessageType.USER_LEFT_CONV:
|
||||
return tr("%1% left the conversation", args: {
|
||||
"1": list.getUser(userID).fullName,
|
||||
"1": list!.getUser(userID).fullName,
|
||||
});
|
||||
|
||||
case ConversationServerMessageType.USER_REMOVED_ANOTHER_USER:
|
||||
return tr("%1% removed %2% from the conversation", args: {
|
||||
"1": list.getUser(userWhoRemoved).fullName,
|
||||
"1": list!.getUser(userWhoRemoved).fullName,
|
||||
"2": list.getUser(userRemoved).fullName,
|
||||
});
|
||||
}
|
||||
@ -191,29 +191,29 @@ class ConversationServerMessage {
|
||||
}
|
||||
|
||||
class ConversationMessage extends SerializableElement<ConversationMessage> {
|
||||
final int id;
|
||||
final int convID;
|
||||
final int userID;
|
||||
final int timeSent;
|
||||
final int? id;
|
||||
final int? convID;
|
||||
final int? userID;
|
||||
final int? timeSent;
|
||||
final DisplayedString message;
|
||||
final ConversationMessageFile file;
|
||||
final ConversationServerMessage serverMessage;
|
||||
final ConversationMessageFile? file;
|
||||
final ConversationServerMessage? serverMessage;
|
||||
|
||||
ConversationMessage({
|
||||
@required this.id,
|
||||
@required this.convID,
|
||||
@required this.userID,
|
||||
@required this.timeSent,
|
||||
@required this.message,
|
||||
@required this.file,
|
||||
@required this.serverMessage,
|
||||
required int this.id,
|
||||
required int this.convID,
|
||||
required this.userID,
|
||||
required int this.timeSent,
|
||||
required this.message,
|
||||
required this.file,
|
||||
required this.serverMessage,
|
||||
}) : assert(id != null),
|
||||
assert(convID != null),
|
||||
assert(userID != null || serverMessage != null),
|
||||
assert(timeSent != null),
|
||||
assert(message != null || file != null || serverMessage != null);
|
||||
|
||||
DateTime get date => DateTime.fromMillisecondsSinceEpoch(timeSent * 1000);
|
||||
DateTime get date => DateTime.fromMillisecondsSinceEpoch(timeSent! * 1000);
|
||||
|
||||
bool get hasMessage => !message.isNull && message.length > 0;
|
||||
|
||||
@ -224,16 +224,16 @@ class ConversationMessage extends SerializableElement<ConversationMessage> {
|
||||
bool get isServerMessage => serverMessage != null;
|
||||
|
||||
/// Get the list of the ID of the users implied in this message
|
||||
Set<int> get usersID {
|
||||
Set<int?> get usersID {
|
||||
if (userID != null) return Set()..add(userID);
|
||||
|
||||
if (serverMessage != null) return serverMessage.usersID;
|
||||
if (serverMessage != null) return serverMessage!.usersID;
|
||||
return Set();
|
||||
}
|
||||
|
||||
@override
|
||||
int compareTo(ConversationMessage other) {
|
||||
return id.compareTo(other.id);
|
||||
return id!.compareTo(other.id!);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
|
@ -3,12 +3,12 @@
|
||||
/// @author Pierre Hubert
|
||||
|
||||
class CountUnreadNotifications {
|
||||
int notifications;
|
||||
int conversations;
|
||||
int? notifications;
|
||||
int? conversations;
|
||||
|
||||
CountUnreadNotifications({
|
||||
this.notifications,
|
||||
this.conversations,
|
||||
required int this.notifications,
|
||||
required int this.conversations,
|
||||
}) : assert(notifications != null),
|
||||
assert(conversations != null);
|
||||
}
|
||||
|
@ -1,20 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
/// Single custom emoji information
|
||||
///
|
||||
/// @author Pierre Hubert
|
||||
|
||||
class CustomEmoji {
|
||||
final int id;
|
||||
final int userID;
|
||||
final String shortcut;
|
||||
final String url;
|
||||
final int? id;
|
||||
final int? userID;
|
||||
final String? shortcut;
|
||||
final String? url;
|
||||
|
||||
const CustomEmoji({
|
||||
@required this.id,
|
||||
@required this.userID,
|
||||
@required this.shortcut,
|
||||
@required this.url,
|
||||
required int this.id,
|
||||
required int this.userID,
|
||||
required String this.shortcut,
|
||||
required String this.url,
|
||||
}) : assert(id != null),
|
||||
assert(userID != null),
|
||||
assert(shortcut != null),
|
||||
|
@ -3,12 +3,12 @@
|
||||
/// @author Pierre Hubert
|
||||
|
||||
class DataConservationPolicySettings {
|
||||
int inactiveAccountLifeTime;
|
||||
int notificationLifetime;
|
||||
int commentsLifetime;
|
||||
int postsLifetime;
|
||||
int conversationMessagesLifetime;
|
||||
int likesLifetime;
|
||||
int? inactiveAccountLifeTime;
|
||||
int? notificationLifetime;
|
||||
int? commentsLifetime;
|
||||
int? postsLifetime;
|
||||
int? conversationMessagesLifetime;
|
||||
int? likesLifetime;
|
||||
|
||||
DataConservationPolicySettings({
|
||||
this.inactiveAccountLifeTime,
|
||||
|
@ -5,32 +5,32 @@ import 'package:comunic/utils/ui_utils.dart';
|
||||
/// @author Pierre Hubert
|
||||
|
||||
class DisplayedString {
|
||||
String _string;
|
||||
String _parseCache;
|
||||
String? _string;
|
||||
String? _parseCache;
|
||||
|
||||
DisplayedString(this._string);
|
||||
|
||||
int get length => _string.length;
|
||||
int get length => _string!.length;
|
||||
|
||||
bool get isEmpty => _string.isEmpty;
|
||||
bool get isEmpty => _string!.isEmpty;
|
||||
|
||||
bool get isNull => _string == null;
|
||||
|
||||
String get content => _string;
|
||||
String? get content => _string;
|
||||
|
||||
set content(String content) {
|
||||
set content(String? content) {
|
||||
_string = content;
|
||||
_parseCache = null;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _string;
|
||||
return _string!;
|
||||
}
|
||||
|
||||
String get parsedString {
|
||||
String? get parsedString {
|
||||
if (_parseCache == null) {
|
||||
_parseCache = parseEmojies(this._string);
|
||||
_parseCache = parseEmojies(this._string!);
|
||||
}
|
||||
|
||||
return _parseCache;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
/// Single presence information
|
||||
///
|
||||
@ -11,10 +11,10 @@ class Presence {
|
||||
final int day;
|
||||
|
||||
const Presence({
|
||||
@required this.userID,
|
||||
@required this.year,
|
||||
@required this.month,
|
||||
@required this.day,
|
||||
required this.userID,
|
||||
required this.year,
|
||||
required this.month,
|
||||
required this.day,
|
||||
}) : assert(userID != null),
|
||||
assert(year != null),
|
||||
assert(month != null),
|
||||
|
@ -1,7 +1,6 @@
|
||||
import 'package:comunic/helpers/database/database_contract.dart';
|
||||
import 'package:comunic/models/cache_model.dart';
|
||||
import 'package:comunic/utils/date_utils.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
/// Single user Friend information
|
||||
///
|
||||
@ -9,16 +8,16 @@ import 'package:meta/meta.dart';
|
||||
|
||||
class Friend extends CacheModel implements Comparable<Friend> {
|
||||
bool accepted;
|
||||
final int lastActive;
|
||||
final int? lastActive;
|
||||
final bool following;
|
||||
final bool canPostTexts;
|
||||
|
||||
Friend({
|
||||
@required int id,
|
||||
@required this.accepted,
|
||||
@required this.lastActive,
|
||||
@required this.following,
|
||||
@required this.canPostTexts,
|
||||
required int id,
|
||||
required this.accepted,
|
||||
required int this.lastActive,
|
||||
required this.following,
|
||||
required this.canPostTexts,
|
||||
}) : assert(id != null),
|
||||
assert(accepted != null),
|
||||
assert(lastActive != null),
|
||||
@ -27,10 +26,10 @@ class Friend extends CacheModel implements Comparable<Friend> {
|
||||
super(id: id);
|
||||
|
||||
/// Check out whether friend is connected or not
|
||||
bool get isConnected => time() - 30 < lastActive;
|
||||
bool get isConnected => time() - 30 < lastActive!;
|
||||
|
||||
@override
|
||||
int compareTo(Friend other) => other.lastActive.compareTo(lastActive);
|
||||
int compareTo(Friend other) => other.lastActive!.compareTo(lastActive!);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toMap() => {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
|
||||
/// Simple friendship status
|
||||
///
|
||||
@ -12,11 +12,11 @@ class FriendStatus {
|
||||
final bool following;
|
||||
|
||||
const FriendStatus({
|
||||
@required this.userID,
|
||||
@required this.areFriend,
|
||||
@required this.sentRequest,
|
||||
@required this.receivedRequest,
|
||||
@required this.following,
|
||||
required this.userID,
|
||||
required this.areFriend,
|
||||
required this.sentRequest,
|
||||
required this.receivedRequest,
|
||||
required this.following,
|
||||
}) : assert(userID != null),
|
||||
assert(areFriend != null),
|
||||
assert(sentRequest != null),
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'package:comunic/enums/user_page_visibility.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// General settings
|
||||
///
|
||||
@ -18,22 +17,22 @@ class GeneralSettings {
|
||||
String virtualDirectory;
|
||||
String personalWebsite;
|
||||
String publicNote;
|
||||
String location;
|
||||
String? location;
|
||||
|
||||
GeneralSettings({
|
||||
@required this.email,
|
||||
@required this.firstName,
|
||||
@required this.lastName,
|
||||
@required this.pageVisibility,
|
||||
@required this.allowComments,
|
||||
@required this.allowPostsFromFriends,
|
||||
@required this.allowComunicEmails,
|
||||
@required this.publicFriendsList,
|
||||
@required this.publicEmail,
|
||||
@required this.virtualDirectory,
|
||||
@required this.personalWebsite,
|
||||
@required this.publicNote,
|
||||
@required this.location,
|
||||
required this.email,
|
||||
required this.firstName,
|
||||
required this.lastName,
|
||||
required this.pageVisibility,
|
||||
required this.allowComments,
|
||||
required this.allowPostsFromFriends,
|
||||
required this.allowComunicEmails,
|
||||
required this.publicFriendsList,
|
||||
required this.publicEmail,
|
||||
required this.virtualDirectory,
|
||||
required this.personalWebsite,
|
||||
required this.publicNote,
|
||||
required this.location,
|
||||
}) : assert(email != null),
|
||||
assert(firstName != null),
|
||||
assert(lastName != null),
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'package:comunic/utils/intl_utils.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
/// Group information
|
||||
///
|
||||
@ -14,20 +13,20 @@ enum GroupMembershipLevel {
|
||||
VISITOR
|
||||
}
|
||||
|
||||
String/*!*/ membershipToText(GroupMembershipLevel level) {
|
||||
String membershipToText(GroupMembershipLevel level) {
|
||||
switch (level) {
|
||||
case GroupMembershipLevel.ADMINISTRATOR:
|
||||
return tr("Administrator");
|
||||
return tr("Administrator")!;
|
||||
case GroupMembershipLevel.MODERATOR:
|
||||
return tr("Moderator");
|
||||
return tr("Moderator")!;
|
||||
case GroupMembershipLevel.MEMBER:
|
||||
return tr("Member");
|
||||
return tr("Member")!;
|
||||
case GroupMembershipLevel.INVITED:
|
||||
return tr("Invited");
|
||||
return tr("Invited")!;
|
||||
case GroupMembershipLevel.PENDING:
|
||||
return tr("Requested");
|
||||
return tr("Requested")!;
|
||||
case GroupMembershipLevel.VISITOR:
|
||||
return tr("Visitor");
|
||||
return tr("Visitor")!;
|
||||
}
|
||||
throw new Exception("Unreachable statement!");
|
||||
}
|
||||
@ -51,16 +50,16 @@ class Group implements Comparable<Group> {
|
||||
bool following;
|
||||
|
||||
Group({
|
||||
@required this.id,
|
||||
@required this.name,
|
||||
@required this.iconURL,
|
||||
@required this.numberMembers,
|
||||
@required this.membershipLevel,
|
||||
@required this.visibilityLevel,
|
||||
@required this.registrationLevel,
|
||||
@required this.postCreationLevel,
|
||||
@required this.virtualDirectory,
|
||||
@required this.following,
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.iconURL,
|
||||
required this.numberMembers,
|
||||
required this.membershipLevel,
|
||||
required this.visibilityLevel,
|
||||
required this.registrationLevel,
|
||||
required this.postCreationLevel,
|
||||
required this.virtualDirectory,
|
||||
required this.following,
|
||||
}) : assert(id != null),
|
||||
assert(name != null),
|
||||
assert(iconURL != null),
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'package:comunic/models/group.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Group membership information
|
||||
///
|
||||
@ -12,10 +11,10 @@ class GroupMembership {
|
||||
final GroupMembershipLevel level;
|
||||
|
||||
const GroupMembership({
|
||||
@required this.userID,
|
||||
@required this.groupID,
|
||||
@required this.timeCreate,
|
||||
@required this.level,
|
||||
required this.userID,
|
||||
required this.groupID,
|
||||
required this.timeCreate,
|
||||
required this.level,
|
||||
}) : assert(userID != null),
|
||||
assert(groupID != null),
|
||||
assert(timeCreate != null),
|
||||
|
@ -9,6 +9,6 @@ abstract class LikeElement {
|
||||
|
||||
int get id;
|
||||
|
||||
bool userLike;
|
||||
int likes;
|
||||
late bool userLike;
|
||||
late int likes;
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import 'package:comunic/models/conversation.dart';
|
||||
import 'package:comunic/models/friend.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Membership information
|
||||
///
|
||||
@ -10,40 +9,40 @@ enum MembershipType { FRIEND, GROUP, CONVERSATION }
|
||||
|
||||
class Membership {
|
||||
final MembershipType type;
|
||||
final Conversation conversation;
|
||||
final Friend friend;
|
||||
final int groupID;
|
||||
final int groupLastActive;
|
||||
final Conversation? conversation;
|
||||
final Friend? friend;
|
||||
final int? groupID;
|
||||
final int? groupLastActive;
|
||||
|
||||
Membership.conversation(this.conversation)
|
||||
Membership.conversation(Conversation this.conversation)
|
||||
: type = MembershipType.CONVERSATION,
|
||||
friend = null,
|
||||
groupID = null,
|
||||
groupLastActive = null,
|
||||
assert(conversation != null);
|
||||
|
||||
Membership.friend(this.friend)
|
||||
Membership.friend(Friend this.friend)
|
||||
: type = MembershipType.FRIEND,
|
||||
conversation = null,
|
||||
groupID = null,
|
||||
groupLastActive = null,
|
||||
assert(friend != null);
|
||||
|
||||
Membership.group({@required this.groupID, @required this.groupLastActive})
|
||||
Membership.group({required int this.groupID, required int this.groupLastActive})
|
||||
: type = MembershipType.GROUP,
|
||||
conversation = null,
|
||||
friend = null,
|
||||
assert(groupID != null),
|
||||
assert(groupLastActive != null);
|
||||
|
||||
int get lastActive {
|
||||
int? get lastActive {
|
||||
switch (type) {
|
||||
case MembershipType.FRIEND:
|
||||
return friend.lastActive;
|
||||
return friend!.lastActive;
|
||||
case MembershipType.GROUP:
|
||||
return groupLastActive;
|
||||
case MembershipType.CONVERSATION:
|
||||
return conversation.lastActivity;
|
||||
return conversation!.lastActivity;
|
||||
default:
|
||||
throw Exception("Unreachable statment!");
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
|
||||
/// New account information container
|
||||
///
|
||||
@ -11,10 +11,10 @@ class NewAccount {
|
||||
final String password;
|
||||
|
||||
NewAccount({
|
||||
@required this.firstName,
|
||||
@required this.lastName,
|
||||
@required this.email,
|
||||
@required this.password,
|
||||
required this.firstName,
|
||||
required this.lastName,
|
||||
required this.email,
|
||||
required this.password,
|
||||
}) : assert(firstName != null),
|
||||
assert(lastName != null),
|
||||
assert(email != null),
|
||||
|
@ -1,5 +1,3 @@
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import 'api_request.dart';
|
||||
|
||||
/// New comment information
|
||||
@ -9,12 +7,12 @@ import 'api_request.dart';
|
||||
class NewComment {
|
||||
final int postID;
|
||||
final String content;
|
||||
final BytesFile image;
|
||||
final BytesFile? image;
|
||||
|
||||
const NewComment({
|
||||
@required this.postID,
|
||||
@required this.content,
|
||||
@required this.image,
|
||||
required this.postID,
|
||||
required this.content,
|
||||
required this.image,
|
||||
}) : assert(postID != null);
|
||||
|
||||
bool get hasContent => content != null && content.length > 0;
|
||||
|
@ -6,17 +6,17 @@ import 'package:flutter/cupertino.dart';
|
||||
|
||||
class NewConversation {
|
||||
final String name;
|
||||
final List<int> members;
|
||||
final List<int?> members;
|
||||
final bool follow;
|
||||
final bool canEveryoneAddMembers;
|
||||
final Color color;
|
||||
final Color? color;
|
||||
|
||||
const NewConversation({
|
||||
@required this.name,
|
||||
@required this.members,
|
||||
@required this.follow,
|
||||
@required this.canEveryoneAddMembers,
|
||||
@required this.color,
|
||||
required this.name,
|
||||
required this.members,
|
||||
required this.follow,
|
||||
required this.canEveryoneAddMembers,
|
||||
required this.color,
|
||||
}) : assert(members != null),
|
||||
assert(members.length > 0),
|
||||
assert(follow != null),
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'package:comunic/models/api_request.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
/// New conversation message model
|
||||
///
|
||||
@ -9,13 +8,13 @@ import 'package:meta/meta.dart';
|
||||
|
||||
class NewConversationMessage {
|
||||
final int conversationID;
|
||||
final String message;
|
||||
final BytesFile file;
|
||||
final BytesFile thumbnail;
|
||||
final String? message;
|
||||
final BytesFile? file;
|
||||
final BytesFile? thumbnail;
|
||||
|
||||
NewConversationMessage({
|
||||
@required this.conversationID,
|
||||
@required this.message,
|
||||
required this.conversationID,
|
||||
required this.message,
|
||||
this.file,
|
||||
this.thumbnail,
|
||||
}) : assert(conversationID != null),
|
||||
|
@ -9,16 +9,16 @@ class NewConversationsSettings {
|
||||
final bool following;
|
||||
final bool isComplete;
|
||||
final String name;
|
||||
final bool canEveryoneAddMembers;
|
||||
final Color color;
|
||||
final bool? canEveryoneAddMembers;
|
||||
final Color? color;
|
||||
|
||||
const NewConversationsSettings({
|
||||
@required this.convID,
|
||||
@required this.following,
|
||||
@required this.isComplete,
|
||||
@required this.name,
|
||||
@required this.canEveryoneAddMembers,
|
||||
@required this.color,
|
||||
required this.convID,
|
||||
required this.following,
|
||||
required this.isComplete,
|
||||
required this.name,
|
||||
required this.canEveryoneAddMembers,
|
||||
required this.color,
|
||||
}) : assert(convID != null),
|
||||
assert(convID > 0),
|
||||
assert(following != null),
|
||||
|
@ -1,5 +1,3 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'api_request.dart';
|
||||
|
||||
/// New emoji information
|
||||
@ -11,8 +9,8 @@ class NewEmoji {
|
||||
final BytesFile image;
|
||||
|
||||
const NewEmoji({
|
||||
@required this.shortcut,
|
||||
@required this.image,
|
||||
required this.shortcut,
|
||||
required this.image,
|
||||
}) : assert(shortcut != null),
|
||||
assert(image != null);
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'package:comunic/models/group.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
/// This class contains information about a conversation linked to a group
|
||||
/// to create
|
||||
@ -12,9 +11,9 @@ class NewGroupConversation {
|
||||
final GroupMembershipLevel minMembershipLevel;
|
||||
|
||||
const NewGroupConversation({
|
||||
@required this.groupID,
|
||||
@required this.name,
|
||||
@required this.minMembershipLevel,
|
||||
required this.groupID,
|
||||
required this.name,
|
||||
required this.minMembershipLevel,
|
||||
}) : assert(groupID != null),
|
||||
assert(name != null),
|
||||
assert(minMembershipLevel != null);
|
||||
|
@ -1,7 +1,6 @@
|
||||
import 'package:comunic/enums/post_kind.dart';
|
||||
import 'package:comunic/enums/post_target.dart';
|
||||
import 'package:comunic/enums/post_visibility_level.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import 'api_request.dart';
|
||||
|
||||
@ -15,9 +14,9 @@ class NewSurvey {
|
||||
final bool allowNewChoicesCreation;
|
||||
|
||||
const NewSurvey({
|
||||
@required this.question,
|
||||
@required this.answers,
|
||||
@required this.allowNewChoicesCreation,
|
||||
required this.question,
|
||||
required this.answers,
|
||||
required this.allowNewChoicesCreation,
|
||||
}) : assert(question != null),
|
||||
assert(answers.length > 1),
|
||||
assert(allowNewChoicesCreation != null);
|
||||
@ -28,26 +27,26 @@ class NewPost {
|
||||
final int targetID;
|
||||
final PostVisibilityLevel visibility;
|
||||
final String content;
|
||||
final BytesFile image;
|
||||
final String url;
|
||||
final List<int> pdf;
|
||||
final BytesFile? image;
|
||||
final String? url;
|
||||
final List<int>? pdf;
|
||||
final PostKind kind;
|
||||
final DateTime timeEnd;
|
||||
final NewSurvey survey;
|
||||
final String youtubeId;
|
||||
final DateTime? timeEnd;
|
||||
final NewSurvey? survey;
|
||||
final String? youtubeId;
|
||||
|
||||
const NewPost({
|
||||
@required this.target,
|
||||
@required this.targetID,
|
||||
@required this.visibility,
|
||||
@required this.content,
|
||||
@required this.kind,
|
||||
@required this.image,
|
||||
@required this.url,
|
||||
@required this.pdf,
|
||||
@required this.timeEnd,
|
||||
@required this.survey,
|
||||
@required this.youtubeId,
|
||||
required this.target,
|
||||
required this.targetID,
|
||||
required this.visibility,
|
||||
required this.content,
|
||||
required this.kind,
|
||||
required this.image,
|
||||
required this.url,
|
||||
required this.pdf,
|
||||
required this.timeEnd,
|
||||
required this.survey,
|
||||
required this.youtubeId,
|
||||
}) : assert(target != null),
|
||||
assert(targetID != null),
|
||||
assert(visibility != null),
|
||||
|
@ -1,4 +1,4 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
|
||||
/// Notification model
|
||||
///
|
||||
@ -45,19 +45,19 @@ class Notification {
|
||||
final int onElemId;
|
||||
final NotificationElementType onElemType;
|
||||
final NotificationType type;
|
||||
final int fromContainerId;
|
||||
final NotificationElementType fromContainerType;
|
||||
final int? fromContainerId;
|
||||
final NotificationElementType? fromContainerType;
|
||||
|
||||
const Notification({
|
||||
@required this.id,
|
||||
@required this.timeCreate,
|
||||
@required this.seen,
|
||||
@required this.fromUser,
|
||||
@required this.onElemId,
|
||||
@required this.onElemType,
|
||||
@required this.type,
|
||||
@required this.fromContainerId,
|
||||
@required this.fromContainerType,
|
||||
required this.id,
|
||||
required this.timeCreate,
|
||||
required this.seen,
|
||||
required this.fromUser,
|
||||
required this.onElemId,
|
||||
required this.onElemType,
|
||||
required this.type,
|
||||
required this.fromContainerId,
|
||||
required this.fromContainerType,
|
||||
}) : assert(id != null),
|
||||
assert(timeCreate != null),
|
||||
assert(seen != null),
|
||||
|
@ -1,4 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
/// Notifications settings
|
||||
///
|
||||
@ -9,8 +9,8 @@ class NotificationsSettings {
|
||||
bool allowNotificationsSound;
|
||||
|
||||
NotificationsSettings({
|
||||
@required this.allowConversations,
|
||||
@required this.allowNotificationsSound,
|
||||
required this.allowConversations,
|
||||
required this.allowNotificationsSound,
|
||||
}) : assert(allowConversations != null),
|
||||
assert(allowNotificationsSound != null);
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import 'package:comunic/lists/comments_list.dart';
|
||||
import 'package:comunic/models/displayed_content.dart';
|
||||
import 'package:comunic/models/like_element.dart';
|
||||
import 'package:comunic/models/survey.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
/// Single post information
|
||||
///
|
||||
@ -15,50 +14,50 @@ import 'package:meta/meta.dart';
|
||||
class Post implements LikeElement {
|
||||
final int id;
|
||||
final int userID;
|
||||
final int userPageID;
|
||||
final int groupID;
|
||||
final int? userPageID;
|
||||
final int? groupID;
|
||||
final int timeSent;
|
||||
DisplayedString content;
|
||||
PostVisibilityLevel visibilityLevel;
|
||||
final PostKind kind;
|
||||
final int fileSize;
|
||||
final String fileType;
|
||||
final String filePath;
|
||||
final String fileURL;
|
||||
final int timeEnd;
|
||||
final String linkURL;
|
||||
final String linkTitle;
|
||||
final String linkDescription;
|
||||
final String linkImage;
|
||||
final int? fileSize;
|
||||
final String? fileType;
|
||||
final String? filePath;
|
||||
final String? fileURL;
|
||||
final int? timeEnd;
|
||||
final String? linkURL;
|
||||
final String? linkTitle;
|
||||
final String? linkDescription;
|
||||
final String? linkImage;
|
||||
int likes;
|
||||
bool userLike;
|
||||
final UserAccessLevels access;
|
||||
final CommentsList comments;
|
||||
Survey survey;
|
||||
final CommentsList? comments;
|
||||
Survey? survey;
|
||||
|
||||
Post(
|
||||
{@required this.id,
|
||||
@required this.userID,
|
||||
@required this.userPageID,
|
||||
@required this.groupID,
|
||||
@required this.timeSent,
|
||||
@required this.content,
|
||||
@required this.visibilityLevel,
|
||||
@required this.kind,
|
||||
@required this.fileSize,
|
||||
@required this.fileType,
|
||||
@required this.filePath,
|
||||
@required this.fileURL,
|
||||
@required this.timeEnd,
|
||||
@required this.linkURL,
|
||||
@required this.linkTitle,
|
||||
@required this.linkDescription,
|
||||
@required this.linkImage,
|
||||
@required this.likes,
|
||||
@required this.userLike,
|
||||
@required this.access,
|
||||
@required this.comments,
|
||||
@required this.survey})
|
||||
{required this.id,
|
||||
required this.userID,
|
||||
required this.userPageID,
|
||||
required this.groupID,
|
||||
required this.timeSent,
|
||||
required this.content,
|
||||
required this.visibilityLevel,
|
||||
required this.kind,
|
||||
required this.fileSize,
|
||||
required this.fileType,
|
||||
required this.filePath,
|
||||
required this.fileURL,
|
||||
required this.timeEnd,
|
||||
required this.linkURL,
|
||||
required this.linkTitle,
|
||||
required this.linkDescription,
|
||||
required this.linkImage,
|
||||
required this.likes,
|
||||
required this.userLike,
|
||||
required this.access,
|
||||
required this.comments,
|
||||
required this.survey})
|
||||
: assert(id != null),
|
||||
assert(userID != null),
|
||||
assert(userPageID != 0 || groupID != 0),
|
||||
@ -72,7 +71,7 @@ class Post implements LikeElement {
|
||||
assert(userLike != null),
|
||||
assert(access != null);
|
||||
|
||||
bool get isGroupPost => groupID != null && groupID > 0;
|
||||
bool get isGroupPost => groupID != null && groupID! > 0;
|
||||
|
||||
bool get hasContent => content != null && !content.isNull;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
/// Check password reset token result
|
||||
///
|
||||
@ -10,9 +10,9 @@ class ResCheckPasswordToken {
|
||||
final String email;
|
||||
|
||||
const ResCheckPasswordToken({
|
||||
@required this.firstName,
|
||||
@required this.lastName,
|
||||
@required this.email,
|
||||
required this.firstName,
|
||||
required this.lastName,
|
||||
required this.email,
|
||||
}) : assert(firstName != null),
|
||||
assert(lastName != null),
|
||||
assert(email != null);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
|
||||
/// Single search result
|
||||
///
|
||||
@ -11,8 +11,8 @@ class SearchResult {
|
||||
final SearchResultKind kind;
|
||||
|
||||
SearchResult({
|
||||
@required this.id,
|
||||
@required this.kind,
|
||||
required this.id,
|
||||
required this.kind,
|
||||
}) : assert(id != null),
|
||||
assert(kind != null);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
/// Security settings of the user
|
||||
///
|
||||
@ -11,10 +11,10 @@ class SecuritySettings {
|
||||
final String securityAnswer2;
|
||||
|
||||
const SecuritySettings({
|
||||
@required this.securityQuestion1,
|
||||
@required this.securityAnswer1,
|
||||
@required this.securityQuestion2,
|
||||
@required this.securityAnswer2,
|
||||
required this.securityQuestion1,
|
||||
required this.securityAnswer1,
|
||||
required this.securityQuestion2,
|
||||
required this.securityAnswer2,
|
||||
}) : assert(securityQuestion1 != null),
|
||||
assert(securityAnswer1 != null),
|
||||
assert(securityQuestion2 != null),
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'package:comunic/utils/date_utils.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:version/version.dart';
|
||||
|
||||
/// Server static configuration
|
||||
@ -11,8 +10,8 @@ class NotificationsPolicy {
|
||||
final bool hasIndependent;
|
||||
|
||||
const NotificationsPolicy({
|
||||
@required this.hasFirebase,
|
||||
@required this.hasIndependent,
|
||||
required this.hasFirebase,
|
||||
required this.hasIndependent,
|
||||
}) : assert(hasFirebase != null),
|
||||
assert(hasIndependent != null);
|
||||
}
|
||||
@ -28,14 +27,14 @@ class PasswordPolicy {
|
||||
final int minCategoriesPresence;
|
||||
|
||||
const PasswordPolicy({
|
||||
@required this.allowMailInPassword,
|
||||
@required this.allowNameInPassword,
|
||||
@required this.minPasswordLength,
|
||||
@required this.minNumberUpperCaseLetters,
|
||||
@required this.minNumberLowerCaseLetters,
|
||||
@required this.minNumberDigits,
|
||||
@required this.minNumberSpecialCharacters,
|
||||
@required this.minCategoriesPresence,
|
||||
required this.allowMailInPassword,
|
||||
required this.allowNameInPassword,
|
||||
required this.minPasswordLength,
|
||||
required this.minNumberUpperCaseLetters,
|
||||
required this.minNumberLowerCaseLetters,
|
||||
required this.minNumberDigits,
|
||||
required this.minNumberSpecialCharacters,
|
||||
required this.minCategoriesPresence,
|
||||
}) : assert(allowMailInPassword != null),
|
||||
assert(allowNameInPassword != null),
|
||||
assert(minPasswordLength != null),
|
||||
@ -55,12 +54,12 @@ class ServerDataConservationPolicy {
|
||||
final int minLikesLifetime;
|
||||
|
||||
const ServerDataConservationPolicy({
|
||||
@required this.minInactiveAccountLifetime,
|
||||
@required this.minNotificationLifetime,
|
||||
@required this.minCommentsLifetime,
|
||||
@required this.minPostsLifetime,
|
||||
@required this.minConversationMessagesLifetime,
|
||||
@required this.minLikesLifetime,
|
||||
required this.minInactiveAccountLifetime,
|
||||
required this.minNotificationLifetime,
|
||||
required this.minCommentsLifetime,
|
||||
required this.minPostsLifetime,
|
||||
required this.minConversationMessagesLifetime,
|
||||
required this.minLikesLifetime,
|
||||
}) : assert(minInactiveAccountLifetime != null),
|
||||
assert(minNotificationLifetime != null),
|
||||
assert(minCommentsLifetime != null),
|
||||
@ -85,19 +84,19 @@ class ConversationsPolicy {
|
||||
final int maxLogoHeight;
|
||||
|
||||
const ConversationsPolicy({
|
||||
@required this.maxConversationNameLen,
|
||||
@required this.minMessageLen,
|
||||
@required this.maxMessageLen,
|
||||
@required this.allowedFilesType,
|
||||
@required this.filesMaxSize,
|
||||
@required this.writingEventInterval,
|
||||
@required this.writingEventLifetime,
|
||||
@required this.maxMessageImageWidth,
|
||||
@required this.maxMessageImageHeight,
|
||||
@required this.maxThumbnailWidth,
|
||||
@required this.maxThumbnailHeight,
|
||||
@required this.maxLogoWidth,
|
||||
@required this.maxLogoHeight,
|
||||
required this.maxConversationNameLen,
|
||||
required this.minMessageLen,
|
||||
required this.maxMessageLen,
|
||||
required this.allowedFilesType,
|
||||
required this.filesMaxSize,
|
||||
required this.writingEventInterval,
|
||||
required this.writingEventLifetime,
|
||||
required this.maxMessageImageWidth,
|
||||
required this.maxMessageImageHeight,
|
||||
required this.maxThumbnailWidth,
|
||||
required this.maxThumbnailHeight,
|
||||
required this.maxLogoWidth,
|
||||
required this.maxLogoHeight,
|
||||
}) : assert(maxConversationNameLen != null),
|
||||
assert(minMessageLen != null),
|
||||
assert(maxMessageLen != null),
|
||||
@ -121,11 +120,11 @@ class AccountInformationPolicy {
|
||||
final int maxLocationLength;
|
||||
|
||||
const AccountInformationPolicy({
|
||||
@required this.minFirstNameLength,
|
||||
@required this.maxFirstNameLength,
|
||||
@required this.minLastNameLength,
|
||||
@required this.maxLastNameLength,
|
||||
@required this.maxLocationLength,
|
||||
required this.minFirstNameLength,
|
||||
required this.maxFirstNameLength,
|
||||
required this.minLastNameLength,
|
||||
required this.maxLastNameLength,
|
||||
required this.maxLocationLength,
|
||||
}) : assert(minFirstNameLength != null),
|
||||
assert(maxFirstNameLength != null),
|
||||
assert(minLastNameLength != null),
|
||||
@ -136,7 +135,7 @@ class AccountInformationPolicy {
|
||||
enum BannerNature { Information, Warning, Success }
|
||||
|
||||
extension BannerNatureExt on BannerNature {
|
||||
static BannerNature fromStr(String s) {
|
||||
static BannerNature fromStr(String? s) {
|
||||
switch (s) {
|
||||
case "information":
|
||||
return BannerNature.Information;
|
||||
@ -151,22 +150,22 @@ extension BannerNatureExt on BannerNature {
|
||||
|
||||
class Banner {
|
||||
final bool enabled;
|
||||
final int expire;
|
||||
final int? expire;
|
||||
final BannerNature nature;
|
||||
final Map<String, String> message;
|
||||
final String link;
|
||||
final String? link;
|
||||
|
||||
const Banner({
|
||||
@required this.enabled,
|
||||
@required this.expire,
|
||||
@required this.nature,
|
||||
@required this.message,
|
||||
@required this.link,
|
||||
required this.enabled,
|
||||
required this.expire,
|
||||
required this.nature,
|
||||
required this.message,
|
||||
required this.link,
|
||||
}) : assert(enabled != null),
|
||||
assert(nature != null),
|
||||
assert(message != null);
|
||||
|
||||
bool get visible => enabled && (expire == null || expire > time());
|
||||
bool get visible => enabled && (expire == null || expire! > time());
|
||||
}
|
||||
|
||||
class ServerConfig {
|
||||
@ -176,7 +175,7 @@ class ServerConfig {
|
||||
final String contactEmail;
|
||||
final String playStoreURL;
|
||||
final String androidDirectDownloadURL;
|
||||
final Banner banner;
|
||||
final Banner? banner;
|
||||
final NotificationsPolicy notificationsPolicy;
|
||||
final PasswordPolicy passwordPolicy;
|
||||
final ServerDataConservationPolicy dataConservationPolicy;
|
||||
@ -184,18 +183,18 @@ class ServerConfig {
|
||||
final AccountInformationPolicy accountInformationPolicy;
|
||||
|
||||
const ServerConfig({
|
||||
@required this.minSupportedMobileVersion,
|
||||
@required this.termsURL,
|
||||
@required this.privacyPolicyURL,
|
||||
@required this.contactEmail,
|
||||
@required this.playStoreURL,
|
||||
@required this.androidDirectDownloadURL,
|
||||
@required this.banner,
|
||||
@required this.notificationsPolicy,
|
||||
@required this.passwordPolicy,
|
||||
@required this.dataConservationPolicy,
|
||||
@required this.conversationsPolicy,
|
||||
@required this.accountInformationPolicy,
|
||||
required this.minSupportedMobileVersion,
|
||||
required this.termsURL,
|
||||
required this.privacyPolicyURL,
|
||||
required this.contactEmail,
|
||||
required this.playStoreURL,
|
||||
required this.androidDirectDownloadURL,
|
||||
required this.banner,
|
||||
required this.notificationsPolicy,
|
||||
required this.passwordPolicy,
|
||||
required this.dataConservationPolicy,
|
||||
required this.conversationsPolicy,
|
||||
required this.accountInformationPolicy,
|
||||
}) : assert(minSupportedMobileVersion != null),
|
||||
assert(termsURL != null),
|
||||
assert(privacyPolicyURL != null),
|
||||
|
@ -1,6 +1,5 @@
|
||||
import 'package:comunic/models/survey_choice.dart';
|
||||
import 'package:comunic/utils/account_utils.dart' as account;
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
/// Survey information
|
||||
///
|
||||
@ -17,14 +16,14 @@ class Survey {
|
||||
bool allowNewChoicesCreation;
|
||||
|
||||
Survey({
|
||||
@required this.id,
|
||||
@required this.userID,
|
||||
@required this.postID,
|
||||
@required this.creationTime,
|
||||
@required this.question,
|
||||
@required this.userChoice,
|
||||
@required this.choices,
|
||||
@required this.allowNewChoicesCreation,
|
||||
required this.id,
|
||||
required this.userID,
|
||||
required this.postID,
|
||||
required this.creationTime,
|
||||
required this.question,
|
||||
required this.userChoice,
|
||||
required this.choices,
|
||||
required this.allowNewChoicesCreation,
|
||||
}) : assert(id != null),
|
||||
assert(userID != null),
|
||||
assert(postID != null),
|
||||
@ -43,14 +42,14 @@ class Survey {
|
||||
bool get canBlockNewChoicesCreation =>
|
||||
allowNewChoicesCreation && account.userID() == this.userID;
|
||||
|
||||
SurveyChoice get userResponse {
|
||||
SurveyChoice? get userResponse {
|
||||
if (!hasResponded) return null;
|
||||
|
||||
return choices.firstWhere((e) => e.id == userChoice);
|
||||
}
|
||||
|
||||
void cancelUserResponse() {
|
||||
if (hasResponded) userResponse.responses--;
|
||||
if (hasResponded) userResponse!.responses--;
|
||||
userChoice = 0;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
|
||||
/// Single survey choice
|
||||
///
|
||||
@ -10,9 +10,9 @@ class SurveyChoice {
|
||||
int responses;
|
||||
|
||||
SurveyChoice({
|
||||
@required this.id,
|
||||
@required this.name,
|
||||
@required this.responses,
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.responses,
|
||||
}) : assert(id != null),
|
||||
assert(name != null),
|
||||
assert(responses != null);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user