Skip to content

Commit

Permalink
Minor tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
sindresorhus committed Jan 17, 2023
1 parent ba1c78c commit 0092873
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 152 deletions.
4 changes: 2 additions & 2 deletions Color Picker.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "swiftlint\n";
shellScript = "PATH=\"/opt/homebrew/bin/:${PATH}\"\nswiftlint\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
Expand Down Expand Up @@ -661,7 +661,7 @@
repositoryURL = "https://github.com/sindresorhus/Defaults";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 6.3.0;
minimumVersion = 7.1.0;
};
};
E3F4BC852788A5780075DC52 /* XCRemoteSwiftPackageReference "sentry-cocoa" */ = {
Expand Down
20 changes: 13 additions & 7 deletions Color Picker/App.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import SwiftUI
import Defaults
import LaunchAtLogin

// TODO: Remove the view menu

/**
NOTES:
- The "com.apple.security.files.user-selected.read-only" entitlement is required by the "Open" menu in the "Color Palettes" pane.
Expand Down Expand Up @@ -62,6 +63,10 @@ struct AppMain: App {
.keyboardShortcut("v", modifiers: [.shift, .command])
.disabled(NSColor.fromPasteboardGraceful(.general) == nil)
}
CommandGroup(after: .windowSize) {
Defaults.Toggle("Stay on Top", key: .stayOnTop)
.keyboardShortcut("t", modifiers: [.control, .command])
}
CommandGroup(replacing: .help) {
Link("What is LCH color?", destination: "https://lea.verou.me/2020/04/lch-colors-in-css-what-why-and-how/")
Link("FAQ", destination: "https://github.com/sindresorhus/System-Color-Picker#faq")
Expand Down Expand Up @@ -136,10 +141,11 @@ private final class AppDelegate: NSObject, NSApplicationDelegate {
}
}

// Does not work on macOS 12.0.1 because of `WindowGroup`: https://github.com/feedback-assistant/reports/issues/246
// This is only run when the app is started when it's already running.
// func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
// AppState.shared.handleAppReopen()
// return true
// }
func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
if #available(macOS 13, *) {
AppState.shared.handleAppReopen()
}

return false
}
}
2 changes: 0 additions & 2 deletions Color Picker/AppState.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import SwiftUI
import Combine
import Defaults
import Sentry

@MainActor
Expand Down
1 change: 0 additions & 1 deletion Color Picker/ColorPanel.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Cocoa
import Defaults

@MainActor
final class ColorPanel: NSColorPanel, NSWindowDelegate {
Expand Down
265 changes: 136 additions & 129 deletions Color Picker/ColorPickerScreen.swift
Original file line number Diff line number Diff line change
@@ -1,133 +1,4 @@
import SwiftUI
import Defaults

private struct RecentlyPickedColorsButton: View {
@EnvironmentObject private var appState: AppState
@Default(.recentlyPickedColors) private var recentlyPickedColors

// TODO: Find a better way to handle this than having to subscribe to each key.
@Default(.preferredColorFormat) private var preferredColorFormat // Only to get updates
@Default(.uppercaseHexColor) private var uppercaseHexColor // Only to get updates
@Default(.hashPrefixInHexColor) private var hashPrefixInHexColor // Only to get updates
@Default(.legacyColorSyntax) private var legacyColorSyntax // Only to get updates

var body: some View {
Menu {
Group {
ForEach(recentlyPickedColors.reversed()) { color in
Button {
appState.colorPanel.color = color
} label: {
Label {
Text(color.stringRepresentation)
} icon: {
// We don't use SwiftUI here as it only supports showing an actual image. (macOS 12.0)
// https://github.com/feedback-assistant/reports/issues/247
Image(nsImage: color.swatchImage)
}
.labelStyle(.titleAndIcon)
}
}
Divider()
Button("Clear") {
recentlyPickedColors = []
}
}
// TODO: Remove when targeting macOS 13 where it's fixed.
// Without, it becomes disabled. (macOS 12.4)
.buttonStyle(.automatic)
} label: {
Image(systemName: "clock.fill")
.controlSize(.large)
// .padding(8) // Has no effect. (macOS 12.0.1)
.contentShape(.rectangle)
}
.menuIndicator(.hidden)
.padding(8)
.fixedSize()
.opacity(0.6) // Try to match the other buttons.
.disabled(recentlyPickedColors.isEmpty)
.help(recentlyPickedColors.isEmpty ? "No recently picked colors" : "Recently picked colors")
}
}

private struct BarView: View {
@Environment(\.colorScheme) private var colorScheme
@EnvironmentObject private var appState: AppState
@StateObject private var pasteboardObserver = NSPasteboard.SimpleObservable(.general).stop()
@Default(.showInMenuBar) private var showInMenuBar

var body: some View {
HStack(spacing: 12) {
Button {
appState.pickColor()
} label: {
Image(systemName: "eyedropper")
.font(.system(size: 14).bold())
.padding(8)
}
.contentShape(.rectangle)
.help("Pick color")
.keyboardShortcut("p")
.padding(.leading, 4)
Button {
appState.pasteColor()
} label: {
Image(systemName: "paintbrush.fill")
.padding(8)
}
.contentShape(.rectangle)
.help("Paste color in the format Hex, HSL, RGB, or LCH")
.keyboardShortcut("v", modifiers: [.shift, .command])
.disabled(NSColor.fromPasteboardGraceful(.general) == nil)
RecentlyPickedColorsButton()
actionButton
Spacer()
}
// Cannot do this as the `Menu` buttons don't respect it. (macOS 12.0.1)
// https://github.com/feedback-assistant/reports/issues/249
// .font(.title3)
.background {
RoundedRectangle(cornerRadius: 6, style: .continuous)
.fill(Color.black.opacity(colorScheme == .dark ? 0.17 : 0.05))
}
.padding(.vertical, 4)
.buttonStyle(.borderless)
.menuStyle(.borderlessButton)
.onAppearOnScreen {
pasteboardObserver.start()
}
.onDisappearFromScreen {
pasteboardObserver.stop()
}
}

private var actionButton: some View {
Menu {
Button("Copy as HSB") {
appState.colorPanel.color.hsbColorString.copyToPasteboard()
}
if showInMenuBar {
Divider()
Button(OS.isMacOS13OrLater ? "Settings…" : "Preferences…") {
SSApp.showSettingsWindow()
}
.keyboardShortcut(",")
}
} label: {
Label("Action", systemImage: "ellipsis.circle.fill")
.labelStyle(.iconOnly)
// .padding(8) // Has no effect. (macOS 12.0.1)
}
// TODO: Remove when targeting macOS 13 where it's fixed.
.buttonStyle(.automatic) // Without, it becomes disabled: https://github.com/feedback-assistant/reports/issues/250 (macOS 12.0.1)
.padding(8)
.contentShape(.rectangle)
.fixedSize()
.opacity(0.6) // Try to match the other buttons.
.menuIndicator(.hidden)
}
}

struct ColorPickerScreen: View {
@EnvironmentObject private var appState: AppState
Expand All @@ -136,6 +7,7 @@ struct ColorPickerScreen: View {
@Default(.legacyColorSyntax) private var legacyColorSyntax
@Default(.shownColorFormats) private var shownColorFormats
@Default(.largerText) private var largerText
@Default(.showAccessibilityColorName) private var showAccessibilityColorName
@State private var hexColor = ""
@State private var hslColor = ""
@State private var rgbColor = ""
Expand Down Expand Up @@ -312,6 +184,11 @@ struct ColorPickerScreen: View {
if shownColorFormats.contains(.lch) {
lchColorView
}
if showAccessibilityColorName {
Text(colorPanel.color.accessibilityName)
.font(.system(largerText ? .title3 : .body))
.textSelection(.enabled)
}
}
.padding(9)
// 244 makes `HSL` always fit in the text field.
Expand Down Expand Up @@ -380,3 +257,133 @@ struct ColorPickerScreen_Previews: PreviewProvider {
ColorPickerScreen(colorPanel: .shared)
}
}

private struct BarView: View {
@Environment(\.colorScheme) private var colorScheme
@EnvironmentObject private var appState: AppState
@StateObject private var pasteboardObserver = NSPasteboard.SimpleObservable(.general).stop()
@Default(.showInMenuBar) private var showInMenuBar

var body: some View {
HStack(spacing: 12) {
Button {
appState.pickColor()
} label: {
Image(systemName: "eyedropper")
.font(.system(size: 14).bold())
.padding(8)
}
.contentShape(.rectangle)
.help("Pick color")
.keyboardShortcut("p")
.padding(.leading, 4)
Button {
appState.pasteColor()
} label: {
Image(systemName: "paintbrush.fill")
.padding(8)
}
.contentShape(.rectangle)
.help("Paste color in the format Hex, HSL, RGB, or LCH")
.keyboardShortcut("v", modifiers: [.shift, .command])
.disabled(NSColor.fromPasteboardGraceful(.general) == nil)
RecentlyPickedColorsButton()
actionButton
Spacer()
}
// Cannot do this as the `Menu` buttons don't respect it. (macOS 12.0.1)
// https://github.com/feedback-assistant/reports/issues/249
// .font(.title3)
.background {
RoundedRectangle(cornerRadius: 6, style: .continuous)
.fill(Color.black.opacity(colorScheme == .dark ? 0.17 : 0.05))
}
.padding(.vertical, 4)
.buttonStyle(.borderless)
.menuStyle(.borderlessButton)
.onAppearOnScreen {
pasteboardObserver.start()
}
.onDisappearFromScreen {
pasteboardObserver.stop()
}
}

private var actionButton: some View {
Menu {
Button("Copy as HSB") {
appState.colorPanel.color.hsbColorString.copyToPasteboard()
}
if showInMenuBar {
Divider()
Defaults.Toggle("Stay on Top", key: .stayOnTop)
Divider()
Button(OS.isMacOS13OrLater ? "Settings…" : "Preferences…") {
SSApp.showSettingsWindow()
}
.keyboardShortcut(",")
}
} label: {
Label("Action", systemImage: "ellipsis.circle.fill")
.labelStyle(.iconOnly)
// .padding(8) // Has no effect. (macOS 12.0.1)
}
// TODO: Remove when targeting macOS 13 where it's fixed.
.buttonStyle(.automatic) // Without, it becomes disabled: https://github.com/feedback-assistant/reports/issues/250 (macOS 12.0.1)
.padding(8)
.contentShape(.rectangle)
.fixedSize()
.opacity(0.6) // Try to match the other buttons.
.menuIndicator(.hidden)
}
}

private struct RecentlyPickedColorsButton: View {
@EnvironmentObject private var appState: AppState
@Default(.recentlyPickedColors) private var recentlyPickedColors

// TODO: Find a better way to handle this than having to subscribe to each key.
@Default(.preferredColorFormat) private var preferredColorFormat // Only to get updates
@Default(.uppercaseHexColor) private var uppercaseHexColor // Only to get updates
@Default(.hashPrefixInHexColor) private var hashPrefixInHexColor // Only to get updates
@Default(.legacyColorSyntax) private var legacyColorSyntax // Only to get updates

var body: some View {
Menu {
Group {
ForEach(recentlyPickedColors.reversed()) { color in
Button {
appState.colorPanel.color = color
} label: {
Label {
Text(color.stringRepresentation)
} icon: {
// We don't use SwiftUI here as it only supports showing an actual image. (macOS 12.0)
// https://github.com/feedback-assistant/reports/issues/247
Image(nsImage: color.swatchImage)
}
.labelStyle(.titleAndIcon)
}
}
Divider()
Button("Clear") {
recentlyPickedColors = []
}
}
// TODO: Remove when targeting macOS 13 where it's fixed.
// Without, it becomes disabled. (macOS 12.4)
.buttonStyle(.automatic)
} label: {
Image(systemName: "clock.fill")
.controlSize(.large)
// .padding(8) // Has no effect. (macOS 12.0.1)
.contentShape(.rectangle)
}
.menuIndicator(.hidden)
.padding(8)
.fixedSize()
.opacity(0.6) // Try to match the other buttons.
.disabled(recentlyPickedColors.isEmpty)
.help(recentlyPickedColors.isEmpty ? "No recently picked colors" : "Recently picked colors")
}
}
2 changes: 1 addition & 1 deletion Color Picker/Constants.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Cocoa
import Defaults
import KeyboardShortcuts

extension Defaults.Keys {
Expand All @@ -18,6 +17,7 @@ extension Defaults.Keys {
static let shownColorFormats = Key<Set<ColorFormat>>("shownColorFormats", default: [.hex, .hsl, .rgb, .lch])
static let largerText = Key<Bool>("largerText", default: false)
static let copyColorAfterPicking = Key<Bool>("copyColorAfterPicking", default: false)
static let showAccessibilityColorName = Key<Bool>("showAccessibilityColorName", default: false)

// Deprecated
static let colorFormatToCopyAfterPicking = Key<CopyColorFormat>("colorFormatToCopyAfterPicking", default: .none)
Expand Down
Loading

0 comments on commit 0092873

Please sign in to comment.