mirror of
https://github.com/XcodesOrg/XcodesApp.git
synced 2026-03-25 08:55:46 +00:00
Extract AppState.XcodeVersion to Xcode
This commit is contained in:
parent
23db486ac6
commit
acd82fa07a
4 changed files with 65 additions and 55 deletions
|
|
@ -12,6 +12,7 @@
|
|||
CA39711924495F0E00AFFB77 /* AppStoreButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA39711824495F0E00AFFB77 /* AppStoreButtonStyle.swift */; };
|
||||
CA44901F2463AD34003D8213 /* Tag.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA44901E2463AD34003D8213 /* Tag.swift */; };
|
||||
CA5D781E257365D6008EDE9D /* PinCodeTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA5D781D257365D6008EDE9D /* PinCodeTextView.swift */; };
|
||||
CA61A6E0259835580008926E /* Xcode.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA61A6DF259835580008926E /* Xcode.swift */; };
|
||||
CA735109257BF96D00EA9CF8 /* AttributedText.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA735108257BF96D00EA9CF8 /* AttributedText.swift */; };
|
||||
CA73510D257BFCEF00EA9CF8 /* NSAttributedString+.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA73510C257BFCEF00EA9CF8 /* NSAttributedString+.swift */; };
|
||||
CA9FF83F2594FBC000E47BAF /* Licenses.rtf in Resources */ = {isa = PBXBuildFile; fileRef = CA9FF83E2594FBC000E47BAF /* Licenses.rtf */; };
|
||||
|
|
@ -77,6 +78,7 @@
|
|||
CA44901E2463AD34003D8213 /* Tag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tag.swift; sourceTree = "<group>"; };
|
||||
CA538A0C255A4F1A00E64DD7 /* AppleAPI */ = {isa = PBXFileReference; lastKnownFileType = folder; name = AppleAPI; path = Xcodes/AppleAPI; sourceTree = "<group>"; };
|
||||
CA5D781D257365D6008EDE9D /* PinCodeTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinCodeTextView.swift; sourceTree = "<group>"; };
|
||||
CA61A6DF259835580008926E /* Xcode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Xcode.swift; sourceTree = "<group>"; };
|
||||
CA735108257BF96D00EA9CF8 /* AttributedText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedText.swift; sourceTree = "<group>"; };
|
||||
CA73510C257BFCEF00EA9CF8 /* NSAttributedString+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+.swift"; sourceTree = "<group>"; };
|
||||
CA8FB5F8256E0F9400469DA5 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||
|
|
@ -229,6 +231,7 @@
|
|||
CABFA9A82592EEE900380FEE /* Version+.swift */,
|
||||
CA9FF876259528CC00E47BAF /* Version+XcodeReleases.swift */,
|
||||
CABFA9A62592EEE900380FEE /* Version+Xcode.swift */,
|
||||
CA61A6DF259835580008926E /* Xcode.swift */,
|
||||
);
|
||||
path = Backend;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -473,6 +476,7 @@
|
|||
CABFA9C52592EEEA00380FEE /* FileManager+.swift in Sources */,
|
||||
CABFA9CD2592EEEA00380FEE /* Foundation.swift in Sources */,
|
||||
CA9FF8872595607900E47BAF /* InstalledXcode.swift in Sources */,
|
||||
CA61A6E0259835580008926E /* Xcode.swift in Sources */,
|
||||
CA9FF84E2595079F00E47BAF /* ScrollingTextView.swift in Sources */,
|
||||
CABFA9C12592EEEA00380FEE /* Version+.swift in Sources */,
|
||||
CA9FF8522595080100E47BAF /* AcknowledgementsView.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import Path
|
|||
import LegibleError
|
||||
import KeychainAccess
|
||||
import SwiftUI
|
||||
import Version
|
||||
|
||||
class AppState: ObservableObject {
|
||||
private let client = AppleAPI.Client()
|
||||
|
|
@ -13,10 +14,10 @@ class AppState: ObservableObject {
|
|||
@Published var authenticationState: AuthenticationState = .unauthenticated
|
||||
@Published var availableXcodes: [AvailableXcode] = [] {
|
||||
willSet {
|
||||
updateAllVersions(newValue)
|
||||
updateAllXcodes(newValue)
|
||||
}
|
||||
}
|
||||
var allVersions: [XcodeVersion] = []
|
||||
var allXcodes: [Xcode] = []
|
||||
@Published var updatePublisher: AnyCancellable?
|
||||
var isUpdating: Bool { updatePublisher != nil }
|
||||
@Published var error: AlertContent?
|
||||
|
|
@ -171,27 +172,27 @@ class AppState: ObservableObject {
|
|||
|
||||
// MARK: -
|
||||
|
||||
func install(id: String) {
|
||||
func install(id: Xcode.ID) {
|
||||
// TODO:
|
||||
}
|
||||
|
||||
func uninstall(id: String) {
|
||||
func uninstall(id: Xcode.ID) {
|
||||
// TODO:
|
||||
}
|
||||
|
||||
func reveal(id: String) {
|
||||
func reveal(id: Xcode.ID) {
|
||||
// TODO: show error if not
|
||||
guard let installedXcode = Current.files.installedXcodes(Path.root/"Applications").first(where: { $0.version.xcodeDescription == id }) else { return }
|
||||
guard let installedXcode = Current.files.installedXcodes(Path.root/"Applications").first(where: { $0.version == id }) else { return }
|
||||
NSWorkspace.shared.activateFileViewerSelecting([installedXcode.path.url])
|
||||
}
|
||||
|
||||
func select(id: String) {
|
||||
func select(id: Xcode.ID) {
|
||||
// TODO:
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func updateAllVersions(_ xcodes: [AvailableXcode]) {
|
||||
private func updateAllXcodes(_ xcodes: [AvailableXcode]) {
|
||||
let installedXcodes = Current.files.installedXcodes(Path.root/"Applications")
|
||||
var allXcodeVersions = xcodes.map { $0.version }
|
||||
for installedXcode in installedXcodes {
|
||||
|
|
@ -210,12 +211,12 @@ class AppState: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
allVersions = allXcodeVersions
|
||||
allXcodes = allXcodeVersions
|
||||
.sorted(by: >)
|
||||
.map { xcodeVersion in
|
||||
let installedXcode = installedXcodes.first(where: { xcodeVersion.isEquivalentForDeterminingIfInstalled(toInstalled: $0.version) })
|
||||
return XcodeVersion(
|
||||
title: xcodeVersion.xcodeDescription,
|
||||
return Xcode(
|
||||
version: xcodeVersion,
|
||||
installState: installedXcodes.contains(where: { xcodeVersion.isEquivalentForDeterminingIfInstalled(toInstalled: $0.version) }) ? .installed : .notInstalled,
|
||||
selected: false,
|
||||
path: installedXcode?.path.string
|
||||
|
|
@ -225,22 +226,6 @@ class AppState: ObservableObject {
|
|||
|
||||
|
||||
// MARK: - Nested Types
|
||||
|
||||
/// A merging of AvailableXcode and InstalledXcode prepared for display
|
||||
struct XcodeVersion: Identifiable {
|
||||
let title: String
|
||||
let installState: InstallState
|
||||
let selected: Bool
|
||||
let path: String?
|
||||
var id: String { title }
|
||||
var installed: Bool { installState == .installed }
|
||||
}
|
||||
|
||||
enum InstallState: Equatable {
|
||||
case notInstalled
|
||||
case installing(Progress)
|
||||
case installed
|
||||
}
|
||||
|
||||
struct AlertContent: Identifiable {
|
||||
var title: String
|
||||
|
|
|
|||
22
Xcodes/Backend/Xcode.swift
Normal file
22
Xcodes/Backend/Xcode.swift
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import Foundation
|
||||
import Version
|
||||
|
||||
struct Xcode: Identifiable, CustomStringConvertible {
|
||||
let version: Version
|
||||
let installState: XcodeInstallState
|
||||
let selected: Bool
|
||||
let path: String?
|
||||
|
||||
var id: Version { version }
|
||||
var installed: Bool { installState == .installed }
|
||||
|
||||
var description: String {
|
||||
version.xcodeDescription
|
||||
}
|
||||
}
|
||||
|
||||
enum XcodeInstallState: Equatable {
|
||||
case notInstalled
|
||||
case installing(Progress)
|
||||
case installed
|
||||
}
|
||||
|
|
@ -4,27 +4,26 @@ import PromiseKit
|
|||
|
||||
struct XcodeListView: View {
|
||||
@EnvironmentObject var appState: AppState
|
||||
@State private var selection = Set<String>()
|
||||
@State private var rowBeingConfirmedForUninstallation: AppState.XcodeVersion?
|
||||
@State private var selection = Set<Version>()
|
||||
@State private var xcodeBeingConfirmedForUninstallation: Xcode?
|
||||
@State private var searchText: String = ""
|
||||
@AppStorage("lastUpdated") private var lastUpdated: Double?
|
||||
|
||||
@AppStorage("xcodeListCategory") private var category: Category = .all
|
||||
|
||||
var visibleVersions: [AppState.XcodeVersion] {
|
||||
var versions: [AppState.XcodeVersion]
|
||||
var visibleXcodes: [Xcode] {
|
||||
var xcodes: [Xcode]
|
||||
switch category {
|
||||
case .all:
|
||||
versions = appState.allVersions
|
||||
xcodes = appState.allXcodes
|
||||
case .installed:
|
||||
versions = appState.allVersions.filter { $0.installed }
|
||||
xcodes = appState.allXcodes.filter { $0.installed }
|
||||
}
|
||||
|
||||
if !searchText.isEmpty {
|
||||
versions = versions.filter { $0.title.contains(searchText) }
|
||||
xcodes = xcodes.filter { $0.description.contains(searchText) }
|
||||
}
|
||||
|
||||
return versions
|
||||
return xcodes
|
||||
}
|
||||
|
||||
enum Category: String, CaseIterable, Identifiable, CustomStringConvertible {
|
||||
|
|
@ -42,36 +41,36 @@ struct XcodeListView: View {
|
|||
}
|
||||
|
||||
var body: some View {
|
||||
List(visibleVersions, selection: $selection) { row in
|
||||
List(visibleXcodes, selection: $selection) { xcode in
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
Text(row.title)
|
||||
Text(xcode.description)
|
||||
.font(.body)
|
||||
if row.selected {
|
||||
if xcode.selected {
|
||||
Tag(text: "SELECTED")
|
||||
.foregroundColor(.green)
|
||||
}
|
||||
Spacer()
|
||||
Button(row.installed ? "INSTALLED" : "INSTALL") {
|
||||
Button(xcode.installed ? "INSTALLED" : "INSTALL") {
|
||||
print("Installing...")
|
||||
}
|
||||
.buttonStyle(AppStoreButtonStyle(installed: row.installed,
|
||||
highlighted: self.selection.contains(row.id)))
|
||||
.disabled(row.installed)
|
||||
.buttonStyle(AppStoreButtonStyle(installed: xcode.installed,
|
||||
highlighted: self.selection.contains(xcode.id)))
|
||||
.disabled(xcode.installed)
|
||||
}
|
||||
Text(verbatim: row.path ?? "")
|
||||
Text(verbatim: xcode.path ?? "")
|
||||
.font(.caption)
|
||||
.foregroundColor(self.selection.contains(row.id) ? Color(NSColor.selectedMenuItemTextColor) : Color(NSColor.secondaryLabelColor))
|
||||
.foregroundColor(self.selection.contains(xcode.id) ? Color(NSColor.selectedMenuItemTextColor) : Color(NSColor.secondaryLabelColor))
|
||||
}
|
||||
.contextMenu {
|
||||
Button(action: { row.installed ? self.rowBeingConfirmedForUninstallation = row : self.appState.install(id: row.id) }) {
|
||||
Text(row.installed ? "Uninstall" : "Install")
|
||||
Button(action: { xcode.installed ? self.xcodeBeingConfirmedForUninstallation = xcode : self.appState.install(id: xcode.id) }) {
|
||||
Text(xcode.installed ? "Uninstall" : "Install")
|
||||
}
|
||||
if row.installed {
|
||||
Button(action: { self.appState.reveal(id: row.id) }) {
|
||||
if xcode.installed {
|
||||
Button(action: { self.appState.reveal(id: xcode.id) }) {
|
||||
Text("Reveal in Finder")
|
||||
}
|
||||
Button(action: { self.appState.select(id: row.id) }) {
|
||||
Button(action: { self.appState.select(id: xcode.id) }) {
|
||||
Text("Select")
|
||||
}
|
||||
}
|
||||
|
|
@ -154,11 +153,11 @@ struct XcodeListView_Previews: PreviewProvider {
|
|||
XcodeListView()
|
||||
.environmentObject({ () -> AppState in
|
||||
let a = AppState()
|
||||
a.allVersions = [
|
||||
AppState.XcodeVersion(title: "12.3", installState: .installed, selected: true, path: nil),
|
||||
AppState.XcodeVersion(title: "12.2", installState: .notInstalled, selected: false, path: nil),
|
||||
AppState.XcodeVersion(title: "12.1", installState: .notInstalled, selected: false, path: nil),
|
||||
AppState.XcodeVersion(title: "12.0", installState: .installed, selected: false, path: nil),
|
||||
a.allXcodes = [
|
||||
Xcode(version: Version("12.3.0")!, installState: .installed, selected: true, path: nil),
|
||||
Xcode(version: Version("12.2.0")!, installState: .notInstalled, selected: false, path: nil),
|
||||
Xcode(version: Version("12.1.0")!, installState: .notInstalled, selected: false, path: nil),
|
||||
Xcode(version: Version("12.0.0")!, installState: .installed, selected: false, path: nil),
|
||||
]
|
||||
return a
|
||||
}())
|
||||
|
|
|
|||
Loading…
Reference in a new issue