Skip to content

Commit

Permalink
Migrate appearance settings to SwiftUI
Browse files Browse the repository at this point in the history
  • Loading branch information
p0deje committed Sep 14, 2024
1 parent 342ef3d commit dcdf84c
Show file tree
Hide file tree
Showing 78 changed files with 1,001 additions and 2,771 deletions.
123 changes: 68 additions & 55 deletions Maccy.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

16 changes: 14 additions & 2 deletions Maccy/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,20 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}

private func migrateUserDefaults() {
// Start 2.x from scratch
Defaults.reset(.migrations)
if Defaults[.migrations]["2024-07-01-version-2"] != true {
// Start 2.x from scratch.
Defaults.reset(.migrations)

// Inverse hide* configuration keys.
Defaults[.showFooter] = !UserDefaults.standard.bool(forKey: "hideFooter")
Defaults[.showSearch] = !UserDefaults.standard.bool(forKey: "hideSearch")
Defaults[.showTitle] = !UserDefaults.standard.bool(forKey: "hideTitle")
UserDefaults.standard.removeObject(forKey: "hideFooter")
UserDefaults.standard.removeObject(forKey: "hideSearch")
UserDefaults.standard.removeObject(forKey: "hideTitle")

Defaults[.migrations]["2024-07-01-version-2"] = true
}
}

