From 4a00617b66d753d483808ad7e476e9a2ae0c2baa Mon Sep 17 00:00:00 2001 From: 0Hooni Date: Sun, 27 Apr 2025 16:50:28 +0900 Subject: [PATCH 01/19] =?UTF-8?q?style/#126:=20View=20=EC=BB=A8=EB=B2=A4?= =?UTF-8?q?=EC=85=98=20=EC=A0=81=EC=9A=A9=20=EB=B0=8F=20=EC=A0=91=EA=B7=BC?= =?UTF-8?q?=EC=A0=9C=EC=96=B4=EC=9E=90=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BeforeSearch/SearchController.swift | 33 ++++- .../Search/BeforeSearch/View/SearchView.swift | 17 ++- .../Search/Main/SearchMainController.swift | 53 +++----- .../Scene/Search/Main/SearchMainView.swift | 125 +++++++++--------- 4 files changed, 116 insertions(+), 112 deletions(-) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift index 9cac2f2b..1c380b2e 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift @@ -30,7 +30,10 @@ final class SearchController: BaseViewController, View { extension SearchController { override func viewDidLoad() { super.viewDidLoad() - setUp() + + self.addViews() + self.setupContstraints() + self.configureUI() } override func viewWillAppear(_ animated: Bool) { @@ -41,36 +44,50 @@ extension SearchController { // MARK: - SetUp private extension SearchController { - func setUp() { + func addViews() { + [mainView].forEach { + self.view.addSubview($0) + } + } + + func setupContstraints() { + mainView.snp.makeConstraints { make in + make.edges.equalTo(view.safeAreaLayoutGuide) + } + } + + func configureUI() { if let layout = reactor?.compositionalLayout { mainView.contentCollectionView.collectionViewLayout = layout } + mainView.contentCollectionView.delegate = self mainView.contentCollectionView.dataSource = self + mainView.contentCollectionView.register( SearchTitleSectionCell.self, forCellWithReuseIdentifier: SearchTitleSectionCell.identifiers ) + mainView.contentCollectionView.register( SpacingSectionCell.self, forCellWithReuseIdentifier: SpacingSectionCell.identifiers ) + mainView.contentCollectionView.register( CancelableTagSectionCell.self, forCellWithReuseIdentifier: CancelableTagSectionCell.identifiers ) + mainView.contentCollectionView.register( SearchCountTitleSectionCell.self, forCellWithReuseIdentifier: SearchCountTitleSectionCell.identifiers ) + mainView.contentCollectionView.register( HomeCardSectionCell.self, forCellWithReuseIdentifier: HomeCardSectionCell.identifiers ) - view.addSubview(mainView) - mainView.snp.makeConstraints { make in - make.edges.equalTo(view.safeAreaLayoutGuide) - } } } @@ -122,8 +139,9 @@ extension SearchController: UICollectionViewDelegate, UICollectionViewDataSource ) -> UICollectionViewCell { let cell = sections[indexPath.section].getCell(collectionView: collectionView, indexPath: indexPath) guard let userDefaultService = reactor?.userDefaultService else { return cell } - var searchList = userDefaultService.fetchArray(key: "searchList") ?? [] + let searchList = userDefaultService.fetchArray(key: "searchList") ?? [] guard let reactor = reactor else { return cell } + if let cell = cell as? SearchTitleSectionCell { cell.titleButton.rx.tap .map { Reactor.Action.recentSearchListAllDeleteButtonTapped } @@ -168,6 +186,7 @@ extension SearchController: UICollectionViewDelegate, UICollectionViewDataSource .bind(to: reactor.action) .disposed(by: cell.disposeBag) } + return cell } diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/View/SearchView.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/View/SearchView.swift index 874e3b1a..8ffc6413 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/View/SearchView.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/View/SearchView.swift @@ -12,26 +12,31 @@ import SnapKit final class SearchView: UIView { // MARK: - Components - let contentCollectionView: UICollectionView = { - return UICollectionView(frame: .zero, collectionViewLayout: .init()) - }() + let contentCollectionView = UICollectionView(frame: .zero, collectionViewLayout: .init()) // MARK: - init init() { super.init(frame: .zero) - setUpConstraints() + + self.addSubviews() + self.setUpConstraints() } required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") + fatalError("\(#file), \(#function) Error") } } // MARK: - SetUp private extension SearchView { + func addSubviews() { + [contentCollectionView].forEach { + self.addSubview($0) + } + } + func setUpConstraints() { - self.addSubview(contentCollectionView) contentCollectionView.snp.makeConstraints { make in make.top.equalToSuperview().offset(56) make.leading.trailing.bottom.equalToSuperview() diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/Main/SearchMainController.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/Main/SearchMainController.swift index 7eb6542e..0808019d 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/Main/SearchMainController.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/Main/SearchMainController.swift @@ -9,6 +9,7 @@ import RxCocoa import RxSwift import SnapKit import Tabman +import Then final class SearchMainController: BaseTabmanController, View { @@ -19,23 +20,19 @@ final class SearchMainController: BaseTabmanController, View { private var mainView = SearchMainView() - var beforeController: SearchController = { - let controller = SearchController() - controller.reactor = SearchReactor( + var beforeController = SearchController().then { + $0.reactor = SearchReactor( userAPIUseCase: DIContainer.resolve(UserAPIUseCase.self), popUpAPIUseCase: DIContainer.resolve(PopUpAPIUseCase.self) ) - return controller - }() + } - var afterController: SearchResultController = { - let controller = SearchResultController() - controller.reactor = SearchResultReactor( + var afterController = SearchResultController().then { + $0.reactor = SearchResultReactor( userAPIUseCase: DIContainer.resolve(UserAPIUseCase.self), popUpAPIUseCase: DIContainer.resolve(PopUpAPIUseCase.self) ) - return controller - }() + } lazy var controllers = [ beforeController, @@ -49,7 +46,9 @@ final class SearchMainController: BaseTabmanController, View { extension SearchMainController { override func viewDidLoad() { super.viewDidLoad() - setUp() + + self.addViews() + self.setupContstraints() } override func viewDidAppear(_ animated: Bool) { @@ -68,14 +67,19 @@ extension SearchMainController { // MARK: - SetUp private extension SearchMainController { - func setUp() { - view.addSubview(mainView) + func addViews() { + [mainView] + .forEach { self.view.addSubview($0) } + } + + func setupContstraints() { + self.dataSource = self + self.isScrollEnabled = false + mainView.snp.makeConstraints { make in make.top.leading.trailing.equalTo(view.safeAreaLayoutGuide) make.height.equalTo(56) } - self.dataSource = self - self.isScrollEnabled = false } } @@ -98,25 +102,6 @@ extension SearchMainController { }) .disposed(by: disposeBag) -// mainView.searchTextField.rx.controlEvent(.editingDidEndOnExit) -// .withUnretained(self) -// .map { (owner, _) in -// Reactor.Action.returnSearchKeyWord(text: owner.mainView.searchTextField.text ) -// } -// .bind(to: reactor.action) -// .disposed(by: disposeBag) -// -// mainView.searchTextField.rx.controlEvent(.editingDidEndOnExit) -// .withUnretained(self) -// .subscribe(onNext: { (owner, _) in -// if let text = owner.mainView.searchTextField.text { -// if !text.isEmpty { -// owner.scrollToPage(.at(index: 1), animated: false) -// } -// } -// owner.beforeController.reactor?.action.onNext(.returnSearchKeyword(text: owner.mainView.searchTextField.text)) -// }) -// .disposed(by: disposeBag) mainView.searchTextField.rx.controlEvent(.editingDidEndOnExit) .withLatestFrom(mainView.searchTextField.rx.text.orEmpty) .withUnretained(self) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/Main/SearchMainView.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/Main/SearchMainView.swift index 3d3ffda9..8798ec65 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/Main/SearchMainView.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/Main/SearchMainView.swift @@ -1,101 +1,96 @@ -// -// SearchMainView.swift -// Poppool -// -// Created by SeoJunYoung on 12/7/24. -// - import UIKit import SnapKit +import Then final class SearchMainView: UIView { // MARK: - Components - private let searchTrailingView: UIView = { - let view = UIView() - view.backgroundColor = .g50 - view.layer.cornerRadius = 4 - view.clipsToBounds = true - return view - }() - - private let searchIconImageView: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "icon_search_gray") - return view - }() - - private let searchStackView: UIStackView = { - let view = UIStackView() - view.spacing = 4 - view.alignment = .center - return view - }() - - let cancelButton: UIButton = { - let button = UIButton(type: .system) - button.setTitle("취소", for: .normal) - button.setTitleColor(.g1000, for: .normal) - button.titleLabel?.font = .korFont(style: .regular, size: 14) - button.imageView?.contentMode = .scaleAspectFit - return button - }() - - let searchTextField: UITextField = { - let view = UITextField() - view.font = .korFont(style: .regular, size: 14) - view.setPlaceholder(text: "팝업스토어명을 입력해보세요", color: .g400, font: .korFont(style: .regular, size: 14)!) - return view - }() - - let clearButton: UIButton = { - let button = UIButton() - button.setImage(UIImage(named: "icon_clearButton"), for: .normal) - return button - }() - - private var headerStackView: UIStackView = { - let view = UIStackView() - view.alignment = .center - view.spacing = 16 - return view - }() + private let searchTrailingView = UIView().then { + $0.backgroundColor = .g50 + $0.layer.cornerRadius = 4 + $0.clipsToBounds = true + } + + private let searchIconImageView = UIImageView().then { + $0.image = UIImage(named: "icon_search_gray") + } + + private let searchStackView = UIStackView().then { + $0.spacing = 4 + $0.alignment = .center + } + + let cancelButton = UIButton(type: .system).then { + $0.setTitle("취소", for: .normal) + $0.setTitleColor(.g1000, for: .normal) + $0.titleLabel?.font = .korFont(style: .regular, size: 14) + $0.imageView?.contentMode = .scaleAspectFit + } + + let searchTextField = UITextField().then { + $0.font = .korFont(style: .regular, size: 14) + $0.setPlaceholder( + text: "팝업스토어명을 입력해보세요", + color: .g400, + font: .korFont(style: .regular, size: 14)! + ) + } + + let clearButton = UIButton().then { + $0.setImage(UIImage(named: "icon_clearButton"), for: .normal) + } + + private var headerStackView = UIStackView().then { + $0.alignment = .center + $0.spacing = 16 + } // MARK: - init init() { super.init(frame: .zero) - setUpConstraints() + + self.addViews() + self.setUpConstraints() } required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") + fatalError("\(#file), \(#function) Error") } } // MARK: - SetUp private extension SearchMainView { + func addViews() { + [headerStackView] + .forEach { self.addSubview($0) } + + [searchTrailingView, cancelButton] + .forEach { headerStackView.addArrangedSubview($0) } + + [searchStackView] + .forEach { searchTrailingView.addSubview($0) } + + [searchIconImageView, searchTextField, clearButton] + .forEach { searchStackView.addArrangedSubview($0) } + } + func setUpConstraints() { searchTrailingView.snp.makeConstraints { make in make.height.equalTo(37) } - headerStackView.addArrangedSubview(searchTrailingView) - headerStackView.addArrangedSubview(cancelButton) - self.addSubview(headerStackView) + headerStackView.snp.makeConstraints { make in make.top.equalToSuperview().inset(7) make.leading.equalToSuperview().inset(20) make.trailing.equalToSuperview().inset(16) } - searchTrailingView.addSubview(searchStackView) + searchStackView.snp.makeConstraints { make in make.top.bottom.equalToSuperview() make.leading.trailing.equalToSuperview().inset(12) } - searchStackView.addArrangedSubview(searchIconImageView) - searchStackView.addArrangedSubview(searchTextField) - searchStackView.addArrangedSubview(clearButton) searchIconImageView.snp.makeConstraints { make in make.size.equalTo(20) From 2d75d3b7b521f413ea9a91da11a22bc613cb7c76 Mon Sep 17 00:00:00 2001 From: 0Hooni Date: Tue, 29 Apr 2025 21:22:45 +0900 Subject: [PATCH 02/19] =?UTF-8?q?refactor/#126:=20=EB=AA=A9=EC=A0=81?= =?UTF-8?q?=EC=9D=B4=20=EC=9E=98=20=EB=93=A4=EC=96=B4=EB=82=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B3=80=EC=88=98=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Scene/Search/BeforeSearch/SearchController.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift index 1c380b2e..8a635377 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift @@ -23,7 +23,7 @@ final class SearchController: BaseViewController, View { private var mainView = SearchView() private var sections: [any Sectionable] = [] private let cellTapped: PublishSubject = .init() - private let pageChange: PublishSubject = .init() + private let loadNextPage = PublishSubject() } // MARK: - Life Cycle @@ -107,7 +107,7 @@ extension SearchController { .bind(to: reactor.action) .disposed(by: disposeBag) - pageChange + loadNextPage .throttle(.milliseconds(1000), scheduler: MainScheduler.asyncInstance) .map { Reactor.Action.changePage } .bind(to: reactor.action) @@ -196,7 +196,7 @@ extension SearchController: UICollectionViewDelegate, UICollectionViewDataSource let scrollViewHeight = scrollView.frame.size.height let contentOffsetY = scrollView.contentOffset.y if contentOffsetY + scrollViewHeight >= contentHeight { - pageChange.onNext(()) + loadNextPage.onNext(()) } } From b593626a6bc73f6200eed4bd75fbcf7b24ccf156 Mon Sep 17 00:00:00 2001 From: 0Hooni Date: Tue, 29 Apr 2025 21:37:10 +0900 Subject: [PATCH 03/19] =?UTF-8?q?fix/#126:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EB=A7=88=EC=A7=80=EB=A7=89=20=EC=9D=B4=EB=B2=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80=20=EB=B0=A9=EC=B6=9C=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - throttle의 마지막 이벤트 방출을 추가로 해주는 latest의 기본값이 true임 - 다음 페이지를 호출하는 이벤트를 시작과 끝에 두번 호출이 되게 하면 페이지 요청이 중복적으로 들어가는 문제와 설계에 따라서는 다음 페이지까지도 불러올 수 있기에 latest 옵션을 false로 변경 --- .../Scene/Search/BeforeSearch/SearchController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift index 8a635377..e8b206a6 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift @@ -108,7 +108,7 @@ extension SearchController { .disposed(by: disposeBag) loadNextPage - .throttle(.milliseconds(1000), scheduler: MainScheduler.asyncInstance) + .throttle(.seconds(1), latest: false, scheduler: MainScheduler.asyncInstance) .map { Reactor.Action.changePage } .bind(to: reactor.action) .disposed(by: disposeBag) From 1c72dd3a16e95239dcb3ce07fa7bfa4301cd1870 Mon Sep 17 00:00:00 2001 From: 0Hooni Date: Tue, 29 Apr 2025 21:50:30 +0900 Subject: [PATCH 04/19] =?UTF-8?q?refactor/#126:=20Action=EC=9D=98=20?= =?UTF-8?q?=EB=84=A4=EC=9D=B4=EB=B0=8D=EC=9D=84=20Subject=EC=9D=98=20?= =?UTF-8?q?=EC=9D=98=EB=8F=84=EC=99=80=20=ED=86=B5=EC=9D=BC=EC=8B=9C?= =?UTF-8?q?=ED=82=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Scene/Search/BeforeSearch/SearchController.swift | 2 +- .../Scene/Search/BeforeSearch/SearchReactor.swift | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift index e8b206a6..7e486a9b 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift @@ -109,7 +109,7 @@ extension SearchController { loadNextPage .throttle(.seconds(1), latest: false, scheduler: MainScheduler.asyncInstance) - .map { Reactor.Action.changePage } + .map { Reactor.Action.loadNextPage } .bind(to: reactor.action) .disposed(by: disposeBag) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift index 17cd6119..9685e9c0 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift @@ -21,7 +21,7 @@ final class SearchReactor: Reactor { case changeCategory(categoryList: [Int64], categoryTitleList: [String?]) case categoryDelteButtonTapped(indexPath: IndexPath) case resetCategory - case changePage + case loadNextPage case bookmarkButtonTapped(indexPath: IndexPath) case resetSearchKeyWord } @@ -102,7 +102,8 @@ final class SearchReactor: Reactor { switch action { case .resetSearchKeyWord: return Observable.just(.resetSearchKeyWord) - case .changePage: + case .loadNextPage: + if isLoading { return Observable.just(.loadView) } else { From 7d82d2a902ea68af336c1b0cdf8454f4bafd949a Mon Sep 17 00:00:00 2001 From: 0Hooni Date: Tue, 29 Apr 2025 22:27:59 +0900 Subject: [PATCH 05/19] =?UTF-8?q?fix/#126:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20View=20=EA=B0=B1=EC=8B=A0=EC=9D=84=20=EB=A7=89?= =?UTF-8?q?=EA=B3=A0=20=EB=A1=9C=EC=A7=81=EC=9D=84=20=EB=8B=A8=EC=88=9C?= =?UTF-8?q?=ED=99=94=EC=8B=9C=ED=82=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 불필요한 상황에서 모두 loadView를 mutate하고 있었음 - 아마 if state가 아닌 상황들에서 return이 없다보니 complete가 아닌 영향을 크게 주지 않는 loadView를 호출할게 아닌가 싶음. --- .../Search/BeforeSearch/SearchReactor.swift | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift index 9685e9c0..742d7c17 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift @@ -103,18 +103,10 @@ final class SearchReactor: Reactor { case .resetSearchKeyWord: return Observable.just(.resetSearchKeyWord) case .loadNextPage: - - if isLoading { - return Observable.just(.loadView) - } else { - if currentPage < lastPage { - isLoading = true - currentPage += 1 - return setBottomSearchList(sort: sort) - } else { - return Observable.just(.loadView) - } - } + guard !isLoading, currentPage < lastPage else { return Observable.empty() } + isLoading = true + currentPage += 1 + return setBottomSearchList(sort: sort) case .viewWillAppear: setSearchList() return setBottomSearchList(sort: sort) From 5996f6e55a08f68553c5c7469f336b12d7142f14 Mon Sep 17 00:00:00 2001 From: 0Hooni Date: Tue, 29 Apr 2025 23:43:39 +0900 Subject: [PATCH 06/19] =?UTF-8?q?refactor/#126:=20=EA=B0=80=EB=8F=85?= =?UTF-8?q?=EC=84=B1=20=EA=B0=9C=EC=84=A0=20=EB=B0=8F=20=EB=B3=80=EC=88=98?= =?UTF-8?q?=EB=AA=85=20=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Search/BeforeSearch/SearchReactor.swift | 73 ++++++++++--------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift index 742d7c17..064472b5 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift @@ -300,14 +300,37 @@ final class SearchReactor: Reactor { func setBottomSearchList(sort: String?) -> Observable { let isOpen = filterIndex == 0 ? true : false - let categorys = searchCategorySection.inputDataList.compactMap { $0.id } - return popUpAPIUseCase.getSearchBottomPopUpList(isOpen: isOpen, categories: categorys, page: currentPage, size: 50, sort: sort) - .withUnretained(self) - .map { (owner, response) in - let isLogin = response.loginYn - if owner.currentPage == 0 { - owner.searchListSection.inputDataList = response.popUpStoreList.map { - return .init( + let categories = searchCategorySection.inputDataList.compactMap { $0.id } + + return popUpAPIUseCase.getSearchBottomPopUpList( + isOpen: isOpen, + categories: categories, + page: currentPage, + size: 50, + sort: sort + ) + .withUnretained(self) + .map { (owner, response) in + let isLogin = response.loginYn + if owner.currentPage == 0 { + owner.searchListSection.inputDataList = response.popUpStoreList.map { + return .init( + imagePath: $0.mainImageUrl, + id: $0.id, + category: $0.category, + title: $0.name, + address: $0.address, + startDate: $0.startDate, + endDate: $0.endDate, + isBookmark: $0.bookmarkYn, + isLogin: isLogin + ) + } + } else { + if owner.currentPage != owner.lastAppendPage { + owner.lastAppendPage = owner.currentPage + let newData = response.popUpStoreList.map { + return HomeCardSectionCell.Input( imagePath: $0.mainImageUrl, id: $0.id, category: $0.category, @@ -319,32 +342,16 @@ final class SearchReactor: Reactor { isLogin: isLogin ) } - } else { - if owner.currentPage != owner.lastAppendPage { - owner.lastAppendPage = owner.currentPage - let newData = response.popUpStoreList.map { - return HomeCardSectionCell.Input( - imagePath: $0.mainImageUrl, - id: $0.id, - category: $0.category, - title: $0.name, - address: $0.address, - startDate: $0.startDate, - endDate: $0.endDate, - isBookmark: $0.bookmarkYn, - isLogin: isLogin - ) - } - owner.searchListSection.inputDataList.append(contentsOf: newData) - } + owner.searchListSection.inputDataList.append(contentsOf: newData) } - let isOpenString = isOpen ? "오픈・" : "종료・" - let sortedString = owner.sortedIndex == 0 ? "신규순" : "인기순" - let sortedTitle = isOpenString + sortedString - owner.searchSortedSection.inputDataList = [.init(count: response.totalElements, sortedTitle: sortedTitle)] - owner.lastPage = response.totalPages - owner.isLoading = false - return .loadView } + let isOpenString = isOpen ? "오픈・" : "종료・" + let sortedString = owner.sortedIndex == 0 ? "신규순" : "인기순" + let sortedTitle = isOpenString + sortedString + owner.searchSortedSection.inputDataList = [.init(count: response.totalElements, sortedTitle: sortedTitle)] + owner.lastPage = response.totalPages + owner.isLoading = false + return .loadView + } } } From b85b113fb72247428bde5180f3f5c4255e36ab44 Mon Sep 17 00:00:00 2001 From: 0Hooni Date: Tue, 29 Apr 2025 23:57:58 +0900 Subject: [PATCH 07/19] =?UTF-8?q?fix/#126:=20=ED=95=9C=EB=B2=88=EC=9D=98?= =?UTF-8?q?=20=EB=A1=9C=EB=94=A9=EC=97=90=20=EB=84=88=EB=AC=B4=20=EB=A7=8E?= =?UTF-8?q?=EC=9D=80=20=EC=95=84=EC=9D=B4=ED=85=9C=EC=9D=84=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=ED=95=98=EB=8A=94=20=EB=B6=80=EB=B6=84=EC=9D=84=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 50개나 요청할 필요가 없다 생각했음 - 한번에 보이는 팝업의 수량이 그리 많지 않았음 - 이미 충분히 카테고리와 정렬로 최상단의 정보의 중요도가 더 높다 판단했음 - 고로 그 아래 50개씩이나 불러올 이유는 없다고 보였음 --- .../Presentation/Scene/Search/BeforeSearch/SearchReactor.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift index 064472b5..3966075a 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift @@ -306,7 +306,7 @@ final class SearchReactor: Reactor { isOpen: isOpen, categories: categories, page: currentPage, - size: 50, + size: 10, sort: sort ) .withUnretained(self) From 6d0b611c5093c71473f4027e7f537fe99f62ca26 Mon Sep 17 00:00:00 2001 From: 0Hooni Date: Wed, 30 Apr 2025 00:00:19 +0900 Subject: [PATCH 08/19] =?UTF-8?q?refactor/#126:=20=EB=B0=98=ED=99=98?= =?UTF-8?q?=EB=90=98=EB=8A=94=20=ED=83=80=EC=9E=85=EC=9D=84=20=EB=AA=85?= =?UTF-8?q?=EC=8B=9C=ED=95=B4=EC=A4=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 단순히 .init으로 설정해주면 return이 뭘로 되어있는지 확인을 해줘야되는 번거로움이 있음 --- .../Presentation/Scene/Search/BeforeSearch/SearchReactor.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift index 3966075a..f878376e 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift @@ -314,7 +314,7 @@ final class SearchReactor: Reactor { let isLogin = response.loginYn if owner.currentPage == 0 { owner.searchListSection.inputDataList = response.popUpStoreList.map { - return .init( + return HomeCardSectionCell.Input( imagePath: $0.mainImageUrl, id: $0.id, category: $0.category, From 6497a30b6cbca74ac7a16ada1c931ca743da726b Mon Sep 17 00:00:00 2001 From: 0Hooni Date: Wed, 30 Apr 2025 00:38:58 +0900 Subject: [PATCH 09/19] =?UTF-8?q?refactor/#126:=20=EC=83=88=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=ED=85=9C=EC=9D=84=20=EC=A4=91=EB=B3=B5=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=83=9D=EC=84=B1=ED=95=B4=EC=A3=BC=EB=8A=94=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=EB=A5=BC=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 한번 생성자로 만들어준 아이템은 저장하도록 함 - 이후 조건에 따라 아이템으로 밀어줄건지 추가해줄건지만 정함 --- .../Search/BeforeSearch/SearchReactor.swift | 51 ++++++++----------- 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift index f878376e..c3a1369b 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift @@ -312,43 +312,32 @@ final class SearchReactor: Reactor { .withUnretained(self) .map { (owner, response) in let isLogin = response.loginYn + let newItems = response.popUpStoreList.map { + HomeCardSectionCell.Input( + imagePath: $0.mainImageUrl, + id: $0.id, + category: $0.category, + title: $0.name, + address: $0.address, + startDate: $0.startDate, + endDate: $0.endDate, + isBookmark: $0.bookmarkYn, + isLogin: isLogin + ) + } + if owner.currentPage == 0 { - owner.searchListSection.inputDataList = response.popUpStoreList.map { - return HomeCardSectionCell.Input( - imagePath: $0.mainImageUrl, - id: $0.id, - category: $0.category, - title: $0.name, - address: $0.address, - startDate: $0.startDate, - endDate: $0.endDate, - isBookmark: $0.bookmarkYn, - isLogin: isLogin - ) - } - } else { - if owner.currentPage != owner.lastAppendPage { - owner.lastAppendPage = owner.currentPage - let newData = response.popUpStoreList.map { - return HomeCardSectionCell.Input( - imagePath: $0.mainImageUrl, - id: $0.id, - category: $0.category, - title: $0.name, - address: $0.address, - startDate: $0.startDate, - endDate: $0.endDate, - isBookmark: $0.bookmarkYn, - isLogin: isLogin - ) - } - owner.searchListSection.inputDataList.append(contentsOf: newData) - } + owner.searchListSection.inputDataList = newItems + } else if owner.currentPage != owner.lastAppendPage { + owner.lastAppendPage = owner.currentPage + owner.searchListSection.inputDataList.append(contentsOf: newItems) } + let isOpenString = isOpen ? "오픈・" : "종료・" let sortedString = owner.sortedIndex == 0 ? "신규순" : "인기순" let sortedTitle = isOpenString + sortedString owner.searchSortedSection.inputDataList = [.init(count: response.totalElements, sortedTitle: sortedTitle)] + owner.lastPage = response.totalPages owner.isLoading = false return .loadView From d4c7a81de8d4516d405bb7dcddfea309f390b9a4 Mon Sep 17 00:00:00 2001 From: 0Hooni Date: Wed, 30 Apr 2025 00:46:18 +0900 Subject: [PATCH 10/19] =?UTF-8?q?refactor/#126:=20=EC=83=88=EB=A1=9C=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EB=90=98=EB=8A=94=20Cell.Input=EC=9E=84?= =?UTF-8?q?=EC=9D=84=20=EB=AA=85=EC=8B=9C=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Scene/Search/BeforeSearch/SearchReactor.swift | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift index c3a1369b..b11fa24f 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift @@ -325,7 +325,7 @@ final class SearchReactor: Reactor { isLogin: isLogin ) } - + if owner.currentPage == 0 { owner.searchListSection.inputDataList = newItems } else if owner.currentPage != owner.lastAppendPage { @@ -336,7 +336,13 @@ final class SearchReactor: Reactor { let isOpenString = isOpen ? "오픈・" : "종료・" let sortedString = owner.sortedIndex == 0 ? "신규순" : "인기순" let sortedTitle = isOpenString + sortedString - owner.searchSortedSection.inputDataList = [.init(count: response.totalElements, sortedTitle: sortedTitle)] + + owner.searchSortedSection.inputDataList = [ + SearchCountTitleSectionCell.Input( + count: response.totalElements, + sortedTitle: sortedTitle + ) + ] owner.lastPage = response.totalPages owner.isLoading = false From 0b57cd528fb3bb811cbd4eaca2c167f0d2e6b670 Mon Sep 17 00:00:00 2001 From: 0Hooni Date: Thu, 1 May 2025 15:48:50 +0900 Subject: [PATCH 11/19] =?UTF-8?q?refactor/#126:=20=EC=B2=AB=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=EC=9D=B8=20=EA=B2=BD=EC=9A=B0=EC=97=90?= =?UTF-8?q?=EB=A7=8C=20filterTitle=EC=9D=B4=20=EC=84=A4=EC=A0=95=EB=90=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Search/BeforeSearch/SearchReactor.swift | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift index b11fa24f..4c2cf1b7 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift @@ -299,7 +299,7 @@ final class SearchReactor: Reactor { } func setBottomSearchList(sort: String?) -> Observable { - let isOpen = filterIndex == 0 ? true : false + let isOpen = filterIndex == 0 let categories = searchCategorySection.inputDataList.compactMap { $0.id } return popUpAPIUseCase.getSearchBottomPopUpList( @@ -327,22 +327,24 @@ final class SearchReactor: Reactor { } if owner.currentPage == 0 { + // 첫 페이지는 전체 reload + // SearchCountTitleSection 설정 + let isOpenString = isOpen ? "오픈・" : "종료・" + let sortedString = owner.sortedIndex == 0 ? "신규순" : "인기순" + let sortedTitle = isOpenString + sortedString + owner.searchSortedSection.inputDataList = [ + SearchCountTitleSectionCell.Input( + count: response.totalElements, + sortedTitle: sortedTitle + ) + ] owner.searchListSection.inputDataList = newItems } else if owner.currentPage != owner.lastAppendPage { owner.lastAppendPage = owner.currentPage owner.searchListSection.inputDataList.append(contentsOf: newItems) } - let isOpenString = isOpen ? "오픈・" : "종료・" - let sortedString = owner.sortedIndex == 0 ? "신규순" : "인기순" - let sortedTitle = isOpenString + sortedString - owner.searchSortedSection.inputDataList = [ - SearchCountTitleSectionCell.Input( - count: response.totalElements, - sortedTitle: sortedTitle - ) - ] owner.lastPage = response.totalPages owner.isLoading = false From 00f5342c2f8976f027cf3a6ea0ad8d96240a2cb8 Mon Sep 17 00:00:00 2001 From: 0Hooni Date: Thu, 1 May 2025 15:51:32 +0900 Subject: [PATCH 12/19] =?UTF-8?q?fix/#126:=20=EC=B2=AB=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=EA=B0=80=20=EC=95=84=EB=8B=90=EB=95=8C?= =?UTF-8?q?=EB=8A=94=20reload=EA=B0=80=20=EC=95=84=EB=8B=8C=20update?= =?UTF-8?q?=EB=A1=9C=20=EB=8F=99=EC=9E=91=EB=90=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Search/BeforeSearch/SearchReactor.swift | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift index 4c2cf1b7..c3fbf0a8 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift @@ -339,16 +339,25 @@ final class SearchReactor: Reactor { ) ] owner.searchListSection.inputDataList = newItems - } else if owner.currentPage != owner.lastAppendPage { + owner.lastAppendPage = owner.currentPage + owner.lastPage = response.totalPages + owner.isLoading = false + return .loadView + } else { + // 다음 페이지는 append 후 부분 업데이트 owner.lastAppendPage = owner.currentPage owner.searchListSection.inputDataList.append(contentsOf: newItems) - } + owner.lastPage = response.totalPages + owner.isLoading = false + // HomeCardGridSection이 컬렉션뷰에서 몇 번째 섹션인지 계산 + let sectionIndex = owner.getSection().enumerated() + .first { _, section in section is HomeCardGridSection }!.offset - - owner.lastPage = response.totalPages - owner.isLoading = false - return .loadView + // append된 첫 아이템의 IndexPath + let firstIndexPath = IndexPath(item: previousCount, section: sectionIndex) + return .updateBottomSearchList(newItems: newItems, IndexPath: firstIndexPath) + } } } } From 7ccb36d81afdd8d66b4ce02076a4b0a8a01333d7 Mon Sep 17 00:00:00 2001 From: 0Hooni Date: Thu, 1 May 2025 16:01:54 +0900 Subject: [PATCH 13/19] =?UTF-8?q?feat/#126:=20=EC=83=88=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=ED=85=9C=EB=A7=8C=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8=20=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D?= =?UTF-8?q?=20=EB=B3=84=EB=8F=84=EC=9D=98=20mutate=EC=99=80=20action=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Scene/Search/BeforeSearch/SearchReactor.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift index c3fbf0a8..1b8d0b76 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift @@ -33,11 +33,15 @@ final class SearchReactor: Reactor { case moveToDetailScene(controller: BaseViewController, indexPath: IndexPath) case setSearchKeyWord(text: String?) case resetSearchKeyWord + case updateBottomSearchList(newItems: [HomeCardSectionCell.Input], IndexPath: IndexPath) } struct State { var sections: [any Sectionable] = [] var searchKeyWord: String? + var newBottomSearchList: [HomeCardSectionCell.Input] = [] + var bottomSearchListLastIndexPath: IndexPath? + } // MARK: - properties From a53ff06fcf8bfc74ec463a0a7862c9362d62b2f3 Mon Sep 17 00:00:00 2001 From: 0Hooni Date: Thu, 1 May 2025 16:03:07 +0900 Subject: [PATCH 14/19] =?UTF-8?q?feat/#126:=20=EB=B7=B0=EA=B0=80=20?= =?UTF-8?q?=EB=8B=A4=EC=8B=9C=20=EA=B7=B8=EB=A0=A4=EC=A7=88=EB=95=8C?= =?UTF-8?q?=EB=8A=94=20=EA=B4=80=EB=A6=AC=ED=95=98=EB=8D=98=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=EB=84=A4=EC=9D=B4=EC=85=98=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=B4=88=EA=B8=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Scene/Search/BeforeSearch/SearchReactor.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift index 1b8d0b76..74d1ca5b 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift @@ -42,6 +42,11 @@ final class SearchReactor: Reactor { var newBottomSearchList: [HomeCardSectionCell.Input] = [] var bottomSearchListLastIndexPath: IndexPath? + mutating func resetPaginationState() { + self.newBottomSearchList = [] + self.bottomSearchListLastIndexPath = nil + } + } // MARK: - properties @@ -183,6 +188,7 @@ final class SearchReactor: Reactor { switch mutation { case .loadView: newState.sections = getSection() + newState.resetPaginationState() case .moveToCategoryScene(let controller): let categoryIDList = searchCategorySection.inputDataList.compactMap { $0.id } let nextController = SearchCategoryController() From 3ae769eec60798fa9786af2e080e053e124cb007 Mon Sep 17 00:00:00 2001 From: 0Hooni Date: Thu, 1 May 2025 16:06:20 +0900 Subject: [PATCH 15/19] =?UTF-8?q?feat/#126:=20=EC=83=88=EB=A1=9C=EC=9A=B4?= =?UTF-8?q?=20updateBottomSearchList=20mutation=20=EB=8F=99=EC=9E=91=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - sections에서 HomeGridSection을 찾음 - HomeGridSection에 새로 추가될 아이템을 넣어줌 - controller가 해당 아이템을 넣어줄 섹션을 알려주기 위한 indexPath 전달 --- .../Scene/Search/BeforeSearch/SearchReactor.swift | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift index 74d1ca5b..e229323a 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift @@ -47,6 +47,15 @@ final class SearchReactor: Reactor { self.bottomSearchListLastIndexPath = nil } + mutating func updateBottomGridSection(by newItems: [HomeCardSectionCell.Input]) { + sections = sections.map { section in + if var grid = section as? HomeCardGridSection { + grid.inputDataList.append(contentsOf: newItems) + return grid + } + return section + } + } } // MARK: - properties @@ -239,6 +248,10 @@ final class SearchReactor: Reactor { case .resetSearchKeyWord: newState.searchKeyWord = nil newState.sections = getSection() + case .updateBottomSearchList(let newItems, let indexPath): + newState.updateBottomGridSection(by: newItems) + newState.newBottomSearchList = newItems + newState.bottomSearchListLastIndexPath = indexPath } return newState } From 7574d2bb6a8b4a82b6c4c3159a539a9d4b90e4a6 Mon Sep 17 00:00:00 2001 From: 0Hooni Date: Thu, 1 May 2025 16:07:09 +0900 Subject: [PATCH 16/19] =?UTF-8?q?refactor/#126:=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0=20=EB=B0=8F=20=EC=9D=B4=ED=95=B4=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Scene/Search/BeforeSearch/SearchReactor.swift | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift index e229323a..63c8179b 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchReactor.swift @@ -248,6 +248,7 @@ final class SearchReactor: Reactor { case .resetSearchKeyWord: newState.searchKeyWord = nil newState.sections = getSection() + case .updateBottomSearchList(let newItems, let indexPath): newState.updateBottomGridSection(by: newItems) newState.newBottomSearchList = newItems @@ -334,7 +335,10 @@ final class SearchReactor: Reactor { ) .withUnretained(self) .map { (owner, response) in - let isLogin = response.loginYn + // 1) 새로 받아오기 전의 기존 아이템 개수 저장 + let previousCount = owner.searchListSection.inputDataList.count + + // 2) API 결과 매핑 let newItems = response.popUpStoreList.map { HomeCardSectionCell.Input( imagePath: $0.mainImageUrl, @@ -345,10 +349,11 @@ final class SearchReactor: Reactor { startDate: $0.startDate, endDate: $0.endDate, isBookmark: $0.bookmarkYn, - isLogin: isLogin + isLogin: response.loginYn ) } + // 3) 첫 페이지 vs 이후 페이지 분기 if owner.currentPage == 0 { // 첫 페이지는 전체 reload // SearchCountTitleSection 설정 From 904830f057f59cead9272bd8b564d771a3430a91 Mon Sep 17 00:00:00 2001 From: 0Hooni Date: Thu, 1 May 2025 16:07:35 +0900 Subject: [PATCH 17/19] =?UTF-8?q?fix/#126:=20reloadData=EA=B0=80=20?= =?UTF-8?q?=EC=83=88=EB=A1=9C=EC=9A=B4=20=EC=83=81=ED=83=9C=EB=A1=9C=20?= =?UTF-8?q?=EA=B7=B8=EB=A0=A4=EC=A0=B8=EC=95=BC=EB=90=A0=EB=95=8C=EB=A7=8C?= =?UTF-8?q?=20=EB=8F=99=EC=9E=91=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Scene/Search/BeforeSearch/SearchController.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift index 7e486a9b..305ef344 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift @@ -114,8 +114,9 @@ extension SearchController { .disposed(by: disposeBag) reactor.state + .filter { $0.newBottomSearchList.isEmpty && $0.bottomSearchListLastIndexPath == nil } .withUnretained(self) - .subscribe { (owner, state) in + .subscribe { owner, state in owner.sections = state.sections owner.mainView.contentCollectionView.reloadData() } From 57e7a844c3155e3f6f7374eb67f7773ef61b7ccf Mon Sep 17 00:00:00 2001 From: 0Hooni Date: Thu, 1 May 2025 16:08:07 +0900 Subject: [PATCH 18/19] =?UTF-8?q?feat/#126:=20=EC=83=88=EB=A1=9C=EC=9A=B4?= =?UTF-8?q?=20=ED=8E=98=EC=9D=B4=EC=A7=80=EB=84=A4=EC=9D=B4=EC=85=98?= =?UTF-8?q?=EC=9D=84=20=EB=8F=99=EC=9E=91=ED=95=98=EA=B8=B0=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20controller=20bind=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BeforeSearch/SearchController.swift | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift index 305ef344..cc473a5c 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/BeforeSearch/SearchController.swift @@ -121,6 +121,31 @@ extension SearchController { owner.mainView.contentCollectionView.reloadData() } .disposed(by: disposeBag) + + reactor.state + .map { (sections: $0.sections, + newItems: $0.newBottomSearchList, + indexPath: $0.bottomSearchListLastIndexPath) } + .filter { !$0.newItems.isEmpty && $0.indexPath != nil } + .withUnretained(self) + .subscribe { (owner, subscribeResponse) in + let (updatedSections, newPopUpItems, popUpGridindexPath) = subscribeResponse + guard let popUpGridindexPath = popUpGridindexPath else { return } + + let start = popUpGridindexPath.item + let count = newPopUpItems.count + let section = popUpGridindexPath.section + let indexPaths = (start.. Date: Thu, 1 May 2025 22:29:29 +0900 Subject: [PATCH 19/19] =?UTF-8?q?style/#126:=20=EC=98=A4=ED=83=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Presentation/Scene/Search/Main/SearchMainController.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/Main/SearchMainController.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/Main/SearchMainController.swift index 0808019d..33d083b1 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/Main/SearchMainController.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Search/Main/SearchMainController.swift @@ -48,7 +48,7 @@ extension SearchMainController { super.viewDidLoad() self.addViews() - self.setupContstraints() + self.setupConstraints() } override func viewDidAppear(_ animated: Bool) { @@ -72,7 +72,7 @@ private extension SearchMainController { .forEach { self.view.addSubview($0) } } - func setupContstraints() { + func setupConstraints() { self.dataSource = self self.isScrollEnabled = false