diff --git a/CursorTravel.xcodeproj/project.pbxproj b/CursorTravel.xcodeproj/project.pbxproj index 7cf2f5b..18d10e1 100644 --- a/CursorTravel.xcodeproj/project.pbxproj +++ b/CursorTravel.xcodeproj/project.pbxproj @@ -18,9 +18,6 @@ 84638062247465B100F6CE79 /* Mouse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84638061247465B100F6CE79 /* Mouse.swift */; }; 84638064247465C700F6CE79 /* Unit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84638063247465C700F6CE79 /* Unit.swift */; }; 84638066247465F000F6CE79 /* EventMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84638065247465F000F6CE79 /* EventMonitor.swift */; }; - 84A714BC247A124200EE705A /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A714BB247A124200EE705A /* main.swift */; }; - 84A714C3247A124400EE705A /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 84A714C2247A124400EE705A /* Preview Assets.xcassets */; }; - 84A714CD247A145100EE705A /* LauncherApplication.app in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84A714B9247A124200EE705A /* LauncherApplication.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 84A714D0247A147B00EE705A /* ServiceManagement.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84A714CF247A147B00EE705A /* ServiceManagement.framework */; }; /* End PBXBuildFile section */ @@ -31,7 +28,6 @@ dstPath = Contents/Library/LoginItems; dstSubfolderSpec = 1; files = ( - 84A714CD247A145100EE705A /* LauncherApplication.app in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -52,11 +48,6 @@ 84638061247465B100F6CE79 /* Mouse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mouse.swift; sourceTree = ""; }; 84638063247465C700F6CE79 /* Unit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Unit.swift; sourceTree = ""; }; 84638065247465F000F6CE79 /* EventMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventMonitor.swift; sourceTree = ""; }; - 84A714B9247A124200EE705A /* LauncherApplication.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LauncherApplication.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 84A714BB247A124200EE705A /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; - 84A714C2247A124400EE705A /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; - 84A714C7247A124400EE705A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 84A714C8247A124400EE705A /* LauncherApplication.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LauncherApplication.entitlements; sourceTree = ""; }; 84A714CF247A147B00EE705A /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = System/Library/Frameworks/ServiceManagement.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ @@ -69,13 +60,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 84A714B6247A124200EE705A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -83,7 +67,6 @@ isa = PBXGroup; children = ( 846380442474647E00F6CE79 /* CursorTravel */, - 84A714BA247A124200EE705A /* LauncherApplication */, 846380432474647E00F6CE79 /* Products */, 84A714CE247A147B00EE705A /* Frameworks */, ); @@ -93,7 +76,6 @@ isa = PBXGroup; children = ( 846380422474647E00F6CE79 /* CursorTravel.app */, - 84A714B9247A124200EE705A /* LauncherApplication.app */, ); name = Products; sourceTree = ""; @@ -150,25 +132,6 @@ path = "Supporting Views"; sourceTree = ""; }; - 84A714BA247A124200EE705A /* LauncherApplication */ = { - isa = PBXGroup; - children = ( - 84A714BB247A124200EE705A /* main.swift */, - 84A714C7247A124400EE705A /* Info.plist */, - 84A714C8247A124400EE705A /* LauncherApplication.entitlements */, - 84A714C1247A124400EE705A /* Preview Content */, - ); - path = LauncherApplication; - sourceTree = ""; - }; - 84A714C1247A124400EE705A /* Preview Content */ = { - isa = PBXGroup; - children = ( - 84A714C2247A124400EE705A /* Preview Assets.xcassets */, - ); - path = "Preview Content"; - sourceTree = ""; - }; 84A714CE247A147B00EE705A /* Frameworks */ = { isa = PBXGroup; children = ( @@ -198,23 +161,6 @@ productReference = 846380422474647E00F6CE79 /* CursorTravel.app */; productType = "com.apple.product-type.application"; }; - 84A714B8247A124200EE705A /* LauncherApplication */ = { - isa = PBXNativeTarget; - buildConfigurationList = 84A714CB247A124400EE705A /* Build configuration list for PBXNativeTarget "LauncherApplication" */; - buildPhases = ( - 84A714B5247A124200EE705A /* Sources */, - 84A714B6247A124200EE705A /* Frameworks */, - 84A714B7247A124200EE705A /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = LauncherApplication; - productName = LauncherApplication; - productReference = 84A714B9247A124200EE705A /* LauncherApplication.app */; - productType = "com.apple.product-type.application"; - }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -228,9 +174,6 @@ 846380412474647E00F6CE79 = { CreatedOnToolsVersion = 11.1; }; - 84A714B8247A124200EE705A = { - CreatedOnToolsVersion = 11.1; - }; }; }; buildConfigurationList = 8463803D2474647E00F6CE79 /* Build configuration list for PBXProject "CursorTravel" */; @@ -247,7 +190,6 @@ projectRoot = ""; targets = ( 846380412474647E00F6CE79 /* CursorTravel */, - 84A714B8247A124200EE705A /* LauncherApplication */, ); }; /* End PBXProject section */ @@ -264,14 +206,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 84A714B7247A124200EE705A /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 84A714C3247A124400EE705A /* Preview Assets.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -289,14 +223,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 84A714B5247A124200EE705A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 84A714BC247A124200EE705A /* main.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ @@ -472,54 +398,6 @@ }; name = Release; }; - 84A714C9247A124400EE705A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_ENTITLEMENTS = LauncherApplication/LauncherApplication.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_ASSET_PATHS = "\"LauncherApplication/Preview Content\""; - DEVELOPMENT_TEAM = 5458M4A7SB; - ENABLE_HARDENED_RUNTIME = YES; - ENABLE_PREVIEWS = YES; - INFOPLIST_FILE = LauncherApplication/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 10.15; - PRODUCT_BUNDLE_IDENTIFIER = com.terkel.LauncherApplication; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - 84A714CA247A124400EE705A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_ENTITLEMENTS = LauncherApplication/LauncherApplication.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_ASSET_PATHS = "\"LauncherApplication/Preview Content\""; - DEVELOPMENT_TEAM = 5458M4A7SB; - ENABLE_HARDENED_RUNTIME = YES; - ENABLE_PREVIEWS = YES; - INFOPLIST_FILE = LauncherApplication/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 10.15; - PRODUCT_BUNDLE_IDENTIFIER = com.terkel.LauncherApplication; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -541,15 +419,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 84A714CB247A124400EE705A /* Build configuration list for PBXNativeTarget "LauncherApplication" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 84A714C9247A124400EE705A /* Debug */, - 84A714CA247A124400EE705A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; /* End XCConfigurationList section */ }; rootObject = 8463803A2474647E00F6CE79 /* Project object */; diff --git a/CursorTravel/AppDelegate.swift b/CursorTravel/AppDelegate.swift index 9139293..1a2b5f4 100644 --- a/CursorTravel/AppDelegate.swift +++ b/CursorTravel/AppDelegate.swift @@ -7,7 +7,7 @@ // // MARK: TODO -// - [ ] Fix start on startup +// - [ ] Allow launcher/open on startup import Cocoa import SwiftUI @@ -21,6 +21,9 @@ class AppDelegate: NSObject, NSApplicationDelegate { let mouseData = Mouse() let popover = NSPopover() + // TODO: Make this an option + private let icon = true + private var cancellableDistance: AnyCancellable? private var eventMonitor: EventMonitor? @@ -29,23 +32,14 @@ class AppDelegate: NSObject, NSApplicationDelegate { initPopover() cancellableDistance = mouseData.objectWillChange.sink(receiveValue: { item in - self.statusItem.button?.title = self.mouseData.formattedTotal() + if !self.icon { + self.statusItem.button?.title = self.mouseData.totalString + } }) eventMonitor = EventMonitor(mask: [.leftMouseDown, .rightMouseDown]) { event in self.togglePopover(nil) } - - // Launcher - let launcherAppId = "com.terkel.LauncherApplication" - let runningApps = NSWorkspace.shared.runningApplications - let isRunning = !runningApps.filter { $0.bundleIdentifier == launcherAppId }.isEmpty - - SMLoginItemSetEnabled(launcherAppId as CFString, true) - - if isRunning { - DistributedNotificationCenter.default().post(name: .killLauncher, object: Bundle.main.bundleIdentifier!) - } } func applicationWillTerminate(_ aNotification: Notification) { @@ -71,9 +65,18 @@ class AppDelegate: NSObject, NSApplicationDelegate { // MARK: Init func initStatusItem() { + if let button = statusItem.button { - button.title = mouseData.formattedTotal() - button.font = NSFont.monospacedDigitSystemFont(ofSize: 14.0, weight: .regular) + + if icon { + button.image = NSImage(named: "Cursor") +// button.imagePosition = NSControl.ImagePosition.imageLeft + button.imageScaling = NSImageScaling.scaleProportionallyDown + statusItem.length = NSStatusItem.squareLength + } else { + button.title = mouseData.totalString + button.font = NSFont.monospacedDigitSystemFont(ofSize: 14.0, weight: .regular) + } button.action = #selector(togglePopover(_:)) } } @@ -84,9 +87,3 @@ class AppDelegate: NSObject, NSApplicationDelegate { popover.contentViewController = NSHostingController(rootView: contentView) } } - -// MARK: - Extensions - -extension Notification.Name { - static let killLauncher = Notification.Name("killLauncher") -} diff --git a/CursorTravel/Assets.xcassets/Cursor.imageset/Contents.json b/CursorTravel/Assets.xcassets/Cursor.imageset/Contents.json index 618e906..8f7bbe3 100644 --- a/CursorTravel/Assets.xcassets/Cursor.imageset/Contents.json +++ b/CursorTravel/Assets.xcassets/Cursor.imageset/Contents.json @@ -2,7 +2,7 @@ "images" : [ { "idiom" : "universal", - "filename" : "tray-icon.pdf", + "filename" : "Cursor.pdf", "scale" : "1x" }, { @@ -17,5 +17,8 @@ "info" : { "version" : 1, "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" } } \ No newline at end of file diff --git a/CursorTravel/Assets.xcassets/Cursor.imageset/Cursor.pdf b/CursorTravel/Assets.xcassets/Cursor.imageset/Cursor.pdf new file mode 100644 index 0000000..e0a4d7f Binary files /dev/null and b/CursorTravel/Assets.xcassets/Cursor.imageset/Cursor.pdf differ diff --git a/CursorTravel/Assets.xcassets/Cursor.imageset/tray-icon.pdf b/CursorTravel/Assets.xcassets/Cursor.imageset/tray-icon.pdf deleted file mode 100644 index ea608dc..0000000 Binary files a/CursorTravel/Assets.xcassets/Cursor.imageset/tray-icon.pdf and /dev/null differ diff --git a/CursorTravel/ContentView.swift b/CursorTravel/ContentView.swift index d186af2..964c2e0 100644 --- a/CursorTravel/ContentView.swift +++ b/CursorTravel/ContentView.swift @@ -20,8 +20,8 @@ struct ContentView: View { } } Divider().padding(.bottom, 10) - MetricView(label: "Session", value: mouseData.formattedSession()) - MetricView(label: "Total Distance", value: mouseData.formattedTotal()) + MetricView(label: "Session", value: mouseData.sessionString) + MetricView(label: "Total Distance", value: mouseData.totalString) Divider().padding(.top, 10) HStack { Button(action: { diff --git a/CursorTravel/Models/Mouse.swift b/CursorTravel/Models/Mouse.swift index b28d2db..bd0ad6c 100644 --- a/CursorTravel/Models/Mouse.swift +++ b/CursorTravel/Models/Mouse.swift @@ -56,20 +56,20 @@ final class Mouse: ObservableObject { // MARK: - Print / Formatting - func getTotalDistance() -> Double { - return distance.total / unitData[distance.unit].multiplier + var totalDistance: Double { + distance.total / unitData[distance.unit].multiplier } - func getSessionDistance() -> Double { - return distance.session / unitData[distance.unit].multiplier + var sessionDistance: Double { + distance.session / unitData[distance.unit].multiplier } - func formattedTotal() -> String { - return String(format: "%.2f %@", getTotalDistance(), unitData[distance.unit].short) + var totalString: String { + String(format: "%.2f %@", totalDistance, unitData[distance.unit].short) } - func formattedSession() -> String { - return String(format: "%.2f %@", getSessionDistance(), unitData[distance.unit].short) + var sessionString: String { + String(format: "%.2f %@", sessionDistance, unitData[distance.unit].short) } // MARK: - Persistant Data diff --git a/LauncherApplication/Info.plist b/LauncherApplication/Info.plist deleted file mode 100644 index 37bb1f0..0000000 --- a/LauncherApplication/Info.plist +++ /dev/null @@ -1,36 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - LSBackgroundOnly - - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2020 Terkel.com. All rights reserved. - NSPrincipalClass - NSApplication - NSSupportsAutomaticTermination - - NSSupportsSuddenTermination - - - diff --git a/LauncherApplication/LauncherApplication.entitlements b/LauncherApplication/LauncherApplication.entitlements deleted file mode 100644 index 852fa1a..0000000 --- a/LauncherApplication/LauncherApplication.entitlements +++ /dev/null @@ -1,8 +0,0 @@ - - - - - com.apple.security.app-sandbox - - - diff --git a/LauncherApplication/Preview Content/Preview Assets.xcassets/Contents.json b/LauncherApplication/Preview Content/Preview Assets.xcassets/Contents.json deleted file mode 100644 index da4a164..0000000 --- a/LauncherApplication/Preview Content/Preview Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/LauncherApplication/main.swift b/LauncherApplication/main.swift deleted file mode 100644 index 6311935..0000000 --- a/LauncherApplication/main.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// AppDelegate.swift -// LauncherApplication -// -// Created by Terkel on 5/23/20. -// Copyright © 2020 Terkel.com. All rights reserved. -// - -import Cocoa - -class AppDelegate: NSObject, NSApplicationDelegate { - - func applicationDidFinishLaunching(_ aNotification: Notification) { - let mainAppIdentifier = "com.terkel.CursorTravel" - let runningApps = NSWorkspace.shared.runningApplications - let isRunning = !runningApps.filter { $0.bundleIdentifier == mainAppIdentifier }.isEmpty - - guard NSRunningApplication.runningApplications(withBundleIdentifier: mainAppIdentifier).isEmpty else { - NSApp.terminate(nil) - return - } - - if !isRunning { - DistributedNotificationCenter.default().addObserver(self, selector: #selector(self.terminate), name: .killLauncher, object: mainAppIdentifier) - - let path = Bundle.main.bundlePath as NSString - var components = path.pathComponents - components.removeLast() - components.removeLast() - components.removeLast() - components.append("MacOS") - components.append("CursorTravel") - - let newPath = NSString.path(withComponents: components) - NSWorkspace.shared.launchApplication(newPath) - } - else { - self.terminate() - } - } - - @objc func terminate() { - NSApp.terminate(nil) - } -} - -extension Notification.Name { - static let killLauncher = Notification.Name("killLauncher") -} - -private let app = NSApplication.shared -private let delegate = AppDelegate() -app.delegate = delegate -app.run()