Compare commits

..
15 Commits
Author SHA1 Message Date
superdooper86 b5c3cc6379 Rerelease as v1.0.10 (was incorrectly versioned as v1.1.0) 2026-05-07 18:11:45 +02:00
github-actions[bot] c8adaf1baf Release v1.1.0 2026-05-07 16:02:51 +00:00
superdooper86 3e99e1417e Release v1.1.0 — always open to main window
Post popoverWillOpen notification on show; ContentView resets showSettings
on receive so reopening always lands on the main window, not Settings.
2026-05-07 18:02:04 +02:00
github-actions[bot] e41d3d0c0f Release v1.0.9 2026-05-07 15:56:24 +00:00
superdooper86 1078951c43 Release v1.0.9 — fix update notification popup showing raw markdown
Sync UpdateNotificationWindow.swift: showUpdate now always uses the
static subtitle "Tap to view release notes & update now!" instead of
passing the full release notes text to the popup.
2026-05-07 17:55:05 +02:00
github-actions[bot] ed6a5e1b51 Release v1.0.8 2026-05-07 15:49:47 +00:00
superdooper86 8701fb1326 Release v1.0.8 2026-05-07 17:48:32 +02:00
github-actions[bot] 247b5fc202 Release v1.0.7 2026-05-07 15:45:02 +00:00
superdooper86 255de797f8 Release v1.0.7 — fix markdown rendering in release notes
Add ReleaseNotesText view that pre-processes headers (##, ###) to bold
and converts - bullets to • before passing to AttributedString, which
only supports inline markdown. Replaces both Text(.init()) call sites.
2026-05-07 17:43:46 +02:00
github-actions[bot] 0046c53283 Release v1.0.6 2026-05-07 15:39:24 +00:00
superdooper86 8d222d63f0 Release v1.0.6 — improve update notification subtitle
Change notification prompt to "Tap to view release notes & update now!"
2026-05-07 17:38:34 +02:00
github-actions[bot] 5720370649 Release v1.0.5 2026-05-07 15:31:00 +00:00
superdooper86 0843730ae1 Release v1.0.5 — fix markdown rendering in release notes
Use Text(.init()) to parse markdown in update sheet and banner.
Notification popup now shows a fixed subtitle instead of raw notes.
2026-05-07 17:29:29 +02:00
superdooper86 9c030fcdd5 Fix version.json containing invalid JSON (literal newlines in notes)
Use jq to build version.json so multiline release notes are properly
escaped as \n sequences. Also fix current version.json for v1.0.4.
2026-05-07 17:22:57 +02:00
github-actions[bot] dd68ff39d6 Release v1.0.4 2026-05-07 15:16:04 +00:00
9 changed files with 54 additions and 29 deletions
+6 -7
View File
@@ -50,13 +50,12 @@ jobs:
- name: Update version.json - name: Update version.json
run: | run: |
cat > version.json << JSON notes=$(cat RELEASE_NOTES.md 2>/dev/null || echo "Release ${{ steps.version.outputs.version }}")
{ jq -n \
"version": "${{ steps.version.outputs.version }}", --arg version "${{ steps.version.outputs.version }}" \
"url": "https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/ClaudeChecker.zip", --arg url "https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/ClaudeChecker.zip" \
"notes": "$(cat RELEASE_NOTES.md 2>/dev/null || echo 'Release ${{ steps.version.outputs.version }}')" --arg notes "$notes" \
} '{version: $version, url: $url, notes: $notes}' > version.json
JSON
- name: Update Homebrew cask - name: Update Homebrew cask
run: | run: |
+2
View File
@@ -199,6 +199,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
@objc func showPopover() { @objc func showPopover() {
guard let button = statusItem?.button, let popover else { return } guard let button = statusItem?.button, let popover else { return }
if !popover.isShown { if !popover.isShown {
NotificationCenter.default.post(name: .popoverWillOpen, object: nil)
popover.show(relativeTo: button.bounds, of: button, preferredEdge: .minY) popover.show(relativeTo: button.bounds, of: button, preferredEdge: .minY)
NSApp.activate(ignoringOtherApps: true) NSApp.activate(ignoringOtherApps: true)
} }
@@ -209,6 +210,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
if popover.isShown { if popover.isShown {
popover.performClose(nil) popover.performClose(nil)
} else { } else {
NotificationCenter.default.post(name: .popoverWillOpen, object: nil)
popover.show(relativeTo: button.bounds, of: button, preferredEdge: .minY) popover.show(relativeTo: button.bounds, of: button, preferredEdge: .minY)
NSApp.activate(ignoringOtherApps: true) NSApp.activate(ignoringOtherApps: true)
} }
+35 -7
View File
@@ -94,6 +94,9 @@ struct ContentView: View {
} }
.frame(width: 480) .frame(width: 480)
.animation(.easeInOut(duration: 0.2), value: showSettings) .animation(.easeInOut(duration: 0.2), value: showSettings)
.onReceive(NotificationCenter.default.publisher(for: .popoverWillOpen)) { _ in
showSettings = false
}
.onReceive(NotificationCenter.default.publisher(for: .openUpdateSheet)) { _ in .onReceive(NotificationCenter.default.publisher(for: .openUpdateSheet)) { _ in
showSettings = false showSettings = false
showUpdateSheet = true showUpdateSheet = true
@@ -977,6 +980,36 @@ struct UpdateSuccessBanner: View {
} }
} }
// MARK: - Markdown notes renderer
struct ReleaseNotesText: View {
let text: String
var font: Font = .system(size: 12)
var body: some View {
let processed = text
.split(separator: "\n", omittingEmptySubsequences: false)
.map { line -> String in
let s = String(line)
if s.hasPrefix("### ") { return "**\(s.dropFirst(4))**" }
if s.hasPrefix("## ") { return "**\(s.dropFirst(3))**" }
if s.hasPrefix("# ") { return "**\(s.dropFirst(2))**" }
if s.hasPrefix("- ") { return "\(s.dropFirst(2))" }
return s
}
.joined(separator: "\n")
if let attr = try? AttributedString(markdown: processed,
options: .init(interpretedSyntax: .inlineOnlyPreservingWhitespace)) {
Text(attr).font(font).foregroundColor(.secondary)
.fixedSize(horizontal: false, vertical: true)
} else {
Text(text).font(font).foregroundColor(.secondary)
.fixedSize(horizontal: false, vertical: true)
}
}
}
// MARK: - Update Banner // MARK: - Update Banner
struct UpdateBanner: View { struct UpdateBanner: View {
@@ -992,10 +1025,7 @@ struct UpdateBanner: View {
Text("Update available — v\(updater.latestVersion)") Text("Update available — v\(updater.latestVersion)")
.font(.system(size: 12, weight: .semibold)) .font(.system(size: 12, weight: .semibold))
if !updater.releaseNotes.isEmpty { if !updater.releaseNotes.isEmpty {
Text(updater.releaseNotes) ReleaseNotesText(text: updater.releaseNotes, font: .system(size: 11))
.font(.system(size: 11))
.foregroundColor(.secondary)
.fixedSize(horizontal: false, vertical: true)
} }
} }
Spacer() Spacer()
@@ -1061,9 +1091,7 @@ struct UpdateSheet: View {
.foregroundColor(.blue) .foregroundColor(.blue)
} }
if !updater.releaseNotes.isEmpty { if !updater.releaseNotes.isEmpty {
Text(updater.releaseNotes) ReleaseNotesText(text: updater.releaseNotes)
.font(.system(size: 12))
.foregroundColor(.secondary)
} }
} }
Spacer() Spacer()
+2 -2
View File
@@ -15,9 +15,9 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.0.4</string> <string>1.0.10</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>23</string> <string>30</string>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>
<string>13.0</string> <string>13.0</string>
<key>LSUIElement</key> <key>LSUIElement</key>
+1 -1
View File
@@ -14,7 +14,7 @@ class UpdateNotificationWindowController: NSWindowController {
// Called when a new update is detected while running // Called when a new update is detected while running
static func showUpdate(version: String, notes: String, near statusItem: NSStatusItem?) { static func showUpdate(version: String, notes: String, near statusItem: NSStatusItem?) {
showWindow(version: version, subtitle: notes.isEmpty ? "Tap to update now." : notes, near: statusItem, isUpdate: true) showWindow(version: version, subtitle: "Tap to view release notes & update now!", near: statusItem, isUpdate: true)
} }
static func showLimitWarning(windowName: String, percent: Int, near statusItem: NSStatusItem?) { static func showLimitWarning(windowName: String, percent: Int, near statusItem: NSStatusItem?) {
+1
View File
@@ -307,6 +307,7 @@ extension Notification.Name {
static let refreshIntervalChanged = Notification.Name("refreshIntervalChanged") static let refreshIntervalChanged = Notification.Name("refreshIntervalChanged")
static let closePopover = Notification.Name("closePopover") static let closePopover = Notification.Name("closePopover")
static let showPopover = Notification.Name("showPopover") static let showPopover = Notification.Name("showPopover")
static let popoverWillOpen = Notification.Name("popoverWillOpen")
static let updateDetected = Notification.Name("updateDetected") static let updateDetected = Notification.Name("updateDetected")
static let limitWarning = Notification.Name("limitWarning") static let limitWarning = Notification.Name("limitWarning")
static let limitReset = Notification.Name("limitReset") static let limitReset = Notification.Name("limitReset")
+1 -1
View File
@@ -8,7 +8,7 @@
[![macOS](https://img.shields.io/badge/macOS-13.0+-000000?style=flat&logo=apple&logoColor=white)](https://www.apple.com/macos/) [![macOS](https://img.shields.io/badge/macOS-13.0+-000000?style=flat&logo=apple&logoColor=white)](https://www.apple.com/macos/)
[![Swift](https://img.shields.io/badge/Swift-5.9-F05138?style=flat&logo=swift&logoColor=white)](https://swift.org) [![Swift](https://img.shields.io/badge/Swift-5.9-F05138?style=flat&logo=swift&logoColor=white)](https://swift.org)
[![Version](https://img.shields.io/badge/version-1.0.3-orange?style=flat)](https://github.com/superdooper86/claudechecker/releases) [![Version](https://img.shields.io/badge/version-1.1.0-orange?style=flat)](https://github.com/superdooper86/claudechecker/releases)
[![License](https://img.shields.io/badge/license-MIT-blue?style=flat)](LICENSE) [![License](https://img.shields.io/badge/license-MIT-blue?style=flat)](LICENSE)
</div> </div>
+3 -8
View File
@@ -1,9 +1,4 @@
## What's new in v1.0.4 ## What's new in v1.0.10
### Clickable notifications ### Main window always opens on click
Notifications are now interactive — tap to act, not just read: Closing the app while Settings was open would cause the next click to reopen straight to Settings. The app now always returns to the main window when reopened.
- **Limit warnings & resets** (80%, 95%, reset) — tapping the notification opens the main ClaudeChecker window so you can see your current usage at a glance
- **Update available** — tapping the notification opens the main window with the update sheet already showing, so you can install in one click
Previously notifications were display-only and required manually clicking the menubar icon to take action. This removes that friction.
+3 -3
View File
@@ -1,5 +1,5 @@
{ {
"version": "1.0.3", "version": "1.1.0",
"url": "https://github.com/superdooper86/claudechecker/releases/download/v1.0.3/ClaudeChecker.zip", "url": "https://github.com/superdooper86/claudechecker/releases/download/v1.1.0/ClaudeChecker.zip",
"notes": "Release 1.0.3" "notes": "## What's new in v1.1.0\n\n### Main window always opens on click\nClosing the app while Settings was open would cause the next click to reopen straight to Settings. The app now always returns to the main window when reopened."
} }