mirror of
https://github.com/XcodesOrg/XcodesApp.git
synced 2026-03-25 08:55:46 +00:00
140 lines
4.8 KiB
Swift
140 lines
4.8 KiB
Swift
import SwiftUI
|
|
import Version
|
|
import Path
|
|
|
|
struct XcodeMinorVersionRow: View {
|
|
let minorVersionGroup: XcodeMinorVersionGroup
|
|
let isExpanded: Bool
|
|
let onToggleExpanded: () -> Void
|
|
let appState: AppState
|
|
|
|
var body: some View {
|
|
HStack {
|
|
Button(action: onToggleExpanded) {
|
|
HStack(spacing: 8) {
|
|
Image(systemName: isExpanded ? "chevron.down" : "chevron.right")
|
|
.font(.caption.weight(.semibold))
|
|
.foregroundColor(.secondary)
|
|
|
|
minorVersionIcon
|
|
|
|
VStack(alignment: .leading, spacing: 2) {
|
|
Text(String(format: localizeString("Xcode %@"), minorVersionGroup.displayName))
|
|
.font(.callout.weight(.medium))
|
|
|
|
if let latestRelease = minorVersionGroup.latestRelease {
|
|
Text(String(format: localizeString("Latest: %@"), latestRelease.description))
|
|
.font(.caption2)
|
|
.foregroundColor(.secondary)
|
|
}
|
|
}
|
|
|
|
Spacer()
|
|
}
|
|
}
|
|
.buttonStyle(.plain)
|
|
|
|
selectControl()
|
|
.padding(.trailing, 16)
|
|
installControl()
|
|
}
|
|
.padding(.vertical, 6)
|
|
.padding(.leading, 20)
|
|
.background(Color.clear)
|
|
.contentShape(Rectangle())
|
|
}
|
|
|
|
@ViewBuilder
|
|
var minorVersionIcon: some View {
|
|
if let latestRelease = minorVersionGroup.latestRelease {
|
|
if let icon = latestRelease.icon {
|
|
Image(nsImage: icon)
|
|
.resizable()
|
|
.frame(width: 28, height: 28)
|
|
} else {
|
|
Image("xcode")
|
|
.resizable()
|
|
.frame(width: 28, height: 28)
|
|
.opacity(0.6)
|
|
}
|
|
} else {
|
|
Image("xcode-beta")
|
|
.resizable()
|
|
.frame(width: 28, height: 28)
|
|
.opacity(0.6)
|
|
}
|
|
}
|
|
|
|
@ViewBuilder
|
|
func selectControl() -> some View {
|
|
if let selectedVersion = minorVersionGroup.selectedVersion {
|
|
if selectedVersion.selected {
|
|
Image(systemName: "checkmark.circle.fill")
|
|
.foregroundColor(.green)
|
|
.help("ActiveVersionDescription")
|
|
} else {
|
|
EmptyView()
|
|
}
|
|
} else if minorVersionGroup.hasInstalled {
|
|
EmptyView()
|
|
} else {
|
|
EmptyView()
|
|
}
|
|
}
|
|
|
|
@ViewBuilder
|
|
func installControl() -> some View {
|
|
if minorVersionGroup.hasInstalling {
|
|
if let installingVersion = minorVersionGroup.versions.first(where: { $0.installState.installing }) {
|
|
if case let .installing(installationStep) = installingVersion.installState {
|
|
InstallationStepRowView(
|
|
installationStep: installationStep,
|
|
highlighted: false,
|
|
cancel: { appState.presentedAlert = .cancelInstall(xcode: installingVersion) }
|
|
)
|
|
}
|
|
}
|
|
} else if let latestRelease = minorVersionGroup.latestRelease {
|
|
switch latestRelease.installState {
|
|
case .installed:
|
|
Button("Open") { appState.open(xcode: latestRelease) }
|
|
.textCase(.uppercase)
|
|
.buttonStyle(AppStoreButtonStyle(primary: true, highlighted: false))
|
|
.help("OpenDescription")
|
|
case .notInstalled:
|
|
Button("Install Latest") {
|
|
appState.checkMinVersionAndInstall(id: latestRelease.id)
|
|
}
|
|
.textCase(.uppercase)
|
|
.buttonStyle(AppStoreButtonStyle(primary: false, highlighted: false))
|
|
.help("InstallLatestVersionDescription")
|
|
case .installing:
|
|
EmptyView()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct XcodeMinorVersionRow_Previews: PreviewProvider {
|
|
static var previews: some View {
|
|
let sampleXcodes = [
|
|
Xcode(version: Version("16.4.0")!, installState: .installed(Path("/Applications/Xcode-16.4.0.app")!), selected: true, icon: nil),
|
|
Xcode(version: Version("16.4.1")!, installState: .notInstalled, selected: false, icon: nil),
|
|
]
|
|
|
|
let minorVersionGroup = XcodeMinorVersionGroup(
|
|
majorVersion: 16,
|
|
minorVersion: 4,
|
|
versions: sampleXcodes,
|
|
isExpanded: false
|
|
)
|
|
|
|
XcodeMinorVersionRow(
|
|
minorVersionGroup: minorVersionGroup,
|
|
isExpanded: false,
|
|
onToggleExpanded: {},
|
|
appState: AppState()
|
|
)
|
|
.previewLayout(.sizeThatFits)
|
|
}
|
|
}
|