feat(live-room): 라이브룸 채팅 삭제 기능 구현
This commit is contained in:
@@ -318,6 +318,10 @@ final class LiveRoomViewModel: NSObject, ObservableObject {
|
||||
return isChatFrozen && liveRoomInfo.creatorId != UserDefaults.int(forKey: .userId)
|
||||
}
|
||||
|
||||
private var isCreator: Bool {
|
||||
liveRoomInfo?.creatorId == UserDefaults.int(forKey: .userId)
|
||||
}
|
||||
|
||||
func stopV2VTranslationIfJoined(clearCaptionText: Bool = true) {
|
||||
guard isV2VJoined else { return }
|
||||
stopV2VTranslation(clearCaptionText: clearCaptionText)
|
||||
@@ -695,21 +699,162 @@ final class LiveRoomViewModel: NSObject, ObservableObject {
|
||||
} else if isNoChatting {
|
||||
self.popupContent = "\(remainingNoChattingTime)초 동안 채팅하실 수 없습니다"
|
||||
self.isShowPopup = true
|
||||
} else if chatMessage.count > 0 {
|
||||
agora.sendMessageToGroup(textMessage: chatMessage) { _, error in
|
||||
} else if !chatMessage.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
let chatId = UUID().uuidString
|
||||
let chatRawMessage = LiveRoomChatRawMessage(
|
||||
type: .NORMAL_CHAT,
|
||||
message: chatMessage,
|
||||
can: 0,
|
||||
donationMessage: nil,
|
||||
chatId: chatId
|
||||
)
|
||||
|
||||
agora.sendRawMessageToGroup(rawMessage: chatRawMessage) { _, error in
|
||||
if error == nil {
|
||||
let (nickname, profileUrl) = self.getUserNicknameAndProfileUrl(accountId: UserDefaults.int(forKey: .userId))
|
||||
let rank = self.getUserRank(userId: UserDefaults.int(forKey: .userId))
|
||||
self.messages.append(LiveRoomNormalChat(userId: UserDefaults.int(forKey: .userId), profileUrl: profileUrl, nickname: nickname, rank: rank, chat: chatMessage))
|
||||
|
||||
self.messages.append(
|
||||
LiveRoomNormalChat(
|
||||
chatId: chatId,
|
||||
userId: UserDefaults.int(forKey: .userId),
|
||||
profileUrl: profileUrl,
|
||||
nickname: nickname,
|
||||
rank: rank,
|
||||
chat: chatMessage
|
||||
)
|
||||
)
|
||||
|
||||
self.invalidateChat()
|
||||
}
|
||||
|
||||
|
||||
onSuccess()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func deleteChat(_ chat: LiveRoomNormalChat) {
|
||||
guard isCreator else {
|
||||
return
|
||||
}
|
||||
|
||||
agora.sendRawMessageToGroup(
|
||||
rawMessage: LiveRoomChatRawMessage(
|
||||
type: .DELETE_CHAT,
|
||||
message: chat.chat,
|
||||
can: 0,
|
||||
donationMessage: nil,
|
||||
chatId: chat.chatId,
|
||||
targetUserId: chat.userId
|
||||
),
|
||||
completion: { [unowned self] _, error in
|
||||
if error == nil {
|
||||
let previousCount = self.messages.count
|
||||
self.applyDeleteChat(chatId: chat.chatId)
|
||||
|
||||
if previousCount == self.messages.count {
|
||||
self.applyDeleteChatFallback(userId: chat.userId, message: chat.chat)
|
||||
}
|
||||
|
||||
if previousCount != self.messages.count {
|
||||
self.invalidateChat()
|
||||
}
|
||||
} else {
|
||||
self.showDeleteSyncError()
|
||||
}
|
||||
},
|
||||
fail: { [unowned self] in
|
||||
self.showDeleteSyncError()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
func deleteChatsByUserId(userId: Int) {
|
||||
guard isCreator else {
|
||||
return
|
||||
}
|
||||
|
||||
agora.sendRawMessageToGroup(
|
||||
rawMessage: LiveRoomChatRawMessage(
|
||||
type: .DELETE_CHAT_BY_USER,
|
||||
message: "",
|
||||
can: 0,
|
||||
donationMessage: nil,
|
||||
targetUserId: userId
|
||||
),
|
||||
completion: { [unowned self] _, error in
|
||||
if error == nil {
|
||||
let previousCount = self.messages.count
|
||||
self.applyDeleteUserChats(userId: userId)
|
||||
|
||||
if previousCount != self.messages.count {
|
||||
self.invalidateChat()
|
||||
}
|
||||
} else {
|
||||
self.showDeleteSyncError()
|
||||
}
|
||||
},
|
||||
fail: { [unowned self] in
|
||||
self.showDeleteSyncError()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private func showDeleteSyncError() {
|
||||
errorMessage = I18n.Common.commonError
|
||||
isShowErrorPopup = true
|
||||
}
|
||||
|
||||
private func applyDeleteChat(chatId: String) {
|
||||
messages.removeAll { chat in
|
||||
guard chat.type == .CHAT,
|
||||
let normalChat = chat as? LiveRoomNormalChat else {
|
||||
return false
|
||||
}
|
||||
|
||||
return normalChat.chatId == chatId
|
||||
}
|
||||
}
|
||||
|
||||
private func applyDeleteChatFallback(userId: Int, message: String) {
|
||||
if let index = messages.firstIndex(where: { chat in
|
||||
guard chat.type == .CHAT,
|
||||
let normalChat = chat as? LiveRoomNormalChat else {
|
||||
return false
|
||||
}
|
||||
|
||||
return normalChat.userId == userId && normalChat.chat == message
|
||||
}) {
|
||||
messages.remove(at: index)
|
||||
}
|
||||
}
|
||||
|
||||
private func applyDeleteUserChats(userId: Int) {
|
||||
messages.removeAll { chat in
|
||||
switch chat.type {
|
||||
case .CHAT:
|
||||
guard let normalChat = chat as? LiveRoomNormalChat else {
|
||||
return false
|
||||
}
|
||||
return normalChat.userId == userId
|
||||
|
||||
case .DONATION:
|
||||
guard let donationChat = chat as? LiveRoomDonationChat else {
|
||||
return false
|
||||
}
|
||||
return donationChat.memberId == userId
|
||||
|
||||
case .ROULETTE_DONATION:
|
||||
guard let rouletteChat = chat as? LiveRoomRouletteDonationChat else {
|
||||
return false
|
||||
}
|
||||
return rouletteChat.memberId == userId
|
||||
|
||||
case .JOIN:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func donation(can: Int, message: String = "", isSecret: Bool = false) {
|
||||
if isSecret && can < 10 {
|
||||
@@ -1204,8 +1349,10 @@ final class LiveRoomViewModel: NSObject, ObservableObject {
|
||||
}
|
||||
|
||||
func kickOut() {
|
||||
if UserDefaults.int(forKey: .userId) == liveRoomInfo?.creatorId {
|
||||
repository.kickOut(roomId: AppState.shared.roomId, userId: kickOutId)
|
||||
let targetUserId = kickOutId
|
||||
|
||||
if UserDefaults.int(forKey: .userId) == liveRoomInfo?.creatorId, targetUserId > 0 {
|
||||
repository.kickOut(roomId: AppState.shared.roomId, userId: targetUserId)
|
||||
.sink { result in
|
||||
switch result {
|
||||
case .finished:
|
||||
@@ -1213,19 +1360,37 @@ final class LiveRoomViewModel: NSObject, ObservableObject {
|
||||
case .failure(let error):
|
||||
ERROR_LOG(error.localizedDescription)
|
||||
}
|
||||
} receiveValue: { _ in
|
||||
|
||||
} receiveValue: { [unowned self] response in
|
||||
let responseData = response.data
|
||||
|
||||
do {
|
||||
let jsonDecoder = JSONDecoder()
|
||||
let decoded = try jsonDecoder.decode(ApiResponseWithoutData.self, from: responseData)
|
||||
|
||||
if decoded.success {
|
||||
let nickname = self.getUserNicknameAndProfileUrl(accountId: targetUserId).nickname
|
||||
self.agora.sendMessageToPeer(peerId: String(targetUserId), rawMessage: LiveRoomRequestType.KICK_OUT.rawValue.data(using: .utf8)!) { [unowned self] _, _ in
|
||||
self.popupContent = "\(nickname)님을 내보냈습니다."
|
||||
self.isShowPopup = true
|
||||
}
|
||||
self.deleteChatsByUserId(userId: targetUserId)
|
||||
} else {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
self.isShowErrorPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowErrorPopup = true
|
||||
}
|
||||
}
|
||||
.store(in: &subscription)
|
||||
|
||||
let nickname = getUserNicknameAndProfileUrl(accountId: kickOutId).nickname
|
||||
agora.sendMessageToPeer(peerId: String(kickOutId), rawMessage: LiveRoomRequestType.KICK_OUT.rawValue.data(using: .utf8)!) { [unowned self] _, error in
|
||||
self.popupContent = "\(nickname)님을 내보냈습니다."
|
||||
self.isShowPopup = true
|
||||
}
|
||||
}
|
||||
|
||||
if let index = muteSpeakers.firstIndex(of: UInt(kickOutId)) {
|
||||
|
||||
if let index = muteSpeakers.firstIndex(of: UInt(targetUserId)) {
|
||||
muteSpeakers.remove(at: index)
|
||||
}
|
||||
|
||||
@@ -2075,6 +2240,7 @@ final class LiveRoomViewModel: NSObject, ObservableObject {
|
||||
let (nickname, profileUrl) = self.getUserNicknameAndProfileUrl(accountId: UserDefaults.int(forKey: .userId))
|
||||
self.messages.append(
|
||||
LiveRoomRouletteDonationChat(
|
||||
memberId: UserDefaults.int(forKey: .userId),
|
||||
profileUrl: profileUrl,
|
||||
nickname: nickname,
|
||||
rouletteResult: rouletteSelectedItem
|
||||
@@ -2939,6 +3105,7 @@ extension LiveRoomViewModel: AgoraRtmClientDelegate {
|
||||
} else if decoded.type == .ROULETTE_DONATION {
|
||||
self.messages.append(
|
||||
LiveRoomRouletteDonationChat(
|
||||
memberId: Int(publisher)!,
|
||||
profileUrl: profileUrl,
|
||||
nickname: nickname,
|
||||
rouletteResult: decoded.message
|
||||
@@ -2958,6 +3125,47 @@ extension LiveRoomViewModel: AgoraRtmClientDelegate {
|
||||
} else {
|
||||
DEBUG_LOG("Ignore TOGGLE_CHAT_FREEZE from non-creator publisher=\(publisher)")
|
||||
}
|
||||
} else if decoded.type == .NORMAL_CHAT {
|
||||
let memberId = Int(publisher) ?? 0
|
||||
let rank = self.getUserRank(userId: memberId)
|
||||
|
||||
if let chatId = decoded.chatId,
|
||||
!decoded.message.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty,
|
||||
!self.blockedMemberIdList.contains(memberId) {
|
||||
self.messages.append(
|
||||
LiveRoomNormalChat(
|
||||
chatId: chatId,
|
||||
userId: memberId,
|
||||
profileUrl: profileUrl,
|
||||
nickname: nickname,
|
||||
rank: rank,
|
||||
chat: decoded.message
|
||||
)
|
||||
)
|
||||
}
|
||||
} else if decoded.type == .DELETE_CHAT {
|
||||
if Int(publisher) == self.liveRoomInfo?.creatorId {
|
||||
if let chatId = decoded.chatId {
|
||||
let previousCount = self.messages.count
|
||||
self.applyDeleteChat(chatId: chatId)
|
||||
|
||||
if previousCount == self.messages.count,
|
||||
let targetUserId = decoded.targetUserId,
|
||||
!decoded.message.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
self.applyDeleteChatFallback(userId: targetUserId, message: decoded.message)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DEBUG_LOG("Ignore DELETE_CHAT from non-creator publisher=\(publisher)")
|
||||
}
|
||||
} else if decoded.type == .DELETE_CHAT_BY_USER {
|
||||
if Int(publisher) == self.liveRoomInfo?.creatorId {
|
||||
if let targetUserId = decoded.targetUserId {
|
||||
self.applyDeleteUserChats(userId: targetUserId)
|
||||
}
|
||||
} else {
|
||||
DEBUG_LOG("Ignore DELETE_CHAT_BY_USER from non-creator publisher=\(publisher)")
|
||||
}
|
||||
} else if decoded.type == .EDIT_ROOM_INFO || decoded.type == .SET_MANAGER {
|
||||
self.getRoomInfo()
|
||||
} else if decoded.type == .HEART_DONATION {
|
||||
@@ -2970,6 +3178,7 @@ extension LiveRoomViewModel: AgoraRtmClientDelegate {
|
||||
self.addBigHeartAnimation()
|
||||
}
|
||||
} catch {
|
||||
ERROR_LOG(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2977,9 +3186,19 @@ extension LiveRoomViewModel: AgoraRtmClientDelegate {
|
||||
if let message = textMessage {
|
||||
let memberId = Int(publisher) ?? 0
|
||||
let rank = getUserRank(userId: memberId)
|
||||
|
||||
let chatId = UUID().uuidString
|
||||
|
||||
if !message.trimmingCharacters(in: .whitespaces).isEmpty && !blockedMemberIdList.contains(memberId) {
|
||||
messages.append(LiveRoomNormalChat(userId: memberId, profileUrl: profileUrl, nickname: nickname, rank: rank, chat: message))
|
||||
messages.append(
|
||||
LiveRoomNormalChat(
|
||||
chatId: chatId,
|
||||
userId: memberId,
|
||||
profileUrl: profileUrl,
|
||||
nickname: nickname,
|
||||
rank: rank,
|
||||
chat: message
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user