From 70a1cc2e63d2c49a135bd89cec3ffb1d427d90ee Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Tue, 30 Jun 2026 16:21:47 +0800
Subject: [PATCH] Freeze prep TagLauncher 8.2.9 Pro status UI
---
src/Apptag/AppGridCollectionView.swift | 79 +++++++++++++++++++++++++++++++++++++--
1 files changed, 74 insertions(+), 5 deletions(-)
diff --git a/src/Apptag/AppGridCollectionView.swift b/src/Apptag/AppGridCollectionView.swift
index d124a61..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,8 +1932,20 @@
let columnWidth = floor((availableWidth - gap * CGFloat(columnCount - 1)) / CGFloat(columnCount))
var columnHeights = Array(repeating: outerPadding, count: columnCount)
var items: [LayoutItem] = []
+ 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() {
+ if bottomPinnedIndexes.contains(index) { continue }
+
let columnIndex = columnHeights.indices.min { columnHeights[$0] < columnHeights[$1] } ?? 0
let x = outerPadding + CGFloat(columnIndex) * (columnWidth + gap)
let y = columnHeights[columnIndex]
@@ -1929,16 +1960,54 @@
frame: NSRect(x: x, y: y, width: columnWidth, height: height)
)
)
+ lastItemIndexForColumn[columnIndex] = items.count - 1
columnHeights[columnIndex] = y + height + gap
}
- let tallest = columnHeights.max() ?? outerPadding
- let contentHeight = (groups.isEmpty ? outerPadding * 2 : tallest - gap + outerPadding)
+ 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(
+ appCount: group.apps.count,
+ width: availableWidth,
+ iconSize: iconSize
+ )
+ items.append(
+ LayoutItem(
+ index: index,
+ frame: NSRect(x: outerPadding, y: y, width: availableWidth, height: height)
+ )
+ )
+ contentBottom = y + height + gap
+ }
+
+ let contentHeight = (items.isEmpty ? outerPadding * 2 : contentBottom - gap + outerPadding)
+ max(0, bottomContentPadding)
return LayoutPlan(
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 {
@@ -2275,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)
@@ -2521,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