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
12 changes: 6 additions & 6 deletions GAMSS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
8F4E518B79C7B76223B098BA /* Tokenizers in Frameworks */ = {isa = PBXBuildFile; productRef = 8E8487F478AF703D394C5EB6 /* Tokenizers */; };
94A526BCCCD9DF730A39BF97 /* sample_sentences.json in Resources */ = {isa = PBXBuildFile; fileRef = D4BE9D664889F13369325DC9 /* sample_sentences.json */; };
9EA6F6B8DF51021E18342083 /* HomeViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EDC07CB1FA5BA970388DB6A /* HomeViewModelTests.swift */; };
FA90ADA39E7A145713881061 /* MainTabTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C15D652D0472A1EBD024674 /* MainTabTests.swift */; };
A8948FBCA4DF4E43F2C582EA /* Pods_GAMSS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EB14F9D00BB8B80EFE9A40A4 /* Pods_GAMSS.framework */; };
A8FEE0AD9A4A60908DC5F5F1 /* CreateMessageRequestDTOTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7DAA522A6DCECC0B3666523C /* CreateMessageRequestDTOTests.swift */; };
ABF5C91182F3B409C1AA9E8E /* GetMessagesUseCaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83A67D7BECCB85A88C969AD7 /* GetMessagesUseCaseTests.swift */; };
B32ACCF04698A89364EDDECE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 316EA002FAC5D3328796EF90 /* Foundation.framework */; };
BA7748118B0D2759E0F6A207 /* Pods_GAMSSTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F1CC8FA289575E4B98C41539 /* Pods_GAMSSTests.framework */; };
Expand All @@ -34,7 +36,6 @@
CC604C7607382102024E0FA1 /* ConversationSummaryPolicyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41CCBD8A019CAA37319E7984 /* ConversationSummaryPolicyTests.swift */; };
DC1369FEAE93D794107D5373 /* Color_GAMSSTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 596EE0F239D37460A7BA389D /* Color_GAMSSTests.swift */; };
E3A3BE7330A1CCAB9E144B41 /* DefaultEmotionAnalysisRepositoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B816EE4A02D0B23C50F35FF9 /* DefaultEmotionAnalysisRepositoryTests.swift */; };
A8FEE0AD9A4A60908DC5F5F1 /* CreateMessageRequestDTOTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7DAA522A6DCECC0B3666523C /* CreateMessageRequestDTOTests.swift */; };
EE5555555555555555555555 /* TypographyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4444444444444444444444 /* TypographyTests.swift */; };
F1D4E5A20F2B3C4D5E6F7A8B /* SpacingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2D4E5A30F2B3C4D5E6F7A8C /* SpacingTests.swift */; };
F29C98F332A3EC127B809DD3 /* ChatViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE5C85E76690E41AE394895D /* ChatViewModelTests.swift */; };
Expand All @@ -57,15 +58,16 @@
1A8F630A15A80F5FAB52F2C1 /* Pods-GAMSSTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GAMSSTests.debug.xcconfig"; path = "Target Support Files/Pods-GAMSSTests/Pods-GAMSSTests.debug.xcconfig"; sourceTree = "<group>"; };
316EA002FAC5D3328796EF90 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
3EDC07CB1FA5BA970388DB6A /* HomeViewModelTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HomeViewModelTests.swift; sourceTree = "<group>"; };
3C15D652D0472A1EBD024674 /* MainTabTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = MainTabTests.swift; sourceTree = "<group>"; };
41CCBD8A019CAA37319E7984 /* ConversationSummaryPolicyTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ConversationSummaryPolicyTests.swift; sourceTree = "<group>"; };
4DDF78D0118869F3D9E1E269 /* SendMessageUseCaseTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SendMessageUseCaseTests.swift; sourceTree = "<group>"; };
596EE0F239D37460A7BA389D /* Color_GAMSSTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Color_GAMSSTests.swift; sourceTree = "<group>"; };
5B4F594F8D1059D3DF30DE92 /* GAMSSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GAMSSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
708F57F33003C651008DF433 /* GAMSS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GAMSS.app; sourceTree = BUILT_PRODUCTS_DIR; };
7674D757C326ABEDB6302AA6 /* GAMSSTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = GAMSSTests.swift; sourceTree = "<group>"; };
7DAA522A6DCECC0B3666523C /* CreateMessageRequestDTOTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CreateMessageRequestDTOTests.swift; sourceTree = "<group>"; };
79F056320618BF2744EAC909 /* EmotionTestViewModelTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = EmotionTestViewModelTests.swift; sourceTree = "<group>"; };
7BB1A4112363D93ED3AD1598 /* EmotionCharacterTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = EmotionCharacterTests.swift; sourceTree = "<group>"; };
7DAA522A6DCECC0B3666523C /* CreateMessageRequestDTOTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CreateMessageRequestDTOTests.swift; sourceTree = "<group>"; };
83A67D7BECCB85A88C969AD7 /* GetMessagesUseCaseTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = GetMessagesUseCaseTests.swift; sourceTree = "<group>"; };
86563A77A8A674E7F050119E /* CommentRevealPolicyTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CommentRevealPolicyTests.swift; sourceTree = "<group>"; };
A17C099A15F7D9B1481998D0 /* DefaultSummaryRepositoryTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DefaultSummaryRepositoryTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -277,6 +279,7 @@
79F056320618BF2744EAC909 /* EmotionTestViewModelTests.swift */,
BE5C85E76690E41AE394895D /* ChatViewModelTests.swift */,
3EDC07CB1FA5BA970388DB6A /* HomeViewModelTests.swift */,
3C15D652D0472A1EBD024674 /* MainTabTests.swift */,
);
path = Presentation;
sourceTree = "<group>";
Expand Down Expand Up @@ -516,14 +519,10 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-GAMSS/Pods-GAMSS-resources-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-GAMSS/Pods-GAMSS-resources-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-GAMSS/Pods-GAMSS-resources.sh\"\n";
Expand Down Expand Up @@ -571,6 +570,7 @@
E3A3BE7330A1CCAB9E144B41 /* DefaultEmotionAnalysisRepositoryTests.swift in Sources */,
06BCF4ADC30405F292D7B64C /* EmotionTestViewModelTests.swift in Sources */,
F29C98F332A3EC127B809DD3 /* ChatViewModelTests.swift in Sources */,
FA90ADA39E7A145713881061 /* MainTabTests.swift in Sources */,
9EA6F6B8DF51021E18342083 /* HomeViewModelTests.swift in Sources */,
C63AB33F1424E4237FF76F6B /* SummaryErrorTests.swift in Sources */,
1D8DF6DFC7E7383B9B8C5850 /* DefaultSummaryRepositoryTests.swift in Sources */,
Expand Down
23 changes: 23 additions & 0 deletions GAMSS/Resources/Assets.xcassets/logoGamss.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "logo_gamss.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "logo_gamss@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "logo_gamss@3x.png",
"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.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions GAMSS/Sources/Presentation/Archive/ArchiveView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// ArchiveView.swift
// GAMSS
//
// Created by cchanmi on 8/10/26.
//

