From efbfc27e0c813c31b570d72fded40eb91d07f2db Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Thu, 28 May 2026 21:01:19 +0800
Subject: [PATCH] Add AppKit tag navigation reordering
---
Apptag/AppGridCollectionView.swift | 38 +++++++++++++++++++++++++++++++-------
1 files changed, 31 insertions(+), 7 deletions(-)
diff --git a/Apptag/AppGridCollectionView.swift b/Apptag/AppGridCollectionView.swift
index 9fdd8af..013e915 100644
--- a/Apptag/AppGridCollectionView.swift
+++ b/Apptag/AppGridCollectionView.swift
@@ -45,6 +45,7 @@
let onBubbleHover: (AppInfo, CGRect, AppBubbleHoverEvent) -> Void
let onEditNote: (AppInfo, CGRect) -> Void
let onDropApp: (String, String, String, Bool) -> Void
+ let onDropOutsideGroup: (String, String, Bool) -> Void
let onGroupActivate: (String) -> Void
let onScrollActivity: () -> Void
let onDragModeChange: (Bool) -> Void
@@ -76,6 +77,7 @@
onBubbleHover: onBubbleHover,
onEditNote: onEditNote,
onDropApp: onDropApp,
+ onDropOutsideGroup: onDropOutsideGroup,
onGroupActivate: onGroupActivate,
onScrollActivity: onScrollActivity,
onDragModeChange: onDragModeChange
@@ -104,6 +106,7 @@
var onBubbleHover: (AppInfo, CGRect, AppBubbleHoverEvent) -> Void = { _, _, _ in }
var onEditNote: (AppInfo, CGRect) -> Void = { _, _ in }
var onDropApp: (String, String, String, Bool) -> Void = { _, _, _, _ in }
+ var onDropOutsideGroup: (String, String, Bool) -> Void = { _, _, _ in }
var onGroupActivate: (String) -> Void = { _ in }
var onScrollActivity: () -> Void = {}
var onDragModeChange: (Bool) -> Void = { _ in }
@@ -124,6 +127,7 @@
onBubbleHover: @escaping (AppInfo, CGRect, AppBubbleHoverEvent) -> Void,
onEditNote: @escaping (AppInfo, CGRect) -> Void,
onDropApp: @escaping (String, String, String, Bool) -> Void,
+ onDropOutsideGroup: @escaping (String, String, Bool) -> Void,
onGroupActivate: @escaping (String) -> Void,
onScrollActivity: @escaping () -> Void,
onDragModeChange: @escaping (Bool) -> Void
@@ -143,6 +147,7 @@
self.onBubbleHover = onBubbleHover
self.onEditNote = onEditNote
self.onDropApp = onDropApp
+ self.onDropOutsideGroup = onDropOutsideGroup
self.onGroupActivate = onGroupActivate
self.onScrollActivity = onScrollActivity
self.onDragModeChange = onDragModeChange
@@ -153,7 +158,6 @@
iconSize: iconSize,
showNames: showNames,
showUncommonAppBubbles: showUncommonAppBubbles,
- highlightedGroupName: highlightedGroupName,
contentRevision: contentRevision
)
if nextSignature != contentSignature {
@@ -230,7 +234,6 @@
iconSize: CGFloat,
showNames: Bool,
showUncommonAppBubbles: Bool,
- highlightedGroupName: String?,
contentRevision: Int
) -> String {
let colorPart = tagColors
@@ -242,7 +245,6 @@
"\(Int(iconSize.rounded()))",
showNames ? "names" : "nonames",
showUncommonAppBubbles ? "uncommon" : "allbubbles",
- highlightedGroupName ?? "",
colorPart,
"rev=\(contentRevision)"
].joined(separator: "|")
@@ -250,7 +252,8 @@
}
}
-final class AppGridCollectionHostView: NSView {
+final class AppGridCollectionHostView: NSView, AppEmptyDropReceivingView {
+ private let emptyDropTargetID = UUID()
private let scrollView = NSScrollView()
private let collectionView = NSCollectionView()
private let gridLayout = AppGridContainerCollectionLayout()
@@ -277,6 +280,7 @@
NotificationCenter.default.removeObserver(scrollObserver)
}
scrollUnfreezeWorkItem?.cancel()
+ AppDragCoordinator.shared.unregisterEmptyDropTarget(id: emptyDropTargetID)
}
func configure(coordinator: AppGridCollectionView.Coordinator) {
@@ -316,6 +320,24 @@
if lastLayoutSize != bounds.size {
lastLayoutSize = bounds.size
gridLayout.invalidateLayout()
+ }
+ }
+
+ override func viewDidMoveToWindow() {
+ super.viewDidMoveToWindow()
+ if window == nil {
+ AppDragCoordinator.shared.unregisterEmptyDropTarget(id: emptyDropTargetID)
+ } else {
+ AppDragCoordinator.shared.registerEmptyDropTarget(id: emptyDropTargetID, view: self)
+ }
+ }
+
+ func performEmptyDrop(path: String, source: String, screenPoint: NSPoint, copy: Bool) {
+ guard let coordinator,
+ coordinator.displayStyle != .flat
+ else { return }
+ DispatchQueue.main.async {
+ coordinator.onDropOutsideGroup(path, source, copy)
}
}
@@ -926,8 +948,9 @@
guard let coordinator, let group else { return }
let displayStyle = coordinator.displayStyle
let tagColor = TagColor.nsColor(for: coordinator.tagColors[group.name] ?? 0)
+ let isNavigationHighlighted = coordinator.highlightedGroupName == group.name
let isColorlessActive = coordinator.isColorlessContainerMode
- && (isHovered || coordinator.highlightedGroupName == group.name)
+ && (isHovered || isNavigationHighlighted)
if displayStyle.usesCardSurface {
let rect = bounds.insetBy(dx: 0.5, dy: 0.5)
@@ -1008,10 +1031,11 @@
private func updateCardShadow() {
guard let coordinator else { return }
+ let isNavigationHighlighted = coordinator.highlightedGroupName == group?.name
let isColorlessActive = coordinator.isColorlessContainerMode
- && (isHovered || coordinator.highlightedGroupName == group?.name)
+ && (isHovered || isNavigationHighlighted)
let shouldShadow = coordinator.displayStyle.usesCardSurface
- && ((coordinator.isColoredContainerMode && isHovered) || isColorlessActive)
+ && ((coordinator.isColoredContainerMode && (isHovered || isNavigationHighlighted)) || isColorlessActive)
layer?.shadowColor = NSColor.black.cgColor
layer?.shadowOpacity = shouldShadow ? 0.22 : 0
layer?.shadowRadius = shouldShadow ? 8 : 0
--
Gitblit v1.9.3