Skip to content

Commit

Permalink
[chore]: Cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
jordanbaird committed Sep 3, 2024
1 parent c7812b3 commit 52390cc
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 28 deletions.
4 changes: 1 addition & 3 deletions Ice/Bridging/Bridging.swift
Original file line number Diff line number Diff line change
Expand Up @@ -315,9 +315,7 @@ extension Bridging {
extension Bridging {
/// Constants that indicate the responsivity of an app.
enum Responsivity {
case responsive
case unresponsive
case unknown
case responsive, unresponsive, unknown
}

/// Returns the responsivity of the given process.
Expand Down
62 changes: 42 additions & 20 deletions Ice/ControlItem/ControlItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,47 @@ import OSLog

/// A status item that controls a section in the menu bar.
@MainActor
final class ControlItem {
enum Identifier: String, Hashable, CaseIterable {
class ControlItem {
/// Possible identifiers for control items.
enum Identifier: String, CaseIterable {
case iceIcon = "SItem"
case hidden = "HItem"
case alwaysHidden = "AHItem"
}

enum HidingState: Int, Hashable {
case hideItems
case showItems
/// Possible hiding states for control items.
enum HidingState {
case hideItems, showItems
}

/// Possible lengths for control items.
enum Lengths {
static let standard: CGFloat = NSStatusItem.variableLength
static let expanded: CGFloat = 10_000
}

private static let sectionStorage = ObjectAssociation<MenuBarSection>()
/// Storage for internal observers.
private var cancellables = Set<AnyCancellable>()

/// The shared app state.
private weak var appState: AppState?
private var cancellables = Set<AnyCancellable>()

/// The control item's underlying status item.
private let statusItem: NSStatusItem

/// A horizontal constraint for the control item's content view.
private let constraint: NSLayoutConstraint?

/// The control item's identifier.
let identifier: Identifier
private let identifier: Identifier

/// The control item's hiding state.
/// The control item's hiding state (`@Published`).
@Published var state = HidingState.hideItems

/// A Boolean value that indicates whether the control item is visible.
/// A Boolean value that indicates whether the control item is visible (`@Published`).
@Published var isVisible = true

/// The frame of the control item's window.
/// The frame of the control item's window (`@Published`).
@Published private(set) var windowFrame: CGRect?

/// The menu bar section associated with the control item.
Expand All @@ -64,20 +70,19 @@ final class ControlItem {
return CGWindowID(window.windowNumber)
}

/// A Boolean value that indicates whether the control item is a section divider.
/// A Boolean value that indicates whether the control item serves as
/// a divider between sections.
var isSectionDivider: Bool {
guard let section else {
return false
}
return section.name != .visible
identifier != .iceIcon
}

/// A Boolean value that indicates whether the control item is currently displayed
/// in the menu bar.
/// A Boolean value that indicates whether the control item is currently
/// displayed in the menu bar.
var isAddedToMenuBar: Bool {
statusItem.isVisible
}

/// Creates a control item with the given identifier.
init(identifier: Identifier) {
let autosaveName = identifier.rawValue

Expand Down Expand Up @@ -120,15 +125,17 @@ final class ControlItem {
configureStatusItem()
}

/// Removes the status item without clearing its stored position.
deinit {
// Removing the status item has the unwanted side effect of
// deleting the preferredPosition. Cache and restore it.
// Removing the status item has the unwanted side effect of deleting
// the preferredPosition. Cache and restore it.
let autosaveName = statusItem.autosaveName as String
let cached = StatusItemDefaults[.preferredPosition, autosaveName]
NSStatusBar.system.removeStatusItem(statusItem)
StatusItemDefaults[.preferredPosition, autosaveName] = cached
}

/// Configures the internal observers for the control item.
private func configureCancellables() {
var c = Set<AnyCancellable>()

Expand Down Expand Up @@ -309,6 +316,7 @@ final class ControlItem {
cancellables = c
}

/// Sets the initial configuration for the status item.
private func configureStatusItem() {
defer {
configureCancellables()
Expand All @@ -321,6 +329,7 @@ final class ControlItem {
button.action = #selector(performAction)
}

/// Updates the appearance of the status item using the given hiding state.
private func updateStatusItem(with state: HidingState) {
guard
let appState,
Expand Down Expand Up @@ -377,6 +386,7 @@ final class ControlItem {
}
}

/// Performs the control item's action.
@objc private func performAction() {
guard
let appState,
Expand All @@ -403,6 +413,7 @@ final class ControlItem {
}
}

/// Creates a menu to show under the control item.
private func createMenu(with appState: AppState) -> NSMenu {
let menu = NSMenu(title: "Ice")

Expand Down Expand Up @@ -480,10 +491,12 @@ final class ControlItem {
return menu
}

/// Toggles the menu bar section associated with the given menu item.
@objc private func toggleMenuBarSection(for menuItem: NSMenuItem) {
Self.sectionStorage[menuItem]?.toggle()
}

/// Opens the settings window and checks for app updates.
@objc private func checkForUpdates() {
guard
let appState,
Expand Down Expand Up @@ -529,6 +542,15 @@ final class ControlItem {
}
}

private extension ControlItem {
/// Storage for menu items that toggle a menu bar section.
///
/// When one of these menu items is created, its section is stored here.
/// When its action is invoked, the section is retrieved from storage.
static let sectionStorage = ObjectAssociation<MenuBarSection>()
}

private extension Logger {
/// The logger to use for control items.
static let controlItem = Logger(category: "ControlItem")
}
9 changes: 4 additions & 5 deletions Ice/ControlItem/ControlItemImage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Cocoa

/// A Codable image for a control item.
enum ControlItemImage: Codable, Hashable {
/// An image created from drawing code in the app.
/// An image created from drawing code built into the app.
case builtin(_ name: ImageBuiltinName)
/// A system symbol image.
case symbol(_ name: String)
Expand All @@ -26,7 +26,7 @@ enum ControlItemImage: Codable, Hashable {
case .chevronSmall: StaticBuiltins.Chevron.small
}
case .symbol(let name):
let image = NSImage(systemSymbolName: name, accessibilityDescription: "")
let image = NSImage(systemSymbolName: name, accessibilityDescription: nil)
image?.isTemplate = true
return image
case .catalog(let name):
Expand Down Expand Up @@ -60,9 +60,8 @@ extension ControlItemImage {
extension ControlItemImage {
/// A namespace for static builtin images.
///
/// - Note: We use the static properties `large` and `small` to avoid
/// repeatedly executing code every time the ``nsImage`` property is
/// accessed.
/// - Note: We use the static properties `large` and `small` to avoid repeatedly
/// executing code every time ``nsImage(for:)`` is called.
private enum StaticBuiltins {
/// A namespace for static builtin chevron images.
enum Chevron {
Expand Down
5 changes: 5 additions & 0 deletions Ice/ControlItem/ControlItemImageSet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
// Ice
//

/// A named set of images that are used by control items.
///
/// An image set contains images for a control item in both the hidden and visible states.
struct ControlItemImageSet: Codable, Hashable, Identifiable {
enum Name: String, Codable, Hashable {
case arrow = "Arrow"
Expand Down Expand Up @@ -33,12 +36,14 @@ struct ControlItemImageSet: Codable, Hashable, Identifiable {
}

extension ControlItemImageSet {
/// The default image set for the Ice icon.
static let defaultIceIcon = ControlItemImageSet(
name: .dot,
hidden: .catalog("DotFill"),
visible: .catalog("DotStroke")
)

/// The image sets that the user can choose to display in the Ice icon.
static let userSelectableIceIcons = [
ControlItemImageSet(
name: .arrow,
Expand Down

0 comments on commit 52390cc

Please sign in to comment.