MinAgoTask.swift 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  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. self.latestMinAgoString = ""
  24. if let snoozer = self.tabBarController?.viewControllers?[2] as? SnoozeViewController {
  25. snoozer.MinAgoLabel.text = ""
  26. snoozer.BGLabel.text = ""
  27. snoozer.BGLabel.attributedText = NSAttributedString(string: "")
  28. }
  29. }
  30. TaskScheduler.shared.rescheduleTask(id: .minAgoUpdate, to: Date().addingTimeInterval(1))
  31. return
  32. }
  33. let bgSeconds = lastBG.date
  34. let now = Date()
  35. let secondsAgo = now.timeIntervalSince1970 - bgSeconds
  36. let formatter = DateComponentsFormatter()
  37. formatter.unitsStyle = .positional
  38. formatter.zeroFormattingBehavior = .dropLeading
  39. let shouldDisplaySeconds = secondsAgo >= 270 && secondsAgo < 720 // 4.5 to 12 minutes
  40. if shouldDisplaySeconds {
  41. formatter.allowedUnits = [.minute, .second]
  42. } else {
  43. formatter.allowedUnits = [.minute]
  44. }
  45. let formattedDuration = formatter.string(from: secondsAgo) ?? ""
  46. let minAgoDisplayText = formattedDuration + " min ago"
  47. // Update UI only if the display text has changed
  48. if minAgoDisplayText != latestMinAgoString {
  49. DispatchQueue.main.async { [weak self] in
  50. guard let self = self else { return }
  51. self.MinAgoText.text = minAgoDisplayText
  52. self.latestMinAgoString = minAgoDisplayText
  53. if let snoozer = self.tabBarController?.viewControllers?[2] as? SnoozeViewController {
  54. snoozer.MinAgoLabel.text = minAgoDisplayText
  55. let bgLabelText = snoozer.BGLabel.text ?? ""
  56. let attributeString = NSMutableAttributedString(string: bgLabelText)
  57. attributeString.addAttribute(.strikethroughStyle,
  58. value: NSUnderlineStyle.single.rawValue,
  59. range: NSRange(location: 0, length: attributeString.length))
  60. attributeString.addAttribute(.strikethroughColor,
  61. value: secondsAgo >= 720 ? UIColor.systemRed : UIColor.clear,
  62. range: NSRange(location: 0, length: attributeString.length))
  63. snoozer.BGLabel.attributedText = attributeString
  64. }
  65. }
  66. }
  67. // Determine the next run interval based on the current state
  68. let nextUpdateInterval: TimeInterval
  69. if shouldDisplaySeconds {
  70. nextUpdateInterval = 1.0 // Update every second when showing seconds
  71. } else if secondsAgo >= 720 {
  72. nextUpdateInterval = 60.0 // Update every minute when showing minutes only
  73. } else {
  74. // Schedule exactly at the transition point to start showing seconds
  75. nextUpdateInterval = 270.0 - secondsAgo
  76. }
  77. // Ensure the nextUpdateInterval is not negative or too small
  78. let safeNextInterval = max(nextUpdateInterval, 1.0)
  79. TaskScheduler.shared.rescheduleTask(id: .minAgoUpdate, to: Date().addingTimeInterval(safeNextInterval))
  80. }
  81. }