mirror of
				https://github.com/maxgoedjen/secretive.git
				synced 2025-11-04 01:10:56 +00:00 
			
		
		
		
	Break up Brief + Document (#311)
This commit is contained in:
		
							parent
							
								
									eb282b4116
								
							
						
					
					
						commit
						da2c460c60
					
				@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					# ``Brief``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Brief is a collection of protocols and concrete implmentation describing updates.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Topics
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Versioning
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- ``SemVer``
 | 
				
			||||||
 | 
					- ``Release``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Updater
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- ``UpdaterProtocol``
 | 
				
			||||||
 | 
					- ``Updater``
 | 
				
			||||||
							
								
								
									
										80
									
								
								Sources/Packages/Sources/Brief/Release.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								Sources/Packages/Sources/Brief/Release.swift
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,80 @@
 | 
				
			|||||||
 | 
					import Foundation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// A release is a representation of a downloadable update.
 | 
				
			||||||
 | 
					public struct Release: Codable {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// The user-facing name of the release. Typically "Secretive 1.2.3"
 | 
				
			||||||
 | 
					    public let name: String
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// A boolean describing whether or not the release is a prerelase build.
 | 
				
			||||||
 | 
					    public let prerelease: Bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// A URL pointing to the HTML page for the release.
 | 
				
			||||||
 | 
					    public let html_url: URL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// A user-facing description of the contents of the update.
 | 
				
			||||||
 | 
					    public let body: String
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Initializes a Release.
 | 
				
			||||||
 | 
					    /// - Parameters:
 | 
				
			||||||
 | 
					    ///   - name: The user-facing name of the release.
 | 
				
			||||||
 | 
					    ///   - prerelease: A boolean describing whether or not the release is a prerelase build.
 | 
				
			||||||
 | 
					    ///   - html_url: A URL pointing to the HTML page for the release.
 | 
				
			||||||
 | 
					    ///   - body: A user-facing description of the contents of the update.
 | 
				
			||||||
 | 
					    public init(name: String, prerelease: Bool, html_url: URL, body: String) {
 | 
				
			||||||
 | 
					        self.name = name
 | 
				
			||||||
 | 
					        self.prerelease = prerelease
 | 
				
			||||||
 | 
					        self.html_url = html_url
 | 
				
			||||||
 | 
					        self.body = body
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extension Release: Identifiable {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public var id: String {
 | 
				
			||||||
 | 
					        html_url.absoluteString
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extension Release: Comparable {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static func < (lhs: Release, rhs: Release) -> Bool {
 | 
				
			||||||
 | 
					        lhs.version < rhs.version
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extension Release {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// A boolean describing whether or not the release contains critical security content.
 | 
				
			||||||
 | 
					    /// - Note: this is determined by the presence of the phrase "Critical Security Update" in the ``body``.
 | 
				
			||||||
 | 
					    /// - Warning: If this property is true, the user will not be able to dismiss UI or reminders associated with the update.
 | 
				
			||||||
 | 
					    public var critical: Bool {
 | 
				
			||||||
 | 
					        body.contains(Constants.securityContent)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// A ``SemVer`` representation of the version number of the release.
 | 
				
			||||||
 | 
					    public var version: SemVer {
 | 
				
			||||||
 | 
					        SemVer(name)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// The minimum macOS version required to run the update.
 | 
				
			||||||
 | 
					    public var minimumOSVersion: SemVer {
 | 
				
			||||||
 | 
					        guard let range = body.range(of: "Minimum macOS Version"),
 | 
				
			||||||
 | 
					              let numberStart = body.rangeOfCharacter(from: CharacterSet.decimalDigits, options: [], range: range.upperBound..<body.endIndex) else { return SemVer("11.0.0") }
 | 
				
			||||||
 | 
					        let numbersEnd = body.rangeOfCharacter(from: CharacterSet.whitespacesAndNewlines, options: [], range: numberStart.upperBound..<body.endIndex)?.lowerBound ?? body.endIndex
 | 
				
			||||||
 | 
					        let version = numberStart.lowerBound..<numbersEnd
 | 
				
			||||||
 | 
					        return SemVer(String(body[version]))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extension Release {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum Constants {
 | 
				
			||||||
 | 
					        static let securityContent = "Critical Security Update"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										43
									
								
								Sources/Packages/Sources/Brief/SemVer.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								Sources/Packages/Sources/Brief/SemVer.swift
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					import Foundation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// A representation of a Semantic Version.
 | 
				
			||||||
 | 
					public struct SemVer {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// The SemVer broken into an array of integers.
 | 
				
			||||||
 | 
					    let versionNumbers: [Int]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Initializes a SemVer from a string representation.
 | 
				
			||||||
 | 
					    /// - Parameter version: A string representation of the SemVer, formatted as "major.minor.patch".
 | 
				
			||||||
 | 
					    public init(_ version: String) {
 | 
				
			||||||
 | 
					        // Betas have the format 1.2.3_beta1
 | 
				
			||||||
 | 
					        let strippedBeta = version.split(separator: "_").first!
 | 
				
			||||||
 | 
					        var split = strippedBeta.split(separator: ".").compactMap { Int($0) }
 | 
				
			||||||
 | 
					        while split.count < 3 {
 | 
				
			||||||
 | 
					            split.append(0)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        versionNumbers = split
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Initializes a SemVer from an ``OperatingSystemVersion`` representation.
 | 
				
			||||||
 | 
					    /// - Parameter version: An  ``OperatingSystemVersion`` representation of the SemVer.
 | 
				
			||||||
 | 
					    public init(_ version: OperatingSystemVersion) {
 | 
				
			||||||
 | 
					        versionNumbers = [version.majorVersion, version.minorVersion, version.patchVersion]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extension SemVer: Comparable {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static func < (lhs: SemVer, rhs: SemVer) -> Bool {
 | 
				
			||||||
 | 
					        for (latest, current) in zip(lhs.versionNumbers, rhs.versionNumbers) {
 | 
				
			||||||
 | 
					            if latest < current {
 | 
				
			||||||
 | 
					                return true
 | 
				
			||||||
 | 
					            } else if latest > current {
 | 
				
			||||||
 | 
					                return false
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,22 +1,24 @@
 | 
				
			|||||||
import Foundation
 | 
					import Foundation
 | 
				
			||||||
import Combine
 | 
					import Combine
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public protocol UpdaterProtocol: ObservableObject {
 | 
					/// A concrete implementation of ``UpdaterProtocol`` which considers the current release and OS version.
 | 
				
			||||||
 | 
					 | 
				
			||||||
    var update: Release? { get }
 | 
					 | 
				
			||||||
    var testBuild: Bool { get }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class Updater: ObservableObject, UpdaterProtocol {
 | 
					public class Updater: ObservableObject, UpdaterProtocol {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Published public var update: Release?
 | 
					    @Published public var update: Release?
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    public let testBuild: Bool
 | 
					    public let testBuild: Bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// The current OS version.
 | 
				
			||||||
    private let osVersion: SemVer
 | 
					    private let osVersion: SemVer
 | 
				
			||||||
 | 
					    /// The current version of the app that is running.
 | 
				
			||||||
    private let currentVersion: SemVer
 | 
					    private let currentVersion: SemVer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public init(checkOnLaunch: Bool, osVersion: SemVer = SemVer(ProcessInfo.processInfo.operatingSystemVersion), currentVersion: SemVer = SemVer(Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "0.0.0")) {
 | 
					    /// Initializes an Updater.
 | 
				
			||||||
 | 
					    /// - Parameters:
 | 
				
			||||||
 | 
					    ///   - checkOnLaunch: A boolean describing whether the Updater should check for available updates on launch.
 | 
				
			||||||
 | 
					    ///   - checkFrequency: The interval at which the Updater should check for updates. Subject to a tolerance of 1 hour.
 | 
				
			||||||
 | 
					    ///   - osVersion: The current OS version.
 | 
				
			||||||
 | 
					    ///   - currentVersion: The current version of the app that is running.
 | 
				
			||||||
 | 
					    public init(checkOnLaunch: Bool, checkFrequency: TimeInterval = Measurement(value: 24, unit: UnitDuration.hours).converted(to: .seconds).value, osVersion: SemVer = SemVer(ProcessInfo.processInfo.operatingSystemVersion), currentVersion: SemVer = SemVer(Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "0.0.0")) {
 | 
				
			||||||
        self.osVersion = osVersion
 | 
					        self.osVersion = osVersion
 | 
				
			||||||
        self.currentVersion = currentVersion
 | 
					        self.currentVersion = currentVersion
 | 
				
			||||||
        testBuild = currentVersion == SemVer("0.0.0")
 | 
					        testBuild = currentVersion == SemVer("0.0.0")
 | 
				
			||||||
@ -24,12 +26,13 @@ public class Updater: ObservableObject, UpdaterProtocol {
 | 
				
			|||||||
            // Don't do a launch check if the user hasn't seen the setup prompt explaining updater yet.
 | 
					            // Don't do a launch check if the user hasn't seen the setup prompt explaining updater yet.
 | 
				
			||||||
            checkForUpdates()
 | 
					            checkForUpdates()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        let timer = Timer.scheduledTimer(withTimeInterval: 60*60*24, repeats: true) { _ in
 | 
					        let timer = Timer.scheduledTimer(withTimeInterval: checkFrequency, repeats: true) { _ in
 | 
				
			||||||
            self.checkForUpdates()
 | 
					            self.checkForUpdates()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        timer.tolerance = 60*60
 | 
					        timer.tolerance = 60*60
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Manually trigger an update check.
 | 
				
			||||||
    public func checkForUpdates() {
 | 
					    public func checkForUpdates() {
 | 
				
			||||||
        URLSession.shared.dataTask(with: Constants.updateURL) { data, _, _ in
 | 
					        URLSession.shared.dataTask(with: Constants.updateURL) { data, _, _ in
 | 
				
			||||||
            guard let data = data else { return }
 | 
					            guard let data = data else { return }
 | 
				
			||||||
@ -38,6 +41,8 @@ public class Updater: ObservableObject, UpdaterProtocol {
 | 
				
			|||||||
        }.resume()
 | 
					        }.resume()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Ignores a specified release. `update` will be nil if the user has ignored the latest available release.
 | 
				
			||||||
 | 
					    /// - Parameter release: The release to ignore.
 | 
				
			||||||
    public func ignore(release: Release) {
 | 
					    public func ignore(release: Release) {
 | 
				
			||||||
        guard !release.critical else { return }
 | 
					        guard !release.critical else { return }
 | 
				
			||||||
        defaults.set(true, forKey: release.name)
 | 
					        defaults.set(true, forKey: release.name)
 | 
				
			||||||
@ -50,6 +55,8 @@ public class Updater: ObservableObject, UpdaterProtocol {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
extension Updater {
 | 
					extension Updater {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Evaluates the available downloadable releases, and selects the newest non-prerelease release that the user is able to run.
 | 
				
			||||||
 | 
					    /// - Parameter releases: An array of ``Release`` objects.
 | 
				
			||||||
    func evaluate(releases: [Release]) {
 | 
					    func evaluate(releases: [Release]) {
 | 
				
			||||||
        guard let release = releases
 | 
					        guard let release = releases
 | 
				
			||||||
                .sorted()
 | 
					                .sorted()
 | 
				
			||||||
@ -66,49 +73,18 @@ extension Updater {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Checks whether the user has ignored a release.
 | 
				
			||||||
 | 
					    /// - Parameter release: The release to check.
 | 
				
			||||||
 | 
					    /// - Returns: A boolean describing whether the user has ignored the release. Will always be false if the release is critical.
 | 
				
			||||||
    func userIgnored(release: Release) -> Bool {
 | 
					    func userIgnored(release: Release) -> Bool {
 | 
				
			||||||
        guard !release.critical else { return false }
 | 
					        guard !release.critical else { return false }
 | 
				
			||||||
        return defaults.bool(forKey: release.name)
 | 
					        return defaults.bool(forKey: release.name)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// The user defaults used to store user ignore state.
 | 
				
			||||||
    var defaults: UserDefaults {
 | 
					    var defaults: UserDefaults {
 | 
				
			||||||
        UserDefaults(suiteName: "com.maxgoedjen.Secretive.updater.ignorelist")!
 | 
					        UserDefaults(suiteName: "com.maxgoedjen.Secretive.updater.ignorelist")!
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public struct SemVer {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let versionNumbers: [Int]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public init(_ version: String) {
 | 
					 | 
				
			||||||
        // Betas have the format 1.2.3_beta1
 | 
					 | 
				
			||||||
        let strippedBeta = version.split(separator: "_").first!
 | 
					 | 
				
			||||||
        var split = strippedBeta.split(separator: ".").compactMap { Int($0) }
 | 
					 | 
				
			||||||
        while split.count < 3 {
 | 
					 | 
				
			||||||
            split.append(0)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        versionNumbers = split
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public init(_ version: OperatingSystemVersion) {
 | 
					 | 
				
			||||||
        versionNumbers = [version.majorVersion, version.minorVersion, version.patchVersion]
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extension SemVer: Comparable {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static func < (lhs: SemVer, rhs: SemVer) -> Bool {
 | 
					 | 
				
			||||||
        for (latest, current) in zip(lhs.versionNumbers, rhs.versionNumbers) {
 | 
					 | 
				
			||||||
            if latest < current {
 | 
					 | 
				
			||||||
                return true
 | 
					 | 
				
			||||||
            } else if latest > current {
 | 
					 | 
				
			||||||
                return false
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return false
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -119,63 +95,3 @@ extension Updater {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
public struct Release: Codable {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public let name: String
 | 
					 | 
				
			||||||
    public let prerelease: Bool
 | 
					 | 
				
			||||||
    public let html_url: URL
 | 
					 | 
				
			||||||
    public let body: String
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public init(name: String, prerelease: Bool, html_url: URL, body: String) {
 | 
					 | 
				
			||||||
        self.name = name
 | 
					 | 
				
			||||||
        self.prerelease = prerelease
 | 
					 | 
				
			||||||
        self.html_url = html_url
 | 
					 | 
				
			||||||
        self.body = body
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extension Release: Identifiable {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public var id: String {
 | 
					 | 
				
			||||||
        html_url.absoluteString
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extension Release: Comparable {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static func < (lhs: Release, rhs: Release) -> Bool {
 | 
					 | 
				
			||||||
        lhs.version < rhs.version
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extension Release {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public var critical: Bool {
 | 
					 | 
				
			||||||
        body.contains(Constants.securityContent)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public var version: SemVer {
 | 
					 | 
				
			||||||
        SemVer(name)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public var minimumOSVersion: SemVer {
 | 
					 | 
				
			||||||
        guard let range = body.range(of: "Minimum macOS Version"),
 | 
					 | 
				
			||||||
              let numberStart = body.rangeOfCharacter(from: CharacterSet.decimalDigits, options: [], range: range.upperBound..<body.endIndex) else { return SemVer("11.0.0") }
 | 
					 | 
				
			||||||
        let numbersEnd = body.rangeOfCharacter(from: CharacterSet.whitespacesAndNewlines, options: [], range: numberStart.upperBound..<body.endIndex)?.lowerBound ?? body.endIndex
 | 
					 | 
				
			||||||
        let version = numberStart.lowerBound..<numbersEnd
 | 
					 | 
				
			||||||
        return SemVer(String(body[version]))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extension Release {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    enum Constants {
 | 
					 | 
				
			||||||
        static let securityContent = "Critical Security Update"
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										12
									
								
								Sources/Packages/Sources/Brief/UpdaterProtocol.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								Sources/Packages/Sources/Brief/UpdaterProtocol.swift
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					import Foundation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// A protocol for retreiving the latest available version of an app.
 | 
				
			||||||
 | 
					public protocol UpdaterProtocol: ObservableObject {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// The latest update
 | 
				
			||||||
 | 
					    var update: Release? { get }
 | 
				
			||||||
 | 
					    /// A boolean describing whether or not the current build of the app is a "test" build (ie, a debug build or otherwise special build)
 | 
				
			||||||
 | 
					    var testBuild: Bool { get }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					# ``SecretAgentKit``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--@START_MENU_TOKEN@-->Summary<!--@END_MENU_TOKEN@-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Overview
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--@START_MENU_TOKEN@-->Text<!--@END_MENU_TOKEN@-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Topics
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### <!--@START_MENU_TOKEN@-->Group<!--@END_MENU_TOKEN@-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- <!--@START_MENU_TOKEN@-->``Symbol``<!--@END_MENU_TOKEN@-->
 | 
				
			||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
# ````SecretKit````
 | 
					# ``SecretKit``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SecretKit is a collection of protocols describing secrets and stores.
 | 
					SecretKit is a collection of protocols describing secrets and stores.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,3 @@
 | 
				
			|||||||
# ````SecureEnclaveSecretKit````
 | 
					# ``SecureEnclaveSecretKit``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SecureEnclaveSecretKit contains implementations of SecretKit protocols backed by the Secure Enclave.
 | 
					SecureEnclaveSecretKit contains implementations of SecretKit protocols backed by the Secure Enclave.
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,3 @@
 | 
				
			|||||||
# ````SmartCardSecretKit````
 | 
					# ``SmartCardSecretKit``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SmartCardSecretKit contains implementations of SecretKit protocols backed by a Smart Card.
 | 
					SmartCardSecretKit contains implementations of SecretKit protocols backed by a Smart Card.
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user