mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-12-25 04:18:51 +00:00
Start to build report dialog
This commit is contained in:
parent
512b058d34
commit
80a1c4e0c4
28
lib/enums/report_target_type.dart
Normal file
28
lib/enums/report_target_type.dart
Normal file
@ -0,0 +1,28 @@
|
||||
/// What kind of content that can be reported
|
||||
enum ReportTargetType {
|
||||
Post,
|
||||
Comment,
|
||||
Conversation,
|
||||
ConversationMessage,
|
||||
User,
|
||||
Group
|
||||
}
|
||||
|
||||
extension ReportTargetExt on ReportTargetType {
|
||||
String get apiId {
|
||||
switch (this) {
|
||||
case ReportTargetType.Post:
|
||||
return "post";
|
||||
case ReportTargetType.Comment:
|
||||
return "comment";
|
||||
case ReportTargetType.Conversation:
|
||||
return "conversation";
|
||||
case ReportTargetType.ConversationMessage:
|
||||
return "conversation_message";
|
||||
case ReportTargetType.User:
|
||||
return "user";
|
||||
case ReportTargetType.Group:
|
||||
return "group";
|
||||
}
|
||||
}
|
||||
}
|
@ -23,77 +23,88 @@ class ServerConfigurationHelper {
|
||||
final dataConservationPolicy = response["data_conservation_policy"];
|
||||
final conversationsPolicy = response["conversations_policy"];
|
||||
final accountInformationPolicy = response["account_info_policy"];
|
||||
final reportPolicy = response["report_policy"];
|
||||
|
||||
_config = ServerConfig(
|
||||
minSupportedMobileVersion:
|
||||
Version.parse(response["min_supported_mobile_version"]),
|
||||
termsURL: response["terms_url"],
|
||||
privacyPolicyURL: response["privacy_policy_url"],
|
||||
contactEmail: response["contact_email"],
|
||||
playStoreURL: response["play_store_url"],
|
||||
androidDirectDownloadURL: response["android_direct_download_url"],
|
||||
banner: banner == null
|
||||
? null
|
||||
: Banner(
|
||||
enabled: banner["enabled"],
|
||||
expire: banner["expire"],
|
||||
nature: BannerNatureExt.fromStr(banner["nature"]),
|
||||
message: Map<String, dynamic>.from(banner["message"])
|
||||
.map((key, value) => MapEntry(key, value.toString())),
|
||||
link: banner["link"]),
|
||||
notificationsPolicy: NotificationsPolicy(
|
||||
hasFirebase: pushNotificationsPolicy["has_firebase"],
|
||||
hasIndependent: pushNotificationsPolicy["has_independent"],
|
||||
),
|
||||
passwordPolicy: PasswordPolicy(
|
||||
allowMailInPassword: passwordPolicy["allow_email_in_password"],
|
||||
allowNameInPassword: passwordPolicy["allow_name_in_password"],
|
||||
minPasswordLength: passwordPolicy["min_password_length"],
|
||||
minNumberUpperCaseLetters:
|
||||
passwordPolicy["min_number_upper_case_letters"],
|
||||
minNumberLowerCaseLetters:
|
||||
passwordPolicy["min_number_lower_case_letters"],
|
||||
minNumberDigits: passwordPolicy["min_number_digits"],
|
||||
minNumberSpecialCharacters:
|
||||
passwordPolicy["min_number_special_characters"],
|
||||
minCategoriesPresence: passwordPolicy["min_categories_presence"],
|
||||
),
|
||||
dataConservationPolicy: ServerDataConservationPolicy(
|
||||
minInactiveAccountLifetime:
|
||||
dataConservationPolicy["min_inactive_account_lifetime"],
|
||||
minNotificationLifetime:
|
||||
dataConservationPolicy["min_notification_lifetime"],
|
||||
minCommentsLifetime: dataConservationPolicy["min_comments_lifetime"],
|
||||
minPostsLifetime: dataConservationPolicy["min_posts_lifetime"],
|
||||
minConversationMessagesLifetime:
|
||||
dataConservationPolicy["min_conversation_messages_lifetime"],
|
||||
minLikesLifetime: dataConservationPolicy["min_likes_lifetime"],
|
||||
),
|
||||
conversationsPolicy: ConversationsPolicy(
|
||||
maxConversationNameLen:
|
||||
conversationsPolicy["max_conversation_name_len"],
|
||||
minMessageLen: conversationsPolicy["min_message_len"],
|
||||
maxMessageLen: conversationsPolicy["max_message_len"],
|
||||
allowedFilesType:
|
||||
conversationsPolicy["allowed_files_type"].cast<String>(),
|
||||
filesMaxSize: conversationsPolicy["files_max_size"],
|
||||
writingEventInterval: conversationsPolicy["writing_event_interval"],
|
||||
writingEventLifetime: conversationsPolicy["writing_event_lifetime"],
|
||||
maxMessageImageWidth: conversationsPolicy["max_message_image_width"],
|
||||
maxMessageImageHeight: conversationsPolicy["max_message_image_height"],
|
||||
maxThumbnailWidth: conversationsPolicy["max_thumbnail_width"],
|
||||
maxThumbnailHeight: conversationsPolicy["max_thumbnail_height"],
|
||||
maxLogoWidth: conversationsPolicy["max_logo_width"],
|
||||
maxLogoHeight: conversationsPolicy["max_logo_height"],
|
||||
),
|
||||
accountInformationPolicy: AccountInformationPolicy(
|
||||
minFirstNameLength: accountInformationPolicy["min_first_name_length"],
|
||||
maxFirstNameLength: accountInformationPolicy["max_first_name_length"],
|
||||
minLastNameLength: accountInformationPolicy["min_last_name_length"],
|
||||
maxLastNameLength: accountInformationPolicy["max_last_name_length"],
|
||||
maxLocationLength: accountInformationPolicy["max_location_length"],
|
||||
),
|
||||
);
|
||||
minSupportedMobileVersion:
|
||||
Version.parse(response["min_supported_mobile_version"]),
|
||||
termsURL: response["terms_url"],
|
||||
privacyPolicyURL: response["privacy_policy_url"],
|
||||
contactEmail: response["contact_email"],
|
||||
playStoreURL: response["play_store_url"],
|
||||
androidDirectDownloadURL: response["android_direct_download_url"],
|
||||
banner: banner == null
|
||||
? null
|
||||
: Banner(
|
||||
enabled: banner["enabled"],
|
||||
expire: banner["expire"],
|
||||
nature: BannerNatureExt.fromStr(banner["nature"]),
|
||||
message: Map<String, dynamic>.from(banner["message"])
|
||||
.map((key, value) => MapEntry(key, value.toString())),
|
||||
link: banner["link"]),
|
||||
notificationsPolicy: NotificationsPolicy(
|
||||
hasFirebase: pushNotificationsPolicy["has_firebase"],
|
||||
hasIndependent: pushNotificationsPolicy["has_independent"],
|
||||
),
|
||||
passwordPolicy: PasswordPolicy(
|
||||
allowMailInPassword: passwordPolicy["allow_email_in_password"],
|
||||
allowNameInPassword: passwordPolicy["allow_name_in_password"],
|
||||
minPasswordLength: passwordPolicy["min_password_length"],
|
||||
minNumberUpperCaseLetters:
|
||||
passwordPolicy["min_number_upper_case_letters"],
|
||||
minNumberLowerCaseLetters:
|
||||
passwordPolicy["min_number_lower_case_letters"],
|
||||
minNumberDigits: passwordPolicy["min_number_digits"],
|
||||
minNumberSpecialCharacters:
|
||||
passwordPolicy["min_number_special_characters"],
|
||||
minCategoriesPresence: passwordPolicy["min_categories_presence"],
|
||||
),
|
||||
dataConservationPolicy: ServerDataConservationPolicy(
|
||||
minInactiveAccountLifetime:
|
||||
dataConservationPolicy["min_inactive_account_lifetime"],
|
||||
minNotificationLifetime:
|
||||
dataConservationPolicy["min_notification_lifetime"],
|
||||
minCommentsLifetime: dataConservationPolicy["min_comments_lifetime"],
|
||||
minPostsLifetime: dataConservationPolicy["min_posts_lifetime"],
|
||||
minConversationMessagesLifetime:
|
||||
dataConservationPolicy["min_conversation_messages_lifetime"],
|
||||
minLikesLifetime: dataConservationPolicy["min_likes_lifetime"],
|
||||
),
|
||||
conversationsPolicy: ConversationsPolicy(
|
||||
maxConversationNameLen:
|
||||
conversationsPolicy["max_conversation_name_len"],
|
||||
minMessageLen: conversationsPolicy["min_message_len"],
|
||||
maxMessageLen: conversationsPolicy["max_message_len"],
|
||||
allowedFilesType:
|
||||
conversationsPolicy["allowed_files_type"].cast<String>(),
|
||||
filesMaxSize: conversationsPolicy["files_max_size"],
|
||||
writingEventInterval: conversationsPolicy["writing_event_interval"],
|
||||
writingEventLifetime: conversationsPolicy["writing_event_lifetime"],
|
||||
maxMessageImageWidth: conversationsPolicy["max_message_image_width"],
|
||||
maxMessageImageHeight:
|
||||
conversationsPolicy["max_message_image_height"],
|
||||
maxThumbnailWidth: conversationsPolicy["max_thumbnail_width"],
|
||||
maxThumbnailHeight: conversationsPolicy["max_thumbnail_height"],
|
||||
maxLogoWidth: conversationsPolicy["max_logo_width"],
|
||||
maxLogoHeight: conversationsPolicy["max_logo_height"],
|
||||
),
|
||||
accountInformationPolicy: AccountInformationPolicy(
|
||||
minFirstNameLength: accountInformationPolicy["min_first_name_length"],
|
||||
maxFirstNameLength: accountInformationPolicy["max_first_name_length"],
|
||||
minLastNameLength: accountInformationPolicy["min_last_name_length"],
|
||||
maxLastNameLength: accountInformationPolicy["max_last_name_length"],
|
||||
maxLocationLength: accountInformationPolicy["max_location_length"],
|
||||
),
|
||||
reportPolicy: reportPolicy == null
|
||||
? null
|
||||
: ReportPolicy(
|
||||
causes: List.from(reportPolicy["causes"]
|
||||
.map((cause) => ReportCause(
|
||||
id: cause["id"],
|
||||
label: new Map<String, String>.from(cause["label"])))
|
||||
.toList()),
|
||||
maxCommentLength: reportPolicy["max_comment_length"],
|
||||
));
|
||||
}
|
||||
|
||||
/// Get current server configuration, throwing if it is not loaded yet
|
||||
@ -109,4 +120,4 @@ class ServerConfigurationHelper {
|
||||
/// Shortcut for server configuration
|
||||
ServerConfig? get srvConfig => ServerConfigurationHelper.config;
|
||||
|
||||
bool get showBanner => srvConfig!.banner != null && srvConfig!.banner!.visible;
|
||||
bool get showBanner => srvConfig!.banner != null && srvConfig!.banner!.visible;
|
||||
|
8
lib/models/report_target.dart
Normal file
8
lib/models/report_target.dart
Normal file
@ -0,0 +1,8 @@
|
||||
import 'package:comunic/enums/report_target_type.dart';
|
||||
|
||||
class ReportTarget {
|
||||
final ReportTargetType type;
|
||||
final int targetId;
|
||||
|
||||
const ReportTarget(this.type, this.targetId);
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import 'package:comunic/utils/date_utils.dart';
|
||||
import 'package:comunic/utils/intl_utils.dart';
|
||||
import 'package:version/version.dart';
|
||||
|
||||
/// Server static configuration
|
||||
@ -137,6 +138,23 @@ class Banner {
|
||||
bool get visible => enabled && (expire == null || expire! > time());
|
||||
}
|
||||
|
||||
class ReportCause {
|
||||
final String id;
|
||||
final Map<String, String> label;
|
||||
|
||||
const ReportCause({required this.id, required this.label});
|
||||
|
||||
String get localeLabel =>
|
||||
label.containsKey(shortLang) ? label[shortLang]! : label["en"]!;
|
||||
}
|
||||
|
||||
class ReportPolicy {
|
||||
final List<ReportCause> causes;
|
||||
final int maxCommentLength;
|
||||
|
||||
const ReportPolicy({required this.causes, required this.maxCommentLength});
|
||||
}
|
||||
|
||||
class ServerConfig {
|
||||
final Version minSupportedMobileVersion;
|
||||
final String termsURL;
|
||||
@ -150,6 +168,7 @@ class ServerConfig {
|
||||
final ServerDataConservationPolicy dataConservationPolicy;
|
||||
final ConversationsPolicy conversationsPolicy;
|
||||
final AccountInformationPolicy accountInformationPolicy;
|
||||
final ReportPolicy? reportPolicy;
|
||||
|
||||
const ServerConfig({
|
||||
required this.minSupportedMobileVersion,
|
||||
@ -164,5 +183,8 @@ class ServerConfig {
|
||||
required this.dataConservationPolicy,
|
||||
required this.conversationsPolicy,
|
||||
required this.accountInformationPolicy,
|
||||
required this.reportPolicy,
|
||||
});
|
||||
|
||||
bool get isReportingEnabled => this.reportPolicy != null;
|
||||
}
|
||||
|
80
lib/ui/dialogs/report_dialog.dart
Normal file
80
lib/ui/dialogs/report_dialog.dart
Normal file
@ -0,0 +1,80 @@
|
||||
import 'package:comunic/helpers/server_config_helper.dart';
|
||||
import 'package:comunic/models/report_target.dart';
|
||||
import 'package:comunic/models/server_config.dart';
|
||||
import 'package:comunic/ui/widgets/dialogs/cancel_dialog_button.dart';
|
||||
import 'package:comunic/utils/intl_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
enum _Status { ChooseCause, GiveComment, Sending }
|
||||
|
||||
/// Show a dialog to report some content
|
||||
Future<void> showReportDialog({
|
||||
required BuildContext ctx,
|
||||
required ReportTarget target,
|
||||
}) async {
|
||||
await showDialog(
|
||||
context: ctx,
|
||||
builder: (ctx) => _ReportDialog(
|
||||
target: target,
|
||||
));
|
||||
}
|
||||
|
||||
class _ReportDialog extends StatefulWidget {
|
||||
final ReportTarget target;
|
||||
|
||||
const _ReportDialog({Key? key, required this.target}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<_ReportDialog> createState() => _ReportDialogState();
|
||||
}
|
||||
|
||||
class _ReportDialogState extends State<_ReportDialog> {
|
||||
var _cause = srvConfig!.reportPolicy!.causes.length - 1;
|
||||
var _status = _Status.ChooseCause;
|
||||
|
||||
List<ReportCause> get _causes => srvConfig!.reportPolicy!.causes;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text(tr("Report abuse")!),
|
||||
content: Container(width: 100, height: 200, child: _buildContent()),
|
||||
actions: _status == _Status.Sending
|
||||
? []
|
||||
: [
|
||||
CancelDialogButton(),
|
||||
MaterialButton(
|
||||
onPressed: null,
|
||||
child: Text(
|
||||
(_status == _Status.ChooseCause ? tr("Next")! : tr("Send")!)
|
||||
.toUpperCase()),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildContent() {
|
||||
if (_status == _Status.Sending)
|
||||
return Center(child: CircularProgressIndicator());
|
||||
|
||||
if (_status == _Status.ChooseCause)
|
||||
return Column(
|
||||
children: [
|
||||
Text(tr("Please choose the reason of your report (you can scroll to access all reasons):")!),
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemBuilder: (c, i) => RadioListTile(
|
||||
dense: false,
|
||||
title: Text(_causes[i].localeLabel),
|
||||
value: i,
|
||||
groupValue: _cause,
|
||||
onChanged: (_i) => setState(() => _cause = i)),
|
||||
itemCount: _causes.length,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
throw Exception("todo");
|
||||
}
|
||||
}
|
@ -1,10 +1,13 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:comunic/enums/report_target_type.dart';
|
||||
import 'package:comunic/helpers/friends_helper.dart';
|
||||
import 'package:comunic/helpers/users_helper.dart';
|
||||
import 'package:comunic/lists/friends_list.dart';
|
||||
import 'package:comunic/lists/users_list.dart';
|
||||
import 'package:comunic/models/friend.dart';
|
||||
import 'package:comunic/models/report_target.dart';
|
||||
import 'package:comunic/ui/dialogs/report_dialog.dart';
|
||||
import 'package:comunic/ui/tiles/accepted_friend_tile.dart';
|
||||
import 'package:comunic/ui/tiles/pending_friend_tile.dart';
|
||||
import 'package:comunic/ui/widgets/safe_state.dart';
|
||||
@ -151,11 +154,13 @@ class _FriendsListScreenState extends SafeState<FriendsListScreen> {
|
||||
onOpenPrivateConversation: _openPrivateConversation,
|
||||
onSetFollowing: _setFollowingFriend,
|
||||
onRequestDelete: _deleteFriend,
|
||||
onReportFriend: _reportFriend,
|
||||
)
|
||||
: PendingFriendTile(
|
||||
friend: _friendsList![i],
|
||||
user: _usersInfo.getUser(_friendsList![i].id),
|
||||
onRespond: _respondRequest,
|
||||
onReport: _reportFriend,
|
||||
);
|
||||
}),
|
||||
),
|
||||
@ -216,6 +221,10 @@ class _FriendsListScreenState extends SafeState<FriendsListScreen> {
|
||||
_refreshList();
|
||||
}
|
||||
|
||||
/// Report a friend
|
||||
Future<void> _reportFriend(Friend friend) async => await showReportDialog(
|
||||
ctx: context, target: ReportTarget(ReportTargetType.User, friend.id));
|
||||
|
||||
/// Open a private conversation for a given [friend]
|
||||
Future<void> _openPrivateConversation(Friend friend) async {
|
||||
await openPrivateConversation(context, friend.id);
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:comunic/helpers/server_config_helper.dart';
|
||||
import 'package:comunic/models/friend.dart';
|
||||
import 'package:comunic/models/user.dart';
|
||||
import 'package:comunic/ui/widgets/account_image_widget.dart';
|
||||
@ -10,11 +11,17 @@ import 'package:flutter/material.dart';
|
||||
///
|
||||
/// @author Pierre HUBERT
|
||||
|
||||
enum _FriendMenuChoices { REMOVE, TOGGLE_FOLLOWING, PRIVATE_CONVERSATION }
|
||||
enum _FriendMenuChoices {
|
||||
REMOVE,
|
||||
TOGGLE_FOLLOWING,
|
||||
PRIVATE_CONVERSATION,
|
||||
REPORT
|
||||
}
|
||||
|
||||
typedef OnRequestDeleteFriend = void Function(Friend);
|
||||
typedef OnSetFollowing = void Function(Friend, bool);
|
||||
typedef OnOpenPrivateConversation = void Function(Friend);
|
||||
typedef OnReportFriend = void Function(Friend);
|
||||
|
||||
class AcceptedFriendTile extends StatelessWidget {
|
||||
final Friend friend;
|
||||
@ -22,6 +29,7 @@ class AcceptedFriendTile extends StatelessWidget {
|
||||
final OnRequestDeleteFriend onRequestDelete;
|
||||
final OnSetFollowing onSetFollowing;
|
||||
final OnOpenPrivateConversation onOpenPrivateConversation;
|
||||
final OnReportFriend onReportFriend;
|
||||
|
||||
const AcceptedFriendTile({
|
||||
Key? key,
|
||||
@ -30,6 +38,7 @@ class AcceptedFriendTile extends StatelessWidget {
|
||||
required this.onRequestDelete,
|
||||
required this.onSetFollowing,
|
||||
required this.onOpenPrivateConversation,
|
||||
required this.onReportFriend,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@ -75,7 +84,15 @@ class AcceptedFriendTile extends StatelessWidget {
|
||||
child: Text(tr("Remove")!),
|
||||
value: _FriendMenuChoices.REMOVE,
|
||||
),
|
||||
],
|
||||
]..addAll(srvConfig!.isReportingEnabled
|
||||
? [
|
||||
// Report user
|
||||
PopupMenuItem(
|
||||
child: Text(tr("Report abuse")!),
|
||||
value: _FriendMenuChoices.REPORT,
|
||||
),
|
||||
]
|
||||
: []),
|
||||
onSelected: _selectedMenuOption,
|
||||
),
|
||||
);
|
||||
@ -97,6 +114,10 @@ class AcceptedFriendTile extends StatelessWidget {
|
||||
case _FriendMenuChoices.REMOVE:
|
||||
onRequestDelete(friend);
|
||||
break;
|
||||
|
||||
case _FriendMenuChoices.REPORT:
|
||||
onReportFriend(friend);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
import 'package:comunic/helpers/server_config_helper.dart';
|
||||
import 'package:comunic/models/friend.dart';
|
||||
import 'package:comunic/models/user.dart';
|
||||
import 'package:comunic/ui/tiles/accepted_friend_tile.dart';
|
||||
import 'package:comunic/ui/widgets/account_image_widget.dart';
|
||||
import 'package:comunic/utils/intl_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@ -14,13 +16,15 @@ class PendingFriendTile extends StatelessWidget {
|
||||
final Friend friend;
|
||||
final User user;
|
||||
final RespondFriendshipRequestCallback onRespond;
|
||||
final OnReportFriend onReport;
|
||||
|
||||
const PendingFriendTile(
|
||||
{Key? key,
|
||||
required this.friend,
|
||||
required this.user,
|
||||
required this.onRespond})
|
||||
: super(key: key);
|
||||
const PendingFriendTile({
|
||||
Key? key,
|
||||
required this.friend,
|
||||
required this.user,
|
||||
required this.onRespond,
|
||||
required this.onReport,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -56,7 +60,19 @@ class PendingFriendTile extends StatelessWidget {
|
||||
style: ButtonStyle(
|
||||
backgroundColor: MaterialStateProperty.all(Colors.red)),
|
||||
onPressed: () => onRespond(friend, false),
|
||||
)
|
||||
),
|
||||
|
||||
// Report button
|
||||
srvConfig!.isReportingEnabled
|
||||
? IconButton(
|
||||
visualDensity: VisualDensity.compact,
|
||||
onPressed: () => onReport(friend),
|
||||
icon: Icon(
|
||||
Icons.flag,
|
||||
size: 15.0,
|
||||
),
|
||||
)
|
||||
: Container()
|
||||
],
|
||||
),
|
||||
),
|
||||
|
Loading…
Reference in New Issue
Block a user