From bcceca83ce966598e00e0319d85ec11d6df9d272 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Tue, 30 Jun 2026 03:44:54 +0800
Subject: [PATCH] Freeze TagLauncher 8.2.8 build 20260630.0128

---
 src/Apptag/AppGridCollectionView.swift |   57 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/src/Apptag/AppGridCollectionView.swift b/src/Apptag/AppGridCollectionView.swift
index 8e95bc8..ba2b864 100644
--- a/src/Apptag/AppGridCollectionView.swift
+++ b/src/Apptag/AppGridCollectionView.swift
@@ -48,6 +48,7 @@
 struct AppGridCollectionView: NSViewRepresentable {
     let groups: [TagGroup]
     let tagColors: [String: Int]
+    let tagCustomColors: [String: TagCustomColor]
     let displayMode: String
     let iconSize: CGFloat
     let showNames: Bool
@@ -89,6 +90,7 @@
         context.coordinator.update(
             groups: groups,
             tagColors: tagColors,
+            tagCustomColors: tagCustomColors,
             displayMode: displayMode,
             iconSize: iconSize,
             showNames: showNames,
@@ -122,6 +124,7 @@
     final class Coordinator: NSObject, NSCollectionViewDataSource, NSCollectionViewDelegate {
         var groups: [TagGroup] = []
         var tagColors: [String: Int] = [:]
+        var tagCustomColors: [String: TagCustomColor] = [:]
         var displayMode = AppDefaults.displayMode
         var iconSize: CGFloat = AppDefaults.iconSize
         var showNames = true
@@ -164,6 +167,7 @@
         func update(
             groups: [TagGroup],
             tagColors: [String: Int],
+            tagCustomColors: [String: TagCustomColor],
             displayMode: String,
             iconSize: CGFloat,
             showNames: Bool,
@@ -193,6 +197,7 @@
         ) {
             self.groups = groups
             self.tagColors = tagColors
+            self.tagCustomColors = tagCustomColors
             self.displayMode = displayMode
             self.iconSize = iconSize
             self.showNames = showNames
@@ -225,6 +230,7 @@
 
             let nextSignature = Self.signature(
                 tagColors: tagColors,
+                tagCustomColors: tagCustomColors,
                 displayMode: displayMode,
                 iconSize: iconSize,
                 showNames: showNames,
@@ -401,6 +407,7 @@
 
         private static func signature(
             tagColors: [String: Int],
+            tagCustomColors: [String: TagCustomColor],
             displayMode: String,
             iconSize: CGFloat,
             showNames: Bool,
@@ -413,6 +420,10 @@
                 .sorted { $0.key < $1.key }
                 .map { "\($0.key)=\($0.value)" }
                 .joined(separator: ",")
+            let customColorPart = tagCustomColors
+                .sorted { $0.key < $1.key }
+                .map { "\($0.key)=\($0.value.signature)" }
+                .joined(separator: ",")
             return [
                 displayMode,
                 "\(Int(iconSize.rounded()))",
@@ -421,8 +432,16 @@
                 showUncommonAppBubbles ? "uncommon" : "allbubbles",
                 "bottom=\(Int(bottomContentPadding.rounded()))",
                 colorPart,
+                customColorPart,
                 "rev=\(contentRevision)"
             ].joined(separator: "|")
+        }
+
+        func tagColor(for groupName: String) -> NSColor {
+            TagColor.nsColor(
+                for: tagColors[groupName] ?? 0,
+                customColor: tagCustomColors[groupName]
+            )
         }
 
         private static func clampedUsageTipIndex(_ index: Int, tips: [AppGridUsageTip]) -> Int {
@@ -1777,7 +1796,7 @@
 
     private struct LayoutItem {
         let index: Int
-        let frame: NSRect
+        var frame: NSRect
     }
 
     private struct LayoutPlan {
@@ -1913,7 +1932,15 @@
         let columnWidth = floor((availableWidth - gap * CGFloat(columnCount - 1)) / CGFloat(columnCount))
         var columnHeights = Array(repeating: outerPadding, count: columnCount)
         var items: [LayoutItem] = []
-        let bottomPinnedGroups = groups.enumerated().filter { $0.element.containerID == AppContainerID.appleBuiltIn }
+        var lastItemIndexForColumn = Array<Int?>(repeating: nil, count: columnCount)
+        let bottomPinnedGroups = groups.enumerated()
+            .filter { bottomPinnedPriority(for: $0.element.containerID) != nil }
+            .sorted {
+                let lhsPriority = bottomPinnedPriority(for: $0.element.containerID) ?? Int.max
+                let rhsPriority = bottomPinnedPriority(for: $1.element.containerID) ?? Int.max
+                if lhsPriority != rhsPriority { return lhsPriority < rhsPriority }
+                return $0.offset < $1.offset
+            }
         let bottomPinnedIndexes = Set(bottomPinnedGroups.map { $0.offset })
 
         for (index, group) in groups.enumerated() {
@@ -1933,10 +1960,21 @@
                     frame: NSRect(x: x, y: y, width: columnWidth, height: height)
                 )
             )
+            lastItemIndexForColumn[columnIndex] = items.count - 1
             columnHeights[columnIndex] = y + height + gap
         }
 
         var contentBottom = columnHeights.max() ?? outerPadding
+        if !bottomPinnedGroups.isEmpty {
+            let alignedBottom = max(outerPadding, contentBottom - gap)
+            for itemIndex in lastItemIndexForColumn.compactMap({ $0 }) {
+                let currentFrame = items[itemIndex].frame
+                let alignedHeight = alignedBottom - currentFrame.minY
+                if alignedHeight > currentFrame.height {
+                    items[itemIndex].frame.size.height = alignedHeight
+                }
+            }
+        }
         for (index, group) in bottomPinnedGroups {
             let y = max(outerPadding, contentBottom)
             let height = AppGridCollectionMetrics.cardHeight(
@@ -1959,6 +1997,17 @@
             items: items,
             contentSize: NSSize(width: boundedContentWidth, height: max(1, contentHeight))
         )
+    }
+
+    private static func bottomPinnedPriority(for containerID: String) -> Int? {
+        switch containerID {
+        case AppContainerID.uncategorized:
+            return 0
+        case AppContainerID.appleBuiltIn:
+            return 1
+        default:
+            return nil
+        }
     }
 
     private struct RowItem {
@@ -2295,7 +2344,7 @@
     override func draw(_ dirtyRect: NSRect) {
         guard let coordinator, let group else { return }
         let displayStyle = coordinator.displayStyle
-        let tagColor = TagColor.nsColor(for: coordinator.tagColors[group.name] ?? 0)
+        let tagColor = coordinator.tagColor(for: group.name)
         let isNavigationHighlighted = coordinator.highlightedGroupName == group.name
         let isColorlessActive = coordinator.isColorlessContainerMode
             && (isHovered || isNavigationHighlighted)
@@ -2541,7 +2590,7 @@
         let shouldShadow = coordinator.displayStyle.usesCardSurface
             && ((coordinator.isColoredContainerMode && (isHovered || isNavigationHighlighted)) || isColorlessActive)
         if coordinator.appGridTheme.usesDarkGlass && coordinator.displayStyle.usesCardSurface {
-            let tagColor = TagColor.nsColor(for: coordinator.tagColors[group?.name ?? ""] ?? 0)
+            let tagColor = coordinator.tagColor(for: group?.name ?? "")
             let active = isHovered || isNavigationHighlighted
             layer?.shadowColor = active
                 ? tagColor.withAlphaComponent(0.82).cgColor

--
Gitblit v1.9.3