Skip to content

Commit 48ae98e

Browse files
authored
Merge pull request #103 from OlegEremenko991/feature/update-loadingoverlay
Обновил индикатор загрузки и сделал небольшой рефактор
2 parents 5409364 + 5db22bf commit 48ae98e

File tree

5 files changed

+71
-98
lines changed

5 files changed

+71
-98
lines changed

SwiftUI-WorkoutApp/DesignSystem/Sources/DesignSystem/ViewModifiers/LoadingOverlayModifier.swift

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,39 @@
11
import SwiftUI
22

33
struct LoadingOverlayModifier: ViewModifier {
4-
@State private var angle: CGFloat = 0
5-
@State private var isAnimating = false
6-
private var foreverAnimation: Animation {
7-
Animation.linear(duration: 2.0)
8-
.repeatForever(autoreverses: false)
9-
}
10-
114
let isLoading: Bool
125

136
func body(content: Content) -> some View {
147
content
158
.disabled(isLoading)
169
.opacity(isLoading ? 0.5 : 1)
1710
.overlay {
18-
Image("LoadingIndicator", bundle: .module)
19-
.resizable()
20-
.scaledToFit()
21-
.frame(width: 50, height: 50)
22-
.opacity(isLoading ? 1 : 0)
23-
.rotationEffect(.degrees(isAnimating ? angle : 0))
24-
.onChange(of: isLoading) { [isLoading] newValue in
25-
switch (isLoading, newValue) {
26-
case (false, true):
27-
isAnimating = true
28-
withAnimation(foreverAnimation) { angle += 360 }
29-
default: break
30-
}
31-
}
11+
LoadingIndicator(isVisible: isLoading)
3212
}
3313
.animation(.default, value: isLoading)
3414
}
3515
}
3616

