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
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,31 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.0.2] - 2024-12-06
### Changed
- Added a softer shade of orange and red when light mode is enabled to improve visibility and readability.
- If launching the app using a URL scheme, the app will now exit **only** when `supportcompanion://` is used. This allows for the app to be started using a URL scheme and remain open when using `supportcompanion://home` or similar. Example:

Will exit when the window is closed:
```bash
open supportcompanion://
```

Will remain open when the window is closed:
```bash
open supportcompanion://home
```

### Added
- Option to hide Categories and Dividers on the Desktop Info view. This allows for a cleaner and more focused view of the information displayed. Example configuration:
```xml
<key>DesktopInfoHideItems</key>
<array>
<string>Category</string>
<string>Divider</string>
</array>
```

## [2.0.1] - 2024-12-05
### Changed
- Added a preinstall script that will uninstall version 1.X if found.
Expand Down
7 changes: 7 additions & 0 deletions SupportCompanion/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,20 @@ class AppDelegate: NSObject, NSApplicationDelegate {
let appStateManager = AppStateManager.shared
var mainWindow: NSWindow?
static var urlLaunch = false
static var shouldExit = false
private var notificationDelegate: NotificationDelegate?
private var cancellables: Set<AnyCancellable> = []
@AppStorage("isDarkMode") private var isDarkMode: Bool = false


func application(_ application: NSApplication, open urls: [URL]) {
guard let url = urls.first else { return }
switch url.host?.lowercased() {
case nil:
AppDelegate.shouldExit = true
default:
AppDelegate.shouldExit = false
}
AppDelegate.urlLaunch = true
showWindow()
NotificationCenter.default.post(name: .handleIncomingURL, object: url)
Expand Down
73 changes: 52 additions & 21 deletions SupportCompanion/Components/CardData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Foundation
import SwiftUI

struct CardData: View {
@Environment(\.colorScheme) var colorScheme
let info: [(key: String, display: String, value: InfoValue)]
let customContent: (String, InfoValue) -> AnyView

Expand Down Expand Up @@ -56,7 +57,7 @@ struct CardData: View {
case Constants.Battery.Keys.temperature:
temperatureContent(value: value)
case Constants.PlatformSSO.Keys.registrationCompleted:
pssoRegistrationContent(value: value, color: colorForValue(key: key, value: value))
pssoRegistrationContent(value: value)
default:
defaultText(value: value, key: key)
}
Expand All @@ -65,19 +66,31 @@ struct CardData: View {

/// Displays health-specific content with color coding
private func healthContent(value: InfoValue) -> some View {
Text(value.displayValue)
.foregroundColor(colorForValue(key: "Health", value: value))
.font(.system(size: 14))
+ Text("%")
.font(.system(size: 14))
let color = colorForValue(key: Constants.Battery.Keys.health, value: value)
let isGreen = color == .green

return Group {
Text(value.displayValue)
.foregroundColor(color)
.font(.system(size: 14))
.shadow(color: isGreen ? .black.opacity(0.4) : .clear, radius: 1, x: 0, y: 1)
Text("%")
.font(.system(size: 14))
}
}

private func temperatureContent(value: InfoValue) -> some View {
Text(value.displayValue)
.foregroundColor(colorForValue(key: Constants.Battery.Keys.temperature, value: value))
.font(.system(size: 14))
+ Text("°C")
.font(.system(size: 14))
let color = colorForValue(key: Constants.Battery.Keys.temperature, value: value)
let isGreen = color == .green

return Group {
Text(value.displayValue)
.foregroundColor(color)
.font(.system(size: 14))
.shadow(color: isGreen ? .black.opacity(0.4) : .clear, radius: 1, x: 0, y: 1)
Text("°C")
.font(.system(size: 14))
}
}

/// Displays generic content with a suffix (e.g., "days")
Expand All @@ -89,10 +102,14 @@ struct CardData: View {
.font(.system(size: 14))
}

private func pssoRegistrationContent(value: InfoValue, color: Color = .primary) -> some View {
Text(value.displayValue)
private func pssoRegistrationContent(value: InfoValue) -> some View {
let color = colorForValue(key: Constants.PlatformSSO.Keys.registrationCompleted, value: value)
let isGreen = color == .green

return Text(value.displayValue)
.foregroundColor(colorForValue(key: Constants.PlatformSSO.Keys.registrationCompleted, value: value))
.font(.system(size: 14))
.shadow(color: isGreen ? .black.opacity(0.4) : .clear, radius: 1, x: 0, y: 1)
}

/// Displays FileVault-specific content with icons
Expand All @@ -101,9 +118,10 @@ struct CardData: View {
if value.displayValue == "Enabled" {
Image(systemName: "checkmark.circle.fill")
.foregroundColor(.green)
.shadow(color: .black.opacity(0.4), radius: 1, x: 0, y: 1)
} else {
Image(systemName: "xmark.circle.fill")
.foregroundColor(.red)
.foregroundColor((colorScheme == .light ? .redLight : .red))
}
Text(value.displayValue)
.font(.system(size: 14))
Expand All @@ -122,30 +140,34 @@ struct CardData: View {
switch key {
case "Health":
if let intValue = value.rawValue as? Int {
return intValue <= 30 ? .red : (intValue < 80 ? .orange : .green)
return intValue <= 30
? (colorScheme == .light ? .redLight : .red)
: (intValue < 80
? (colorScheme == .light ? .orangeLight : .orange)
: .green)
}
case "LastRestart":
if let intValue = value.rawValue as? Int {
return intValue > 7 ? .red : .green
return intValue > 7 ? (colorScheme == .light ? .redLight : .red) : .green
}
case "FileVault":
if let boolValue = value.rawValue as? Bool {
return !boolValue ? .red : .green
return !boolValue ? (colorScheme == .light ? .redLight : .red) : .green
}
case Constants.PlatformSSO.Keys.registrationCompleted:
if let boolValue = value.rawValue as? Bool {
return !boolValue ? .red : .green
return !boolValue ? (colorScheme == .light ? .redLight : .red) : .green
}
case Constants.KerberosSSO.Keys.expiryDays:
if let intValue = value.rawValue as? Int {
return intValue <= 30 ? .orange : (intValue < 2 ? .red : .green)
return intValue <= 30 ? (colorScheme == .light ? .orangeLight : .orange) : (intValue < 2 ? (colorScheme == .light ? .redLight : .red) : .green)
}
case Constants.Battery.Keys.temperature:
if let doubleValue = value.rawValue as? Double {
return doubleValue > 80 ? .red : (doubleValue >= 60 ? .orange : .green)
return doubleValue > 80 ? (colorScheme == .light ? .redLight : .red) : (doubleValue >= 60 ? (colorScheme == .light ? .orange : .orange) : .green)
} else if let intValue = value.rawValue as? Int {
let temperature = Double(intValue)
return temperature > 80 ? .red : (temperature >= 60 ? .orange : .green)
return temperature > 80 ? (colorScheme == .light ? .redLight : .red) : (temperature >= 60 ? (colorScheme == .light ? .orangeLight : .orange) : .green)
} else {
return .primary
}
Expand All @@ -154,4 +176,13 @@ struct CardData: View {
}
return .primary
}

struct ConditionalShadowModifier: ViewModifier {
let isGreen: Bool

func body(content: Content) -> some View {
content
.shadow(color: isGreen ? .black.opacity(0.4) : .clear, radius: 2, x: 0, y: 1)
}
}
}
2 changes: 1 addition & 1 deletion SupportCompanion/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ struct ContentView: View {
case "knowledgebase":
selectedItem = items.first(where: { $0.id == Constants.Navigation.knowledgeBase })
default:
Logger.shared.logDebug("Unhandled URL: \(url)")
selectedItem = items.first(where: { $0.id == Constants.Navigation.home })
}
}

Expand Down
12 changes: 10 additions & 2 deletions SupportCompanion/Extensions/Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ extension ToastConfig {

extension AppDelegate: NSWindowDelegate {
func windowWillClose(_ notification: Notification) {
if AppDelegate.urlLaunch {
if AppDelegate.shouldExit {
NSApplication.shared.terminate(nil)
}
Logger.shared.logDebug("Main window is closing.")
Expand All @@ -87,4 +87,12 @@ extension AppDelegate: NSWindowDelegate {

extension Notification.Name {
static let handleIncomingURL = Notification.Name("handleIncomingURL")
}
}

extension Color {
// Orange shades
static let orangeLight = Color(hue: 0.1, saturation: 0.9, brightness: 0.75) // Softer orange for light mode

// Red shades
static let redLight = Color(hue: 0.02, saturation: 0.8, brightness: 0.7) // Softer red for light mode
}
4 changes: 2 additions & 2 deletions SupportCompanion/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>CFBundleShortVersionString</key>
<string>2.0.1</string>
<string>2.0.2</string>
<key>CFBundleVersion</key>
<string>2.0.1</string>
<string>2.0.2</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
Expand Down
10 changes: 0 additions & 10 deletions SupportCompanion/Models/Storage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,6 @@ struct StorageInfo: Identifiable {
let fileVault: Bool
let usage: Double

var percentageColor: Color {
if usage > 80 {
return Color(NSColor.red)
} else if usage > 60 {
return Color(NSColor.orange)
} else {
return Color(NSColor.green)
}
}

func toKeyValuePairs() -> [(key: String, display: String, value: InfoValue)] {
return [
(
Expand Down
12 changes: 12 additions & 0 deletions SupportCompanion/ViewModels/StorageInfoManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import Combine
import SwiftUI

class StorageInfoManager: ObservableObject {
@Environment(\.colorScheme) var colorScheme

static let shared = StorageInfoManager(
storageInfo: StorageInfo(
id: UUID(),
Expand Down Expand Up @@ -38,6 +40,16 @@ class StorageInfoManager: ObservableObject {
self.updateStorageInfo()
}

func getPercentageColor(percentage: Double) -> Color {
if percentage < 50 {
return .green
} else if percentage < 80 {
return colorScheme == .light ? .orangeLight : .orange
} else {
return colorScheme == .light ? .redLight : .red
}
}

func updateStorageInfo(usagePercentage: Double = getStorageUsagePercentage()) {
DispatchQueue.main.async {
self.storageInfo = StorageInfo(
Expand Down
Loading