Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -124,22 +124,22 @@ List<Notification> findUnreadGroupedNotificationsForUpdate(
Pageable pageable
);

// 미읽음 그룹 알림이 없으면 누적 개수는 0이다.
@Query("""
select coalesce(max(n.groupCount), 0)
select n.targetId, coalesce(max(n.groupCount), 0)
from Notification n
where n.user.id = :userId
and n.type = :type
and n.targetType = :targetType
and n.targetId = :targetId
and n.targetId in :targetIds
and n.isRead = false
and n.deletedAt is null
group by n.targetId
""")
int findUnreadGroupedNotificationCount(
List<Object[]> findUnreadGroupedNotificationCounts(
@Param("userId") Long userId,
@Param("type") NotificationType type,
@Param("targetType") String targetType,
@Param("targetId") Long targetId
@Param("targetIds") List<Long> targetIds
);
Comment thread
young0206 marked this conversation as resolved.

@Modifying(clearAutomatically = true, flushAutomatically = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.function.IntFunction;

@Service
Expand Down Expand Up @@ -101,18 +103,24 @@ public void markAllNotificationsAsRead(Long currentUserId) {
}

/**
* 영상 카드의 미읽은 피드백 개수에 사용할 그룹 알림 누적 개수를 조회한다.
* 영상 목록의 미읽은 피드백 누적 개수를 한 번에 조회한다.
*/
public int getUnreadVideoFeedbackCount(Long currentUserId, Long videoId) {
public Map<Long, Integer> getUnreadVideoFeedbackCounts(Long currentUserId, List<Long> videoIds) {
validateActiveUser(currentUserId);
validateRequiredId(videoId);
if (videoIds.isEmpty()) {
return Map.of();
}

return notificationRepository.findUnreadGroupedNotificationCount(
currentUserId,
NotificationType.VIDEO_FEEDBACK_COMMENTED,
NotificationTargetType.VIDEO.name(),
videoId
);
return notificationRepository.findUnreadGroupedNotificationCounts(
currentUserId,
NotificationType.VIDEO_FEEDBACK_COMMENTED,
NotificationTargetType.VIDEO.name(),
videoIds
).stream()
.collect(Collectors.toMap(
row -> (Long) row[0],
row -> ((Number) row[1]).intValue()
));
}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,18 @@ public record VideoDetailResDTO(
String thumbnailUrl,
@Schema(description = "영상 진행 상태", example = "IN_PROGRESS") String progressStatus,
@Schema(description = "로그인한 사용자의 북마크 여부", example = "true") boolean bookmarked,
@Schema(description = "로그인한 사용자의 읽지 않은 피드백 개수", example = "0")
int unreadCommentCount,
@Schema(description = "프로젝트 소개", example = "프로젝트 소개글") String description,
@Schema(description = "영상 메모", example = "영상에 관련된 메모", nullable = true) String memo,
@Schema(description = "프로젝트 태그", example = "[\"뮤직비디오\", \"단편\", \"외주\", \"연출\"]")
List<String> projectTags,
@Schema(description = "생성일", example = "2026-05-20T00:00:00") LocalDateTime createdAt,
@Schema(description = "수정일", example = "2026-05-25T00:00:00") LocalDateTime updatedAt
) {
public static VideoDetailResDTO from(Video video, boolean bookmarked, List<String> projectTags) {
// TODO: 피드백 도메인의 사용자별 읽지 않은 피드백 개수 조회 기능 연동 후 실제 값으로 교체
int unreadCommentCount = 0;

public static VideoDetailResDTO from(
Video video,
boolean bookmarked,
List<String> projectTags
) {
return new VideoDetailResDTO(
video.getId(),
video.getProject().getId(),
Expand All @@ -44,7 +43,6 @@ public static VideoDetailResDTO from(Video video, boolean bookmarked, List<Strin
video.getThumbnailUrl(),
video.getProgressStatus().name(),
bookmarked,
unreadCommentCount,
video.getProject().getDescription(),
video.getMemo(),
projectTags,
Expand Down Expand Up @@ -132,14 +130,15 @@ public record VideoItemResDTO(
@Schema(example = "https://img.youtube.com/vi/abc123/maxresdefault.jpg") String thumbnailUrl,
@Schema(example = "true") boolean bookmarked,
@Schema(example = "IN_PROGRESS") String progressStatus,
@Schema(example = "3") int unreadCommentCount,
@Schema(description = "읽지 않은 피드백 존재 여부", example = "true")
boolean hasUnreadFeedback,
LocalDateTime createdAt,
LocalDateTime updatedAt
) {
public static VideoItemResDTO from(Video video, boolean bookmarked) {
public static VideoItemResDTO from(Video video, boolean bookmarked, boolean hasUnreadFeedback) {
return new VideoItemResDTO(
video.getId(), video.getTitle(), video.getThumbnailUrl(), bookmarked,
video.getProgressStatus().name(), 0, video.getCreatedAt(), video.getUpdatedAt()
video.getProgressStatus().name(), hasUnreadFeedback, video.getCreatedAt(), video.getUpdatedAt()
);
}
}
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/com/slatto/domain/video/service/VideoService.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.slatto.domain.video.service;

import com.slatto.domain.project.entity.Project;
import com.slatto.domain.notification.service.NotificationService;
import com.slatto.domain.project.enums.LengthType;
import com.slatto.domain.user.enums.CategoryName;
import com.slatto.domain.user.enums.Kind;
Expand Down Expand Up @@ -32,6 +33,7 @@
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;

Expand All @@ -53,6 +55,7 @@ public class VideoService {
private final VideoProjectAccessRepository projectAccessRepository;
private final VideoRepository videoRepository;
private final VideoBookmarkRepository videoBookmarkRepository;
private final NotificationService notificationService;
private final YoutubeUrlParser youtubeUrlParser;
private final YoutubeApiClient youtubeApiClient;

Expand Down Expand Up @@ -192,10 +195,15 @@ public VideoListResDTO getVideos(Long memberId, Long projectId, Long cursor, Int
Set<Long> bookmarkedVideoIds = videoIds.isEmpty()
? Set.of()
: Set.copyOf(videoBookmarkRepository.findBookmarkedVideoIdsByUserIdAndVideoIds(memberId, videoIds));
Map<Long, Integer> unreadCommentCounts = notificationService.getUnreadVideoFeedbackCounts(
memberId,
videoIds
);
List<VideoItemResDTO> items = currentPageVideos.stream()
.map(video -> VideoItemResDTO.from(
video,
bookmarkedVideoIds.contains(video.getId())
bookmarkedVideoIds.contains(video.getId()),
unreadCommentCounts.getOrDefault(video.getId(), 0) > 0
))
.toList();
Long nextCursor = hasNext && !items.isEmpty() ? items.getLast().videoId() : null;
Expand Down
Loading