라이브 후원
- 비밀 후원 기능 추가
This commit is contained in:
		| @@ -111,6 +111,23 @@ final class Agora { | |||||||
|         rtmKit?.send(message, toPeer: peerId, completion: completion) |         rtmKit?.send(message, toPeer: peerId, completion: completion) | ||||||
|     } |     } | ||||||
|      |      | ||||||
|  |     func sendRawMessageToPeer(peerId: String, rawMessage: LiveRoomChatRawMessage, completion: AgoraRtmSendPeerMessageBlock? = nil, fail: (() -> Void)? = nil) { | ||||||
|  |         let encoder = JSONEncoder() | ||||||
|  |         let jsonMessageData = try? encoder.encode(rawMessage) | ||||||
|  |         let option = AgoraRtmSendMessageOptions() | ||||||
|  |         option.enableOfflineMessaging = false | ||||||
|  |         option.enableHistoricalMessaging = false | ||||||
|  |          | ||||||
|  |         if let jsonMessageData = jsonMessageData { | ||||||
|  |             let message = AgoraRtmRawMessage(rawData: jsonMessageData, description: "") | ||||||
|  |             rtmKit?.send(message, toPeer: peerId, sendMessageOptions: option, completion: completion) | ||||||
|  |         } else { | ||||||
|  |             if let fail = fail { | ||||||
|  |                 fail() | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|     func mute(_ isMute: Bool) { |     func mute(_ isMute: Bool) { | ||||||
|         rtcEngine?.muteLocalAudioStream(isMute) |         rtcEngine?.muteLocalAudioStream(isMute) | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -323,7 +323,7 @@ struct ContentDetailView: View { | |||||||
|                     } |                     } | ||||||
|                      |                      | ||||||
|                     if viewModel.isShowDonationPopup { |                     if viewModel.isShowDonationPopup { | ||||||
|                         LiveRoomDonationDialogView(isShowing: $viewModel.isShowDonationPopup, isAudioContentDonation: true) { can, comment in |                         LiveRoomDonationDialogView(isShowing: $viewModel.isShowDonationPopup, isAudioContentDonation: true) { can, comment, _ in | ||||||
|                             viewModel.donation(can: can, comment: comment) |                             viewModel.donation(can: can, comment: comment) | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|   | |||||||
| @@ -18,10 +18,11 @@ struct LiveRoomDonationDialogView: View { | |||||||
|     @State private var donationMessage = "" |     @State private var donationMessage = "" | ||||||
|     @State private var isShowErrorPopup = false |     @State private var isShowErrorPopup = false | ||||||
|     @State private var errorMessage = "" |     @State private var errorMessage = "" | ||||||
|  |     @State private var isSecret = false | ||||||
|      |      | ||||||
|     @Binding var isShowing: Bool |     @Binding var isShowing: Bool | ||||||
|     let isAudioContentDonation: Bool |     let isAudioContentDonation: Bool | ||||||
|     let onClickDonation: (Int, String) -> Void |     let onClickDonation: (Int, String, Bool) -> Void | ||||||
|      |      | ||||||
|     @StateObject var keyboardHandler = KeyboardHandler() |     @StateObject var keyboardHandler = KeyboardHandler() | ||||||
|      |      | ||||||
| @@ -82,6 +83,27 @@ struct LiveRoomDonationDialogView: View { | |||||||
|                         .foregroundColor(Color.gray90) |                         .foregroundColor(Color.gray90) | ||||||
|                         .padding(.top, 16) |                         .padding(.top, 16) | ||||||
|                      |                      | ||||||
|  |                     if !isAudioContentDonation { | ||||||
|  |                         HStack(spacing: 0) { | ||||||
|  |                             Spacer() | ||||||
|  |                              | ||||||
|  |                             HStack(spacing: 8) { | ||||||
|  |                                 Image(isSecret ? "btn_select_checked" : "btn_select_normal") | ||||||
|  |                                     .resizable() | ||||||
|  |                                     .frame(width: 20, height: 20) | ||||||
|  |                                  | ||||||
|  |                                 Text("비밀후원") | ||||||
|  |                                     .font(.custom(Font.medium.rawValue, size: 14.7)) | ||||||
|  |                                     .foregroundColor(Color.grayee) | ||||||
|  |                             } | ||||||
|  |                             .onTapGesture { | ||||||
|  |                                 isSecret.toggle() | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                         .padding(.horizontal, 20) | ||||||
|  |                         .padding(.top, 16) | ||||||
|  |                     } | ||||||
|  |                      | ||||||
|                     TextField("몇 캔을 후원할까요?", text: $donationCan) |                     TextField("몇 캔을 후원할까요?", text: $donationCan) | ||||||
|                         .font(.custom(Font.medium.rawValue, size: 13.3)) |                         .font(.custom(Font.medium.rawValue, size: 13.3)) | ||||||
|                         .foregroundColor(Color.grayee) |                         .foregroundColor(Color.grayee) | ||||||
| @@ -221,7 +243,7 @@ struct LiveRoomDonationDialogView: View { | |||||||
|                             .onTapGesture { |                             .onTapGesture { | ||||||
|                                 if !donationCan.trimmingCharacters(in: .whitespaces).isEmpty, |                                 if !donationCan.trimmingCharacters(in: .whitespaces).isEmpty, | ||||||
|                                    let can = Int(donationCan) { |                                    let can = Int(donationCan) { | ||||||
|                                     onClickDonation(can, donationMessage) |                                     onClickDonation(can, donationMessage, isSecret) | ||||||
|                                     isShowing = false |                                     isShowing = false | ||||||
|                                 } else { |                                 } else { | ||||||
|                                     errorMessage = "1캔 이상 후원하실 수 있습니다." |                                     errorMessage = "1캔 이상 후원하실 수 있습니다." | ||||||
|   | |||||||
| @@ -73,8 +73,8 @@ final class LiveRepository { | |||||||
|         return api.requestPublisher(.getRoomInfo(roomId: roomId)) |         return api.requestPublisher(.getRoomInfo(roomId: roomId)) | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     func donation(roomId: Int, can: Int, message: String = "") -> AnyPublisher<Response, MoyaError> { |     func donation(roomId: Int, can: Int, message: String = "", isSecret: Bool = false) -> AnyPublisher<Response, MoyaError> { | ||||||
|         return api.requestPublisher(.donation(request: LiveRoomDonationRequest(roomId: roomId, can: can, message: message))) |         return api.requestPublisher(.donation(request: LiveRoomDonationRequest(roomId: roomId, can: can, message: message, isSecret: isSecret))) | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     func refundDonation(roomId: Int) -> AnyPublisher<Response, MoyaError> { |     func refundDonation(roomId: Int) -> AnyPublisher<Response, MoyaError> { | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ import Foundation | |||||||
|  |  | ||||||
| struct LiveRoomChatRawMessage: Codable { | struct LiveRoomChatRawMessage: Codable { | ||||||
|     enum LiveRoomChatRawMessageType: String, Codable { |     enum LiveRoomChatRawMessageType: String, Codable { | ||||||
|         case DONATION, EDIT_ROOM_INFO, SET_MANAGER, TOGGLE_ROULETTE, ROULETTE_DONATION |         case DONATION, SECRET_DONATION, EDIT_ROOM_INFO, SET_MANAGER, TOGGLE_ROULETTE, ROULETTE_DONATION | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     let type: LiveRoomChatRawMessageType |     let type: LiveRoomChatRawMessageType | ||||||
|   | |||||||
| @@ -43,7 +43,7 @@ struct LiveRoomDonationChatItemView: View { | |||||||
|                         .font(.system(size: 15)) |                         .font(.system(size: 15)) | ||||||
|                         .foregroundColor(Color(hex: "fdca2f")) |                         .foregroundColor(Color(hex: "fdca2f")) | ||||||
|                      |                      | ||||||
|                     Text("을 후원하셨습니다.") |                     Text(chatMessage.chat.contains("비밀") ? "을 비밀후원하셨습니다.💰🪙" : "을 후원하셨습니다.💰🪙") | ||||||
|                         .font(.system(size: 15)) |                         .font(.system(size: 15)) | ||||||
|                         .foregroundColor(.white) |                         .foregroundColor(.white) | ||||||
|                 } |                 } | ||||||
| @@ -58,6 +58,7 @@ struct LiveRoomDonationChatItemView: View { | |||||||
|         .padding(13) |         .padding(13) | ||||||
|         .frame(width: screenSize().width - 86, alignment: .leading) |         .frame(width: screenSize().width - 86, alignment: .leading) | ||||||
|         .background( |         .background( | ||||||
|  |             chatMessage.chat.contains("비밀") ? Color(hex: "333333").opacity(0.8) : | ||||||
|             chatMessage.can >= 10000 ? Color(hex: "c25264").opacity(0.8) : |             chatMessage.can >= 10000 ? Color(hex: "c25264").opacity(0.8) : | ||||||
|                 chatMessage.can >= 5000 ? Color(hex: "d85e37").opacity(0.8) : |                 chatMessage.can >= 5000 ? Color(hex: "d85e37").opacity(0.8) : | ||||||
|                 chatMessage.can >= 1000 ? Color(hex: "d38c38").opacity(0.8) : |                 chatMessage.can >= 1000 ? Color(hex: "d38c38").opacity(0.8) : | ||||||
|   | |||||||
| @@ -11,5 +11,6 @@ struct LiveRoomDonationRequest: Encodable { | |||||||
|     let roomId: Int |     let roomId: Int | ||||||
|     let can: Int |     let can: Int | ||||||
|     let message: String |     let message: String | ||||||
|  |     var isSecret: Bool = false | ||||||
|     let container: String = "ios" |     let container: String = "ios" | ||||||
| } | } | ||||||
|   | |||||||
| @@ -380,11 +380,11 @@ final class LiveRoomViewModel: NSObject, ObservableObject { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     func donation(can: Int, message: String = "") { |     func donation(can: Int, message: String = "", isSecret: Bool = false) { | ||||||
|         if can > 0 { |         if can > 0 { | ||||||
|             isLoading = true |             isLoading = true | ||||||
|              |              | ||||||
|             repository.donation(roomId: AppState.shared.roomId, can: can, message: message) |             repository.donation(roomId: AppState.shared.roomId, can: can, message: message, isSecret: isSecret) | ||||||
|                 .sink { result in |                 .sink { result in | ||||||
|                     switch result { |                     switch result { | ||||||
|                     case .finished: |                     case .finished: | ||||||
| @@ -402,9 +402,16 @@ final class LiveRoomViewModel: NSObject, ObservableObject { | |||||||
|                         self.isLoading = false |                         self.isLoading = false | ||||||
|                          |                          | ||||||
|                         if decoded.success { |                         if decoded.success { | ||||||
|                             let rawMessage = "\(can)캔을 후원하셨습니다." |                             var rawMessage = "" | ||||||
|  |                              | ||||||
|  |                             if isSecret { | ||||||
|  |                                 rawMessage = "\(can)캔을 비밀후원하셨습니다.💰🪙" | ||||||
|  |                             } else { | ||||||
|  |                                 rawMessage = "\(can)캔을 후원하셨습니다.💰🪙" | ||||||
|  |                             } | ||||||
|  |                              | ||||||
|                             let donationRawMessage = LiveRoomChatRawMessage( |                             let donationRawMessage = LiveRoomChatRawMessage( | ||||||
|                                 type: .DONATION, |                                 type: isSecret ? .SECRET_DONATION : .DONATION, | ||||||
|                                 message: rawMessage, |                                 message: rawMessage, | ||||||
|                                 can: can, |                                 can: can, | ||||||
|                                 signature: decoded.data, |                                 signature: decoded.data, | ||||||
| @@ -414,36 +421,68 @@ final class LiveRoomViewModel: NSObject, ObservableObject { | |||||||
|                              |                              | ||||||
|                             UserDefaults.set(UserDefaults.int(forKey: .can) - can, forKey: .can) |                             UserDefaults.set(UserDefaults.int(forKey: .can) - can, forKey: .can) | ||||||
|                              |                              | ||||||
|                             agora.sendRawMessageToGroup( |                             if isSecret { | ||||||
|                                 rawMessage: donationRawMessage, |                                 agora.sendRawMessageToPeer( | ||||||
|                                 completion: { [unowned self] errorCode in |                                     peerId: String(liveRoomInfo!.creatorId), rawMessage: donationRawMessage, | ||||||
|                                     if errorCode == .errorOk { |                                     completion: { [unowned self] errorCode in | ||||||
|                                         let (nickname, profileUrl) = self.getUserNicknameAndProfileUrl(accountId: UserDefaults.int(forKey: .userId)) |                                         if errorCode == .ok { | ||||||
|                                         self.messages.append( |                                             let (nickname, profileUrl) = self.getUserNicknameAndProfileUrl(accountId: UserDefaults.int(forKey: .userId)) | ||||||
|                                             LiveRoomDonationChat( |                                             self.messages.append( | ||||||
|                                                 profileUrl: profileUrl, |                                                 LiveRoomDonationChat( | ||||||
|                                                 nickname: nickname, |                                                     profileUrl: profileUrl, | ||||||
|                                                 chat: rawMessage, |                                                     nickname: nickname, | ||||||
|                                                 can: can, |                                                     chat: rawMessage, | ||||||
|                                                 donationMessage: message |                                                     can: can, | ||||||
|  |                                                     donationMessage: message | ||||||
|  |                                                 ) | ||||||
|                                             ) |                                             ) | ||||||
|                                         ) |                                              | ||||||
|                                          |                                             addSignature(signature: decoded.data) | ||||||
|                                         totalDonationCan += can |                                              | ||||||
|                                         addSignature(signature: decoded.data) |                                             self.messageChangeFlag.toggle() | ||||||
|                                          |                                             if self.messages.count > 100 { | ||||||
|                                         self.messageChangeFlag.toggle() |                                                 self.messages.remove(at: 0) | ||||||
|                                         if self.messages.count > 100 { |                                             } | ||||||
|                                             self.messages.remove(at: 0) |                                         } else { | ||||||
|  |                                             refundDonation() | ||||||
|                                         } |                                         } | ||||||
|                                     } else { |                                     }, | ||||||
|  |                                     fail: { [unowned self] in | ||||||
|                                         refundDonation() |                                         refundDonation() | ||||||
|                                     } |                                     } | ||||||
|                                 }, |                                 ) | ||||||
|                                 fail: { [unowned self] in |                             } else { | ||||||
|                                     refundDonation() |                                 agora.sendRawMessageToGroup( | ||||||
|                                 } |                                     rawMessage: donationRawMessage, | ||||||
|                             ) |                                     completion: { [unowned self] errorCode in | ||||||
|  |                                         if errorCode == .errorOk { | ||||||
|  |                                             let (nickname, profileUrl) = self.getUserNicknameAndProfileUrl(accountId: UserDefaults.int(forKey: .userId)) | ||||||
|  |                                             self.messages.append( | ||||||
|  |                                                 LiveRoomDonationChat( | ||||||
|  |                                                     profileUrl: profileUrl, | ||||||
|  |                                                     nickname: nickname, | ||||||
|  |                                                     chat: rawMessage, | ||||||
|  |                                                     can: can, | ||||||
|  |                                                     donationMessage: message | ||||||
|  |                                                 ) | ||||||
|  |                                             ) | ||||||
|  |                                              | ||||||
|  |                                             totalDonationCan += can | ||||||
|  |                                             addSignature(signature: decoded.data) | ||||||
|  |                                              | ||||||
|  |                                             self.messageChangeFlag.toggle() | ||||||
|  |                                             if self.messages.count > 100 { | ||||||
|  |                                                 self.messages.remove(at: 0) | ||||||
|  |                                             } | ||||||
|  |                                         } else { | ||||||
|  |                                             refundDonation() | ||||||
|  |                                         } | ||||||
|  |                                     }, | ||||||
|  |                                     fail: { [unowned self] in | ||||||
|  |                                         refundDonation() | ||||||
|  |                                     } | ||||||
|  |                                 ) | ||||||
|  |                             } | ||||||
|                         } else { |                         } else { | ||||||
|                             if let message = decoded.message { |                             if let message = decoded.message { | ||||||
|                                 self.popupContent = message |                                 self.popupContent = message | ||||||
| @@ -1858,6 +1897,31 @@ extension LiveRoomViewModel: AgoraRtmDelegate { | |||||||
|                         self.startNoChatting() |                         self.startNoChatting() | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |                  | ||||||
|  |                 do { | ||||||
|  |                     let jsonDecoder = JSONDecoder() | ||||||
|  |                     let decoded = try jsonDecoder.decode(LiveRoomChatRawMessage.self, from: rawMessage.rawData) | ||||||
|  |                     let (nickname, profileUrl) = getUserNicknameAndProfileUrl(accountId: Int(peerId)!) | ||||||
|  |                      | ||||||
|  |                     if decoded.type == .SECRET_DONATION { | ||||||
|  |                         self.messages.append( | ||||||
|  |                             LiveRoomDonationChat( | ||||||
|  |                                 profileUrl: profileUrl, | ||||||
|  |                                 nickname: nickname, | ||||||
|  |                                 chat: decoded.message, | ||||||
|  |                                 can: decoded.can, | ||||||
|  |                                 donationMessage: decoded.donationMessage ?? "" | ||||||
|  |                             ) | ||||||
|  |                         ) | ||||||
|  |                          | ||||||
|  |                         if let signature = decoded.signature { | ||||||
|  |                             self.addSignature(signature: signature) | ||||||
|  |                         } else if let imageUrl = decoded.signatureImageUrl { | ||||||
|  |                             self.addSignatureImage(imageUrl: imageUrl) | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } catch { | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -203,10 +203,12 @@ struct LiveRoomViewV2: View { | |||||||
|                                             ) |                                             ) | ||||||
|                                         } |                                         } | ||||||
|                                          |                                          | ||||||
|                                         LiveRoomRightBottomButton( |                                         if liveRoomInfo.creatorId != UserDefaults.int(forKey: .userId) { | ||||||
|                                             imageName: "ic_donation", |                                             LiveRoomRightBottomButton( | ||||||
|                                             onClick: { viewModel.isShowDonationPopup = true } |                                                 imageName: "ic_donation", | ||||||
|                                         ) |                                                 onClick: { viewModel.isShowDonationPopup = true } | ||||||
|  |                                             ) | ||||||
|  |                                         } | ||||||
|                                          |                                          | ||||||
|                                         LiveRoomRightBottomButton( |                                         LiveRoomRightBottomButton( | ||||||
|                                             imageName: "ic_donation_message_list", |                                             imageName: "ic_donation_message_list", | ||||||
| @@ -390,8 +392,8 @@ struct LiveRoomViewV2: View { | |||||||
|                 } |                 } | ||||||
|                  |                  | ||||||
|                 if viewModel.isShowDonationPopup { |                 if viewModel.isShowDonationPopup { | ||||||
|                     LiveRoomDonationDialogView(isShowing: $viewModel.isShowDonationPopup, isAudioContentDonation: false) { can, message in |                     LiveRoomDonationDialogView(isShowing: $viewModel.isShowDonationPopup, isAudioContentDonation: false) { can, message, isSecret in | ||||||
|                         viewModel.donation(can: can, message: message) |                         viewModel.donation(can: can, message: message, isSecret: isSecret) | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                  |                  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Yu Sung
					Yu Sung