From 9abd2554308521c72bd0c3b60f6e7f5e7a129a8b Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Mon, 18 May 2026 16:42:50 +0800
Subject: [PATCH] Fix built-in app grouping and bubble hover settings
---
Apptag/TagGroupView.swift | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 53 insertions(+), 1 deletions(-)
diff --git a/Apptag/TagGroupView.swift b/Apptag/TagGroupView.swift
index c5618ea..2ef0661 100644
--- a/Apptag/TagGroupView.swift
+++ b/Apptag/TagGroupView.swift
@@ -1,4 +1,5 @@
import SwiftUI
+import UniformTypeIdentifiers
// MARK: - Tag Group Section (with centered separator-line header)
@@ -8,10 +9,17 @@
let tagFontSize: CGFloat
let iconSize: CGFloat
var showNames: Bool = true
+ var dragModeActive: Bool = false
+ var onDragModeChange: ((Bool) -> Void)? = nil
+ var onBubbleHover: ((AppInfo, CGRect, Bool) -> Void)? = nil
+ var onEditNote: ((AppInfo, CGRect) -> Void)? = nil
+ @Binding var hoveredAppItemID: String?
+ var onDropApp: ((String, String, Bool) -> Void)? = nil
/// Adaptive columns — auto-fit based on icon size and available width.
private var columns: [GridItem] {
- [GridItem(.adaptive(minimum: iconSize + 28, maximum: iconSize + 64), spacing: 6)]
+ let itemWidth = AppGridItem.stableWidth(iconSize: iconSize)
+ return [GridItem(.adaptive(minimum: itemWidth, maximum: itemWidth + 36), spacing: 6)]
}
// Subtle separator line color — adapts to light/dark mode
@@ -45,10 +53,54 @@
app: app,
iconSize: iconSize,
showName: showNames,
+ sourceTag: group.name,
+ dragModeActive: dragModeActive,
+ onDragModeChange: onDragModeChange,
+ onBubbleHover: onBubbleHover,
+ onEditNote: onEditNote,
+ itemID: "\(group.name)|\(app.path.path)",
+ hoveredAppItemID: $hoveredAppItemID,
onSelect: { onSelectApp(app) }
)
}
}
}
+ .contentShape(Rectangle())
+ .overlay {
+ AppDropTargetView(targetTag: group.name) { path, source, copy in
+ onDropApp?(path, source, copy)
+ }
+ .allowsHitTesting(false)
+ }
+ .onDrop(of: [UTType.plainText], isTargeted: nil) { providers in
+ handleDrop(providers)
+ }
+ }
+
+ private func handleDrop(_ providers: [NSItemProvider]) -> Bool {
+ guard let provider = providers.first(where: { $0.hasItemConformingToTypeIdentifier(UTType.plainText.identifier) }) else {
+ return false
+ }
+ provider.loadItem(forTypeIdentifier: UTType.plainText.identifier, options: nil) { item, _ in
+ let text: String?
+ if let data = item as? Data {
+ text = String(data: data, encoding: .utf8)
+ } else if let string = item as? String {
+ text = string
+ } else if let string = item as? NSString {
+ text = string as String
+ } else {
+ text = nil
+ }
+ guard let text else { return }
+ let parts = text.components(separatedBy: "\n")
+ guard let path = parts.first, !path.isEmpty else { return }
+ let source = parts.dropFirst().first ?? ""
+ let copy = NSEvent.modifierFlags.contains(.option)
+ DispatchQueue.main.async {
+ onDropApp?(path, source, copy)
+ }
+ }
+ return true
}
}
--
Gitblit v1.9.3