From 70369df56053af8699c5856e93d28496e2a4f47b Mon Sep 17 00:00:00 2001 From: opficdev Date: Wed, 4 Mar 2026 23:41:16 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EB=AC=B8=EA=B5=AC=EA=B0=80=20?= =?UTF-8?q?=EB=B3=B4=EC=9D=BC=20=EB=95=8C=EB=8A=94=20=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=EB=A1=A4=EC=9D=84=20=EC=9E=A0=EA=B5=AC=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DevLog/Resource/Localizable.xcstrings | 3 +++ DevLog/UI/Home/TodoListView.swift | 25 ++++++++++++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/DevLog/Resource/Localizable.xcstrings b/DevLog/Resource/Localizable.xcstrings index 252bb80d..89a502fe 100644 --- a/DevLog/Resource/Localizable.xcstrings +++ b/DevLog/Resource/Localizable.xcstrings @@ -6,6 +6,9 @@ }, "%@ 검색" : { + }, + "%@의 제목이나 내용을 검색해 보세요." : { + }, "%lld" : { diff --git a/DevLog/UI/Home/TodoListView.swift b/DevLog/UI/Home/TodoListView.swift index 152e82b1..b097c928 100644 --- a/DevLog/UI/Home/TodoListView.swift +++ b/DevLog/UI/Home/TodoListView.swift @@ -23,10 +23,10 @@ struct TodoListView: View { } } else { Group { - if viewModel.state.searchText.isEmpty { - todoListContent - } else { + if viewModel.state.isSearching { searchResultsContent + } else { + todoListContent } } .searchable( @@ -34,6 +34,10 @@ struct TodoListView: View { get: { viewModel.state.searchText }, set: { viewModel.send(.setSearchText($0)) } ), + isPresented: Binding( + get: { viewModel.state.isSearching }, + set: { viewModel.send(.setIsSearching($0)) } + ), placement: .navigationBarDrawer(displayMode: .always), prompt: "\(viewModel.state.kind.localizedName) 검색" ) @@ -162,9 +166,8 @@ struct TodoListView: View { .listRowBackground(Color.clear) } .listStyle(.plain) - .refreshable { - viewModel.send(.refresh) - } + .refreshable { viewModel.send(.refresh) } + .scrollDisabled(viewModel.state.todos.isEmpty || viewModel.state.isLoading) if viewModel.state.isLoading { LoadingView() @@ -198,14 +201,17 @@ struct TodoListView: View { return ScrollView { LazyVStack(spacing: 0) { - if viewModel.state.isLoading { + if viewModel.state.searchText.isEmpty { + Text("\(viewModel.state.kind.localizedName)의 제목이나 내용을 검색해 보세요.") + .foregroundStyle(Color.gray) + .frame(maxWidth: .infinity) + } else if viewModel.state.isLoading { LoadingView() .padding(.top, 40) } else if searchResults.isEmpty { Text("검색 결과가 없습니다.") .foregroundStyle(Color.gray) - .frame(maxWidth: .infinity) - .padding(.top, 40) + .frame(maxWidth: .infinity, maxHeight: .infinity) } else { ForEach(displayedTodos) { todo in Button { @@ -231,6 +237,7 @@ struct TodoListView: View { } } } + .scrollDisabled(viewModel.state.searchText.isEmpty || viewModel.state.isLoading || searchResults.isEmpty) } private var headerView: some View { From 4770f08bdcb9fccd487bacb8487ebff82c437ee7 Mon Sep 17 00:00:00 2001 From: opficdev Date: Thu, 5 Mar 2026 00:06:36 +0900 Subject: [PATCH 2/2] =?UTF-8?q?ui:=20=EA=B5=AC=EC=A1=B0=EB=A5=BC=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=ED=95=98=EC=97=AC=20=EA=B2=80=EC=83=89=20?= =?UTF-8?q?=EA=B2=B0=EA=B3=BC=EB=A7=8C=EC=9D=84=20=EB=B3=B4=EC=97=AC?= =?UTF-8?q?=EC=A4=84=20=EB=95=8C=EB=A7=8C=20=EC=8A=A4=ED=81=AC=EB=A1=A4?= =?UTF-8?q?=EC=9D=B4=20=EA=B0=80=EB=8A=A5=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DevLog/UI/Home/TodoListView.swift | 31 ++++++++++++++++--------------- DevLog/UI/Search/SearchView.swift | 26 ++++++++++++++------------ 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/DevLog/UI/Home/TodoListView.swift b/DevLog/UI/Home/TodoListView.swift index b097c928..56f73a80 100644 --- a/DevLog/UI/Home/TodoListView.swift +++ b/DevLog/UI/Home/TodoListView.swift @@ -192,6 +192,7 @@ struct TodoListView: View { ) } + @ViewBuilder private var searchResultsContent: some View { let searchResults = viewModel.state.searchResults let limit = viewModel.searchResultsLimit @@ -199,20 +200,21 @@ struct TodoListView: View { ? searchResults : Array(searchResults.prefix(limit)) - return ScrollView { - LazyVStack(spacing: 0) { - if viewModel.state.searchText.isEmpty { - Text("\(viewModel.state.kind.localizedName)의 제목이나 내용을 검색해 보세요.") - .foregroundStyle(Color.gray) - .frame(maxWidth: .infinity) - } else if viewModel.state.isLoading { - LoadingView() - .padding(.top, 40) - } else if searchResults.isEmpty { - Text("검색 결과가 없습니다.") - .foregroundStyle(Color.gray) - .frame(maxWidth: .infinity, maxHeight: .infinity) - } else { + if viewModel.state.searchText.isEmpty { + Text("\(viewModel.state.kind.localizedName)의 제목이나 내용을 검색해 보세요.") + .foregroundStyle(Color.gray) + .frame(maxWidth: .infinity) + } else if viewModel.state.isLoading { + LoadingView() + } else if searchResults.isEmpty { + Spacer() + Text("검색 결과가 없습니다.") + .foregroundStyle(Color.gray) + .frame(maxWidth: .infinity) + Spacer() + } else { + ScrollView { + LazyVStack(spacing: 0) { ForEach(displayedTodos) { todo in Button { router.push(Path.detail(todo.id)) @@ -237,7 +239,6 @@ struct TodoListView: View { } } } - .scrollDisabled(viewModel.state.searchText.isEmpty || viewModel.state.isLoading || searchResults.isEmpty) } private var headerView: some View { diff --git a/DevLog/UI/Search/SearchView.swift b/DevLog/UI/Search/SearchView.swift index 9e23a2ba..9710eff7 100644 --- a/DevLog/UI/Search/SearchView.swift +++ b/DevLog/UI/Search/SearchView.swift @@ -59,23 +59,25 @@ struct SearchView: View { @ViewBuilder private var searchableContent: some View { - ScrollView { - LazyVStack(alignment: .leading, spacing: 0) { - if viewModel.state.isLoading { - LoadingView() - } else if viewModel.state.searchQuery.isEmpty { - if viewModel.state.recentQueries.isEmpty { - searchInstruction - } else { + Group { + if viewModel.state.isLoading { + LoadingView() + } else if viewModel.state.searchQuery.isEmpty { + if viewModel.state.recentQueries.isEmpty { + searchInstruction + } else { + ScrollView { recentQueries } - } else if viewModel.state.webPages.isEmpty && viewModel.state.todos.isEmpty { - emptySearchResult - } else { + } + } else if viewModel.state.webPages.isEmpty && viewModel.state.todos.isEmpty { + emptySearchResult + } else { + ScrollView { searchResults + .frame(maxWidth: .infinity, alignment: .leading) } } - .frame(maxWidth: .infinity, alignment: .leading) } .searchable( text: Binding(