mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-28 05:16:23 -06:00
64f30c70d7
* test(macos): add debug menu fixtures and submenu-open capture hooks
* feat(macos): render automation summaries as hosted cards
The Automations/Usage/Devices rows were native items cramming count and
next-run into a fitted title that middle-ellipsized into garbage
('5 …s'). They are now hosted summary cards - title left, compact detail
right, own chevron - which escape the native title budget and pick up
the selection highlight. Automation submenu jobs become hosted rows
(name left, next run right, full name on the accessibility label) that
open the Automations page on click instead of dead disabled text.
* style(macos): swiftformat pass on menu fixture hooks
* test(macos): capture hooks accept CLI arguments
launchctl setenv races open(1), which made screenshot launches flaky;
--debug-open-menu / --debug-menu-fixtures / --debug-probe-rightclick now
work as arguments. The arrow-key submenu navigation never fired inside
the tracking loop and is removed.
92 lines
3.0 KiB
Swift
92 lines
3.0 KiB
Swift
import Foundation
|
|
import SwiftUI
|
|
|
|
/// Root-menu summary row (Automations, Usage, Devices): title left, compact
|
|
/// detail right, own chevron. Hosted cards escape the native title budget,
|
|
/// so long details truncate instead of stretching or ellipsizing the title.
|
|
@MainActor
|
|
struct StatusSummaryCard: View {
|
|
let symbolName: String
|
|
let title: String
|
|
let detail: String?
|
|
@Environment(\.menuItemHighlighted) private var isHighlighted
|
|
|
|
private var palette: MenuItemHighlightColors.Palette {
|
|
MenuItemHighlightColors.palette(self.isHighlighted)
|
|
}
|
|
|
|
var body: some View {
|
|
HStack(spacing: 10) {
|
|
Image(systemName: self.symbolName)
|
|
.foregroundStyle(self.palette.secondary)
|
|
.frame(width: 16, height: 16)
|
|
|
|
Text(self.title)
|
|
.font(.callout)
|
|
.foregroundStyle(self.palette.primary)
|
|
.lineLimit(1)
|
|
.layoutPriority(1)
|
|
|
|
Spacer(minLength: 8)
|
|
|
|
if let detail = self.detail {
|
|
Text(detail)
|
|
.font(.caption)
|
|
.foregroundStyle(self.palette.secondary)
|
|
.lineLimit(1)
|
|
.truncationMode(.tail)
|
|
}
|
|
|
|
Image(systemName: "chevron.right")
|
|
.font(.caption.weight(.semibold))
|
|
.foregroundStyle(self.palette.secondary)
|
|
}
|
|
.padding(.horizontal, 14)
|
|
.padding(.vertical, 8)
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
.accessibilityElement(children: .combine)
|
|
.accessibilityLabel(self.detail.map { "\(self.title), \($0)" } ?? self.title)
|
|
}
|
|
}
|
|
|
|
/// Automations submenu row: job name left, next run right. The full name
|
|
/// stays on the accessibility label; middle truncation keeps the suffix.
|
|
@MainActor
|
|
struct StatusJobRow: View {
|
|
let name: String
|
|
let nextRun: String?
|
|
@Environment(\.menuItemHighlighted) private var isHighlighted
|
|
|
|
private var palette: MenuItemHighlightColors.Palette {
|
|
MenuItemHighlightColors.palette(self.isHighlighted)
|
|
}
|
|
|
|
var body: some View {
|
|
HStack(spacing: 10) {
|
|
Image(systemName: "clock")
|
|
.foregroundStyle(self.palette.secondary)
|
|
.frame(width: 16, height: 16)
|
|
|
|
Text(self.name)
|
|
.font(.callout)
|
|
.foregroundStyle(self.palette.primary)
|
|
.lineLimit(1)
|
|
.truncationMode(.middle)
|
|
|
|
Spacer(minLength: 8)
|
|
|
|
if let nextRun = self.nextRun {
|
|
Text(nextRun)
|
|
.font(.caption.monospacedDigit())
|
|
.foregroundStyle(self.palette.secondary)
|
|
.lineLimit(1)
|
|
}
|
|
}
|
|
.padding(.horizontal, 14)
|
|
.padding(.vertical, 7)
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
.accessibilityElement(children: .combine)
|
|
.accessibilityLabel(self.nextRun.map { "\(self.name), \($0)" } ?? self.name)
|
|
}
|
|
}
|