fix: 启用菜单项交互功能并添加价格复制功能

- 修复菜单项在价格加载后仍保持禁用状态的问题
- 添加点击选择币种功能:用户可以直接点击价格菜单项选择该币种
- 添加 Option+点击复制价格功能:按住Option键点击菜单项复制价格到剪贴板
- 添加用户友好的操作提示和通知反馈
- 更新应用权限以支持用户通知功能

解决 PR #3 中的反馈意见:菜单项应在价格加载后变为可交互状态
This commit is contained in:
SherlockKudou
2025-10-30 04:51:18 +00:00
parent ee3e9e650c
commit 370f0731d8
2 changed files with 86 additions and 0 deletions

View File

@@ -8,6 +8,7 @@
import SwiftUI
import AppKit
import Combine
import UserNotifications
// macOS
@MainActor
@@ -166,15 +167,30 @@ class BTCMenuBarApp: NSObject, ObservableObject {
guard let (priceOpt, errorOpt) = results[symbol], let menuItem = symbolMenuItems[symbol] else { continue }
if let price = priceOpt {
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 {
menuItem.title = "\(symbol.displayName): 错误"
menuItem.toolTip = error
menuItem.isEnabled = true // 使
menuItem.action = #selector(self.selectSymbol(_:))
menuItem.target = self
menuItem.representedObject = symbol.rawValue
} else {
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 {
let errorItem = NSMenuItem(title: "错误: \(errorMessage)", action: nil, keyEquivalent: "")
@@ -333,6 +349,38 @@ class BTCMenuBarApp: NSObject, ObservableObject {
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) {
guard let interval = sender.representedObject as? RefreshInterval else {
@@ -397,6 +445,42 @@ class BTCMenuBarApp: NSObject, ObservableObject {
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() {
NSApplication.shared.terminate(nil)

View File

@@ -4,5 +4,7 @@
<dict>
<key>com.apple.security.network.server</key>
<false/>
<key>com.apple.security.user-notifications</key>
<true/>
</dict>
</plist>