From 554dce57269e2ae24f5de9c39972cacbc0a350dc Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Tue, 19 May 2026 03:03:21 +0800
Subject: [PATCH] Fix stale app hover bubbles

---
 Apptag/TagGroupView.swift  |    2 +-
 AppStore_Submission.md     |    1 +
 Apptag/AppGridItem.swift   |   20 ++++++++++++--------
 Apptag/ContentView.swift   |   14 ++++++++++----
 AppStore_TODO_7.3.5_744.md |    1 +
 CHANGELOG.md               |    1 +
 6 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/AppStore_Submission.md b/AppStore_Submission.md
index f0f4b6c..80ca34f 100644
--- a/AppStore_Submission.md
+++ b/AppStore_Submission.md
@@ -204,6 +204,7 @@
 - Fixed the Smart Start apply confirmation in Settings so the warning stays above the Settings window with clearer readable controls
 - Fixed right-side tag navigation getting stuck in a dimmed drag visual state after a tag click
 - Fixed an icon grid rendering issue that could make many app icons disappear after drag-state resets
+- Fixed stale hover bubbles so app notes no longer remain pinned to the previous app while hovering another app
 - Version updated to 7.3.5, Build updated to 744
 ```
 
diff --git a/AppStore_TODO_7.3.5_744.md b/AppStore_TODO_7.3.5_744.md
index 3dbb0e2..a3dd269 100644
--- a/AppStore_TODO_7.3.5_744.md
+++ b/AppStore_TODO_7.3.5_744.md
@@ -57,6 +57,7 @@
 - 确认设置按钮和编辑按钮都能从浮层右上角打开。
 - 确认设置页语言切换正常。
 - 确认标签拖拽排序、右侧标签点击切换、App 拖入标签、拖到未分类确认面板正常。
+- 确认快速滑过 App 图标时,用途气泡不会停留在上一个 App 上。
 - 确认数据页导出 / 导入分类与布局正常。
 - 确认 Smart Start 初始分类方案可应用、确认提示不被设置窗口遮挡、恢复和导出。
 - 确认 App Store 沙盒构建中 Launch at Login 控件隐藏。
diff --git a/Apptag/AppGridItem.swift b/Apptag/AppGridItem.swift
index 72dc1fb..746d384 100644
--- a/Apptag/AppGridItem.swift
+++ b/Apptag/AppGridItem.swift
@@ -10,7 +10,7 @@
     var sourceTag: String? = nil
     var dragModeActive: Bool = false
     var onDragModeChange: ((Bool) -> Void)? = nil
-    var onBubbleHover: ((AppInfo, CGRect, Bool) -> Void)? = nil
+    var onBubbleHover: ((AppInfo, CGRect, AppBubbleHoverEvent) -> Void)? = nil
     var onEditNote: ((AppInfo, CGRect) -> Void)? = nil
     var bubbleDisabled: Bool = false
     var itemID: String
@@ -75,16 +75,15 @@
                 interactionFrame = frame
                 if bubbleDisabled || dragModeActive {
                     setHoverState(false)
-                    onBubbleHover?(app, frame, false)
+                    onBubbleHover?(app, frame, .exited)
                     return
                 }
                 if hovering {
                     setHoverState(true)
-                    guard shouldShowAppBubble else { return }
-                    onBubbleHover?(app, frame, hovering)
+                    onBubbleHover?(app, frame, .entered(canShowBubble: shouldShowAppBubble))
                 } else if isHovered {
                     setHoverState(false)
-                    onBubbleHover?(app, frame, hovering)
+                    onBubbleHover?(app, frame, .exited)
                 } else {
                     setHoverState(false)
                 }
@@ -102,19 +101,19 @@
         .onChange(of: dragModeActive) { _, active in
             if active {
                 setHoverState(false)
-                onBubbleHover?(app, interactionFrame, false)
+                onBubbleHover?(app, interactionFrame, .exited)
             }
         }
         .onChange(of: bubbleDisabled) { _, disabled in
             if disabled {
                 setHoverState(false)
-                onBubbleHover?(app, interactionFrame, false)
+                onBubbleHover?(app, interactionFrame, .exited)
             }
         }
         .onDisappear {
             if hoveredAppItemID == itemID {
                 hoveredAppItemID = nil
-                onBubbleHover?(app, interactionFrame, false)
+                onBubbleHover?(app, interactionFrame, .exited)
             }
         }
     }
@@ -138,6 +137,11 @@
     }
 }
 
+enum AppBubbleHoverEvent {
+    case entered(canShowBubble: Bool)
+    case exited
+}
+
 private struct AppGridItemHoverTracker: NSViewRepresentable {
     let onHover: (Bool, CGRect) -> Void
 
diff --git a/Apptag/ContentView.swift b/Apptag/ContentView.swift
index fd8ffa8..b9bb245 100644
--- a/Apptag/ContentView.swift
+++ b/Apptag/ContentView.swift
@@ -1873,15 +1873,21 @@
         notchHeight = activeScreen?.safeAreaInsets.top ?? 0
     }
 
-    private func handleBubbleHover(app: AppInfo, frame: CGRect, hovering: Bool) {
+    private func handleBubbleHover(app: AppInfo, frame: CGRect, event: AppBubbleHoverEvent) {
         guard !appBubbleDisabled else {
             clearAppBubbleState()
             return
         }
         guard editingBubble == nil else { return }
-        if hovering {
-            hoveredBubble = AppBubbleContext(app: app, frame: frame)
-        } else if hoveredBubble?.app.path == app.path {
+        switch event {
+        case .entered(let canShowBubble):
+            if canShowBubble {
+                hoveredBubble = AppBubbleContext(app: app, frame: frame)
+            } else {
+                hoveredBubble = nil
+            }
+        case .exited:
+            guard hoveredBubble?.app.path == app.path else { return }
             hoveredBubble = nil
         }
     }
diff --git a/Apptag/TagGroupView.swift b/Apptag/TagGroupView.swift
index 02075e9..3220b93 100644
--- a/Apptag/TagGroupView.swift
+++ b/Apptag/TagGroupView.swift
@@ -11,7 +11,7 @@
     var showNames: Bool = true
     var dragModeActive: Bool = false
     var onDragModeChange: ((Bool) -> Void)? = nil
-    var onBubbleHover: ((AppInfo, CGRect, Bool) -> Void)? = nil
+    var onBubbleHover: ((AppInfo, CGRect, AppBubbleHoverEvent) -> Void)? = nil
     var onEditNote: ((AppInfo, CGRect) -> Void)? = nil
     var bubbleDisabled: Bool = false
     var dragResetToken: Int = 0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a1293c4..1735e86 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@
 - 修复设置页“应用系统智能化初始分类”确认提示可能跑到设置窗口背后、被遮挡的问题,并优化为更清晰的实底确认框
 - 修复右侧标签列表点击后可能停留在拖拽视觉状态,导致后续标签无法正常点击切换的问题
 - 修复拖拽状态重置后 App 图标网格可能大量不渲染的问题,确保平铺、容器、网格视图切换后图标完整显示
+- 修复快速滑过 App 图标时旧用途气泡可能冻结在上一 App 上的问题,让新 hover 目标主动接管气泡状态
 - 版本号更新为 `7.3.5`,Build 更新为 `744`
 
 ## [7.3.4] — 2026-05-18

--
Gitblit v1.9.3