MinAgoTask.swift 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. // LoopFollow
  2. // MinAgoTask.swift
  3. import Foundation
  4. extension MainViewController {
  5. func scheduleMinAgoTask(initialDelay: TimeInterval = 1.0) {
  6. let firstRun = Date().addingTimeInterval(initialDelay)
  7. TaskScheduler.shared.scheduleTask(id: .minAgoUpdate, nextRun: firstRun) { [weak self] in
  8. guard let self = self else { return }
  9. self.minAgoTaskAction()
  10. }
  11. }
  12. func minAgoTaskAction() {
  13. guard bgData.count > 0, let lastBG = bgData.last else {
  14. DispatchQueue.main.async {
  15. Observable.shared.minAgoText.value = ""
  16. Observable.shared.bgText.value = ""
  17. }
  18. TaskScheduler.shared.rescheduleTask(id: .minAgoUpdate, to: Date().addingTimeInterval(1))
  19. return
  20. }
  21. let bgSeconds = lastBG.date
  22. let now = Date()
  23. let secondsAgo = now.timeIntervalSince1970 - bgSeconds
  24. let formatter = DateComponentsFormatter()
  25. formatter.unitsStyle = .positional
  26. formatter.zeroFormattingBehavior = .dropLeading
  27. let shouldDisplaySeconds = secondsAgo >= 270 && secondsAgo < 720 // 4.5 to 12 minutes
  28. if shouldDisplaySeconds {
  29. formatter.allowedUnits = [.minute, .second]
  30. } else {
  31. formatter.allowedUnits = [.minute]
  32. }
  33. let formattedDuration = formatter.string(from: secondsAgo) ?? ""
  34. let minAgoDisplayText = formattedDuration + " min ago"
  35. // Update UI only if the display text has changed
  36. if minAgoDisplayText != Observable.shared.minAgoText.value {
  37. DispatchQueue.main.async {
  38. Observable.shared.minAgoText.value = minAgoDisplayText
  39. }
  40. }
  41. let deltaTime = secondsAgo / 60
  42. Observable.shared.bgStale.value = deltaTime >= 12
  43. // Update badge based on staleness
  44. if Observable.shared.bgStale.value {
  45. updateBadge(val: 0)
  46. } else {
  47. updateBadge(val: Observable.shared.bg.value ?? 0)
  48. }
  49. // Determine the next run interval based on the current state
  50. let nextUpdateInterval: TimeInterval
  51. if shouldDisplaySeconds {
  52. // Update every second when showing seconds
  53. nextUpdateInterval = 1.0
  54. } else if secondsAgo >= 240, secondsAgo < 720 {
  55. // Schedule exactly at the transition point to start showing seconds
  56. nextUpdateInterval = 270.0 - secondsAgo
  57. } else {
  58. // Schedule exactly at the transition point to next minute
  59. let secondsToNextMinute = 60.0 - (secondsAgo.truncatingRemainder(dividingBy: 60.0))
  60. nextUpdateInterval = secondsToNextMinute
  61. }
  62. // Ensure the nextUpdateInterval is not negative or too small
  63. let safeNextInterval = max(nextUpdateInterval, 1.0)
  64. TaskScheduler.shared.rescheduleTask(id: .minAgoUpdate, to: Date().addingTimeInterval(safeNextInterval))
  65. }
  66. }