More fixes

This commit is contained in:
Tim Zöller 2025-11-30 10:33:28 +01:00
parent 96cf1fe5ad
commit d42f9b5339
5 changed files with 466 additions and 15 deletions

View file

@ -72,22 +72,31 @@ public class TimelineController {
/**
* Get the public timeline.
* Shows all public activities from all users.
* Optionally authenticated - if user is logged in, will show which activities they've liked.
*
* GET /api/timeline/public?page=0&size=20
*
* @param userDetails the authenticated user details (optional)
* @param page page number (default: 0)
* @param size page size (default: 20)
* @return page of timeline activities
*/
@GetMapping("/public")
public ResponseEntity<Page<TimelineActivityDTO>> getPublicTimeline(
@AuthenticationPrincipal(errorOnInvalidType = false) UserDetails userDetails,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size
) {
log.debug("Public timeline request");
UUID userId = null;
if (userDetails != null) {
userId = getUserId(userDetails);
log.debug("Public timeline request from authenticated user: {}", userId);
} else {
log.debug("Public timeline request (unauthenticated)");
}
Pageable pageable = PageRequest.of(page, size);
Page<TimelineActivityDTO> timeline = timelineService.getPublicTimeline(pageable);
Page<TimelineActivityDTO> timeline = timelineService.getPublicTimeline(userId, pageable);
return ResponseEntity.ok(timeline);
}

View file

@ -38,6 +38,11 @@ public class TimelineActivityDTO {
private String avatarUrl;
private boolean isLocal;
// Social interaction counts
private Long likesCount;
private Long commentsCount;
private Boolean likedByCurrentUser;
// Metrics summary
private ActivityMetricsSummary metrics;

View file

@ -33,6 +33,8 @@ public class TimelineService {
private final ActivityRepository activityRepository;
private final FollowRepository followRepository;
private final UserRepository userRepository;
private final org.operaton.fitpub.repository.LikeRepository likeRepository;
private final org.operaton.fitpub.repository.CommentRepository commentRepository;
@Value("${fitpub.base-url}")
private String baseUrl;
@ -74,12 +76,19 @@ public class TimelineService {
if (activityUser == null) {
return null;
}
return TimelineActivityDTO.fromActivity(
TimelineActivityDTO dto = TimelineActivityDTO.fromActivity(
activity,
activityUser.getUsername(),
activityUser.getDisplayName() != null ? activityUser.getDisplayName() : activityUser.getUsername(),
activityUser.getAvatarUrl()
);
// Add social interaction counts
dto.setLikesCount(likeRepository.countByActivityId(activity.getId()));
dto.setCommentsCount(commentRepository.countByActivityIdAndNotDeleted(activity.getId()));
dto.setLikedByCurrentUser(likeRepository.existsByActivityIdAndUserId(activity.getId(), userId));
return dto;
})
.filter(dto -> dto != null)
.collect(Collectors.toList());
@ -91,11 +100,12 @@ public class TimelineService {
* Get the public timeline.
* Shows all public activities from all users.
*
* @param userId optional user ID for checking liked status (null for unauthenticated)
* @param pageable pagination parameters
* @return page of timeline activities
*/
@Transactional(readOnly = true)
public Page<TimelineActivityDTO> getPublicTimeline(Pageable pageable) {
public Page<TimelineActivityDTO> getPublicTimeline(UUID userId, Pageable pageable) {
log.debug("Fetching public timeline");
// Fetch all public activities
@ -111,12 +121,25 @@ public class TimelineService {
if (activityUser == null) {
return null;
}
return TimelineActivityDTO.fromActivity(
TimelineActivityDTO dto = TimelineActivityDTO.fromActivity(
activity,
activityUser.getUsername(),
activityUser.getDisplayName() != null ? activityUser.getDisplayName() : activityUser.getUsername(),
activityUser.getAvatarUrl()
);
// Add social interaction counts
dto.setLikesCount(likeRepository.countByActivityId(activity.getId()));
dto.setCommentsCount(commentRepository.countByActivityIdAndNotDeleted(activity.getId()));
// Check if current user liked this activity (if authenticated)
if (userId != null) {
dto.setLikedByCurrentUser(likeRepository.existsByActivityIdAndUserId(activity.getId(), userId));
} else {
dto.setLikedByCurrentUser(false);
}
return dto;
})
.filter(dto -> dto != null)
.collect(Collectors.toList());
@ -141,12 +164,21 @@ public class TimelineService {
Page<Activity> activities = activityRepository.findByUserIdOrderByStartedAtDesc(userId, pageable);
List<TimelineActivityDTO> timelineActivities = activities.getContent().stream()
.map(activity -> TimelineActivityDTO.fromActivity(
activity,
user.getUsername(),
user.getDisplayName() != null ? user.getDisplayName() : user.getUsername(),
user.getAvatarUrl()
))
.map(activity -> {
TimelineActivityDTO dto = TimelineActivityDTO.fromActivity(
activity,
user.getUsername(),
user.getDisplayName() != null ? user.getDisplayName() : user.getUsername(),
user.getAvatarUrl()
);
// Add social interaction counts
dto.setLikesCount(likeRepository.countByActivityId(activity.getId()));
dto.setCommentsCount(commentRepository.countByActivityIdAndNotDeleted(activity.getId()));
dto.setLikedByCurrentUser(likeRepository.existsByActivityIdAndUserId(activity.getId(), userId));
return dto;
})
.collect(Collectors.toList());
return new PageImpl<>(timelineActivities, pageable, activities.getTotalElements());