Skip to content

Commit 37490a3

Browse files
Merge pull request #264 from root3nl/development
v3.0.1
2 parents 1c1f1ab + 24b8f4e commit 37490a3

18 files changed

Lines changed: 152 additions & 80 deletions

File tree

src/Support.xcodeproj/project.pbxproj

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
498DB7F22E5D113A00DDC33B /* AppModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 498DB7F12E5D113A00DDC33B /* AppModel.swift */; };
8888
498DB8412E5E49D700DDC33B /* LocalPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 498DB8402E5E49D700DDC33B /* LocalPreferences.swift */; };
8989
498DB8432E5EE13A00DDC33B /* ConfiguratorSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 498DB8422E5EE13A00DDC33B /* ConfiguratorSettingsView.swift */; };
90+
499CC4672EBBA24D00ED16EC /* BackButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 499CC4662EBBA24D00ED16EC /* BackButton.swift */; };
9091
499F56732AE0832100CBDE73 /* AppCatalogSubview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 499F56722AE0832100CBDE73 /* AppCatalogSubview.swift */; };
9192
499F56752AE47A3900CBDE73 /* AppUpdatesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 499F56742AE47A3900CBDE73 /* AppUpdatesView.swift */; };
9293
499F56782AE47BE800CBDE73 /* InstalledAppItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 499F56772AE47BE800CBDE73 /* InstalledAppItem.swift */; };
@@ -251,6 +252,7 @@
251252
498DB7F12E5D113A00DDC33B /* AppModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppModel.swift; sourceTree = "<group>"; };
252253
498DB8402E5E49D700DDC33B /* LocalPreferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalPreferences.swift; sourceTree = "<group>"; };
253254
498DB8422E5EE13A00DDC33B /* ConfiguratorSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfiguratorSettingsView.swift; sourceTree = "<group>"; };
255+
499CC4662EBBA24D00ED16EC /* BackButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackButton.swift; sourceTree = "<group>"; };
254256
499F56722AE0832100CBDE73 /* AppCatalogSubview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCatalogSubview.swift; sourceTree = "<group>"; };
255257
499F56742AE47A3900CBDE73 /* AppUpdatesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppUpdatesView.swift; sourceTree = "<group>"; };
256258
499F56772AE47BE800CBDE73 /* InstalledAppItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstalledAppItem.swift; sourceTree = "<group>"; };
@@ -336,6 +338,7 @@
336338
49CB03B02E663F8200D0016D /* LegacyContentView.swift */,
337339
490B27972E8D49C700DE50E0 /* RemoveItemButtonView.swift */,
338340
491ECC592DAC5BEB00B88732 /* ItemConfigurationView.swift */,
341+
499CC4662EBBA24D00ED16EC /* BackButton.swift */,
339342
4915291B259CD38800056B5F /* EffectsView.swift */,
340343
4915290C259CCF7A00056B5F /* NotificationBadgeView.swift */,
341344
0A24AB432624CABB004208C4 /* NotificationBadgeTextView.swift */,
@@ -761,6 +764,7 @@
761764
0A4A7388260208B500927DAB /* UptimeSubview.swift in Sources */,
762765
491ECC5A2DAC5BEB00B88732 /* ItemConfigurationView.swift in Sources */,
763766
498DB8432E5EE13A00DDC33B /* ConfiguratorSettingsView.swift in Sources */,
767+
499CC4672EBBA24D00ED16EC /* BackButton.swift in Sources */,
764768
49BF03FC2BC0BE3A00AB7152 /* FileUtilities.swift in Sources */,
765769
49822CE324B4C3F100E8DE54 /* AppDelegate.swift in Sources */,
766770
4934C79A2B99317000268CE2 /* SoftwareUpdateDeclarationModel.swift in Sources */,
@@ -821,7 +825,7 @@
821825
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application";
822826
CODE_SIGN_STYLE = Manual;
823827
CREATE_INFOPLIST_SECTION_IN_BINARY = YES;
824-
CURRENT_PROJECT_VERSION = 94;
828+
CURRENT_PROJECT_VERSION = 100;
825829
DEAD_CODE_STRIPPING = YES;
826830
DEVELOPMENT_TEAM = "";
827831
"DEVELOPMENT_TEAM[sdk=macosx*]" = 98LJ4XBGYK;
@@ -860,7 +864,7 @@
860864
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application";
861865
CODE_SIGN_STYLE = Manual;
862866
CREATE_INFOPLIST_SECTION_IN_BINARY = YES;
863-
CURRENT_PROJECT_VERSION = 94;
867+
CURRENT_PROJECT_VERSION = 100;
864868
DEAD_CODE_STRIPPING = YES;
865869
DEVELOPMENT_TEAM = "";
866870
"DEVELOPMENT_TEAM[sdk=macosx*]" = 98LJ4XBGYK;
@@ -897,7 +901,7 @@
897901
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application";
898902
CODE_SIGN_STYLE = Manual;
899903
COMBINE_HIDPI_IMAGES = YES;
900-
CURRENT_PROJECT_VERSION = 94;
904+
CURRENT_PROJECT_VERSION = 100;
901905
DEVELOPMENT_TEAM = "";
902906
"DEVELOPMENT_TEAM[sdk=macosx*]" = 98LJ4XBGYK;
903907
ENABLE_HARDENED_RUNTIME = YES;
@@ -930,7 +934,7 @@
930934
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application";
931935
CODE_SIGN_STYLE = Manual;
932936
COMBINE_HIDPI_IMAGES = YES;
933-
CURRENT_PROJECT_VERSION = 94;
937+
CURRENT_PROJECT_VERSION = 100;
934938
DEVELOPMENT_TEAM = "";
935939
"DEVELOPMENT_TEAM[sdk=macosx*]" = 98LJ4XBGYK;
936940
ENABLE_HARDENED_RUNTIME = YES;
@@ -1081,7 +1085,7 @@
10811085
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application";
10821086
CODE_SIGN_STYLE = Manual;
10831087
COMBINE_HIDPI_IMAGES = YES;
1084-
CURRENT_PROJECT_VERSION = 94;
1088+
CURRENT_PROJECT_VERSION = 100;
10851089
DEVELOPMENT_ASSET_PATHS = "\"Support/Preview Content\"";
10861090
DEVELOPMENT_TEAM = "";
10871091
"DEVELOPMENT_TEAM[sdk=macosx*]" = 98LJ4XBGYK;
@@ -1128,7 +1132,7 @@
11281132
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application";
11291133
CODE_SIGN_STYLE = Manual;
11301134
COMBINE_HIDPI_IMAGES = YES;
1131-
CURRENT_PROJECT_VERSION = 94;
1135+
CURRENT_PROJECT_VERSION = 100;
11321136
DEVELOPMENT_ASSET_PATHS = "\"Support/Preview Content\"";
11331137
DEVELOPMENT_TEAM = "";
11341138
"DEVELOPMENT_TEAM[sdk=macosx*]" = 98LJ4XBGYK;

src/Support/Info.plist

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
<key>CFBundlePackageType</key>
1818
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
1919
<key>CFBundleShortVersionString</key>
20-
<string>3.0</string>
20+
<string>3.0.1</string>
2121
<key>CFBundleVersion</key>
22-
<string>94</string>
22+
<string>100</string>
2323
<key>LSApplicationCategoryType</key>
2424
<string>public.app-category.utilities</string>
2525
<key>LSMinimumSystemVersion</key>

src/Support/Views/AppCatalog/AppUpdatesView.swift

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,7 @@ struct AppUpdatesView: View {
5858
Button(action: {
5959
appCatalogController.showAppUpdates.toggle()
6060
}) {
61-
if #available(macOS 26, *) {
62-
Image(systemName: "chevron.backward")
63-
.font(.system(size: 16))
64-
.padding(4)
65-
} else {
66-
Ellipse()
67-
.foregroundColor(colorScheme == .dark ? .white.opacity(0.2) : .black.opacity(0.1))
68-
.overlay(
69-
Image(systemName: "chevron.backward")
70-
)
71-
.frame(width: 26, height: 26)
72-
}
61+
BackButton()
7362
}
7463
.modify {
7564
if #available(macOS 26, *) {

src/Support/Views/BackButton.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//
2+
// BackButton.swift
3+
// Support
4+
//
5+
// Created by Jordy Witteman on 05/11/2025.
6+
//
7+
8+
import SwiftUI
9+
10+
struct BackButton: View {
11+
12+
// Dark Mode detection
13+
@Environment(\.colorScheme) var colorScheme
14+
15+
var body: some View {
16+
if #available(macOS 26, *) {
17+
Label(NSLocalizedString("BACK", comment: ""), systemImage: "chevron.backward")
18+
.labelStyle(.iconOnly)
19+
.font(.system(size: 12))
20+
.frame(width: 12, height: 12)
21+
.padding(4)
22+
} else {
23+
Ellipse()
24+
.foregroundColor(colorScheme == .dark ? .white.opacity(0.2) : .black.opacity(0.1))
25+
.overlay(
26+
Image(systemName: "chevron.backward")
27+
)
28+
.frame(width: 26, height: 26)
29+
.accessibilityLabel(NSLocalizedString("BACK", comment: ""))
30+
}
31+
}
32+
}
33+
34+
#Preview {
35+
BackButton()
36+
}

src/Support/Views/ButtonTemplateViews/Item.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ struct Item: View {
9494
.foregroundStyle(.white.opacity(colorScheme == .dark ? 0.8 : 1.0))
9595
.lineLimit(2)
9696

97-
if let subtitle = subtitle {
97+
if let subtitle = subtitle, !subtitle.isEmpty {
9898
if hoverView && showSubtitle {
9999
// Show the subtitle when hover animation is enabled
100100
Text(subtitle.replaceLocalVariables(computerInfo: computerinfo, userInfo: userinfo))
@@ -215,7 +215,7 @@ struct Item: View {
215215
.font(.system(.body, design: .rounded)).fontWeight(.medium)
216216
.lineLimit(2)
217217

218-
if let subtitle = subtitle {
218+
if let subtitle = subtitle, !subtitle.isEmpty {
219219
if hoverView && showSubtitle {
220220
// Show the subtitle when hover animation is enabled
221221
Text(subtitle.replaceLocalVariables(computerInfo: computerinfo, userInfo: userinfo))

src/Support/Views/ButtonTemplateViews/ItemExtension.swift

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ struct ItemExtension: View {
6161
@AppStorage private var extensionValue: String?
6262
@AppStorage private var extensionLoading: Bool?
6363
@AppStorage private var extensionAlert: Bool?
64+
@AppStorage private var extensionSymbol: String?
65+
@AppStorage private var extensionActionType: String?
66+
@AppStorage private var extensionAction: String?
6467

6568
init(title: String,
6669
subtitle: String? = nil,
@@ -97,8 +100,37 @@ struct ItemExtension: View {
97100
self._extensionValue = AppStorage(extensionIdentifier, store: .standard)
98101
self._extensionLoading = AppStorage("\(extensionIdentifier)_loading", store: .standard)
99102
self._extensionAlert = AppStorage("\(extensionIdentifier)_alert", store: .standard)
103+
self._extensionSymbol = AppStorage("\(extensionIdentifier)_symbol", store: .standard)
104+
self._extensionActionType = AppStorage("\(extensionIdentifier)_action_type", store: .standard)
105+
self._extensionAction = AppStorage("\(extensionIdentifier)_action", store: .standard)
106+
}
107+
108+
// Show dynamic SF Symbol or MDM managed SF Symbol
109+
var activeExtensionSymbol: String {
110+
if let extensionSymbol {
111+
return extensionSymbol
112+
} else {
113+
return image
114+
}
100115
}
101116

117+
// Dynamic action type or MDM managed action type
118+
var activeExtensionActionType: String? {
119+
if let extensionActionType {
120+
return extensionActionType
121+
} else {
122+
return linkType
123+
}
124+
}
125+
126+
// Dynamic action or MDM managed action
127+
var activeExtensionAction: String? {
128+
if let extensionAction {
129+
return extensionAction
130+
} else {
131+
return link
132+
}
133+
}
102134

103135
var body: some View {
104136

@@ -120,7 +152,7 @@ struct ItemExtension: View {
120152
Ellipse()
121153
.foregroundColor(.white)
122154
.overlay(
123-
Image(systemName: image)
155+
Image(systemName: activeExtensionSymbol)
124156
.foregroundColor(symbolColor)
125157
.font(.system(size: 18))
126158
)
@@ -226,10 +258,10 @@ struct ItemExtension: View {
226258
.accessibilityHidden(true)
227259
} else {
228260
Ellipse()
229-
.foregroundColor(hoverView && link != "" ? .primary : symbolColor)
261+
.foregroundColor(hoverView && activeExtensionAction != "" ? .primary : symbolColor)
230262
.overlay(
231-
Image(systemName: image)
232-
.foregroundColor(hoverView && link != "" ? Color("hoverColor") : Color.white)
263+
Image(systemName: activeExtensionSymbol)
264+
.foregroundColor(hoverView && activeExtensionAction != "" ? Color("hoverColor") : Color.white)
233265
)
234266
.frame(width: 26, height: 26)
235267
.padding(.leading, 10)
@@ -264,7 +296,7 @@ struct ItemExtension: View {
264296
}
265297
.frame(width: Constants.largeItemWidth, height: Constants.itemLegacyHeight)
266298
.accessibilityLabel(title + ", " + (subtitle ?? ""))
267-
.background(hoverView && hoverEffectEnable && link != "" ? EffectsView(material: NSVisualEffectView.Material.windowBackground, blendingMode: NSVisualEffectView.BlendingMode.withinWindow) : EffectsView(material: NSVisualEffectView.Material.popover, blendingMode: NSVisualEffectView.BlendingMode.withinWindow))
299+
.background(hoverView && hoverEffectEnable && activeExtensionAction != "" ? EffectsView(material: NSVisualEffectView.Material.windowBackground, blendingMode: NSVisualEffectView.BlendingMode.withinWindow) : EffectsView(material: NSVisualEffectView.Material.popover, blendingMode: NSVisualEffectView.BlendingMode.withinWindow))
268300
.cornerRadius(10)
269301
// Apply gray and black border in Dark Mode to better view the buttons like Control Center
270302
.modifier(DarkModeBorder())
@@ -318,35 +350,35 @@ struct ItemExtension: View {
318350

319351
func tapGesture() {
320352
// Don't do anything when no link is specified
321-
guard link != "" else {
353+
guard activeExtensionAction != "" else {
322354
logger.debug("No link specified for \(title, privacy: .public), button disabled...")
323355
return
324356
}
325357

326-
if linkType == "App" {
358+
if activeExtensionActionType == "App" {
327359
openApp()
328-
} else if linkType == "URL" {
360+
} else if activeExtensionActionType == "URL" {
329361
openLink()
330-
} else if linkType == "Command" {
362+
} else if activeExtensionActionType == "Command" {
331363
runCommand()
332364
// MARK: - DistributedNotification is deprecated, use PrivilegedScript instead
333-
} else if linkType == "DistributedNotification" || linkType == "PrivilegedScript" {
334-
guard let link else {
365+
} else if activeExtensionActionType == "DistributedNotification" || activeExtensionActionType == "PrivilegedScript" {
366+
guard let activeExtensionAction else {
335367
return
336368
}
337369
Task {
338-
await runPrivilegedCommand(command: link, key: "Action")
370+
await runPrivilegedCommand(command: activeExtensionAction, key: "Action")
339371
}
340372
} else {
341373
self.showingAlert.toggle()
342-
logger.error("Invalid Link Type: \(linkType!)")
374+
logger.error("Invalid Link Type: \(activeExtensionActionType!)")
343375
}
344376
}
345377

346378
// Open application with given Bundle Identifier
347379
func openApp() {
348380

349-
guard let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: link ?? "")
381+
guard let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: activeExtensionAction ?? "")
350382
// Show alert when there is an error
351383
else {
352384
self.showingAlert.toggle()
@@ -361,7 +393,7 @@ struct ItemExtension: View {
361393

362394
// Open URL
363395
func openLink() {
364-
guard let url = URL(string: link ?? "")
396+
guard let url = URL(string: activeExtensionAction ?? "")
365397
// Show alert when there is an error
366398
else {
367399
self.showingAlert.toggle()
@@ -381,7 +413,7 @@ struct ItemExtension: View {
381413
let task = Process()
382414
let pipe = Pipe()
383415

384-
let command = link?.replaceLocalVariables(computerInfo: computerinfo, userInfo: userinfo)
416+
let command = activeExtensionAction?.replaceLocalVariables(computerInfo: computerinfo, userInfo: userinfo)
385417

386418
task.standardOutput = pipe
387419
task.standardError = pipe

src/Support/Views/ButtonTemplateViews/ProgressBarItem.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,20 @@ struct ProgressBarItem: View {
6969
ProgressView(value: percentage , total: 120)
7070
.padding(.trailing, 14)
7171
.accessibilityHidden(true)
72+
.modify {
73+
if percentage >= 108 {
74+
// Show red bar if more than 90% of 120 points (108)
75+
$0
76+
.tint(.red)
77+
} else if notificationBadgeBool ?? false && percentage < 108 {
78+
// Show orange bar if optional storageLimit is reached and still below 90%
79+
$0
80+
.tint(.orange)
81+
} else {
82+
$0
83+
.tint(symbolColor)
84+
}
85+
}
7286

7387
}
7488
.accessibilityElement(children: .combine)

src/Support/Views/ItemConfigurationView.swift

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -90,18 +90,7 @@ struct ItemConfigurationView: View {
9090
Button(action: {
9191
preferences.showItemConfiguration = false
9292
}) {
93-
if #available(macOS 26, *) {
94-
Image(systemName: "chevron.backward")
95-
.font(.system(size: 16))
96-
.padding(4)
97-
} else {
98-
Ellipse()
99-
.foregroundColor(colorScheme == .dark ? .white.opacity(0.2) : .black.opacity(0.1))
100-
.overlay(
101-
Image(systemName: "chevron.backward")
102-
)
103-
.frame(width: 26, height: 26)
104-
}
93+
BackButton()
10594
}
10695
.modify {
10796
if #available(macOS 26, *) {

0 commit comments

Comments
 (0)