feat: allow updating notification prefs

This commit is contained in:
Tim
2025-08-12 14:28:34 +08:00
parent d195d2f624
commit 02076e24e5
7 changed files with 151 additions and 10 deletions

View File

@@ -3,6 +3,8 @@ package com.openisle.controller;
import com.openisle.dto.NotificationDto;
import com.openisle.dto.NotificationMarkReadRequest;
import com.openisle.dto.NotificationUnreadCountDto;
import com.openisle.dto.NotificationPreferenceDto;
import com.openisle.dto.NotificationPreferenceUpdateRequest;
import com.openisle.mapper.NotificationMapper;
import com.openisle.service.NotificationService;
import lombok.RequiredArgsConstructor;
@@ -40,4 +42,14 @@ public class NotificationController {
public void markRead(@RequestBody NotificationMarkReadRequest req, Authentication auth) {
notificationService.markRead(auth.getName(), req.getIds());
}
@GetMapping("/prefs")
public List<NotificationPreferenceDto> prefs(Authentication auth) {
return notificationService.listPreferences(auth.getName());
}
@PostMapping("/prefs")
public void updatePref(@RequestBody NotificationPreferenceUpdateRequest req, Authentication auth) {
notificationService.updatePreference(auth.getName(), req.getType(), req.isEnabled());
}
}

View File

@@ -0,0 +1,11 @@
package com.openisle.dto;
import com.openisle.model.NotificationType;
import lombok.Data;
/** User notification preference DTO. */
@Data
public class NotificationPreferenceDto {
private NotificationType type;
private boolean enabled;
}

View File

@@ -0,0 +1,11 @@
package com.openisle.dto;
import com.openisle.model.NotificationType;
import lombok.Data;
/** Request to update a single notification preference. */
@Data
public class NotificationPreferenceUpdateRequest {
private NotificationType type;
private boolean enabled;
}

View File

@@ -7,6 +7,8 @@ import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Set;
/**
* Simple user entity with basic fields and a role.
@@ -62,6 +64,12 @@ public class User {
@Enumerated(EnumType.STRING)
private MedalType displayMedal;
@ElementCollection(targetClass = NotificationType.class)
@CollectionTable(name = "user_disabled_notification_types", joinColumns = @JoinColumn(name = "user_id"))
@Column(name = "notification_type")
@Enumerated(EnumType.STRING)
private Set<NotificationType> disabledNotificationTypes = new HashSet<>();
@CreationTimestamp
@Column(nullable = false, updatable = false,
columnDefinition = "DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6)")

View File

@@ -1,6 +1,7 @@
package com.openisle.service;
import com.openisle.model.*;
import com.openisle.dto.NotificationPreferenceDto;
import com.openisle.repository.NotificationRepository;
import com.openisle.repository.ReactionRepository;
import com.openisle.repository.UserRepository;
@@ -20,7 +21,9 @@ import java.util.Set;
import java.util.HashSet;
import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
/** Service for creating and retrieving notifications. */
@Service
@@ -138,13 +141,43 @@ public class NotificationService {
}
}
public List<NotificationPreferenceDto> listPreferences(String username) {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found"));
Set<NotificationType> disabled = user.getDisabledNotificationTypes();
List<NotificationPreferenceDto> prefs = new ArrayList<>();
for (NotificationType nt : NotificationType.values()) {
NotificationPreferenceDto dto = new NotificationPreferenceDto();
dto.setType(nt);
dto.setEnabled(!disabled.contains(nt));
prefs.add(dto);
}
return prefs;
}
public void updatePreference(String username, NotificationType type, boolean enabled) {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found"));
Set<NotificationType> disabled = user.getDisabledNotificationTypes();
if (enabled) {
disabled.remove(type);
} else {
disabled.add(type);
}
userRepository.save(user);
}
public List<Notification> listNotifications(String username, Boolean read) {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found"));
Set<NotificationType> disabled = user.getDisabledNotificationTypes();
List<Notification> list;
if (read == null) {
return notificationRepository.findByUserOrderByCreatedAtDesc(user);
list = notificationRepository.findByUserOrderByCreatedAtDesc(user);
} else {
list = notificationRepository.findByUserAndReadOrderByCreatedAtDesc(user, read);
}
return notificationRepository.findByUserAndReadOrderByCreatedAtDesc(user, read);
return list.stream().filter(n -> !disabled.contains(n.getType())).collect(Collectors.toList());
}
public void markRead(String username, List<Long> ids) {
@@ -162,7 +195,9 @@ public class NotificationService {
public long countUnread(String username) {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found"));
return notificationRepository.countByUserAndRead(user, false);
Set<NotificationType> disabled = user.getDisabledNotificationTypes();
return notificationRepository.findByUserAndReadOrderByCreatedAtDesc(user, false).stream()
.filter(n -> !disabled.contains(n.getType())).count();
}
public void notifyMentions(String content, User fromUser, Post post, Comment comment) {