Skip to content

Commit

Permalink
Merge pull request thunder-app#396 from ajsosa/comments
Browse files Browse the repository at this point in the history
Initial support for viewing comment context.
  • Loading branch information
hjiangsu authored Jul 19, 2023
2 parents dc2b3d6 + 5535efe commit d12589e
Show file tree
Hide file tree
Showing 10 changed files with 186 additions and 69 deletions.
29 changes: 23 additions & 6 deletions lib/post/bloc/post_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -113,16 +113,22 @@ class PostBloc extends Bloc<PostEvent, PostState> {

CommentSortType sortType = event.sortType ?? (state.sortType ?? defaultSortType);

int? parentId;
if (event.selectedCommentPath != null) {
parentId = int.parse(event.selectedCommentPath!.split('.')[1]);
}

List<CommentView> getCommentsResponse = await lemmy
.run(GetComments(
page: 1,
page: event.selectedCommentId == null ? 1 : null,
auth: account?.jwt,
communityId: postView?.postView.post.communityId,
maxDepth: COMMENT_MAX_DEPTH,
postId: postView?.postView.post.id,
sort: sortType,
limit: commentLimit,
type: CommentListingType.all,
parentId: parentId,
))
.timeout(timeout, onTimeout: () {
throw Exception('Error: Timeout when attempting to fetch comments');
Expand All @@ -142,12 +148,14 @@ class PostBloc extends Bloc<PostEvent, PostState> {
postId: postView?.postView.post.id,
postView: postView,
comments: commentTree,
commentPage: state.commentPage + (event.selectedCommentId == null ? 1 : 0),
commentResponseMap: responseMap,
commentPage: state.commentPage + 1,
commentCount: getCommentsResponse.length,
hasReachedCommentEnd: getCommentsResponse.isEmpty || getCommentsResponse.length < commentLimit,
communityId: postView?.postView.post.communityId,
sortType: sortType),
sortType: sortType,
selectedCommentId: event.selectedCommentId,
selectedCommentPath: event.selectedCommentPath),
);
} catch (e, s) {
exception = e;
Expand Down Expand Up @@ -178,8 +186,12 @@ class PostBloc extends Bloc<PostEvent, PostState> {
try {
LemmyApiV3 lemmy = LemmyClient.instance.lemmyApiV3;

if (event.reset) {
emit(state.copyWith(status: PostStatus.loading));
if (event.reset || event.viewAllCommentsRefresh) {
if (event.viewAllCommentsRefresh) {
emit(state.copyWith(status: PostStatus.refreshing, selectedCommentId: state.selectedCommentId, viewAllCommentsRefresh: true, sortType: sortType));
} else {
emit(state.copyWith(status: PostStatus.loading, sortType: sortType));
}

List<CommentView> getCommentsResponse = await lemmy
.run(GetComments(
Expand Down Expand Up @@ -207,6 +219,8 @@ class PostBloc extends Bloc<PostEvent, PostState> {

return emit(
state.copyWith(
selectedCommentId: null,
selectedCommentPath: null,
status: PostStatus.success,
comments: commentTree,
commentResponseMap: responseMap,
Expand All @@ -230,7 +244,7 @@ class PostBloc extends Bloc<PostEvent, PostState> {
sort: sortType,
limit: commentLimit,
maxDepth: COMMENT_MAX_DEPTH,
page: event.commentParentId != null ? 1 : state.commentPage,
page: state.commentPage, //event.commentParentId != null ? 1 : state.commentPage,
type: CommentListingType.all,
))
.timeout(timeout, onTimeout: () {
Expand All @@ -248,7 +262,10 @@ class PostBloc extends Bloc<PostEvent, PostState> {

// We'll add in a edge case here to stop fetching comments after theres no more comments to be fetched
return emit(state.copyWith(
sortType: sortType,
status: PostStatus.success,
selectedCommentPath: null,
selectedCommentId: null,
comments: commentViewTree,
commentResponseMap: state.commentResponseMap,
commentPage: event.commentParentId != null ? 1 : state.commentPage + 1,
Expand Down
7 changes: 5 additions & 2 deletions lib/post/bloc/post_event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,20 @@ class GetPostEvent extends PostEvent {
final int? postId;
final PostViewMedia? postView;
final CommentSortType? sortType;
final String? selectedCommentPath;
final int? selectedCommentId;

const GetPostEvent({this.sortType, this.postView, this.postId});
const GetPostEvent({this.sortType, this.postView, this.postId, this.selectedCommentPath, this.selectedCommentId});
}

class GetPostCommentsEvent extends PostEvent {
final int? postId;
final int? commentParentId;
final bool reset;
final bool viewAllCommentsRefresh;
final CommentSortType? sortType;

const GetPostCommentsEvent({this.postId, this.commentParentId, this.reset = false, this.sortType});
const GetPostCommentsEvent({this.postId, this.commentParentId, this.reset = false, this.viewAllCommentsRefresh = false, this.sortType});
}

class VotePostEvent extends PostEvent {
Expand Down
21 changes: 17 additions & 4 deletions lib/post/bloc/post_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,15 @@ class PostState extends Equatable {
this.hasReachedCommentEnd = false,
this.errorMessage,
this.sortType,
this.sortTypeIcon});
this.sortTypeIcon,
this.selectedCommentId,
this.selectedCommentPath,
this.viewAllCommentsRefresh = false});

final PostStatus status;

final bool viewAllCommentsRefresh;

final CommentSortType? sortType;
final IconData? sortTypeIcon;

Expand All @@ -32,6 +37,8 @@ class PostState extends Equatable {
final int commentPage;
final int commentCount;
final bool hasReachedCommentEnd;
final int? selectedCommentId;
final String? selectedCommentPath;

final String? errorMessage;

Expand All @@ -48,6 +55,9 @@ class PostState extends Equatable {
String? errorMessage,
CommentSortType? sortType,
IconData? sortTypeIcon,
int? selectedCommentId,
String? selectedCommentPath,
bool? viewAllCommentsRefresh = false,
}) {
return PostState(
status: status,
Expand All @@ -60,11 +70,14 @@ class PostState extends Equatable {
hasReachedCommentEnd: hasReachedCommentEnd ?? this.hasReachedCommentEnd,
communityId: communityId ?? this.communityId,
errorMessage: errorMessage ?? this.errorMessage,
sortType: sortType,
sortTypeIcon: sortTypeIcon,
sortType: sortType ?? this.sortType,
sortTypeIcon: sortTypeIcon ?? this.sortTypeIcon,
selectedCommentId: selectedCommentId,
selectedCommentPath: selectedCommentPath,
viewAllCommentsRefresh: viewAllCommentsRefresh ?? false,
);
}

@override
List<Object?> get props => [status, postId, postView, comments, commentPage, commentCount, communityId, errorMessage, hasReachedCommentEnd, sortType, sortTypeIcon];
List<Object?> get props => [status, postId, postView, comments, commentPage, commentCount, communityId, errorMessage, hasReachedCommentEnd, sortType, sortTypeIcon, selectedCommentId, selectedCommentPath, viewAllCommentsRefresh];
}
14 changes: 9 additions & 5 deletions lib/post/pages/post_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ import 'package:thunder/thunder/bloc/thunder_bloc.dart';
class PostPage extends StatefulWidget {
final PostViewMedia? postView;
final int? postId;
final String? selectedCommentPath;
final int? selectedCommentId;

final VoidCallback onPostUpdated;

const PostPage({super.key, this.postView, this.postId, required this.onPostUpdated});
const PostPage({super.key, this.postView, this.postId, this.selectedCommentPath, this.selectedCommentId, required this.onPostUpdated});

@override
State<PostPage> createState() => _PostPageState();
Expand Down Expand Up @@ -196,7 +198,6 @@ class _PostPageState extends State<PostPage> {
backgroundColor: theme.colorScheme.onErrorContainer,
behavior: SnackBarBehavior.floating,
);

WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(snackBar);
Expand All @@ -205,7 +206,8 @@ class _PostPageState extends State<PostPage> {
}
switch (state.status) {
case PostStatus.initial:
context.read<PostBloc>().add(GetPostEvent(postView: widget.postView, postId: widget.postId));
context.read<PostBloc>().add(GetPostEvent(postView: widget.postView, postId: widget.postId,
selectedCommentPath: widget.selectedCommentPath, selectedCommentId: widget.selectedCommentId));
return const Center(child: CircularProgressIndicator());
case PostStatus.loading:
return const Center(child: CircularProgressIndicator());
Expand All @@ -216,9 +218,11 @@ class _PostPageState extends State<PostPage> {
return RefreshIndicator(
onRefresh: () async {
HapticFeedback.mediumImpact();
return context.read<PostBloc>().add(GetPostEvent(postView: widget.postView, postId: widget.postId));
return context.read<PostBloc>().add(GetPostEvent(postView: widget.postView, postId: widget.postId,
selectedCommentId: state.selectedCommentId, selectedCommentPath: state.selectedCommentPath));
},
child: PostPageSuccess(postView: state.postView!, comments: state.comments, scrollController: _scrollController, hasReachedCommentEnd: state.hasReachedCommentEnd),
child: PostPageSuccess(postView: state.postView!, comments: state.comments, selectedCommentId: state.selectedCommentId,
viewFullCommentsRefreshing: state.viewAllCommentsRefresh, scrollController: _scrollController, hasReachedCommentEnd: state.hasReachedCommentEnd),
);
}
return ErrorMessage(
Expand Down
13 changes: 13 additions & 0 deletions lib/post/pages/post_page_success.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,21 @@ import 'package:thunder/post/widgets/comment_view.dart';
class PostPageSuccess extends StatefulWidget {
final PostViewMedia postView;
final List<CommentViewTree> comments;
final int? selectedCommentId;

final ScrollController scrollController;
final bool hasReachedCommentEnd;

final bool viewFullCommentsRefreshing;

const PostPageSuccess({
super.key,
required this.postView,
this.comments = const [],
required this.scrollController,
this.hasReachedCommentEnd = false,
this.selectedCommentId,
this.viewFullCommentsRefreshing = false,
});

@override
Expand All @@ -41,6 +46,12 @@ class _PostPageSuccessState extends State<PostPageSuccess> {
}

void _onScroll() {
// We don't want to trigger comment fetch when looking at a comment context.
// This also fixes a weird behavior that can happen when if the fetch triggers
// right before you click view all comments. The fetch for all comments won't happen.
if (widget.selectedCommentId != null) {
return;
}
if (widget.scrollController.position.pixels >= widget.scrollController.position.maxScrollExtent * 0.6) {
context.read<PostBloc>().add(const GetPostCommentsEvent());
}
Expand All @@ -52,6 +63,8 @@ class _PostPageSuccessState extends State<PostPageSuccess> {
children: [
Expanded(
child: CommentSubview(
viewFullCommentsRefreshing: widget.viewFullCommentsRefreshing,
selectedCommentId: widget.selectedCommentId,
now: DateTime.now().toUtc(),
scrollController: widget.scrollController,
postViewMedia: widget.postView,
Expand Down
4 changes: 4 additions & 0 deletions lib/post/widgets/comment_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class CommentCard extends StatefulWidget {
final Function(int, bool) onCollapseCommentChange;

final Set collapsedCommentSet;
final int? selectCommentId;

final DateTime now;

Expand All @@ -35,6 +36,7 @@ class CommentCard extends StatefulWidget {
required this.onCollapseCommentChange,
required this.now,
this.collapsedCommentSet = const {},
this.selectCommentId,
});

/// CommentViewTree containing relevant information
Expand Down Expand Up @@ -127,6 +129,7 @@ class _CommentCardState extends State<CommentCard> with SingleTickerProviderStat

return Container(
decoration: BoxDecoration(
color: widget.selectCommentId == widget.commentViewTree.commentView!.comment.id ? theme.highlightColor : theme.colorScheme.background,
border: widget.level > 0
? Border(
left: BorderSide(
Expand Down Expand Up @@ -374,6 +377,7 @@ class _CommentCardState extends State<CommentCard> with SingleTickerProviderStat
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) => CommentCard(
selectCommentId: widget.selectCommentId,
now: widget.now,
commentViewTree: widget.commentViewTree.replies[index],
collapsedCommentSet: widget.collapsedCommentSet,
Expand Down
Loading

0 comments on commit d12589e

Please sign in to comment.