Skip to content

Commit ef4feb8

Browse files
authored
Release 1.0.0
2 parents 257a45f + 23eef08 commit ef4feb8

File tree

7 files changed

+194
-152
lines changed

7 files changed

+194
-152
lines changed

Surcharges/PresentationLayer/UIs/CommonUI/Sources/Text+extension/blurBackground.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,11 @@ import Resources
1313
public extension View {
1414
func blurBackground() -> some View {
1515
self
16-
.padding([.top, .bottom], 10)
17-
.padding([.leading, .trailing], 20)
18-
.frame(maxWidth: .infinity, alignment: .leading)
1916
.background(.ultraThinMaterial, in: Rectangle())
2017
}
2118

2219
func blurRoundedBackground(cornerRadius: CGFloat) -> some View {
2320
self
24-
.padding([.top, .bottom], 10)
25-
.padding([.leading, .trailing], 20)
26-
.frame(maxWidth: .infinity, alignment: .leading)
2721
.background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: cornerRadius))
2822
}
2923
}

Surcharges/PresentationLayer/UIs/Main/Sources/MainView.swift

Lines changed: 64 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ public struct MainView<VM: MainViewModelProtocol, Router: MainRouterProtocol, Ad
2424
@StateObject private var _adsService: AdsService = AdsService()
2525

2626
private let _surchargeStatusTip = SurchargeStatusTip()
27-
private let _useLocationTip = UseLocationTip()
28-
@State private var _showLocationDeniedAlert = false
29-
@FocusState private var _isSearchTextFeildFocused: Bool
3027

