From 2f5a78879bde7e817f1d3a71864685f0269ccb07 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Mon, 18 May 2026 17:17:41 +0800
Subject: [PATCH] Hide app bubbles during drag decisions

---
 Apptag/TagGroupView.swift |    2 ++
 Apptag/AppGridItem.swift  |   16 ++++++++++++++++
 Apptag/ContentView.swift  |   26 ++++++++++++++++++++++++++
 Apptag/Info.plist         |    4 ++--
 CHANGELOG.md              |    6 ++++++
 5 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/Apptag/AppGridItem.swift b/Apptag/AppGridItem.swift
index 5cda31b..22c204c 100644
--- a/Apptag/AppGridItem.swift
+++ b/Apptag/AppGridItem.swift
@@ -12,6 +12,7 @@
     var onDragModeChange: ((Bool) -> Void)? = nil
     var onBubbleHover: ((AppInfo, CGRect, Bool) -> Void)? = nil
     var onEditNote: ((AppInfo, CGRect) -> Void)? = nil
+    var bubbleDisabled: Bool = false
     var itemID: String
     @Binding var hoveredAppItemID: String?
     let onSelect: () -> Void
@@ -72,6 +73,11 @@
         .background(
             AppGridItemHoverTracker { hovering, frame in
                 interactionFrame = frame
+                if bubbleDisabled || dragModeActive {
+                    setHoverState(false)
+                    onBubbleHover?(app, frame, false)
+                    return
+                }
                 if hovering {
                     setHoverState(true)
                     guard shouldShowAppBubble else { return }
@@ -99,6 +105,16 @@
         )
         .onChange(of: dragModeActive) { _, active in
             wiggle = active
+            if active {
+                setHoverState(false)
+                onBubbleHover?(app, interactionFrame, false)
+            }
+        }
+        .onChange(of: bubbleDisabled) { _, disabled in
+            if disabled {
+                setHoverState(false)
+                onBubbleHover?(app, interactionFrame, false)
+            }
         }
         .onDisappear {
             if hoveredAppItemID == itemID {
diff --git a/Apptag/ContentView.swift b/Apptag/ContentView.swift
index 87ee89a..8eae143 100644
--- a/Apptag/ContentView.swift
+++ b/Apptag/ContentView.swift
@@ -396,6 +396,9 @@
     private let editSidebarHorizontalInset: CGFloat = 12
     private let floatingControlsTrailingInset: CGFloat = 20
     private let floatingControlsReservedWidth: CGFloat = 120
+    private var appBubbleDisabled: Bool {
+        appDragModeActive || pendingUncategorizedDrop != nil
+    }
     private let rightSidebarFloatingClearance: CGFloat = 44
 
     private var isSideLayout: Bool {
@@ -834,6 +837,7 @@
                             onDragModeChange: { setAppDragMode($0) },
                             onBubbleHover: handleBubbleHover,
                             onEditNote: beginEditingBubbleNote,
+                            bubbleDisabled: appBubbleDisabled,
                             hoveredAppItemID: $hoveredAppItemID,
                             onDropApp: { path, source, copy in
                                 dropApp(path: path, sourceTag: source, targetTag: group.name, copy: copy)
@@ -937,6 +941,7 @@
                         onDragModeChange: { setAppDragMode($0) },
                         onBubbleHover: handleBubbleHover,
                         onEditNote: beginEditingBubbleNote,
+                        bubbleDisabled: appBubbleDisabled,
                         itemID: "\(group.name)|\(app.path.path)",
                         hoveredAppItemID: $hoveredAppItemID,
                         onSelect: { openApp(app) }
@@ -1175,6 +1180,7 @@
                                 onDragModeChange: { setAppDragMode($0) },
                                 onBubbleHover: handleBubbleHover,
                                 onEditNote: beginEditingBubbleNote,
+                                bubbleDisabled: appBubbleDisabled,
                                 itemID: "\(group.name)|\(app.path.path)",
                                 hoveredAppItemID: $hoveredAppItemID,
                                 onSelect: { openApp(app) }
@@ -1848,6 +1854,10 @@
     // MARK: - Actions
 
     private func handleBubbleHover(app: AppInfo, frame: CGRect, hovering: Bool) {
+        guard !appBubbleDisabled else {
+            clearAppBubbleState()
+            return
+        }
         guard editingBubble == nil else { return }
         if hovering {
             hoveredBubble = AppBubbleContext(app: app, frame: frame)
@@ -1857,6 +1867,10 @@
     }
 
     private func beginEditingBubbleNote(app: AppInfo, frame: CGRect) {
+        guard !appBubbleDisabled else {
+            clearAppBubbleState()
+            return
+        }
         bubbleDraftNote = currentNote(for: app)
         hoveredBubble = nil
         editingBubble = AppBubbleContext(app: app, frame: frame)
@@ -1879,6 +1893,16 @@
     }
 
     private func dismissAppBubble() {
+        hoveredBubble = nil
+        if editingBubble != nil {
+            notifyAppNoteEditing(active: false)
+        }
+        editingBubble = nil
+        bubbleNoteFocused = false
+    }
+
+    private func clearAppBubbleState() {
+        hoveredAppItemID = nil
         hoveredBubble = nil
         if editingBubble != nil {
             notifyAppNoteEditing(active: false)
@@ -2089,6 +2113,7 @@
         let assignedTags = assignedRegularDisplayTags(for: app)
         guard !assignedTags.isEmpty else { return }
 
+        clearAppBubbleState()
         withAnimation(.spring(response: 0.24, dampingFraction: 0.84)) {
             pendingUncategorizedDrop = PendingUncategorizedDrop(app: app, assignedTags: assignedTags)
         }
@@ -2183,6 +2208,7 @@
     private func setAppDragMode(_ active: Bool) {
         if active {
             endTagNavReorder()
+            clearAppBubbleState()
         }
         appDragModeActive = active
         if active {
diff --git a/Apptag/Info.plist b/Apptag/Info.plist
index 8ec0063..0f31def 100644
--- a/Apptag/Info.plist
+++ b/Apptag/Info.plist
@@ -19,9 +19,9 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>7.3.2</string>
+	<string>7.3.3</string>
 	<key>CFBundleVersion</key>
-	<string>741</string>
+	<string>742</string>
 	<key>LSMinimumSystemVersion</key>
 	<string>15.0</string>
 	<key>NSHighResolutionCapable</key>
diff --git a/Apptag/TagGroupView.swift b/Apptag/TagGroupView.swift
index 2ef0661..bea1637 100644
--- a/Apptag/TagGroupView.swift
+++ b/Apptag/TagGroupView.swift
@@ -13,6 +13,7 @@
     var onDragModeChange: ((Bool) -> Void)? = nil
     var onBubbleHover: ((AppInfo, CGRect, Bool) -> Void)? = nil
     var onEditNote: ((AppInfo, CGRect) -> Void)? = nil
+    var bubbleDisabled: Bool = false
     @Binding var hoveredAppItemID: String?
     var onDropApp: ((String, String, Bool) -> Void)? = nil
 
@@ -58,6 +59,7 @@
                         onDragModeChange: onDragModeChange,
                         onBubbleHover: onBubbleHover,
                         onEditNote: onEditNote,
+                        bubbleDisabled: bubbleDisabled,
                         itemID: "\(group.name)|\(app.path.path)",
                         hoveredAppItemID: $hoveredAppItemID,
                         onSelect: { onSelectApp(app) }
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 71cf978..7f47fdd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Apptag Changelog
 
+## [7.3.3] — 2026-05-18
+
+- 拖拽 App 时会立即关闭并禁用 App 用途气泡,避免拖向目标容器时旧气泡继续遮挡视线
+- 「归类为未分类」确认浮层出现前会清理 App 气泡,确认决策期间不再显示背景 App 的说明气泡
+- 版本号更新为 `7.3.3`,Build 更新为 `742`
+
 ## [7.3.2] — 2026-05-18
 
 - 优化设置页「标签」界面布局,将标签列表内容区整体居中,避免左侧拥挤、右侧大面积留白

--
Gitblit v1.9.3