MinAgoTask.swift 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. //
  2. // MinAgoTask.swift
  3. // LoopFollow
  4. //
  5. // Created by Jonas Björkert on 2025-01-11.
  6. // Copyright © 2025 Jon Fawcett. All rights reserved.
  7. //
  8. import Foundation
  9. import UIKit
  10. extension MainViewController {
  11. func scheduleMinAgoTask(initialDelay: TimeInterval = 1.0) {
  12. let firstRun = Date().addingTimeInterval(initialDelay)
  13. TaskScheduler.shared.scheduleTask(id: .minAgoUpdate, nextRun: firstRun) { [weak self] in
  14. guard let self = self else { return }
  15. self.minAgoTaskAction()
  16. }
  17. }
  18. func minAgoTaskAction() {
  19. guard bgData.count > 0, let lastBG = bgData.last else {
  20. DispatchQueue.main.async { [weak self] in
  21. guard let self = self else { return }
  22. self.MinAgoText.text = ""
  23. Observable.shared.minAgoText.value = ""
  24. Observable.shared.bgText.value = ""
  25. /* TODO:
  26. if let snoozer = self.tabBarController?.viewControllers?[2] as? SnoozeViewController {
  27. snoozer.BGLabel.attributedText = NSAttributedString(string: "")
  28. }
  29. */
  30. }
  31. TaskScheduler.shared.rescheduleTask(id: .minAgoUpdate, to: Date().addingTimeInterval(1))
  32. return
  33. }
  34. let bgSeconds = lastBG.date
  35. let now = Date()
  36. let secondsAgo = now.timeIntervalSince1970 - bgSeconds
  37. let formatter = DateComponentsFormatter()
  38. formatter.unitsStyle = .positional
  39. formatter.zeroFormattingBehavior = .dropLeading
  40. let shouldDisplaySeconds = secondsAgo >= 270 && secondsAgo < 720 // 4.5 to 12 minutes
  41. if shouldDisplaySeconds {
  42. formatter.allowedUnits = [.minute, .second]
  43. } else {
  44. formatter.allowedUnits = [.minute]
  45. }
  46. let formattedDuration = formatter.string(from: secondsAgo) ?? ""
  47. let minAgoDisplayText = formattedDuration + " min ago"
  48. // Update UI only if the display text has changed
  49. if minAgoDisplayText != Observable.shared.minAgoText.value {
  50. DispatchQueue.main.async { [weak self] in
  51. guard let self = self else { return }
  52. self.MinAgoText.text = minAgoDisplayText
  53. Observable.shared.minAgoText.value = minAgoDisplayText
  54. /* TODO:
  55. if let snoozer = self.tabBarController?.viewControllers?[2] as? SnoozeViewController {
  56. let bgLabelText = snoozer.BGLabel.text ?? ""
  57. let attributeString = NSMutableAttributedString(string: bgLabelText)
  58. attributeString.addAttribute(.strikethroughStyle,
  59. value: NSUnderlineStyle.single.rawValue,
  60. range: NSRange(location: 0, length: attributeString.length))
  61. attributeString.addAttribute(.strikethroughColor,
  62. value: secondsAgo >= 720 ? UIColor.systemRed : UIColor.clear,
  63. range: NSRange(location: 0, length: attributeString.length))
  64. snoozer.BGLabel.attributedText = attributeString
  65. }
  66. */
  67. }
  68. }
  69. // Determine the next run interval based on the current state
  70. let nextUpdateInterval: TimeInterval
  71. if shouldDisplaySeconds {
  72. // Update every second when showing seconds
  73. nextUpdateInterval = 1.0
  74. } else if secondsAgo >= 240, secondsAgo < 720 {
  75. // Schedule exactly at the transition point to start showing seconds
  76. nextUpdateInterval = 270.0 - secondsAgo
  77. } else {
  78. // Schedule exactly at the transition point to next minute
  79. let secondsToNextMinute = 60.0 - (secondsAgo.truncatingRemainder(dividingBy: 60.0))
  80. nextUpdateInterval = secondsToNextMinute
  81. }
  82. // Ensure the nextUpdateInterval is not negative or too small
  83. let safeNextInterval = max(nextUpdateInterval, 1.0)
  84. TaskScheduler.shared.rescheduleTask(id: .minAgoUpdate, to: Date().addingTimeInterval(safeNextInterval))
  85. }
  86. }