3128
public init(viewModel: VM, router: Router) {
3229
__viewModel = StateObject(wrappedValue: viewModel)
@@ -48,49 +45,24 @@ public struct MainView<VM: MainViewModelProtocol, Router: MainRouterProtocol, Ad
4845
.padding([.top], 10)
4946
.padding([.leading, .trailing], 20)
5047

51-
/*
52-
// Favourite Places is currently not available.
5348
Section {
5449

55-
FavouritePlacesView()
56-
.padding([.leading, .trailing], 20)
57-
58-
} header: {
59-
Text("Favourite Places")
60-
.font(.title3)
61-
.blurBackground()
62-
}
63-
*/
64-
65-
if _viewModel.isLoading {
66-
67-
Spacer()
68-
69-
CircleProgress()
70-
71-
Spacer()
72-
73-
} else {
74-
75-
if _viewModel.noResults {
50+
if _viewModel.isLoading {
7651

77-
if _adsService.isShowingAds {
78-
ListAdsView(unitId: _adsService.listBannerUnitId)
79-
}
80-
81-
NoResultView(searchedText: _viewModel.searchedText)
82-
.padding(.top, 40)
83-
.padding([.leading, .trailing], 20)
52+
CircleProgress()
8453

8554
} else {
8655

87-
if !_viewModel.mainModel.places.isEmpty {
56+
if _viewModel.noResults {
8857

89-
if _adsService.isShowingAds {
90-
ListAdsView(unitId: _adsService.listBannerUnitId)
91-
}
58+
NoResultView(searchedText: _viewModel.searchedText)
59+
.padding(.top, 40)
60+
.padding([.leading, .trailing], 20)
61+
62+
} else {
9263

93-
Section {
64+
if !_viewModel.mainModel.places.isEmpty {
65+
9466
PlacesView(
9567
mainModel: $_viewModel.mainModel,
9668
selectedPlace: { placeId in
@@ -103,117 +75,72 @@ public struct MainView<VM: MainViewModelProtocol, Router: MainRouterProtocol, Ad
10375
}
10476
)
10577

106-
} header: {
107-
Text("🔎\(R.string.localizable.searchFor(_viewModel.searchedText))")
108-
.blurBackground()
78+
} else {
79+
80+
WelcomeView()
81+
.padding(.top, 40)
82+
.padding([.leading, .trailing], 20)
83+
84+
FixedAdsView(isAdShowing: $_adsService.isShowingAds, unitId: _adsService.fixedBannerUnitId)
85+
.blurRoundedBackground(cornerRadius: 20)
86+
.padding([.top, .bottom], 10)
87+
.padding([.leading, .trailing], 20)
88+
10989
}
90+
}
91+
92+
}
93+
94+
} header: {
95+
96+
if !_viewModel.showWelcome {
97+
98+
VStack(spacing: 0) {
11099

111-
} else {
112-
113-
WelcomeView()
114-
.padding(.top, 40)
115-
.padding([.leading, .trailing], 20)
100+
if _adsService.isShowingAds {
101+
ListAdsView(unitId: _adsService.listBannerUnitId)
102+
}
116103

117-
FixedAdsView(isAdShowing: $_adsService.isShowingAds, unitId: _adsService.fixedBannerUnitId)
118-
.padding(.top, 20)
104+
Text("🔎\(R.string.localizable.searchFor(_viewModel.searchedText))")
105+
.frame(maxWidth: .infinity, alignment: .leading)
119106
.padding([.leading, .trailing], 20)
107+
.padding(.top, 10)
108+
.padding(.bottom, 10)
120109

121110
}
111+
.blurBackground()
112+
113+
} else {
114+
115+
Rectangle()
116+
.foregroundStyle(R.color.clear.color)
117+
.frame(height: 20)
118+
122119
}
123-
}
124-
}
125-
}
126-
.scrollDismissesKeyboard(.interactively)
127-
128-
HStack(spacing: 10) {
129-
130-
Button {
131-
132-
if _viewModel.isDeniedToUseUserLocation {
133-
_showLocationDeniedAlert.toggle()
134-
} else {
135-
136-
withAnimation {
137-
_viewModel.toggleUserLocation()
138-
}
139-
140-
_useLocationTip.invalidate(reason: .actionPerformed)
141-
142-
}
143-
144-
} label: {
145-
146-
if _viewModel.isDeniedToUseUserLocation {
147-
Image(systemName: "location.slash")
148-
.foregroundStyle(R.color.blue600.color)
149-
} else {
150-
Image(systemName: _viewModel.isUserLocationOn ? "location.fill" : "location")
151-
.foregroundStyle(R.color.blue600.color)
152-
}
153-
154-
}
155-
.buttonStyle(.plain)
156-
.contentTransition(.symbolEffect(.replace))
157-
.alert(
158-
R.string.localizable.alertUseLocationDeniedTitle(),
159-
isPresented: $_showLocationDeniedAlert
160-
) {
161-
162-
Button {
163-
164-
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil)
165120

166-
} label: {
167-
Text(R.string.localizable.goToSettings())
168121
}
169122

170-
Button(role: .cancel) {
171-
_showLocationDeniedAlert.toggle()
172-
} label: {
173-
Text(R.string.localizable.close())
174-
}
175-
176-
} message: {
177-
Text(R.string.localizable.alertUseLocationDeniedMessage())
178-
}
179-
.popoverTip(_useLocationTip, arrowEdge: .leading) { action in
180-
withAnimation {
181-
_viewModel.toggleUserLocation()
182-
}
183-
_useLocationTip.invalidate(reason: .actionPerformed)
184-
}
185-
186-
TextField(R.string.localizable.searchBoxPlaceholder(), text: $_viewModel.searchText)
187-
.textFieldStyle(.roundedBorder)
188-
.font(.body)
189-
.disabled(_viewModel.isLoading)
190-
.onSubmit {
191-
Task {
192-
await _viewModel.search()
193-
}
194-
}
195-
.submitLabel(.search)
196-
.focused($_isSearchTextFeildFocused)
197-
.onChange(of: _isSearchTextFeildFocused, { _, newValue in
198-
if newValue {
199-
UseLocationTip.tryToSearch.toggle()
200-
}
201-
})
202-
203-
Button {
204-
Task {
205-
await _viewModel.search()
206-
}
207-
} label: {
208-
Text(R.string.localizable.searchButtonTitle())
209-
.font(.body)
210-
.disabled(!_viewModel.canSearch)
123+
/*
124+
// Favourite Places is currently not available.
125+
Section {
126+
127+
FavouritePlacesView()
128+
.padding([.leading, .trailing], 20)
129+
130+
} header: {
131+
Text("Favourite Places")
132+
.font(.title3)
133+
.blurBackground()
134+
}
135+
*/
211136
}
212-
213137
}
214-
.padding([.top], 10)
215-
.padding([.leading, .trailing], 30)
216-
.padding([.bottom], 10)
138+
.scrollDismissesKeyboard(.interactively)
139+
140+
SearchView(viewModel: __viewModel)
141+
.padding([.top], 10)
142+
.padding([.leading, .trailing], 30)
143+
.padding([.bottom], 10)
217144

218145
}
219146
.navigationTitle("Surcharges💸")
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
//
2+
// SearchView.swift
3+
// Main
4+
//
5+
// Created by Bonsung Koo on 01/02/2025.
6+
// Copyright © 2025 Surcharges. All rights reserved.
7+
//
8+
9+
import SwiftUI
10+
11+
import Resources
12+
import ViewModelProtocols
13+
14+
struct SearchView<VM: MainViewModelProtocol>: View {
15+
16+
private let _useLocationTip = UseLocationTip()
17+
@State private var _showLocationDeniedAlert = false
18+
@StateObject private var _viewModel: VM
19+
20+
@FocusState private var _isSearchTextFeildFocused: Bool
21+
22+
init(viewModel: StateObject<VM>) {
23+
__viewModel = viewModel
24+
}
25+
26+
var body: some View {
27+
HStack(spacing: 10) {
28+
29+
Button {
30+
31+
if _viewModel.isDeniedToUseUserLocation {
32+
_showLocationDeniedAlert.toggle()
33+
} else {
34+
35+
withAnimation {
36+
_viewModel.toggleUserLocation()
37+
}
38+
39+
_useLocationTip.invalidate(reason: .actionPerformed)
40+
41+
}
42+
43+
} label: {
44+
45+
if _viewModel.isDeniedToUseUserLocation {
46+
Image(systemName: "location.slash")
47+
.foregroundStyle(R.color.blue600.color)
48+
} else {
49+
Image(systemName: _viewModel.isUserLocationOn ? "location.fill" : "location")
50+
.foregroundStyle(R.color.blue600.color)
51+
}
52+
53+
}
54+
.buttonStyle(.plain)
55+
.contentTransition(.symbolEffect(.replace))
56+
.alert(
57+
R.string.localizable.alertUseLocationDeniedTitle(),
58+
isPresented: $_showLocationDeniedAlert
59+
) {
60+
61+
Button {
62+
63+
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil)
64+
65+
} label: {
66+
Text(R.string.localizable.goToSettings())
67+
}
68+
69+
Button(role: .cancel) {
70+
_showLocationDeniedAlert.toggle()
71+
} label: {
72+
Text(R.string.localizable.close())
73+
}
74+
75+
} message: {
76+
Text(R.string.localizable.alertUseLocationDeniedMessage())
77+
}
78+
.popoverTip(_useLocationTip, arrowEdge: .leading) { action in
79+
withAnimation {
80+
_viewModel.toggleUserLocation()
81+
}
82+
_useLocationTip.invalidate(reason: .actionPerformed)
83+
}
84+
85+
TextField(R.string.localizable.searchBoxPlaceholder(), text: $_viewModel.searchText)
86+
.textFieldStyle(.roundedBorder)
87+
.font(.body)
88+
.disabled(_viewModel.isLoading)
89+
.onSubmit {
90+
91+
if _viewModel.canSearch {
92+
Task {
93+
await _viewModel.search()
94+
}
95+
}
96+
97+
}
98+
.submitLabel(.search)
99+
.focused($_isSearchTextFeildFocused)
100+
.onChange(of: _isSearchTextFeildFocused, { _, newValue in
101+
if newValue {
102+
UseLocationTip.tryToSearch.toggle()
103+
}
104+
})
105+
106+
Button {
107+
108+
Task {
109+
await _viewModel.search()
110+
}
111+
112+
} label: {
113+
Text(R.string.localizable.searchButtonTitle())
114+
.font(.body)
115+
.disabled(!_viewModel.canSearch)
116+
}
117+
118+
}
119+
}
120+
}

Surcharges/PresentationLayer/UIs/MobileAds/Sources/FixedAdsView.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ public struct FixedAdsView: View {
9595

9696
}
9797
}
98-
.background(R.color.gray100.color)
9998
.frame(minHeight: _adSize.size.width, maxHeight: _adSize.size.width)
10099
.cornerRadius(20)
101100
.readSize { size in

Surcharges/PresentationLayer/UIs/MobileAds/Sources/ListAdsView.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ public struct ListAdsView: View {
3030
.frame(height: _adSize.size.height)
3131
}
3232
.background(R.color.gray100.color)
33-
.cornerRadius(20)
3433
.readSize { size in
3534
_adSize = GADCurrentOrientationAnchoredAdaptiveBannerAdSizeWithWidth(size.width)
3635
}

0 commit comments

Comments
 (0)