feat(social): local blocklist — hide blocked authors' offers, chats and incoming messages, with unblock management
This commit is contained in:
parent
5d25f65f76
commit
11b242edbf
13 changed files with 399 additions and 4 deletions
|
|
@ -16,6 +16,7 @@ import '../services/profile_cache.dart';
|
|||
import '../services/profile_store.dart';
|
||||
import '../services/social_connection.dart';
|
||||
import '../services/social_service.dart';
|
||||
import '../services/social_settings.dart';
|
||||
import '../services/unread_service.dart';
|
||||
import '../state/messages_cubit.dart';
|
||||
import '../state/peer_rating_cubit.dart';
|
||||
|
|
@ -36,6 +37,7 @@ class ChatScreen extends StatefulWidget {
|
|||
this.messageStore,
|
||||
this.profileCache,
|
||||
this.onboarding,
|
||||
this.settings,
|
||||
super.key,
|
||||
});
|
||||
|
||||
|
|
@ -57,6 +59,11 @@ class ChatScreen extends StatefulWidget {
|
|||
/// entering the market). Null in tests → no gate.
|
||||
final OnboardingStore? onboarding;
|
||||
|
||||
/// Social settings holding the local blocklist; falls back to the app-wide
|
||||
/// instance so the block action also works when not injected. Null in
|
||||
/// tests → the block menu is hidden.
|
||||
final SocialSettings? settings;
|
||||
|
||||
@override
|
||||
State<ChatScreen> createState() => _ChatScreenState();
|
||||
}
|
||||
|
|
@ -191,6 +198,42 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||
}
|
||||
}
|
||||
|
||||
SocialSettings? get _settings =>
|
||||
widget.settings ??
|
||||
(getIt.isRegistered<SocialSettings>() ? getIt<SocialSettings>() : null);
|
||||
|
||||
/// Blocks this peer after confirmation and leaves the chat; their offers,
|
||||
/// conversation and future messages disappear (all locally).
|
||||
Future<void> _blockPeer() async {
|
||||
final settings = _settings;
|
||||
if (settings == null) return;
|
||||
final t = context.t;
|
||||
final confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(t.block.confirmTitle),
|
||||
content: Text(t.block.confirmBody),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(false),
|
||||
child: Text(t.common.cancel),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () => Navigator.of(context).pop(true),
|
||||
child: Text(t.block.confirm),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
if (confirmed != true || !mounted) return;
|
||||
await settings.block(widget.peerPubkey);
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context)
|
||||
..hideCurrentSnackBar()
|
||||
..showSnackBar(SnackBar(content: Text(t.block.blockedToast)));
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
Future<void> _send() async {
|
||||
final cubit = _messages;
|
||||
if (cubit == null || _input.text.trim().isEmpty) return;
|
||||
|
|
@ -244,6 +287,19 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||
tooltip: t.chat.payG1,
|
||||
onPressed: _payG1,
|
||||
),
|
||||
if (_settings != null)
|
||||
PopupMenuButton<String>(
|
||||
key: const Key('chat.menu'),
|
||||
onSelected: (value) {
|
||||
if (value == 'block') _blockPeer();
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem(
|
||||
value: 'block',
|
||||
child: Text(t.block.action),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
body: _loading || messages == null || trust == null || rating == null
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue