feat(social): local blocklist — hide blocked authors' offers, chats and incoming messages, with unblock management

This commit is contained in:
vjrj 2026-07-13 01:03:10 +02:00
parent 5d25f65f76
commit 11b242edbf
13 changed files with 399 additions and 4 deletions

View file

@ -21,6 +21,7 @@ class OffersState extends Equatable {
this.typeFilter = const {},
this.categoryFilter = const {},
this.organicOnly = false,
this.blockedAuthors = const {},
this.searching = false,
this.publishing = false,
this.hasSearched = false,
@ -45,6 +46,11 @@ class OffersState extends Equatable {
/// When true, show only offers the grower declared organic ("eco").
final bool organicOnly;
/// Authors this user has blocked; their offers never surface. Kept in the
/// state (not dropped at merge time) so unblocking can resurface what was
/// already discovered.
final Set<String> blockedAuthors;
final bool searching;
final bool publishing;
@ -60,6 +66,7 @@ class OffersState extends Equatable {
List<Offer> get visibleOffers {
final q = query.trim().toLowerCase();
return offers.where((o) {
if (blockedAuthors.contains(o.authorPubkeyHex)) return false;
if (q.isNotEmpty && !o.summary.toLowerCase().contains(q)) return false;
if (typeFilter.isNotEmpty && !typeFilter.contains(o.type)) return false;
if (categoryFilter.isNotEmpty &&
@ -96,6 +103,7 @@ class OffersState extends Equatable {
Set<OfferType>? typeFilter,
Set<String>? categoryFilter,
bool? organicOnly,
Set<String>? blockedAuthors,
bool? searching,
bool? publishing,
bool? hasSearched,
@ -108,6 +116,7 @@ class OffersState extends Equatable {
typeFilter: typeFilter ?? this.typeFilter,
categoryFilter: categoryFilter ?? this.categoryFilter,
organicOnly: organicOnly ?? this.organicOnly,
blockedAuthors: blockedAuthors ?? this.blockedAuthors,
searching: searching ?? this.searching,
publishing: publishing ?? this.publishing,
hasSearched: hasSearched ?? this.hasSearched,
@ -123,6 +132,7 @@ class OffersState extends Equatable {
typeFilter,
categoryFilter,
organicOnly,
blockedAuthors,
searching,
publishing,
hasSearched,
@ -180,6 +190,7 @@ class OffersCubit extends Cubit<OffersState> {
typeFilter: state.typeFilter,
categoryFilter: state.categoryFilter,
organicOnly: state.organicOnly,
blockedAuthors: state.blockedAuthors,
searching: true,
hasSearched: true,
));
@ -234,6 +245,11 @@ class OffersCubit extends Cubit<OffersState> {
void toggleOrganicOnly() =>
emit(state.copyWith(organicOnly: !state.organicOnly));
/// Replaces the set of blocked authors (loaded from the local blocklist);
/// their offers disappear from the visible list at once.
void setBlockedAuthors(Set<String> pubkeys) =>
emit(state.copyWith(blockedAuthors: pubkeys));
/// Clears every chip filter (leaves the text search untouched).
void clearFilters() => emit(state.copyWith(
typeFilter: const {},