Stabilize iOS/watchOS/tvOS apps and add cross-platform audit remediation

This commit is contained in:
Trey t
2026-02-11 12:54:40 -06:00
parent e40275e694
commit acce712261
77 changed files with 2940 additions and 765 deletions

View File

@@ -9,6 +9,67 @@ import Foundation
import UIKit
import SwiftUI
private enum DateFormatterCache {
static let lock = NSLock()
static let serverDateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssX"
formatter.locale = Locale(identifier: "en_US_POSIX")
return formatter
}()
static let plannedDateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
formatter.locale = Locale(identifier: "en_US_POSIX")
return formatter
}()
static let weekDayFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "EEE"
formatter.locale = Locale(identifier: "en_US_POSIX")
return formatter
}()
static let monthFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "MMM"
formatter.locale = Locale(identifier: "en_US_POSIX")
return formatter
}()
static let dayFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "d"
formatter.locale = Locale(identifier: "en_US_POSIX")
return formatter
}()
static func withLock<T>(_ block: () -> T) -> T {
lock.lock()
defer { lock.unlock() }
return block()
}
}
private enum DurationFormatterCache {
static let lock = NSLock()
static let formatter: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.hour, .minute, .second, .nanosecond]
return formatter
}()
static func string(from seconds: Double, style: DateComponentsFormatter.UnitsStyle) -> String {
lock.lock()
defer { lock.unlock() }
formatter.unitsStyle = style
return formatter.string(from: seconds) ?? ""
}
}
extension Dictionary {
func percentEncoded() -> Data? {
map { key, value in
@@ -34,25 +95,23 @@ extension CharacterSet {
extension Date {
var timeFormatForUpload: String {
let isoFormatter = DateFormatter()
isoFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssX"
return isoFormatter.string(from: self)
DateFormatterCache.withLock {
DateFormatterCache.serverDateFormatter.string(from: self)
}
}
}
extension String {
var dateFromServerDate: Date? {
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd'T'HH:mm:ssX"
df.locale = Locale(identifier: "en_US_POSIX")
return df.date(from: self)
DateFormatterCache.withLock {
DateFormatterCache.serverDateFormatter.date(from: self)
}
}
var plannedDate: Date? {
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd"
df.locale = Locale(identifier: "en_US_POSIX")
return df.date(from: self)
DateFormatterCache.withLock {
DateFormatterCache.plannedDateFormatter.date(from: self)
}
}
}
@@ -66,31 +125,27 @@ extension Date {
}
var formatForPlannedWorkout: String {
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd"
df.locale = Locale(identifier: "en_US_POSIX")
return df.string(from: self)
DateFormatterCache.withLock {
DateFormatterCache.plannedDateFormatter.string(from: self)
}
}
var weekDay: String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEE"
let weekDay = dateFormatter.string(from: self)
return weekDay
DateFormatterCache.withLock {
DateFormatterCache.weekDayFormatter.string(from: self)
}
}
var monthString: String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM"
let weekDay = dateFormatter.string(from: self)
return weekDay
DateFormatterCache.withLock {
DateFormatterCache.monthFormatter.string(from: self)
}
}
var dateString: String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "d"
let weekDay = dateFormatter.string(from: self)
return weekDay
DateFormatterCache.withLock {
DateFormatterCache.dayFormatter.string(from: self)
}
}
}
@@ -116,10 +171,7 @@ extension Double {
10000.asString(style: .brief) // 2hr 46min 40sec
*/
func asString(style: DateComponentsFormatter.UnitsStyle) -> String {
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.hour, .minute, .second, .nanosecond]
formatter.unitsStyle = style
return formatter.string(from: self) ?? ""
DurationFormatterCache.string(from: self, style: style)
}
}