From 099cd85c325a605e0d6606817174bf99ea88c351 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Tue, 19 May 2026 16:57:08 +0800
Subject: [PATCH] Refresh SmartStart defaults for 7.3.5 build 744

---
 Apptag/AppGridItem.swift |   69 +++++++++++++++++++++++++---------
 1 files changed, 51 insertions(+), 18 deletions(-)

diff --git a/Apptag/AppGridItem.swift b/Apptag/AppGridItem.swift
index 9848d88..746d384 100644
--- a/Apptag/AppGridItem.swift
+++ b/Apptag/AppGridItem.swift
@@ -10,12 +10,14 @@
     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
+    var dragResetToken: Int = 0
+    @Binding var hoveredAppItemID: String?
     let onSelect: () -> Void
 
-    @State private var isHovered = false
-    @State private var wiggle = false
     @State private var interactionFrame: CGRect = .zero
     @AppStorage("showUncommonAppBubbles") private var showUncommonAppBubbles = AppDefaults.showUncommonAppBubbles
 
@@ -35,6 +37,7 @@
     private var iconSlotSize: CGFloat { iconSize * Self.hoverScale }
     private var labelWidth: CGFloat { iconSize + 20 }
     private var labelHeight: CGFloat { Self.labelHeight }
+    private var isHovered: Bool { hoveredAppItemID == itemID }
 
     var body: some View {
         VStack(spacing: 6) {
@@ -62,7 +65,7 @@
                 .lineLimit(1)
                 .truncationMode(.tail)
                 .frame(width: labelWidth, height: labelHeight)
-                .opacity(showName ? 1 : (isHovered ? 0.85 : 0))
+                .opacity(showName ? 1 : (shouldShowHoverName ? 0.85 : 0))
         }
         .padding(.vertical, 8)
         .padding(.horizontal, 4)
@@ -70,12 +73,19 @@
         .background(
             AppGridItemHoverTracker { hovering, frame in
                 interactionFrame = frame
-                setHoverState(hovering)
+                if bubbleDisabled || dragModeActive {
+                    setHoverState(false)
+                    onBubbleHover?(app, frame, .exited)
+                    return
+                }
                 if hovering {
-                    guard shouldShowAppBubble else { return }
-                    onBubbleHover?(app, frame, hovering)
+                    setHoverState(true)
+                    onBubbleHover?(app, frame, .entered(canShowBubble: shouldShowAppBubble))
+                } else if isHovered {
+                    setHoverState(false)
+                    onBubbleHover?(app, frame, .exited)
                 } else {
-                    onBubbleHover?(app, frame, hovering)
+                    setHoverState(false)
                 }
             }
         )
@@ -85,15 +95,26 @@
                 onEditNote?(app, interactionFrame)
             }
         }
-        .rotationEffect(.degrees(dragModeActive ? (wiggle ? 2.0 : -2.0) : 0))
-        .animation(
-            dragModeActive
-                ? .easeInOut(duration: 0.12).repeatForever(autoreverses: true)
-                : .default,
-            value: wiggle
-        )
+        .opacity(dragModeActive ? 0.92 : 1)
+        .animation(.easeOut(duration: 0.08), value: dragModeActive)
+        .id("\(itemID)|reset-\(dragResetToken)")
         .onChange(of: dragModeActive) { _, active in
-            wiggle = active
+            if active {
+                setHoverState(false)
+                onBubbleHover?(app, interactionFrame, .exited)
+            }
+        }
+        .onChange(of: bubbleDisabled) { _, disabled in
+            if disabled {
+                setHoverState(false)
+                onBubbleHover?(app, interactionFrame, .exited)
+            }
+        }
+        .onDisappear {
+            if hoveredAppItemID == itemID {
+                hoveredAppItemID = nil
+                onBubbleHover?(app, interactionFrame, .exited)
+            }
         }
     }
 
@@ -101,14 +122,26 @@
         !showUncommonAppBubbles || app.isUncommon
     }
 
+    private var shouldShowHoverName: Bool {
+        !showName && !shouldShowAppBubble && isHovered
+    }
+
     private func setHoverState(_ hovering: Bool) {
-        guard isHovered != hovering else { return }
         withAnimation(hovering ? Self.hoverInAnimation : Self.hoverOutAnimation) {
-            isHovered = hovering
+            if hovering {
+                hoveredAppItemID = itemID
+            } else if hoveredAppItemID == itemID {
+                hoveredAppItemID = nil
+            }
         }
     }
 }
 
+enum AppBubbleHoverEvent {
+    case entered(canShowBubble: Bool)
+    case exited
+}
+
 private struct AppGridItemHoverTracker: NSViewRepresentable {
     let onHover: (Bool, CGRect) -> Void
 

--
Gitblit v1.9.3