Files
xcodesApp-mirror/Xcodes/Frontend/XcodeList/XcodeListViewRow.swift
2024-02-29 09:04:28 +08:00

166 lines
6.0 KiB
Swift

import Path
import SwiftUI
import Version
struct XcodeListViewRow: View {
let xcode: Xcode
let selected: Bool
let appState: AppState
var body: some View {
HStack {
appIconView(for: xcode)
VStack(alignment: .leading) {
HStack {
Text(verbatim: "\(xcode.description) \(xcode.version.buildMetadataIdentifiersDisplay)")
.font(.body)
if !xcode.identicalBuilds.isEmpty {
Image(systemName: "square.fill.on.square.fill")
.font(.subheadline)
.foregroundColor(.secondary)
.accessibility(label: Text("IdenticalBuilds"))
.accessibility(value: Text(xcode.identicalBuilds.map(\.appleDescription).joined(separator: ", ")))
.help("IdenticalBuilds.help")
}
}
if case let .installed(path) = xcode.installState {
Text(verbatim: path.string)
.font(.caption)
.foregroundColor(.secondary)
}
}
Spacer()
selectControl(for: xcode)
.padding(.trailing, 16)
installControl(for: xcode)
}
.padding(.vertical, 4)
.contextMenu {
switch xcode.installState {
case .notInstalled:
InstallButton(xcode: xcode)
case .installing:
CancelInstallButton(xcode: xcode)
case let .installed(path):
SelectButton(xcode: xcode)
OpenButton(xcode: xcode)
RevealButton(xcode: xcode)
CopyPathButton(xcode: xcode)
CreateSymbolicLinkButton(xcode: xcode)
if xcode.version.isPrerelease {
CreateSymbolicBetaLinkButton(xcode: xcode)
}
Divider()
UninstallButton(xcode: xcode)
#if DEBUG
Divider()
Button("Perform post-install steps") {
appState.performPostInstallSteps(for: InstalledXcode(path: path)!) as Void
}
#endif
}
}
}
@ViewBuilder
func appIconView(for xcode: Xcode) -> some View {
if let icon = xcode.icon {
Image(nsImage: icon)
} else {
Image(xcode.version.isPrerelease ? "xcode-beta" : "xcode")
.resizable()
.frame(width: 32, height: 32)
.opacity(0.2)
}
}
@ViewBuilder
private func selectControl(for xcode: Xcode) -> some View {
if xcode.installState.installed {
if xcode.selected {
Image(systemName: "checkmark.circle.fill")
.foregroundColor(.green)
.help("ActiveVersionDescription")
} else {
Button(action: { appState.select(xcode: xcode) }) {
Image(systemName: "checkmark.circle")
.foregroundColor(.secondary)
}
.buttonStyle(PlainButtonStyle())
.help("MakeActiveVersionDescription")
}
} else {
EmptyView()
}
}
@ViewBuilder
private func installControl(for xcode: Xcode) -> some View {
switch xcode.installState {
case .installed:
Button("Open") { appState.open(xcode: xcode) }
.textCase(.uppercase)
.buttonStyle(AppStoreButtonStyle(primary: true, highlighted: selected))
.help("OpenDescription")
case .notInstalled:
InstallButton(xcode: xcode)
.textCase(.uppercase)
.buttonStyle(AppStoreButtonStyle(primary: false, highlighted: false))
case let .installing(installationStep):
InstallationStepRowView(
installationStep: installationStep,
highlighted: selected,
cancel: { appState.presentedAlert = .cancelInstall(xcode: xcode) }
)
}
}
}
struct XcodeListViewRow_Previews: PreviewProvider {
static var previews: some View {
Group {
XcodeListViewRow(
xcode: Xcode(version: Version("12.3.0")!, installState: .installed(Path("/Applications/Xcode-12.3.0.app")!), selected: true, icon: nil),
selected: false,
appState: AppState()
)
XcodeListViewRow(
xcode: Xcode(version: Version("12.2.0")!, installState: .notInstalled, selected: false, icon: nil),
selected: false,
appState: AppState()
)
XcodeListViewRow(
xcode: Xcode(version: Version("12.1.0")!, installState: .installing(.downloading(progress: configure(Progress(totalUnitCount: 100)) { $0.completedUnitCount = 40 })), selected: false, icon: nil),
selected: false,
appState: AppState()
)
XcodeListViewRow(
xcode: Xcode(version: Version("12.0.0")!, installState: .installed(Path("/Applications/Xcode-12.3.0.app")!), selected: false, icon: nil),
selected: false,
appState: AppState()
)
XcodeListViewRow(
xcode: Xcode(version: Version("12.0.0+1234A")!, installState: .installed(Path("/Applications/Xcode-12.3.0.app")!), selected: false, icon: nil),
selected: false,
appState: AppState()
)
XcodeListViewRow(
xcode: Xcode(version: Version("12.0.0+1234A")!, identicalBuilds: [Version("12.0.0-RC+1234A")!], installState: .installed(Path("/Applications/Xcode-12.3.0.app")!), selected: false, icon: nil),
selected: false,
appState: AppState()
)
}
}
}