private func clearOrphanRecords() {
Expand Down
14 changes: 7 additions & 7 deletions Maccy/Defaults.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ extension Defaults.Keys {
static let enabledPasteboardTypes = Key<Set<NSPasteboard.PasteboardType>>(
"enabledPasteboardTypes", default: [.fileURL, .png, .string, .tiff]
)
static let hideFooter = Key<Bool>("hideFooter", default: false)
static let hideSearch = Key<Bool>("hideSearch", default: false)
static let hideTitle = Key<Bool>("hideTitle", default: false)
static let highlightMatch = Key<String>("highlightMatch", default: "bold")
static let highlightMatch = Key<HighlightMatch>("highlightMatch", default: .bold)
static let ignoreAllAppsExceptListed = Key<Bool>("ignoreAllAppsExceptListed", default: false)
static let ignoreEvents = Key<Bool>("ignoreEvents", default: false)
static let ignoreOnlyNextEvent = Key<Bool>("ignoreOnlyNextEvent", default: false)
Expand All @@ -30,19 +27,22 @@ extension Defaults.Keys {
static let lastReviewRequestedAt = Key<Date>("lastReviewRequestedAt", default: Date.now)
static let maxMenuItemLength = Key<Int>("maxMenuItemLength", default: 50)
static let maxMenuItems = Key<Int>("maxMenuItems", default: 0)
static let menuIcon = Key<String>("menuIcon", default: "maccy")
static let menuIcon = Key<MenuIcon>("menuIcon", default: .maccy)
static let migrations = Key<[String: Bool]>("migrations", default: [:])
static let numberOfUsages = Key<Int>("numberOfUsages", default: 0)
static let pasteByDefault = Key<Bool>("pasteByDefault", default: false)
static let pinTo = Key<String>("pinTo", default: "top")
static let popupPosition = Key<String>("popupPosition", default: "cursor")
static let pinTo = Key<PinsPosition>("pinTo", default: .top)
static let popupPosition = Key<PopupPosition>("popupPosition", default: .cursor)
static let popupScreen = Key<Int>("popupScreen", default: 0)
static let previewDelay = Key<Int>("previewDelay", default: 1500)
static let removeFormattingByDefault = Key<Bool>("removeFormattingByDefault", default: false)
static let searchMode = Key<Search.Mode>("searchMode", default: .exact)
static let showFooter = Key<Bool>("showFooter", default: true)
static let showInStatusBar = Key<Bool>("showInStatusBar", default: true)
static let showRecentCopyInMenuBar = Key<Bool>("showRecentCopyInMenuBar", default: false)
static let showSearch = Key<Bool>("showSearch", default: true)
static let showSpecialSymbols = Key<Bool>("showSpecialSymbols", default: true)
static let showTitle = Key<Bool>("showTitle", default: true)
static let size = Key<Int>("historySize", default: 200)
static let sortBy = Key<Sorter.By>("sortBy", default: .lastCopiedAt)
static let suppressClearAlert = Key<Bool>("suppressClearAlert", default: false)
Expand Down
1 change: 1 addition & 0 deletions Maccy/Extensions/NSImage+Names.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Cocoa
extension NSImage {
static let gearshape = NSImage(systemSymbolName: "gearshape", accessibilityDescription: "gearshape")
static let externaldrive = NSImage(systemSymbolName: "externaldrive", accessibilityDescription: "externaldrive")
static let paintpalette = NSImage(systemSymbolName: "paintpalette", accessibilityDescription: "paintpalette")
}

extension NSImage.Name {
Expand Down
4 changes: 2 additions & 2 deletions Maccy/Extensions/NSScreen+ForPopup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import Defaults
extension NSScreen {
static var forPopup: NSScreen? {
let desiredScreen = Defaults[.popupScreen]
if desiredScreen == 0 || desiredScreen > NSScreen.screens.count {
if desiredScreen == 0 || desiredScreen >= NSScreen.screens.count {
return NSScreen.main
} else {
return NSScreen.screens[desiredScreen - 1]
return NSScreen.screens[desiredScreen]
}
}
}
21 changes: 21 additions & 0 deletions Maccy/HighlightMatch.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Foundation
import Defaults

enum HighlightMatch: String, CaseIterable, Identifiable, CustomStringConvertible, Defaults.Serializable {
case bold
case italic
case underline

var id: Self { self }

var description: String {
switch self {
case .bold:
return NSLocalizedString("HighlightMatchBold", tableName: "AppearanceSettings", comment: "")
case .italic:
return NSLocalizedString("HighlightMatchItalic", tableName: "AppearanceSettings", comment: "")
case .underline:
return NSLocalizedString("HighlightMatchUnderline", tableName: "AppearanceSettings", comment: "")
}
}
}
2 changes: 1 addition & 1 deletion Maccy/History/Sorter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class Sorter {
}

private func byPinned(_ lhs: HistoryItem, _ rhs: HistoryItem) -> Bool {
if Defaults[.pinTo] == "bottom" {
if Defaults[.pinTo] == .bottom {
return (lhs.pin == nil) && (rhs.pin != nil)
} else {
return (lhs.pin != nil) && (rhs.pin == nil)
Expand Down
26 changes: 19 additions & 7 deletions Maccy/Maccy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,18 @@ class Maccy: NSObject {
return Settings.PaneHostingController(pane: paneView)
}

private let AppearanceSettingsViewController: () -> SettingsPane = {
let paneView = Settings.Pane(
identifier: Settings.PaneIdentifier.appearance,
title: NSLocalizedString("Title", tableName: "AppearanceSettings", comment: ""),
toolbarIcon: NSImage.paintpalette!
) {
AppearanceSettingsPane()
}

return Settings.PaneHostingController(pane: paneView)
}

private lazy var settingsWindowController = SettingsWindowController(
panes: [
GeneralSettingsViewController(),
Expand Down Expand Up @@ -266,17 +278,17 @@ class Maccy: NSObject {
statusItem.button?.title = String(title.prefix(statusItemTitleMaxLength))
}

private func updateStatusMenuIcon(_ newIcon: String) {
private func updateStatusMenuIcon(_ newIcon: MenuIcon) {
guard let button = statusItem.button else {
return
}

switch newIcon {
case "scissors":
case .scissors:
button.image = NSImage(named: .scissors)
case "paperclip":
case .paperclip:
button.image = NSImage(named: .paperclip)
case "clipboard":
case .clipboard:
button.image = NSImage(named: .clipboard)
default:
button.image = NSImage(named: .maccyStatusBar)
Expand Down Expand Up @@ -308,13 +320,13 @@ class Maccy: NSObject {
self.menu.regenerateMenuItemTitles()
CoreDataManager.shared.saveContext()
}
hideFooterObserver = Defaults.observe(.hideFooter, options: []) { _ in
hideFooterObserver = Defaults.observe(.showFooter, options: []) { _ in
self.updateFooter()
}
hideSearchObserver = Defaults.observe(.hideSearch, options: []) { _ in
hideSearchObserver = Defaults.observe(.showSearch, options: []) { _ in
self.updateHeader()
}
hideTitleObserver = Defaults.observe(.hideTitle, options: []) { _ in
hideTitleObserver = Defaults.observe(.showTitle, options: []) { _ in
self.updateHeader()
}
pasteByDefaultObserver = Defaults.observe(.pasteByDefault, options: []) { _ in
Expand Down
4 changes: 2 additions & 2 deletions Maccy/Menu/HistoryMenuItem/HistoryMenuItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,9 @@ class HistoryMenuItem: NSMenuItem {

if Range(highlightRange, in: title) != nil {
switch Defaults[.highlightMatch] {
case "italic":
case .italic:
attributedTitle.addAttribute(.font, value: systemItalicFont, range: highlightRange)
case "underline":
case .underline:
attributedTitle.addAttributes([
.underlineStyle: NSUnderlineStyle.single.rawValue,
.font: systemFont
Expand Down
4 changes: 2 additions & 2 deletions Maccy/Menu/MenuFooter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ enum MenuFooter: Int, CaseIterable {

var menuItem: NSMenuItem {
let item = self == .separator ? NSMenuItem.separator() : NSMenuItem()
item.isAlternate = isAlternate && !Defaults[.hideFooter]
item.isHidden = Defaults[.hideFooter]
item.isAlternate = isAlternate && Defaults[.showFooter]
item.isHidden = !Defaults[.showFooter]
item.keyEquivalent = keyEquivalent
item.keyEquivalentModifierMask = keyEquivalentModifierMask
item.tag = rawValue
Expand Down
6 changes: 3 additions & 3 deletions Maccy/Menu/MenuHeader/MenuHeaderView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class MenuHeaderView: NSView, NSSearchFieldDelegate {
}

private lazy var customMenu: Menu? = self.enclosingMenuItem?.menu as? Menu
private lazy var headerHeight = Defaults[.hideSearch] ? 1 : 28
private lazy var headerHeight = !Defaults[.showSearch] ? 1 : 28
private lazy var headerSize = NSSize(width: Menu.menuWidth, height: headerHeight)

override func awakeFromNib() {
Expand All @@ -41,12 +41,12 @@ class MenuHeaderView: NSView, NSSearchFieldDelegate {
horizontalRightPadding.constant = macOSXRightPadding
}

if Defaults[.hideTitle] {
if !Defaults[.showTitle] {
titleField.isHidden = true
removeConstraint(titleAndSearchSpacing)
}

if Defaults[.hideSearch] {
if !Defaults[.showSearch] {
constraints.forEach(removeConstraint)
}
}
Expand Down
24 changes: 24 additions & 0 deletions Maccy/Menu/MenuIcon.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import AppKit
import Defaults

enum MenuIcon: String, CaseIterable, Identifiable, Defaults.Serializable {
case maccy
case clipboard
case scissors
case paperclip

var id: Self { self }

var image: NSImage {
switch self {
case .maccy:
return NSImage(named: .maccyStatusBar)!
case .clipboard:
return NSImage(named: .clipboard)!
case .scissors:
return NSImage(named: .scissors)!
case .paperclip:
return NSImage(named: .paperclip)!
}
}
}
6 changes: 3 additions & 3 deletions Maccy/Menu/PopupLocation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ enum PopupLocation {

static var forUserDefaults: PopupLocation {
switch Defaults[.popupPosition] {
case "center":
case .center:
if let frame = NSScreen.forPopup?.visibleFrame {
return .centeredInScreen(frame: frame)
}
case "statusItem":
case .statusItem:
return .inMenuBar
case "window":
case .window:
if let windowFrame = NSWorkspace.shared.frontmostApplication?.windowFrame {
return .centeredInWindow(frame: windowFrame)
}
Expand Down
18 changes: 18 additions & 0 deletions Maccy/PinsPosition.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Foundation
import Defaults

enum PinsPosition: String, CaseIterable, Identifiable, CustomStringConvertible, Defaults.Serializable {
case top
case bottom

var id: Self { self }

var description: String {
switch self {
case .top:
return NSLocalizedString("PinToTop", tableName: "AppearanceSettings", comment: "")
case .bottom:
return NSLocalizedString("PinToBottom", tableName: "AppearanceSettings", comment: "")
}
}
}
24 changes: 24 additions & 0 deletions Maccy/PopupPosition.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Foundation
import Defaults

enum PopupPosition: String, CaseIterable, Identifiable, CustomStringConvertible, Defaults.Serializable {
case cursor
case statusItem
case window
case center

var id: Self { self }

var description: String {
switch self {
case .cursor:
return NSLocalizedString("PopupAtCursor", tableName: "AppearanceSettings", comment: "")
case .statusItem:
return NSLocalizedString("PopupAtMenuBarIcon", tableName: "AppearanceSettings", comment: "")
case .window:
return NSLocalizedString("PopupAtWindowCenter", tableName: "AppearanceSettings", comment: "")
case .center:
return NSLocalizedString("PopupAtScreenCenter", tableName: "AppearanceSettings", comment: "")
}
}
}
Loading

0 comments on commit dcdf84c

Please sign in to comment.