Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public enum DictionaryListEndPoint {
let joinedCategoryIds = categoryIds?.map(String.init).joined(separator: ",")
let joinedJobIds = jobId?.map(String.init).joined(separator: ",")

let query = DictionaryListQuery(keyword: keyword, page: page ?? 0, size: size ?? 20, sort: sort, minLevel: minLevel ?? 1, maxLevel: maxLevel ?? 200, jobIds: joinedJobIds, categoryIds: joinedCategoryIds)
let query = DictionaryListQuery(keyword: keyword, page: page ?? 0, size: size ?? 20, sort: sort, minLevel: minLevel, maxLevel: maxLevel, jobIds: joinedJobIds, categoryIds: joinedCategoryIds)
return .init(baseURL: base, path: "/api/v1/items", method: .GET, query: query
)
}
Expand Down
15 changes: 15 additions & 0 deletions MLS/Data/Data/Repository/UserDefaultsRepositoryImpl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,21 @@ public final class UserDefaultsRepositoryImpl: UserDefaultsRepository {
}
}

public func removeAllSearch() -> Completable {
return Completable.create { completable in
var current = UserDefaults.standard.stringArray(forKey: self.recentSearchkey) ?? []

// 해당 키워드 제거
current.removeAll()

// 다시 저장
UserDefaults.standard.set(current, forKey: self.recentSearchkey)

completable(.completed)
return Disposables.create()
}
}

public func fetchPlatform() -> Observable<LoginPlatform?> {
return Observable.create { observer in
if let rawValue = UserDefaults.standard.string(forKey: self.platformKey),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@ import RxSwift

public class RecentSearchRemoveUseCaseImpl: RecentSearchRemoveUseCase {
var repository: UserDefaultsRepository

public init(repository: UserDefaultsRepository) {
self.repository = repository
}

public func remove(keyword: String) -> Completable {
return repository.removeRecentSearch(keyword: keyword)
}

public func removeAll() -> Completable {
return repository.removeAllSearch()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ public protocol UserDefaultsRepository {
func fetchRecentSearch() -> Observable<[String]>
func addRecentSearch(keyword: String) -> Completable
func removeRecentSearch(keyword: String) -> Completable
func removeAllSearch() -> Completable

func fetchPlatform() -> Observable<LoginPlatform?>
func savePlatform(platform: LoginPlatform) -> Completable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ import RxSwift

public protocol RecentSearchRemoveUseCase {
func remove(keyword: String) -> Completable
func removeAll() -> Completable
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,6 @@ public extension DictionaryNotificationCell {
subTitleLabel.attributedText = .makeStyledString(font: .b_s_r, text: input.subTitle, color: input.isChecked ? .neutral500 : .neutral700, alignment: .left)
backgroundColor = input.isChecked ? .neutral100 : .clearMLS
layer.cornerRadius = input.isChecked ? Constant.radius : 0
checkIcon.isHidden = !input.isChecked
checkIcon.isHidden = input.isChecked
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import UIKit
public final class RecentSearchHeaderView: UICollectionReusableView {
// MARK: - Components
private let titleLabel = UILabel()
private let deleteButton = UIButton()
public let deleteButton = UIButton()
private let spacer = UIView()

// MARK: - Init
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ extension BookmarkListViewController: UICollectionViewDelegate, UICollectionView

onBookmarkTapped: { [weak self] in
guard let self else { return }
guard state.isLogin else {
guard self.reactor?.currentState.isLogin == true else {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Changing state.isLogin to self.reactor?.currentState.isLogin == true introduces optional chaining and explicit comparison to true. While functionally similar, state.isLogin is more direct if state is guaranteed to be non-nil. If reactor or currentState could be nil, this change correctly handles it, but it's important to understand the implications. If isLogin is a Bool?, then == true is correct. If isLogin is Bool, then state.isLogin is sufficient.

self.reactor?.action.onNext(.showLogin)
return
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ class DictionaryDetailBaseViewController: BaseViewController {
/// 각 탭에 해당하는 콘텐츠 뷰들을 담는 배열
public var contentViews: [UIView] = [] {
didSet {
if let index = currentTabIndex {
mainView.setTabView(index: index, contentViews: contentViews)
}
let index = currentTabIndex ?? 0
guard index < contentViews.count else { return }
mainView.setTabView(index: index, contentViews: contentViews)
Comment on lines +25 to +27

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The didSet observer for contentViews now uses currentTabIndex ?? 0 and a guard statement. This is an improvement as it provides a default value for currentTabIndex and prevents out-of-bounds access if contentViews is empty or index is invalid. This makes the UI update logic more robust.

}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ extension DictionaryListViewController: UICollectionViewDelegate, UICollectionVi
isMap: item.type == .map,
onBookmarkTapped: { [weak self] in
guard let self else { return }
guard state.isLogin else {
guard self.reactor?.currentState.isLogin == true else {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to BookmarkListViewController, changing state.isLogin to self.reactor?.currentState.isLogin == true introduces optional chaining. Ensure that isLogin is indeed an optional Bool? or that reactor and currentState can be nil at this point. If state is always available and isLogin is a non-optional Bool, the original state.isLogin is cleaner.

self.reactor?.action.onNext(.showLogin)
return
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ public final class DictionarySearchReactor: Reactor {
case backButtonTapped
case searchButtonTapped(String)
case cancelRecentButtonTapped(String)
case deleteAllButtonTapped
case recentButtonTapped(String)
}

public enum Mutation {
case navigateTo(Route)
case deleteItem(String)
case deleteAllItems
case addRecentItem(String)
case setRecentList([String])
}
Expand Down Expand Up @@ -106,6 +108,9 @@ public final class DictionarySearchReactor: Reactor {
.andThen(.just(.deleteItem(keyword)))
case .recentButtonTapped(let keyword):
return Observable.just(.navigateTo(.search(keyword)))
case .deleteAllButtonTapped:
return recentSearchRemoveUseCase.removeAll()
.andThen(.just(.deleteAllItems))
}
}

Expand All @@ -121,6 +126,8 @@ public final class DictionarySearchReactor: Reactor {
newState.recentResult.insert(name, at: 0) // 맨 앞에 최근 검색어 추가
case .deleteItem(let name):
newState.recentResult = state.recentResult.filter { $0 != name }
case .deleteAllItems:
newState.recentResult = []
}

return newState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,11 +242,19 @@ extension DictionarySearchViewController: UICollectionViewDelegate, UICollection
) -> UICollectionReusableView {
switch indexPath.section {
case 0:
let view = collectionView.dequeueReusableSupplementaryView(
guard let view = collectionView.dequeueReusableSupplementaryView(
ofKind: kind,
withReuseIdentifier: RecentSearchHeaderView.identifier,
for: indexPath
) as! RecentSearchHeaderView
) as? RecentSearchHeaderView else { return UICollectionViewCell() }

guard let reactor = reactor else { return UICollectionViewCell() }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Adding a guard let reactor = reactor else { return UICollectionViewCell() } check here is good practice. It prevents potential crashes if the reactor is nil when trying to bind actions to it.


view.deleteButton.rx.tap
.map { Reactor.Action.deleteAllButtonTapped }
.bind(to: reactor.action)
.disposed(by: disposeBag)

return view

case 2:
Expand Down