diff --git a/Offroad-iOS/Offroad-iOS/Presentation/Chat/CharacterChat/ORBCharacterChatBox.swift b/Offroad-iOS/Offroad-iOS/Presentation/Chat/CharacterChat/ORBCharacterChatBox.swift index 73ca6346..2fa1968a 100644 --- a/Offroad-iOS/Offroad-iOS/Presentation/Chat/CharacterChat/ORBCharacterChatBox.swift +++ b/Offroad-iOS/Offroad-iOS/Presentation/Chat/CharacterChat/ORBCharacterChatBox.swift @@ -7,6 +7,8 @@ import UIKit +import Lottie + enum ChatBoxMode { // 답장하기 버튼이 있고, 접혀 있을 때 - 캐릭터 선톡 왔을 때 case withReplyButtonShrinked @@ -24,6 +26,7 @@ class ORBCharacterChatBox: UIView { let characterNameLabel = UILabel() let messageLabel = UILabel() + let loadingAnimationView = LottieAnimationView(name: "loading2") let chevronImageButton = UIButton() let replyButton = UIButton() @@ -69,10 +72,16 @@ extension ORBCharacterChatBox { messageLabel.snp.makeConstraints { make in make.top.equalTo(characterNameLabel) make.leading.equalTo(characterNameLabel.snp.trailing).offset(4) -// make.trailing.equalToSuperview().inset(24) make.bottom.lessThanOrEqualToSuperview().inset(18) } + loadingAnimationView.snp.makeConstraints { make in + make.centerY.equalTo(characterNameLabel) + make.leading.equalTo(characterNameLabel.snp.trailing).offset(-10) + make.width.equalTo(80) + make.height.equalTo(40) + } + chevronImageButton.snp.makeConstraints { make in make.top.equalToSuperview().inset(19) make.trailing.equalToSuperview().inset(24) @@ -139,6 +148,13 @@ extension ORBCharacterChatBox { } } + loadingAnimationView.do { animationView in + animationView.loopMode = .loop + animationView.contentMode = .scaleAspectFit + animationView.play() + animationView.isHidden = true + } + chevronImageButton.do { button in button.setImage(.icnChatViewChevronDown, for: .normal) } @@ -157,7 +173,7 @@ extension ORBCharacterChatBox { } private func setupHierarchy() { - addSubviews(characterNameLabel, messageLabel, chevronImageButton, replyButton) + addSubviews(characterNameLabel, messageLabel, loadingAnimationView, chevronImageButton, replyButton) } } diff --git a/Offroad-iOS/Offroad-iOS/Presentation/Chat/CharacterChat/ORBCharacterChatManager.swift b/Offroad-iOS/Offroad-iOS/Presentation/Chat/CharacterChat/ORBCharacterChatManager.swift index 9fd94c4f..01a398a0 100644 --- a/Offroad-iOS/Offroad-iOS/Presentation/Chat/CharacterChat/ORBCharacterChatManager.swift +++ b/Offroad-iOS/Offroad-iOS/Presentation/Chat/CharacterChat/ORBCharacterChatManager.swift @@ -36,7 +36,7 @@ extension ORBCharacterChatManager { func showCharacterChatBox(character name: String, message: String, mode: ChatBoxMode) { chatWindow.makeKeyAndVisible() - chatViewController.configureCharacterChatBox(character: name, message: message, mode: mode) + chatViewController.configureCharacterChatBox(character: name, message: message, mode: mode, animated: false) chatViewController.showCharacterChatBox() } diff --git a/Offroad-iOS/Offroad-iOS/Presentation/Chat/CharacterChat/ORBCharacterChatViewController.swift b/Offroad-iOS/Offroad-iOS/Presentation/Chat/CharacterChat/ORBCharacterChatViewController.swift index 5bb55a5e..80a42fa2 100644 --- a/Offroad-iOS/Offroad-iOS/Presentation/Chat/CharacterChat/ORBCharacterChatViewController.swift +++ b/Offroad-iOS/Offroad-iOS/Presentation/Chat/CharacterChat/ORBCharacterChatViewController.swift @@ -129,6 +129,34 @@ extension ORBCharacterChatViewController { rootView.sendButton.rx.tap.bind { [weak self] in guard let self else { return } print("메시지 전송: \(self.rootView.userChatInputView.text!)") + + //MARK: - TODO: - 캐릭터 채팅 보내는 기능 구현하기 + let randomResponseList: [String] = [ + "아직도 서버 API 완성이 안됐어...캐릭터 이미지도 아직 못 받았어...기한 내에 어떻게 완성하라는 거야?", + "개발 마감 당일까지 이미지도 못받고 서버 API도 완성 안된 상황이라 어쩔 수 없어..좀만 기다려줄래...?", + "나도 빨리 완성된 모습을 보고 싶다...언제쯤 완성이 될까??", + "이건 더미데이터야...", + "지금 대표캐릭터랑 이야기하는 거일껄?", + "서버에서 API 완성하는데 오래 걸리나봐. 일단은 그냥 이거 보여주고 있어.", + "좀만 기다려..." + ] + let randomResponseTimeList: [DispatchTime] = [ + .now() + 0.5, + .now() + 1, + .now() + 1.5, + .now() + 2, + .now() + 2.5 + ] + self.configureCharacterChatBox(character: "오푸", message: randomResponseList.randomElement()!, mode: .withoutReplyButtonShrinked, animated: true) + rootView.characterChatBox.messageLabel.isHidden = true + rootView.characterChatBox.loadingAnimationView.isHidden = false + rootView.characterChatBox.loadingAnimationView.play() + self.showCharacterChatBox() + DispatchQueue.main.asyncAfter(deadline: randomResponseTimeList.randomElement()!) { [weak self] in + guard let self else { return } + self.changeChatBoxMode(to: .withoutReplyButtonExpanded, animated: true) + } + self.rootView.userChatDisplayView.text = self.rootView.userChatInputView.text.trimmingCharacters(in: .whitespacesAndNewlines) self.rootView.userChatDisplayView.bounds.origin.y = -(self.rootView.userChatDisplayView.bounds.height) UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1) { @@ -229,6 +257,9 @@ extension ORBCharacterChatViewController { characterChatBoxPositionAnimator.addCompletion { [weak self] _ in guard let self else { return } self.rootView.characterChatBox.characterNameLabel.text = "" + self.rootView.characterChatBox.loadingAnimationView.stop() + self.rootView.characterChatBox.loadingAnimationView.isHidden = true + self.rootView.characterChatBox.messageLabel.isHidden = false self.rootView.characterChatBox.messageLabel.text = "" } characterChatBoxPositionAnimator.startAnimation() @@ -264,10 +295,10 @@ extension ORBCharacterChatViewController { userChatDisplayViewHeightAnimator.startAnimation() } - func configureCharacterChatBox(character name: String, message: String, mode: ChatBoxMode) { + func configureCharacterChatBox(character name: String, message: String, mode: ChatBoxMode, animated: Bool) { rootView.characterChatBox.characterNameLabel.text = name + " :" rootView.characterChatBox.messageLabel.text = message - changeChatBoxMode(to: mode, animated: false) + changeChatBoxMode(to: mode, animated: animated) } func changeChatBoxMode(to mode: ChatBoxMode, animated: Bool) { @@ -280,17 +311,29 @@ extension ORBCharacterChatViewController { guard let self else { return } switch mode { case .withReplyButtonShrinked: + self.rootView.characterChatBox.messageLabel.isHidden = false self.rootView.characterChatBox.replyButton.isHidden = false self.rootView.characterChatBox.chevronImageButton.transform = .identity + self.rootView.characterChatBox.loadingAnimationView.isHidden = true + self.rootView.characterChatBox.loadingAnimationView.stop() case .withReplyButtonExpanded: + self.rootView.characterChatBox.messageLabel.isHidden = false self.rootView.characterChatBox.replyButton.isHidden = false self.rootView.characterChatBox.chevronImageButton.transform = .init(rotationAngle: .pi * 0.99) + self.rootView.characterChatBox.loadingAnimationView.isHidden = true + self.rootView.characterChatBox.loadingAnimationView.stop() case .withoutReplyButtonShrinked: + self.rootView.characterChatBox.messageLabel.isHidden = true self.rootView.characterChatBox.replyButton.isHidden = true self.rootView.characterChatBox.chevronImageButton.transform = .identity + self.rootView.characterChatBox.loadingAnimationView.isHidden = false + self.rootView.characterChatBox.loadingAnimationView.play() case .withoutReplyButtonExpanded: + self.rootView.characterChatBox.messageLabel.isHidden = false self.rootView.characterChatBox.replyButton.isHidden = true self.rootView.characterChatBox.chevronImageButton.transform = .init(rotationAngle: .pi * 0.99) + self.rootView.characterChatBox.loadingAnimationView.isHidden = true + self.rootView.characterChatBox.loadingAnimationView.stop() } self.rootView.characterChatBox.setupAdditionalLayout() self.rootView.layoutIfNeeded() @@ -299,17 +342,29 @@ extension ORBCharacterChatViewController { } else { switch mode { case .withReplyButtonShrinked: + self.rootView.characterChatBox.messageLabel.isHidden = false self.rootView.characterChatBox.replyButton.isHidden = false self.rootView.characterChatBox.chevronImageButton.transform = .identity + self.rootView.characterChatBox.loadingAnimationView.isHidden = true + self.rootView.characterChatBox.loadingAnimationView.stop() case .withReplyButtonExpanded: + self.rootView.characterChatBox.messageLabel.isHidden = false self.rootView.characterChatBox.replyButton.isHidden = false - self.rootView.characterChatBox.chevronImageButton.transform = .init(rotationAngle: .pi) + self.rootView.characterChatBox.chevronImageButton.transform = .init(rotationAngle: .pi * 0.99) + self.rootView.characterChatBox.loadingAnimationView.isHidden = true + self.rootView.characterChatBox.loadingAnimationView.stop() case .withoutReplyButtonShrinked: + self.rootView.characterChatBox.messageLabel.isHidden = true self.rootView.characterChatBox.replyButton.isHidden = true self.rootView.characterChatBox.chevronImageButton.transform = .identity + self.rootView.characterChatBox.loadingAnimationView.isHidden = false + self.rootView.characterChatBox.loadingAnimationView.play() case .withoutReplyButtonExpanded: + self.rootView.characterChatBox.messageLabel.isHidden = false self.rootView.characterChatBox.replyButton.isHidden = true - self.rootView.characterChatBox.chevronImageButton.transform = .init(rotationAngle: .pi) + self.rootView.characterChatBox.chevronImageButton.transform = .init(rotationAngle: .pi * 0.99) + self.rootView.characterChatBox.loadingAnimationView.isHidden = true + self.rootView.characterChatBox.loadingAnimationView.stop() } rootView.characterChatBox.setupAdditionalLayout() rootView.layoutIfNeeded()