Skip to content

Commit

Permalink
[Feat/#288] characterChatBox 모드 세분화(로티 뜨는 케이스 추가) 및 열고 접힘 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
nolanMinsung committed Nov 17, 2024
1 parent 19d767e commit adf871f
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@
import UIKit

enum ChatBoxMode {
case withReplyButton
case withoutReplyButton
// 답장하기 버튼이 있고, 접혀 있을 때 - 캐릭터 선톡 왔을 때
case withReplyButtonShrinked
// 답장하기 버튼이 있고, 펼쳐 있을 때 - 사용자가 chenvron 버튼 탭했을 때
case withReplyButtonExpanded
// 답장하기 버튼이 없고, 접혀 있을 때 - 로딩 로티 띄울 때
case withoutReplyButtonShrinked
// 답장하기 버튼이 없고, 펼쳐 있을 때 - 캐릭터와 채팅중일 때
case withoutReplyButtonExpanded
}

class ORBCharacterChatBox: UIView {
Expand All @@ -18,9 +24,18 @@ class ORBCharacterChatBox: UIView {

let characterNameLabel = UILabel()
let messageLabel = UILabel()
let chevronImageButton = UIButton()
let replyButton = UIButton()

lazy var replyButtonTopConstraint = replyButton.topAnchor.constraint(equalTo: messageLabel.bottomAnchor, constant: 10)
lazy var messageLabelTrailingConstraintToChevronImageButton = messageLabel.trailingAnchor.constraint(
equalTo: chevronImageButton.leadingAnchor,
constant: -2
)
lazy var messageLabelTrailingConstraintToSuperview = messageLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -24)
lazy var replyButtonTopConstraint = replyButton.topAnchor.constraint(
equalTo: messageLabel.bottomAnchor,
constant: 10
)
lazy var replyButtonBottomConstraint = replyButton.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -18)

init(mode: ChatBoxMode) {
Expand All @@ -44,6 +59,7 @@ extension ORBCharacterChatBox {
//MARK: - Layout Func

private func setupLayout() {
characterNameLabel.setContentCompressionResistancePriority(.init(999), for: .horizontal)
characterNameLabel.snp.makeConstraints { make in
make.top.equalToSuperview().inset(18)
make.leading.equalToSuperview().inset(24)
Expand All @@ -53,18 +69,57 @@ 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.trailing.equalToSuperview().inset(24)
make.bottom.lessThanOrEqualToSuperview().inset(18)
}

chevronImageButton.snp.makeConstraints { make in
make.top.equalToSuperview().inset(19)
make.trailing.equalToSuperview().inset(24)
make.width.equalTo(34)
make.height.equalTo(22)
}

replyButton.snp.makeConstraints { make in
make.trailing.equalToSuperview().inset(20)
}
}

func setupAdditionalLayout() {
replyButtonTopConstraint.isActive = mode == .withReplyButton ? true : false
replyButtonBottomConstraint.isActive = mode == .withReplyButton ? true : false
switch mode {
case .withReplyButtonShrinked:
messageLabel.numberOfLines = 1
messageLabelTrailingConstraintToChevronImageButton.isActive = true
messageLabelTrailingConstraintToSuperview.isActive = false
replyButtonTopConstraint.isActive = true
replyButtonBottomConstraint.isActive = true
case .withReplyButtonExpanded:
messageLabel.numberOfLines = 0
messageLabelTrailingConstraintToChevronImageButton.isActive = true
messageLabelTrailingConstraintToSuperview.isActive = false
replyButtonTopConstraint.isActive = true
replyButtonBottomConstraint.isActive = true
case .withoutReplyButtonShrinked:
messageLabel.numberOfLines = 1
messageLabelTrailingConstraintToChevronImageButton.isActive = false
messageLabelTrailingConstraintToSuperview.isActive = true
replyButtonTopConstraint.isActive = false
replyButtonBottomConstraint.isActive = false
case .withoutReplyButtonExpanded:
messageLabel.numberOfLines = 0
messageLabelTrailingConstraintToChevronImageButton.isActive = false
messageLabelTrailingConstraintToSuperview.isActive = true
replyButtonTopConstraint.isActive = false
replyButtonBottomConstraint.isActive = false
}
//
//
// //messageLabel의 trailingAnchor관련 setupLayout 함수 안에 있는거 없에고 여기서 chevronImageButton이랑 엮어서 처리
// messageLabelTrailingConstraintToSuperview.isActive = mode == .withReplyButton ? false : true
// messageLabelTrailingConstraintToChevronImageButton.isActive = mode == .withReplyButton ? true : false
// replyButtonTopConstraint.isActive = mode == .withReplyButton ? true : false
// replyButtonBottomConstraint.isActive = mode == .withReplyButton ? true : false
// messageLabel.numberOfLines = mode == .withReplyButton ? 1 : 0
}

//MARK: - Private Func
Expand All @@ -83,7 +138,17 @@ extension ORBCharacterChatBox {
messageLabel.do { label in
label.font = .offroad(style: .iosText)
label.textColor = .main(.main2)
label.numberOfLines = 0
label.contentMode = .topLeft
switch mode {
case .withReplyButtonShrinked, .withoutReplyButtonShrinked:
label.numberOfLines = 1
case .withReplyButtonExpanded, .withoutReplyButtonExpanded:
label.numberOfLines = 0
}
}

chevronImageButton.do { button in
button.setImage(.icnPlaceListExpendableCellChevron, for: .normal)
}

replyButton.do { button in
Expand All @@ -93,14 +158,14 @@ extension ORBCharacterChatBox {
button.configureTitleFontWhen(normal: .offroad(style: .iosTextContents))
button.roundCorners(cornerRadius: 8)
switch mode {
case .withReplyButton: button.isHidden = false
case .withoutReplyButton: button.isHidden = true
case .withReplyButtonShrinked, .withReplyButtonExpanded: button.isHidden = false
case .withoutReplyButtonShrinked, .withoutReplyButtonExpanded: button.isHidden = true
}
}
}

private func setupHierarchy() {
addSubviews(characterNameLabel, messageLabel, replyButton)
addSubviews(characterNameLabel, messageLabel, chevronImageButton, replyButton)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ final class ORBCharacterChatManager {

extension ORBCharacterChatManager {

func showCharacterChatBox(character name: String, message: String, withReplyButton: Bool) {
func showCharacterChatBox(character name: String, message: String, mode: ChatBoxMode) {
chatWindow.makeKeyAndVisible()
chatViewController.configureCharacterChatBox(character: name, message: message, withReplyButton: withReplyButton)
chatViewController.configureCharacterChatBox(character: name, message: message, mode: mode)
chatViewController.showCharacterChatBox()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ final class ORBCharacterChatView: UIView {

//MARK: - UI Properties

let characterChatBox = ORBCharacterChatBox(mode: .withReplyButton)
let characterChatBox = ORBCharacterChatBox(mode: .withReplyButtonShrinked)
let userChatView = UIView()

let meLabel = UILabel()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class ORBCharacterChatViewController: UIViewController {
let userChatDisplayViewTextInputViewHeightRelay = PublishRelay<CGFloat>()

let characterChatBoxPositionAnimator = UIViewPropertyAnimator(duration: 0.5, dampingRatio: 1)
let characterChatBoxModeChangingAnimator = UIViewPropertyAnimator(duration: 0.5, dampingRatio: 1)
let characterChatBoxModeChangingAnimator = UIViewPropertyAnimator(duration: 0.4, dampingRatio: 1)
let userChatViewAnimator = UIViewPropertyAnimator(duration: 0.5, dampingRatio: 1)
let userChatInputViewHeightAnimator = UIViewPropertyAnimator(duration: 0.3, dampingRatio: 1)
let userChatDisplayViewHeightAnimator = UIViewPropertyAnimator(duration: 0.3, dampingRatio: 1)
Expand Down Expand Up @@ -63,7 +63,8 @@ extension ORBCharacterChatViewController {
}

@objc private func panGestureHandler(sender: UIPanGestureRecognizer) {
guard rootView.characterChatBox.mode == .withReplyButton else { return }
guard rootView.characterChatBox.mode == .withReplyButtonShrinked
|| rootView.characterChatBox.mode == .withReplyButtonExpanded else { return }
switch sender.state {
case .possible, .began:
return
Expand All @@ -86,7 +87,8 @@ extension ORBCharacterChatViewController {
}

@objc private func tapGestureHandler(sender: UITapGestureRecognizer) {
guard rootView.characterChatBox.mode == .withReplyButton else { return }
guard rootView.characterChatBox.mode == .withReplyButtonShrinked
|| rootView.characterChatBox.mode == .withReplyButtonExpanded else { return }
ORBCharacterChatManager.shared.shouldPushCharacterChatLogViewController.onNext(rootView.characterChatBox.characterNameLabel.text!)
}

Expand All @@ -108,10 +110,20 @@ extension ORBCharacterChatViewController {
}

private func bindData() {
rootView.characterChatBox.chevronImageButton.rx.tap.bind { [weak self] in
guard let self else { return }
if self.rootView.characterChatBox.mode == .withReplyButtonShrinked {
self.changeChatBoxMode(to: .withReplyButtonExpanded, animated: true)
} else if self.rootView.characterChatBox.mode == .withReplyButtonExpanded {
self.changeChatBoxMode(to: .withReplyButtonShrinked, animated: true)
}

}.disposed(by: disposeBag)

rootView.characterChatBox.replyButton.rx.tap.bind { [weak self] in
guard let self else { return }
self.rootView.userChatInputView.becomeFirstResponder()
self.changeMode(to: .withoutReplyButton, animated: true)
self.changeChatBoxMode(to: .withoutReplyButtonExpanded, animated: true)
}.disposed(by: disposeBag)

rootView.sendButton.rx.tap.bind { [weak self] in
Expand Down Expand Up @@ -252,24 +264,28 @@ extension ORBCharacterChatViewController {
userChatDisplayViewHeightAnimator.startAnimation()
}

func configureCharacterChatBox(character name: String, message: String, withReplyButton: Bool) {
func configureCharacterChatBox(character name: String, message: String, mode: ChatBoxMode) {
rootView.characterChatBox.characterNameLabel.text = name + " :"
rootView.characterChatBox.messageLabel.text = message
changeMode(to: withReplyButton ? .withReplyButton : .withoutReplyButton, animated: false)
changeChatBoxMode(to: mode, animated: false)
}

func changeMode(to mode: ChatBoxMode, animated: Bool) {
func changeChatBoxMode(to mode: ChatBoxMode, animated: Bool) {
rootView.characterChatBox.mode = mode
rootView.characterChatBox.chevronImageButton.isHidden =
(mode == .withoutReplyButtonShrinked || mode == .withoutReplyButtonExpanded) ? true : false
if animated {
characterChatBoxModeChangingAnimator.addAnimations { [weak self] in
guard let self else { return }
self.rootView.characterChatBox.replyButton.isHidden = mode == .withReplyButton ? false : true
self.rootView.characterChatBox.replyButton.isHidden =
(mode == .withoutReplyButtonShrinked || mode == .withoutReplyButtonExpanded) ? true : false
self.rootView.characterChatBox.setupAdditionalLayout()
self.rootView.layoutIfNeeded()
}
characterChatBoxModeChangingAnimator.startAnimation()
} else {
rootView.characterChatBox.replyButton.isHidden = mode == .withReplyButton ? false : true
self.rootView.characterChatBox.replyButton.isHidden =
(mode == .withoutReplyButtonShrinked || mode == .withoutReplyButtonExpanded) ? true : false
rootView.characterChatBox.setupAdditionalLayout()
rootView.layoutIfNeeded()
}
Expand Down

0 comments on commit adf871f

Please sign in to comment.