diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c9675b06c..8b8ba29a73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Update podcast list when episode is archived or marked as played from player [#1976](https://github.com/Automattic/pocket-casts-ios/issues/1976) - Dismiss search if already active when double tap is performed on tab bar [#1652](https://github.com/Automattic/pocket-casts-ios/issues/1652) - Show transcript for episodes that support it [#2102](https://github.com/Automattic/pocket-casts-ios/issues/2102) +- Add a check to prevent stats from decreasing [#2106](https://github.com/Automattic/pocket-casts-ios/issues/2106) 7.71 ----- diff --git a/Modules/Server/Sources/PocketCastsServer/Public/StatsManager.swift b/Modules/Server/Sources/PocketCastsServer/Public/StatsManager.swift index b6b9531589..d9de62c2f4 100644 --- a/Modules/Server/Sources/PocketCastsServer/Public/StatsManager.swift +++ b/Modules/Server/Sources/PocketCastsServer/Public/StatsManager.swift @@ -36,7 +36,7 @@ public class StatsManager { public func addTimeSavedDynamicSpeed(_ seconds: TimeInterval) { updateQueue.async { [weak self] in - self?.savedDynamicSpeed += seconds + self?.savedDynamicSpeed += max(seconds, 0) self?.isSynced = false } } @@ -49,7 +49,7 @@ public class StatsManager { public func addTimeSavedVariableSpeed(_ seconds: TimeInterval) { updateQueue.async { [weak self] in - self?.savedVariableSpeed += seconds + self?.savedVariableSpeed += max(seconds, 0) self?.isSynced = false } } @@ -62,7 +62,7 @@ public class StatsManager { public func addTotalListeningTime(_ seconds: TimeInterval) { updateQueue.async { [weak self] in - self?.totalListenedTo += seconds + self?.totalListenedTo += max(seconds, 0) self?.isSynced = false } } @@ -75,7 +75,7 @@ public class StatsManager { public func addSkippedTime(_ seconds: TimeInterval) { updateQueue.async { [weak self] in - self?.totalSkipped += seconds + self?.totalSkipped += max(seconds, 0) self?.isSynced = false } } @@ -88,7 +88,7 @@ public class StatsManager { public func addAutoSkipTime(_ seconds: TimeInterval) { updateQueue.async { [weak self] in - self?.savedAutoSkipping += seconds + self?.savedAutoSkipping += max(seconds, 0) self?.isSynced = false } } @@ -216,7 +216,7 @@ public class StatsManager { } private func saveTime(_ time: TimeInterval, key: String) { - if time < 0 { return } + if time < 0, time < timeForKey(key) { return } UserDefaults.standard.set(time, forKey: key) } diff --git a/Modules/Server/Sources/PocketCastsServer/Public/Sync/SyncTask+LocalChanges.swift b/Modules/Server/Sources/PocketCastsServer/Public/Sync/SyncTask+LocalChanges.swift index 10371d45ab..33bba9309d 100644 --- a/Modules/Server/Sources/PocketCastsServer/Public/Sync/SyncTask+LocalChanges.swift +++ b/Modules/Server/Sources/PocketCastsServer/Public/Sync/SyncTask+LocalChanges.swift @@ -157,24 +157,23 @@ extension SyncTask { } func changedStats() -> Api_Record? { - let timeSavedDynamicSpeed = convertStat(StatsManager.shared.timeSavedDynamicSpeed()) - let totalSkippedTime = convertStat(StatsManager.shared.totalSkippedTime()) - let totalIntroSkippedTime = convertStat(StatsManager.shared.totalAutoSkippedTime()) - let timeSavedVariableSpeed = convertStat(StatsManager.shared.timeSavedVariableSpeed()) - let totalListeningTime = convertStat(StatsManager.shared.totalListeningTime()) - let startSyncTime = Int64(StatsManager.shared.statsStartDate().timeIntervalSince1970) - - // check to see if there's actually any stats we need to sync - if StatsManager.shared.syncStatus() != .notSynced || (timeSavedDynamicSpeed == nil && totalSkippedTime == nil && totalSkippedTime == nil && timeSavedVariableSpeed == nil && totalListeningTime == nil) { + guard StatsManager.shared.syncStatus() == .notSynced, + let timeSavedDynamicSpeed = convertStat(StatsManager.shared.timeSavedDynamicSpeed()), + let totalSkippedTime = convertStat(StatsManager.shared.totalSkippedTime()), + let totalIntroSkippedTime = convertStat(StatsManager.shared.totalAutoSkippedTime()), + let timeSavedVariableSpeed = convertStat(StatsManager.shared.timeSavedVariableSpeed()), + let totalListeningTime = convertStat(StatsManager.shared.totalListeningTime()) else { return nil } + let startSyncTime = Int64(StatsManager.shared.statsStartDate().timeIntervalSince1970) + var deviceRecord = Api_SyncUserDevice() - deviceRecord.timeSilenceRemoval.value = timeSavedDynamicSpeed ?? 0 - deviceRecord.timeSkipping.value = totalSkippedTime ?? 0 - deviceRecord.timeIntroSkipping.value = totalIntroSkippedTime ?? 0 - deviceRecord.timeVariableSpeed.value = timeSavedVariableSpeed ?? 0 - deviceRecord.timeListened.value = totalListeningTime ?? 0 + deviceRecord.timeSilenceRemoval.value = timeSavedDynamicSpeed + deviceRecord.timeSkipping.value = totalSkippedTime + deviceRecord.timeIntroSkipping.value = totalIntroSkippedTime + deviceRecord.timeVariableSpeed.value = timeSavedVariableSpeed + deviceRecord.timeListened.value = totalListeningTime deviceRecord.timesStartedAt.value = startSyncTime deviceRecord.deviceID.value = ServerConfig.shared.syncDelegate?.uniqueAppId() ?? "" deviceRecord.deviceType.value = ServerConstants.Values.deviceTypeiOS