-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
26 changed files
with
400 additions
and
0 deletions.
There are no files selected for viewing
133 changes: 133 additions & 0 deletions
133
package-kuring/Sources/Features/BotFeatures/BotFeature.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
// | ||
// File.swift | ||
// | ||
// | ||
// Created by 최효원 on 8/5/24. | ||
// | ||
|
||
import Foundation | ||
import ComposableArchitecture | ||
|
||
@Reducer | ||
public struct BotFeature { | ||
@ObservableState | ||
public struct State: Equatable { | ||
public var chatInfo: ChatInfo = .init() // 현재 입력 중인 질문과 그 답변의 상태를 저장하는 구조체 | ||
public var chatHistory: [ChatInfo] = [] // 이전의 질문과 답변을 저장하는 배열 | ||
public var focus: Field? = .question | ||
|
||
|
||
// 개별 채팅 정보를 나타내는 구조체 | ||
public struct ChatInfo: Equatable { | ||
public var question: String = "" | ||
public var answer: String = "" | ||
public var chatStatus: ChatStatus = .before | ||
|
||
// 채팅 상태를 나타내는 열거형 | ||
public enum ChatStatus { | ||
case before // 질문 전 상태 | ||
case waiting // 질문을 보내고 응답을 기다리는 상태 | ||
case complete // 응답을 성공적으로 받은 상태 | ||
case failure // 응답을 받지 못한 상태 (오류 발생) | ||
} | ||
|
||
// 기본 초기화 함수 | ||
public init( | ||
question: String = "", | ||
answer: String = "", | ||
chatStatus: ChatStatus = .before | ||
) { | ||
self.question = question | ||
self.answer = answer | ||
self.chatStatus = chatStatus | ||
} | ||
} | ||
|
||
public enum Field { | ||
case question | ||
} | ||
|
||
// 기본 초기화 함수 | ||
public init( | ||
chatInfo: ChatInfo = .init(), | ||
chatHistory: [ChatInfo] = [], | ||
focus: Field? = .question | ||
|
||
) { | ||
self.chatInfo = chatInfo | ||
self.chatHistory = chatHistory | ||
self.focus = focus | ||
|
||
} | ||
} | ||
|
||
|
||
|
||
// 사용자 동작을 정의하는 열거형 | ||
public enum Action: BindableAction, Equatable { | ||
case sendMessage // 질문을 보내는 액션 | ||
case messageResponse(Result<String, ChatError>) // 서버 응답을 받는 액션 | ||
case updateQuestion(String) // 사용자가 질문을 입력할 때 상태를 업데이트하는 액션 | ||
case binding(BindingAction<State>) // 상태 변경을 처리하는 액션 | ||
|
||
// 서버 오류를 정의하는 열거형 | ||
public enum ChatError: Error, Equatable { | ||
case serverError(Error) // 서버 오류 | ||
|
||
public static func == (lhs: ChatError, rhs: ChatError) -> Bool { | ||
switch (lhs, rhs) { | ||
case let (.serverError(lhsError), .serverError(rhsError)): | ||
return lhsError.localizedDescription == rhsError.localizedDescription | ||
} | ||
} | ||
} | ||
} | ||
|
||
// 종속성 (Dependencies) | ||
//@Dependency(\.chatService) var chatService 질문을 서버로 보내고 응답을 받는 서비스 | ||
|
||
// 리듀서 본문 | ||
public var body: some ReducerOf<Self> { | ||
BindingReducer() // 상태 바인딩을 처리 | ||
|
||
Reduce { state, action in | ||
switch action { | ||
case .binding: | ||
return .none | ||
|
||
case .sendMessage: | ||
guard !state.chatInfo.question.isEmpty else { return .none } // 질문이 비어있지 않은지 확인 | ||
state.focus = nil | ||
state.chatInfo.chatStatus = .waiting // 질문을 보내고 상태를 waiting으로 변경 | ||
return .run { [question = state.chatInfo.question] send in | ||
do { | ||
// let answer = try await chatService.sendQuestion(question) // 질문을 보내고 응답을 기다림 | ||
await send(.messageResponse(.success(question))) // 응답을 성공적으로 받은 경우 | ||
} catch { | ||
await send(.messageResponse(.failure(.serverError(error)))) // 오류가 발생한 경우 | ||
} | ||
} | ||
|
||
case let .messageResponse(.success(answer)): | ||
state.chatInfo.answer = answer // 받은 답변을 상태에 저장 | ||
state.chatInfo.chatStatus = .complete // 상태를 complete로 변경 | ||
state.chatHistory.append(state.chatInfo) // 현재 채팅 정보를 히스토리에 추가 | ||
state.chatInfo = .init() // 현재 채팅 정보를 초기화 | ||
return .none | ||
|
||
case let .messageResponse(.failure(error)): | ||
state.chatInfo.chatStatus = .failure // 상태를 failure로 변경 | ||
print(error.localizedDescription) // 오류 메시지 출력 | ||
return .none | ||
|
||
case let .updateQuestion(question): | ||
state.chatInfo.question = question // 사용자가 입력한 질문을 상태에 저장 | ||
return .none | ||
} | ||
} | ||
} | ||
|
||
public init() { } | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
// | ||
// SwiftUIView.swift | ||
// | ||
// | ||
// Created by 최효원 on 8/5/24. | ||
// | ||
|
||
import SwiftUI | ||
import ComposableArchitecture | ||
import ColorSet | ||
import BotFeatures | ||
|
||
public struct BotView: View { | ||
@Bindable var store: StoreOf<BotFeature> | ||
@FocusState private var isFocused: Bool | ||
@State private var isShowingPopover = false | ||
|
||
public var body: some View { | ||
ZStack { | ||
Color.Kuring.bg | ||
.ignoresSafeArea() | ||
.onTapGesture { | ||
isFocused = false | ||
} | ||
VStack(alignment: .center) { | ||
HStack { | ||
Button { | ||
|
||
} label: { | ||
Image(systemName: "chevron.backward") | ||
} | ||
.padding() | ||
.frame(width: 20, height: 11) | ||
.foregroundStyle(Color.black) | ||
Spacer() | ||
Text("쿠링봇") | ||
.padding() | ||
.font(.system(size: 18, weight: .semibold)) | ||
Spacer() | ||
|
||
Button { | ||
self.isShowingPopover = true | ||
} label: { | ||
Image("icon_info_circle", bundle: Bundle.bots) | ||
} | ||
.popover( | ||
isPresented: $isShowingPopover, arrowEdge: .top | ||
) { | ||
Text(" ・ 쿠링봇은 2024년 6월 이후의 공지사항 내용을 기준으로 답변할 수 있어요.\n・ 테스트 기간인 관계로 한 달에 2회까지만 질문 가능해요.") | ||
.font(.system(size: 15, weight: .medium)) | ||
.padding() | ||
} | ||
} | ||
.padding(.horizontal, 18) | ||
Spacer() | ||
Image("kuring_app_gray", bundle: Bundle.bots) | ||
Spacer().frame(height: 20) | ||
Text("궁금한 건국대학교의\n공지 내용을 질문해보세요") | ||
.foregroundStyle(Color.Kuring.caption1) | ||
.font(.system(size: 15, weight: .medium)) | ||
.multilineTextAlignment(.center) | ||
.lineSpacing(5) | ||
Spacer() | ||
HStack(alignment: .bottom, spacing: 12) { | ||
TextField("메세지 입력", text: $store.chatInfo.question.max(), axis: .vertical) | ||
.lineLimit(5) | ||
.focused($isFocused) | ||
.padding(.horizontal) | ||
.padding(.vertical, 12) | ||
.overlay(RoundedRectangle(cornerRadius: 20).strokeBorder(Color.Kuring.gray200, style: StrokeStyle(lineWidth: 1.0))) | ||
|
||
Button { | ||
isFocused = false | ||
|
||
} label: { | ||
Image(systemName: "arrow.up.circle.fill") | ||
.resizable() | ||
.foregroundStyle(Color.Kuring.gray400) | ||
.scaledToFit() | ||
.frame(width: 40, height: 40) | ||
} | ||
} | ||
.padding(.horizontal, 20) | ||
Spacer().frame(height: 8) | ||
Text("쿠링봇은 실수를 할 수 있습니다. 중요한 정보를 확인하세요.") | ||
.foregroundStyle(Color.Kuring.caption2) | ||
.font(.system(size: 12, weight: .medium)) | ||
} | ||
.padding(.bottom, 16) | ||
} | ||
} | ||
|
||
public init(store: StoreOf<BotFeature>) { | ||
self.store = store | ||
} | ||
} | ||
|
||
extension View { | ||
func hideKeyboard() { | ||
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) | ||
} | ||
} | ||
|
||
extension Binding where Value == String { | ||
func max() -> Self { | ||
if self.wrappedValue.count > 200 { | ||
DispatchQueue.main.async { | ||
self.wrappedValue = String(self.wrappedValue.dropLast()) | ||
} | ||
} | ||
return self | ||
} | ||
} | ||
|
||
#Preview { | ||
BotView( | ||
store: Store( | ||
initialState: BotFeature.State(), | ||
reducer: { BotFeature() } | ||
) | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// | ||
// File.swift | ||
// | ||
// | ||
// Created by 최효원 on 8/5/24. | ||
// | ||
|
||
import Foundation | ||
|
||
extension Bundle { | ||
public static var bots: Bundle { .module } | ||
} |
6 changes: 6 additions & 0 deletions
6
package-kuring/Sources/UIKit/BotUI/Resources/Resources.xcassets/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
package-kuring/Sources/UIKit/BotUI/Resources/Resources.xcassets/appIcon/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
...UIKit/BotUI/Resources/Resources.xcassets/appIcon/kuring_app_circle.imageset/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"images" : [ | ||
{ | ||
"filename" : "kuring.app.png", | ||
"idiom" : "universal", | ||
"scale" : "1x" | ||
}, | ||
{ | ||
"filename" : "kuring.app2.png", | ||
"idiom" : "universal", | ||
"scale" : "2x" | ||
}, | ||
{ | ||
"filename" : "kuring.app3.png", | ||
"idiom" : "universal", | ||
"scale" : "3x" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
Binary file added
BIN
+1.13 KB
.../Resources/Resources.xcassets/appIcon/kuring_app_circle.imageset/kuring.app.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.4 KB
...Resources/Resources.xcassets/appIcon/kuring_app_circle.imageset/kuring.app2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+3.55 KB
...Resources/Resources.xcassets/appIcon/kuring_app_circle.imageset/kuring.app3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.19 KB
...I/Resources/Resources.xcassets/appIcon/kuring_app_gray.imageset/Component 1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.14 KB
...I/Resources/Resources.xcassets/appIcon/kuring_app_gray.imageset/Component 2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+3.13 KB
...I/Resources/Resources.xcassets/appIcon/kuring_app_gray.imageset/Component 3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 23 additions & 0 deletions
23
...s/UIKit/BotUI/Resources/Resources.xcassets/appIcon/kuring_app_gray.imageset/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"images" : [ | ||
{ | ||
"filename" : "Component 1.png", | ||
"idiom" : "universal", | ||
"scale" : "1x" | ||
}, | ||
{ | ||
"filename" : "Component 2.png", | ||
"idiom" : "universal", | ||
"scale" : "2x" | ||
}, | ||
{ | ||
"filename" : "Component 3.png", | ||
"idiom" : "universal", | ||
"scale" : "3x" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
package-kuring/Sources/UIKit/BotUI/Resources/Resources.xcassets/icon/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
...ces/UIKit/BotUI/Resources/Resources.xcassets/icon/icon_info_circle.imageset/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"images" : [ | ||
{ | ||
"filename" : "icon-info-circle-mono.png", | ||
"idiom" : "universal", | ||
"scale" : "1x" | ||
}, | ||
{ | ||
"filename" : "icon-info-circle-mono2.png", | ||
"idiom" : "universal", | ||
"scale" : "2x" | ||
}, | ||
{ | ||
"filename" : "icon-info-circle-mono3.png", | ||
"idiom" : "universal", | ||
"scale" : "3x" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
Binary file added
BIN
+481 Bytes
...ces/Resources.xcassets/icon/icon_info_circle.imageset/icon-info-circle-mono.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+961 Bytes
...es/Resources.xcassets/icon/icon_info_circle.imageset/icon-info-circle-mono2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.25 KB
...es/Resources.xcassets/icon/icon_info_circle.imageset/icon-info-circle-mono3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 23 additions & 0 deletions
23
...rces/UIKit/BotUI/Resources/Resources.xcassets/icon/icon_send_white.imageset/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"images" : [ | ||
{ | ||
"filename" : "Send.png", | ||
"idiom" : "universal", | ||
"scale" : "1x" | ||
}, | ||
{ | ||
"filename" : "Send2.png", | ||
"idiom" : "universal", | ||
"scale" : "2x" | ||
}, | ||
{ | ||
"filename" : "Send3.png", | ||
"idiom" : "universal", | ||
"scale" : "3x" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
Binary file added
BIN
+876 Bytes
...UIKit/BotUI/Resources/Resources.xcassets/icon/icon_send_white.imageset/Send.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.56 KB
...IKit/BotUI/Resources/Resources.xcassets/icon/icon_send_white.imageset/Send2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.29 KB
...IKit/BotUI/Resources/Resources.xcassets/icon/icon_send_white.imageset/Send3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.