import SwiftUI

struct ArchiveView: View {
var body: some View {
VStack {
Spacer()
Text("준비 중입니다")
.typography(.body3Regular)
.foregroundStyle(Color.colorGray500)
Spacer()
}
}
}

#Preview {
ArchiveView()
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import SwiftUI

struct ConversationListView: View {
@StateObject private var viewModel: ConversationListViewModel
@Binding private var isTabBarHidden: Bool

init(viewModel: ConversationListViewModel) {
init(viewModel: ConversationListViewModel, isTabBarHidden: Binding<Bool>) {
_viewModel = StateObject(wrappedValue: viewModel)
_isTabBarHidden = isTabBarHidden
}

var body: some View {
Expand All @@ -36,7 +38,8 @@ struct ConversationListView: View {
conversationId: conversation.id
)
)
.toolbar(.hidden, for: .tabBar)
.onAppear { isTabBarHidden = true }
.onDisappear { isTabBarHidden = false }
}
}
.task {
Expand All @@ -57,6 +60,7 @@ struct ConversationListView: View {
getConversationsUseCase: GetConversationsUseCase(
conversationRepository: DefaultConversationRepository(networkManager: NetworkManager.shared)
)
)
),
isTabBarHidden: .constant(false)
)
}
21 changes: 11 additions & 10 deletions GAMSS/Sources/Presentation/Home/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import SwiftUI
struct HomeView: View {
@StateObject private var viewModel: HomeViewModel
@FocusState private var isInputFocused: Bool
@Binding private var isTabBarHidden: Bool

init(viewModel: HomeViewModel) {
init(viewModel: HomeViewModel, isTabBarHidden: Binding<Bool>) {
_viewModel = StateObject(wrappedValue: viewModel)
_isTabBarHidden = isTabBarHidden
}

var body: some View {
Expand Down Expand Up @@ -55,7 +57,8 @@ struct HomeView: View {
initialSentMessage: viewModel.createdSentMessage
)
)
.toolbar(.hidden, for: .tabBar)
.onAppear { isTabBarHidden = true }
.onDisappear { isTabBarHidden = false }
}
}
.alert(viewModel.alertMessage ?? "", isPresented: Binding(
Expand All @@ -68,13 +71,10 @@ struct HomeView: View {

private var header: some View {
HStack {
Text("GAMSS")
.typography(.subtitle3)
.foregroundStyle(Color.colorGray950)
.padding(.horizontal, Spacing.spacing300)
.padding(.vertical, Spacing.spacing100)
.background(Color.colorGray050)
.clipShape(Capsule())
Image("logoGamss")
.resizable()
.scaledToFit()
.frame(height: 24)

Spacer()

Expand Down Expand Up @@ -139,6 +139,7 @@ struct HomeView: View {
sendMessageUseCase: SendMessageUseCase(
conversationRepository: DefaultConversationRepository(networkManager: NetworkManager.shared)
)
)
),
isTabBarHidden: .constant(false)
)
}
59 changes: 59 additions & 0 deletions GAMSS/Sources/Presentation/Root/CustomTabBar.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//
// CustomTabBar.swift
// GAMSS
//
// Created by cchanmi on 8/10/26.
//

import SwiftUI

struct CustomTabBar: View {
@Binding var selectedTab: MainTab

var body: some View {
HStack(spacing: 0) {
ForEach(MainTab.allCases, id: \.self) { tab in
tabButton(for: tab)
}
}
.padding(.top, Spacing.spacing200)
.padding(.bottom, Spacing.spacing100)
.background(Color.colorWhite)
.overlay(
Rectangle()
.stroke(Color.colorBlack, lineWidth: 1.5)
)
}

@ViewBuilder
private func tabButton(for tab: MainTab) -> some View {
let isSelected = selectedTab == tab

Button {
selectedTab = tab
} label: {
VStack(spacing: Spacing.spacing050) {
Image(tab.iconName)
.renderingMode(.template)
.resizable()
.scaledToFit()
.frame(width: 24, height: 24)

Text(tab.title)
.typography(.caption3)
}
.foregroundStyle(isSelected ? Color.colorGray950 : Color.colorGray300)
.frame(maxWidth: .infinity)
}
.buttonStyle(.plain)
}
}

#Preview {
VStack {
Spacer()
CustomTabBar(selectedTab: .constant(.home))
.padding(.horizontal, Spacing.spacing400)
.padding(.bottom, Spacing.spacing200)
}
}
30 changes: 30 additions & 0 deletions GAMSS/Sources/Presentation/Root/MainTab.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// MainTab.swift
// GAMSS
//
// Created by cchanmi on 8/10/26.
//

import Foundation

enum MainTab: CaseIterable, Hashable {
case archive
case home
case chat

var title: String {
switch self {
case .archive: return "보관함"
case .home: return "홈"
case .chat: return "대화"
}
}

var iconName: String {
switch self {
case .archive: return "tabIconArchive"
case .home: return "tabIconHome"
case .chat: return "tabIconChat"
}
}
}
32 changes: 27 additions & 5 deletions GAMSS/Sources/Presentation/Root/MainTabView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,47 @@
import SwiftUI

struct MainTabView: View {
@State private var selectedTab: MainTab = .home
@State private var isTabBarHidden = false

var body: some View {
TabView {
content
.safeAreaInset(edge: .bottom) {
if !isTabBarHidden {
CustomTabBar(selectedTab: $selectedTab)
.padding(.horizontal, Spacing.spacing400)
.padding(.bottom, Spacing.spacing200)
.transition(.opacity)
}
}
.animation(.easeInOut(duration: 0.15), value: isTabBarHidden)
}

@ViewBuilder
private var content: some View {
switch selectedTab {
case .archive:
ArchiveView()

case .home:
HomeView(
viewModel: HomeViewModel(
sendMessageUseCase: SendMessageUseCase(
conversationRepository: DefaultConversationRepository(networkManager: NetworkManager.shared)
)
)
),
isTabBarHidden: $isTabBarHidden
)
.tabItem { Label("홈", systemImage: "house") }

case .chat:
ConversationListView(
viewModel: ConversationListViewModel(
getConversationsUseCase: GetConversationsUseCase(
conversationRepository: DefaultConversationRepository(networkManager: NetworkManager.shared)
)
)
),
isTabBarHidden: $isTabBarHidden
)
.tabItem { Label("대화", systemImage: "bubble.left.and.bubble.right") }
}
}
}
Expand Down
27 changes: 27 additions & 0 deletions GAMSSTests/Presentation/MainTabTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// MainTabTests.swift
// GAMSS
//
// Created by cchanmi on 8/10/26.
//

import XCTest
@testable import GAMSS

final class MainTabTests: XCTestCase {
func test_title_returnsKoreanLabelForEachTab() {
XCTAssertEqual(MainTab.archive.title, "보관함")
XCTAssertEqual(MainTab.home.title, "홈")
XCTAssertEqual(MainTab.chat.title, "대화")
}

func test_iconName_returnsAssetNameForEachTab() {
XCTAssertEqual(MainTab.archive.iconName, "tabIconArchive")
XCTAssertEqual(MainTab.home.iconName, "tabIconHome")
XCTAssertEqual(MainTab.chat.iconName, "tabIconChat")
}

func test_allCases_containsThreeTabsInOrder() {
XCTAssertEqual(MainTab.allCases, [.archive, .home, .chat])
}
}
Loading