crossmate

A collaborative crossword app for iOS
Log | Files | Refs | LICENSE

LastUpdatedView.swift (2030B)


      1 import SwiftUI
      2 
      3 struct LastUpdatedView: View {
      4     let date: Date
      5     let usesRoomierType: Bool
      6 
      7     var body: some View {
      8         TimelineView(.lastUpdated(from: date)) { context in
      9             Text(text(now: context.date))
     10                 .font(usesRoomierType ? .footnote : .caption)
     11                 .foregroundStyle(.secondary)
     12         }
     13     }
     14 
     15     private func text(now: Date) -> String {
     16         let elapsed = max(0, now.timeIntervalSince(date))
     17         if elapsed < 60 {
     18             let seconds = max(1, Int(elapsed.rounded(.down)))
     19             return "Last updated \(seconds) \(seconds == 1 ? "second" : "seconds") ago"
     20         }
     21         if elapsed < 60 * 60 {
     22             let minutes = Int((elapsed / 60).rounded(.down))
     23             return "Last updated \(minutes) \(minutes == 1 ? "minute" : "minutes") ago"
     24         }
     25         if elapsed <= 48 * 60 * 60 {
     26             let hours = Int((elapsed / (60 * 60)).rounded(.down))
     27             return "Last updated \(hours) \(hours == 1 ? "hour" : "hours") ago"
     28         }
     29         return "Last updated on \(date.formatted(.dateTime.day().month(.abbreviated).year()))"
     30     }
     31 }
     32 
     33 private struct LastUpdatedSchedule: TimelineSchedule {
     34     let anchor: Date
     35 
     36     func entries(from startDate: Date, mode: TimelineScheduleMode) -> AnyIterator<Date> {
     37         var next = startDate
     38         return AnyIterator {
     39             let current = next
     40             let elapsed = max(0, current.timeIntervalSince(anchor))
     41             let step: TimeInterval
     42             if elapsed < 60 {
     43                 step = 1
     44             } else if elapsed < 60 * 60 {
     45                 step = 60
     46             } else if elapsed <= 48 * 60 * 60 {
     47                 step = 60 * 60
     48             } else {
     49                 return nil
     50             }
     51             next = current.addingTimeInterval(step)
     52             return current
     53         }
     54     }
     55 }
     56 
     57 extension TimelineSchedule where Self == LastUpdatedSchedule {
     58     static func lastUpdated(from date: Date) -> LastUpdatedSchedule {
     59         LastUpdatedSchedule(anchor: date)
     60     }
     61 }
     62