From 41a58b14128d1147aef1be3c4ee4e2c96e80cd0b Mon Sep 17 00:00:00 2001 From: jeonjimin Date: Wed, 10 Apr 2024 20:05:40 +0900 Subject: [PATCH 01/11] =?UTF-8?q?[Feat]=20#523=20-=20=EA=B2=80=EC=83=89?= =?UTF-8?q?=ED=99=94=EB=A9=B4=20UI=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HappyAnding.xcodeproj/project.pbxproj | 4 + .../HappyAnding/Extensions/SCZColor.swift | 8 + .../HappyAnding/Views/SearchView.swift | 465 ++++++++++++++---- .../HappyAnding/Views/SearchViewModel.swift | 60 +++ 4 files changed, 439 insertions(+), 98 deletions(-) create mode 100644 HappyAnding/HappyAnding/Extensions/SCZColor.swift create mode 100644 HappyAnding/HappyAnding/Views/SearchViewModel.swift diff --git a/HappyAnding/HappyAnding.xcodeproj/project.pbxproj b/HappyAnding/HappyAnding.xcodeproj/project.pbxproj index 206637ab..72291601 100644 --- a/HappyAnding/HappyAnding.xcodeproj/project.pbxproj +++ b/HappyAnding/HappyAnding.xcodeproj/project.pbxproj @@ -168,6 +168,7 @@ F9DB8EBB293986E100516CE1 /* ShareExtensionViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F976E85029395B350088BBA1 /* ShareExtensionViewModel.swift */; }; F9DB8EBD293987BD00516CE1 /* ShareExtensionCustomTextEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9DB8EBC293987BD00516CE1 /* ShareExtensionCustomTextEditor.swift */; }; F9DB8ED3293B4C3200516CE1 /* ShareExtensionTagTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9DB8ED2293B4C3200516CE1 /* ShareExtensionTagTextField.swift */; }; + F9E7073A2BC6933000319533 /* SearchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9E707392BC6933000319533 /* SearchViewModel.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -343,6 +344,7 @@ F9DB8EB82939853D00516CE1 /* ShareExtensionValidationTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareExtensionValidationTextField.swift; sourceTree = ""; }; F9DB8EBC293987BD00516CE1 /* ShareExtensionCustomTextEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareExtensionCustomTextEditor.swift; sourceTree = ""; }; F9DB8ED2293B4C3200516CE1 /* ShareExtensionTagTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareExtensionTagTextField.swift; sourceTree = ""; }; + F9E707392BC6933000319533 /* SearchViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchViewModel.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -544,6 +546,7 @@ A34BF82929AFC308009BC946 /* FeatureViews */, 87E606AE291062D300C3DA13 /* SignInViews */, 8792479A291BDF820040D5C3 /* SearchView.swift */, + F9E707392BC6933000319533 /* SearchViewModel.swift */, 3D41EE07290A4C18008BE986 /* Launch Screen.storyboard */, F9136EB5293612310034AAB2 /* ShortcutsZipView.swift */, ); @@ -994,6 +997,7 @@ A323D3CA2AEE870700DDA716 /* SuggestionForm.swift in Sources */, 4DF15D752A4ECE1F0014F854 /* ListCategoryShortcutViewModel.swift in Sources */, 87E99CDB29042CCA009B691F /* Category.swift in Sources */, + F9E7073A2BC6933000319533 /* SearchViewModel.swift in Sources */, 876B4F6F299E3D91009672D9 /* NavigationRouter.swift in Sources */, F98017202BBC2A6F004F2EA7 /* ExploreCell.swift in Sources */, A04ACB062903D0B2004A85A6 /* MyShortcutCardView.swift in Sources */, diff --git a/HappyAnding/HappyAnding/Extensions/SCZColor.swift b/HappyAnding/HappyAnding/Extensions/SCZColor.swift new file mode 100644 index 00000000..e59149c9 --- /dev/null +++ b/HappyAnding/HappyAnding/Extensions/SCZColor.swift @@ -0,0 +1,8 @@ +// +// SCZColor.swift +// HappyAnding +// +// Created by JeonJimin on 4/10/24. +// + +import Foundation diff --git a/HappyAnding/HappyAnding/Views/SearchView.swift b/HappyAnding/HappyAnding/Views/SearchView.swift index 58ed256a..406c0a73 100644 --- a/HappyAnding/HappyAnding/Views/SearchView.swift +++ b/HappyAnding/HappyAnding/Views/SearchView.swift @@ -8,144 +8,413 @@ import MessageUI import SwiftUI +//TODO: 머지 전 화면 연결 필요 +///검색 방식 변경 필요할 수도..(현재는 기존 방식 유지) struct SearchView: View { - @Environment(\.isSearching) private var isSearching: Bool - @Environment(\.dismissSearch) private var dismissSearch - @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel - - @FocusState private var isFocused: Bool - - @State var keywords: Keyword = Keyword(keyword: [String]()) - @State var isSearched: Bool = false - @State var searchText: String = "" - @State var shortcutResults = Set() - - + @StateObject var viewModel: SearchViewModel +// @Binding var isSearchAcivated: Bool + var body: some View { - VStack { - SearchBar() + VStack(spacing: 12) { + SearchBar(viewModel: self.viewModel) + if viewModel.searchText.isEmpty { + SearchSuggestionList(viewModel: self.viewModel) + } else if viewModel.shortcutResults.isEmpty && viewModel.postResults.isEmpty { + EmptyResultView(searchText: $viewModel.searchText) + } else { + SearchResultList(shortcuts: viewModel.shortcutResults, posts: viewModel.postResults) + } + Spacer() } .frame(maxWidth: .infinity, maxHeight: .infinity) - .background(Color.black.opacity(0.13).ignoresSafeArea()) + .background(SCZColor.CharcoalGray.opacity24.ignoresSafeArea()) + .onChange(of: viewModel.searchText) { _ in + viewModel.didChangedSearchText() + if !viewModel.searchText.isEmpty { + viewModel.isSearched = true + } else { + viewModel.shortcutResults.removeAll() + viewModel.isSearched = false + } + } + //빈 부분 터치 시 검색화면 벗어나기 +// .onTapGesture { +// isSearchAcivated.toggle() +// } } - - private func runSearch() { - isSearched = true +} + +struct EmptyResultView: View { + @Binding var searchText: String + var body: some View { + VStack(alignment: .leading, spacing: 0) { + Text("😵 \'\(searchText)\'에 관련된 단축어나 글이 없어요.") + .foregroundStyle(SCZColor.CharcoalGray.opacity48) + .padding(.horizontal, 16) + .padding(.vertical, 8) + Divider() + .padding(.vertical, 10) + Button{ + print("단축어 작성 페이지 연결") + } label: { + HStack { + Text("\'\(searchText)\' 관련 단축어 공유하기") + .foregroundStyle(SCZColor.CharcoalGray.opacity64) + Spacer() + Image(systemName: "chevron.right") + .foregroundStyle(SCZColor.CharcoalGray.opacity24) + } + .padding(.horizontal, 16) + .padding(.vertical, 8) + } + Divider() + .padding(.vertical, 10) + Button{ + print("post 작성 페이지 연결") + } label: { + HStack { + Text("\'\(searchText)\' 관련 질문하기") + .foregroundStyle(SCZColor.CharcoalGray.opacity64) + Spacer() + Image(systemName: "chevron.right") + .foregroundStyle(SCZColor.CharcoalGray.opacity24) + } + .padding(.horizontal, 16) + .padding(.vertical, 8) + } + } + .font(.system(size: 14, weight: .medium)) + .padding(.vertical, 8) + .background( + ZStack { + Color.white.opacity(0.64) + SCZColor.CharcoalGray.opacity08 + } + ) + .clipShape(RoundedRectangle(cornerRadius: 16)) + .roundedBorder(cornerRadius: 16, color: Color.white, isNormalBlend: true, opacity: 0.12) + .padding(.horizontal, 16) } - - var searchTextfield: some View { - HStack(alignment: .center, spacing: 8) { - HStack { - Image(systemName: "magnifyingglass") - .foregroundStyle(Color.gray5) - TextField(TextLiteral.searchViewPrompt, text: $searchText) - .shortcutsZipBody1() - .accentColor(.gray5) - .disableAutocorrection(true) - .onChange(of: searchText) { _ in - // TODO: 수정 필요 - didChangedSearchText() +} +enum ResultType { + case shortcut, post +} + +struct SearchResultList: View { + var shortcuts: [Shortcuts] + var posts: [[String]] + var body: some View { + ScrollView { + VStack(alignment: .leading, spacing: 16) { + if shortcuts.count > 0 { + ResultSection(type: .shortcut, title: "관련된 단축어", shortcuts: shortcuts) + } + if posts.count > 0 { + ResultSection(type: .post, title: "관련된 글", posts: posts) + } + } + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.horizontal, 16) + } + .scrollDismissesKeyboard(.immediately) + } +} + +struct ResultSection: View { + let type: ResultType + let title: String + var shortcuts: [Shortcuts]? + var posts: [[String]]? + //TODO: Post 구조 추가 + var body: some View { + VStack(alignment: .leading, spacing: 12) { + Text(title) + .font(.system(size: 14, weight: .medium)) + .foregroundStyle(SCZColor.CharcoalGray.opacity48) + .padding(.horizontal, 12) + + if let shortcuts { + VStack(alignment: .leading, spacing: 6) { + Rectangle()// 상단 여백을 주기 위함 + .frame(height: 0.1) + .foregroundStyle(Color.clear) + ForEach(Array(shortcuts.prefix(3).enumerated()), id: \.offset) { index, shortcut in + ResultShortcutCell(shortcut: shortcut) + + if index != shortcuts.count-1 || shortcuts.count > 3{ + Divider() + .padding(.vertical, 10) + .foregroundStyle(SCZColor.CharcoalGray.opacity08) + } } - .focused($isFocused) - .task { - DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { - isFocused = true + + if shortcuts.count > 3 { + Button { + print("더많은 검색결과") + } label: { + HStack { + Text("더 많은 검색 결과 보기") + .font(.system(size: 14, weight: .medium)) + .foregroundStyle(SCZColor.CharcoalGray.opacity48) + Spacer() + Image(systemName: "chevron.right") + .foregroundStyle(SCZColor.CharcoalGray.opacity24) + } + .padding(.horizontal, 16) + .padding(.bottom, 6) } } - .shortcutsZipBody1() + } + .padding(.vertical, 10) + .background( + ZStack { + Color.white.opacity(0.64) + SCZColor.CharcoalGray.opacity08 + } + ) + .roundedBorder(cornerRadius: 16, color: Color.white, isNormalBlend: true, opacity: 0.12) } - .padding(11) - .background(Color.gray1) - .cornerRadius(12) - } - .padding(EdgeInsets(top: 12, leading: 16, bottom: 20, trailing: 16)) - } - - var recommendKeyword: some View { - VStack(alignment: .leading) { - Text(TextLiteral.searchViewRecommendedKeyword) - .padding(.leading, 16) - .shortcutsZipHeadline() - ScrollView(.horizontal) { - HStack { - ForEach(keywords.keyword, id: \.self) { keyword in - Text(keyword) - .shortcutsZipBody2() - .foregroundStyle(Color.gray4) - .padding(.horizontal, 12) - .padding(.vertical, 8) - .overlay( - RoundedRectangle(cornerRadius: 12) - .strokeBorder(Color.gray4, lineWidth: 1) - ) - .onTapGesture { - searchText = keyword - runSearch() + if let posts { + VStack(alignment: .leading, spacing: 6) { + Rectangle()// 상단 여백을 주기 위함 + .frame(height: 0.1) + .foregroundStyle(Color.clear) + ForEach(Array(posts.prefix(3).enumerated()), id: \.offset) { index, post in + ResultPostCell(post: post) + + if index != posts.count-1 || posts.count>3 { + Divider() + .padding(.vertical, 10) + .foregroundStyle(SCZColor.CharcoalGray.opacity08) + } + } + + if posts.count > 3 { + Button { + print("더많은 검색결과") + } label: { + HStack { + Text("더 많은 검색 결과 보기") + .font(.system(size: 14, weight: .medium)) + .foregroundStyle(SCZColor.CharcoalGray.opacity48) + Spacer() + Image(systemName: "chevron.right") + .foregroundStyle(SCZColor.CharcoalGray.opacity24) } + .padding(.horizontal, 16) + .padding(.bottom, 6) + } } } - .padding(.leading, 16) - .padding(.top, 8) + .padding(.vertical, 10) + .background( + ZStack { + Color.white.opacity(0.64) + SCZColor.CharcoalGray.opacity08 + } + ) + .roundedBorder(cornerRadius: 16, color: Color.white, isNormalBlend: true, opacity: 0.12) } } } +} + +struct ResultShortcutCell: View { + let shortcut: Shortcuts - var proposeView: some View { - VStack(alignment: .center) { - Text("\'\(searchText)\'의 결과가 없어요.\n원하는 단축어가 있다면 제안해보세요!").multilineTextAlignment(.center) - .shortcutsZipBody1() - .foregroundStyle(Color.gray4) - - Link(destination: URL(string: TextLiteral.searchViewProposalURL)!) { - Text(TextLiteral.searchViewProposal) - .padding(.horizontal, 28) - .padding(.vertical, 8) + var body: some View { + Button { + print("단축어 상세페이지 연결") + } label: { + HStack { + ShortcutIcon(sfSymbol: shortcut.sfSymbol, color: shortcut.color, size: 56) + VStack(alignment: .leading, spacing: 4) { + Text(shortcut.title) + //Pretendard bold 16 + .font(.system(size: 16, weight: .bold)) + .foregroundStyle(SCZColor.Basic) + Text(shortcut.subtitle) + //Pretendard medieum 14 + .font(.system(size: 14, weight: .medium)) + .foregroundStyle(SCZColor.CharcoalGray.opacity48) + } + Spacer() + Image(systemName: "chevron.right") + .foregroundStyle(SCZColor.CharcoalGray.opacity24) } - .buttonStyle(.borderedProminent) - .padding(16) + .padding(.horizontal, 16) } - .frame(maxWidth: .infinity, maxHeight: .infinity) - .background(Color.shortcutsZipBackground) } - private func didChangedSearchText() { - shortcutResults.removeAll() - - for data in shortcutsZipViewModel.allShortcuts { - if data.title.lowercased().contains(searchText.lowercased()) || - !data.requiredApp.filter({ $0.lowercased().contains(searchText.lowercased()) }).isEmpty || - data.subtitle.lowercased().contains(searchText.lowercased()) - { - shortcutResults.insert(data) +} + +struct ResultPostCell: View { + let post: [String] + + var body: some View { + Button { + print("post 상세페이지 연결") + } label: { + HStack { + Text(post[1]) + //Pretendard medieum 14 + .font(.system(size: 14, weight: .medium)) + .foregroundStyle(SCZColor.CharcoalGray.opacity64) + Spacer() + Image(systemName: "chevron.right") + .foregroundStyle(SCZColor.CharcoalGray.opacity24) } + .padding(.horizontal, 16) } } } +//TODO: 검색기록 추가 +struct SearchSuggestionList: View { + @StateObject var viewModel: SearchViewModel + + var body: some View { + VStack(alignment: .leading, spacing: 0) { + + + if viewModel.searchHistory.isEmpty { + //추천 검색어 + ForEach(0.. Date: Sat, 13 Apr 2024 20:51:52 +0900 Subject: [PATCH 02/11] =?UTF-8?q?[Feat]=20#523=20-=20=EB=94=94=EC=9E=90?= =?UTF-8?q?=EC=9D=B8=20=EC=88=98=EC=A0=95=EC=82=AC=ED=95=AD=20=EB=B0=98?= =?UTF-8?q?=EC=98=81=20=EB=B0=8F=20=ED=85=8D=EC=8A=A4=ED=8A=B8=20=EB=A6=AC?= =?UTF-8?q?=ED=84=B0=EB=9F=B4=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 컬러 익스텐션 수정 및 반영 --- .../HappyAnding.xcodeproj/project.pbxproj | 25 +- .../HappyAnding/Extensions/SCZ+Color.swift | 12 +- .../Extensions/String/String+Date.swift | 16 + .../Extensions/View/View+Navigation.swift | 5 - .../HappyAnding/Model/SectionType.swift | 8 +- HappyAnding/HappyAnding/TextLiteral.swift | 12 + .../Views/Components/ExploreCell.swift | 4 +- .../Views/Components/ShortcutIcon.swift | 2 +- .../ExploreShortcutView.swift | 4 +- .../HappyAnding/Views/SearchView.swift | 370 +++++++++--------- .../HappyAnding/Views/SearchViewModel.swift | 73 +++- .../Views/TabView/ShortcutTabView.swift | 10 +- 12 files changed, 313 insertions(+), 228 deletions(-) diff --git a/HappyAnding/HappyAnding.xcodeproj/project.pbxproj b/HappyAnding/HappyAnding.xcodeproj/project.pbxproj index 72291601..ff274338 100644 --- a/HappyAnding/HappyAnding.xcodeproj/project.pbxproj +++ b/HappyAnding/HappyAnding.xcodeproj/project.pbxproj @@ -672,7 +672,6 @@ F91F09DC29AE012600E04FA0 /* ShortcutGrade.swift */, 872B5D3C2A2E0FF9008DCC57 /* CurationType.swift */, A323D3C92AEE870700DDA716 /* SuggestionForm.swift */, - F980171D2BBC2A24004F2EA7 /* ExploreShortcutSectionType.swift */, ); path = Model; sourceTree = ""; @@ -1296,7 +1295,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.happyanding.HappyAnding; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = ShortcutsZipProfile_Dev_20231113; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = ShortcutsZipProfile_Dev_20240317; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; @@ -1339,7 +1338,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.happyanding.HappyAnding; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = ShortcutsZipProfile_Dev_20231113; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = ShortcutsZipProfile_Dev_20240317; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; @@ -1354,14 +1353,16 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 7JPPWR5997; + DEVELOPMENT_TEAM = ""; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 16.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.happyanding.HappyAndingTests; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -1374,14 +1375,16 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 7JPPWR5997; + DEVELOPMENT_TEAM = ""; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 16.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.happyanding.HappyAndingTests; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -1393,13 +1396,15 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 7JPPWR5997; + DEVELOPMENT_TEAM = ""; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.happyanding.HappyAndingUITests; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -1411,13 +1416,15 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 7JPPWR5997; + DEVELOPMENT_TEAM = ""; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.happyanding.HappyAndingUITests; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -1448,7 +1455,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.happyanding.HappyAnding.ShareExtension; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = ShortcutsZipShareExtProfile_Dev_20231113; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = ShortcutsZipShareExtProfile_Dev_20240317; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -1480,7 +1487,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.happyanding.HappyAnding.ShareExtension; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = ShortcutsZipShareExtProfile_Dev_20231113; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = ShortcutsZipShareExtProfile_Dev_20240317; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; diff --git a/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift b/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift index 5ed1833b..b55c5ec5 100644 --- a/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift +++ b/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift @@ -60,7 +60,6 @@ struct GradientType { } struct SCZColor { - static let defaultColor = Red().light.fillGradient() static let colors: [String: ColorProtocol] = [ "Red": Red(), "Coral": Coral(), @@ -565,7 +564,7 @@ extension SCZColor { ) } struct CharcoalGray { - static let color: Color = Color(hexString: "404040") + static let color = Color(hexString: "404040") static let opacity88 = Color(hexString: "404040", opacity: 0.88) static let opacity64 = Color(hexString: "404040", opacity: 0.64) static let opacity48 = Color(hexString: "404040", opacity: 0.48) @@ -574,4 +573,13 @@ extension SCZColor { static let opacity08 = Color(hexString: "404040", opacity: 0.08) static let opacity04 = Color(hexString: "404040", opacity: 0.04) } + + ///SCZBlue 색상 사용 시 백그라운드에 white 색상 넣어줘야 의도한 색으로 나타납니다. + struct SCZBlue { + static let color = Color(hexString: "3366FF") + static let opacity88 = Color(hexString: "3366FF", opacity: 0.88) + static let opacity48 = Color(hexString: "3366FF", opacity: 0.48) + static let opacity16 = Color(hexString: "3366FF", opacity: 0.16) + static let opacity08 = Color(hexString: "3366FF", opacity: 0.08) + } } diff --git a/HappyAnding/HappyAnding/Extensions/String/String+Date.swift b/HappyAnding/HappyAnding/Extensions/String/String+Date.swift index 71a96588..598bdc6c 100644 --- a/HappyAnding/HappyAnding/Extensions/String/String+Date.swift +++ b/HappyAnding/HappyAnding/Extensions/String/String+Date.swift @@ -34,4 +34,20 @@ extension String { return date } + + func getPostDateFormat() -> String? { + let inputFormatter = DateFormatter() + inputFormatter.dateFormat = "yyyyMMddHHmmss" + + if let date = inputFormatter.date(from: self) { + let outputFormatter = DateFormatter() + outputFormatter.locale = Locale(identifier: "ko_KR") + outputFormatter.dateFormat = "M월 d일 a h시 m분" + + let output = outputFormatter.string(from: date) + return output + } else { + return nil + } + } } diff --git a/HappyAnding/HappyAnding/Extensions/View/View+Navigation.swift b/HappyAnding/HappyAnding/Extensions/View/View+Navigation.swift index 27f50f03..89b23fba 100644 --- a/HappyAnding/HappyAnding/Extensions/View/View+Navigation.swift +++ b/HappyAnding/HappyAnding/Extensions/View/View+Navigation.swift @@ -87,8 +87,6 @@ extension View { ListCurationView(viewModel: ListCurationViewModel(data: data as! CurationType)) case is User: ShowProfileView(viewModel: ShowProfileViewModel(data: data as! User)) - case is NavigationSearch: - SearchView() case is Category: ListCategoryShortcutView(viewModel: ListCategoryShortcutViewModel(data: data as! Category)) case is NavigationNicknameView: @@ -141,9 +139,6 @@ struct NavigationViewModifier: ViewModifier { .navigationDestination(for: NavigationWithdrawal.self) { _ in WithdrawalView() } - .navigationDestination(for: NavigationSearch.self) { _ in - SearchView() - } .navigationDestination(for: NavigationSettingView.self) { _ in SettingView() } diff --git a/HappyAnding/HappyAnding/Model/SectionType.swift b/HappyAnding/HappyAnding/Model/SectionType.swift index 34e040b9..46cdb649 100644 --- a/HappyAnding/HappyAnding/Model/SectionType.swift +++ b/HappyAnding/HappyAnding/Model/SectionType.swift @@ -83,8 +83,8 @@ enum SectionType { case .popular: return Image(systemName: self.icon) .foregroundStyle( - Color(hexString: "3366FF", opacity: 0.88), - Color(hexString: "3366FF", opacity: 0.88) + SCZColor.SCZBlue.opacity88, + SCZColor.SCZBlue.opacity88 ) case .myShortcut: return Image(systemName: "square.text.square.fill") @@ -101,8 +101,8 @@ enum SectionType { case .myLovingShortcut: return Image(systemName: "heart.fill") .foregroundStyle( - Color(hexString: "3366FF", opacity: 0.88), - Color(hexString: "3366FF", opacity: 0.88) + SCZColor.SCZBlue.opacity88, + SCZColor.SCZBlue.opacity88 ) } } diff --git a/HappyAnding/HappyAnding/TextLiteral.swift b/HappyAnding/HappyAnding/TextLiteral.swift index 487884f1..fc358608 100644 --- a/HappyAnding/HappyAnding/TextLiteral.swift +++ b/HappyAnding/HappyAnding/TextLiteral.swift @@ -246,6 +246,18 @@ enum TextLiteral { static let searchViewRecommendedKeyword: String = "추천 검색어" static let searchViewProposal: String = "단축어 제안하기" static let searchViewProposalURL: String = "https://docs.google.com/forms/d/e/1FAIpQLScQc3KeYjDGCE-C2YRU-Hwy2XNy5bt89KVX1OMUzRiySaMX1Q/viewform" + static let searchViewMoreResult: String = "더 많은 검색 결과 보기" + static let searchViewRelatedShortcut: String = "관련된 단축어" + static let searchVIewRelatedPost: String = "관련된 글" + static func searchViewEmptyResult(_ searchText: String) -> String { + return "😵 \'\(searchText)\'에 관련된 단축어나 글이 없어요." + } + static func searchTextRelatedShortcutShare(_ searchText: String) -> String { + return "\'\(searchText)\' 관련 단축어 공유하기" + } + static func searchTextRelatedPost(_ searchText: String) -> String { + return "\'\(searchText)\' 관련 질문하기" + } //MARK: - CustomShareViewController static let customShareViewControllerSignInAlertTitle: String = "로그인을 먼저 진행해주세요" diff --git a/HappyAnding/HappyAnding/Views/Components/ExploreCell.swift b/HappyAnding/HappyAnding/Views/Components/ExploreCell.swift index 4d00396e..98faa9c3 100644 --- a/HappyAnding/HappyAnding/Views/Components/ExploreCell.swift +++ b/HappyAnding/HappyAnding/Views/Components/ExploreCell.swift @@ -45,7 +45,7 @@ struct OrderedCell: View { } .padding(12) .frame(width: 108, height: 144, alignment: .top) - .background( SCZColor.colors[shortcut.color]?.color(for: colorScheme).fillGradient() ?? SCZColor.defaultColor) + .background( SCZColor.colors[shortcut.color]?.color(for: colorScheme).fillGradient() ?? Color.clear.toGradient()) .cornerRadius(16) .roundedBorder(cornerRadius: 16, color: Color.white, isNormalBlend: true, opacity: 0.12) } @@ -66,7 +66,7 @@ struct UnorderedCell: View{ HStack { RoundedRectangle(cornerRadius: 1) .frame(width: 2, height: 30) - .foregroundStyle(SCZColor.colors[shortcut.color]?.color(for: colorScheme).fillGradient() ?? SCZColor.defaultColor) + .foregroundStyle(SCZColor.colors[shortcut.color]?.color(for: colorScheme).fillGradient() ?? Color.clear.toGradient()) Image(systemName: shortcut.sfSymbol) .foregroundStyle(SCZColor.CharcoalGray.opacity88) } diff --git a/HappyAnding/HappyAnding/Views/Components/ShortcutIcon.swift b/HappyAnding/HappyAnding/Views/Components/ShortcutIcon.swift index 3fbee17d..800d259f 100644 --- a/HappyAnding/HappyAnding/Views/Components/ShortcutIcon.swift +++ b/HappyAnding/HappyAnding/Views/Components/ShortcutIcon.swift @@ -17,7 +17,7 @@ struct ShortcutIcon: View { var body: some View { ZStack { RoundedRectangle(cornerRadius: 13) - .foregroundStyle(SCZColor.colors[color]?.color(for: colorScheme).fillGradient() ?? SCZColor.defaultColor) + .foregroundStyle(SCZColor.colors[color]?.color(for: colorScheme).fillGradient() ?? Color.clear.toGradient()) .roundedBorder(cornerRadius: 13, color: .white, isNormalBlend: true, opacity: 0.24) .frame(width: size, height: size) Image(systemName: sfSymbol) diff --git a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView.swift b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView.swift index c3bce693..df8cf0e9 100644 --- a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView.swift +++ b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView.swift @@ -17,6 +17,7 @@ struct ExploreShortcutView: View { ScrollView(.vertical, showsIndicators: false) { VStack(spacing: 12) { PromoteSection(items: viewModel.fetchAdminCuration()) + .padding(.top, 12) ForEach (sectionType, id: \.self) { type in CardSection(type: type, shortcuts: viewModel.fetchShortcuts(by: type)) } @@ -32,7 +33,6 @@ struct ExploreShortcutView: View { withAnimation { isSearchActivated.toggle() } - print("검색창") } label: { Image(systemName: "sparkle.magnifyingglass") .symbolRenderingMode(.palette) @@ -52,7 +52,7 @@ struct ExploreShortcutView: View { Image(systemName: "bell.badge.fill") .symbolRenderingMode(.palette) .foregroundStyle( - Color(hexString: "3366FF"), + SCZColor.SCZBlue.color, LinearGradient( colors: [SCZColor.CharcoalGray.opacity88, SCZColor.CharcoalGray.opacity48], startPoint: .top, diff --git a/HappyAnding/HappyAnding/Views/SearchView.swift b/HappyAnding/HappyAnding/Views/SearchView.swift index 406c0a73..fd2e50ec 100644 --- a/HappyAnding/HappyAnding/Views/SearchView.swift +++ b/HappyAnding/HappyAnding/Views/SearchView.swift @@ -12,22 +12,33 @@ import SwiftUI ///검색 방식 변경 필요할 수도..(현재는 기존 방식 유지) struct SearchView: View { @StateObject var viewModel: SearchViewModel -// @Binding var isSearchAcivated: Bool + @FocusState var searchBarFocused: Bool + @Binding var isSearchAcivated: Bool var body: some View { - VStack(spacing: 12) { - SearchBar(viewModel: self.viewModel) - if viewModel.searchText.isEmpty { - SearchSuggestionList(viewModel: self.viewModel) - } else if viewModel.shortcutResults.isEmpty && viewModel.postResults.isEmpty { - EmptyResultView(searchText: $viewModel.searchText) - } else { - SearchResultList(shortcuts: viewModel.shortcutResults, posts: viewModel.postResults) + VStack(spacing: 16) { + SearchBar(viewModel: self.viewModel, isSearchActivated: $isSearchAcivated, searchBarFocused: _searchBarFocused) + ScrollView { + if viewModel.searchText.isEmpty { + SearchSuggestionList(viewModel: self.viewModel, searchBarFocused: _searchBarFocused) + } else if viewModel.shortcutResults.isEmpty && viewModel.postResults.isEmpty { + EmptyResultView(searchText: $viewModel.searchText) + } else { + ResultSection(viewModel: self.viewModel) + } + } + .onTapGesture { + if searchBarFocused { + searchBarFocused = false + } else { + withAnimation { + isSearchAcivated = false + } + } } - Spacer() } .frame(maxWidth: .infinity, maxHeight: .infinity) - .background(SCZColor.CharcoalGray.opacity24.ignoresSafeArea()) + .background( SCZColor.CharcoalGray.opacity24.ignoresSafeArea() ) .onChange(of: viewModel.searchText) { _ in viewModel.didChangedSearchText() if !viewModel.searchText.isEmpty { @@ -37,10 +48,6 @@ struct SearchView: View { viewModel.isSearched = false } } - //빈 부분 터치 시 검색화면 벗어나기 -// .onTapGesture { -// isSearchAcivated.toggle() -// } } } @@ -48,7 +55,7 @@ struct EmptyResultView: View { @Binding var searchText: String var body: some View { VStack(alignment: .leading, spacing: 0) { - Text("😵 \'\(searchText)\'에 관련된 단축어나 글이 없어요.") + Text(TextLiteral.searchViewEmptyResult(searchText)) .foregroundStyle(SCZColor.CharcoalGray.opacity48) .padding(.horizontal, 16) .padding(.vertical, 8) @@ -58,7 +65,7 @@ struct EmptyResultView: View { print("단축어 작성 페이지 연결") } label: { HStack { - Text("\'\(searchText)\' 관련 단축어 공유하기") + Text(TextLiteral.searchTextRelatedShortcutShare(searchText)) .foregroundStyle(SCZColor.CharcoalGray.opacity64) Spacer() Image(systemName: "chevron.right") @@ -73,7 +80,7 @@ struct EmptyResultView: View { print("post 작성 페이지 연결") } label: { HStack { - Text("\'\(searchText)\' 관련 질문하기") + Text(TextLiteral.searchTextRelatedPost(searchText)) .foregroundStyle(SCZColor.CharcoalGray.opacity64) Spacer() Image(systemName: "chevron.right") @@ -94,129 +101,111 @@ struct EmptyResultView: View { .clipShape(RoundedRectangle(cornerRadius: 16)) .roundedBorder(cornerRadius: 16, color: Color.white, isNormalBlend: true, opacity: 0.12) .padding(.horizontal, 16) - } -} -enum ResultType { - case shortcut, post -} - -struct SearchResultList: View { - var shortcuts: [Shortcuts] - var posts: [[String]] - var body: some View { - ScrollView { - VStack(alignment: .leading, spacing: 16) { - if shortcuts.count > 0 { - ResultSection(type: .shortcut, title: "관련된 단축어", shortcuts: shortcuts) - } - if posts.count > 0 { - ResultSection(type: .post, title: "관련된 글", posts: posts) - } - } - .frame(maxWidth: .infinity, alignment: .leading) - .padding(.horizontal, 16) - } - .scrollDismissesKeyboard(.immediately) + .onTapGesture { } } } struct ResultSection: View { - let type: ResultType - let title: String - var shortcuts: [Shortcuts]? - var posts: [[String]]? + let maxNum = 2 + + @StateObject var viewModel: SearchViewModel + //TODO: Post 구조 추가 var body: some View { - VStack(alignment: .leading, spacing: 12) { - Text(title) - .font(.system(size: 14, weight: .medium)) - .foregroundStyle(SCZColor.CharcoalGray.opacity48) - .padding(.horizontal, 12) - - if let shortcuts { - VStack(alignment: .leading, spacing: 6) { - Rectangle()// 상단 여백을 주기 위함 - .frame(height: 0.1) - .foregroundStyle(Color.clear) - ForEach(Array(shortcuts.prefix(3).enumerated()), id: \.offset) { index, shortcut in - ResultShortcutCell(shortcut: shortcut) - - if index != shortcuts.count-1 || shortcuts.count > 3{ - Divider() - .padding(.vertical, 10) - .foregroundStyle(SCZColor.CharcoalGray.opacity08) - } + VStack(alignment: .leading, spacing: 16) { + if !viewModel.shortcutResults.isEmpty { + VStack (alignment: .leading, spacing: 8) { + if !viewModel.postResults.isEmpty { + Text(TextLiteral.searchViewRelatedShortcut) + .font(.system(size: 14, weight: .medium)) + .foregroundStyle(SCZColor.CharcoalGray.opacity48) + .padding(.horizontal, 12) } - - if shortcuts.count > 3 { - Button { - print("더많은 검색결과") - } label: { - HStack { - Text("더 많은 검색 결과 보기") - .font(.system(size: 14, weight: .medium)) - .foregroundStyle(SCZColor.CharcoalGray.opacity48) - Spacer() - Image(systemName: "chevron.right") - .foregroundStyle(SCZColor.CharcoalGray.opacity24) + VStack(alignment: .leading, spacing: 6) { + ForEach(Array(viewModel.shortcutResults.prefix(maxNum).enumerated()), id: \.offset) { index, shortcut in + ResultShortcutCell(shortcut: shortcut) + + if index != viewModel.shortcutResults.count-1 || viewModel.shortcutResults.count > maxNum { + Divider() + .padding(.vertical, 8) + .foregroundStyle(SCZColor.CharcoalGray.opacity08) + } + } + + if viewModel.shortcutResults.count > maxNum { + Button { + print("더많은 검색결과") + } label: { + HStack { + Text(TextLiteral.searchViewMoreResult) + .font(.system(size: 14, weight: .medium)) + .foregroundStyle(SCZColor.CharcoalGray.opacity48) + Spacer() + Image(systemName: "chevron.right") + .foregroundStyle(SCZColor.CharcoalGray.opacity24) + } + .padding(.horizontal, 16) } - .padding(.horizontal, 16) - .padding(.bottom, 6) } } + .padding(.vertical, 16) + .background( + ZStack { + Color.white.opacity(0.64) + SCZColor.CharcoalGray.opacity08 + } + ) + .roundedBorder(cornerRadius: 16, color: Color.white, isNormalBlend: true, opacity: 0.12) } - .padding(.vertical, 10) - .background( - ZStack { - Color.white.opacity(0.64) - SCZColor.CharcoalGray.opacity08 - } - ) - .roundedBorder(cornerRadius: 16, color: Color.white, isNormalBlend: true, opacity: 0.12) } - if let posts { - VStack(alignment: .leading, spacing: 6) { - Rectangle()// 상단 여백을 주기 위함 - .frame(height: 0.1) - .foregroundStyle(Color.clear) - ForEach(Array(posts.prefix(3).enumerated()), id: \.offset) { index, post in - ResultPostCell(post: post) - - if index != posts.count-1 || posts.count>3 { - Divider() - .padding(.vertical, 10) - .foregroundStyle(SCZColor.CharcoalGray.opacity08) - } + if !viewModel.postResults.isEmpty { + VStack (alignment: .leading, spacing: 8) { + if !viewModel.shortcutResults.isEmpty { + Text(TextLiteral.searchVIewRelatedPost) + .font(.system(size: 14, weight: .medium)) + .foregroundStyle(SCZColor.CharcoalGray.opacity48) + .padding(.horizontal, 12) } - - if posts.count > 3 { - Button { - print("더많은 검색결과") - } label: { - HStack { - Text("더 많은 검색 결과 보기") - .font(.system(size: 14, weight: .medium)) - .foregroundStyle(SCZColor.CharcoalGray.opacity48) - Spacer() - Image(systemName: "chevron.right") - .foregroundStyle(SCZColor.CharcoalGray.opacity24) + VStack(alignment: .leading, spacing: 6) { + ForEach(Array(viewModel.postResults.prefix(maxNum).enumerated()), id: \.offset) { index, post in + ResultPostCell(post: post) + if index != viewModel.postResults.count-1 || viewModel.postResults.count>maxNum { + Divider() + .padding(.vertical, 8) + .foregroundStyle(SCZColor.CharcoalGray.opacity08) + } + } + + if viewModel.postResults.count > maxNum { + Button { + print("더많은 검색결과") + } label: { + HStack { + Text(TextLiteral.searchViewMoreResult) + .font(.system(size: 14, weight: .medium)) + .foregroundStyle(SCZColor.CharcoalGray.opacity48) + Spacer() + Image(systemName: "chevron.right") + .foregroundStyle(SCZColor.CharcoalGray.opacity24) + } + .padding(.horizontal, 16) } - .padding(.horizontal, 16) - .padding(.bottom, 6) } } + .padding(.vertical, 16) + .background( + ZStack { + Color.white.opacity(0.64) + SCZColor.CharcoalGray.opacity08 + } + ) + .roundedBorder(cornerRadius: 16, color: Color.white, isNormalBlend: true, opacity: 0.12) } - .padding(.vertical, 10) - .background( - ZStack { - Color.white.opacity(0.64) - SCZColor.CharcoalGray.opacity08 - } - ) - .roundedBorder(cornerRadius: 16, color: Color.white, isNormalBlend: true, opacity: 0.12) } } + .padding(.horizontal, 16) + .onTapGesture { } } } @@ -234,10 +223,13 @@ struct ResultShortcutCell: View { //Pretendard bold 16 .font(.system(size: 16, weight: .bold)) .foregroundStyle(SCZColor.Basic) - Text(shortcut.subtitle) + .lineLimit(1) + Text(shortcut.subtitle.replacingOccurrences(of: "\\n", with: "\n")) //Pretendard medieum 14 .font(.system(size: 14, weight: .medium)) .foregroundStyle(SCZColor.CharcoalGray.opacity48) + .multilineTextAlignment(.leading) + .lineLimit(2) } Spacer() Image(systemName: "chevron.right") @@ -249,49 +241,62 @@ struct ResultShortcutCell: View { } struct ResultPostCell: View { - let post: [String] + let post: Post var body: some View { Button { print("post 상세페이지 연결") } label: { HStack { - Text(post[1]) //Pretendard medieum 14 - .font(.system(size: 14, weight: .medium)) - .foregroundStyle(SCZColor.CharcoalGray.opacity64) + VStack(alignment: .leading, spacing: 8) { + HStack(spacing: 8) { + Text(post.author) + .foregroundStyle(SCZColor.CharcoalGray.opacity64) + Text(post.createdAt.getPostDateFormat() ?? "") + .foregroundStyle(SCZColor.CharcoalGray.opacity48) + } + .lineLimit(1) + Text(post.content.replacingOccurrences(of: "\\n", with: "\n")) + .foregroundStyle(SCZColor.CharcoalGray.opacity64) + .multilineTextAlignment(.leading) + .lineLimit(2) + .frame(maxWidth: .infinity, alignment: .leading) + } + .font(.system(size: 14, weight: .medium)) Spacer() Image(systemName: "chevron.right") .foregroundStyle(SCZColor.CharcoalGray.opacity24) } + .frame(maxWidth: .infinity, alignment: .leading) .padding(.horizontal, 16) } } } -//TODO: 검색기록 추가 struct SearchSuggestionList: View { @StateObject var viewModel: SearchViewModel - + @FocusState var searchBarFocused: Bool var body: some View { VStack(alignment: .leading, spacing: 0) { - - if viewModel.searchHistory.isEmpty { //추천 검색어 ForEach(0.. 5 { + searchHistory.removeLast() + } UserDefaults.standard.set(searchHistory, forKey: "searchHistory") } diff --git a/HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift b/HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift index 9f034133..0498608e 100644 --- a/HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift +++ b/HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift @@ -109,14 +109,8 @@ struct ShortcutTabView: View { } if isSearchActivated { - Color.black.opacity(0.33) - .ignoresSafeArea() - .onTapGesture { - withAnimation { - isSearchActivated.toggle() - } - - } + SearchView(viewModel: SearchViewModel(), isSearchAcivated: $isSearchActivated) + .background(.ultraThickMaterial) } } } From d20781d69c8ac3827b1d2fe3fc56d5b6058dd524 Mon Sep 17 00:00:00 2001 From: jeonjimin Date: Sat, 13 Apr 2024 20:51:52 +0900 Subject: [PATCH 03/11] =?UTF-8?q?[Feat]=20#523=20-=20=EB=94=94=EC=9E=90?= =?UTF-8?q?=EC=9D=B8=20=EC=88=98=EC=A0=95=EC=82=AC=ED=95=AD=20=EB=B0=98?= =?UTF-8?q?=EC=98=81=20=EB=B0=8F=20=ED=85=8D=EC=8A=A4=ED=8A=B8=20=EB=A6=AC?= =?UTF-8?q?=ED=84=B0=EB=9F=B4=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 컬러 익스텐션 수정 및 반영 --- .../HappyAnding.xcodeproj/project.pbxproj | 25 +- .../HappyAnding/Extensions/SCZ+Color.swift | 13 +- .../Extensions/String/String+Date.swift | 16 + .../Extensions/View/View+Navigation.swift | 5 - .../HappyAnding/Model/SectionType.swift | 8 +- HappyAnding/HappyAnding/TextLiteral.swift | 12 + .../Views/Components/ExploreCell.swift | 4 +- .../Views/Components/ShortcutIcon.swift | 2 +- .../ExploreShortcutView.swift | 4 +- .../HappyAnding/Views/SearchView.swift | 370 +++++++++--------- .../HappyAnding/Views/SearchViewModel.swift | 73 +++- .../Views/TabView/ShortcutTabView.swift | 10 +- 12 files changed, 314 insertions(+), 228 deletions(-) diff --git a/HappyAnding/HappyAnding.xcodeproj/project.pbxproj b/HappyAnding/HappyAnding.xcodeproj/project.pbxproj index 72291601..ff274338 100644 --- a/HappyAnding/HappyAnding.xcodeproj/project.pbxproj +++ b/HappyAnding/HappyAnding.xcodeproj/project.pbxproj @@ -672,7 +672,6 @@ F91F09DC29AE012600E04FA0 /* ShortcutGrade.swift */, 872B5D3C2A2E0FF9008DCC57 /* CurationType.swift */, A323D3C92AEE870700DDA716 /* SuggestionForm.swift */, - F980171D2BBC2A24004F2EA7 /* ExploreShortcutSectionType.swift */, ); path = Model; sourceTree = ""; @@ -1296,7 +1295,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.happyanding.HappyAnding; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = ShortcutsZipProfile_Dev_20231113; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = ShortcutsZipProfile_Dev_20240317; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; @@ -1339,7 +1338,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.happyanding.HappyAnding; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = ShortcutsZipProfile_Dev_20231113; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = ShortcutsZipProfile_Dev_20240317; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; @@ -1354,14 +1353,16 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 7JPPWR5997; + DEVELOPMENT_TEAM = ""; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 16.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.happyanding.HappyAndingTests; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -1374,14 +1375,16 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 7JPPWR5997; + DEVELOPMENT_TEAM = ""; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 16.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.happyanding.HappyAndingTests; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -1393,13 +1396,15 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 7JPPWR5997; + DEVELOPMENT_TEAM = ""; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.happyanding.HappyAndingUITests; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -1411,13 +1416,15 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 7JPPWR5997; + DEVELOPMENT_TEAM = ""; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.happyanding.HappyAndingUITests; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -1448,7 +1455,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.happyanding.HappyAnding.ShareExtension; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = ShortcutsZipShareExtProfile_Dev_20231113; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = ShortcutsZipShareExtProfile_Dev_20240317; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -1480,7 +1487,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.happyanding.HappyAnding.ShareExtension; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = ShortcutsZipShareExtProfile_Dev_20231113; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = ShortcutsZipShareExtProfile_Dev_20240317; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; diff --git a/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift b/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift index 5ed1833b..dfe984b8 100644 --- a/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift +++ b/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift @@ -60,7 +60,6 @@ struct GradientType { } struct SCZColor { - static let defaultColor = Red().light.fillGradient() static let colors: [String: ColorProtocol] = [ "Red": Red(), "Coral": Coral(), @@ -71,6 +70,7 @@ struct SCZColor { "Teal": Teal(), "Cyan": Cyan(), "Blue": Blue(), + "Pink": Pink(), "Purple": Purple(), "LightPurple": Lavendar(), "Silver": Silver(), @@ -565,7 +565,7 @@ extension SCZColor { ) } struct CharcoalGray { - static let color: Color = Color(hexString: "404040") + static let color = Color(hexString: "404040") static let opacity88 = Color(hexString: "404040", opacity: 0.88) static let opacity64 = Color(hexString: "404040", opacity: 0.64) static let opacity48 = Color(hexString: "404040", opacity: 0.48) @@ -574,4 +574,13 @@ extension SCZColor { static let opacity08 = Color(hexString: "404040", opacity: 0.08) static let opacity04 = Color(hexString: "404040", opacity: 0.04) } + + ///SCZBlue 색상 사용 시 백그라운드에 white 색상 넣어줘야 의도한 색으로 나타납니다. + struct SCZBlue { + static let color = Color(hexString: "3366FF") + static let opacity88 = Color(hexString: "3366FF", opacity: 0.88) + static let opacity48 = Color(hexString: "3366FF", opacity: 0.48) + static let opacity16 = Color(hexString: "3366FF", opacity: 0.16) + static let opacity08 = Color(hexString: "3366FF", opacity: 0.08) + } } diff --git a/HappyAnding/HappyAnding/Extensions/String/String+Date.swift b/HappyAnding/HappyAnding/Extensions/String/String+Date.swift index 71a96588..598bdc6c 100644 --- a/HappyAnding/HappyAnding/Extensions/String/String+Date.swift +++ b/HappyAnding/HappyAnding/Extensions/String/String+Date.swift @@ -34,4 +34,20 @@ extension String { return date } + + func getPostDateFormat() -> String? { + let inputFormatter = DateFormatter() + inputFormatter.dateFormat = "yyyyMMddHHmmss" + + if let date = inputFormatter.date(from: self) { + let outputFormatter = DateFormatter() + outputFormatter.locale = Locale(identifier: "ko_KR") + outputFormatter.dateFormat = "M월 d일 a h시 m분" + + let output = outputFormatter.string(from: date) + return output + } else { + return nil + } + } } diff --git a/HappyAnding/HappyAnding/Extensions/View/View+Navigation.swift b/HappyAnding/HappyAnding/Extensions/View/View+Navigation.swift index 27f50f03..89b23fba 100644 --- a/HappyAnding/HappyAnding/Extensions/View/View+Navigation.swift +++ b/HappyAnding/HappyAnding/Extensions/View/View+Navigation.swift @@ -87,8 +87,6 @@ extension View { ListCurationView(viewModel: ListCurationViewModel(data: data as! CurationType)) case is User: ShowProfileView(viewModel: ShowProfileViewModel(data: data as! User)) - case is NavigationSearch: - SearchView() case is Category: ListCategoryShortcutView(viewModel: ListCategoryShortcutViewModel(data: data as! Category)) case is NavigationNicknameView: @@ -141,9 +139,6 @@ struct NavigationViewModifier: ViewModifier { .navigationDestination(for: NavigationWithdrawal.self) { _ in WithdrawalView() } - .navigationDestination(for: NavigationSearch.self) { _ in - SearchView() - } .navigationDestination(for: NavigationSettingView.self) { _ in SettingView() } diff --git a/HappyAnding/HappyAnding/Model/SectionType.swift b/HappyAnding/HappyAnding/Model/SectionType.swift index 34e040b9..46cdb649 100644 --- a/HappyAnding/HappyAnding/Model/SectionType.swift +++ b/HappyAnding/HappyAnding/Model/SectionType.swift @@ -83,8 +83,8 @@ enum SectionType { case .popular: return Image(systemName: self.icon) .foregroundStyle( - Color(hexString: "3366FF", opacity: 0.88), - Color(hexString: "3366FF", opacity: 0.88) + SCZColor.SCZBlue.opacity88, + SCZColor.SCZBlue.opacity88 ) case .myShortcut: return Image(systemName: "square.text.square.fill") @@ -101,8 +101,8 @@ enum SectionType { case .myLovingShortcut: return Image(systemName: "heart.fill") .foregroundStyle( - Color(hexString: "3366FF", opacity: 0.88), - Color(hexString: "3366FF", opacity: 0.88) + SCZColor.SCZBlue.opacity88, + SCZColor.SCZBlue.opacity88 ) } } diff --git a/HappyAnding/HappyAnding/TextLiteral.swift b/HappyAnding/HappyAnding/TextLiteral.swift index 487884f1..fc358608 100644 --- a/HappyAnding/HappyAnding/TextLiteral.swift +++ b/HappyAnding/HappyAnding/TextLiteral.swift @@ -246,6 +246,18 @@ enum TextLiteral { static let searchViewRecommendedKeyword: String = "추천 검색어" static let searchViewProposal: String = "단축어 제안하기" static let searchViewProposalURL: String = "https://docs.google.com/forms/d/e/1FAIpQLScQc3KeYjDGCE-C2YRU-Hwy2XNy5bt89KVX1OMUzRiySaMX1Q/viewform" + static let searchViewMoreResult: String = "더 많은 검색 결과 보기" + static let searchViewRelatedShortcut: String = "관련된 단축어" + static let searchVIewRelatedPost: String = "관련된 글" + static func searchViewEmptyResult(_ searchText: String) -> String { + return "😵 \'\(searchText)\'에 관련된 단축어나 글이 없어요." + } + static func searchTextRelatedShortcutShare(_ searchText: String) -> String { + return "\'\(searchText)\' 관련 단축어 공유하기" + } + static func searchTextRelatedPost(_ searchText: String) -> String { + return "\'\(searchText)\' 관련 질문하기" + } //MARK: - CustomShareViewController static let customShareViewControllerSignInAlertTitle: String = "로그인을 먼저 진행해주세요" diff --git a/HappyAnding/HappyAnding/Views/Components/ExploreCell.swift b/HappyAnding/HappyAnding/Views/Components/ExploreCell.swift index 4d00396e..98faa9c3 100644 --- a/HappyAnding/HappyAnding/Views/Components/ExploreCell.swift +++ b/HappyAnding/HappyAnding/Views/Components/ExploreCell.swift @@ -45,7 +45,7 @@ struct OrderedCell: View { } .padding(12) .frame(width: 108, height: 144, alignment: .top) - .background( SCZColor.colors[shortcut.color]?.color(for: colorScheme).fillGradient() ?? SCZColor.defaultColor) + .background( SCZColor.colors[shortcut.color]?.color(for: colorScheme).fillGradient() ?? Color.clear.toGradient()) .cornerRadius(16) .roundedBorder(cornerRadius: 16, color: Color.white, isNormalBlend: true, opacity: 0.12) } @@ -66,7 +66,7 @@ struct UnorderedCell: View{ HStack { RoundedRectangle(cornerRadius: 1) .frame(width: 2, height: 30) - .foregroundStyle(SCZColor.colors[shortcut.color]?.color(for: colorScheme).fillGradient() ?? SCZColor.defaultColor) + .foregroundStyle(SCZColor.colors[shortcut.color]?.color(for: colorScheme).fillGradient() ?? Color.clear.toGradient()) Image(systemName: shortcut.sfSymbol) .foregroundStyle(SCZColor.CharcoalGray.opacity88) } diff --git a/HappyAnding/HappyAnding/Views/Components/ShortcutIcon.swift b/HappyAnding/HappyAnding/Views/Components/ShortcutIcon.swift index 3fbee17d..800d259f 100644 --- a/HappyAnding/HappyAnding/Views/Components/ShortcutIcon.swift +++ b/HappyAnding/HappyAnding/Views/Components/ShortcutIcon.swift @@ -17,7 +17,7 @@ struct ShortcutIcon: View { var body: some View { ZStack { RoundedRectangle(cornerRadius: 13) - .foregroundStyle(SCZColor.colors[color]?.color(for: colorScheme).fillGradient() ?? SCZColor.defaultColor) + .foregroundStyle(SCZColor.colors[color]?.color(for: colorScheme).fillGradient() ?? Color.clear.toGradient()) .roundedBorder(cornerRadius: 13, color: .white, isNormalBlend: true, opacity: 0.24) .frame(width: size, height: size) Image(systemName: sfSymbol) diff --git a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView.swift b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView.swift index c3bce693..df8cf0e9 100644 --- a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView.swift +++ b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView.swift @@ -17,6 +17,7 @@ struct ExploreShortcutView: View { ScrollView(.vertical, showsIndicators: false) { VStack(spacing: 12) { PromoteSection(items: viewModel.fetchAdminCuration()) + .padding(.top, 12) ForEach (sectionType, id: \.self) { type in CardSection(type: type, shortcuts: viewModel.fetchShortcuts(by: type)) } @@ -32,7 +33,6 @@ struct ExploreShortcutView: View { withAnimation { isSearchActivated.toggle() } - print("검색창") } label: { Image(systemName: "sparkle.magnifyingglass") .symbolRenderingMode(.palette) @@ -52,7 +52,7 @@ struct ExploreShortcutView: View { Image(systemName: "bell.badge.fill") .symbolRenderingMode(.palette) .foregroundStyle( - Color(hexString: "3366FF"), + SCZColor.SCZBlue.color, LinearGradient( colors: [SCZColor.CharcoalGray.opacity88, SCZColor.CharcoalGray.opacity48], startPoint: .top, diff --git a/HappyAnding/HappyAnding/Views/SearchView.swift b/HappyAnding/HappyAnding/Views/SearchView.swift index 406c0a73..fd2e50ec 100644 --- a/HappyAnding/HappyAnding/Views/SearchView.swift +++ b/HappyAnding/HappyAnding/Views/SearchView.swift @@ -12,22 +12,33 @@ import SwiftUI ///검색 방식 변경 필요할 수도..(현재는 기존 방식 유지) struct SearchView: View { @StateObject var viewModel: SearchViewModel -// @Binding var isSearchAcivated: Bool + @FocusState var searchBarFocused: Bool + @Binding var isSearchAcivated: Bool var body: some View { - VStack(spacing: 12) { - SearchBar(viewModel: self.viewModel) - if viewModel.searchText.isEmpty { - SearchSuggestionList(viewModel: self.viewModel) - } else if viewModel.shortcutResults.isEmpty && viewModel.postResults.isEmpty { - EmptyResultView(searchText: $viewModel.searchText) - } else { - SearchResultList(shortcuts: viewModel.shortcutResults, posts: viewModel.postResults) + VStack(spacing: 16) { + SearchBar(viewModel: self.viewModel, isSearchActivated: $isSearchAcivated, searchBarFocused: _searchBarFocused) + ScrollView { + if viewModel.searchText.isEmpty { + SearchSuggestionList(viewModel: self.viewModel, searchBarFocused: _searchBarFocused) + } else if viewModel.shortcutResults.isEmpty && viewModel.postResults.isEmpty { + EmptyResultView(searchText: $viewModel.searchText) + } else { + ResultSection(viewModel: self.viewModel) + } + } + .onTapGesture { + if searchBarFocused { + searchBarFocused = false + } else { + withAnimation { + isSearchAcivated = false + } + } } - Spacer() } .frame(maxWidth: .infinity, maxHeight: .infinity) - .background(SCZColor.CharcoalGray.opacity24.ignoresSafeArea()) + .background( SCZColor.CharcoalGray.opacity24.ignoresSafeArea() ) .onChange(of: viewModel.searchText) { _ in viewModel.didChangedSearchText() if !viewModel.searchText.isEmpty { @@ -37,10 +48,6 @@ struct SearchView: View { viewModel.isSearched = false } } - //빈 부분 터치 시 검색화면 벗어나기 -// .onTapGesture { -// isSearchAcivated.toggle() -// } } } @@ -48,7 +55,7 @@ struct EmptyResultView: View { @Binding var searchText: String var body: some View { VStack(alignment: .leading, spacing: 0) { - Text("😵 \'\(searchText)\'에 관련된 단축어나 글이 없어요.") + Text(TextLiteral.searchViewEmptyResult(searchText)) .foregroundStyle(SCZColor.CharcoalGray.opacity48) .padding(.horizontal, 16) .padding(.vertical, 8) @@ -58,7 +65,7 @@ struct EmptyResultView: View { print("단축어 작성 페이지 연결") } label: { HStack { - Text("\'\(searchText)\' 관련 단축어 공유하기") + Text(TextLiteral.searchTextRelatedShortcutShare(searchText)) .foregroundStyle(SCZColor.CharcoalGray.opacity64) Spacer() Image(systemName: "chevron.right") @@ -73,7 +80,7 @@ struct EmptyResultView: View { print("post 작성 페이지 연결") } label: { HStack { - Text("\'\(searchText)\' 관련 질문하기") + Text(TextLiteral.searchTextRelatedPost(searchText)) .foregroundStyle(SCZColor.CharcoalGray.opacity64) Spacer() Image(systemName: "chevron.right") @@ -94,129 +101,111 @@ struct EmptyResultView: View { .clipShape(RoundedRectangle(cornerRadius: 16)) .roundedBorder(cornerRadius: 16, color: Color.white, isNormalBlend: true, opacity: 0.12) .padding(.horizontal, 16) - } -} -enum ResultType { - case shortcut, post -} - -struct SearchResultList: View { - var shortcuts: [Shortcuts] - var posts: [[String]] - var body: some View { - ScrollView { - VStack(alignment: .leading, spacing: 16) { - if shortcuts.count > 0 { - ResultSection(type: .shortcut, title: "관련된 단축어", shortcuts: shortcuts) - } - if posts.count > 0 { - ResultSection(type: .post, title: "관련된 글", posts: posts) - } - } - .frame(maxWidth: .infinity, alignment: .leading) - .padding(.horizontal, 16) - } - .scrollDismissesKeyboard(.immediately) + .onTapGesture { } } } struct ResultSection: View { - let type: ResultType - let title: String - var shortcuts: [Shortcuts]? - var posts: [[String]]? + let maxNum = 2 + + @StateObject var viewModel: SearchViewModel + //TODO: Post 구조 추가 var body: some View { - VStack(alignment: .leading, spacing: 12) { - Text(title) - .font(.system(size: 14, weight: .medium)) - .foregroundStyle(SCZColor.CharcoalGray.opacity48) - .padding(.horizontal, 12) - - if let shortcuts { - VStack(alignment: .leading, spacing: 6) { - Rectangle()// 상단 여백을 주기 위함 - .frame(height: 0.1) - .foregroundStyle(Color.clear) - ForEach(Array(shortcuts.prefix(3).enumerated()), id: \.offset) { index, shortcut in - ResultShortcutCell(shortcut: shortcut) - - if index != shortcuts.count-1 || shortcuts.count > 3{ - Divider() - .padding(.vertical, 10) - .foregroundStyle(SCZColor.CharcoalGray.opacity08) - } + VStack(alignment: .leading, spacing: 16) { + if !viewModel.shortcutResults.isEmpty { + VStack (alignment: .leading, spacing: 8) { + if !viewModel.postResults.isEmpty { + Text(TextLiteral.searchViewRelatedShortcut) + .font(.system(size: 14, weight: .medium)) + .foregroundStyle(SCZColor.CharcoalGray.opacity48) + .padding(.horizontal, 12) } - - if shortcuts.count > 3 { - Button { - print("더많은 검색결과") - } label: { - HStack { - Text("더 많은 검색 결과 보기") - .font(.system(size: 14, weight: .medium)) - .foregroundStyle(SCZColor.CharcoalGray.opacity48) - Spacer() - Image(systemName: "chevron.right") - .foregroundStyle(SCZColor.CharcoalGray.opacity24) + VStack(alignment: .leading, spacing: 6) { + ForEach(Array(viewModel.shortcutResults.prefix(maxNum).enumerated()), id: \.offset) { index, shortcut in + ResultShortcutCell(shortcut: shortcut) + + if index != viewModel.shortcutResults.count-1 || viewModel.shortcutResults.count > maxNum { + Divider() + .padding(.vertical, 8) + .foregroundStyle(SCZColor.CharcoalGray.opacity08) + } + } + + if viewModel.shortcutResults.count > maxNum { + Button { + print("더많은 검색결과") + } label: { + HStack { + Text(TextLiteral.searchViewMoreResult) + .font(.system(size: 14, weight: .medium)) + .foregroundStyle(SCZColor.CharcoalGray.opacity48) + Spacer() + Image(systemName: "chevron.right") + .foregroundStyle(SCZColor.CharcoalGray.opacity24) + } + .padding(.horizontal, 16) } - .padding(.horizontal, 16) - .padding(.bottom, 6) } } + .padding(.vertical, 16) + .background( + ZStack { + Color.white.opacity(0.64) + SCZColor.CharcoalGray.opacity08 + } + ) + .roundedBorder(cornerRadius: 16, color: Color.white, isNormalBlend: true, opacity: 0.12) } - .padding(.vertical, 10) - .background( - ZStack { - Color.white.opacity(0.64) - SCZColor.CharcoalGray.opacity08 - } - ) - .roundedBorder(cornerRadius: 16, color: Color.white, isNormalBlend: true, opacity: 0.12) } - if let posts { - VStack(alignment: .leading, spacing: 6) { - Rectangle()// 상단 여백을 주기 위함 - .frame(height: 0.1) - .foregroundStyle(Color.clear) - ForEach(Array(posts.prefix(3).enumerated()), id: \.offset) { index, post in - ResultPostCell(post: post) - - if index != posts.count-1 || posts.count>3 { - Divider() - .padding(.vertical, 10) - .foregroundStyle(SCZColor.CharcoalGray.opacity08) - } + if !viewModel.postResults.isEmpty { + VStack (alignment: .leading, spacing: 8) { + if !viewModel.shortcutResults.isEmpty { + Text(TextLiteral.searchVIewRelatedPost) + .font(.system(size: 14, weight: .medium)) + .foregroundStyle(SCZColor.CharcoalGray.opacity48) + .padding(.horizontal, 12) } - - if posts.count > 3 { - Button { - print("더많은 검색결과") - } label: { - HStack { - Text("더 많은 검색 결과 보기") - .font(.system(size: 14, weight: .medium)) - .foregroundStyle(SCZColor.CharcoalGray.opacity48) - Spacer() - Image(systemName: "chevron.right") - .foregroundStyle(SCZColor.CharcoalGray.opacity24) + VStack(alignment: .leading, spacing: 6) { + ForEach(Array(viewModel.postResults.prefix(maxNum).enumerated()), id: \.offset) { index, post in + ResultPostCell(post: post) + if index != viewModel.postResults.count-1 || viewModel.postResults.count>maxNum { + Divider() + .padding(.vertical, 8) + .foregroundStyle(SCZColor.CharcoalGray.opacity08) + } + } + + if viewModel.postResults.count > maxNum { + Button { + print("더많은 검색결과") + } label: { + HStack { + Text(TextLiteral.searchViewMoreResult) + .font(.system(size: 14, weight: .medium)) + .foregroundStyle(SCZColor.CharcoalGray.opacity48) + Spacer() + Image(systemName: "chevron.right") + .foregroundStyle(SCZColor.CharcoalGray.opacity24) + } + .padding(.horizontal, 16) } - .padding(.horizontal, 16) - .padding(.bottom, 6) } } + .padding(.vertical, 16) + .background( + ZStack { + Color.white.opacity(0.64) + SCZColor.CharcoalGray.opacity08 + } + ) + .roundedBorder(cornerRadius: 16, color: Color.white, isNormalBlend: true, opacity: 0.12) } - .padding(.vertical, 10) - .background( - ZStack { - Color.white.opacity(0.64) - SCZColor.CharcoalGray.opacity08 - } - ) - .roundedBorder(cornerRadius: 16, color: Color.white, isNormalBlend: true, opacity: 0.12) } } + .padding(.horizontal, 16) + .onTapGesture { } } } @@ -234,10 +223,13 @@ struct ResultShortcutCell: View { //Pretendard bold 16 .font(.system(size: 16, weight: .bold)) .foregroundStyle(SCZColor.Basic) - Text(shortcut.subtitle) + .lineLimit(1) + Text(shortcut.subtitle.replacingOccurrences(of: "\\n", with: "\n")) //Pretendard medieum 14 .font(.system(size: 14, weight: .medium)) .foregroundStyle(SCZColor.CharcoalGray.opacity48) + .multilineTextAlignment(.leading) + .lineLimit(2) } Spacer() Image(systemName: "chevron.right") @@ -249,49 +241,62 @@ struct ResultShortcutCell: View { } struct ResultPostCell: View { - let post: [String] + let post: Post var body: some View { Button { print("post 상세페이지 연결") } label: { HStack { - Text(post[1]) //Pretendard medieum 14 - .font(.system(size: 14, weight: .medium)) - .foregroundStyle(SCZColor.CharcoalGray.opacity64) + VStack(alignment: .leading, spacing: 8) { + HStack(spacing: 8) { + Text(post.author) + .foregroundStyle(SCZColor.CharcoalGray.opacity64) + Text(post.createdAt.getPostDateFormat() ?? "") + .foregroundStyle(SCZColor.CharcoalGray.opacity48) + } + .lineLimit(1) + Text(post.content.replacingOccurrences(of: "\\n", with: "\n")) + .foregroundStyle(SCZColor.CharcoalGray.opacity64) + .multilineTextAlignment(.leading) + .lineLimit(2) + .frame(maxWidth: .infinity, alignment: .leading) + } + .font(.system(size: 14, weight: .medium)) Spacer() Image(systemName: "chevron.right") .foregroundStyle(SCZColor.CharcoalGray.opacity24) } + .frame(maxWidth: .infinity, alignment: .leading) .padding(.horizontal, 16) } } } -//TODO: 검색기록 추가 struct SearchSuggestionList: View { @StateObject var viewModel: SearchViewModel - + @FocusState var searchBarFocused: Bool var body: some View { VStack(alignment: .leading, spacing: 0) { - - if viewModel.searchHistory.isEmpty { //추천 검색어 ForEach(0.. 5 { + searchHistory.removeLast() + } UserDefaults.standard.set(searchHistory, forKey: "searchHistory") } diff --git a/HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift b/HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift index 9f034133..0498608e 100644 --- a/HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift +++ b/HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift @@ -109,14 +109,8 @@ struct ShortcutTabView: View { } if isSearchActivated { - Color.black.opacity(0.33) - .ignoresSafeArea() - .onTapGesture { - withAnimation { - isSearchActivated.toggle() - } - - } + SearchView(viewModel: SearchViewModel(), isSearchAcivated: $isSearchActivated) + .background(.ultraThickMaterial) } } } From 823cbd06a2a98301a32e3307a745b87872a7e291 Mon Sep 17 00:00:00 2001 From: jeonjimin Date: Sat, 13 Apr 2024 22:20:00 +0900 Subject: [PATCH 04/11] =?UTF-8?q?[Comment]=20-=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HappyAnding/HappyAnding/Views/SearchView.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/HappyAnding/HappyAnding/Views/SearchView.swift b/HappyAnding/HappyAnding/Views/SearchView.swift index fd2e50ec..87b2fdcf 100644 --- a/HappyAnding/HappyAnding/Views/SearchView.swift +++ b/HappyAnding/HappyAnding/Views/SearchView.swift @@ -8,8 +8,6 @@ import MessageUI import SwiftUI -//TODO: 머지 전 화면 연결 필요 -///검색 방식 변경 필요할 수도..(현재는 기존 방식 유지) struct SearchView: View { @StateObject var viewModel: SearchViewModel @FocusState var searchBarFocused: Bool From fb471b60d28e5cb99687d675b35fc5ca8fa12d57 Mon Sep 17 00:00:00 2001 From: jeonjimin Date: Mon, 15 Apr 2024 21:19:37 +0900 Subject: [PATCH 05/11] =?UTF-8?q?[Feat]=20#523=20-=20SCZBlue=20=EC=83=89?= =?UTF-8?q?=EC=83=81=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HappyAnding/HappyAnding/Extensions/SCZ+Color.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift b/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift index dfe984b8..d33ca17c 100644 --- a/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift +++ b/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift @@ -578,9 +578,9 @@ extension SCZColor { ///SCZBlue 색상 사용 시 백그라운드에 white 색상 넣어줘야 의도한 색으로 나타납니다. struct SCZBlue { static let color = Color(hexString: "3366FF") - static let opacity88 = Color(hexString: "3366FF", opacity: 0.88) - static let opacity48 = Color(hexString: "3366FF", opacity: 0.48) - static let opacity16 = Color(hexString: "3366FF", opacity: 0.16) - static let opacity08 = Color(hexString: "3366FF", opacity: 0.08) + static let opacity88 = Color(hexString: "4B78FF", opacity: 0.88) + static let opacity48 = Color(hexString: "9DB6FF", opacity: 0.48) + static let opacity16 = Color(hexString: "DEE7FF", opacity: 0.16) + static let opacity08 = Color(hexString: "EFF3FF", opacity: 0.08) } } From e6a1033514ab90b74be4d27e4ad29591bd99fb4c Mon Sep 17 00:00:00 2001 From: jeonjimin Date: Mon, 15 Apr 2024 21:20:43 +0900 Subject: [PATCH 06/11] =?UTF-8?q?[Comment]=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HappyAnding/HappyAnding/Extensions/SCZ+Color.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift b/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift index d33ca17c..9eefbf0b 100644 --- a/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift +++ b/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift @@ -575,7 +575,6 @@ extension SCZColor { static let opacity04 = Color(hexString: "404040", opacity: 0.04) } - ///SCZBlue 색상 사용 시 백그라운드에 white 색상 넣어줘야 의도한 색으로 나타납니다. struct SCZBlue { static let color = Color(hexString: "3366FF") static let opacity88 = Color(hexString: "4B78FF", opacity: 0.88) From a70f8d8e40c323ebea201b578dcc89dba23cf349 Mon Sep 17 00:00:00 2001 From: Jeon Jimin <41153398+JMM00@users.noreply.github.com> Date: Mon, 15 Apr 2024 21:22:50 +0900 Subject: [PATCH 07/11] Update HappyAnding/HappyAnding/Extensions/SCZ+Color.swift Co-authored-by: teemo <60784937+teethemoji@users.noreply.github.com> --- HappyAnding/HappyAnding/Extensions/SCZ+Color.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift b/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift index 9eefbf0b..c141d30c 100644 --- a/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift +++ b/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift @@ -576,7 +576,7 @@ extension SCZColor { } struct SCZBlue { - static let color = Color(hexString: "3366FF") + static let strong = Color(hexString: "3366FF") static let opacity88 = Color(hexString: "4B78FF", opacity: 0.88) static let opacity48 = Color(hexString: "9DB6FF", opacity: 0.48) static let opacity16 = Color(hexString: "DEE7FF", opacity: 0.16) From 1d520c8aec2c4a9899b674899faa49f7f532928a Mon Sep 17 00:00:00 2001 From: jeonjimin Date: Mon, 15 Apr 2024 21:24:20 +0900 Subject: [PATCH 08/11] =?UTF-8?q?[Feat]=20#523=20-=20SCZBlue=20=EC=83=89?= =?UTF-8?q?=EC=83=81=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HappyAnding/HappyAnding/Extensions/SCZ+Color.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift b/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift index c141d30c..7ba67af5 100644 --- a/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift +++ b/HappyAnding/HappyAnding/Extensions/SCZ+Color.swift @@ -577,9 +577,9 @@ extension SCZColor { struct SCZBlue { static let strong = Color(hexString: "3366FF") - static let opacity88 = Color(hexString: "4B78FF", opacity: 0.88) - static let opacity48 = Color(hexString: "9DB6FF", opacity: 0.48) - static let opacity16 = Color(hexString: "DEE7FF", opacity: 0.16) - static let opacity08 = Color(hexString: "EFF3FF", opacity: 0.08) + static let opacity88 = Color(hexString: "4B78FF") + static let opacity48 = Color(hexString: "9DB6FF") + static let opacity16 = Color(hexString: "DEE7FF") + static let opacity08 = Color(hexString: "EFF3FF") } } From 5135d350750bd4d0170d635ea2a0f59b4e110e0b Mon Sep 17 00:00:00 2001 From: jeonjimin Date: Mon, 15 Apr 2024 21:33:37 +0900 Subject: [PATCH 09/11] =?UTF-8?q?[Style]=20=EB=B0=94=EB=80=90=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=EB=AA=85=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Views/ExploreShortcutViews/ExploreShortcutView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView.swift b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView.swift index df8cf0e9..4dccb0e5 100644 --- a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView.swift +++ b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView.swift @@ -52,7 +52,7 @@ struct ExploreShortcutView: View { Image(systemName: "bell.badge.fill") .symbolRenderingMode(.palette) .foregroundStyle( - SCZColor.SCZBlue.color, + SCZColor.SCZBlue.strong, LinearGradient( colors: [SCZColor.CharcoalGray.opacity88, SCZColor.CharcoalGray.opacity48], startPoint: .top, From 839edc1d2f3849553d0810e2367945db3a3a927e Mon Sep 17 00:00:00 2001 From: jeonjimin Date: Wed, 17 Apr 2024 15:00:55 +0900 Subject: [PATCH 10/11] =?UTF-8?q?[Feat]=20#523=20-=20=EB=94=94=EC=9E=90?= =?UTF-8?q?=EC=9D=B8=20=ED=94=BC=EB=93=9C=EB=B0=B1=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - divider 상하 여백 변경 - 터치 영역 반영 --- .../HappyAnding/Views/SearchView.swift | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/HappyAnding/HappyAnding/Views/SearchView.swift b/HappyAnding/HappyAnding/Views/SearchView.swift index 87b2fdcf..5473a421 100644 --- a/HappyAnding/HappyAnding/Views/SearchView.swift +++ b/HappyAnding/HappyAnding/Views/SearchView.swift @@ -301,38 +301,38 @@ struct SearchSuggestionList: View { if index != viewModel.keywords.keyword.count-1 { Divider() - .padding(.vertical, 10) + .padding(.vertical, 8) .foregroundStyle(SCZColor.CharcoalGray.opacity08) } } } else { //검색 기록 ForEach(0.. Date: Sat, 20 Apr 2024 16:48:24 +0900 Subject: [PATCH 11/11] =?UTF-8?q?[Feat]=20#523=20-=20SearchView=20?= =?UTF-8?q?=EC=82=AC=EB=9D=BC=EC=A7=88=20=EB=95=8C=20=EC=95=A0=EB=8B=88?= =?UTF-8?q?=EB=A9=94=EC=9D=B4=EC=85=98=20=EC=A0=81=EC=9A=A9=20-=20zIndex?= =?UTF-8?q?=20=EB=AA=85=EC=8B=9C=EC=A0=81=EC=9C=BC=EB=A1=9C=20=EC=A7=80?= =?UTF-8?q?=EC=A0=95=ED=95=98=EC=97=AC=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift b/HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift index 0498608e..182f49fb 100644 --- a/HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift +++ b/HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift @@ -97,6 +97,7 @@ struct ShortcutTabView: View { } .tag(3) } + .zIndex(1) .onChange(of: phase) { newPhase in switch newPhase { case .background: isShortcutDeeplink = false; isCurationDeeplink = false @@ -111,6 +112,7 @@ struct ShortcutTabView: View { if isSearchActivated { SearchView(viewModel: SearchViewModel(), isSearchAcivated: $isSearchActivated) .background(.ultraThickMaterial) + .zIndex(2) } } }