Skip to content

Commit b482a0a

Browse files
authored
Develop/refactor (#64)
* Доработка обновления площадок - При обновлении всех площадок запрашиваем список площадок, измененных с предыдущей даты ручного обновления справочника (2023-01-12T00:00:00) - Запрашиваем обновления за 5 минут вместо 30 секунд при создании новой площадки - Удалил неиспользуемый код - Обновил комментарии - Обновил нейминги - Обновил версию билда до 2
1 parent 4239f5f commit b482a0a

File tree

5 files changed

+53
-19
lines changed

5 files changed

+53
-19
lines changed

SwiftUI-WorkoutApp.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,7 +1433,7 @@
14331433
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
14341434
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
14351435
CODE_SIGN_STYLE = Automatic;
1436-
CURRENT_PROJECT_VERSION = 1;
1436+
CURRENT_PROJECT_VERSION = 2;
14371437
DEVELOPMENT_ASSET_PATHS = "SwiftUI-WorkoutApp/Preview\\ Content/PreviewContent.swift SwiftUI-WorkoutApp/Preview\\ Content";
14381438
DEVELOPMENT_TEAM = CR68PP2Z3F;
14391439
ENABLE_PREVIEWS = YES;
@@ -1469,7 +1469,7 @@
14691469
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
14701470
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
14711471
CODE_SIGN_STYLE = Automatic;
1472-
CURRENT_PROJECT_VERSION = 1;
1472+
CURRENT_PROJECT_VERSION = 2;
14731473
DEVELOPMENT_ASSET_PATHS = "SwiftUI-WorkoutApp/Preview\\ Content/PreviewContent.swift SwiftUI-WorkoutApp/Preview\\ Content";
14741474
DEVELOPMENT_TEAM = CR68PP2Z3F;
14751475
ENABLE_PREVIEWS = YES;

SwiftUI-WorkoutApp/DateFormatterService/Sources/DateFormatterService/DateFormatterService.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ public enum DateFormatterService {
2525
return string
2626
}
2727

28-
public static var halfMinuteAgoDateString: String {
28+
public static var fiveMinutesAgoDateString: String {
2929
let dateFormatter = DateFormatter()
3030
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
3131
dateFormatter.dateFormat = DateFormat.serverDateTimeSec.rawValue
32-
let halfMinuteAgo = Calendar.current.date(byAdding: .second, value: -30, to: .now) ?? .now
33-
return dateFormatter.string(from: halfMinuteAgo)
32+
let fiveMinutesAgo = Calendar.current.date(byAdding: .minute, value: -5, to: .now) ?? .now
33+
return dateFormatter.string(from: fiveMinutesAgo)
3434
}
3535

3636
public static func dateFromIsoString(_ string: String?) -> Date {

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ struct SportsGroundsMapView: View {
77
@EnvironmentObject private var defaults: DefaultsService
88
@StateObject private var viewModel = SportsGroundsMapViewModel()
99
@State private var presentation = Presentation.map
10-
@State private var needUpdateRecent = false
1110
@State private var showErrorAlert = false
1211
@State private var alertMessage = ""
1312
@State private var showFilters = false
@@ -189,7 +188,7 @@ private extension SportsGroundsMapView {
189188
coordinate: viewModel.region.center,
190189
cityID: defaults.mainUserCityID
191190
),
192-
refreshClbk: updateRecent
191+
refreshClbk: getNewSportsGround
193192
)
194193
}
195194
}
@@ -203,7 +202,7 @@ private extension SportsGroundsMapView {
203202
showDetailsView.toggle()
204203
}
205204

206-
func updateRecent() {
205+
func getNewSportsGround() {
207206
Task { await viewModel.checkForRecentUpdates(with: defaults) }
208207
}
209208

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

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,23 @@ import ShortAddressService
55

66
@MainActor
77
final class SportsGroundsMapViewModel: NSObject, ObservableObject {
8+
/// Дата предыдущего ручного обновления справочника площадок
9+
///
10+
/// - При обновлении справочника вручную необходимо обновить тут дату
11+
/// - Неудобно, зато спасаемся от постоянных ошибок 500 на сервере
12+
private let previousManualUpdateDateString = "2023-01-12T00:00:00"
13+
/// Менеджер локации
814
private let manager = CLLocationManager()
915
private let urlOpener: URLOpener = URLOpenerImp()
16+
/// Держит обновление фильтра площадок
1017
private var filterCancellable: AnyCancellable?
18+
/// Держит обновление ошибки определения геолокации
1119
private var locationErrorCancellable: AnyCancellable?
20+
/// Идентификатор страны пользователя
1221
private var userCountryID = Int.zero
22+
/// Идентификатор города пользователя
1323
private var userCityID = Int.zero
24+
/// Дефолтный список площадок, загруженный из `json`-файла
1425
private var defaultList = [SportsGround]()
1526
@Published private(set) var isLoading = false
1627
@Published private(set) var errorMessage = ""
@@ -43,6 +54,7 @@ final class SportsGroundsMapViewModel: NSObject, ObservableObject {
4354
}
4455
}
4556

57+
/// Заполняем/обновляем дефолтный список площадок
4658
func makeGrounds(refresh: Bool, with defaults: DefaultsProtocol) async {
4759
if isLoading || !defaultList.isEmpty, !refresh { return }
4860
if defaultList.isEmpty {
@@ -52,36 +64,38 @@ final class SportsGroundsMapViewModel: NSObject, ObservableObject {
5264
}
5365
isLoading.toggle()
5466
do {
55-
defaultList = try await APIService(with: defaults, needAuth: false).getAllSportsGrounds()
67+
let updatedGrounds = try await APIService(with: defaults, needAuth: false).getUpdatedSportsGrounds(
68+
from: previousManualUpdateDateString
69+
)
70+
updateDefaultList(with: updatedGrounds)
71+
applyFilter(with: defaults.mainUserInfo)
5672
} catch {
57-
fillDefaultList()
5873
errorMessage = ErrorFilterService.message(from: error)
5974
}
60-
applyFilter(with: defaults.mainUserInfo)
6175
isLoading.toggle()
6276
}
6377

78+
/// Проверяем недавние обновления списка площадок
79+
///
80+
/// Запрашиваем обновление за прошедшие 5 минут
6481
func checkForRecentUpdates(with defaults: DefaultsProtocol) async {
6582
if isLoading { return }
6683
isLoading.toggle()
6784
do {
6885
let updatedGrounds = try await APIService(with: defaults, needAuth: false).getUpdatedSportsGrounds(
69-
from: DateFormatterService.halfMinuteAgoDateString
86+
from: DateFormatterService.fiveMinutesAgoDateString
7087
)
71-
updatedGrounds.forEach { ground in
72-
if !defaultList.contains(ground) {
73-
defaultList.append(ground)
74-
} else if let index = sportsGrounds.firstIndex(where: { $0.id == ground.id }) {
75-
defaultList[index] = ground
76-
}
77-
}
88+
updateDefaultList(with: updatedGrounds)
7889
applyFilter(with: defaults.mainUserInfo)
7990
} catch {
8091
errorMessage = ErrorFilterService.message(from: error)
8192
}
8293
isLoading.toggle()
8394
}
8495

96+
/// Удаляет площадку с указанным идентификатором из списка
97+
///
98+
/// Используется при ручном удалении площадки с детального экрана площадки
8599
func deleteSportsGroundFromList(with groundID: Int) {
86100
sportsGrounds.removeAll(where: { $0.id == groundID })
87101
needUpdateAnnotations.toggle()
@@ -102,18 +116,22 @@ final class SportsGroundsMapViewModel: NSObject, ObservableObject {
102116
}
103117
}
104118

119+
/// Запускаем обновление локации пользователя
105120
func onAppearAction() { manager.startUpdatingLocation() }
106121

122+
/// Отключаем обновление локации пользователя
107123
func onDisappearAction() { manager.stopUpdatingLocation() }
108124

109125
func clearErrorMessage() { errorMessage = "" }
110126
}
111127

112128
extension SportsGroundsMapViewModel {
129+
/// `true` - регион пользователя установлен, `false` - не установлен
113130
var isRegionSet: Bool {
114131
region.center.latitude != .zero && region.center.longitude != .zero
115132
}
116133

134+
/// `true` - прячем карту, `false` - не прячем
117135
var shouldHideMap: Bool {
118136
!isRegionSet && ignoreUserLocation
119137
}
@@ -179,6 +197,7 @@ private extension SportsGroundsMapViewModel {
179197
applyFilter(userInfo?.countryID, userInfo?.cityID)
180198
}
181199

200+
/// Применяем фильтры к `defaultList` и выводим итоговый список в `sportsGrounds`
182201
func applyFilter(_ countryID: Int?, _ cityID: Int?) {
183202
DispatchQueue.global(qos: .utility).async { [weak self] in
184203
guard let self else { return }
@@ -207,6 +226,7 @@ private extension SportsGroundsMapViewModel {
207226
}
208227
}
209228

229+
/// Заполняем дефолтный список площадок контентом из `json`-файла
210230
func fillDefaultList() {
211231
do {
212232
let oldGrounds = try Bundle.main.decodeJson(
@@ -220,6 +240,17 @@ private extension SportsGroundsMapViewModel {
220240
}
221241
}
222242

243+
/// Обновляем дефолтный список площадок
244+
func updateDefaultList(with updatedList: [SportsGround]) {
245+
updatedList.forEach { ground in
246+
if let index = defaultList.firstIndex(where: { $0.id == ground.id }) {
247+
defaultList[index] = ground
248+
} else {
249+
defaultList.append(ground)
250+
}
251+
}
252+
}
253+
223254
func setupDefaultLocation(permissionDenied: Bool = false) {
224255
ignoreUserLocation = true
225256
locationErrorMessage = permissionDenied

SwiftUI-WorkoutApp/Services/APIService.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,10 @@ struct APIService {
206206
}
207207

208208
/// Загружает список всех площадок
209+
///
210+
/// Пока не используется, потому что:
211+
/// - сервер очень часто возвращает ошибку `500` при запросе всех площадок
212+
/// - справочник площадок хранится в `json`-файле и обновляется вручную
209213
/// - Returns: Список всех площадок
210214
func getAllSportsGrounds() async throws -> [SportsGround] {
211215
try await makeResult([SportsGround].self, for: Endpoint.getAllSportsGrounds.urlRequest(with: baseUrlString))

0 commit comments

Comments
 (0)