Skip to content

Commit

Permalink
Add back FAB actions for experimental post page (#1713)
Browse files Browse the repository at this point in the history
* feat: add back fab actions for experimental post page

* feat: scroll to comment when searching, migrate to new post page by default, automatically collapse post body when viewing comment context

* feat: remove legacy post page and related widgets, linting

* feat: show loading screen for post body when refreshing
  • Loading branch information
hjiangsu authored Feb 27, 2025
1 parent 1d2f5cd commit 3046638
Show file tree
Hide file tree
Showing 17 changed files with 407 additions and 1,866 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ app.*.map.json
/android/app/profile
/android/app/release
/android/build
/android/app/.cxx/

# IOS build
/ios/build
Expand Down
2 changes: 1 addition & 1 deletion lib/comment/widgets/comment_list_entry.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class CommentListEntry extends StatelessWidget {
parentCommentView: isEdit ? null : commentView,
onCommentSuccess: (commentView, userChanged) {
if (!userChanged) {
context.read<post_bloc.PostBloc>().add(post_bloc.UpdateCommentEvent(commentView: commentView, isEdit: isEdit));
context.read<post_bloc.PostBloc>().add(post_bloc.CommentItemUpdatedEvent(commentView: commentView));
}
},
),
Expand Down
4 changes: 0 additions & 4 deletions lib/feed/bloc/feed_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -421,11 +421,7 @@ class FeedBloc extends Bloc<FeedEvent, FeedState> {
return emit(state.copyWith(status: FeedStatus.failure));
}
case PostAction.pinInstance:
// TODO: Handle this case.
case PostAction.purge:
// TODO: Handle this case.
default:
emit(state.copyWith(status: FeedStatus.failure, message: 'Action is not supported'));
break;
}

Expand Down
4 changes: 0 additions & 4 deletions lib/feed/widgets/feed_fab.dart
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,6 @@ class FeedFAB extends StatelessWidget {
case FeedFabAction.newPost:
triggerNewPost(context, isPostingLocked: isPostLocked);
break;
default:
break;
}
},
onLongPress: () {
Expand Down Expand Up @@ -169,8 +167,6 @@ class FeedFAB extends StatelessWidget {
case FeedFabAction.newPost:
triggerNewPost(context, isPostingLocked: isPostLocked);
break;
default:
break;
}
},
children: getEnabledActions(context, isPostingLocked: isPostLocked, disabledActions: disabledActions),
Expand Down
151 changes: 1 addition & 150 deletions lib/post/bloc/post_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,22 +63,6 @@ class PostBloc extends Bloc<PostEvent, PostState> {
_commentItemUpdatedEvent,
transformer: throttleDroppable(Duration.zero),
);
on<VoteCommentEvent>(
_voteCommentEvent,
transformer: throttleDroppable(Duration.zero), // Don't give a throttle on vote
);
on<SaveCommentEvent>(
_saveCommentEvent,
transformer: throttleDroppable(Duration.zero), // Don't give a throttle on save
);
on<DeleteCommentEvent>(
_deleteCommentEvent,
transformer: throttleDroppable(throttleDuration),
);
on<UpdateCommentEvent>(
_updateCommentEvent,
transformer: throttleDroppable(Duration.zero), // Don't give a throttle on update
);
on<NavigateCommentEvent>(
_navigateCommentEvent,
);
Expand Down Expand Up @@ -250,7 +234,7 @@ class PostBloc extends Bloc<PostEvent, PostState> {

if (event.reset || event.viewAllCommentsRefresh) {
if (event.viewAllCommentsRefresh) {
emit(state.copyWith(status: PostStatus.refreshing, selectedCommentId: state.selectedCommentId, viewAllCommentsRefresh: true, sortType: sortType));
emit(state.copyWith(status: PostStatus.loading, selectedCommentId: state.selectedCommentId, viewAllCommentsRefresh: true, sortType: sortType));
} else {
emit(state.copyWith(status: PostStatus.loading, sortType: sortType));
}
Expand Down Expand Up @@ -525,139 +509,6 @@ class PostBloc extends Bloc<PostEvent, PostState> {
));
}

Future<void> _voteCommentEvent(VoteCommentEvent event, Emitter<PostState> emit) async {
try {
emit(state.copyWith(status: PostStatus.refreshing, selectedCommentId: state.selectedCommentId, selectedCommentPath: state.selectedCommentPath));

List<int> commentIndexes = findCommentIndexesFromCommentViewTree(state.comments, event.commentId);
CommentViewTree currentTree = state.comments[commentIndexes[0]]; // Get the initial CommentViewTree

for (int i = 1; i < commentIndexes.length; i++) {
currentTree = currentTree.replies[commentIndexes[i]]; // Traverse to the next CommentViewTree
}

// Optimistically update the comment
CommentView? originalCommentView = currentTree.commentView;

CommentView updatedCommentView = optimisticallyVoteComment(currentTree.commentView!, event.score);
currentTree.commentView = updatedCommentView;

// Immediately set the status, and continue
emit(state.copyWith(status: PostStatus.success, selectedCommentId: state.selectedCommentId, selectedCommentPath: state.selectedCommentPath));
emit(state.copyWith(status: PostStatus.refreshing, selectedCommentId: state.selectedCommentId, selectedCommentPath: state.selectedCommentPath));

CommentView commentView = await voteComment(event.commentId, event.score).timeout(timeout, onTimeout: () {
currentTree.commentView = originalCommentView; // Reset this on exception
throw Exception(AppLocalizations.of(GlobalContext.context)!.timeoutUpvoteComment);
});

currentTree.commentView = commentView;

return emit(state.copyWith(status: PostStatus.success, selectedCommentId: state.selectedCommentId, selectedCommentPath: state.selectedCommentPath));
} catch (e) {
return emit(state.copyWith(status: PostStatus.failure, errorMessage: e.toString()));
}
}

