Ariver
2026-05-19 57abfdc2ba880be1fae4a1a184531e3228d62dae
Apptag/AppGridItem.swift
@@ -12,11 +12,12 @@
    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
    var dragResetToken: Int = 0
    @Binding var hoveredAppItemID: String?
    let onSelect: () -> Void
    @State private var wiggle = false
    @State private var interactionFrame: CGRect = .zero
    @AppStorage("showUncommonAppBubbles") private var showUncommonAppBubbles = AppDefaults.showUncommonAppBubbles
@@ -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 }
@@ -90,15 +96,20 @@
                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(dragResetToken)
        .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 {