Skip to content

Add notification delivery model#2

Closed
kibermaks wants to merge 315 commits into
mainfrom
notification-model
Closed

Add notification delivery model#2
kibermaks wants to merge 315 commits into
mainfrom
notification-model

Conversation

@kibermaks
Copy link
Copy Markdown
Owner

Summary

  • Add an isolated notification delivery model with event-specific local delivery settings.
  • Keep existing local notification callers working while adding injectable authorization, posting, and sound delivery seams.
  • Cover disabled settings, global gating, authorization denial, request posting, and custom sound behavior.

Stack

  1. notification-model (this PR)
  2. notification-shortcuts (local branch, stacked on this)
  3. notification-webhooks (local branch, stacked on notification-shortcuts)
  4. quota-notifications-migration (local branch, stacked on notification-webhooks)

Tests

  • swift test --filter AppNotificationsTests
  • pnpm check

steipete and others added 30 commits May 6, 2026 01:42
* fix: restore menu bar icon on macOS 26.4 (steipete#805)

Two changes addressing the invisible status item icon on macOS 26.4:

1. Replace compositingGroup + blendMode(.destinationOut) in UsageProgressBar
   with a single Canvas that draws track, fill, and pace-tip punch-out entirely
   inside Core Graphics. SwiftUI compositing modifiers (.compositingGroup,
   .blendMode as a view modifier) trigger Metal/RenderBox shader compilation;
   on macOS 26.4 that compilation can fail with a precondition error, making
   the NSStatusItem window invisible. Moving the blend to the GraphicsContext
   API inside the Canvas avoids the Metal path entirely.

2. Gate migrateLegacySecrets and migrateLegacyAccounts behind existing == nil
   in CodexBarConfigMigrator.loadOrMigrate(). These ran unconditionally on
   every launch, performing ~28 SecItemCopyMatching calls on the main thread.
   After the first launch the config is the source of truth and legacy stores
   are cleared, so subsequent calls all hit errSecItemNotFound — but macOS 26.4
   Performance Diagnostics still emits a fault per call, adding startup jank.
   applyLegacyCookieSources (cheap UserDefaults reads) remains unconditional.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: use completion flag for legacy migration instead of existing == nil

Replaces the `existing == nil` gate added in the previous commit with a
UserDefaults boolean flag (`codexbar.legacySecretsMigrationCompleted`).

The `existing == nil` gate had a blind spot: if the app crashed after
configStore.save() but before clearLegacyStores(), the config would exist
on the next launch (`existing != nil`) so migration would be skipped and
orphaned Keychain items would never be cleaned up.

The flag approach is safe for all cases:
- Fresh install: flag absent → migration runs → items found → clear → set flag
- Normal re-launch: flag present → skip (0 Keychain calls)
- Crash-interrupted first migration: flag absent → migration re-runs → items
  still present → clear → set flag (data already in config via setIfEmpty)
- No legacy data ever existed: flag absent → migration runs → finds nothing →
  set flag → never scans again

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: add changelog entry for steipete#805

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: only mark migration complete when clearLegacyStores succeeds

clearLegacyStores catches keychain write failures internally and returns
normally, so the completion flag was being set even on partial cleanup.
A transient keychain error would permanently suppress retry on next launch.

- Make clearLegacyStores return Bool (true = all deletes succeeded)
- Gate legacyMigrationCompletedKey on that return value
- Remove comment block above the key constant (SwiftFormat docComments lint)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: cover legacy migration completion flag

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
…te#854)

OpenRouter has a brand logo, but the logo suppresses usage information
that is more useful in the menu bar. This change makes OpenRouter always
render its usage meter (the same capsule bar all other providers use)
regardless of whether a brand image is available.

- Removes the logo-fallback branch from applyIcon(for:phase:) for
  OpenRouter; the meter path is now unconditional
- Adds pixel-level tests confirming the meter renders (not the logo) both
  when key data is available with no configured limit and when key data
  has not been fetched yet

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…ls (steipete#868)

Five RelativeDateTimeFormatter sites lacked an explicit locale, so on
non-English systems they emitted localized output (e.g. "1分钟前") next
to hardcoded English labels like "Updated", producing strings such as
"Updated 1分钟前". The same field flipped to "Updated just now" inside
the 60-second window, visibly switching languages while the menu was
open.

Pin every RelativeDateTimeFormatter to Locale(identifier: "en_US"),
matching the en_US / en_US_POSIX pattern already used by every other
formatter in UsageFormatter.swift.

Tighten the existing relative-updated test, which previously accepted
Korean output as a workaround for this bug, to assert English output.

Closes steipete#866
Fixes steipete#867.

Co-authored-by: Changyu Dai <kelsoprotein@gmail.com>
Adds Crof as an API-key provider with request quota and credit balance tracking.

Validated locally with targeted Crof tests and pnpm check.
Shows balance-style menu bar text for OpenRouter, Mistral, and Kimi K2 where quota percentage is not the useful default.

Validated locally with targeted balance/provider tests and pnpm check.
steipete and others added 27 commits May 17, 2026 00:11
Co-authored-by: Sergey Lavrentev <slavrentev@gradoservice.ru>
Adds a README pointer to the codexbar-waybar companion project for Linux desktop integration.\n\nVerified target repo exists and is active.
Add Kiro overage credit/cost parsing and exhausted-plan menu bar display modes.\n\nThanks @raflyazf for the contribution.\n\nVerification:\n- swift test --filter KiroStatusProbeTests --filter StatusItemBalanceDisplayTests --filter MenuCardModelTests\n- swift test --filter StatusItemBalanceDisplayTests\n- make check\n- codex-review --mode branch --base origin/main
Include the triggering account in quota-warning notification copy when personal info is visible.

Thanks @raflyazf for the contribution.

Verification:
- swift test --filter QuotaWarningNotificationLogicTests --filter UsageStoreSessionQuotaTransitionTests
- swift test
- make check
- codex-review --mode branch --base origin/main
Route app-owned provider HTTP calls through a shared transport seam and replace process-global URLProtocol tests with injected transport coverage.

Thanks @serezha93 for the contribution.

Verification:
- swift build
- swift test --filter CopilotUsageFetcherTests
- swift test --filter GoogleWorkspaceStatusNetworkTests
- swift test --filter ProviderHTTPClientTests
- make check
- swift test
- codex-review --mode branch --base origin/main

Co-authored-by: Sergey Fomintsev <sfomintsev@gmail.com>
Co-authored-by: Christopher Pellicci <chris@czjzpz.xyz>
Co-authored-by: Michael Smolkin <michael@smolkin.org>
Co-authored-by: Yubo Wang <wang3399@wisc.edu>
@kibermaks kibermaks force-pushed the notification-model branch from e169229 to 0172cdc Compare May 17, 2026 13:02
@kibermaks
Copy link
Copy Markdown
Owner Author

Closing this because it was opened against the fork by mistake. Correct draft PR is steipete#1010.

@kibermaks kibermaks closed this May 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.