Skip to content

Commit 3fa3a72

Browse files
authored
[NL-79]: 홈 화면 미비점 수정 - 2 (#56)
* [NL-79]: 번호 새로 받으면 스크롤 최상단으로 이동 * [NL-79]: 스와이프 제스쳐 활성화 * [NL-79]: 로딩 인디케이터 추가 * [NL-79]: 홈화면 결과 조회 가능 여부 확인 로직 추가 * [NL-79]: 추천 상세 화면 결과 조회 가능 여부 확인 로직 추가
1 parent 35563ee commit 3fa3a72

File tree

9 files changed

+94
-27
lines changed

9 files changed

+94
-27
lines changed

Common/Base/Sources/BaseViewController.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@ open class BaseViewController: UIViewController {
1818
open var navigationBarStyle: NavigationBar.Style { .text(alignment: .center) }
1919
public private(set) lazy var navigationBar = NavigationBar(
2020
style: navigationBarStyle, height: Constant.navigationBarHeight)
21+
private lazy var interactionBlockerView = UIView().then {
22+
$0.backgroundColor = .clear
23+
$0.isHidden = true
24+
$0.isUserInteractionEnabled = true
25+
}
26+
private lazy var activityIndicator = UIActivityIndicatorView(style: .large).then {
27+
$0.hidesWhenStopped = true
28+
}
29+
2130
public override var title: String? {
2231
get { navigationBar.title }
2332
set { navigationBar.title = newValue }
@@ -29,12 +38,27 @@ open class BaseViewController: UIViewController {
2938
super.viewDidLoad()
3039
setupNavigationBar()
3140
setNavigationBarHidden(false)
41+
42+
view.addSubview(interactionBlockerView)
43+
interactionBlockerView.snp.makeConstraints { make in
44+
make.top.equalTo(view.safeAreaLayoutGuide.snp.top)
45+
make.leading.trailing.bottom.equalToSuperview()
46+
}
47+
48+
view.addSubview(activityIndicator)
49+
activityIndicator.snp.makeConstraints { make in
50+
make.center.equalToSuperview()
51+
}
3252
}
3353

3454
open override func viewDidLayoutSubviews() {
3555
super.viewDidLayoutSubviews()
3656
updateBottomSafeArea()
3757
view.bringSubviewToFront(navigationBar)
58+
if interactionBlockerView.isHidden == false {
59+
view.bringSubviewToFront(interactionBlockerView)
60+
view.bringSubviewToFront(activityIndicator)
61+
}
3862
}
3963

4064
public func setNavigationBarHidden(_ isHidden: Bool) {
@@ -52,6 +76,7 @@ open class BaseViewController: UIViewController {
5276

5377
private func setupNavigationBar() {
5478
navigationController?.setNavigationBarHidden(true, animated: false)
79+
navigationController?.interactivePopGestureRecognizer?.delegate = self
5580
view.addSubview(navigationBar)
5681
navigationBar.snp.makeConstraints { make in
5782
make.bottom.equalTo(view.safeAreaLayoutGuide.snp.top)
@@ -69,3 +94,24 @@ open class BaseViewController: UIViewController {
6994
additionalSafeAreaInsets.bottom = TabBarView.Constant.tabBarHeight
7095
}
7196
}
97+
98+
extension BaseViewController: UIGestureRecognizerDelegate {
99+
public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
100+
return true
101+
}
102+
}
103+
104+
extension BaseViewController {
105+
public func showLoading() {
106+
interactionBlockerView.isHidden = false
107+
view.bringSubviewToFront(interactionBlockerView)
108+
view.bringSubviewToFront(activityIndicator)
109+
activityIndicator.startAnimating()
110+
view.bringSubviewToFront(navigationBar)
111+
}
112+
113+
public func hideLoading() {
114+
interactionBlockerView.isHidden = true
115+
activityIndicator.stopAnimating()
116+
}
117+
}

Feature/Home/Sources/Home/HomeService.swift

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,27 +29,28 @@ struct HomeService {
2929
let (lottoRecommendation, dailyFortunes) = try await (
3030
lottoRecommendationRequest, dailyFortunesRequest
3131
)
32-
let recommendationCollectionViewCellModel =
33-
if let recommendationContent = lottoRecommendation.content {
34-
HomeRecommendationCollectionViewCellModel(
35-
title: "\(name)님을 위한 로또 번호 추천",
36-
state: .recommended( // TODO: 서버 - 결과 확인 여부 추가 예정
37-
numbers: [
38-
recommendationContent.num1,
39-
recommendationContent.num2,
40-
recommendationContent.num3,
41-
recommendationContent.num4,
42-
recommendationContent.num5,
43-
recommendationContent.num6,
44-
].sorted()
45-
)
46-
)
47-
} else {
48-
HomeRecommendationCollectionViewCellModel(
49-
title: "\(name)님을 위한 로또 번호 추천",
50-
state: .needsRecommendation
51-
)
52-
}
32+
33+
let recommendationCollectionViewCellModel: HomeRecommendationCollectionViewCellModel
34+
if let recommendationContent = lottoRecommendation.content {
35+
let numbers = [
36+
recommendationContent.num1,
37+
recommendationContent.num2,
38+
recommendationContent.num3,
39+
recommendationContent.num4,
40+
recommendationContent.num5,
41+
recommendationContent.num6,
42+
].sorted()
43+
recommendationCollectionViewCellModel = HomeRecommendationCollectionViewCellModel(
44+
title: "\(name)님을 위한 로또 번호 추천",
45+
state: lottoRecommendation.isFinished ? .needsResultCheck(numbers: numbers) : .recommended(numbers: numbers)
46+
)
47+
} else {
48+
recommendationCollectionViewCellModel = HomeRecommendationCollectionViewCellModel(
49+
title: "\(name)님을 위한 로또 번호 추천",
50+
state: .needsRecommendation
51+
)
52+
}
53+
5354
let homeTodayFortuneCollectionViewCellModels = dailyFortunes.content.map { item in
5455
FortuneItemCollectionViewCellModel(
5556
title: item.fortuneType,

Feature/Home/Sources/Home/HomeViewController.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,17 @@ public final class HomeViewController: BaseViewController {
6565
}
6666

6767
private func setupBinding() {
68+
viewModel.output.isLoading
69+
.receive(on: DispatchQueue.main)
70+
.sink { [weak self] isLoading in
71+
if isLoading {
72+
self?.showLoading()
73+
} else {
74+
self?.hideLoading()
75+
}
76+
}
77+
.store(in: &cancellables)
78+
6879
viewModel.output.sections
6980
.receive(on: DispatchQueue.main)
7081
.sink { [weak self] _ in

Feature/Home/Sources/Home/HomeViewModel.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public final class HomeViewModel {
1919
}
2020

2121
struct Output {
22+
let isLoading = CurrentValueSubject<Bool, Never>(false)
2223
let sections = CurrentValueSubject<[any HomeCellModel], Never>([])
2324
}
2425

@@ -31,6 +32,7 @@ public final class HomeViewModel {
3132
func send(input: Input) {
3233
switch input {
3334
case .viewDidLoad:
35+
output.isLoading.send(true)
3436
Task {
3537
do {
3638
let sections = try await homeService.fetch()
@@ -39,6 +41,7 @@ public final class HomeViewModel {
3941
// TODO: 에러 처리
4042
print(error)
4143
}
44+
output.isLoading.send(false)
4245
}
4346

4447
case .recommendationButtonTapped(let state):

Feature/Home/Sources/Model/LottoRecommendationDTO.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ struct LottoRecommendationDTO: Decodable {
1313
case userId = "user_id"
1414
case round
1515
case content
16+
case isFinished = "is_finished"
1617
}
1718

1819
let userId: String
1920
let round: Int
2021
let content: Content?
22+
let isFinished: Bool
2123

2224
struct Content: Codable {
2325

Feature/Home/Sources/RecommendationDetail/NumberRecommendationCollectionViewCell.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,13 @@ import UIKit
1313

1414
struct NumberRecommendationCollectionViewCellModel: RecommendationDetailCellModel {
1515
let roundText: String
16+
let isFinished: Bool
1617
let title: String
1718
let numbers: [Int]
18-
var secondsUntilResult: Int { // TODO: 기기 시간 설정을 바꾼 경우, 오후 8시 35분이 지났으나 서버에서 결과 조회가 준비되지 않은 경우 논의 필요
19+
var secondsUntilResult: Int { // TODO: 기기 시간 설정을 바꾼 케이스 논의 필요
20+
if isFinished {
21+
return .zero
22+
}
1923
var calendar = Calendar(identifier: .gregorian)
2024
calendar.timeZone = .current
2125
calendar.locale = Locale(identifier: "ko_KR")
@@ -154,10 +158,7 @@ final class NumberRecommendationCollectionViewCell: BaseCollectionViewCell {
154158

155159
countdownCancellable = Timer.publish(every: 1, on: .main, in: .common)
156160
.autoconnect()
157-
.handleEvents(receiveSubscription: { [weak self] _ in
158-
self?.timeUntilDrawLabel.styledText = self?.countdownText(
159-
from: Int(target.timeIntervalSinceNow))
160-
})
161+
.prepend(target)
161162
.map { _ in
162163
return max(0, Int(target.timeIntervalSinceNow))
163164
}
@@ -219,6 +220,7 @@ final class NumberRecommendationCollectionViewCell: BaseCollectionViewCell {
219220
#Preview {
220221
let cellModel = NumberRecommendationCollectionViewCellModel(
221222
roundText: "1181회",
223+
isFinished: false,
222224
title: "콩떡님을 위한 로또 번호 추천",
223225
numbers: [9, 11, 18, 24, 33, 42]
224226
)

Feature/Home/Sources/RecommendationDetail/RecommendationDetailService.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ struct RecommendationDetailService {
5050
return [
5151
NumberRecommendationCollectionViewCellModel(
5252
roundText: "\(recommendation.round)",
53+
isFinished: recommendation.isFinished,
5354
title: title,
5455
numbers: [
5556
content.num1,

Feature/Home/Sources/RecommendationDetail/RecommendationDetailViewController.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ final class RecommendationDetailViewController: BaseViewController {
170170
self?.loadingView.play()
171171
self?.title = nil
172172
} else {
173+
self?.collectionView.setContentOffset(.zero, animated: false)
173174
UIView.animate(
174175
withDuration: 0.25,
175176
animations: {

Feature/Onboarding/Sources/Agreement/AgreementViewController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ extension AgreementViewController: AgreementCellDelegate {
240240
}
241241
}
242242

243-
extension AgreementViewController: UIGestureRecognizerDelegate {
243+
extension AgreementViewController {
244244
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch)
245245
-> Bool
246246
{

0 commit comments

Comments
 (0)