메세지를 보낼때 메세지가 왔다는 알람이 오려면
메세지를 보낸 사람이 알람을 보내줘야 한다
알람을 보내기 위한 SQL 쿼리문 작성
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.repository.AlarmRepository">
<!-- 상대한테 알람보내기 -->
<insert id = "sendAlarm">
insert into alarm_tb (type, type_id, user_id, opponent_id, content)
values(#{type},#{typeId},#{userId},#{opponentId},#{content})
</insert>
<!-- 나한테 온 알람 전부 받아오기 -->
<select id = "findAlarmAll" resultType="com.example.demo.repository.model.Alarm">
select * from alarm_tb
where user_id = #{userId}
order by id DESC
</select>
<!-- 읽은 알람은 상태값 변경 -->
<update id="changeStatusBatch">
UPDATE alarm_tb
SET status = 1
WHERE id IN
<foreach collection="alarmIdList" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</update>
<!-- 알람 삭제 -->
<delete id="deleteAlarmBatch">
DELETE FROM alarm_tb
WHERE id IN
<foreach collection="alarmIdList" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<!-- 알람 전부 삭제 -->
<delete id = "deleteAlarmAll">
delete from alarm_tb
where user_id = #{userId}
</delete>
<!-- 알람 확인했는지 체크 -->
<select id = "checkStatusAlarm" resultType ="Integer">
select status from alarm_tb
where user_id = #{userId}
and opponent_id = #{opponentId}
and type = 1
</select>
</mapper>
친구요청을 보낼때, 수락했을때, 거절했을때, 채팅을 보냈을때 알람을 전송하도록 리팩토리
// 친구 요청 보내기
@PostMapping("/sendFriend")
@ResponseBody
public String postMethodName(@RequestBody FriendDTO friendDTO) {
User principal = (User)session.getAttribute("principal");
List<User> sendList = friendService.checkSendFriendList(friendDTO.getUserId());
List<User> friendList = friendService.findFriendList(friendDTO.getUserId());
for(User user : sendList) { // 이미 친구추가 요청을 보낸 사용자인지 확인
if(user.getUserId() == friendDTO.getFriendId()) {
return "이미 친구요청을 보낸 사용자입니다.";
}
}
for(User user : friendList) { // 이미 친구추가 되어있는 사용자인지 확인
if(user.getUserId() == friendDTO.getFriendId()) {
return "이미 친구추가된 사용자입니다.";
}
}
friendService.insertWaitingFriend(friendDTO.getUserId(), friendDTO.getFriendId());
Alarm alarm = Alarm.builder().type(2).userId(friendDTO.getFriendId())
.opponentId(friendDTO.getUserId()).content(principal.getNickname() + " 님이 친구추가 요청을 보냈습니다.").build();
alarmService.sendAlarm(alarm);
return "친구요청 성공";
}
// 친구 요청 수락
@GetMapping("/accept/{id}")
@ResponseBody
public String acceptFriend(@PathVariable("id")int id) {
User user = (User)session.getAttribute("principal");
int userId = user.getUserId();
int result = friendService.checkWaitFriend(id, userId);
if(result != 0) {
friendService.addFriend(userId, id);
friendService.removeWaitFriend(id, userId);
friendService.removeWaitFriend(userId, id); // 서로 신청했을수있으니 다 삭제
Alarm alarm = Alarm.builder().type(2).userId(id).opponentId(userId)
.content(user.getNickname() + " 님이 친구요청을 수락하셨습니다").build();
alarmService.sendAlarm(alarm);
return "친구 요청 수락 성공";
} else {
return "친구 요청 수락 실패";
}
}
// 친구 요청 거절
@GetMapping("refuse/{id}")
@ResponseBody
public String refuseFriend(@PathVariable("id")int id) {
User user = (User)session.getAttribute("principal");
int userId = user.getUserId();
int result = 0;
result = friendService.removeWaitFriend(id, userId);
if(result != 0) {
Alarm alarm = Alarm.builder().type(2).userId(id).opponentId(userId)
.content(user.getNickname() + " 님이 친구요청을 거절하셨습니다").build();
alarmService.sendAlarm(alarm);
}
return "친구 요청 거절 성공";
}
@Override // 데이터 통신시
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
User user = (User) session.getAttributes().get("principal");
Integer key = (Integer) session.getAttributes().get("key");
ObjectMapper objectMapper = new ObjectMapper();
String userMessage = message.getPayload();
MessageDTO messageDTO = MessageDTO.builder().name(user.getNickname()).uploadFileName(user.getUploadFileName())
.message(userMessage).build();
boolean view = false; // 상대가 매세지를 봤는지 확인
for (WebSocketSession users : KEYS.keySet()) {
if (KEYS.get(users) == key && users != session) {
users.sendMessage(new TextMessage(objectMapper.writeValueAsString(messageDTO)));
view = true;
}
}
if(view == false) {
// 방에 상대방이 없다면 알림 전송
// 상대방에게 간 알림이 상태값이 0이면 전송 X
List<User>userList = chatService.getUserList(key);
for(User opponent : userList) {
if(opponent.getUserId() != user.getUserId()) {
List<Integer>statusList = alarmService.checkStatusAlarm(opponent.getUserId(), user.getUserId());
if(statusList != null) {
int read = 0;
for(int i : statusList) {
if(i == 1) {
read++;
}
}
if(read == statusList.size()) {
// 만약 알림을 전부 읽은 상태라면 새로운 알림을 보냄
String content = user.getNickname() + " 님이 채팅을 보내셨습니다.";
Alarm alarm = Alarm.builder().type(1).typeId(key).userId(opponent.getUserId())
.opponentId(user.getUserId()).content(content).build();
alarmService.sendAlarm(alarm);
}
} else {
// 만약 보낸 채팅 알람이 하나도 없다면 새로운 알림을 보냄
String content = user.getNickname() + " 님이 채팅을 보내셨습니다.";
Alarm alarm = Alarm.builder().type(1).typeId(key).userId(opponent.getUserId())
.opponentId(user.getUserId()).content(content).build();
alarmService.sendAlarm(alarm);
}
}
}
}
saveFile(user, message.getPayload(), key); // 채팅 로그 저장
saveLogByJSON(user, userMessage, key); // 채팅 JSON으로 저장
}
로그인하면 모든 페이지에 따라다닐 header에 알람 div 추가
<div class="alarm-box">
<div class="alarm-header">
<input type="checkbox" id="select-all" style="display: none;">
<span class="alarm-all active" onclick="selectAlarmType(this)">전체</span>
<span class="alarm-friend" onclick="selectAlarmType(this)">친구</span>
<span class="alarm-post" onclick="selectAlarmType(this)">게시글</span> <span
class="alarm-chat" onclick="selectAlarmType(this)">채팅</span> <span
class="alarm-lecture" onclick="selectAlarmType(this)">강의</span> <span
class="alarm-delete" onclick="toggleDeleteMode()">삭제하기</span>
</div>
<!-- 삭제 모드가 활성화되면 보여줄 요소 -->
<div class="delete-header" style="display: none;">
<input type="checkbox" id="selectAll" class="round-checkbox"
onclick="toggleSelectAll()"> <label for="selectAll">전체선택</label>
<button class="delete-alarms-btn" onclick="deleteSelectedAlarms()">삭제하기</button>
<button class="cancel-btn" onclick="cancelDeleteMode()">취소</button>
</div>
<div class="alarm-content"></div>
</div>
새로고침할때마다 서버에 새로운 알림이 있으면 가져오도록 하는 스크립트 추가
<script>
var socket = new WebSocket("ws://localhost:8080/alarm");
const alarmBox = document.querySelector(".alarm-box");
const alarmBell = document.querySelector(".alarm-bell");
const alarmContent = document.querySelector(".alarm-content");
let alarmList;
const alarmHeader = document.querySelector(".alarm-header"); // 기존 알람 헤더
let originalHeaderHTML = alarmHeader.innerHTML; // 원래의 헤더 내용을 저장
let deleteMode = false;
let selectedAlarms = [];
alarmBox.style.display = 'none';
// 알림 정보를 서버에서 가져와서 알림 창에 표시
fetch("http://localhost:8080/user/alarm")
.then((response) => response.text())
.then((text) => {
if (text !== null) {
alarmList = JSON.parse(text);
console.log(alarmList);
if (alarmList.length > 0) {
alarmList.forEach(function (alarms) {
const alarm = document.createElement("div");
const opponentPic = document.createElement("img");
const opponentName = document.createElement("span");
const content = document.createElement("span");
const checkbox = document.createElement("input");
const hiddenId = document.createElement("input");
alarm.classList.add("alarm-element");
checkbox.type = "checkbox";
checkbox.style.display = "none"; // 처음엔 숨김
hiddenId.type = "hidden";
hiddenId.value = alarms.id; // 알람 ID 저장
opponentPic.classList.add("alarm-pic");
content.classList.add("alarm-message");
if (alarms.uploadFileName === null) {
opponentPic.src = "/static/images/defaultProfile.jpeg";
} else {
opponentPic.src = "/images/" + alarms.uploadFileName;
}
opponentName.innerText = alarms.nickname;
content.innerText = alarms.content;
alarm.appendChild(checkbox); // 체크박스 추가
alarm.appendChild(hiddenId); // 숨겨진 ID 추가
alarm.appendChild(opponentPic);
alarm.appendChild(content);
// 체크박스 클릭 시 이벤트 전파 중지
checkbox.addEventListener('click', function(event) {
event.stopPropagation(); // 이벤트 전파 중지하여 체크박스 클릭 시 div의 이벤트가 발생하지 않도록 함
if (checkbox.checked) {
selectedAlarms.push(alarms.id); // 체크된 경우 선택된 알람 ID 추가
} else {
selectedAlarms = selectedAlarms.filter(id => id !== alarms.id); // 체크 해제 시 ID 제거
}
});
// 클릭 시 체크박스 선택
alarm.addEventListener('click', function () {
if (deleteMode) {
checkbox.checked = !checkbox.checked;
if (checkbox.checked) {
selectedAlarms.push(alarms.id); // 선택된 알람 ID 추가
} else {
selectedAlarms = selectedAlarms.filter(id => id !== alarms.id); // 선택 해제 시 ID 제거
}
} else {
// 원래의 클릭 이벤트 동작
if (alarms.userId !== undefined) {
window.open(`${pageContext.request.contextPath}/user/move?type=` + alarms.type + '&userId=' + alarms.userId);
} else {
location.href = `${pageContext.request.contextPath}/user/move?type=` + alarms.type + '&userId=0';
}
}
});
alarmContent.appendChild(alarm);
// 새로운 알림이 있을 경우 알림 아이콘 변경
if (alarms.status === 0) {
alarmBell.src = "/static/images/alarm2.png";
}
});
} else {
const noAlarmMessage = document.createElement("div");
noAlarmMessage.classList.add("no-alarm-message");
noAlarmMessage.innerText = "알림이 없습니다.";
alarmContent.appendChild(noAlarmMessage);
}
}
});
// 알림 벨 클릭 시 알림 창이 벨 왼쪽 하단에 나타나도록 수정
alarmBell.addEventListener('click', function(event) {
if (alarmBox.style.display === 'none') {
const bellPosition = alarmBell.getBoundingClientRect();
alarmBox.style.left = (bellPosition.left - 310) + "px"; // 왼쪽으로 310px 이동
alarmBox.style.top = (bellPosition.bottom + 10) + "px"; // 벨 아래로 약간의 간격
alarmBox.style.display = 'block';
alarmBell.src = "/static/images/alarm.png";
// 서버에 읽은 상태 업데이트
fetch("http://localhost:8080/user/status", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(alarmList) // alarmList 자체를 JSON으로 변환
})
.then((response) => response.text())
.then((text) => {
console.log(text);
});
} else {
alarmBox.style.display = 'none';
}
});
// 삭제 모드로 전환
function toggleDeleteMode() {
deleteMode = !deleteMode;
const checkboxes = document.querySelectorAll(".alarm-element input[type='checkbox']");
if (deleteMode) {
// 삭제 모드 활성화 시 delete-header 표시
alarmHeader.innerHTML = `
<span>
<input type="checkbox" id="select-all" onchange="toggleSelectAll(this)">
<label for="select-all">전체 선택</label>
</span>
<button onclick="deleteSelectedAlarms()">삭제하기</button>
<button onclick="toggleDeleteMode()">취소</button>
`;
checkboxes.forEach(checkbox => checkbox.style.display = "block"); // 체크박스 표시
} else {
// 삭제 모드 비활성화 시 원래의 헤더로 복구
alarmHeader.innerHTML = originalHeaderHTML;
checkboxes.forEach(checkbox => checkbox.style.display = "none"); // 체크박스 숨김
}
}
// 전체 선택 기능
function toggleSelectAll(selectAllCheckbox) {
const checkboxes = document.querySelectorAll(".alarm-element input[type='checkbox']");
selectedAlarms = []; // 초기화
if (selectAllCheckbox.checked) {
checkboxes.forEach(checkbox => {
checkbox.checked = true;
const id = checkbox.nextElementSibling.value; // hidden input에 저장된 ID 가져오기
selectedAlarms.push(parseInt(id));
});
} else {
checkboxes.forEach(checkbox => checkbox.checked = false);
selectedAlarms = [];
}
}
// 선택된 알람 삭제
function deleteSelectedAlarms() {
if (selectedAlarms.length === 0) {
alert("삭제할 알림을 선택하세요.");
return;
}
fetch("http://localhost:8080/user/deleteAlarm", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(selectedAlarms) // 선택된 알람 ID를 서버로 전송
})
.then((response) => response.text())
.then((text) => {
console.log(text);
if (text === 'ok') {
// 삭제 성공 후 화면에서 선택된 알람 요소 제거
selectedAlarms.forEach(id => {
const alarmElement = document.querySelector('input[value="'+id+'"]').closest('.alarm-element');
if (alarmElement) {
alarmElement.remove(); // 해당 알람 DOM 요소 제거
}
});
// 선택된 알람 리스트 초기화
selectedAlarms = [];
alert('선택된 알람이 삭제되었습니다.');
} else {
alert('알람 삭제에 실패했습니다.');
}
})
.catch((error) => {
console.error('Error:', error);
});
}
function match(id) {
if (${principal.mbti == 0}) {
alert("먼저 mbti 검사를 하셔야합니다!");
} else {
location.href = "http://localhost:8080/chat/match?type=" + id;
}
}
function selectAlarmType(selected) {
// 기존의 active 클래스 제거
document.querySelectorAll('.alarm-header span').forEach(function (item) {
item.classList.remove('active');
});
// 선택된 항목에 active 클래스 추가
selected.classList.add('active');
}
</script>
'My Project > Final Project' 카테고리의 다른 글
2024-09-20 (알람 기능 완성) (0) | 2024.09.25 |
---|---|
2024-09-13 (채팅 기록 불러오기,신고 기능) (1) | 2024.09.13 |
2024-09-09(친구 기능 완성) (1) | 2024.09.09 |
2024-09-06(친구 추가 기능, 알람 소켓) (0) | 2024.09.06 |
2024-09-05 (친구 찾기 기능 and 채팅 로그 저장) (1) | 2024.09.05 |