diff options
| author | Christian Cleberg <[email protected]> | 2026-07-17 17:12:46 -0500 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2026-07-17 17:12:46 -0500 |
| commit | 277e2a7209047ed1514ea7b34034c510a4e51a4f (patch) | |
| tree | 3a0f5ae9c088a14f09831e23f8cb8608210d78cd /octosentry/SecurityEventRow.swift | |
| parent | 8e6d29f1806cc569b48d913564c7d80a1c2f2355 (diff) | |
| download | octosentry-277e2a7209047ed1514ea7b34034c510a4e51a4f.tar.gz octosentry-277e2a7209047ed1514ea7b34034c510a4e51a4f.tar.bz2 octosentry-277e2a7209047ed1514ea7b34034c510a4e51a4f.zip | |
Add mark-seen action, critical-alert badge, and a dedicated window0.5.0
Closes #8-#10 (milestone 0.5.0).
- Mark-seen: each row gets a checkmark button (separate from the
click-to-open button) that persists the event into seenEventIDs and
removes it from the active stream immediately, no API write.
- Menu bar icon switches to a filled exclamation-shield with a red badge
showing the count of unseen critical alerts when any exist.
- Added a dedicated Window (singleton scene, not WindowGroup — avoids
spawning duplicates) opened via a header button, sharing the exact
same store/authStore instances as the popover. The button hides itself
when already viewing the standalone window.
Diffstat (limited to 'octosentry/SecurityEventRow.swift')
| -rw-r--r-- | octosentry/SecurityEventRow.swift | 99 |
1 files changed, 57 insertions, 42 deletions
diff --git a/octosentry/SecurityEventRow.swift b/octosentry/SecurityEventRow.swift index 9a73037..85dbfa2 100644 --- a/octosentry/SecurityEventRow.swift +++ b/octosentry/SecurityEventRow.swift @@ -8,6 +8,7 @@ import SwiftUI struct SecurityEventRow: View { let event: SecurityEvent + var onMarkSeen: () -> Void private static let relativeFormatter: RelativeDateTimeFormatter = { let formatter = RelativeDateTimeFormatter() @@ -16,58 +17,72 @@ struct SecurityEventRow: View { }() var body: some View { - Button { - NSWorkspace.shared.open(event.detailURL) - } label: { - VStack(alignment: .leading, spacing: 3) { - HStack(spacing: 6) { - Text(event.nativeSeverityLabel.uppercased()) - .font(.caption2.weight(.bold)) - .foregroundStyle(event.severity.color) - .padding(.horizontal, 6) - .padding(.vertical, 2) - .background(event.severity.color.opacity(0.18), in: Capsule()) + HStack(alignment: .top, spacing: 0) { + Button { + NSWorkspace.shared.open(event.detailURL) + } label: { + VStack(alignment: .leading, spacing: 3) { + HStack(spacing: 6) { + Text(event.nativeSeverityLabel.uppercased()) + .font(.caption2.weight(.bold)) + .foregroundStyle(event.severity.color) + .padding(.horizontal, 6) + .padding(.vertical, 2) + .background(event.severity.color.opacity(0.18), in: Capsule()) - Text(event.source.displayName) - .font(.caption2.weight(.semibold)) - .padding(.horizontal, 6) - .padding(.vertical, 2) - .background(.secondary.opacity(0.15), in: Capsule()) + Text(event.source.displayName) + .font(.caption2.weight(.semibold)) + .padding(.horizontal, 6) + .padding(.vertical, 2) + .background(.secondary.opacity(0.15), in: Capsule()) - Text(event.repoFullName) - .font(.caption) - .foregroundStyle(.secondary) + Text(event.repoFullName) + .font(.caption) + .foregroundStyle(.secondary) - Spacer() + Spacer() - Text(Self.relativeFormatter.localizedString(for: event.createdAt, relativeTo: .now)) - .font(.caption2) - .foregroundStyle(.secondary) + Text(Self.relativeFormatter.localizedString(for: event.createdAt, relativeTo: .now)) + .font(.caption2) + .foregroundStyle(.secondary) + } + + Text(event.summary) + .font(.callout) + .lineLimit(1) + .foregroundStyle(.primary) } + .padding(10) + .contentShape(Rectangle()) + } + .buttonStyle(.plain) - Text(event.summary) - .font(.callout) - .lineLimit(1) - .foregroundStyle(.primary) + Button(action: onMarkSeen) { + Image(systemName: "checkmark.circle") } - .padding(10) - .contentShape(Rectangle()) + .buttonStyle(.plain) + .foregroundStyle(.secondary) + .help("Mark as seen") + .padding(.top, 12) + .padding(.trailing, 10) } - .buttonStyle(.plain) } } #Preview { - SecurityEventRow(event: SecurityEvent( - id: "preview-1", - source: .dependabot, - repoFullName: "zerolabsco/octosentry", - severity: .critical, - nativeSeverityLabel: "Critical", - summary: "Denial of service in some-package", - detailURL: URL(string: "https://github.com")!, - createdAt: .now.addingTimeInterval(-3600 * 26), - updatedAt: .now, - seenLocally: false - )) + SecurityEventRow( + event: SecurityEvent( + id: "preview-1", + source: .dependabot, + repoFullName: "zerolabsco/octosentry", + severity: .critical, + nativeSeverityLabel: "Critical", + summary: "Denial of service in some-package", + detailURL: URL(string: "https://github.com")!, + createdAt: .now.addingTimeInterval(-3600 * 26), + updatedAt: .now, + seenLocally: false + ), + onMarkSeen: {} + ) } |
