Skip to content

Commit 0002272

Browse files
committed
Implemented submitting the quest answers in the background
- updated syncDataToOSM method to responding back in same thread - removed holding realm objects in long duration - updated getChangesets API with predicate - removed dependancy of submitted state in answering quest - added new state syncBackground in answer quest - removed alerting user on success / failure cases of answer quests
1 parent 9d2fe61 commit 0002272

File tree

5 files changed

+49
-57
lines changed

5 files changed

+49
-57
lines changed

GoInfoGame/GoInfoGame/DataBase/DatabaseConnector.swift

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -326,15 +326,9 @@ class DatabaseConnector {
326326
/// - parameter synced: Optional variable of whether synced or non synced
327327
/// - Returns: an instance of `Results<StoredChangeset>`
328328
func getChangesets(synced: Bool = false) -> Results<StoredChangeset> {
329-
let results: Results<StoredChangeset>
330329
let realm = try! Realm(configuration: RealmConfig.configuration)
331-
if synced {
332-
results = realm.objects(StoredChangeset.self).where { $0.changesetId != -1 }
333-
} else {
334-
results = realm.objects(StoredChangeset.self).where { $0.changesetId == -1 }
335-
}
336-
print("Found \(results.count) changesets for synced=\(synced)")
337-
return results
330+
let predicateString = synced ? "updatedVersion != -1" : "updatedVersion == -1"
331+
return realm.objects(StoredChangeset.self).filter(NSPredicate(format: predicateString))
338332
}
339333

340334
func getChangeset(for id: String) -> StoredChangeset? {

GoInfoGame/GoInfoGame/UI/Map/MapView.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,13 @@ struct MapView: View {
220220
.toolbar {
221221

222222
ToolbarItem(placement: .navigationBarTrailing) {
223-
QuestSyncButton(badgeCount: 0, isSyncing: isSyncing, action: {
223+
QuestSyncButton(badgeCount: viewModel.syncFailedElementsCount, isSyncing: isSyncing, action: {
224224
debugPrint("Sync taped")
225+
isSyncing = true
226+
DatasyncManager.shared.syncDataToOSM(exclude_gig_tags: false) { _ in
227+
isSyncing = false
228+
viewModel.checkSyncStatus()
229+
}
225230
})
226231
.frame(width: 20, height: 20)
227232
.foregroundStyle(Color("theme"))
@@ -424,23 +429,15 @@ struct MapView: View {
424429
switch scenario {
425430
case .dismissed:
426431
shouldShowPolyline = false
427-
case .submitted(let elementId):
428-
shouldShowPolyline = false
429-
showAlert = true
430-
alertMessage = "Quest Submitted"
431-
viewModel.refreshMapAfterSubmission(elementId: elementId)
432432
case .syncing:
433433
isSyncing = true
434434
print("syncing")
435435
case .synced:
436436
isSyncing = false
437437
print("synced")
438-
alertIcon = "checkmark.circle.fill"
439438
case .failed(let message):
440439
isSyncing = false
441-
alertIcon = "exclamationmark.triangle.fill"
442-
alertMessage = message
443-
showAlert = true
440+
viewModel.checkSyncStatus()
444441
case .hideElement(let elementId, let elementName):
445442
shouldShowPolyline = false
446443
viewModel.hideQuest(elementId: elementId, elementName: elementName)
@@ -449,6 +446,9 @@ struct MapView: View {
449446
showAlert = true
450447
alertMessage = "Changes reverted"
451448
viewModel.refreshMapAfterUndoSumbit(storedChangesetId: changesetId)
449+
case .syncBackground(let elementID):
450+
shouldShowPolyline = false
451+
viewModel.refreshMapAfterSubmission(elementId: elementID)
452452
}
453453
}
454454
.onReceive(QuestsPublisher.shared.refreshQuest, perform: { _ in
@@ -565,12 +565,12 @@ public class QuestsPublisher: ObservableObject {
565565

566566
public enum SheetDismissalScenario {
567567
case dismissed
568-
case submitted(String)
569568
case syncing
570569
case synced
571570
case failed(String)
572571
case hideElement(String, String)
573572
case undoDone(String)
573+
case syncBackground(Int)
574574
}
575575

576576
//TODO: Move to a new file

GoInfoGame/GoInfoGame/UI/Map/MapViewModel.swift

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class MapViewModel: ObservableObject {
4141
@Published var availableOptions: [SatelliteOption] = []
4242
@Published var selectedOption: SatelliteOption = .none
4343
@Published var showSatellitePicker: Bool = false
44+
@Published private(set) var syncFailedElementsCount: Int = 0
4445

4546
init(mapRepo: MapRepositoryProtocol = MapRepository()) {
4647
self.mapRepo = mapRepo
@@ -55,8 +56,13 @@ class MapViewModel: ObservableObject {
5556
Task {
5657
self.allSattileLayers = try await self.mapRepo.fetchAvailableServers()
5758
}
59+
checkSyncStatus()
5860
}
5961

62+
func checkSyncStatus() {
63+
self.syncFailedElementsCount = dbInstance.getChangesets(synced: false).count
64+
}
65+
6066
func sattiliteServersFor(point: CLLocationCoordinate2D) -> [SatelliteServer] {
6167
return allSattileLayers.filter{ $0.extent.isPointInsideBoundary(point)}
6268
}
@@ -157,21 +163,10 @@ class MapViewModel: ObservableObject {
157163
self.items = AppQuestManager.shared.fetchQuestsFromDB()
158164
}
159165

160-
func refreshMapAfterSubmission(elementId: String) {
161-
162-
// if let newItem = AppQuestManager.shared.getUpdatedQuest(elementId: elementId) {
163-
// let toReplace = self.items.first(where: {$0.id == Int(elementId)!})
164-
// let index = self.items.firstIndex(where: {$0.id == Int(elementId)!})
165-
//
166-
// self.items.remove(at: index!)
167-
// self.items.insert(newItem, at: index!)
168-
// }
169-
// else{
170-
if let toReplace = self.items.first(where: {$0.id == Int(elementId)!}) {
171-
let index = self.items.firstIndex(where: {$0.id == Int(elementId)!})
172-
self.items.remove(at: index!)
173-
}
174-
// }
166+
func refreshMapAfterSubmission(elementId: Int) {
167+
if let index = self.items.firstIndex(where: {$0.id == elementId}) {
168+
self.items.remove(at: index)
169+
}
175170
}
176171

177172
// The item may have been already resolved or changed.

GoInfoGame/GoInfoGame/data/DatasyncManager.swift

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ class DatasyncManager {
2121
private let barrierQueue: DispatchQueue = DispatchQueue(label: "com.goinfogame.DatasyncManager.barrierQueue", attributes: .concurrent)
2222

2323
func syncDataToOSM(exclude_gig_tags: Bool, completionHandler: @escaping (Result<Bool, APIError>) -> Void) {
24+
let currentQueue = OperationQueue.current?.underlyingQueue ?? .main
25+
2426
barrierQueue.async(flags: .barrier) { [weak self] in
2527
guard let self = self else { return }
2628
let semaphore = DispatchSemaphore(value: 0)
@@ -30,16 +32,20 @@ class DatasyncManager {
3032
let isSynced = try await self.syncData(exclude_gig_tags: exclude_gig_tags)
3133

3234
print("Sync finished")
33-
if isSynced {
34-
print("Sync successful")
35-
completionHandler(.success(true)) // Success
36-
} else {
37-
print("Sync failed")
38-
completionHandler(.failure(APIError.custom("Sync failed. Please try again."))) // Failure
35+
currentQueue.async {
36+
if isSynced {
37+
print("Sync successful")
38+
completionHandler(.success(true)) // Success
39+
} else {
40+
print("Sync failed")
41+
completionHandler(.failure(APIError.custom("Sync failed. Please try again."))) // Failure
42+
}
3943
}
4044
} catch {
41-
print("Sync failed: \(error)")
42-
completionHandler(.failure(error as! APIError)) // Failure
45+
currentQueue.async {
46+
print("Sync failed: \(error)")
47+
completionHandler(.failure(error as! APIError)) // Failure
48+
}
4349
}
4450
semaphore.signal()
4551
}
@@ -79,14 +85,14 @@ class DatasyncManager {
7985

8086
print("📦 Found \(validChangesets.count) unsynced changesets with valid edits")
8187

82-
var nodesToSync: [String: StoredChangeset] = [:]
83-
var waysToSync: [String: StoredChangeset] = [:]
88+
var nodesToSync: [String: OSMNode] = [:]
89+
var waysToSync: [String: OSMWay] = [:]
8490

8591
for cs in validChangesets {
8692
if cs.elementType == .node {
87-
nodesToSync[cs.id] = cs
93+
nodesToSync[cs.id] = cs.asOSMNode()
8894
} else if cs.elementType == .way {
89-
waysToSync[cs.id] = cs
95+
waysToSync[cs.id] = cs.asOSMWay()
9096
}
9197
}
9298

@@ -98,10 +104,10 @@ class DatasyncManager {
98104
}
99105

100106
for (key, node) in nodesToSync {
101-
print("📤 Syncing node ID: \(node.id)")
102-
let payload = node.asOSMNode()
107+
// print("📤 Syncing node ID: \(node.id)")
108+
let payload = node
103109
do {
104-
let status = try await syncNode(node: payload, exclude_gig_tags: exclude_gig_tags, editedTags: node.tags.toDictionary())
110+
let status = try await syncNode(node: payload, exclude_gig_tags: exclude_gig_tags, editedTags: node.tags)
105111
if status.result {
106112
_ = self.dbInstance.assignChangesetId(obj: key, changesetId: 0, updatedVersion: status.version)
107113
print("✅ Node sync finished: \(payload.id)")
@@ -117,10 +123,10 @@ class DatasyncManager {
117123
}
118124

119125
for (key, way) in waysToSync {
120-
print("📤 Syncing way ID: \(way.id)")
121-
let payload = way.asOSMWay()
126+
// print("📤 Syncing way ID: \(way.id)")
127+
let payload = way
122128
do {
123-
let status = try await syncWay(way: payload, exclude_gig_tags: exclude_gig_tags, editedTags: way.tags.toDictionary())
129+
let status = try await syncWay(way: payload, exclude_gig_tags: exclude_gig_tags, editedTags: way.tags)
124130
if status.result {
125131
_ = self.dbInstance.assignChangesetId(obj: key, changesetId: 0, updatedVersion: status.version)
126132
print("✅ Way sync finished: \(payload.id)")

GoInfoGame/GoInfoGame/quests/QuestProtocols.swift

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,18 +104,15 @@ class QuestBase {
104104

105105
// Dismiss sheet after syncing to db
106106
MapViewPublisher.shared.dismissSheet.send(.syncing)
107+
MapViewPublisher.shared.dismissSheet.send(.syncBackground(Int(id)))
107108

108109
DatasyncManager.shared.syncDataToOSM(exclude_gig_tags: exclude_gig_tags) { success in
109110
DispatchQueue.main.async {
110111
MapViewPublisher.shared.dismissSheet.send(.synced)
111112

112113
switch success {
113114
case .success(let success):
114-
if success {
115-
116-
MapViewPublisher.shared.dismissSheet.send(.submitted("\(id)"))
117-
}
118-
else {
115+
if !success {
119116
print("Sync failed. Handle accordingly.")
120117
MapViewPublisher.shared.dismissSheet.send(.failed("Submission failed. Please try again."))
121118
}

0 commit comments

Comments
 (0)