17+
private struct LoadingIndicator: View {
18+
@State private var isAnimating = false
19+
let isVisible: Bool
20+
21+
var body: some View {
22+
Image("LoadingIndicator", bundle: .module)
23+
.resizable()
24+
.frame(width: 50, height: 50)
25+
.rotationEffect(Angle(degrees: isAnimating ? 360 : 0))
26+
.animation(
27+
.linear(duration: 2.0).repeatForever(autoreverses: false),
28+
value: isAnimating
29+
)
30+
.onAppear { isAnimating = true }
31+
.opacity(isVisible ? 1 : 0)
32+
}
33+
}
34+
3735
public extension View {
36+
/// Добавляет в оверлей индикатор загрузки
3837
func loadingOverlay(if isLoading: Bool) -> some View {
3938
modifier(LoadingOverlayModifier(isLoading: isLoading))
4039
}

SwiftUI-WorkoutApp/Screens/Events/List/EventsListView.swift

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,17 @@ struct EventsListView: View {
2020
NavigationView {
2121
VStack {
2222
segmentedControl
23-
if showEmptyView {
24-
emptyView
25-
} else {
26-
eventsList
27-
}
23+
eventsList
24+
.overlay { emptyView }
2825
}
26+
.loadingOverlay(if: viewModel.isLoading)
27+
.background(Color.swBackground)
2928
.alert("Необходимо выбрать площадку", isPresented: $showEventCreationRule) {
3029
Button(action: createEventIfAvailable) { Text("Перейти на карту") }
3130
Button(role: .cancel, action: {}, label: { Text("Понятно") })
3231
} message: {
3332
Text(Constants.Alert.eventCreationRule)
3433
}
35-
.loadingOverlay(if: viewModel.isLoading)
36-
.background(Color.swBackground)
3734
.alert(alertMessage, isPresented: $showErrorAlert) {
3835
Button("Ok", action: closeAlert)
3936
}

SwiftUI-WorkoutApp/Screens/Journals/JournalsList/JournalsListView.swift

Lines changed: 24 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -24,37 +24,32 @@ struct JournalsListView: View {
2424
}
2525

2626
var body: some View {
27-
Group {
28-
if viewModel.list.isEmpty {
29-
emptyContentView
30-
} else {
31-
journalsList
27+
journalsList
28+
.overlay { emptyContentView }
29+
.loadingOverlay(if: viewModel.isLoading)
30+
.background(Color.swBackground)
31+
.confirmationDialog(
32+
Constants.Alert.deleteJournal,
33+
isPresented: $showDeleteDialog,
34+
titleVisibility: .visible
35+
) { deleteJournalButton }
36+
.onChange(of: viewModel.errorMessage, perform: setupErrorAlert)
37+
.onChange(of: viewModel.isJournalCreated, perform: closeSheet)
38+
.sheet(isPresented: $isCreatingJournal) { newJournalSheet }
39+
.alert(errorTitle, isPresented: $showErrorAlert) {
40+
Button("Ok", action: closeAlert)
3241
}
33-
}
34-
.loadingOverlay(if: viewModel.isLoading)
35-
.background(Color.swBackground)
36-
.confirmationDialog(
37-
Constants.Alert.deleteJournal,
38-
isPresented: $showDeleteDialog,
39-
titleVisibility: .visible
40-
) { deleteJournalButton }
41-
.onChange(of: viewModel.errorMessage, perform: setupErrorAlert)
42-
.onChange(of: viewModel.isJournalCreated, perform: closeSheet)
43-
.sheet(isPresented: $isCreatingJournal) { newJournalSheet }
44-
.alert(errorTitle, isPresented: $showErrorAlert) {
45-
Button("Ok", action: closeAlert)
46-
}
47-
.task { await askForJournals() }
48-
.refreshable { await askForJournals(refresh: true) }
49-
.toolbar {
50-
ToolbarItem(placement: .navigationBarLeading) {
51-
refreshButton
52-
}
53-
ToolbarItem(placement: .navigationBarTrailing) {
54-
addJournalButton
42+
.task { await askForJournals() }
43+
.refreshable { await askForJournals(refresh: true) }
44+
.toolbar {
45+
ToolbarItem(placement: .navigationBarLeading) {
46+
refreshButton
47+
}
48+
ToolbarItem(placement: .navigationBarTrailing) {
49+
addJournalButton
50+
}
5551
}
56-
}
57-
.onDisappear(perform: cancelTasks)
52+
.onDisappear(perform: cancelTasks)
5853
}
5954
}
6055

@@ -93,7 +88,6 @@ private extension JournalsListView {
9388
action: showNewJournalSheet
9489
)
9590
.opacity(showEmptyView ? 1 : 0)
96-
.disabled(viewModel.isLoading)
9791
}
9892

9993
var journalsList: some View {
@@ -118,9 +112,6 @@ private extension JournalsListView {
118112
.padding([.top, .horizontal])
119113
}
120114
.sheet(item: $journalToEdit, content: showSettingsSheet)
121-
.opacity(viewModel.isLoading ? 0.5 : 1)
122-
.animation(.default, value: viewModel.isLoading)
123-
.disabled(viewModel.isLoading)
124115
}
125116

126117
var showEmptyView: Bool {

SwiftUI-WorkoutApp/Screens/Messages/DialogList/DialogListView.swift

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,30 @@ struct DialogListView: View {
1717
@State private var deleteDialogTask: Task<Void, Never>?
1818

1919
var body: some View {
20-
Group {
21-
if viewModel.list.isEmpty {
22-
emptyContentView
23-
} else {
24-
dialogList
25-
}
26-
}
27-
.loadingOverlay(if: viewModel.isLoading)
28-
.background(Color.swBackground)
29-
.confirmationDialog(
30-
Constants.Alert.deleteDialog,
31-
isPresented: $showDeleteConfirmation,
32-
titleVisibility: .visible
33-
) { deleteDialogButton }
34-
.onChange(of: viewModel.errorMessage, perform: setupErrorAlert)
35-
.alert(errorTitle, isPresented: $showErrorAlert) {
36-
Button("Ok", action: closeAlert)
37-
}
38-
.task { await askForDialogs() }
39-
.refreshable { await askForDialogs(refresh: true) }
40-
.toolbar {
41-
ToolbarItem(placement: .navigationBarLeading) {
42-
refreshButton
20+
dialogList
21+
.overlay { emptyContentView }
22+
.loadingOverlay(if: viewModel.isLoading)
23+
.background(Color.swBackground)
24+
.confirmationDialog(
25+
Constants.Alert.deleteDialog,
26+
isPresented: $showDeleteConfirmation,
27+
titleVisibility: .visible
28+
) { deleteDialogButton }
29+
.onChange(of: viewModel.errorMessage, perform: setupErrorAlert)
30+
.alert(errorTitle, isPresented: $showErrorAlert) {
31+
Button("Ok", action: closeAlert)
4332
}
44-
ToolbarItem(placement: .navigationBarTrailing) {
45-
friendListButton
33+
.task { await askForDialogs() }
34+
.refreshable { await askForDialogs(refresh: true) }
35+
.toolbar {
36+
ToolbarItem(placement: .navigationBarLeading) {
37+
refreshButton
38+
}
39+
ToolbarItem(placement: .navigationBarTrailing) {
40+
friendListButton
41+
}
4642
}
47-
}
48-
.onDisappear(perform: cancelTasks)
43+
.onDisappear(perform: cancelTasks)
4944
}
5045
}
5146

@@ -126,9 +121,6 @@ private extension DialogListView {
126121
}
127122
.padding([.top, .horizontal])
128123
}
129-
.opacity(viewModel.isLoading ? 0.5 : 1)
130-
.animation(.default, value: viewModel.isLoading)
131-
.disabled(viewModel.isLoading)
132124
}
133125

134126
var deleteDialogButton: some View {

SwiftUI-WorkoutApp/Screens/SportsGrounds/Map/SportsGroundsMapView.swift

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ private extension SportsGroundsMapView {
116116
}
117117
.padding([.top, .horizontal])
118118
}
119-
.opacity(viewModel.isLoading ? 0.5 : 1)
120119
case .map:
121120
MapViewUI(
122121
"SportsGroundsMapView",
@@ -127,7 +126,7 @@ private extension SportsGroundsMapView {
127126
$viewModel.needUpdateRegion,
128127
openDetailsClbk: openDetailsView
129128
)
130-
.opacity(mapOpacity)
129+
.opacity(viewModel.shouldHideMap ? 0 : 1)
131130
.overlay(alignment: viewModel.isRegionSet ? .bottom : .center) {
132131
NavigationLink(isActive: $showDetailsView) {
133132
SportsGroundDetailView(
@@ -147,11 +146,6 @@ private extension SportsGroundsMapView {
147146
}
148147
}
149148

150-
var mapOpacity: Double {
151-
guard !viewModel.shouldHideMap else { return .zero }
152-
return viewModel.isLoading ? 0.5 : 1
153-
}
154-
155149
var locationSettingsReminder: some View {
156150
VStack(spacing: 12) {
157151
Text(viewModel.locationErrorMessage)

0 commit comments

Comments
 (0)