MinAgoTask.swift 4.1 KB

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