mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-04-03 10:55:54 +00:00
123 lines
3.8 KiB
Swift
123 lines
3.8 KiB
Swift
import Foundation
|
|
|
|
/// Represents the available update channels for the application.
|
|
///
|
|
/// This enum defines the different update channels that users can choose from,
|
|
/// allowing them to receive either stable releases only or include pre-release versions.
|
|
public enum UpdateChannel: String, CaseIterable, Codable, Sendable {
|
|
case stable
|
|
case prerelease
|
|
|
|
/// Human-readable display name for the update channel
|
|
public var displayName: String {
|
|
switch self {
|
|
case .stable:
|
|
"Stable Only"
|
|
case .prerelease:
|
|
"Include Pre-releases"
|
|
}
|
|
}
|
|
|
|
/// Detailed description of what each channel includes
|
|
public var description: String {
|
|
switch self {
|
|
case .stable:
|
|
"Receive only stable, production-ready releases"
|
|
case .prerelease:
|
|
"Receive both stable releases and pre-release versions."
|
|
}
|
|
}
|
|
|
|
/// The Sparkle appcast URL for this update channel
|
|
public var appcastURL: URL {
|
|
switch self {
|
|
case .stable:
|
|
Self.stableAppcastURL
|
|
case .prerelease:
|
|
Self.prereleaseAppcastURL
|
|
}
|
|
}
|
|
|
|
/// Static URLs to ensure they're validated at compile time
|
|
private static let stableAppcastURL: URL = {
|
|
guard let url =
|
|
URL(string: "https://stats.store/api/v1/appcast/appcast.xml")
|
|
else {
|
|
fatalError("Invalid stable appcast URL - this should never happen with a hardcoded URL")
|
|
}
|
|
return url
|
|
}()
|
|
|
|
private static let prereleaseAppcastURL: URL = {
|
|
guard let url =
|
|
URL(
|
|
string: "https://stats.store/api/v1/appcast/appcast-prerelease.xml"
|
|
)
|
|
else {
|
|
fatalError("Invalid prerelease appcast URL - this should never happen with a hardcoded URL")
|
|
}
|
|
return url
|
|
}()
|
|
|
|
/// Whether this channel includes pre-release versions
|
|
public var includesPreReleases: Bool {
|
|
switch self {
|
|
case .stable:
|
|
false
|
|
case .prerelease:
|
|
true
|
|
}
|
|
}
|
|
|
|
/// The current update channel based on user defaults
|
|
public static var current: Self {
|
|
if let rawValue = UserDefaults.standard.string(forKey: "updateChannel"),
|
|
let channel = Self(rawValue: rawValue)
|
|
{
|
|
return channel
|
|
}
|
|
return defaultChannel
|
|
}
|
|
|
|
/// The default update channel based on the current app version
|
|
public static var defaultChannel: Self {
|
|
defaultChannel(for: Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "1.0")
|
|
}
|
|
|
|
/// Determines if the current app version suggests this channel should be default
|
|
public static func defaultChannel(for appVersion: String) -> Self {
|
|
// First check if this build was marked as a pre-release during build time
|
|
if let isPrereleaseValue = Bundle.main.object(forInfoDictionaryKey: "IS_PRERELEASE_BUILD"),
|
|
let isPrerelease = isPrereleaseValue as? Bool,
|
|
isPrerelease
|
|
{
|
|
return .prerelease
|
|
}
|
|
|
|
// Otherwise, check if the version string contains pre-release keywords
|
|
let prereleaseKeywords = ["beta", "alpha", "rc", "pre", "dev"]
|
|
let lowercaseVersion = appVersion.lowercased()
|
|
|
|
for keyword in prereleaseKeywords where lowercaseVersion.contains(keyword) {
|
|
return .prerelease
|
|
}
|
|
|
|
return .stable
|
|
}
|
|
}
|
|
|
|
// MARK: - Identifiable Conformance
|
|
|
|
extension UpdateChannel: Identifiable {
|
|
public var id: String { rawValue }
|
|
}
|
|
|
|
// MARK: - UserDefaults Integration
|
|
|
|
extension UserDefaults {
|
|
/// KVO-compatible property for update channel
|
|
@objc dynamic var updateChannel: String? {
|
|
get { string(forKey: "updateChannel") }
|
|
set { set(newValue, forKey: "updateChannel") }
|
|
}
|
|
}
|