From 3f9bb250f42814dbfc947cd0ea8279afcec65d7f Mon Sep 17 00:00:00 2001 From: Michael Freno Date: Sat, 10 Jan 2026 20:02:18 -0500 Subject: [PATCH] feat: add icon --- Gaze.icon/Assets/Ellipse 1 4.svg | 3 + Gaze.icon/Assets/Ellipse 10 3.svg | 3 + Gaze.icon/Assets/Ellipse 11.svg | 3 + Gaze.icon/Assets/Ellipse 3 3.svg | 3 + Gaze.icon/Assets/Ellipse 4 3.svg | 3 + Gaze.icon/Assets/Ellipse 5 3.svg | 3 + Gaze.icon/Assets/Ellipse 7 3.svg | 3 + Gaze.icon/Assets/Ellipse 8 3.svg | 3 + Gaze.icon/Assets/Ellipse 9 3.svg | 3 + Gaze.icon/Assets/Line 7.svg | 3 + Gaze.icon/Assets/Line 8.svg | 3 + Gaze.icon/icon.json | 313 ++++++++++++++++++ Gaze.xcodeproj/project.pbxproj | 13 +- Gaze/AppDelegate.swift | 19 +- .../AppIcon.appiconset/Contents.json | 58 ---- Gaze/GazeApp.swift | 4 +- Gaze/Views/MenuBar/MenuBarContentView.swift | 39 ++- 17 files changed, 393 insertions(+), 86 deletions(-) create mode 100644 Gaze.icon/Assets/Ellipse 1 4.svg create mode 100644 Gaze.icon/Assets/Ellipse 10 3.svg create mode 100644 Gaze.icon/Assets/Ellipse 11.svg create mode 100644 Gaze.icon/Assets/Ellipse 3 3.svg create mode 100644 Gaze.icon/Assets/Ellipse 4 3.svg create mode 100644 Gaze.icon/Assets/Ellipse 5 3.svg create mode 100644 Gaze.icon/Assets/Ellipse 7 3.svg create mode 100644 Gaze.icon/Assets/Ellipse 8 3.svg create mode 100644 Gaze.icon/Assets/Ellipse 9 3.svg create mode 100644 Gaze.icon/Assets/Line 7.svg create mode 100644 Gaze.icon/Assets/Line 8.svg create mode 100644 Gaze.icon/icon.json delete mode 100644 Gaze/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/Gaze.icon/Assets/Ellipse 1 4.svg b/Gaze.icon/Assets/Ellipse 1 4.svg new file mode 100644 index 0000000..4c4862c --- /dev/null +++ b/Gaze.icon/Assets/Ellipse 1 4.svg @@ -0,0 +1,3 @@ + + + diff --git a/Gaze.icon/Assets/Ellipse 10 3.svg b/Gaze.icon/Assets/Ellipse 10 3.svg new file mode 100644 index 0000000..0483ea5 --- /dev/null +++ b/Gaze.icon/Assets/Ellipse 10 3.svg @@ -0,0 +1,3 @@ + + + diff --git a/Gaze.icon/Assets/Ellipse 11.svg b/Gaze.icon/Assets/Ellipse 11.svg new file mode 100644 index 0000000..df185ff --- /dev/null +++ b/Gaze.icon/Assets/Ellipse 11.svg @@ -0,0 +1,3 @@ + + + diff --git a/Gaze.icon/Assets/Ellipse 3 3.svg b/Gaze.icon/Assets/Ellipse 3 3.svg new file mode 100644 index 0000000..fc5bf24 --- /dev/null +++ b/Gaze.icon/Assets/Ellipse 3 3.svg @@ -0,0 +1,3 @@ + + + diff --git a/Gaze.icon/Assets/Ellipse 4 3.svg b/Gaze.icon/Assets/Ellipse 4 3.svg new file mode 100644 index 0000000..3783d84 --- /dev/null +++ b/Gaze.icon/Assets/Ellipse 4 3.svg @@ -0,0 +1,3 @@ + + + diff --git a/Gaze.icon/Assets/Ellipse 5 3.svg b/Gaze.icon/Assets/Ellipse 5 3.svg new file mode 100644 index 0000000..c9032bd --- /dev/null +++ b/Gaze.icon/Assets/Ellipse 5 3.svg @@ -0,0 +1,3 @@ + + + diff --git a/Gaze.icon/Assets/Ellipse 7 3.svg b/Gaze.icon/Assets/Ellipse 7 3.svg new file mode 100644 index 0000000..fce0bf0 --- /dev/null +++ b/Gaze.icon/Assets/Ellipse 7 3.svg @@ -0,0 +1,3 @@ + + + diff --git a/Gaze.icon/Assets/Ellipse 8 3.svg b/Gaze.icon/Assets/Ellipse 8 3.svg new file mode 100644 index 0000000..501fe19 --- /dev/null +++ b/Gaze.icon/Assets/Ellipse 8 3.svg @@ -0,0 +1,3 @@ + + + diff --git a/Gaze.icon/Assets/Ellipse 9 3.svg b/Gaze.icon/Assets/Ellipse 9 3.svg new file mode 100644 index 0000000..9006935 --- /dev/null +++ b/Gaze.icon/Assets/Ellipse 9 3.svg @@ -0,0 +1,3 @@ + + + diff --git a/Gaze.icon/Assets/Line 7.svg b/Gaze.icon/Assets/Line 7.svg new file mode 100644 index 0000000..dfc9be9 --- /dev/null +++ b/Gaze.icon/Assets/Line 7.svg @@ -0,0 +1,3 @@ + + + diff --git a/Gaze.icon/Assets/Line 8.svg b/Gaze.icon/Assets/Line 8.svg new file mode 100644 index 0000000..e8a68dc --- /dev/null +++ b/Gaze.icon/Assets/Line 8.svg @@ -0,0 +1,3 @@ + + + diff --git a/Gaze.icon/icon.json b/Gaze.icon/icon.json new file mode 100644 index 0000000..7efc4f6 --- /dev/null +++ b/Gaze.icon/icon.json @@ -0,0 +1,313 @@ +{ + "fill" : { + "automatic-gradient" : "extended-srgb:0.00000,0.53333,1.00000,1.00000" + }, + "groups" : [ + { + "layers" : [ + { + "blend-mode" : "multiply", + "fill" : { + "automatic-gradient" : "extended-srgb:0.00000,0.53333,1.00000,1.00000" + }, + "glass" : false, + "image-name" : "Ellipse 3 3.svg", + "name" : "Ellipse 3 3", + "position" : { + "scale" : 1, + "translation-in-points" : [ + 0, + 250 + ] + } + }, + { + "blend-mode" : "multiply", + "fill" : { + "automatic-gradient" : "extended-srgb:0.00000,0.53333,1.00000,1.00000" + }, + "glass" : false, + "image-name" : "Ellipse 4 3.svg", + "name" : "Ellipse 4 3", + "position" : { + "scale" : 1, + "translation-in-points" : [ + 0, + -250 + ] + } + }, + { + "blend-mode" : "multiply", + "fill" : { + "automatic-gradient" : "extended-srgb:0.00000,0.53333,1.00000,1.00000" + }, + "glass" : false, + "hidden" : true, + "image-name" : "Ellipse 5 3.svg", + "name" : "Ellipse 5 3", + "position" : { + "scale" : 1, + "translation-in-points" : [ + 0, + 0 + ] + } + }, + { + "blend-mode" : "multiply", + "fill" : { + "automatic-gradient" : "extended-srgb:0.00000,0.53333,1.00000,1.00000" + }, + "glass" : false, + "hidden" : true, + "image-name" : "Ellipse 5 3.svg", + "name" : "Ellipse 5 3", + "position" : { + "scale" : 1, + "translation-in-points" : [ + 250, + 0 + ] + } + }, + { + "blend-mode" : "multiply", + "fill" : { + "automatic-gradient" : "extended-srgb:0.00000,0.53333,1.00000,1.00000" + }, + "glass" : false, + "hidden" : true, + "image-name" : "Ellipse 5 3.svg", + "name" : "Ellipse 5 3", + "position" : { + "scale" : 1, + "translation-in-points" : [ + -250, + 0 + ] + } + }, + { + "blend-mode" : "multiply", + "fill" : { + "automatic-gradient" : "extended-srgb:0.00000,0.53333,1.00000,1.00000" + }, + "glass" : false, + "image-name" : "Ellipse 7 3.svg", + "name" : "Ellipse 7 3", + "position" : { + "scale" : 1, + "translation-in-points" : [ + 185, + -185 + ] + } + }, + { + "blend-mode" : "multiply", + "fill" : { + "automatic-gradient" : "extended-srgb:0.00000,0.53333,1.00000,1.00000" + }, + "glass" : false, + "image-name" : "Ellipse 8 3.svg", + "name" : "Ellipse 8 3", + "position" : { + "scale" : 1, + "translation-in-points" : [ + 185, + 185 + ] + } + }, + { + "blend-mode" : "multiply", + "fill" : { + "automatic-gradient" : "extended-srgb:0.00000,0.53333,1.00000,1.00000" + }, + "glass" : false, + "image-name" : "Ellipse 9 3.svg", + "name" : "Ellipse 9 3", + "position" : { + "scale" : 1, + "translation-in-points" : [ + -185, + 185 + ] + } + }, + { + "blend-mode" : "multiply", + "fill" : { + "automatic-gradient" : "extended-srgb:0.00000,0.53333,1.00000,1.00000" + }, + "glass" : false, + "image-name" : "Ellipse 10 3.svg", + "name" : "Ellipse 10 3", + "position" : { + "scale" : 1, + "translation-in-points" : [ + -185, + -185 + ] + } + } + ], + "shadow" : { + "kind" : "neutral", + "opacity" : 0.5 + }, + "translucency" : { + "enabled" : true, + "value" : 0.5 + } + }, + { + "hidden" : false, + "layers" : [ + { + "glass" : false, + "image-name" : "Line 7.svg", + "name" : "Line 7", + "position" : { + "scale" : 1.08, + "translation-in-points" : [ + 5.838429928574556, + 82.99998474120002 + ] + } + }, + { + "blend-mode" : "darken", + "fill" : { + "automatic-gradient" : "extended-srgb:0.00000,0.53333,1.00000,1.00000" + }, + "glass" : false, + "image-name" : "Line 8.svg", + "name" : "Line 8", + "position" : { + "scale" : 1.21, + "translation-in-points" : [ + -0.1999973177900074, + -82.12440000000004 + ] + } + } + ], + "shadow" : { + "kind" : "neutral", + "opacity" : 0.5 + }, + "translucency" : { + "enabled" : true, + "value" : 0.5 + } + }, + { + "layers" : [ + { + "blend-mode" : "plus-darker", + "fill" : { + "automatic-gradient" : "extended-srgb:0.00000,0.53333,1.00000,1.00000" + }, + "glass" : true, + "hidden" : false, + "image-name" : "Ellipse 11.svg", + "name" : "Ellipse 11", + "position" : { + "scale" : 1.32, + "translation-in-points" : [ + 0, + 0 + ] + } + }, + { + "blend-mode" : "hard-light", + "fill" : { + "solid" : "extended-srgb:0.00000,0.53333,1.00000,1.00000" + }, + "glass" : true, + "image-name" : "Ellipse 11.svg", + "name" : "Ellipse 11", + "position" : { + "scale" : 0.99, + "translation-in-points" : [ + 0, + 0 + ] + } + } + ], + "shadow" : { + "kind" : "neutral", + "opacity" : 0.5 + }, + "translucency" : { + "enabled" : true, + "value" : 0.5 + } + }, + { + "blend-mode" : "plus-darker", + "blur-material" : 0.5, + "layers" : [ + { + "blend-mode-specializations" : [ + { + "value" : "darken" + }, + { + "appearance" : "tinted", + "value" : "lighten" + } + ], + "fill-specializations" : [ + { + "value" : { + "linear-gradient" : [ + "display-p3:0.38403,0.64839,1.04685,1.00000", + "extended-srgb:0.00000,0.53333,1.00000,1.00000" + ], + "orientation" : { + "start" : { + "x" : 0.5, + "y" : 0 + }, + "stop" : { + "x" : 0.5, + "y" : 0.7 + } + } + } + }, + { + "appearance" : "dark", + "value" : { + "automatic-gradient" : "extended-srgb:0.00000,0.53333,1.00000,1.00000" + } + } + ], + "glass" : true, + "image-name" : "Ellipse 1 4.svg", + "name" : "Ellipse 1 4" + } + ], + "shadow" : { + "kind" : "neutral", + "opacity" : 0.5 + }, + "specular" : true, + "translucency" : { + "enabled" : true, + "value" : 0.5 + } + } + ], + "supported-platforms" : { + "circles" : [ + "watchOS" + ], + "squares" : "shared" + } +} \ No newline at end of file diff --git a/Gaze.xcodeproj/project.pbxproj b/Gaze.xcodeproj/project.pbxproj index 837d900..1de8326 100644 --- a/Gaze.xcodeproj/project.pbxproj +++ b/Gaze.xcodeproj/project.pbxproj @@ -6,6 +6,11 @@ objectVersion = 77; objects = { +/* Begin PBXBuildFile section */ + 275915892F132A9200D0E60D /* Lottie in Frameworks */ = {isa = PBXBuildFile; productRef = 27AE10B12F10B1FC00E00DBC /* Lottie */; }; + 2759160C2F132C7A00D0E60D /* Gaze.icon in Resources */ = {isa = PBXBuildFile; fileRef = 2759160B2F132C7A00D0E60D /* Gaze.icon */; }; +/* End PBXBuildFile section */ + /* Begin PBXContainerItemProxy section */ 27A21B4A2F0F69DD0018C4F3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; @@ -24,6 +29,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 2759160B2F132C7A00D0E60D /* Gaze.icon */ = {isa = PBXFileReference; lastKnownFileType = folder.iconcomposer.icon; path = Gaze.icon; sourceTree = ""; }; 27A21B3C2F0F69DC0018C4F3 /* Gaze.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Gaze.app; sourceTree = BUILT_PRODUCTS_DIR; }; 27A21B492F0F69DD0018C4F3 /* GazeTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GazeTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 27A21B532F0F69DD0018C4F3 /* GazeUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GazeUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -52,6 +58,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 275915892F132A9200D0E60D /* Lottie in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -75,6 +82,7 @@ 27A21B332F0F69DC0018C4F3 = { isa = PBXGroup; children = ( + 2759160B2F132C7A00D0E60D /* Gaze.icon */, 27A21B3E2F0F69DC0018C4F3 /* Gaze */, 27A21B4C2F0F69DD0018C4F3 /* GazeTests */, 27A21B562F0F69DD0018C4F3 /* GazeUITests */, @@ -216,6 +224,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 2759160C2F132C7A00D0E60D /* Gaze.icon in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -396,7 +405,6 @@ 27A21B5E2F0F69DD0018C4F3 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; @@ -428,7 +436,6 @@ 27A21B5F2F0F69DD0018C4F3 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; @@ -588,6 +595,7 @@ }; }; /* End XCRemoteSwiftPackageReference section */ + /* Begin XCSwiftPackageProductDependency section */ 27AE10B12F10B1FC00E00DBC /* Lottie */ = { isa = XCSwiftPackageProductDependency; @@ -595,7 +603,6 @@ productName = Lottie; }; /* End XCSwiftPackageProductDependency section */ - }; rootObject = 27A21B342F0F69DC0018C4F3 /* Project object */; } diff --git a/Gaze/AppDelegate.swift b/Gaze/AppDelegate.swift index c9b8f98..5a7dfe8 100644 --- a/Gaze/AppDelegate.swift +++ b/Gaze/AppDelegate.swift @@ -158,7 +158,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { showReminderWindow(contentView) } -private func showReminderWindow(_ content: AnyView) { + private func showReminderWindow(_ content: AnyView) { guard let screen = NSScreen.main else { return } let window = KeyableWindow( @@ -266,12 +266,15 @@ private func showReminderWindow(_ content: AnyView) { // Observe when window is closed to clean up reference NotificationCenter.default.addObserver( - forName: NSWindow.willCloseNotification, - object: window, - queue: .main - ) { [weak self] _ in - self?.settingsWindowController = nil - } + self, + selector: #selector(settingsWindowWillCloseNotification(_:)), + name: NSWindow.willCloseNotification, + object: window + ) + } + + @objc private func settingsWindowWillCloseNotification(_ notification: Notification) { + settingsWindowController = nil } } @@ -284,4 +287,4 @@ class KeyableWindow: NSWindow { override var canBecomeMain: Bool { return true } -} \ No newline at end of file +} diff --git a/Gaze/Assets.xcassets/AppIcon.appiconset/Contents.json b/Gaze/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 3f00db4..0000000 --- a/Gaze/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images" : [ - { - "idiom" : "mac", - "scale" : "1x", - "size" : "16x16" - }, - { - "idiom" : "mac", - "scale" : "2x", - "size" : "16x16" - }, - { - "idiom" : "mac", - "scale" : "1x", - "size" : "32x32" - }, - { - "idiom" : "mac", - "scale" : "2x", - "size" : "32x32" - }, - { - "idiom" : "mac", - "scale" : "1x", - "size" : "128x128" - }, - { - "idiom" : "mac", - "scale" : "2x", - "size" : "128x128" - }, - { - "idiom" : "mac", - "scale" : "1x", - "size" : "256x256" - }, - { - "idiom" : "mac", - "scale" : "2x", - "size" : "256x256" - }, - { - "idiom" : "mac", - "scale" : "1x", - "size" : "512x512" - }, - { - "idiom" : "mac", - "scale" : "2x", - "size" : "512x512" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Gaze/GazeApp.swift b/Gaze/GazeApp.swift index b909fc2..7e72991 100644 --- a/Gaze/GazeApp.swift +++ b/Gaze/GazeApp.swift @@ -22,7 +22,7 @@ struct GazeApp: App { } } else { OnboardingContainerView(settingsManager: settingsManager) - .onChange(of: settingsManager.settings.hasCompletedOnboarding) { completed in + .onChange(of: settingsManager.settings.hasCompletedOnboarding) { _, completed in if completed { closeAllWindows() appDelegate.onboardingCompleted() @@ -56,4 +56,4 @@ struct GazeApp: App { window.close() } } -} \ No newline at end of file +} diff --git a/Gaze/Views/MenuBar/MenuBarContentView.swift b/Gaze/Views/MenuBar/MenuBarContentView.swift index 5158dc0..4b330ab 100644 --- a/Gaze/Views/MenuBar/MenuBarContentView.swift +++ b/Gaze/Views/MenuBar/MenuBarContentView.swift @@ -64,7 +64,7 @@ struct MenuBarContentView: View { EmptyView() } } - + private var onboardingIncompleteView: some View { VStack(alignment: .leading, spacing: 0) { // Header @@ -79,15 +79,15 @@ struct MenuBarContentView: View { .padding() Divider() - + // Message VStack(alignment: .leading, spacing: 12) { Text("Welcome to Gaze!") .font(.headline) .padding(.horizontal) .padding(.top, 16) - - Text("Please complete the onboarding to start using Gaze.") + + Text("Complete the onboarding to start using Gaze!") .font(.subheadline) .foregroundColor(.secondary) .padding(.horizontal) @@ -133,11 +133,13 @@ struct MenuBarContentView: View { .padding(.vertical, 8) } .frame(width: 300) - .onReceive(NotificationCenter.default.publisher(for: Notification.Name("CloseMenuBarPopover"))) { _ in + .onReceive( + NotificationCenter.default.publisher(for: Notification.Name("CloseMenuBarPopover")) + ) { _ in dismiss() } } - + private func fullMenuBarView(timerEngine: TimerEngine) -> some View { VStack(alignment: .leading, spacing: 0) { // Header @@ -185,14 +187,15 @@ struct MenuBarContentView: View { ) } } - + // Show user timers if any exist and are enabled - ForEach(settingsManager.settings.userTimers.filter { $0.enabled }, id: \.id) { userTimer in + ForEach(settingsManager.settings.userTimers.filter { $0.enabled }, id: \.id) { + userTimer in UserTimerStatusRow( timer: userTimer, - state: nil, // We'll implement proper state tracking later + state: nil, // We'll implement proper state tracking later onTap: { - onOpenSettingsTab(3) // Switch to User Timers tab + onOpenSettingsTab(3) // Switch to User Timers tab } ) } @@ -211,8 +214,12 @@ struct MenuBarContentView: View { } }) { HStack { - Image(systemName: isPaused(timerEngine: timerEngine) ? "play.circle" : "pause.circle") - Text(isPaused(timerEngine: timerEngine) ? "Resume All Timers" : "Pause All Timers") + Image( + systemName: isPaused(timerEngine: timerEngine) + ? "play.circle" : "pause.circle") + Text( + isPaused(timerEngine: timerEngine) + ? "Resume All Timers" : "Pause All Timers") Spacer() } .padding(.horizontal, 8) @@ -254,7 +261,9 @@ struct MenuBarContentView: View { .padding(.vertical, 8) } .frame(width: 300) - .onReceive(NotificationCenter.default.publisher(for: Notification.Name("CloseMenuBarPopover"))) { _ in + .onReceive( + NotificationCenter.default.publisher(for: Notification.Name("CloseMenuBarPopover")) + ) { _ in dismiss() } } @@ -430,7 +439,7 @@ struct UserTimerStatusRow: View { Circle() .fill(timer.color) .frame(width: 8, height: 8) - + Image(systemName: "clock.fill") .foregroundColor(timer.color) .frame(width: 20) @@ -440,7 +449,7 @@ struct UserTimerStatusRow: View { .font(.subheadline) .fontWeight(.medium) .lineLimit(1) - + if let state = state { Text(timeRemaining(state)) .font(.caption)