Skip to content

Commit

Permalink
Immediately remove blocked users/communities from feed, disable abili…
Browse files Browse the repository at this point in the history
…ty to block self (#1391)

* A few post sheet improvements

* Replace subscribed status update with snackbar

* Remove unused fields
  • Loading branch information
micahmo authored Jun 25, 2024
1 parent 3ee5e52 commit c3c7ceb
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 10 deletions.
11 changes: 10 additions & 1 deletion lib/community/bloc/community_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:thunder/community/enums/community_action.dart';
import 'package:thunder/core/singletons/lemmy_client.dart';
import 'package:thunder/feed/utils/community.dart';
import 'package:thunder/shared/snackbar.dart';
import 'package:thunder/utils/global_context.dart';

part 'community_event.dart';
Expand Down Expand Up @@ -73,9 +74,17 @@ class CommunityBloc extends Bloc<CommunityEvent, CommunityState> {
emit(state.copyWith(status: CommunityStatus.fetching));

// Wait for one second before fetching the community information to get any updated information
Future.delayed(const Duration(seconds: 1)).then((value) async {
await Future.delayed(const Duration(seconds: 1)).then((value) async {
GetCommunityResponse? getCommunityResponse = await fetchCommunityInformation(id: event.communityId);
emit(state.copyWith(status: CommunityStatus.success, communityView: getCommunityResponse.communityView));

if (GlobalContext.context.mounted) {
if (event.value) {
showSnackbar(AppLocalizations.of(GlobalContext.context)!.subscribed);
} else {
showSnackbar(AppLocalizations.of(GlobalContext.context)!.unsubscribed);
}
}
});
} catch (e) {
return emit(state.copyWith(status: CommunityStatus.failure));
Expand Down
41 changes: 32 additions & 9 deletions lib/community/utils/post_card_action_helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -287,11 +287,13 @@ void showPostActionBottomModalSheet(
BuildContext context,
PostViewMedia postViewMedia, {
PostActionBottomSheetPage page = PostActionBottomSheetPage.general,
void Function(int userId)? onBlockedUser,
void Function(int userId)? onBlockedCommunity,
}) {
final bool isOwnPost = postViewMedia.postView.creator.id == context.read<AuthBloc>().state.account?.userId;

final bool isModerator =
context.read<AccountBloc>().state.moderates.any((CommunityModeratorView communityModeratorView) => communityModeratorView.community.id == postViewMedia.postView.community.id);
final int? currentUserId = context.read<AuthBloc>().state.account?.userId;

// Generate the list of default actions for the general page
final List<ExtendedPostCardActions> defaultPostCardActions = postCardActionItems
Expand Down Expand Up @@ -365,7 +367,7 @@ void showPostActionBottomModalSheet(
final List<ExtendedPostCardActions> userActions = postCardActionItems
.where((extendedAction) => [
PostCardAction.visitProfile,
PostCardAction.blockUser,
if (postViewMedia.postView.creator.id != currentUserId) PostCardAction.blockUser,
].contains(extendedAction.postCardAction))
.toList();

Expand Down Expand Up @@ -421,6 +423,8 @@ void showPostActionBottomModalSheet(
PostActionBottomSheetPage.instance: l10n.instanceActions,
},
outerContext: context,
onBlockedUser: onBlockedUser,
onBlockedCommunity: onBlockedCommunity,
),
);
}
Expand All @@ -444,6 +448,12 @@ class PostCardActionPicker extends StatefulWidget {
/// The context from whoever invoked this sheet (useful for blocs that would otherwise be missing)
final BuildContext outerContext;

/// Callback used to notify that we blocked a user
final void Function(int userId)? onBlockedUser;

/// Callback used to notify that we blocked a community
final Function(int userId)? onBlockedCommunity;

const PostCardActionPicker({
super.key,
required this.postViewMedia,
Expand All @@ -452,6 +462,8 @@ class PostCardActionPicker extends StatefulWidget {
required this.multiPostCardActions,
required this.titles,
required this.outerContext,
required this.onBlockedUser,
required this.onBlockedCommunity,
});

@override
Expand Down Expand Up @@ -651,8 +663,10 @@ class _PostCardActionPickerState extends State<PostCardActionPicker> {
pop = false;
break;
case PostCardAction.blockCommunity:
action =
() => widget.outerContext.read<CommunityBloc>().add(CommunityActionEvent(communityAction: CommunityAction.block, communityId: widget.postViewMedia.postView.community.id, value: true));
action = () {
widget.outerContext.read<CommunityBloc>().add(CommunityActionEvent(communityAction: CommunityAction.block, communityId: widget.postViewMedia.postView.community.id, value: true));
widget.onBlockedCommunity?.call(widget.postViewMedia.postView.community.id);
};
break;
case PostCardAction.upvote:
action = () => widget.outerContext
Expand All @@ -677,15 +691,24 @@ class _PostCardActionPickerState extends State<PostCardActionPicker> {
action = () => setState(() => page = PostActionBottomSheetPage.share);
break;
case PostCardAction.blockUser:
action = () => widget.outerContext.read<UserBloc>().add(UserActionEvent(userAction: UserAction.block, userId: widget.postViewMedia.postView.creator.id, value: true));
action = () {
widget.outerContext.read<UserBloc>().add(UserActionEvent(userAction: UserAction.block, userId: widget.postViewMedia.postView.creator.id, value: true));
widget.onBlockedCommunity?.call(widget.postViewMedia.postView.creator.id);
};
break;
case PostCardAction.subscribeToCommunity:
action =
() => widget.outerContext.read<CommunityBloc>().add(CommunityActionEvent(communityAction: CommunityAction.follow, communityId: widget.postViewMedia.postView.community.id, value: true));
action = () => widget.outerContext.read<CommunityBloc>().add(CommunityActionEvent(
communityAction: CommunityAction.follow,
communityId: widget.postViewMedia.postView.community.id,
value: true,
));
break;
case PostCardAction.unsubscribeFromCommunity:
action =
() => widget.outerContext.read<CommunityBloc>().add(CommunityActionEvent(communityAction: CommunityAction.follow, communityId: widget.postViewMedia.postView.community.id, value: false));
action = () => widget.outerContext.read<CommunityBloc>().add(CommunityActionEvent(
communityAction: CommunityAction.follow,
communityId: widget.postViewMedia.postView.community.id,
value: false,
));
break;
case PostCardAction.delete:
action = () => widget.outerContext
Expand Down
2 changes: 2 additions & 0 deletions lib/community/widgets/post_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ class _PostCardState extends State<PostCard> {
onLongPress: () => showPostActionBottomModalSheet(
context,
widget.postViewMedia,
onBlockedUser: (userId) => context.read<FeedBloc>().add(FeedDismissBlockedEvent(userId: userId)),
onBlockedCommunity: (communityId) => context.read<FeedBloc>().add(FeedDismissBlockedEvent(communityId: communityId)),
),
onTap: () async {
PostView postView = widget.postViewMedia.postView;
Expand Down
3 changes: 3 additions & 0 deletions lib/community/widgets/post_card_view_comfortable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import 'package:thunder/core/enums/media_type.dart';
import 'package:thunder/core/enums/view_mode.dart';
import 'package:thunder/core/models/post_view_media.dart';
import 'package:thunder/core/theme/bloc/theme_bloc.dart';
import 'package:thunder/feed/bloc/feed_bloc.dart';
import 'package:thunder/feed/view/feed_page.dart';
import 'package:thunder/shared/media_view.dart';
import 'package:thunder/shared/text/scalable_text.dart';
Expand Down Expand Up @@ -325,6 +326,8 @@ class PostCardViewComfortable extends StatelessWidget {
showPostActionBottomModalSheet(
context,
postViewMedia,
onBlockedUser: (userId) => context.read<FeedBloc>().add(FeedDismissBlockedEvent(userId: userId)),
onBlockedCommunity: (communityId) => context.read<FeedBloc>().add(FeedDismissBlockedEvent(communityId: communityId)),
);
HapticFeedback.mediumImpact();
}),
Expand Down
11 changes: 11 additions & 0 deletions lib/feed/bloc/feed_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ class FeedBloc extends Bloc<FeedEvent, FeedState> {
transformer: throttleDroppable(Duration.zero),
);

/// Handles dismissing posts from blocked users/communities
on<FeedDismissBlockedEvent>(
_onFeedDismissBlocked,
transformer: throttleDroppable(Duration.zero),
);

/// Handles hiding posts from the feed
on<FeedHidePostsFromViewEvent>(
_onFeedHidePostsFromView,
Expand Down Expand Up @@ -117,6 +123,11 @@ class FeedBloc extends Bloc<FeedEvent, FeedState> {
emit(state.copyWith(status: FeedStatus.success, dismissReadId: state.dismissReadId + 1));
}

/// Handles dismissing read posts from the feed
Future<void> _onFeedDismissBlocked(FeedDismissBlockedEvent event, Emitter<FeedState> emit) async {
emit(state.copyWith(status: FeedStatus.success, dismissBlockedUserId: event.userId, dismissBlockedCommunityId: event.communityId));
}

/// Handles scrolling to top of the feed
Future<void> _onFeedScrollToTop(ScrollToTopEvent event, Emitter<FeedState> emit) async {
emit(state.copyWith(status: FeedStatus.success, scrollId: state.scrollId + 1));
Expand Down
7 changes: 7 additions & 0 deletions lib/feed/bloc/feed_event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@ final class ScrollToTopEvent extends FeedEvent {}

final class FeedDismissReadEvent extends FeedEvent {}

final class FeedDismissBlockedEvent extends FeedEvent {
final int? communityId;
final int? userId;

const FeedDismissBlockedEvent({this.communityId, this.userId});
}

final class FeedHidePostsFromViewEvent extends FeedEvent {
final List<int> postIds;

Expand Down
14 changes: 14 additions & 0 deletions lib/feed/bloc/feed_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ final class FeedState extends Equatable {
this.message,
this.scrollId = 0,
this.dismissReadId = 0,
this.dismissBlockedUserId,
this.dismissBlockedCommunityId,
this.insertedPostIds = const [],
});

Expand Down Expand Up @@ -79,6 +81,12 @@ final class FeedState extends Equatable {
/// This id is used for dismissing already read posts in the feed
final int dismissReadId;

/// This id is used for dismissing posts from blocked users
final int? dismissBlockedUserId;

/// This id is used for dismissing posts from blocked communities
final int? dismissBlockedCommunityId;

/// The inserted post ids. This is used to prevent duplicate posts
final List<int> insertedPostIds;

Expand All @@ -101,6 +109,8 @@ final class FeedState extends Equatable {
String? message,
int? scrollId,
int? dismissReadId,
int? dismissBlockedUserId,
int? dismissBlockedCommunityId,
List<int>? insertedPostIds,
}) {
return FeedState(
Expand All @@ -122,6 +132,8 @@ final class FeedState extends Equatable {
message: message,
scrollId: scrollId ?? this.scrollId,
dismissReadId: dismissReadId ?? this.dismissReadId,
dismissBlockedUserId: dismissBlockedUserId,
dismissBlockedCommunityId: dismissBlockedCommunityId,
insertedPostIds: insertedPostIds ?? this.insertedPostIds,
);
}
Expand Down Expand Up @@ -151,6 +163,8 @@ final class FeedState extends Equatable {
message,
scrollId,
dismissReadId,
dismissBlockedUserId,
dismissBlockedCommunityId,
insertedPostIds
];
}
22 changes: 22 additions & 0 deletions lib/feed/view/feed_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,27 @@ class _FeedViewState extends State<FeedView> {
}
}

Future<void> dismissBlockedUsersAndCommunities(int? userId, int? communityId) async {
ThunderState state = context.read<ThunderBloc>().state;

FeedBloc feedBloc = context.read<FeedBloc>();
List<PostViewMedia> postViewMedias = feedBloc.state.postViewMedias;

if (postViewMedias.isNotEmpty) {
for (PostViewMedia postViewMedia in postViewMedias) {
if (postViewMedia.postView.creator.id == userId || postViewMedia.postView.community.id == communityId) {
setState(() => queuedForRemoval.add(postViewMedia.postView.post.id));
await Future.delayed(Duration(milliseconds: state.useCompactView ? 60 : 100));
}
}

await Future.delayed(const Duration(milliseconds: 500));

feedBloc.add(FeedHidePostsFromViewEvent(postIds: List.from(queuedForRemoval)));
setState(() => queuedForRemoval.clear());
}
}

@override
Widget build(BuildContext context) {
ThunderBloc thunderBloc = context.watch<ThunderBloc>();
Expand Down Expand Up @@ -280,6 +301,7 @@ class _FeedViewState extends State<FeedView> {
if (current.status == FeedStatus.initial) setState(() => showAppBarTitle = false);
if (previous.scrollId != current.scrollId) _scrollController.animateTo(0, duration: const Duration(milliseconds: 300), curve: Curves.easeInOut);
if (previous.dismissReadId != current.dismissReadId) dismissRead();
if (current.dismissBlockedUserId != null || current.dismissBlockedCommunityId != null) dismissBlockedUsersAndCommunities(current.dismissBlockedUserId, current.dismissBlockedCommunityId);
return true;
},
listener: (context, state) {
Expand Down

0 comments on commit c3c7ceb

Please sign in to comment.