mirror of
https://github.com/jiayouzl/Bitcoin-Monitoring.git
synced 2025-11-25 19:37:50 +08:00
fix: 启用菜单项交互功能并添加价格复制功能
- 修复菜单项在价格加载后仍保持禁用状态的问题 - 添加点击选择币种功能:用户可以直接点击价格菜单项选择该币种 - 添加 Option+点击复制价格功能:按住Option键点击菜单项复制价格到剪贴板 - 添加用户友好的操作提示和通知反馈 - 更新应用权限以支持用户通知功能 解决 PR #3 中的反馈意见:菜单项应在价格加载后变为可交互状态
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import AppKit
|
import AppKit
|
||||||
import Combine
|
import Combine
|
||||||
|
import UserNotifications
|
||||||
|
|
||||||
// macOS菜单栏应用主类
|
// macOS菜单栏应用主类
|
||||||
@MainActor
|
@MainActor
|
||||||
@@ -166,15 +167,30 @@ class BTCMenuBarApp: NSObject, ObservableObject {
|
|||||||
guard let (priceOpt, errorOpt) = results[symbol], let menuItem = symbolMenuItems[symbol] else { continue }
|
guard let (priceOpt, errorOpt) = results[symbol], let menuItem = symbolMenuItems[symbol] else { continue }
|
||||||
if let price = priceOpt {
|
if let price = priceOpt {
|
||||||
menuItem.title = "\(symbol.displayName): $\(self.formatPriceWithCommas(price))"
|
menuItem.title = "\(symbol.displayName): $\(self.formatPriceWithCommas(price))"
|
||||||
|
menuItem.isEnabled = true // 启用菜单项,允许用户交互
|
||||||
|
menuItem.action = #selector(self.copyPriceOrSelectSymbol(_:))
|
||||||
|
menuItem.target = self
|
||||||
|
menuItem.representedObject = ["symbol": symbol, "price": price]
|
||||||
} else if let error = errorOpt {
|
} else if let error = errorOpt {
|
||||||
menuItem.title = "\(symbol.displayName): 错误"
|
menuItem.title = "\(symbol.displayName): 错误"
|
||||||
menuItem.toolTip = error
|
menuItem.toolTip = error
|
||||||
|
menuItem.isEnabled = true // 即使有错误也允许交互,用户可以查看错误详情
|
||||||
|
menuItem.action = #selector(self.selectSymbol(_:))
|
||||||
|
menuItem.target = self
|
||||||
|
menuItem.representedObject = symbol.rawValue
|
||||||
} else {
|
} else {
|
||||||
menuItem.title = "\(symbol.displayName): 加载中..."
|
menuItem.title = "\(symbol.displayName): 加载中..."
|
||||||
|
// 保持禁用状态,直到加载完成
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加使用提示
|
||||||
|
let hintItem = NSMenuItem(title: "💡 点击选择币种,Option+点击复制价格", action: nil, keyEquivalent: "")
|
||||||
|
hintItem.isEnabled = false
|
||||||
|
menu.addItem(hintItem)
|
||||||
|
menu.addItem(NSMenuItem.separator())
|
||||||
|
|
||||||
// 如果有错误,显示错误信息(带错误图标)
|
// 如果有错误,显示错误信息(带错误图标)
|
||||||
if let errorMessage = priceManager.errorMessage {
|
if let errorMessage = priceManager.errorMessage {
|
||||||
let errorItem = NSMenuItem(title: "错误: \(errorMessage)", action: nil, keyEquivalent: "")
|
let errorItem = NSMenuItem(title: "错误: \(errorMessage)", action: nil, keyEquivalent: "")
|
||||||
@@ -333,6 +349,38 @@ class BTCMenuBarApp: NSObject, ObservableObject {
|
|||||||
print("✅ 币种已更新为: \(symbol.pairDisplayName)")
|
print("✅ 币种已更新为: \(symbol.pairDisplayName)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 复制价格或选择币种(支持复制价格到剪贴板和切换币种)
|
||||||
|
@objc private func copyPriceOrSelectSymbol(_ sender: NSMenuItem) {
|
||||||
|
guard let data = sender.representedObject as? [String: Any],
|
||||||
|
let symbol = data["symbol"] as? CryptoSymbol,
|
||||||
|
let price = data["price"] as? Double else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否按住了 Option 键,如果是则复制价格到剪贴板
|
||||||
|
let currentEvent = NSApp.currentEvent
|
||||||
|
let isOptionPressed = currentEvent?.modifierFlags.contains(.option) ?? false
|
||||||
|
|
||||||
|
if isOptionPressed {
|
||||||
|
// 复制价格到剪贴板
|
||||||
|
let priceString = formatPriceWithCommas(price)
|
||||||
|
let pasteboard = NSPasteboard.general
|
||||||
|
pasteboard.clearContents()
|
||||||
|
pasteboard.setString("$\(priceString)", forType: .string)
|
||||||
|
|
||||||
|
print("✅ 已复制 \(symbol.displayName) 价格到剪贴板: $\(priceString)")
|
||||||
|
|
||||||
|
// 显示通知告知用户已复制
|
||||||
|
Task {
|
||||||
|
await self.showCopyNotification(symbol: symbol, price: priceString)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 默认行为:选择该币种
|
||||||
|
appSettings.saveSelectedSymbol(symbol)
|
||||||
|
print("✅ 币种已更新为: \(symbol.pairDisplayName)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 选择刷新间隔
|
// 选择刷新间隔
|
||||||
@objc private func selectRefreshInterval(_ sender: NSMenuItem) {
|
@objc private func selectRefreshInterval(_ sender: NSMenuItem) {
|
||||||
guard let interval = sender.representedObject as? RefreshInterval else {
|
guard let interval = sender.representedObject as? RefreshInterval else {
|
||||||
@@ -397,6 +445,42 @@ class BTCMenuBarApp: NSObject, ObservableObject {
|
|||||||
return version
|
return version
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 显示价格复制通知
|
||||||
|
private func showCopyNotification(symbol: CryptoSymbol, price: String) async {
|
||||||
|
let center = UNUserNotificationCenter.current()
|
||||||
|
|
||||||
|
// 请求通知权限(如果尚未授权)
|
||||||
|
do {
|
||||||
|
let granted = try await center.requestAuthorization(options: [.alert, .sound])
|
||||||
|
if !granted {
|
||||||
|
return // 用户拒绝了通知权限
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
print("❌ 通知权限请求失败: \(error)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建通知内容
|
||||||
|
let content = UNMutableNotificationContent()
|
||||||
|
content.title = "价格已复制"
|
||||||
|
content.body = "\(symbol.displayName): $\(price)"
|
||||||
|
content.sound = .default
|
||||||
|
|
||||||
|
// 创建通知请求
|
||||||
|
let request = UNNotificationRequest(
|
||||||
|
identifier: "price-copied-\(Date().timeIntervalSince1970)",
|
||||||
|
content: content,
|
||||||
|
trigger: nil // 立即显示
|
||||||
|
)
|
||||||
|
|
||||||
|
// 发送通知
|
||||||
|
do {
|
||||||
|
try await center.add(request)
|
||||||
|
} catch {
|
||||||
|
print("❌ 通知发送失败: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 退出应用
|
// 退出应用
|
||||||
@objc private func quitApp() {
|
@objc private func quitApp() {
|
||||||
NSApplication.shared.terminate(nil)
|
NSApplication.shared.terminate(nil)
|
||||||
|
|||||||
@@ -4,5 +4,7 @@
|
|||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.security.network.server</key>
|
<key>com.apple.security.network.server</key>
|
||||||
<false/>
|
<false/>
|
||||||
|
<key>com.apple.security.user-notifications</key>
|
||||||
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
Reference in New Issue
Block a user