diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 16b8178..2ffe90a 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -30,7 +30,8 @@ jobs: env: RUN_ID: ${{ github.run_id }} run: | - sed -i '' -e "s/GITHUB_CI_VERSION/0.0.0/g" Sources/Config/Config.xcconfig + DATE=$(date "+%Y-%m-%d") + sed -i '' -e "s/GITHUB_CI_VERSION/0.0.0_nightly-$DATE/g" Sources/Config/Config.xcconfig sed -i '' -e "s/GITHUB_BUILD_NUMBER/1.$RUN_ID/g" Sources/Config/Config.xcconfig sed -i '' -e "s/GITHUB_BUILD_URL/https:\/\/github.com\/maxgoedjen\/secretive\/actions\/runs\/$RUN_ID/g" Sources/Secretive/Credits.rtf - name: Build diff --git a/Sources/Packages/Resources/Localizable.xcstrings b/Sources/Packages/Resources/Localizable.xcstrings index 3d386dc..b316d10 100644 --- a/Sources/Packages/Resources/Localizable.xcstrings +++ b/Sources/Packages/Resources/Localizable.xcstrings @@ -6292,6 +6292,17 @@ } } } + }, + "updater_download_latest_nightly_button" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Download Latest Nightly Build" + } + } + } } }, "version" : "1.0" diff --git a/Sources/Packages/Sources/Brief/SemVer.swift b/Sources/Packages/Sources/Brief/SemVer.swift index 8df8c4a..472cd0e 100644 --- a/Sources/Packages/Sources/Brief/SemVer.swift +++ b/Sources/Packages/Sources/Brief/SemVer.swift @@ -5,12 +5,20 @@ public struct SemVer: Sendable { /// The SemVer broken into an array of integers. let versionNumbers: [Int] + public let previewDescription: String? + + public var isTestBuild: Bool { + versionNumbers == [0, 0, 0] + } /// 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! + // Nightlies have the format 0.0.0_nightly-2025-09-03 + let splitFull = version.split(separator: "_") + let strippedBeta = splitFull.first! + previewDescription = splitFull.count > 1 ? String(splitFull[1]) : nil var split = strippedBeta.split(separator: ".").compactMap { Int($0) } while split.count < 3 { split.append(0) @@ -22,6 +30,7 @@ public struct SemVer: Sendable { /// - Parameter version: An `OperatingSystemVersion` representation of the SemVer. public init(_ version: OperatingSystemVersion) { versionNumbers = [version.majorVersion, version.minorVersion, version.patchVersion] + previewDescription = nil } } diff --git a/Sources/Packages/Sources/Brief/Updater.swift b/Sources/Packages/Sources/Brief/Updater.swift index f79effe..600ddc5 100644 --- a/Sources/Packages/Sources/Brief/Updater.swift +++ b/Sources/Packages/Sources/Brief/Updater.swift @@ -13,12 +13,11 @@ import Observation state.update } - public let testBuild: Bool + /// The current version of the app that is running. + public let currentVersion: SemVer /// The current OS version. private let osVersion: SemVer - /// The current version of the app that is running. - private let currentVersion: SemVer /// Initializes an Updater. /// - Parameters: @@ -34,7 +33,6 @@ import Observation ) { self.osVersion = osVersion self.currentVersion = currentVersion - testBuild = currentVersion == SemVer("0.0.0") if checkOnLaunch { // Don't do a launch check if the user hasn't seen the setup prompt explaining updater yet. Task { diff --git a/Sources/Packages/Sources/Brief/UpdaterProtocol.swift b/Sources/Packages/Sources/Brief/UpdaterProtocol.swift index b9df10a..06c248e 100644 --- a/Sources/Packages/Sources/Brief/UpdaterProtocol.swift +++ b/Sources/Packages/Sources/Brief/UpdaterProtocol.swift @@ -5,8 +5,8 @@ public protocol UpdaterProtocol: Observable, Sendable { /// The latest update @MainActor 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 } + + var currentVersion: SemVer { get } func ignore(release: Release) async } diff --git a/Sources/SecretAgent/AppDelegate.swift b/Sources/SecretAgent/AppDelegate.swift index 877145e..ee4b799 100644 --- a/Sources/SecretAgent/AppDelegate.swift +++ b/Sources/SecretAgent/AppDelegate.swift @@ -58,7 +58,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { updater.update } onChange: { [updater, notifier] in Task { - guard !updater.testBuild else { return } + guard !updater.currentVersion.isTestBuild else { return } await notifier.notify(update: updater.update!) { release in await updater.ignore(release: release) } diff --git a/Sources/Secretive/Preview Content/PreviewUpdater.swift b/Sources/Secretive/Preview Content/PreviewUpdater.swift index 77fbeea..b8bc29a 100644 --- a/Sources/Secretive/Preview Content/PreviewUpdater.swift +++ b/Sources/Secretive/Preview Content/PreviewUpdater.swift @@ -6,7 +6,7 @@ import Brief var update: Release? = nil - let testBuild = false + let currentVersion = SemVer("0.0.0_preview") init(update: Update = .none) { switch update { diff --git a/Sources/Secretive/Views/Views/ContentView.swift b/Sources/Secretive/Views/Views/ContentView.swift index 33e8c87..54b0fe5 100644 --- a/Sources/Secretive/Views/Views/ContentView.swift +++ b/Sources/Secretive/Views/Views/ContentView.swift @@ -75,7 +75,7 @@ extension ContentView { if update.critical { return (.updateCriticalNoticeTitle, .red) } else { - if updater.testBuild { + if updater.currentVersion.isTestBuild { return (.updateTestNoticeTitle, .blue) } else { return (.updateNormalNoticeTitle, .orange) @@ -95,7 +95,22 @@ extension ContentView { }) .buttonStyle(ToolbarButtonStyle(color: color)) .sheet(item: $selectedUpdate) { update in - UpdateDetailView(update: update) + VStack { + if updater.currentVersion.isTestBuild { + VStack { + if let description = updater.currentVersion.previewDescription { + Text(description) + } + Link(destination: URL(string: "https://github.com/maxgoedjen/secretive/actions/workflows/nightly.yml")!) { + Button(.updaterDownloadLatestNightlyButton) {} + .frame(maxWidth: .infinity) + .primaryButton() + } + } + .padding() + } + UpdateDetailView(update: update) + } } } }