Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion Sources/ClaudeUsageMonitor/App/BundleConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@
}

static var ccusageVersion: String {
return Bundle.main.object(forInfoDictionaryKey: "CcusageVersion") as? String ?? ""
let version = Bundle.main.object(forInfoDictionaryKey: "CcusageVersion") as? String ?? ""
let fallbackVersion = "15.3.0"

Check warning on line 23 in Sources/ClaudeUsageMonitor/App/BundleConfiguration.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Lines should not have trailing whitespace (trailing_whitespace)
// Debug時にInfo.plistが更新されていない場合のフォールバック
if version.isEmpty {
print("⚠️ [BundleConfiguration] CcusageVersion not found in Info.plist, using fallback: \(fallbackVersion)")
return fallbackVersion
}

Check warning on line 29 in Sources/ClaudeUsageMonitor/App/BundleConfiguration.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Lines should not have trailing whitespace (trailing_whitespace)
print("📦 [BundleConfiguration] Using ccusage version: \(version)")
return version
}
}
10 changes: 8 additions & 2 deletions Sources/ClaudeUsageMonitor/Services/CommandExecutor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,23 @@ class CommandExecutor {
func executeCcusageCommand(subcommand: String? = nil, additionalArgs: [String] = []) async throws -> String {
var command: String
var ccusageArgs: [String] = []

let ccusageVersion = BundleConfiguration.ccusageVersion
guard !ccusageVersion.isEmpty else {
throw CommandError.commandNotFound("ccusage version not configured")
}

// Try bunx first
if let bunxPath = try await findCommand("bunx") {
print("[CommandExecutor] Found bunx at: \(bunxPath)")
command = bunxPath
ccusageArgs.append("ccusage@\(BundleConfiguration.ccusageVersion)")
ccusageArgs.append("ccusage@\(ccusageVersion)")
}
// Fall back to npx
else if let npxPath = try await findCommand("npx") {
print("[CommandExecutor] Found npx at: \(npxPath)")
command = npxPath
ccusageArgs.append("ccusage@\(BundleConfiguration.ccusageVersion)")
ccusageArgs.append("ccusage@\(ccusageVersion)")
}
// Neither found
else {
Expand All @@ -103,6 +108,7 @@ class CommandExecutor {
ccusageArgs.append(contentsOf: additionalArgs)

print("[CommandExecutor] Executing: \(command) \(ccusageArgs.joined(separator: " "))")
print("[CommandExecutor] Using ccusage version: \(ccusageVersion)")

// Execute the command
let task = Process()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,17 @@
}

session = data
remainingTokens = monitor.usageData.sessionTokenLimit - data.totalTokens
remainingTokens = max(0, monitor.usageData.sessionTokenLimit - data.totalTokens)
percentage = monitor.usageData.sessionUsagePercentage
burnRate = Double(monitor.usageData.sessionBurnRate) ?? 0
remainingTime = monitor.usageData.sessionRemainingTime
cost = data.costUSD
planDescription = monitor.usageData.planDescription
resetTime = Date.formatTime(from: data.endTime)

Check warning on line 36 in Sources/ClaudeUsageMonitor/ViewModels/SessionViewModel.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Lines should not have trailing whitespace (trailing_whitespace)
// デバッグ用ログ
print("🔍 [SessionViewModel] Total: \(data.totalTokens), Limit: \(monitor.usageData.sessionTokenLimit), Remaining: \(remainingTokens)")

Check warning on line 38 in Sources/ClaudeUsageMonitor/ViewModels/SessionViewModel.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Line should be 120 characters or less; currently it has 142 characters (line_length)
print("🔍 [SessionViewModel] Plan: \(planDescription), Percentage: \(String(format: "%.1f", percentage))%")

// 通知機能は初回リリースでは無効化
/*
Expand Down
37 changes: 36 additions & 1 deletion Sources/ClaudeUsageMonitor/Views/Tabs/SettingsTabView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -580,10 +580,15 @@ struct SettingsTabView: View {
private func selectUpdateChannel(_ channel: UpdateChannel) {
UserDefaults.standard.updateChannel = channel

#if canImport(Sparkle)
// Notify AppDelegate to update Sparkle configuration
if let appDelegate = NSApplication.shared.delegate as? AppDelegate {
appDelegate.updateChannelChanged(to: channel)
}
#endif

// Re-fetch latest versions when channel changes
fetchLatestVersions()
}

private func checkLatestVersion() {
Expand Down Expand Up @@ -628,39 +633,69 @@ struct SettingsTabView: View {
}

private func fetchLatestVersions() {
print("🔄 Starting to fetch latest versions...")

// Fetch stable version
Task {
await fetchLatestVersion(for: .stable) { version in
self.latestStableVersion = version
print("📦 Stable version set to: \(version ?? "nil")")
}
}

// Fetch dev version
Task {
await fetchLatestVersion(for: .dev) { version in
self.latestDevVersion = version
print("📦 Dev version set to: \(version ?? "nil")")
}
}
}

private func fetchLatestVersion(for channel: UpdateChannel, completion: @escaping (String?) -> Void) async {
guard let url = URL(string: channel.appcastURL) else {
print("❌ Invalid URL for channel \(channel): \(channel.appcastURL)")
completion(nil)
return
}

do {
let (data, _) = try await URLSession.shared.data(from: url)
let (data, response) = try await URLSession.shared.data(from: url)

if let httpResponse = response as? HTTPURLResponse {
print("📡 Fetching \(channel) version from: \(url)")
print("📡 Response status: \(httpResponse.statusCode)")

guard httpResponse.statusCode == 200 else {
print("❌ HTTP error: \(httpResponse.statusCode)")
await MainActor.run {
completion(nil)
}
return
}
}

let parser = XMLParser(data: data)
let delegate = AppcastParserDelegate()
parser.delegate = delegate

if parser.parse(), let version = delegate.latestVersion {
print("✅ Found \(channel) version: \(version)")
await MainActor.run {
completion(version)
}
} else {
print("❌ Failed to parse XML for \(channel)")
// デバッグ用: XMLの最初の部分を表示
if let xmlString = String(data: data.prefix(500), encoding: .utf8) {
print("XML preview: \(xmlString)")
}
await MainActor.run {
completion(nil)
}
}
} catch {
print("❌ Error fetching \(channel) version: \(error)")
await MainActor.run {
completion(nil)
}
Expand Down
Loading