Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions Pika.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
1C7412E01A6EF6E6D516CEB6 /* ColorHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB487C20A8FA16610A2DE6C4 /* ColorHistory.swift */; };
220D5E9428DB154300B6285E /* AppModeButtons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 220D5E9328DB154300B6285E /* AppModeButtons.swift */; };
220D5E9828DB158400B6285E /* AppModeToggleGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 220D5E9728DB158400B6285E /* AppModeToggleGroup.swift */; };
221600F925A62E5B00B8B7D9 /* IconImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 221600F825A62E5B00B8B7D9 /* IconImage.swift */; };
Expand All @@ -16,8 +17,22 @@
22D28DB72862377F00FC7DD4 /* OverflowContentViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22D28DB62862377F00FC7DD4 /* OverflowContentViewModifier.swift */; };
22EF1D9B25B7AA18001102FA /* Sequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22EF1D9A25B7AA18001102FA /* Sequence.swift */; };
22FE80B325BA0F820063759E /* KeyboardShortcutItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22FE80B225BA0F820063759E /* KeyboardShortcutItem.swift */; };
3FB457874C3F741FC84DADD6 /* ColorHistoryManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1804CBF1E38631A06B89C401 /* ColorHistoryManager.swift */; };
68267E79E2A1817195C7C16F /* ColorHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB487C20A8FA16610A2DE6C4 /* ColorHistory.swift */; };
C49A11482DB394F500EE7E80 /* APCACompliance.swift in Sources */ = {isa = PBXBuildFile; fileRef = C49A11472DB394F500EE7E80 /* APCACompliance.swift */; };
C49A11492DB394F500EE7E80 /* APCACompliance.swift in Sources */ = {isa = PBXBuildFile; fileRef = C49A11472DB394F500EE7E80 /* APCACompliance.swift */; };
B1C2D3E4F5061728394A5B6C /* ColorPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F60718293A4B5C /* ColorPalette.swift */; };
C1D2E3F4051627384A5B6C7D /* ColorPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F60718293A4B5C /* ColorPalette.swift */; };
B1C2D3E4F5061728394A5B6D /* PaletteSyncManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F60718293A4B5D /* PaletteSyncManager.swift */; };
C1D2E3F4051627384A5B6C7E /* PaletteSyncManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F60718293A4B5D /* PaletteSyncManager.swift */; };
B1C2D3E4F5061728394A5B6E /* ColorPaletteBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F60718293A4B5E /* ColorPaletteBar.swift */; };
C1D2E3F4051627384A5B6C7F /* ColorPaletteBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F60718293A4B5E /* ColorPaletteBar.swift */; };
B1C2D3E4F5061728394A5B6F /* ColorPalettes.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F60718293A4B5F /* ColorPalettes.swift */; };
C1D2E3F4051627384A5B6C80 /* ColorPalettes.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F60718293A4B5F /* ColorPalettes.swift */; };
B1C2D3E4F5061728394A5B70 /* PaletteEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F60718293A4B60 /* PaletteEditor.swift */; };
C1D2E3F4051627384A5B6C81 /* PaletteEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F60718293A4B60 /* PaletteEditor.swift */; };
D1E2F3A4B5C6D7E8F9A0B1C1 /* SwatchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1E2F3A4B5C6D7E8F9A0B1C0 /* SwatchBar.swift */; };
D1E2F3A4B5C6D7E8F9A0B1C2 /* SwatchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1E2F3A4B5C6D7E8F9A0B1C0 /* SwatchBar.swift */; };
EA0C525025AA729300AFF716 /* Visualisation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0C524F25AA729300AFF716 /* Visualisation.swift */; };
EA0C526025AB5A2B00AFF716 /* NavigationMenuItems.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0C525F25AB5A2B00AFF716 /* NavigationMenuItems.swift */; };
EA0C526425AB5D1700AFF716 /* PikaWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0C526325AB5D1700AFF716 /* PikaWindow.swift */; };
Expand Down Expand Up @@ -128,9 +143,11 @@
F8ABAC5B2EAAD0DF008CD152 /* ColorPickOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8ABAC592EAAD0DF008CD152 /* ColorPickOverlay.swift */; };
F8ABAC5D2EAAD0F0008CD152 /* ColorPickOverlayWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8ABAC5C2EAAD0F0008CD152 /* ColorPickOverlayWindow.swift */; };
F8ABAC5E2EAAD0F0008CD152 /* ColorPickOverlayWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8ABAC5C2EAAD0F0008CD152 /* ColorPickOverlayWindow.swift */; };
FC6B02943A97C369AEDA0D64 /* ColorHistoryManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1804CBF1E38631A06B89C401 /* ColorHistoryManager.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
1804CBF1E38631A06B89C401 /* ColorHistoryManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorHistoryManager.swift; sourceTree = "<group>"; };
220D5E9328DB154300B6285E /* AppModeButtons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppModeButtons.swift; sourceTree = "<group>"; };
220D5E9728DB158400B6285E /* AppModeToggleGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppModeToggleGroup.swift; sourceTree = "<group>"; };
221600F825A62E5B00B8B7D9 /* IconImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconImage.swift; sourceTree = "<group>"; };
Expand All @@ -152,6 +169,13 @@
C1BF64202C1AE53C004D33DD /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = "<group>"; };
C1BF64212C1AE53C004D33DD /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Main.strings"; sourceTree = "<group>"; };
C49A11472DB394F500EE7E80 /* APCACompliance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APCACompliance.swift; sourceTree = "<group>"; };
CB487C20A8FA16610A2DE6C4 /* ColorHistory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorHistory.swift; sourceTree = "<group>"; };
A1B2C3D4E5F60718293A4B5C /* ColorPalette.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPalette.swift; sourceTree = "<group>"; };
A1B2C3D4E5F60718293A4B5D /* PaletteSyncManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaletteSyncManager.swift; sourceTree = "<group>"; };
A1B2C3D4E5F60718293A4B5E /* ColorPaletteBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPaletteBar.swift; sourceTree = "<group>"; };
A1B2C3D4E5F60718293A4B5F /* ColorPalettes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPalettes.swift; sourceTree = "<group>"; };
A1B2C3D4E5F60718293A4B60 /* PaletteEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaletteEditor.swift; sourceTree = "<group>"; };
D1E2F3A4B5C6D7E8F9A0B1C0 /* SwatchBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwatchBar.swift; sourceTree = "<group>"; };
EA0C524F25AA729300AFF716 /* Visualisation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Visualisation.swift; sourceTree = "<group>"; };
EA0C525F25AB5A2B00AFF716 /* NavigationMenuItems.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationMenuItems.swift; sourceTree = "<group>"; };
EA0C526325AB5D1700AFF716 /* PikaWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PikaWindow.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -306,6 +330,7 @@
EAD0B6D7259CED1D00FA2F67 /* Info.plist */,
EAE2EB9B2D03697600FA9BC9 /* Info (Mac App Store).plist */,
EA72BB8125A5334B008205E7 /* Metal */,
D1E2F30415263748596A7B8C /* Models */,
EAD0B6D8259CED1D00FA2F67 /* Pika.entitlements */,
EAD0B6D1259CED1D00FA2F67 /* Preview Content */,
EAD0B71A259D14C200FA2F67 /* Styles */,
Expand Down Expand Up @@ -344,10 +369,12 @@
isa = PBXGroup;
children = (
EA7B199B25FBA0E600E06D9D /* ClosestVector.swift */,
1804CBF1E38631A06B89C401 /* ColorHistoryManager.swift */,
F8ABAC5C2EAAD0F0008CD152 /* ColorPickOverlayWindow.swift */,
EACA8A44260501210064035C /* Exporter.swift */,
EAD0B6F1259CF29300FA2F67 /* Eyedroppers.swift */,
EA7B199525FBA08100E06D9D /* LoadColors.swift */,
A1B2C3D4E5F60718293A4B5D /* PaletteSyncManager.swift */,
EA0C526325AB5D1700AFF716 /* PikaWindow.swift */,
22D28DB62862377F00FC7DD4 /* OverflowContentViewModifier.swift */,
);
Expand All @@ -362,6 +389,9 @@
220D5E9728DB158400B6285E /* AppModeToggleGroup.swift */,
EAD0B6F5259CF29300FA2F67 /* AppVersion.swift */,
22903B0228294F49004BB9F0 /* ColorExampleRow.swift */,
CB487C20A8FA16610A2DE6C4 /* ColorHistory.swift */,
A1B2C3D4E5F60718293A4B5E /* ColorPaletteBar.swift */,
A1B2C3D4E5F60718293A4B5F /* ColorPalettes.swift */,
EA635DE025B4FC580014D91A /* ColorPickers.swift */,
F8ABAC592EAAD0DF008CD152 /* ColorPickOverlay.swift */,
EABAEADF284D50D1000716AE /* ComplianceButtons.swift */,
Expand All @@ -377,8 +407,10 @@
EAA8AE1825B8EC070049299B /* KeyboardShortcutKey.swift */,
EAD0B71B259D151400FA2F67 /* NavigationMenu.swift */,
EA0C525F25AB5A2B00AFF716 /* NavigationMenuItems.swift */,
A1B2C3D4E5F60718293A4B60 /* PaletteEditor.swift */,
EAD0B6F4259CF29300FA2F67 /* PreferencesView.swift */,
EA72BB8725A53750008205E7 /* SplashView.swift */,
D1E2F3A4B5C6D7E8F9A0B1C0 /* SwatchBar.swift */,
EA635DF025B5A6D80014D91A /* Toast.swift */,
EAF100CC25C785C4006E1EC3 /* TouchBarVisual.swift */,
226FD60F25A940F90021A67F /* VisualEffect.swift */,
Expand All @@ -387,6 +419,14 @@
path = Views;
sourceTree = "<group>";
};
D1E2F30415263748596A7B8C /* Models */ = {
isa = PBXGroup;
children = (
A1B2C3D4E5F60718293A4B5C /* ColorPalette.swift */,
);
path = Models;
sourceTree = "<group>";
};
EAD0B71A259D14C200FA2F67 /* Styles */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -657,6 +697,14 @@
EAD0B713259CFD2000FA2F67 /* Defaults.swift in Sources */,
226FD61025A940F90021A67F /* VisualEffect.swift in Sources */,
EAD0B6FE259CF29C00FA2F67 /* Constants.swift in Sources */,
FC6B02943A97C369AEDA0D64 /* ColorHistoryManager.swift in Sources */,
68267E79E2A1817195C7C16F /* ColorHistory.swift in Sources */,
D1E2F3A4B5C6D7E8F9A0B1C1 /* SwatchBar.swift in Sources */,
B1C2D3E4F5061728394A5B6C /* ColorPalette.swift in Sources */,
B1C2D3E4F5061728394A5B6D /* PaletteSyncManager.swift in Sources */,
B1C2D3E4F5061728394A5B6E /* ColorPaletteBar.swift in Sources */,
B1C2D3E4F5061728394A5B6F /* ColorPalettes.swift in Sources */,
B1C2D3E4F5061728394A5B70 /* PaletteEditor.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -717,6 +765,14 @@
EAE23DD52D032A38005BB270 /* Defaults.swift in Sources */,
EAE23DD62D032A38005BB270 /* VisualEffect.swift in Sources */,
EAE23DD72D032A38005BB270 /* Constants.swift in Sources */,
3FB457874C3F741FC84DADD6 /* ColorHistoryManager.swift in Sources */,
1C7412E01A6EF6E6D516CEB6 /* ColorHistory.swift in Sources */,
D1E2F3A4B5C6D7E8F9A0B1C2 /* SwatchBar.swift in Sources */,
C1D2E3F4051627384A5B6C7D /* ColorPalette.swift in Sources */,
C1D2E3F4051627384A5B6C7E /* PaletteSyncManager.swift in Sources */,
C1D2E3F4051627384A5B6C7F /* ColorPaletteBar.swift in Sources */,
C1D2E3F4051627384A5B6C80 /* ColorPalettes.swift in Sources */,
C1D2E3F4051627384A5B6C81 /* PaletteEditor.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
103 changes: 87 additions & 16 deletions Pika/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,53 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
var aboutWindow: NSWindow!
var preferencesWindow: NSWindow!
var eyedroppers: Eyedroppers!
let colorHistoryManager = ColorHistoryManager()
/// Retained for the app's lifetime to keep the iCloud KVS observer alive.
let paletteSyncManager = PaletteSyncManager()

var undoManager = UndoManager()
private var cachedPaletteCount = 0
private var hadColorHistory = false

override init() {
super.init()
eyedroppers = Eyedroppers()
eyedroppers.foreground.undoManager = undoManager
eyedroppers.background.undoManager = undoManager
eyedroppers.foreground.colorHistoryManager = colorHistoryManager
eyedroppers.background.colorHistoryManager = colorHistoryManager
}

var pikaTouchBarController: PikaTouchBarController!
var splashTouchBarController: SplashTouchBarController!
var aboutTouchBarController: SplashTouchBarController!

let notificationCenter = NotificationCenter.default

private func idealWindowContentHeight() -> CGFloat {
SwatchLayout.totalHeight(
base: 230,
hasHistory: hadColorHistory,
paletteCount: cachedPaletteCount
)
}

func updateWindowSize(animate: Bool) {
guard pikaWindow != nil else { return }
let contentHeight = idealWindowContentHeight()
let targetContent = NSRect(x: 0, y: 0, width: CGFloat(pikaWindow.frame.width), height: contentHeight)
let targetFrame = pikaWindow.frameRect(forContentRect: targetContent)
// Pin the top edge of the window.
let currentFrame = pikaWindow.frame
let newFrame = NSRect(
x: currentFrame.origin.x,
y: currentFrame.origin.y + currentFrame.size.height - targetFrame.height,
width: currentFrame.size.width,
height: targetFrame.height
)
pikaWindow.setFrame(newFrame, display: true, animate: animate && pikaWindow.isVisible)
}

func setupAppMode() {
var currentMode = Defaults[.appMode] == .regular
? NSApplication.ActivationPolicy.regular
Expand All @@ -41,7 +79,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
NSApp.setActivationPolicy(newMode)
NSApp.activate(ignoringOtherApps: true)
if change.newValue == .regular {
DispatchQueue.main.asyncAfter(deadline: .now()) {
DispatchQueue.main.async {
NSApp.unhide(self)

if let window = NSApp.windows.first {
Expand Down Expand Up @@ -99,11 +137,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
setupAppMode()
setupStatusBar()

// Set up eyedroppers
eyedroppers = Eyedroppers()
eyedroppers.foreground.undoManager = undoManager
eyedroppers.background.undoManager = undoManager

// Define content view
let contentView = ContentView()
.environmentObject(eyedroppers)
Expand All @@ -112,13 +145,47 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
maxWidth: 650,
minHeight: 230,
idealHeight: 230,
maxHeight: 400,
maxHeight: 550,
alignment: .center)

pikaWindow = PikaWindow.createPrimaryWindow()
pikaWindow.contentView = NSHostingView(rootView: contentView)
pikaTouchBarController = PikaTouchBarController(window: pikaWindow)

cachedPaletteCount = PaletteParser.countSections(Defaults[.paletteText])
hadColorHistory = Defaults[.showColorHistory] && !Defaults[.colorHistory].isEmpty
updateWindowSize(animate: false)

Defaults.observe(.paletteText) { [weak self] change in
DispatchQueue.main.async {
guard let self = self else { return }
let newCount = PaletteParser.countSections(change.newValue)
guard newCount != self.cachedPaletteCount else { return }
self.cachedPaletteCount = newCount
self.updateWindowSize(animate: true)
}
}.tieToLifetime(of: self)

Defaults.observe(.colorHistory) { [weak self] _ in
DispatchQueue.main.async {
guard let self = self else { return }
let hasHistory = Defaults[.showColorHistory] && !Defaults[.colorHistory].isEmpty
guard hasHistory != self.hadColorHistory else { return }
self.hadColorHistory = hasHistory
self.updateWindowSize(animate: true)
}
}.tieToLifetime(of: self)

Defaults.observe(.showColorHistory) { [weak self] _ in
DispatchQueue.main.async {
guard let self = self else { return }
let hasHistory = Defaults[.showColorHistory] && !Defaults[.colorHistory].isEmpty
guard hasHistory != self.hadColorHistory else { return }
self.hadColorHistory = hasHistory
self.updateWindowSize(animate: true)
}
}.tieToLifetime(of: self)

// Define global keyboard shortcuts
KeyboardShortcuts.onKeyUp(for: .togglePika) { [] in
if Defaults[.viewedSplash] {
Expand Down Expand Up @@ -157,25 +224,26 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
// swiftlint:disable function_body_length
@objc func handleGetURLEvent(_ event: NSAppleEventDescriptor, withReplyEvent _: NSAppleEventDescriptor) {
if let urlString = event.forKeyword(AEKeyword(keyDirectObject))?.stringValue {
let url = URL(string: urlString)
guard url != nil, let scheme = url!.scheme, let action = url!.host else {
// some error
guard let url = URL(string: urlString),
let scheme = url.scheme,
let action = url.host
else {
return
}

var list = url!.pathComponents.dropFirst()
var list = url.pathComponents.dropFirst()
let task = list.popFirst()
let colorFormat = list.popFirst()

if scheme.caseInsensitiveCompare("pika") == .orderedSame {
if colorFormat != nil {
if let format = ColorFormat.withLabel(colorFormat!) {
Defaults[.colorFormat] = format
}
if let colorFormat = colorFormat,
let format = ColorFormat.withLabel(colorFormat)
{
Defaults[.colorFormat] = format
}

if action == "format" {
if let format = ColorFormat.withLabel(task!) {
if let task = task, let format = ColorFormat.withLabel(task) {
Defaults[.colorFormat] = format
}
}
Expand Down Expand Up @@ -385,14 +453,17 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
}

@IBAction func triggerSystemPickerForeground(_: Any) {
eyedroppers.foreground.togglePicker()
notificationCenter.post(name: Notification.Name(PikaConstants.ncTriggerSystemPickerForeground), object: self)
}

@IBAction func triggerSystemPickerBackground(_: Any) {
eyedroppers.background.togglePicker()
notificationCenter.post(name: Notification.Name(PikaConstants.ncTriggerSystemPickerBackground), object: self)
}

@IBAction func triggerSwap(_: Any) {
swap(&eyedroppers.foreground.color, &eyedroppers.background.color)
notificationCenter.post(name: Notification.Name(PikaConstants.ncTriggerSwap), object: self)
}

Expand Down
3 changes: 3 additions & 0 deletions Pika/Assets/de.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -351,3 +351,6 @@

/* Duration: */
"preferences.overlay.duration" = "Dauer";

/* Color History */
"color.history" = "Color History";
Loading