diff --git a/Color Picker.xcodeproj/project.pbxproj b/Color Picker.xcodeproj/project.pbxproj index 0d120f8..86b01d7 100644 --- a/Color Picker.xcodeproj/project.pbxproj +++ b/Color Picker.xcodeproj/project.pbxproj @@ -361,8 +361,7 @@ ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "Intents Extension/Info.plist"; - INFOPLIST_KEY_CFBundleDisplayName = "Intents Extension"; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_CFBundleDisplayName = "Color Picker Intents Extension"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -370,6 +369,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = "com.sindresorhus.Color-Picker.Intents-Extension"; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG APP_EXTENSION"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -388,8 +388,7 @@ ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "Intents Extension/Info.plist"; - INFOPLIST_KEY_CFBundleDisplayName = "Intents Extension"; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_CFBundleDisplayName = "Color Picker Intents Extension"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -397,6 +396,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = "com.sindresorhus.Color-Picker.Intents-Extension"; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = APP_EXTENSION; SWIFT_EMIT_LOC_STRINGS = YES; @@ -459,7 +459,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 14.1; + MACOSX_DEPLOYMENT_TARGET = 14.4; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -519,7 +519,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 14.1; + MACOSX_DEPLOYMENT_TARGET = 14.4; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = macosx; @@ -544,6 +544,7 @@ DEVELOPMENT_TEAM = YG56YK5RN5; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "Color Picker/Info.plist"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools"; LD_RUNPATH_SEARCH_PATHS = ( @@ -571,6 +572,7 @@ DEVELOPMENT_TEAM = YG56YK5RN5; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "Color Picker/Info.plist"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools"; LD_RUNPATH_SEARCH_PATHS = ( @@ -629,7 +631,7 @@ repositoryURL = "https://github.com/sindresorhus/KeyboardShortcuts"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 1.9.0; + minimumVersion = 2.0.0; }; }; E3E14060259A0D97004FC89F /* XCRemoteSwiftPackageReference "Defaults" */ = { diff --git a/Color Picker/Constants.swift b/Color Picker/Constants.swift index be06786..5c451d0 100644 --- a/Color Picker/Constants.swift +++ b/Color Picker/Constants.swift @@ -9,6 +9,7 @@ extension Defaults.Keys { static let recentlyPickedColors = Key<[NSColor]>("recentlyPickedColors", default: []) // Settings + static let showInMenuBar = Key("showInMenuBar", default: false) static let hideMenuBarIcon = Key("hideMenuBarIcon", default: false) static let showColorSamplerOnOpen = Key("showColorSamplerOnOpen", default: false) @@ -25,7 +26,10 @@ extension Defaults.Keys { static let showAccessibilityColorName = Key("showAccessibilityColorName", default: false) static let stickyPaletteName = Key("stickyPaletteName") + // Hidden settings + + // defaults write com.sindresorhus.System-Color-Picker showOnAllSpaces -bool false static let showOnAllSpaces = Key("showOnAllSpaces", default: true) } diff --git a/Color Picker/Info.plist b/Color Picker/Info.plist index 6b76842..6b9ba7d 100644 --- a/Color Picker/Info.plist +++ b/Color Picker/Info.plist @@ -2,28 +2,8 @@ - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - $(MARKETING_VERSION) - CFBundleVersion - $(CURRENT_PROJECT_VERSION) ITSAppUsesNonExemptEncryption - LSApplicationCategoryType - public.app-category.developer-tools - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) MDItemKeywords color,picker,system,pick,colour,colors,colours,sampler diff --git a/Color Picker/MainScreen.swift b/Color Picker/MainScreen.swift index 25a5b9d..da94490 100644 --- a/Color Picker/MainScreen.swift +++ b/Color Picker/MainScreen.swift @@ -1,6 +1,9 @@ import SwiftUI +import TipKit struct MainScreen: View { + // Note to self: Do not access the color picker here as it would create an infinite loop. + @Default(.uppercaseHexColor) private var uppercaseHexColor @Default(.hashPrefixInHexColor) private var hashPrefixInHexColor @Default(.legacyColorSyntax) private var legacyColorSyntax @@ -10,6 +13,7 @@ struct MainScreen: View { @State private var isPreventingUpdate = false @State private var focusedTextField: ColorFormat? @State private var colorStrings = EnumCaseMap(defaultValue: "") + @State private var colorAccessibilityName: String? let colorPanel: NSColorPanel @@ -18,6 +22,9 @@ struct MainScreen: View { BarView() colorInputs colorName + if SSApp.isFirstLaunch { // Note: We only show it on first launch as TipKit doesn't currently preserve the dismissed state. (macOS 14.3) + TipView(ColorPaletteTip()) + } } .padding(9) // 244 makes `HSL` always fit in the text field. @@ -35,13 +42,18 @@ struct MainScreen: View { .onChange(of: legacyColorSyntax) { updateColorsFromPanel() } - .onReceive(colorPanel.colorDidChangePublisher) { + .onReceive(colorPanel.colorDidChange) { + colorAccessibilityName = colorPanel.color.accessibilityName + guard focusedTextField == nil else { return } updateColorsFromPanel(preventUpdate: true) } + .task { + try? Tips.configure() + } } private func updateColorsFromPanel( @@ -124,7 +136,7 @@ struct MainScreen: View { @ViewBuilder private var colorName: some View { if showAccessibilityColorName { - Text(colorPanel.color.accessibilityName) + Text(colorAccessibilityName ?? colorPanel.color.accessibilityName) .font(.system(largerText ? .title3 : .body)) .textSelection(.enabled) .accessibilityHidden(true) @@ -358,3 +370,17 @@ private struct PalettesButton: View { } } } + +private struct ColorPaletteTip: Tip { + var title: Text { + Text("Creating a Color Palette") + } + + var message: Text? { + Text("To create a new color palette, click the third tab at the top of the window, click the \(Image(systemName: "ellipsis.circle")) button, and then select “New”.") + } + + var image: Image? { + Image(systemName: "swatchpalette") + } +} diff --git a/Color Picker/Utilities.swift b/Color Picker/Utilities.swift index 78eaf3c..9aa62cf 100644 --- a/Color Picker/Utilities.swift +++ b/Color Picker/Utilities.swift @@ -298,7 +298,7 @@ extension SSApp { Initialize Sentry. */ static func initSentry(_ dsn: String) { - #if !DEBUG && canImport(Sentry) + #if !DEBUG && !APP_EXTENSION && canImport(Sentry) SentrySDK.start { $0.dsn = dsn $0.enableSwizzling = false @@ -1278,7 +1278,7 @@ extension NSColorPanel { /** Publishes when the color in the color panel changes. */ - var colorDidChangePublisher: some Publisher { + var colorDidChange: some Publisher { NotificationCenter.default .publisher(for: Self.colorDidChangeNotification, object: self) .map { _ in } @@ -2054,7 +2054,7 @@ extension NSObject { } -enum SSPublishers { +enum SSEvents { /** Publishes when the app becomes active/inactive. */ @@ -2157,7 +2157,10 @@ extension NSPasteboard { @Published var pasteboard: NSPasteboard { didSet { - if onlyWhenAppIsActive, !NSApp.isActive { + if + onlyWhenAppIsActive, + !NSApp.isActive + { stop() return } @@ -2178,7 +2181,7 @@ extension NSPasteboard { self.onlyWhenAppIsActive = onlyWhileAppIsActive if onlyWhileAppIsActive { - SSPublishers.appIsActive + SSEvents.appIsActive .sink { [weak self] isActive in guard let self else { return @@ -3302,6 +3305,7 @@ extension NSStatusItem { /** Show a one-time menu from the status item. */ + @MainActor func showMenu(_ menu: NSMenu) { self.menu = menu button!.performClick(nil) @@ -3459,6 +3463,7 @@ extension NSColorList { .filter { !$0.allKeys.isEmpty } // `availableColorLists` returns duplicates after editing a palette, for example, adding a color to it. .removingDuplicates() + .sorted(using: .keyPath(\.name)) } var colors: [Color.Resolved] { @@ -3555,3 +3560,20 @@ extension NSColorPanel { } } } + + +extension SortComparator { + static func keyPath( + _ keyPath: KeyPath, + order: SortOrder = .forward + ) -> KeyPathComparator where Self == KeyPathComparator { + .init(keyPath, order: order) + } + + static func keyPath( + _ keyPath: KeyPath, + order: SortOrder = .forward + ) -> KeyPathComparator where Self == KeyPathComparator { + .init(keyPath, order: order) + } +} diff --git a/readme.md b/readme.md index 617da02..f62e759 100644 --- a/readme.md +++ b/readme.md @@ -15,7 +15,7 @@ The macOS color picker as an app with lots of extra features. ## Download -[![](https://tools.applemediaservices.com/api/badges/download-on-the-mac-app-store/black/en-us?size=250x83&releaseDate=1615852800)](https://apps.apple.com/app/id1545870783) +[![](https://sindresorhus.com/assets/download-on-app-store-badge.svg)](https://apps.apple.com/app/id1545870783) Requires macOS 14 or later. @@ -66,7 +66,7 @@ You can use the following keyboard shortcuts in the app: The built-in color picker supports plugins: -- [Scala Color](https://bjango.com/mac/skalacolor/) +- [Skala Color](https://bjango.com/mac/skalacolor/) - [Pro Picker](https://formulae.brew.sh/cask/colorpicker-propicker) - [Material Design](https://github.com/johnyanarella/MaterialDesignColorPicker) - [Color Picker Plus](https://github.com/viktorstrate/color-picker-plus)