Future<void> _saveCommentEvent(SaveCommentEvent event, Emitter<PostState> emit) async {
try {
emit(state.copyWith(status: PostStatus.refreshing, selectedCommentId: state.selectedCommentId, selectedCommentPath: state.selectedCommentPath));

CommentView commentView = await saveComment(event.commentId, event.save).timeout(timeout, onTimeout: () {
throw Exception(AppLocalizations.of(GlobalContext.context)!.timeoutSaveComment);
});

List<int> commentIndexes = findCommentIndexesFromCommentViewTree(state.comments, event.commentId);
CommentViewTree currentTree = state.comments[commentIndexes[0]]; // Get the initial CommentViewTree

for (int i = 1; i < commentIndexes.length; i++) {
currentTree = currentTree.replies[commentIndexes[i]]; // Traverse to the next CommentViewTree
}

currentTree.commentView = commentView; // Update the comment's information

return emit(state.copyWith(status: PostStatus.success, selectedCommentId: state.selectedCommentId, selectedCommentPath: state.selectedCommentPath));
} catch (e) {
emit(state.copyWith(status: PostStatus.failure, errorMessage: e.toString()));
}
}

Future<void> _deleteCommentEvent(DeleteCommentEvent event, Emitter<PostState> emit) async {
try {
emit(state.copyWith(status: PostStatus.refreshing, moddingCommentId: event.commentId, selectedCommentId: state.selectedCommentId, selectedCommentPath: state.selectedCommentPath));

Account? account = await fetchActiveProfileAccount();
LemmyApiV3 lemmy = LemmyClient.instance.lemmyApiV3;

if (account?.jwt == null) {
return emit(state.copyWith(
status: PostStatus.failure,
errorMessage: AppLocalizations.of(GlobalContext.context)!.loginToPerformAction,
selectedCommentId: state.selectedCommentId,
selectedCommentPath: state.selectedCommentPath));
}

if (state.postView?.postView.post.id == null) {
return emit(state.copyWith(
status: PostStatus.failure,
errorMessage: AppLocalizations.of(GlobalContext.context)!.couldNotDetermineCommentDelete,
selectedCommentId: state.selectedCommentId,
selectedCommentPath: state.selectedCommentPath));
}

CommentResponse deletedComment = await lemmy.run(DeleteComment(commentId: event.commentId, deleted: event.deleted, auth: account!.jwt!));
updateModifiedComment(state.comments, deletedComment.commentView);

return emit(
state.copyWith(status: PostStatus.success, comments: state.comments, moddingCommentId: -1, selectedCommentId: state.selectedCommentId, selectedCommentPath: state.selectedCommentPath));
} catch (e) {
return emit(state.copyWith(status: PostStatus.failure, errorMessage: e.toString(), moddingCommentId: -1));
}
}

/// This function updates a comment in the comments tree
Future<void> _updateCommentEvent(UpdateCommentEvent event, Emitter<PostState> emit) async {
/// The comment was created
if (event.isEdit) {
try {
emit(state.copyWith(
status: PostStatus.refreshing,
moddingCommentId: event.commentView.comment.id,
selectedCommentId: state.selectedCommentId,
selectedCommentPath: state.selectedCommentPath,
));

updateModifiedComment(state.comments, event.commentView);

return emit(state.copyWith(
status: PostStatus.success,
moddingCommentId: -1,
selectedCommentId: state.selectedCommentId,
selectedCommentPath: state.selectedCommentPath,
));
} catch (e) {
return emit(state.copyWith(status: PostStatus.failure, errorMessage: e.toString()));
}
}

/// The comment was created
try {
emit(state.copyWith(status: PostStatus.refreshing));

List<CommentViewTree> updatedComments = insertNewComment(state.comments, event.commentView);

return emit(state.copyWith(
status: PostStatus.success,
comments: updatedComments,
selectedCommentId: null,
selectedCommentPath: null,
newlyCreatedCommentId: event.commentView.comment.id,
));
} catch (e) {
return emit(state.copyWith(status: PostStatus.failure, errorMessage: e.toString()));
}
}

Future<void> _reportCommentEvent(ReportCommentEvent event, Emitter<PostState> emit) async {
try {
emit(state.copyWith(status: PostStatus.refreshing, moddingCommentId: event.commentId, selectedCommentId: state.selectedCommentId, selectedCommentPath: state.selectedCommentPath));
Expand Down
32 changes: 0 additions & 32 deletions lib/post/bloc/post_event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,38 +56,6 @@ final class CommentItemUpdatedEvent extends PostEvent {
const CommentItemUpdatedEvent({required this.commentView});
}

@Deprecated('Use CommentActionEvent instead')
class VoteCommentEvent extends PostEvent {
final int commentId;
final int score;

const VoteCommentEvent({required this.commentId, required this.score});
}

@Deprecated('Use CommentActionEvent instead')
class SaveCommentEvent extends PostEvent {
final int commentId;
final bool save;

const SaveCommentEvent({required this.commentId, required this.save});
}

@Deprecated('Use CommentActionEvent instead')
class DeleteCommentEvent extends PostEvent {
final int commentId;
final bool deleted;

const DeleteCommentEvent({required this.deleted, required this.commentId});
}

@Deprecated('Use CommentItemUpdatedEvent instead')
class UpdateCommentEvent extends PostEvent {
final CommentView commentView;
final bool isEdit;

const UpdateCommentEvent({required this.commentView, this.isEdit = false});
}

enum NavigateCommentDirection { up, down }

class NavigateCommentEvent extends PostEvent {
Expand Down
Loading

0 comments on commit 3046638

Please sign in to comment.