mirror of
https://github.com/XcodesOrg/XcodesApp.git
synced 2026-03-25 08:55:46 +00:00
Auto Install Xcode if wanted
This commit is contained in:
parent
e4165d5366
commit
8011f4a288
4 changed files with 119 additions and 23 deletions
|
|
@ -8,6 +8,31 @@ import os.log
|
|||
|
||||
/// Downloads and installs Xcodes
|
||||
extension AppState {
|
||||
|
||||
// check to see if we should auto install for the user
|
||||
public func autoInstallIfNeeded() {
|
||||
guard let storageValue = UserDefaults.standard.object(forKey: "autoInstallation") as? Int, let autoInstallType = AutoInstallationType(rawValue: storageValue) else { return }
|
||||
|
||||
if autoInstallType == .none { return }
|
||||
|
||||
// get newest xcode version
|
||||
guard let newestXcode = allXcodes.first, newestXcode.installState == .notInstalled else {
|
||||
Logger.appState.info("User has latest Xcode already installed")
|
||||
return
|
||||
}
|
||||
|
||||
if autoInstallType == .newestBeta {
|
||||
Logger.appState.info("Auto installing newest Xcode Beta")
|
||||
// install it, as user doesn't have it installed and it's either latest beta or latest release
|
||||
install(id: newestXcode.id)
|
||||
} else if autoInstallType == .newestVersion && newestXcode.version.isNotPrerelease {
|
||||
Logger.appState.info("Auto installing newest Xcode")
|
||||
install(id: newestXcode.id)
|
||||
} else {
|
||||
Logger.appState.info("No new Xcodes version found to auto install")
|
||||
}
|
||||
}
|
||||
|
||||
public func install(_ installationType: InstallationType, downloader: Downloader) -> AnyPublisher<Void, Error> {
|
||||
install(installationType, downloader: downloader, attemptNumber: 0)
|
||||
.map { _ in Void() }
|
||||
|
|
@ -517,5 +542,30 @@ public enum InstallationType {
|
|||
case version(AvailableXcode)
|
||||
}
|
||||
|
||||
public enum AutoInstallationType: Int, Identifiable {
|
||||
case none = 0
|
||||
case newestVersion
|
||||
case newestBeta
|
||||
|
||||
public var id: Self { self }
|
||||
|
||||
public var isAutoInstalling: Bool {
|
||||
get {
|
||||
return self != .none
|
||||
}
|
||||
set {
|
||||
self = newValue ? .newestVersion : .none
|
||||
}
|
||||
}
|
||||
public var isAutoInstallingBeta: Bool {
|
||||
get {
|
||||
return self == .newestBeta
|
||||
}
|
||||
set {
|
||||
self = newValue ? .newestBeta : (isAutoInstalling ? .newestVersion : .none)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let XcodeTeamIdentifier = "59GAB85EFG"
|
||||
let XcodeCertificateAuthority = ["Software Signing", "Apple Code Signing Certification Authority", "Apple Root CA"]
|
||||
|
|
|
|||
|
|
@ -6,11 +6,20 @@ import SwiftSoup
|
|||
import struct XCModel.Xcode
|
||||
|
||||
extension AppState {
|
||||
|
||||
var isReadyForUpdate: Bool {
|
||||
guard let lastUpdated = Current.defaults.date(forKey: "lastUpdated"),
|
||||
// This is bad date math but for this use case it doesn't need to be exact
|
||||
lastUpdated < Current.date().addingTimeInterval(-60 * 60 * 5)
|
||||
else {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func updateIfNeeded() {
|
||||
guard
|
||||
let lastUpdated = Current.defaults.date(forKey: "lastUpdated"),
|
||||
// This is bad date math but for this use case it doesn't need to be exact
|
||||
lastUpdated < Current.date().addingTimeInterval(-60 * 60 * 24)
|
||||
isReadyForUpdate
|
||||
else {
|
||||
updatePublisher = updateSelectedXcodePath()
|
||||
.sink(
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ class AppState: ObservableObject {
|
|||
selectedXcodePath: selectedXcodePath
|
||||
)
|
||||
}
|
||||
didSet {
|
||||
autoInstallIfNeeded()
|
||||
}
|
||||
}
|
||||
@Published var allXcodes: [Xcode] = []
|
||||
@Published var selectedXcodePath: String? {
|
||||
|
|
@ -56,7 +59,7 @@ class AppState: ObservableObject {
|
|||
private var installationPublishers: [Version: AnyCancellable] = [:]
|
||||
private var selectPublisher: AnyCancellable?
|
||||
private var uninstallPublisher: AnyCancellable?
|
||||
|
||||
private var autoInstallTimer: Timer?
|
||||
// MARK: -
|
||||
|
||||
var dataSource: DataSource {
|
||||
|
|
@ -69,8 +72,20 @@ class AppState: ObservableObject {
|
|||
guard !isTesting else { return }
|
||||
try? loadCachedAvailableXcodes()
|
||||
checkIfHelperIsInstalled()
|
||||
setupAutoInstallTimer()
|
||||
}
|
||||
|
||||
// MARK: Timer
|
||||
/// Runs a timer every 6 hours when app is open to check if it needs to auto install any xcodes
|
||||
func setupAutoInstallTimer() {
|
||||
guard let storageValue = UserDefaults.standard.object(forKey: "autoInstallation") as? Int, let autoInstallType = AutoInstallationType(rawValue: storageValue) else { return }
|
||||
|
||||
if autoInstallType == .none { return }
|
||||
|
||||
autoInstallTimer = Timer.scheduledTimer(withTimeInterval: 60*60*6, repeats: true) { [weak self] _ in
|
||||
self?.updateIfNeeded()
|
||||
}
|
||||
}
|
||||
// MARK: - Authentication
|
||||
|
||||
func validateSession() -> AnyPublisher<Void, Error> {
|
||||
|
|
|
|||
|
|
@ -5,29 +5,51 @@ import SwiftUI
|
|||
struct UpdatesPreferencePane: View {
|
||||
@StateObject var updater = ObservableUpdater()
|
||||
|
||||
@AppStorage("autoInstallation") var autoInstallationType: AutoInstallationType = .none
|
||||
|
||||
var body: some View {
|
||||
GroupBox(label: Text("Updates")) {
|
||||
VStack(alignment: .leading) {
|
||||
Toggle(
|
||||
"Automatically check for app updates",
|
||||
isOn: $updater.automaticallyChecksForUpdates
|
||||
)
|
||||
|
||||
Toggle(
|
||||
"Include prerelease app versions",
|
||||
isOn: $updater.includePrereleaseVersions
|
||||
)
|
||||
|
||||
Button("Check Now") {
|
||||
SUUpdater.shared()?.checkForUpdates(nil)
|
||||
VStack(alignment: .leading, spacing: 20) {
|
||||
GroupBox(label: Text("Versions")) {
|
||||
VStack(alignment: .leading) {
|
||||
Toggle(
|
||||
"Automatically install new versions of Xcode",
|
||||
isOn: $autoInstallationType.isAutoInstalling
|
||||
)
|
||||
|
||||
Toggle(
|
||||
"Include prerelease/beta versions",
|
||||
isOn: $autoInstallationType.isAutoInstallingBeta
|
||||
)
|
||||
}
|
||||
|
||||
Text("Last checked: \(lastUpdatedString)")
|
||||
.font(.footnote)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.groupBoxStyle(PreferencesGroupBoxStyle())
|
||||
|
||||
Divider()
|
||||
|
||||
GroupBox(label: Text("Xcodes.app Updates")) {
|
||||
VStack(alignment: .leading) {
|
||||
Toggle(
|
||||
"Automatically check for app updates",
|
||||
isOn: $updater.automaticallyChecksForUpdates
|
||||
)
|
||||
|
||||
Toggle(
|
||||
"Include prerelease app versions",
|
||||
isOn: $updater.includePrereleaseVersions
|
||||
)
|
||||
|
||||
Button("Check Now") {
|
||||
SUUpdater.shared()?.checkForUpdates(nil)
|
||||
}
|
||||
|
||||
Text("Last checked: \(lastUpdatedString)")
|
||||
.font(.footnote)
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
.groupBoxStyle(PreferencesGroupBoxStyle())
|
||||
}
|
||||
.groupBoxStyle(PreferencesGroupBoxStyle())
|
||||
.frame(width: 400)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue