Skip to content

Commit 3f26149

Browse files
committed
cleanup
1 parent a364763 commit 3f26149

File tree

9 files changed

+523
-59
lines changed

9 files changed

+523
-59
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ localOnly/
22
.DS_Store
33
*.xcuserstate
44
*.xcbkptlist
5+
6+
**/TelemetryDeckConfig.swift

Object Info.xcodeproj/project.pbxproj

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
B5E61EBA25A8BF070047A25F /* Globals.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E61EB925A8BF070047A25F /* Globals.swift */; };
2121
CE03BF6E2E0B8F15000EADA9 /* ResourceCheck.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE03BF6D2E0B8F15000EADA9 /* ResourceCheck.swift */; };
2222
CE03BF722E0B9142000EADA9 /* WriteToLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE03BF712E0B9142000EADA9 /* WriteToLog.swift */; };
23+
CECA956C2EF0BF3500EC8F63 /* AboutVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = CECA956B2EF0BF3500EC8F63 /* AboutVC.swift */; };
24+
CECA95F22EF144E300EC8F63 /* TelemetryDeckConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = CECA95F12EF144E300EC8F63 /* TelemetryDeckConfig.swift */; };
25+
CEFD664C2EEE025500D748BF /* TelemetryDeck in Frameworks */ = {isa = PBXBuildFile; productRef = CEFD664B2EEE025500D748BF /* TelemetryDeck */; };
2326
/* End PBXBuildFile section */
2427

2528
/* Begin PBXFileReference section */
@@ -40,6 +43,8 @@
4043
CE03BF6D2E0B8F15000EADA9 /* ResourceCheck.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourceCheck.swift; sourceTree = "<group>"; };
4144
CE03BF712E0B9142000EADA9 /* WriteToLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WriteToLog.swift; sourceTree = "<group>"; };
4245
CE57AAA72D14C930007CF27B /* Object Info legacy.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Object Info legacy.entitlements"; sourceTree = "<group>"; };
46+
CECA956B2EF0BF3500EC8F63 /* AboutVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutVC.swift; sourceTree = "<group>"; };
47+
CECA95F12EF144E300EC8F63 /* TelemetryDeckConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TelemetryDeckConfig.swift; sourceTree = "<group>"; };
4348
CECDF9F32D1495590039CD84 /* Object Info.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Object Info.entitlements"; sourceTree = "<group>"; };
4449
/* End PBXFileReference section */
4550

@@ -48,6 +53,7 @@
4853
isa = PBXFrameworksBuildPhase;
4954
buildActionMask = 2147483647;
5055
files = (
56+
CEFD664C2EEE025500D748BF /* TelemetryDeck in Frameworks */,
5157
);
5258
runOnlyForDeploymentPostprocessing = 0;
5359
};
@@ -81,6 +87,7 @@
8187
B5932DDD1F6FF3FC00720831 /* Object Info */ = {
8288
isa = PBXGroup;
8389
children = (
90+
CECA956B2EF0BF3500EC8F63 /* AboutVC.swift */,
8491
B54D66982A61083500998963 /* Alert.swift */,
8592
B5D53F122BA65CB2009493E2 /* ApiAction.swift */,
8693
B5932DDE1F6FF3FC00720831 /* AppDelegate.swift */,
@@ -89,6 +96,7 @@
8996
B5767BA9278A195900A1713E /* JamfPro.swift */,
9097
B5D53F102BA60048009493E2 /* LoginVC.swift */,
9198
CE03BF6D2E0B8F15000EADA9 /* ResourceCheck.swift */,
99+
CECA95F12EF144E300EC8F63 /* TelemetryDeckConfig.swift */,
92100
B5932DE01F6FF3FC00720831 /* ViewController.swift */,
93101
CE03BF712E0B9142000EADA9 /* WriteToLog.swift */,
94102
B5932DE21F6FF3FC00720831 /* Assets.xcassets */,
@@ -159,6 +167,9 @@
159167
Base,
160168
);
161169
mainGroup = B5932DD21F6FF3FC00720831;
170+
packageReferences = (
171+
CEFD664A2EEE025500D748BF /* XCRemoteSwiftPackageReference "SwiftSDK" */,
172+
);
162173
productRefGroup = B5932DDC1F6FF3FC00720831 /* Products */;
163174
projectDirPath = "";
164175
projectRoot = "";
@@ -186,13 +197,15 @@
186197
isa = PBXSourcesBuildPhase;
187198
buildActionMask = 2147483647;
188199
files = (
200+
CECA95F22EF144E300EC8F63 /* TelemetryDeckConfig.swift in Sources */,
189201
B5E61EBA25A8BF070047A25F /* Globals.swift in Sources */,
190202
B5767BAA278A195900A1713E /* JamfPro.swift in Sources */,
191203
B5D53F112BA60048009493E2 /* LoginVC.swift in Sources */,
192204
B5D53F132BA65CB2009493E2 /* ApiAction.swift in Sources */,
193205
B58D8834250BF46C00E8D6E4 /* Credentials.swift in Sources */,
194206
B5932DE11F6FF3FC00720831 /* ViewController.swift in Sources */,
195207
B5932DDF1F6FF3FC00720831 /* AppDelegate.swift in Sources */,
208+
CECA956C2EF0BF3500EC8F63 /* AboutVC.swift in Sources */,
196209
CE03BF6E2E0B8F15000EADA9 /* ResourceCheck.swift in Sources */,
197210
B54D66992A61083500998963 /* Alert.swift in Sources */,
198211
CE03BF722E0B9142000EADA9 /* WriteToLog.swift in Sources */,
@@ -347,7 +360,7 @@
347360
"@executable_path/../Frameworks",
348361
);
349362
MACOSX_DEPLOYMENT_TARGET = 13.0;
350-
MARKETING_VERSION = 3.2.1;
363+
MARKETING_VERSION = 3.3.0;
351364
PRODUCT_BUNDLE_IDENTIFIER = com.jamf.pse.ObjectInfo;
352365
PRODUCT_NAME = "$(TARGET_NAME)";
353366
SWIFT_VERSION = 5.0;
@@ -373,7 +386,7 @@
373386
"@executable_path/../Frameworks",
374387
);
375388
MACOSX_DEPLOYMENT_TARGET = 13.0;
376-
MARKETING_VERSION = 3.2.1;
389+
MARKETING_VERSION = 3.3.0;
377390
PRODUCT_BUNDLE_IDENTIFIER = com.jamf.pse.ObjectInfo;
378391
PRODUCT_NAME = "$(TARGET_NAME)";
379392
SWIFT_VERSION = 5.0;
@@ -402,6 +415,25 @@
402415
defaultConfigurationName = Release;
403416
};
404417
/* End XCConfigurationList section */
418+
419+
/* Begin XCRemoteSwiftPackageReference section */
420+
CEFD664A2EEE025500D748BF /* XCRemoteSwiftPackageReference "SwiftSDK" */ = {
421+
isa = XCRemoteSwiftPackageReference;
422+
repositoryURL = "https://github.com/TelemetryDeck/SwiftSDK";
423+
requirement = {
424+
kind = upToNextMajorVersion;
425+
minimumVersion = 2.11.0;
426+
};
427+
};
428+
/* End XCRemoteSwiftPackageReference section */
429+
430+
/* Begin XCSwiftPackageProductDependency section */
431+
CEFD664B2EEE025500D748BF /* TelemetryDeck */ = {
432+
isa = XCSwiftPackageProductDependency;
433+
package = CEFD664A2EEE025500D748BF /* XCRemoteSwiftPackageReference "SwiftSDK" */;
434+
productName = TelemetryDeck;
435+
};
436+
/* End XCSwiftPackageProductDependency section */
405437
};
406438
rootObject = B5932DD31F6FF3FC00720831 /* Project object */;
407439
}

Object Info.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ObjectInfo/AboutVC.swift

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
//
2+
// Copyright 2025 Jamf. All rights reserved.
3+
//
4+
5+
import AppKit
6+
import Cocoa
7+
import Foundation
8+
9+
class AboutVC: NSViewController {
10+
11+
@IBOutlet weak var optOut_button: NSButton!
12+
13+
@IBAction func optOut_action(_ sender: NSButton) {
14+
UserDefaults.standard.set(sender.state == .on, forKey: "optOut")
15+
TelemetryDeckConfig.OptOut = (sender.state == .on)
16+
}
17+
18+
let supportText = """
19+
This application helps identify how items are used/scoped. Identifies how/where items like extension attributes, scripts, packages, configuration payloads are used.
20+
21+
By default Object Info sends basic hardware, OS, and usage data for the app. Data is sent anonymously to https://telemetrydeck.com and used to aid in application development. To disable the sending of data click the 'Opt out of analytics' below.
22+
23+
"""
24+
25+
let feedback = """
26+
27+
Please share feedback by filing an issue.
28+
29+
"""
30+
31+
let warningText = """
32+
33+
Due to occasional changes to the API and introduction of new items the results may not include some items.
34+
35+
"""
36+
37+
let agreementText = """
38+
39+
This software is licensed under the terms of the Jamf Concepts Use Agreement
40+
41+
Copyright xxxx, Jamf Software, LLC.
42+
"""
43+
44+
func formattedText() -> NSAttributedString {
45+
let basicFont = NSFont.systemFont(ofSize: 12)
46+
let basicAttributes = [NSAttributedString.Key.font: basicFont, .foregroundColor: defaultTextColor]
47+
let supportText = NSMutableAttributedString(string: supportText, attributes: basicAttributes)
48+
49+
let tdRange = supportText.mutableString.range(of: "https://telemetrydeck.com")
50+
if tdRange.location != NSNotFound {
51+
supportText.addAttribute(NSAttributedString.Key.link, value: "https://telemetrydeck.com", range: tdRange)
52+
}
53+
54+
let aboutString = supportText
55+
56+
let currentYear = "\(Calendar.current.component(.year, from: Date()))"
57+
58+
let feedbackString = NSMutableAttributedString(string: feedback, attributes: basicAttributes)
59+
// let feedbackRange = feedbackString.mutableString.range(of: "<repoPlaceHolder>/api-roles-and-clients/discussions")
60+
// if feedbackRange.location != NSNotFound {
61+
// feedbackString.addAttribute(NSAttributedString.Key.link, value: "<repoPlaceHolder>/api-roles-and-clients/discussions", range: feedbackRange)
62+
// }
63+
// aboutString.append(feedbackString)
64+
65+
let issuesRange = feedbackString.mutableString.range(of: "filing an issue")
66+
if issuesRange.location != NSNotFound {
67+
feedbackString.addAttribute(NSAttributedString.Key.link, value: "https://github.com/Jamf-Concepts/api-roles-and-clients/issues", range: issuesRange)
68+
}
69+
aboutString.append(feedbackString)
70+
71+
let warningFont = NSFont(name: "HelveticaNeue-Italic", size: 12)
72+
// let warningFont = NSFont.systemFont(ofSize: 12)
73+
let warningAttributes = [NSAttributedString.Key.font: warningFont, .foregroundColor: defaultTextColor]
74+
let warningString = NSMutableAttributedString(string: warningText, attributes: warningAttributes as [NSAttributedString.Key : Any])
75+
aboutString.append(warningString)
76+
77+
let agreementString = NSMutableAttributedString(string: agreementText.replacingOccurrences(of: "Copyright xxxx", with: "Copyright \(currentYear)"), attributes: basicAttributes)
78+
let foundRange = agreementString.mutableString.range(of: "Jamf Concepts Use Agreement")
79+
if foundRange.location != NSNotFound {
80+
agreementString.addAttribute(NSAttributedString.Key.link, value: "https://resources.jamf.com/documents/jamf-concept-projects-use-agreement.pdf", range: foundRange)
81+
}
82+
aboutString.append(agreementString)
83+
84+
return aboutString
85+
}
86+
87+
@IBOutlet weak var about_image: NSImageView!
88+
89+
@IBOutlet weak var appName_textfield: NSTextField!
90+
@IBOutlet weak var version_textfield: NSTextField!
91+
@IBOutlet var license_textfield: NSTextView!
92+
93+
94+
@objc func interfaceModeChanged(sender: NSNotification) {
95+
setTheme(darkMode: isDarkMode)
96+
}
97+
func setTheme(darkMode: Bool) {
98+
self.view.layer?.backgroundColor = darkMode ? CGColor.init(gray: 0.2, alpha: 1.0):CGColor.init(gray: 0.2, alpha: 0.2)
99+
defaultTextColor = isDarkMode ? NSColor.white:NSColor.black
100+
license_textfield.textStorage?.setAttributedString(formattedText())
101+
}
102+
103+
override func viewDidLoad() {
104+
super.viewDidLoad()
105+
106+
optOut_button.state = UserDefaults.standard.bool(forKey: "optOut") ? .on : .off
107+
108+
DistributedNotificationCenter.default.addObserver(self, selector: #selector(interfaceModeChanged(sender:)), name: NSNotification.Name(rawValue: "AppleInterfaceThemeChangedNotification"), object: nil)
109+
110+
// Do any additional setup after loading the view.
111+
self.view.wantsLayer = true
112+
setTheme(darkMode: isDarkMode)
113+
view.window?.titlebarAppearsTransparent = true
114+
view.window?.isOpaque = false
115+
116+
about_image.image = NSImage(named: "AppIcon")
117+
appName_textfield.stringValue = "\(AppInfo.name)"
118+
version_textfield.stringValue = "Version \(AppInfo.version) (\(AppInfo.build))"
119+
license_textfield.textStorage?.setAttributedString(formattedText())
120+
}
121+
122+
override func viewWillDisappear() {
123+
super.viewWillDisappear()
124+
DistributedNotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: "AppleInterfaceThemeChangedNotification"), object: nil)
125+
}
126+
127+
func grayscale(image: CGImage, theSize: NSSize) -> NSImage? {
128+
let context = CIContext(options: nil)
129+
// CIPhotoEffectNoir
130+
// CIPhotoEffectMono
131+
// CIPhotoEffectTonal
132+
if let filter = CIFilter(name: "CIPhotoEffectTonal") {
133+
134+
filter.setValue(CIImage(cgImage: image), forKey: kCIInputImageKey)
135+
136+
if let output = filter.outputImage {
137+
if let cgImage = context.createCGImage(output, from: output.extent) {
138+
return NSImage(cgImage: cgImage, size: theSize)
139+
}
140+
}
141+
}
142+
return nil
143+
}
144+
145+
}
146+
147+
extension NSImage {
148+
func newCIImage() -> CIImage? {
149+
if let cgImage = self.newCGImage() {
150+
return CIImage(cgImage: cgImage)
151+
}
152+
return nil
153+
}
154+
155+
func newCGImage() -> CGImage? {
156+
var imageRect = NSRect(origin: CGPoint(x: 0, y: 0), size: self.size)
157+
return self.cgImage(forProposedRect: &imageRect, context: NSGraphicsContext.current, hints: nil)
158+
}
159+
}

ObjectInfo/AppDelegate.swift

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import Cocoa
1212
class AppDelegate: NSObject, NSApplicationDelegate {
1313

1414
let resourceCheck = ResourceCheck()
15-
15+
1616
@IBOutlet weak var resetVersionAlert_MenuItem: NSMenuItem!
1717
@IBAction func resetVersionAlert_Action(_ sender: Any) {
1818
resetVersionAlert_MenuItem.isEnabled = false
@@ -31,9 +31,40 @@ class AppDelegate: NSObject, NSApplicationDelegate {
3131
}
3232
}
3333
}
34+
35+
@IBAction func showAbout(_ sender: Any) {
36+
let storyboard = NSStoryboard(name: "Main", bundle: nil)
37+
let aboutWindowController = storyboard.instantiateController(withIdentifier: "aboutWC") as! NSWindowController
38+
if !windowIsVisible(windowName: "About") {
39+
aboutWindowController.window?.hidesOnDeactivate = false
40+
aboutWindowController.showWindow(self)
41+
} else {
42+
let windowsCount = NSApp.windows.count
43+
for i in (0..<windowsCount) {
44+
if NSApp.windows[i].title == "About" {
45+
NSApp.windows[i].makeKeyAndOrderFront(self)
46+
break
47+
}
48+
}
49+
}
50+
}
51+
52+
func windowIsVisible(windowName: String) -> Bool {
53+
let options = CGWindowListOption(arrayLiteral: CGWindowListOption.excludeDesktopElements, CGWindowListOption.optionOnScreenOnly)
54+
let windowListInfo = CGWindowListCopyWindowInfo(options, CGWindowID(0))
55+
let infoList = windowListInfo as NSArray? as? [[String: AnyObject]]
56+
for item in infoList! {
57+
if let _ = item["kCGWindowOwnerName"], let _ = item["kCGWindowName"] {
58+
if "\(item["kCGWindowOwnerName"]!)" == AppInfo.displayname && "\(item["kCGWindowName"]!)" == windowName {
59+
return true
60+
}
61+
}
62+
}
63+
return false
64+
}
3465

3566
func applicationDidFinishLaunching(_ aNotification: Notification) {
36-
// Insert code here to initialize your application
67+
configureTelemetryDeck()
3768
let skipVersionAlert = UserDefaults.standard.bool(forKey: "skipVersionAlert")
3869
resetVersionAlert_MenuItem.isEnabled = skipVersionAlert
3970
resetVersionAlert_MenuItem.isHidden = !skipVersionAlert

0 commit comments

Comments
 (0)