Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,10 @@ struct OnePageInstallerView: View {
.font(OmarchyTheme.eyebrow)
.textCase(.uppercase)
.foregroundStyle(OmarchyTheme.accent)
if isBlocked {
StatusBadge(text: PlainLanguage.blockedBadge, kind: .blocked)
} else {
StatusBadge(text: PlainLanguage.supportedBadge, kind: .ok)
if let supported = session.modelSupported {
StatusBadge(
text: supported ? PlainLanguage.supportedBadge : PlainLanguage.blockedBadge,
kind: supported ? .ok : .blocked)
}
if let channel {
StatusBadge(text: PlainLanguage.badge(for: channel), kind: .ok)
Expand All @@ -169,15 +169,6 @@ struct OnePageInstallerView: View {
}
}

private var isBlocked: Bool {
switch session.phase {
case .unsupported, .existingInstallRefused:
return true
default:
return false
}
}

// MARK: The middle of the page

@ViewBuilder
Expand Down
17 changes: 17 additions & 0 deletions Sources/OmarchyInstallerUXCore/InstallerSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,23 @@
return environment.installationBlocked
}

/// The header's word on this Mac model: false only for a refused model, so
/// an existing install or too little space never reads as Not supported.
/// Nil when the installer stopped before it could tell.
public var modelSupported: Bool? {
switch phase {
case .inspecting:
return nil
case .existingInstallRefused(let host):
return host.supported ? true : nil
case .unsupported(let failure):
if failure.isBlockedModel { return false }
return failure.device?.supported == true ? true : nil
default:
return true
}
}

public var credentialSheet: CredentialSheetState {
if case .awaitingInstall(_, _, let sheet) = phase {
return sheet
Expand Down
57 changes: 57 additions & 0 deletions Tests/OmarchyInstallerUXCoreTests/InstallerSessionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1240,6 +1240,63 @@
XCTAssertEqual(environment.prepareCount, 1)
}

/// On the M2 Max (apple,j414c, enabled in the signed catalog) the header
/// said NOT SUPPORTED because an older install was still on the disk. Only
/// a refused model says that; a stop for any other reason says Supported
/// when the Mac is, and nothing when the installer couldn't tell.
func testHeaderSaysNotSupportedOnlyForARefusedModel() async {
let supported = MockInstallerEnvironment.supportedHost
let install = ExistingInstallDisplay(sourceIdentifier: "disk0s3", sizeDescription: "256 GB")
let cases: [(String, HostDisplay, Bool, Bool?)] = [
("ready", supported, false, true),
(
"existing install on a supported Mac",
HostDisplay(
chipAndSpace: supported.chipAndSpace, supported: true, existingInstalls: [install]),
false, true
),
(
"existing install, engine couldn't tell",
HostDisplay(
chipAndSpace: supported.chipAndSpace, supported: false, existingInstalls: [install]),
false, nil
),
(
"too little space",
HostDisplay(
chipAndSpace: supported.chipAndSpace, supported: true,
spaceShortfall: .insufficientSpace(
requiredBytes: 76_562_825_216, availableBytes: 73_528_246_272)),
false, true
),
(
"not ready",
HostDisplay(
chipAndSpace: supported.chipAndSpace, supported: false,
blockingReason: "The installer engine is unavailable."),
false, nil
),
(
"model not in the catalog",
HostDisplay(
chipAndSpace: "Apple M3 · 400 GB free", supported: false,
unsupportedModel: UnsupportedModelDisplay(
deviceIdentifier: "apple,j504", modelIdentifier: "Mac15,3",
supportedDeviceIdentifiers: ["apple,j314s"])),
false, false
),
("blocked model", HostDisplay(chipAndSpace: "Apple M4 Pro", supported: false), true, false),
]
for (name, host, blocked, expected) in cases {
let environment = MockInstallerEnvironment()
environment.host = host
environment.installationBlocked = blocked
let session = InstallerSession(environment: environment)
await session.inspect()
XCTAssertEqual(session.modelSupported, expected, name)
}
}

func testReinspectResetsDisplayedAndStoredEncryptionChoice() async {
let environment = MockInstallerEnvironment()
let session = InstallerSession(environment: environment)
Expand Down
Loading