Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions Projects/Chat/Sources/View/ChatViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,126 @@
// Created by 박지윤 on 7/1/25.
//

import UIKit
import CommonUI
import RxSwift
import Domain

public class ChatViewController: BaseViewController {
let viewModel: ChatViewModel
let chatView = ChatView()

private var messages: [ChatMessageVO] = []

public init(chatViewModel: ChatViewModel) {
self.viewModel = chatViewModel
super.init()
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

public override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: false)
}

public override func viewDidLoad() {
super.viewDidLoad()
setupViewProperty()
setupHierarchy()
setupLayout()
bindData()
bindActions()
setupTextFieldActions()
viewModel.startTextChat()
}

public override func setupViewProperty() {
view.backgroundColor = CommonUIAssets.LMOrange4
}

public override func setupHierarchy() {
view.addSubview(chatView)
}

public override func setupDelegate() {
}

public override func setupLayout() {
chatView.snp.makeConstraints {
$0.edges.equalToSuperview()
}
}

private func bindData() {
viewModel.chatSubject
.observe(on: MainScheduler.instance)
.subscribe(onNext: { [weak self] (chat: ChatVO) in
print("📨 ChatVO 수신: \(chat)")
self?.updateRecommendTopics(chat.recommendSubjects)
})
.disposed(by: disposeBag)

viewModel.messageSubject
.observe(on: MainScheduler.instance)
.subscribe(onNext: { [weak self] (message: ChatMessageVO) in
print("📨 메시지 수신: \(message)")
self?.addMessageToUI(message)
})
.disposed(by: disposeBag)
}

private func bindActions() {
chatView.onSendButtonTapped = { [weak self] message in
self?.sendMessage(message)
}
}

private func setupTextFieldActions() {
chatView.chatTextField.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
}

@objc private func textFieldDidChange() {
let text = chatView.chatTextField.text ?? ""
chatView.sendButton.isEnabled = !text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
}

private func sendMessage(_ text: String) {
// 첫 번째 메시지 전송 시 추천 섹션 숨기기
if messages.isEmpty {
chatView.hideRecommendSection()
}

// 사용자 메시지 UI에 추가
let userMessage = ChatMessageVO(chatId: 0, author: "HUMAN", content: text)
addMessageToUI(userMessage)

// API 호출
viewModel.sendMessage(content: text)

// 텍스트 필드 초기화 및 버튼 비활성화
chatView.chatTextField.text = ""
chatView.sendButton.isEnabled = false
}

private func addMessageToUI(_ message: ChatMessageVO) {
messages.append(message)
chatView.addMessageToUI(message)
}

private func updateRecommendTopics(_ topics: [String]) {
print("🔄 추천 주제 업데이트: \(topics)")

guard !topics.isEmpty else {
print("⚠️ 추천 주제가 비어있습니다")
return
}

// ChatView의 recommendTexts 프로퍼티로 간단하게 업데이트
chatView.recommendTexts = topics

print("✅ 추천 주제 업데이트 완료: \(topics.count)개")
}
}
50 changes: 50 additions & 0 deletions Projects/Chat/Sources/ViewModel/ChatViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,53 @@
//
// Created by 박지윤 on 7/1/25.
//

import Domain
import RxSwift

protocol ChatViewModelProtocol {
func startTextChat()
func sendMessage(content: String)
}

public class ChatViewModel: ChatViewModelProtocol {
private let disposeBag = DisposeBag()
private let chatUseCase: ChatUseCase
private let tokenUseCase: TokenUseCase

let chatSubject = PublishSubject<ChatVO>()
let messageSubject = PublishSubject<ChatMessageVO>()
private var currentChatRoomId: Int = 0

public init(chatUseCase: ChatUseCase,
tokenUseCase: TokenUseCase) {
self.chatUseCase = chatUseCase
self.tokenUseCase = tokenUseCase
}

func startTextChat() {
chatUseCase.postChatStart()
.subscribe(onSuccess: { [weak self] chat in
print("✅ 텍스트 대화 시작 성공: \(chat)")
self?.currentChatRoomId = chat.chatRoomId
self?.chatSubject.onNext(chat)
}, onFailure: { error in
print("❌ 텍스트 대화 시작 실패: \(error)")
}).disposed(by: disposeBag)
}

func sendMessage(content: String) {
guard !content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else {
print("⚠️ 빈 메시지는 전송할 수 없습니다")
return
}

chatUseCase.postChat(chatRoomId: currentChatRoomId, content: content)
.subscribe(onSuccess: { [weak self] message in
print("✅ 메시지 전송 성공: \(message)")
self?.messageSubject.onNext(message)
}, onFailure: { error in
print("❌ 메시지 전송 실패: \(error)")
}).disposed(by: disposeBag)
}
}
10 changes: 9 additions & 1 deletion Projects/CommonUI/CommonUI.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -194,13 +194,21 @@
path = Extension;
sourceTree = "<group>";
};
951F3F852E6DDE7F0022583B /* Chat */ = {
isa = PBXGroup;
children = (
3EBDD10D8389EBB23B42C54F /* ChatView.swift */,
);
path = Chat;
sourceTree = "<group>";
};
9786E1056828B1E6D5EDAB7C /* View */ = {
isa = PBXGroup;
children = (
DFA6DB2905DB98838A8AEA6F /* Home */,
4F020027E0FF96E7A77E5F05 /* Login */,
7F5AEF3C3719E8689E7AF017 /* Navigation */,
3EBDD10D8389EBB23B42C54F /* ChatView.swift */,
951F3F852E6DDE7F0022583B /* Chat */,
C28FE6392E1612667826E5C5 /* DiaryView.swift */,
9266801EFBA6178C5B70C641 /* MyPageView.swift */,
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0xEA",
"green" : "0x77",
"red" : "0x1A"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0xEA",
"green" : "0x77",
"red" : "0x1A"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "[email protected]",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "[email protected]",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions Projects/CommonUI/Sources/Enum/CommonUIAssets.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public enum CommonUIAssets {
/// * Icon
public static let IconPlay = image(named: "play")
public static let IconBack = image(named: "back")
public static let IconSend = image(named: "send")

/// color
public static let LMOrange1 = color(named: "LMOrange01")
Expand All @@ -62,6 +63,7 @@ public enum CommonUIAssets {
public static let LMGray5 = color(named: "LMGray05")
public static let LMGray6 = color(named: "LMGray06")
public static let LMBlue = color(named: "LMBlue")
public static let LMBlue2 = color(named: "LMBlue02")
public static let LMGreen = color(named: "LMGreen")
public static let LMRed = color(named: "LMRed")
public static let LMRed2 = color(named: "LMRed02")
Expand Down
Loading
Loading