diff --git a/Sources/ContentView.swift b/Sources/ContentView.swift index 7cffeba9..c7708c7c 100644 --- a/Sources/ContentView.swift +++ b/Sources/ContentView.swift @@ -7789,10 +7789,6 @@ struct VerticalTabsSidebar: View { Spacer() .frame(height: trafficLightPadding) - SidebarUpdateBanner(updateViewModel: updateViewModel) - .padding(.horizontal, 8) - .padding(.top, 8) - LazyVStack(spacing: tabRowSpacing) { ForEach(Array(tabManager.tabs.enumerated()), id: \.element.id) { index, tab in TabItemView( @@ -8723,107 +8719,6 @@ private final class SidebarShortcutHintModifierMonitor: ObservableObject { } } -private struct SidebarUpdateBanner: View { - @ObservedObject var updateViewModel: UpdateViewModel - - private var bannerVersion: String? { - if let detectedUpdateVersion = updateViewModel.detectedUpdateVersion { - return detectedUpdateVersion - } - if case .updateAvailable(let update) = updateViewModel.effectiveState { - return UpdateViewModel.normalizedDetectedUpdateVersion(from: update.appcastItem.displayVersionString) - } - return nil - } - - private var titleText: String { - guard let bannerVersion else { - return String(localized: "update.available.short", defaultValue: "Update Available") - } - return String(localized: "update.available.withVersion", defaultValue: "Update Available: \(bannerVersion)") - } - - private var messageText: String { - if case .updateAvailable = updateViewModel.effectiveState { - let message = updateViewModel.description - if !message.isEmpty { - return message - } - } - return String(localized: "update.downloadAndInstall", defaultValue: "Download and install the latest version") - } - - private var actionDisabled: Bool { - switch updateViewModel.effectiveState { - case .checking, .downloading, .extracting, .installing: - return true - default: - return false - } - } - - var body: some View { - if bannerVersion != nil { - VStack(alignment: .leading, spacing: 10) { - HStack(alignment: .top, spacing: 10) { - Image(systemName: "shippingbox.fill") - .font(.system(size: 13, weight: .semibold)) - .foregroundStyle(cmuxAccentColor()) - .padding(.top, 1) - - VStack(alignment: .leading, spacing: 4) { - Text(titleText) - .font(.system(size: 12, weight: .semibold)) - .foregroundColor(.primary) - .accessibilityIdentifier("SidebarUpdateBannerTitle") - Text(messageText) - .font(.system(size: 11)) - .foregroundColor(.secondary) - .fixedSize(horizontal: false, vertical: true) - } - - Spacer(minLength: 0) - } - - HStack { - Spacer(minLength: 0) - Button(String(localized: "common.installAndRelaunch", defaultValue: "Install and Relaunch")) { - installDetectedUpdate() - } - .buttonStyle(.borderedProminent) - .controlSize(.small) - .disabled(actionDisabled) - .accessibilityIdentifier("SidebarUpdateBannerAction") - } - } - .padding(12) - .frame(maxWidth: .infinity, alignment: .leading) - .background( - RoundedRectangle(cornerRadius: 12, style: .continuous) - .fill(cmuxAccentColor().opacity(0.12)) - ) - .overlay( - RoundedRectangle(cornerRadius: 12, style: .continuous) - .stroke(cmuxAccentColor().opacity(0.28), lineWidth: 1) - ) - .contentShape(RoundedRectangle(cornerRadius: 12, style: .continuous)) - .accessibilityIdentifier("SidebarUpdateBanner") - } - } - - private func installDetectedUpdate() { - if case .updateAvailable(let update) = updateViewModel.effectiveState { - update.reply(.install) - return - } - if updateViewModel.effectiveState.isInstallable { - updateViewModel.effectiveState.confirm() - return - } - AppDelegate.shared?.attemptUpdate(nil) - } -} - private struct SidebarFooter: View { @ObservedObject var updateViewModel: UpdateViewModel let onSendFeedback: () -> Void diff --git a/cmuxUITests/UpdatePillUITests.swift b/cmuxUITests/UpdatePillUITests.swift index 099dfb93..cfa86670 100644 --- a/cmuxUITests/UpdatePillUITests.swift +++ b/cmuxUITests/UpdatePillUITests.swift @@ -124,17 +124,21 @@ final class UpdatePillUITests: XCTestCase { assertVisibleSize(noUpdatePill) } - func testSidebarUpdateBannerShowsForBackgroundDetectedUpdate() { + func testBackgroundDetectedUpdateKeepsOnlyBottomUpdatePill() { let systemSettings = XCUIApplication(bundleIdentifier: "com.apple.systempreferences") systemSettings.terminate() let app = XCUIApplication() app.launchEnvironment["CMUX_UI_TEST_MODE"] = "1" app.launchEnvironment["CMUX_UI_TEST_DETECTED_UPDATE_VERSION"] = "9.9.9" + app.launchEnvironment["CMUX_UI_TEST_UPDATE_STATE"] = "available" + app.launchEnvironment["CMUX_UI_TEST_UPDATE_VERSION"] = "9.9.9" launchAndActivate(app) - XCTAssertTrue(app.otherElements["SidebarUpdateBanner"].waitForExistence(timeout: 6.0)) - XCTAssertTrue(app.staticTexts["Update Available: 9.9.9"].waitForExistence(timeout: 2.0)) - XCTAssertTrue(app.buttons["SidebarUpdateBannerAction"].waitForExistence(timeout: 2.0)) + let pill = pillButton(app: app, expectedLabel: "Update Available: 9.9.9") + XCTAssertTrue(pill.waitForExistence(timeout: 6.0)) + assertVisibleSize(pill) + XCTAssertFalse(app.otherElements["SidebarUpdateBanner"].exists) + XCTAssertFalse(app.buttons["SidebarUpdateBannerAction"].exists) } func testNoSparklePermissionDialogIsShown() {