mirror of
https://github.com/yattee/yattee.git
synced 2026-10-23 13:12:53 +00:00
MAC6: a snapshot mutation carries its video count back to the list cache. MAC8: playlist rows and cards are Buttons with the context menu attached, so macOS accessibility can reach Edit and Delete. MAC10: a published date stamped with the request's own time is dropped at both API sentinels, and formattedPublishedDate refuses zero-interval output. MAC11: a failed history hydration shows Details unavailable with a Try Again action instead of keeping the raw video ID forever; an empty 200 body is a legible failure.
53 lines
2.1 KiB
Swift
53 lines
2.1 KiB
Swift
//
|
|
// RelativeDateFormatter.swift
|
|
// Yattee
|
|
//
|
|
// Centralized utility for formatting relative dates with "just now" support.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
/// Utility for formatting dates relative to now, with proper handling of very recent times.
|
|
enum RelativeDateFormatter {
|
|
/// Formats a date relative to now, showing "just now" for very recent dates.
|
|
/// - Parameters:
|
|
/// - date: The date to format
|
|
/// - justNowThreshold: Seconds within which to show "just now" (default: 10)
|
|
/// - unitsStyle: The style for the relative date formatter (default: .abbreviated)
|
|
/// - Returns: Formatted string (e.g., "just now", "5 min ago", "2 hours ago")
|
|
static func string(
|
|
for date: Date,
|
|
justNowThreshold: TimeInterval = 10,
|
|
unitsStyle: RelativeDateTimeFormatter.UnitsStyle = .abbreviated
|
|
) -> String {
|
|
let interval = Date().timeIntervalSince(date)
|
|
|
|
if interval < justNowThreshold {
|
|
return String(localized: "common.justNow")
|
|
}
|
|
|
|
let formatter = RelativeDateTimeFormatter()
|
|
formatter.unitsStyle = unitsStyle
|
|
return formatter.localizedString(for: date, relativeTo: Date())
|
|
}
|
|
|
|
/// Whether a date is so close to now that a relative rendering of it reads
|
|
/// "in 0 seconds".
|
|
static func isEffectivelyNow(_ date: Date, tolerance: TimeInterval = 1) -> Bool {
|
|
abs(Date().timeIntervalSince(date)) < tolerance
|
|
}
|
|
|
|
/// Whether a publication date is the stamp an instance writes when it has
|
|
/// none to send.
|
|
///
|
|
/// Invidious answers `published` with the moment it replied — and
|
|
/// `publishedText` with "0 seconds ago" — for a video whose upload date it
|
|
/// could not read, which renders as "in 0 seconds"; a scraping Piped does
|
|
/// the same with `uploaded`. Read with a minute of slack, because the
|
|
/// clocks at the two ends of a request are not the same clock, and because
|
|
/// nothing reaches a listing within a minute of being published.
|
|
static func isStampedNow(_ date: Date, tolerance: TimeInterval = 60) -> Bool {
|
|
Date().timeIntervalSince(date) < tolerance
|
|
}
|
|
}
|