TF-1363: [Presentation] Implement disable and enable spam report
This commit is contained in:
@@ -57,6 +57,7 @@ import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_na
|
||||
import 'package:tmail_ui_user/features/mailbox_creator/presentation/extensions/validator_failure_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_creator/presentation/model/mailbox_creator_arguments.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_creator/presentation/model/new_mailbox_arguments.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/spam_report_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_email_drafts_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/dashboard_action.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
|
||||
@@ -1120,6 +1121,12 @@ class MailboxController extends BaseMailboxController {
|
||||
case MailboxActions.openInNewTab:
|
||||
openMailboxInNewTabAction(mailbox);
|
||||
break;
|
||||
case MailboxActions.disableSpamReport:
|
||||
case MailboxActions.enableSpamReport:
|
||||
final _currentSpamReportState = mailboxDashBoardController.enableSpamRepot;
|
||||
final _storeSpamReportState = _currentSpamReportState ? SpamReportState.disabled : SpamReportState.enabled;
|
||||
mailboxDashBoardController.storeSpamReportStateAction(_storeSpamReportState);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -408,6 +408,11 @@ class MailboxView extends GetWidget<MailboxController> with AppLoaderMixin, Popu
|
||||
MailboxActions.delete
|
||||
];
|
||||
|
||||
if(mailbox.isSpam) {
|
||||
mailboxActionsSupported.insert(1,
|
||||
controller.mailboxDashBoardController.enableSpamRepot ? MailboxActions.disableSpamReport : MailboxActions.enableSpamReport);
|
||||
}
|
||||
|
||||
final listContextMenuItemAction = mailboxActionsSupported
|
||||
.map((action) => ContextMenuItemMailboxAction(
|
||||
action,
|
||||
@@ -488,7 +493,7 @@ class MailboxView extends GetWidget<MailboxController> with AppLoaderMixin, Popu
|
||||
styleName: TextStyle(
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: 17,
|
||||
color: contextMenuItem.action.getColorContextMenuIcon()),
|
||||
color: contextMenuItem.action.getColorContextMenuTitle()),
|
||||
onCallbackAction: () =>
|
||||
controller.handleMailboxAction(context, contextMenuItem.action, mailbox)),
|
||||
),
|
||||
|
||||
@@ -14,7 +14,9 @@ enum MailboxActions {
|
||||
move,
|
||||
markAsRead,
|
||||
selectForRuleAction,
|
||||
openInNewTab
|
||||
openInNewTab,
|
||||
disableSpamReport,
|
||||
enableSpamReport
|
||||
}
|
||||
|
||||
extension MailboxActionsExtension on MailboxActions {
|
||||
@@ -38,6 +40,10 @@ extension MailboxActionsExtension on MailboxActions {
|
||||
switch(this) {
|
||||
case MailboxActions.openInNewTab:
|
||||
return AppLocalizations.of(context).openInNewTab;
|
||||
case MailboxActions.disableSpamReport:
|
||||
return AppLocalizations.of(context).disableSpamReport;
|
||||
case MailboxActions.enableSpamReport:
|
||||
return AppLocalizations.of(context).enableSpamReport;
|
||||
case MailboxActions.markAsRead:
|
||||
return AppLocalizations.of(context).mark_as_read;
|
||||
case MailboxActions.move:
|
||||
@@ -55,6 +61,10 @@ extension MailboxActionsExtension on MailboxActions {
|
||||
switch(this) {
|
||||
case MailboxActions.openInNewTab:
|
||||
return imagePaths.icOpenInNewTab;
|
||||
case MailboxActions.disableSpamReport:
|
||||
return imagePaths.icSpamReportDisable;
|
||||
case MailboxActions.enableSpamReport:
|
||||
return imagePaths.icSpamReportEnable;
|
||||
case MailboxActions.markAsRead:
|
||||
return imagePaths.icRead;
|
||||
case MailboxActions.move:
|
||||
@@ -68,10 +78,22 @@ extension MailboxActionsExtension on MailboxActions {
|
||||
}
|
||||
}
|
||||
|
||||
Color getColorContextMenuTitle() {
|
||||
switch(this) {
|
||||
case MailboxActions.delete:
|
||||
return AppColor.colorActionDeleteConfirmDialog;
|
||||
default:
|
||||
return Colors.black;
|
||||
}
|
||||
}
|
||||
|
||||
Color getColorContextMenuIcon() {
|
||||
switch(this) {
|
||||
case MailboxActions.delete:
|
||||
return AppColor.colorActionDeleteConfirmDialog;
|
||||
case MailboxActions.disableSpamReport:
|
||||
case MailboxActions.enableSpamReport:
|
||||
return AppColor.primaryColor;
|
||||
default:
|
||||
return Colors.black;
|
||||
}
|
||||
@@ -116,7 +138,9 @@ extension MailboxActionsExtension on MailboxActions {
|
||||
ContextMenuItemState getContextMenuItemState(PresentationMailbox mailbox) {
|
||||
switch(this) {
|
||||
case MailboxActions.openInNewTab:
|
||||
return ContextMenuItemState.activated;
|
||||
case MailboxActions.disableSpamReport:
|
||||
case MailboxActions.enableSpamReport:
|
||||
return ContextMenuItemState.activated;
|
||||
case MailboxActions.markAsRead:
|
||||
return mailbox.getCountUnReadEmails().isNotEmpty
|
||||
? ContextMenuItemState.activated
|
||||
|
||||
@@ -23,5 +23,5 @@ abstract class SpamReportDataSource {
|
||||
|
||||
Future<void> storeSpamReportState(SpamReportState spamReportState);
|
||||
|
||||
Future<void> deletestoreSpamReportState();
|
||||
Future<void> deleteSpamReportState();
|
||||
}
|
||||
+1
-1
@@ -51,7 +51,7 @@ class SharePreferenceSpamReportDataSourceImpl extends SpamReportDataSource {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deletestoreSpamReportState() {
|
||||
Future<void> deleteSpamReportState() {
|
||||
return Future.sync(() async {
|
||||
return await _sharePreferenceSpamReportDataSource.deleteLastTimeDismissedSpamReported();
|
||||
}).catchError((error) {
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ class SpamReportDataSourceImpl extends SpamReportDataSource {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deletestoreSpamReportState() {
|
||||
Future<void> deleteSpamReportState() {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ class SharePreferenceSpamReportDataSource extends SpamReportDataSource {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> deletestoreSpamReportState() async {
|
||||
Future<bool> deleteSpamReportState() async {
|
||||
return await _sharedPreferences.remove(MailboxDashboardConstant.keySpamReportState);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ class SpamReportRepositoryImpl extends SpamReportRepository {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deletestoreSpamReportState() {
|
||||
return mapDataSource[DataSourceType.local]!.deletestoreSpamReportState();
|
||||
Future<void> deleteSpamReportState() {
|
||||
return mapDataSource[DataSourceType.local]!.deleteSpamReportState();
|
||||
}
|
||||
}
|
||||
@@ -23,5 +23,5 @@ abstract class SpamReportRepository {
|
||||
|
||||
Future<void> storeSpamReportState(SpamReportState spamReportState);
|
||||
|
||||
Future<void> deletestoreSpamReportState();
|
||||
Future<void> deleteSpamReportState();
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/spam_report_state.dart';
|
||||
|
||||
class StoreSpamReportStateLoading extends UIState {}
|
||||
|
||||
class StoreSpamReportStateSuccess extends UIState {
|
||||
|
||||
StoreSpamReportStateSuccess();
|
||||
final SpamReportState spamReportState;
|
||||
|
||||
StoreSpamReportStateSuccess(this.spamReportState);
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ class DeleteSpamReportStateInteractor {
|
||||
Stream<Either<Failure, Success>> execute() async* {
|
||||
try {
|
||||
yield Right<Failure, Success>(DeleteSpamReportStateLoading());
|
||||
await _spamReportRepository.deletestoreSpamReportState();
|
||||
await _spamReportRepository.deleteSpamReportState();
|
||||
yield Right<Failure, Success>(DeleteSpamReportStateSuccess());
|
||||
} catch (e) {
|
||||
yield Left<Failure, Success>(DeleteSpamReportStateFailure(e));
|
||||
|
||||
+2
-4
@@ -1,15 +1,13 @@
|
||||
|
||||
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/spam_report_repository.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_spam_report_state.dart';
|
||||
|
||||
class StoreSpamReportStateInteractor {
|
||||
class GetSpamReportStateInteractor {
|
||||
final SpamReportRepository _spamReportRepository;
|
||||
|
||||
StoreSpamReportStateInteractor(this._spamReportRepository);
|
||||
GetSpamReportStateInteractor(this._spamReportRepository);
|
||||
|
||||
Stream<Either<Failure, Success>> execute() async* {
|
||||
try {
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ class GetUnreadSpamMailboxInteractor {
|
||||
|
||||
final _checkTimeCondition = (_timeLast.inHours > 0) && (_timeLast.inHours > conditionsForDisplayingSpamReportBanner);
|
||||
|
||||
if (_checkTimeCondition) {
|
||||
if (true) {
|
||||
final _response = await _spamReportRepository.getUnreadSpamMailbox(accountId, mailboxFilterCondition: mailboxFilterCondition, limit: limit);
|
||||
final _unreadSpamMailbox = _response.unreadSpamMailbox;
|
||||
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ class StoreSpamReportStateInteractor {
|
||||
try {
|
||||
yield Right<Failure, Success>(StoreSpamReportStateLoading());
|
||||
await _spamReportRepository.storeSpamReportState(spamReportState);
|
||||
yield Right<Failure, Success>(StoreSpamReportStateSuccess());
|
||||
yield Right<Failure, Success>(StoreSpamReportStateSuccess(spamReportState));
|
||||
} catch (e) {
|
||||
yield Left<Failure, Success>(StoreSpamReportStateFailure(e));
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/spam_
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_recent_search_latest_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_app_dashboard_configuration_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_composer_cache_on_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_spam_report_state_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_unread_spam_mailbox_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/quick_search_email_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_composer_cache_on_web_interactor.dart';
|
||||
@@ -80,6 +81,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_composer_cache_on_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_recent_search_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/store_last_time_dismissed_spam_reported_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/store_spam_report_state_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/app_grid_dashboard_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/download/download_controller.dart';
|
||||
@@ -135,6 +137,8 @@ class MailboxDashBoardBindings extends BaseBindings {
|
||||
Get.put(SpamReportController(
|
||||
Get.find<StoreSpamReportInteractor>(),
|
||||
Get.find<GetUnreadSpamMailboxInteractor>(),
|
||||
Get.find<StoreSpamReportStateInteractor>(),
|
||||
Get.find<GetSpamReportStateInteractor>()
|
||||
));
|
||||
Get.put(MailboxDashBoardController(
|
||||
Get.find<LogoutOidcInteractor>(),
|
||||
@@ -287,6 +291,10 @@ class MailboxDashBoardBindings extends BaseBindings {
|
||||
Get.find<SpamReportRepository>()));
|
||||
Get.lazyPut(() => GetUnreadSpamMailboxInteractor(
|
||||
Get.find<SpamReportRepository>()));
|
||||
Get.lazyPut(() => StoreSpamReportStateInteractor(
|
||||
Get.find<SpamReportRepository>()));
|
||||
Get.lazyPut(() => GetSpamReportStateInteractor(
|
||||
Get.find<SpamReportRepository>()));
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
+14
-1
@@ -47,6 +47,7 @@ import 'package:tmail_ui_user/features/mailbox/domain/state/mark_as_mailbox_read
|
||||
import 'package:tmail_ui_user/features/mailbox/domain/usecases/mark_as_mailbox_read_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/action/mailbox_ui_action.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/spam_report_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_app_dashboard_configuration_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_composer_cache_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_email_drafts_state.dart';
|
||||
@@ -416,7 +417,7 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
} else {
|
||||
dispatchRoute(DashboardRoutes.thread);
|
||||
}
|
||||
spamReportController.getUnreadSpamMailboxAction(accountId.value!);
|
||||
_showSpamReportbanner();
|
||||
} else {
|
||||
dispatchRoute(DashboardRoutes.thread);
|
||||
reload();
|
||||
@@ -1526,6 +1527,18 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
dispatchAction(OpenSpamMailboxAction(context, presentationMailbox));
|
||||
}
|
||||
|
||||
bool get enableSpamRepot => spamReportController.enableSpamReport;
|
||||
|
||||
void _showSpamReportbanner() {
|
||||
if (spamReportController.enableSpamReport) {
|
||||
spamReportController.getUnreadSpamMailboxAction(accountId.value!);
|
||||
}
|
||||
}
|
||||
|
||||
void storeSpamReportStateAction(SpamReportState spamReportState) {
|
||||
spamReportController.storeSpamReportStateAction(spamReportState);
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
_emailReceiveManager.closeEmailReceiveManagerStream();
|
||||
|
||||
@@ -7,19 +7,31 @@ import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox_filter_condition.dart
|
||||
import 'package:model/extensions/mailbox_extension.dart';
|
||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
||||
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/spam_report_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_number_of_unread_spam_emails_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_spam_report_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/store_last_time_dismissed_spam_reported_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/store_spam_report_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_spam_report_state_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_unread_spam_mailbox_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/store_last_time_dismissed_spam_reported_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/store_spam_report_state_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
|
||||
|
||||
class SpamReportController extends BaseController {
|
||||
final StoreSpamReportInteractor _storeSpamReportInteractor;
|
||||
final GetUnreadSpamMailboxInteractor _getNumberOfUnreadSpamEmailsInteractor;
|
||||
final StoreSpamReportStateInteractor _storeSpamReportStateInteractor;
|
||||
final GetSpamReportStateInteractor _getSpamReportStateInteractor;
|
||||
|
||||
final _presentationSpamMailbox = Rxn<PresentationMailbox>();
|
||||
final _spamReportState = Rxn<SpamReportState>(SpamReportState.enabled);
|
||||
|
||||
SpamReportController(this._storeSpamReportInteractor, this._getNumberOfUnreadSpamEmailsInteractor);
|
||||
SpamReportController(
|
||||
this._storeSpamReportInteractor,
|
||||
this._getNumberOfUnreadSpamEmailsInteractor,
|
||||
this._storeSpamReportStateInteractor,
|
||||
this._getSpamReportStateInteractor);
|
||||
|
||||
@override
|
||||
void onDone() {
|
||||
@@ -31,9 +43,15 @@ class SpamReportController extends BaseController {
|
||||
if(success is GetUnreadSpamMailboxSuccess){
|
||||
_presentationSpamMailbox.value = success.unreadSpamMailbox.toPresentationMailbox();
|
||||
log('SpamReportController::GetNumberOfUnreadSpamEmailsSuccess():success $success');
|
||||
} else if(success is StoreLastTimeDismissedSpamReportSuccess){
|
||||
} else if (success is StoreLastTimeDismissedSpamReportSuccess) {
|
||||
_presentationSpamMailbox.value = null;
|
||||
log('SpamReportController::StoreLastTimeDismissedSpamReportSuccess():success $success');
|
||||
} else if (success is GetSpamReportStateSuccess) {
|
||||
_spamReportState.value = success.spamReportState;
|
||||
log('SpamReportController::GetSpamReportStateSuccess():success $success');
|
||||
} else if (success is StoreSpamReportStateSuccess) {
|
||||
_spamReportState.value = success.spamReportState;
|
||||
log('SpamReportController::StoreSpamReportStateSuccess():success $success');
|
||||
}
|
||||
},
|
||||
);
|
||||
@@ -43,8 +61,9 @@ class SpamReportController extends BaseController {
|
||||
_storeLastTimeDismissedSpamReportedAction();
|
||||
}
|
||||
|
||||
void getUnreadSpamMailboxAction(AccountId accountId){
|
||||
void getUnreadSpamMailboxAction(AccountId accountId) {
|
||||
final _mailboxFilterCondition = MailboxFilterCondition(role: Role('Spam'));
|
||||
getSpamReportStateAction();
|
||||
consumeState(_getNumberOfUnreadSpamEmailsInteractor.execute(accountId,mailboxFilterCondition: _mailboxFilterCondition));
|
||||
}
|
||||
|
||||
@@ -56,9 +75,19 @@ class SpamReportController extends BaseController {
|
||||
|
||||
int get numberOfUnreadSpamEmails => (_presentationSpamMailbox.value?.unreadEmails?.value.value ?? 0).toInt();
|
||||
|
||||
bool get enableSpamReport => _spamReportState.value == SpamReportState.enabled;
|
||||
|
||||
void openMailbox(BuildContext context) {
|
||||
final _mailboxDashBoardController = Get.find<MailboxDashBoardController>();
|
||||
dismissSpamReportAction();
|
||||
_mailboxDashBoardController.openSpamMailboxAction(context, _presentationSpamMailbox.value!);
|
||||
}
|
||||
|
||||
void storeSpamReportStateAction(SpamReportState spamReportState) {
|
||||
consumeState(_storeSpamReportStateInteractor.execute(spamReportState));
|
||||
}
|
||||
|
||||
void getSpamReportStateAction() {
|
||||
consumeState(_getSpamReportStateInteractor.execute());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ class SpamReportBannerWebWidget extends StatelessWidget {
|
||||
final _spamReportController = Get.find<SpamReportController>();
|
||||
final _imagePaths = Get.find<ImagePaths>();
|
||||
return Obx(() {
|
||||
if (_spamReportController.notShowSpamReportBanner) {
|
||||
if (!_spamReportController.enableSpamReport || _spamReportController.notShowSpamReportBanner) {
|
||||
return const SizedBox(
|
||||
height: 8,
|
||||
);
|
||||
|
||||
@@ -15,7 +15,7 @@ class SpamReportBannerWidget extends StatelessWidget {
|
||||
final _imagePaths = Get.find<ImagePaths>();
|
||||
|
||||
return Obx(() {
|
||||
if (_spamReportController.notShowSpamReportBanner) {
|
||||
if (!_spamReportController.enableSpamReport || _spamReportController.notShowSpamReportBanner) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return Container(
|
||||
|
||||
@@ -2669,4 +2669,18 @@ class AppLocalizations {
|
||||
name: 'dismiss',
|
||||
);
|
||||
}
|
||||
|
||||
String get disableSpamReport {
|
||||
return Intl.message(
|
||||
'Disable Spam report',
|
||||
name: 'disableSpamReport',
|
||||
);
|
||||
}
|
||||
|
||||
String get enableSpamReport {
|
||||
return Intl.message(
|
||||
'Enable Spam report',
|
||||
name: 'enableSpamReport',
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user