Make iconName optional in UpdateViewModel
Change `iconName` in @macos/Sources/Features/Update/UpdateViewModel.swift to be an optional, return nil for blank. Update usage.
The user wants me to:
- Change the
iconNameproperty in UpdateViewModel.swift to be an optional (String?) - Return nil instead of empty strings for blank cases
- Update any usage of this property
Let me first check the current implementation - I can see that iconName currently returns empty strings ("") for certain states like .idle, .downloading, and .extracting.
I need to:
- Change the return type from
StringtoString? - Change the empty string returns to
nil - Find where
iconNameis used and update those usages to handle the optional
First, let me search for where iconName is used in the codebase.
iconName 3 matches
in
macos
@@ -113,20 +113,20 @@
return "Update Failed"
}
}
var iconName: String {
var iconName: String? {
switch state {
case .idle:
return ""
return nil
case .permissionRequest:
return "questionmark.circle"
case .checking:
return "arrow.triangle.2.circlepath"
case .updateAvailable:
return "arrow.down.circle.fill"
case .downloading, .extracting:
return ""
return nil
case .readyToInstall:
return "checkmark.circle.fill"
case .installing:
return "gear"
+14
-10
~10
@@ -26,21 +26,25 @@
case .extracting(let extracting):
ProgressRingView(progress: extracting.progress)
case .checking, .installing:
Image(systemName: model.iconName)
.rotationEffect(.degrees(rotationAngle))
.onAppear {
withAnimation(.linear(duration: 2.5).repeatForever(autoreverses: false)) {
rotationAngle = 360
if let iconName = model.iconName {
Image(systemName: iconName)
.rotationEffect(.degrees(rotationAngle))
.onAppear {
withAnimation(.linear(duration: 2.5).repeatForever(autoreverses: false)) {
rotationAngle = 360
}
}
}
.onDisappear {
rotationAngle = 0
}
.onDisappear {
rotationAngle = 0
}
}
default:
Image(systemName: model.iconName)
if let iconName = model.iconName {
Image(systemName: iconName)
}
}
}
}
Done. Changed iconName to String? returning nil for blank states, and updated UpdateBadge.swift to handle the optional with if let bindings.
Let me look at the text and stateTooltip properties. They do seem very similar. Looking at them:
stateTooltip:
- idle: ""
- permissionRequest: "Update permission required"
- checking: "Checking for updates…"
- updateAvailable: "Update available: (version)"
- downloading: "Downloading %.0f%%…" or "Downloading…"
- extracting: "Preparing %.0f%%…"
- readyToInstall: "Ready to install"
- installing: "Installing…"
- notFound: "No updates found"
- error: error.localizedDescription
text:
- idle: ""
- permissionRequest: "Update Permission"
- checking: "Checking for Updates…"
- updateAvailable: "Update Available: (version)"
- downloading: "Downloading: %.0f%%" or "Downloading…"
- extracting: "Preparing: %.0f%%"
- readyToInstall: "Install Update"
- installing: "Installing…"
- notFound: "No Updates Available"
- error: "Update Failed"
They're very similar. The main differences:
- permissionRequest: "Update permission required" vs "Update Permission"
- checking: "Checking for updates…" vs "Checking for Updates…" (capitalization)
- updateAvailable: "Update available:" vs "Update Available:"
- downloading: "Downloading %.0f%%…" vs "Downloading: %.0f%%" (colon vs ellipsis)
- extracting: "Preparing %.0f%%…" vs "Preparing: %.0f%%"
- readyToInstall: "Ready to install" vs "Install Update"
- notFound: "No updates found" vs "No Updates Available"
- error: localizedDescription vs "Update Failed"
I should search for where these are used to understand which one to keep and how to unify them.
\.text 32 matches
in
macos
stateTooltip 2 matches
in
macos
@@ -55,37 +55,8 @@
class UpdateViewModel: ObservableObject {
@Published var state: UpdateState = .idle
var stateTooltip: String {
switch state {
case .idle:
return ""
case .permissionRequest:
return "Update permission required"
case .checking:
return "Checking for updates…"
case .updateAvailable(let update):
return "Update available: \(update.appcastItem.displayVersionString)"
case .downloading(let download):
if let expectedLength = download.expectedLength, expectedLength > 0 {
let progress = Double(download.progress) / Double(expectedLength)
return String(format: "Downloading %.0f%%…", progress * 100)
}
return "Downloading…"
case .extracting(let extracting):
return String(format: "Preparing %.0f%%…", extracting.progress * 100)
case .readyToInstall:
return "Ready to install"
case .installing:
return "Installing…"
case .notFound:
return "No updates found"
case .error(let err):
return err.error.localizedDescription
}
}
var text: String {
switch state {
case .idle:
return ""
@@ -108,10 +79,10 @@
case .installing:
return "Installing…"
case .notFound:
return "No Updates Available"
case .error:
return "Update Failed"
case .error(let err):
return err.error.localizedDescription
}
}
var iconName: String? {
@@ -39,7 +39,7 @@
.foregroundColor(model.foregroundColor)
.contentShape(Capsule())
}
.buttonStyle(.plain)
.help(model.stateTooltip)
.help(model.text)
}
}
Public
Thread
3mo ago
ghostty-org/ghostty
smart (Sonnet 4.5)
CLI
3
prompts
3% of 968k
3
files
+36
-45
~16
Reference Thread
T-0477a9aa-e1ff-4df0-bf16-eed5131b6c14