Skip to content

Commit

Permalink
Update caching
Browse files Browse the repository at this point in the history
  • Loading branch information
jordanbaird committed Oct 9, 2024
1 parent 464abfa commit 588031d
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 18 deletions.
20 changes: 15 additions & 5 deletions Ice/MenuBar/ItemManagement/MenuBarItemImageCache.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ final class MenuBarItemImageCache: ObservableObject {
cancellables = c
}

/// Logs a reason for skipping the cache.
private func logSkippingCache(reason: String) {
Logger.imageCache.debug("Skipping menu bar item image cache as \(reason)")
}

/// Returns a Boolean value that indicates whether caching menu bar items failed for
/// the given section.
@MainActor
Expand Down Expand Up @@ -231,22 +236,27 @@ final class MenuBarItemImageCache: ObservableObject {

if !isIceBarPresented && !isSearchPresented {
guard await appState.navigationState.isAppFrontmost else {
Logger.imageCache.debug("Skipping image cache as Ice Bar not visible, app not frontmost")
logSkippingCache(reason: "Ice Bar not visible, app not frontmost")
return
}
guard await appState.navigationState.isSettingsPresented else {
Logger.imageCache.debug("Skipping image cache as Ice Bar not visible, Settings not visible")
logSkippingCache(reason: "Ice Bar not visible, Settings not visible")
return
}
guard case .menuBarLayout = await appState.navigationState.settingsNavigationIdentifier else {
Logger.imageCache.debug("Skipping image cache as Ice Bar not visible, Settings visible but not on Menu Bar Layout pane")
logSkippingCache(reason: "Ice Bar not visible, Settings visible but not on Menu Bar Layout")
return
}
}

guard await !appState.itemManager.isMovingItem else {
logSkippingCache(reason: "an item is currently being moved")
return
}

if let lastItemMoveStartDate = await appState.itemManager.lastItemMoveStartDate {
guard Date.now.timeIntervalSince(lastItemMoveStartDate) > 3 else {
Logger.imageCache.debug("Skipping image cache as an item was recently moved")
guard Date.now.timeIntervalSince(lastItemMoveStartDate) > 1 else {
logSkippingCache(reason: "an item was recently moved")
return
}
}
Expand Down
63 changes: 55 additions & 8 deletions Ice/MenuBar/ItemManagement/MenuBarItemManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ final class MenuBarItemManager: ObservableObject {
/// The last time an item was moved.
private(set) var lastItemMoveStartDate: Date?

/// Counter to determine if a menu bar item, or group of menu bar
/// items is being moved.
private var itemMoveCount = 0

/// A Boolean value that indicates whether a mouse button is down.
private var isMouseButtonDown = false

Expand All @@ -132,6 +136,10 @@ final class MenuBarItemManager: ObservableObject {
.otherMouseUp,
]

/// A Boolean value that indicates whether a menu bar item, or group
/// of menu bar items is being moved.
var isMovingItem: Bool { itemMoveCount > 0 }

/// Creates a manager with the given app state.
init(appState: AppState) {
self.appState = appState
Expand Down Expand Up @@ -208,6 +216,11 @@ extension MenuBarItemManager {
Logger.itemManager.warning("\(item.logString) was not cached")
}

/// Logs a reason for skipping the cache.
private func logSkippingCache(reason: String) {
Logger.itemManager.debug("Skipping menu bar item cache as \(reason)")
}

/// Caches the given menu bar items, without checking whether the control
/// items are in the correct order.
private func uncheckedCacheItems(
Expand Down Expand Up @@ -283,17 +296,24 @@ extension MenuBarItemManager {

/// Caches the current menu bar items if needed, ensuring that the control
/// items are in the correct order.
private func cacheItemsIfNeeded() async {
if let lastItemMoveStartDate {
guard Date.now.timeIntervalSince(lastItemMoveStartDate) > 1 else {
Logger.itemManager.debug("Skipping item cache as an item was recently moved")
return
func cacheItemsIfNeeded() async {
do {
try await waitForItemsToStopMoving(timeout: .seconds(1))
} catch is TaskTimeoutError {
logSkippingCache(reason: "an item is currently being moved")
return
} catch {
if let lastItemMoveStartDate {
guard Date.now.timeIntervalSince(lastItemMoveStartDate) > 1 else {
logSkippingCache(reason: "an item was recently moved")
return
}
}
}

let itemWindowIDs = Bridging.getWindowList(option: [.menuBarItems, .activeSpace])
if cachedItemWindowIDs == itemWindowIDs {
Logger.itemManager.debug("Skipping item cache as item windows have not changed")
logSkippingCache(reason: "item windows have not changed")
return
} else {
cachedItemWindowIDs = itemWindowIDs
Expand All @@ -306,7 +326,7 @@ extension MenuBarItemManager {

guard let hiddenControlItem else {
Logger.itemManager.warning("Missing control item for hidden section")
Logger.itemManager.debug("Clearing item cache")
Logger.itemManager.debug("Clearing menu bar item cache")
itemCache.clear()
return
}
Expand All @@ -325,7 +345,7 @@ extension MenuBarItemManager {
)
} catch {
Logger.itemManager.error("Error enforcing control item order: \(error)")
Logger.itemManager.debug("Clearing item cache")
Logger.itemManager.debug("Clearing menu bar item cache")
itemCache.clear()
}
}
Expand Down Expand Up @@ -861,6 +881,11 @@ extension MenuBarItemManager {
_ item: MenuBarItem,
to destination: MoveDestination
) async throws {
itemMoveCount += 1
defer {
itemMoveCount -= 1
}

guard item.isMovable else {
throw EventError(code: .notMovable, item: item)
}
Expand Down Expand Up @@ -1006,6 +1031,10 @@ extension MenuBarItemManager {
/// - destination: A destination to move the menu bar item.
/// - timeout: Amount of time to wait before throwing an error.
func slowMove(item: MenuBarItem, to destination: MoveDestination, timeout: Duration = .seconds(1)) async throws {
itemMoveCount += 1
defer {
itemMoveCount -= 1
}
try await move(item: item, to: destination)
let waitTask = Task(timeout: timeout) {
while true {
Expand All @@ -1021,6 +1050,19 @@ extension MenuBarItemManager {
throw EventError(code: .otherTimeout, item: item)
}
}

/// Waits asynchronously for all menu bar items to stop moving.
///
/// - Parameter timeout: Amount of time to wait before throwing an error.
func waitForItemsToStopMoving(timeout: Duration) async throws {
let isMovingItemCheckTask = Task(timeout: timeout) {
while await self.isMovingItem {
try Task.checkCancellation()
try await Task.sleep(for: .milliseconds(10))
}
}
try await isMovingItemCheckTask.value
}
}

// MARK: - Click Items
Expand Down Expand Up @@ -1275,6 +1317,11 @@ extension MenuBarItemManager {
/// If an item is currently showing its interface, this method waits for the
/// interface to close before hiding the items.
func rehideTempShownItems() async {
itemMoveCount += 1
defer {
itemMoveCount -= 1
}

guard !tempShownItemContexts.isEmpty else {
return
}
Expand Down
7 changes: 2 additions & 5 deletions Ice/MenuBar/Search/MenuBarSearchPanel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,9 @@ final class MenuBarSearchPanel: NSPanel {
else {
return event
}
if let lastItemMoveStartDate = appState.itemManager.lastItemMoveStartDate {
guard Date.now.timeIntervalSince(lastItemMoveStartDate) > 1 else {
return event
}
if !appState.itemManager.isMovingItem {
close()
}
close()
return event
}
keyDownMonitor = UniversalEventMonitor(mask: .keyDown) { [weak self] event in
Expand Down
1 change: 1 addition & 0 deletions Ice/UI/IceBar/IceBar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ final class IceBarPanel: NSPanel {
appState.navigationState.isIceBarPresented = true
currentSection = section

await appState.itemManager.cacheItemsIfNeeded()
await appState.imageCache.updateCache()

contentView = IceBarHostingView(appState: appState, colorManager: colorManager, section: section) { [weak self] in
Expand Down

0 comments on commit 588031d

Please sign in to comment.