fix menu bar icon, support snooze battery notifications
@@ -157,6 +157,9 @@
|
||||
18892A8F2B81F8320017377E /* BatteryWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatteryWidget.swift; sourceTree = "<group>"; };
|
||||
18892A952B81F8330017377E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
18892A962B81F8330017377E /* widget.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = widget.entitlements; sourceTree = "<group>"; };
|
||||
1893984B2DF73D6800E7C32E /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = "zh-Hant"; path = "zh-Hant.lproj/Credits.rtf"; sourceTree = "<group>"; };
|
||||
1893984C2DF73D8100E7C32E /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||
1893984D2DF73DF000E7C32E /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||
1895851A2B724DCD00108E5C /* IDeviceBattery.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IDeviceBattery.swift; sourceTree = "<group>"; };
|
||||
189BD5EA2BDE69660056D06C /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||
18A0A9CC2AAE07EA00975B81 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = "zh-Hans"; path = "zh-Hans.lproj/Credits.rtf"; sourceTree = "<group>"; };
|
||||
@@ -460,6 +463,7 @@
|
||||
en,
|
||||
Base,
|
||||
"zh-Hans",
|
||||
"zh-Hant",
|
||||
);
|
||||
mainGroup = 1841D4422AA6071C0022A1BE;
|
||||
packageReferences = (
|
||||
@@ -592,6 +596,7 @@
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
1841D47B2AA8DF0B0022A1BE /* zh-Hans */,
|
||||
1893984D2DF73DF000E7C32E /* zh-Hant */,
|
||||
);
|
||||
name = Localizable.strings;
|
||||
sourceTree = "<group>";
|
||||
@@ -600,6 +605,7 @@
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
189BD5EA2BDE69660056D06C /* zh-Hans */,
|
||||
1893984C2DF73D8100E7C32E /* zh-Hant */,
|
||||
);
|
||||
name = InfoPlist.strings;
|
||||
path = AirBattery;
|
||||
@@ -610,6 +616,7 @@
|
||||
children = (
|
||||
18A0A9CC2AAE07EA00975B81 /* zh-Hans */,
|
||||
18C7CFDE2AAF842E005898EF /* Base */,
|
||||
1893984B2DF73D6800E7C32E /* zh-Hant */,
|
||||
);
|
||||
name = Credits.rtf;
|
||||
sourceTree = "<group>";
|
||||
@@ -811,7 +818,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = AirBattery/AirBattery.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 162;
|
||||
CURRENT_PROJECT_VERSION = 163;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"AirBattery/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = L4T783637F;
|
||||
@@ -829,7 +836,7 @@
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
MARKETING_VERSION = 1.6.2;
|
||||
MARKETING_VERSION = 1.6.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lihaoyun6.AirBattery;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
@@ -845,7 +852,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = AirBattery/AirBattery.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 162;
|
||||
CURRENT_PROJECT_VERSION = 163;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"AirBattery/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = L4T783637F;
|
||||
@@ -863,7 +870,7 @@
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
MARKETING_VERSION = 1.6.2;
|
||||
MARKETING_VERSION = 1.6.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lihaoyun6.AirBattery;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
@@ -910,7 +917,7 @@
|
||||
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||
CODE_SIGN_ENTITLEMENTS = widget/widget.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 162;
|
||||
CURRENT_PROJECT_VERSION = 163;
|
||||
DEVELOPMENT_TEAM = L4T783637F;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
@@ -926,7 +933,7 @@
|
||||
);
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
MARKETING_VERSION = 1.6.2;
|
||||
MARKETING_VERSION = 1.6.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lihaoyun6.AirBattery.widget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
@@ -944,7 +951,7 @@
|
||||
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||
CODE_SIGN_ENTITLEMENTS = widget/widget.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 162;
|
||||
CURRENT_PROJECT_VERSION = 163;
|
||||
DEVELOPMENT_TEAM = L4T783637F;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
@@ -960,7 +967,7 @@
|
||||
);
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
MARKETING_VERSION = 1.6.2;
|
||||
MARKETING_VERSION = 1.6.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lihaoyun6.AirBattery.widget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
|
||||
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 778 B After Width: | Height: | Size: 810 B |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 180 KiB After Width: | Height: | Size: 177 KiB |
@@ -6,6 +6,7 @@
|
||||
//
|
||||
import SwiftUI
|
||||
import Foundation
|
||||
import IOBluetooth
|
||||
|
||||
class SPBluetoothDataModel {
|
||||
static var shared: SPBluetoothDataModel = SPBluetoothDataModel()
|
||||
@@ -40,6 +41,7 @@ class MagicBattery {
|
||||
@objc func scanDevices() {
|
||||
//Thread.detachNewThread {
|
||||
if self.readBTDevice {
|
||||
self.getIOBTBattery()
|
||||
self.getOtherBTBattery()
|
||||
self.getMagicBattery()
|
||||
self.getOldMagicKeyboard()
|
||||
@@ -131,10 +133,10 @@ class MagicBattery {
|
||||
}
|
||||
if let percentProperty = IORegistryEntryCreateCFProperty(object, "BatteryStatusFlags" as CFString, kCFAllocatorDefault, 0) {
|
||||
status = percentProperty.takeRetainedValue() as! Int
|
||||
if status == 4 { status = 0 }
|
||||
}
|
||||
if let percentProperty = IORegistryEntryCreateCFProperty(object, "BatteryPercent" as CFString, kCFAllocatorDefault, 0) {
|
||||
percent = percentProperty.takeRetainedValue() as! Int
|
||||
if percent == 4 { percent = 0 }
|
||||
}
|
||||
if let productProperty = IORegistryEntryCreateCFProperty(object, "Product" as CFString, kCFAllocatorDefault, 0) {
|
||||
productName = productProperty.takeRetainedValue() as! String
|
||||
@@ -325,4 +327,38 @@ class MagicBattery {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getIOBTBattery() {
|
||||
if let devices = IOBluetoothDevice.pairedDevices() as? [IOBluetoothDevice] {
|
||||
for device in devices {
|
||||
let name = device.name
|
||||
let address = device.addressString
|
||||
let connected = device.isConnected()
|
||||
//let usb = device.getValue(forKey: "isPluggedOverUSB") as! Bool ?? false
|
||||
|
||||
if connected && !device.isAppleDevice {
|
||||
if let battery = device.getValue(forKey: "batteryPercentSingle") as? Int, let name = name, let address = address, battery != 0 {
|
||||
let type = getDeviceType(address.replacingOccurrences(of: "-", with: ":").uppercased(),"")
|
||||
AirBatteryModel.updateDevice(Device(deviceID: address, deviceType: type, deviceName: name, batteryLevel: battery, isCharging: 0, lastUpdate: Date().timeIntervalSince1970))
|
||||
}
|
||||
//let left = device.getValue(forKey: "batteryPercentLeft") as? Int
|
||||
//let right = device.getValue(forKey: "batteryPercentRight") as? Int
|
||||
//let _case = device.getValue(forKey: "batteryPercentCase") as? Int
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension IOBluetoothDevice {
|
||||
func getValue(forKey: String) -> Any? {
|
||||
if self.responds(to: Selector((forKey))) {
|
||||
return self.value(forKey: forKey)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var isAppleDevice: Bool {
|
||||
return self.getValue(forKey: "isAppleDevice") as? Bool ?? false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ struct AirBatteryApp: App {
|
||||
// If you want to start the updater manually, pass false to startingUpdater and call .startUpdater() later
|
||||
// This is where you can also pass an updater delegate if you need one
|
||||
updaterController = SPUStandardUpdaterController(startingUpdater: true, updaterDelegate: nil, userDriverDelegate: nil)
|
||||
registerNotificationCategory()
|
||||
}
|
||||
|
||||
var body: some Scene {
|
||||
@@ -70,6 +71,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate, UNUserNotifi
|
||||
@AppStorage("alertSound") var alertSound = true
|
||||
@AppStorage("readBTHID") var readBTHID = true
|
||||
@AppStorage("hideLevel") var hideLevel = 90
|
||||
@AppStorage("disappearTime") var disappearTime = 20
|
||||
@AppStorage("whitelistMode") var whitelistMode = false
|
||||
@AppStorage("iosBatteryStyle") var iosBatteryStyle = false
|
||||
@AppStorage("updateInterval") var updateInterval = 1
|
||||
@@ -84,6 +86,15 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate, UNUserNotifi
|
||||
var startTime = Date()
|
||||
let nc = NSWorkspace.shared.notificationCenter
|
||||
|
||||
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
|
||||
|
||||
if response.actionIdentifier == "DELAY_30_MIN" {
|
||||
let deviceName = response.notification.request.content.userInfo["customInfo"] as? String ?? ""
|
||||
lowPowerNoteDelay[deviceName] = Date().timeIntervalSince1970 + 1800
|
||||
}
|
||||
completionHandler()
|
||||
}
|
||||
|
||||
func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
|
||||
// 用户点击 Dock 图标时会调用这个方法
|
||||
if showOn == "sbar" || showOn == "none" {
|
||||
@@ -307,13 +318,15 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate, UNUserNotifi
|
||||
if now.timeIntervalSince(startTime) >= 10 {
|
||||
if let name = device.name, let macAdd = device.addressString {
|
||||
if AirBatteryModel.checkIfBlocked(name: name) { return }
|
||||
if let prefix = getFirstNCharacters(of: macAdd, count: 8) {
|
||||
//if let prefix = getFirstNCharacters(of: macAdd, count: 8) {
|
||||
print("ℹ️ \(name) (\(macAdd)) connected")
|
||||
DispatchQueue.global(qos: .background).async {
|
||||
usleep(2500000)
|
||||
if !appleMacPrefix.contains(prefix) {
|
||||
//if !appleMacPrefix.contains(prefix) {
|
||||
if !device.isAppleDevice {
|
||||
SPBluetoothDataModel.shared.refeshData { _ in
|
||||
BTDBattery.getOtherDevice(last: "2m", timeout: 2)
|
||||
MagicBattery.shared.getIOBTBattery()
|
||||
MagicBattery.shared.getOtherBTBattery()
|
||||
}
|
||||
} else {
|
||||
@@ -326,7 +339,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate, UNUserNotifi
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ let nearCastTimer = Timer.publish(every: TimeInterval(60 * updateInterval + Int(
|
||||
let widgetViewTimer = Timer.publish(every: TimeInterval(60 * updateInterval), on: .main, in: .common).autoconnect()
|
||||
let macID = getMacModelIdentifier()
|
||||
let isoFormatter = ISO8601DateFormatter()
|
||||
var lowPowerNoteDelay = [String: Double]()
|
||||
|
||||
struct dayAndWeek {
|
||||
var day: String
|
||||
@@ -178,17 +179,38 @@ func createAlert(level: NSAlert.Style = .warning, title: String, message: String
|
||||
return alert
|
||||
}
|
||||
|
||||
func createNotification(title: String, message: String, alertSound: Bool = true, interval: TimeInterval = 2) {
|
||||
//@AppStorage("alertSound") var alertSound = true
|
||||
|
||||
func registerNotificationCategory() {
|
||||
let delayAction = UNNotificationAction(
|
||||
identifier: "DELAY_30_MIN",
|
||||
title: "Snooze for 30 minutes".local,
|
||||
options: []
|
||||
)
|
||||
|
||||
let category = UNNotificationCategory(
|
||||
identifier: "DELAY_CATEGORY",
|
||||
actions: [delayAction],
|
||||
intentIdentifiers: [],
|
||||
options: []
|
||||
)
|
||||
|
||||
UNUserNotificationCenter.current().setNotificationCategories([category])
|
||||
}
|
||||
|
||||
func createNotification(title: String, message: String, alertSound: Bool = true, interval: TimeInterval = 2, delay: Bool = false, info: String = "") {
|
||||
let content = UNMutableNotificationContent()
|
||||
content.title = title
|
||||
content.body = message
|
||||
content.sound = alertSound ? UNNotificationSound.default : nil
|
||||
if delay { content.categoryIdentifier = "DELAY_CATEGORY" }
|
||||
content.userInfo = ["customInfo": info]
|
||||
|
||||
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: interval, repeats: false)
|
||||
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
|
||||
|
||||
UNUserNotificationCenter.current().add(request) { error in
|
||||
if let error = error { print("Notification failed to send:\(error.localizedDescription)") }
|
||||
if let error = error {
|
||||
print("Notification failed to send:\(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -210,6 +210,9 @@ class AlertWindowController {
|
||||
func batteryAlert() {
|
||||
@AppStorage("nearCast") var nearCast = false
|
||||
|
||||
let now = Date()
|
||||
lowPowerNoteDelay = lowPowerNoteDelay.filter { $0.value >= now.timeIntervalSince1970 }
|
||||
|
||||
let alertList = ud.get(objectType: [btAlert].self, forKey: "alertList") ?? []
|
||||
var allDevices = AirBatteryModel.getAll()
|
||||
allDevices.append(ib2ab(InternalBattery.status))
|
||||
@@ -219,17 +222,19 @@ func batteryAlert() {
|
||||
for device in allDevices.filter({ alertList.map({$0.name}).contains($0.deviceName) }) {
|
||||
if let alert = alertList.first(where: { $0.name == device.deviceName }) {
|
||||
if device.batteryLevel < alert.low && device.isCharging == 0 && alert.lowOn {
|
||||
if let delay = lowPowerNoteDelay[device.deviceName], delay > now.timeIntervalSince1970 { return }
|
||||
let title = "Low Battery".local
|
||||
let body = String(format: "\"%@\" remaining battery %d%%".local, device.deviceName, device.batteryLevel)
|
||||
createNotification(title: title, message: body, alertSound: alert.lowSound)
|
||||
createNotification(title: title, message: body, alertSound: alert.lowSound, delay: true, info: device.deviceName)
|
||||
if nearCast {
|
||||
if let info = netcastService.createInfo(title: title, info: body) { netcastService.sendMessage(info) }
|
||||
}
|
||||
}
|
||||
if device.batteryLevel > alert.full && device.isCharging != 0 && alert.fullOn {
|
||||
if let delay = lowPowerNoteDelay[device.deviceName], delay > now.timeIntervalSince1970 { return }
|
||||
let title = "Fully Charged".local
|
||||
let body = String(format: "\"%@\" battery has reached %d%%".local, device.deviceName, device.batteryLevel)
|
||||
createNotification(title: title, message: body, alertSound: alert.fullSound)
|
||||
createNotification(title: title, message: body, alertSound: alert.fullSound, delay: true, info: device.deviceName)
|
||||
if nearCast {
|
||||
if let info = netcastService.createInfo(title: title, info: body) { netcastService.sendMessage(info) }
|
||||
}
|
||||
|
||||
@@ -88,15 +88,16 @@ struct mainBatteryView: View {
|
||||
.frame(width: width, height: 8, alignment: .leading)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 1.5, style: .continuous))
|
||||
.offset(x:2)
|
||||
if item.acPowered {
|
||||
Image("batt_" + ((item.isCharging || item.isCharged) ? "bolt" : "plug") + "_mask")
|
||||
.blendMode(.destinationOut)
|
||||
.offset(x:6)
|
||||
Image("batt_" + ((item.isCharging || item.isCharged) ? "bolt" : "plug"))
|
||||
.offset(x:6)
|
||||
.foregroundColor(.blackWhite)
|
||||
}
|
||||
}
|
||||
if item.acPowered && batteryPercent != "inside" {
|
||||
Image("batt_" + ((item.isCharging || item.isCharged) ? "bolt" : "plug") + "_mask")
|
||||
.blendMode(.destinationOut)
|
||||
.offset(x:6)
|
||||
Image("batt_" + ((item.isCharging || item.isCharged) ? "bolt" : "plug"))
|
||||
.offset(x:6)
|
||||
.foregroundColor(.blackWhite)
|
||||
}
|
||||
|
||||
}.compositingGroup()
|
||||
} else {
|
||||
ZStack(alignment: .leading) {
|
||||
@@ -128,7 +129,6 @@ struct mainBatteryView: View {
|
||||
BatteryLevelView(item: item)
|
||||
.foregroundColor(.white)
|
||||
.blendMode(.destinationOut)
|
||||
//.background(Color.red.opacity(0.5))
|
||||
}
|
||||
} else {
|
||||
if item.acPowered {
|
||||
|
||||
@@ -43,7 +43,7 @@ struct SettingsView: View {
|
||||
.listStyle(.sidebar)
|
||||
.padding(.top, 9)
|
||||
}
|
||||
.frame(width: 600, height: 430)
|
||||
.frame(width: 600, height: 440)
|
||||
.navigationTitle("AirBattery Settings")
|
||||
}
|
||||
}
|
||||
@@ -275,36 +275,44 @@ struct DisplayView: View {
|
||||
@AppStorage("intBattOnStatusBar") var intBattOnStatusBar = true
|
||||
@AppStorage("batteryPercent") var batteryPercent = "outside"
|
||||
@AppStorage("hideLevel") var hideLevel = 90
|
||||
@AppStorage("disappearTime") var disappearTime = 20
|
||||
@State private var levelList = [95, 90, 80, 70, 60, 50, 40, 30, 20, 10]
|
||||
|
||||
var body: some View {
|
||||
SForm {
|
||||
SGroupBox(label: "Menu Bar") {
|
||||
SToggle("Dynamic Battery Icon", isOn: $intBattOnStatusBar)
|
||||
Divider().opacity(0.5)
|
||||
SToggle("Colorful Battery Icon", isOn: $colorfulBattery)
|
||||
.disabled(!intBattOnStatusBar)
|
||||
Divider().opacity(0.5)
|
||||
SPicker("Battery Icon Style", selection: $iosBatteryStyle) {
|
||||
Text("macOS").tag(false)
|
||||
Text("iOS").tag(true)
|
||||
}.disabled(!intBattOnStatusBar)
|
||||
Divider().opacity(0.5)
|
||||
SPicker("Show Percentage", selection: $batteryPercent) {
|
||||
Text("Hidden").tag("hide")
|
||||
Text("Inside").tag("inside")
|
||||
Text("Outside").tag("outside")
|
||||
}.disabled(!intBattOnStatusBar)
|
||||
Divider().opacity(0.5)
|
||||
SPicker("Hide percentage when above", selection: $hideLevel) {
|
||||
Text("Never").tag(100)
|
||||
ForEach(levelList, id: \.self) { number in
|
||||
Text("\(number)%").tag(number)
|
||||
}
|
||||
if !levelList.contains(hideLevel) && hideLevel != 100 {
|
||||
Text("\(hideLevel)%").tag(hideLevel)
|
||||
}
|
||||
}.disabled(!intBattOnStatusBar || (batteryPercent == "hide"))
|
||||
SToggle("Dynamic Battery Icon", isOn: $intBattOnStatusBar)
|
||||
Divider().opacity(0.5)
|
||||
SToggle("Colorful Battery Icon", isOn: $colorfulBattery)
|
||||
.disabled(!intBattOnStatusBar)
|
||||
Divider().opacity(0.5)
|
||||
SPicker("Battery Icon Style", selection: $iosBatteryStyle) {
|
||||
Text("macOS").tag(false)
|
||||
Text("iOS").tag(true)
|
||||
}.disabled(!intBattOnStatusBar)
|
||||
Divider().opacity(0.5)
|
||||
SPicker("Show Percentage", selection: $batteryPercent) {
|
||||
Text("Hidden").tag("hide")
|
||||
Text("Inside").tag("inside")
|
||||
Text("Outside").tag("outside")
|
||||
}.disabled(!intBattOnStatusBar)
|
||||
Divider().opacity(0.5)
|
||||
SPicker("Remove Offline Device", selection: $disappearTime) {
|
||||
Text("Never").tag(UInt32.max)
|
||||
Text("after 20min").tag(20)
|
||||
Text("after 40min").tag(40)
|
||||
Text("after 60min").tag(60)
|
||||
}
|
||||
Divider().opacity(0.5)
|
||||
SPicker("Hide percentage when above", selection: $hideLevel) {
|
||||
Text("Never").tag(100)
|
||||
ForEach(levelList, id: \.self) { number in
|
||||
Text("\(number)%").tag(number)
|
||||
}
|
||||
if !levelList.contains(hideLevel) && hideLevel != 100 {
|
||||
Text("\(hideLevel)%").tag(hideLevel)
|
||||
}
|
||||
}.disabled(!intBattOnStatusBar || (batteryPercent == "hide"))
|
||||
}
|
||||
SGroupBox(label: "Dock") {
|
||||
SPicker("Appearance", selection: $appearance) {
|
||||
@@ -338,32 +346,30 @@ struct WidgetView: View {
|
||||
var body: some View {
|
||||
SForm {
|
||||
SGroupBox(label: "Widget") {
|
||||
//SToggle("Show Built-in Battery", isOn: $showMacOnWidget)
|
||||
//Divider().opacity(0.5)
|
||||
SToggle("Reverse Device List", isOn: $revListOnWidget)
|
||||
SToggle("Reverse Device List", isOn: $revListOnWidget)
|
||||
Divider().opacity(0.5)
|
||||
SPicker("Refresh Interval", selection: $widgetInterval) {
|
||||
Text("System Default").tag(-1)
|
||||
Text("Same as Nearbility").tag(0)
|
||||
}
|
||||
if #unavailable(macOS 14) {
|
||||
Divider().opacity(0.5)
|
||||
SPicker("Refresh Interval", selection: $widgetInterval) {
|
||||
Text("System Default").tag(-1)
|
||||
Text("Same as Nearbility").tag(0)
|
||||
}
|
||||
if #unavailable(macOS 14) {
|
||||
Divider().opacity(0.5)
|
||||
SPicker("Single Device Widget", selection: $deviceOnWidget) {
|
||||
Text("Not Set").tag("")
|
||||
if ib { Text(deviceName).tag(deviceName) }
|
||||
ForEach(devices, id: \.self) { device in
|
||||
Text(device).tag(device)
|
||||
}
|
||||
if !devices.contains(deviceOnWidget) && deviceOnWidget != deviceName && deviceOnWidget != "" {
|
||||
Text(deviceOnWidget).tag(deviceOnWidget)
|
||||
}
|
||||
}.onChange(of: deviceOnWidget) { _ in _ = AirBatteryModel.singleDeviceName() }
|
||||
}
|
||||
Divider().opacity(0.5)
|
||||
SButton("Reload All Widgets", buttonTitle: "Reload") {
|
||||
AirBatteryModel.writeData()
|
||||
WidgetCenter.shared.reloadAllTimelines()
|
||||
}
|
||||
SPicker("Single Device Widget", selection: $deviceOnWidget) {
|
||||
Text("Not Set").tag("")
|
||||
if ib { Text(deviceName).tag(deviceName) }
|
||||
ForEach(devices, id: \.self) { device in
|
||||
Text(device).tag(device)
|
||||
}
|
||||
if !devices.contains(deviceOnWidget) && deviceOnWidget != deviceName && deviceOnWidget != "" {
|
||||
Text(deviceOnWidget).tag(deviceOnWidget)
|
||||
}
|
||||
}.onChange(of: deviceOnWidget) { _ in _ = AirBatteryModel.singleDeviceName() }
|
||||
}
|
||||
Divider().opacity(0.5)
|
||||
SButton("Reload All Widgets", buttonTitle: "Reload") {
|
||||
AirBatteryModel.writeData()
|
||||
WidgetCenter.shared.reloadAllTimelines()
|
||||
}
|
||||
}
|
||||
}
|
||||
.onAppear { devices = AirBatteryModel.getAll(noFilter: true).filter({ $0.hasBattery }).map({ $0.deviceName }) }
|
||||
|
||||
@@ -5,5 +5,5 @@
|
||||
Created by apple on 2024/2/11.
|
||||
|
||||
*/
|
||||
"NSBluetoothAlwaysUsageDescription" = "AirBattery使用蓝牙来获取周边设备的电量信息";
|
||||
"NSLocalNetworkUsageDescription" = "AirBattery会通过局域网络来获取周边设备的电量";
|
||||
"NSBluetoothAlwaysUsageDescription" = "AirBattery使用蓝牙来获取周边设备的电池信息";
|
||||
"NSLocalNetworkUsageDescription" = "AirBattery会通过局域网络来获取周边设备的电池信息";
|
||||
|
||||
@@ -11,12 +11,8 @@
|
||||
"Light" = "浅色";
|
||||
"Dark" = "深色";
|
||||
"Settings..." = "偏好设置...";
|
||||
"No Battery!" = "未检测到电池!";
|
||||
"Time until full: " = "距充满还有: ";
|
||||
"Time until empty: " = "距用完还有: ";
|
||||
"Until Full:" = "距离充满:";
|
||||
"Until Empty:" = "可用时长:";
|
||||
"Show" = "显示";
|
||||
"About AirBattery" = "关于 AirBattery";
|
||||
" (Case)" = " (充电盒)";
|
||||
" mins ago" = " 分钟前";
|
||||
@@ -25,26 +21,21 @@
|
||||
"Built-in Battery Style" = "内建电池样式";
|
||||
"Quit AirBattery" = "退出 AirBattery";
|
||||
"Show AirBattery" = "将 AirBattery 置于";
|
||||
"Dock Icon" = "程序坞";
|
||||
"Dock" = "程序坞";
|
||||
"Menu Bar" = "菜单栏";
|
||||
"Both" = "同时显示";
|
||||
"None" = "隐藏图标";
|
||||
"Carousel Mode" = "轮播模式";
|
||||
"On" = "启用";
|
||||
"Off" = "关闭";
|
||||
"Discover iOS devices via Network" = "通过局域网扫描 iOS 设备";
|
||||
"Discover iOS devices via Bluetooth" = "通过蓝牙扫描 iOS 设备";
|
||||
"Apple Pencil from your iPad" = "从 iPad 读取 Apple Pencil";
|
||||
"Discover BT and BLE devices" = "扫描常规和低功耗蓝牙设备";
|
||||
//"Find AirPods / Beats" = "扫描AirPods/Beats耳机";
|
||||
//"Non-Apple BLE Devices" = "扫描第三方 BLE 设备";
|
||||
//"Guess Power Status" = "推测 BLE 设备充电状态";
|
||||
"Discover more BT devices" = "扫描更多常规蓝牙设备";
|
||||
"Discover more BLE devices" = "扫描更多低功耗蓝牙设备";
|
||||
"after 20min" = "20分钟后";
|
||||
"after 40min" = "40分钟后";
|
||||
"min" = "分钟";
|
||||
"Remove Offline Device:" = "移除离线设备:";
|
||||
"after 60min" = "60分钟后";
|
||||
"Remove Offline Device" = "移除离线设备";
|
||||
"Never" = "永不";
|
||||
"Hidden" = "不显示";
|
||||
"AirBattery is not running\nLaunch the app to make the widget work" = "请先启动 AirBattery 主程序以使小组件正常工作";
|
||||
@@ -56,17 +47,12 @@
|
||||
"Batteries" = "电量信息";
|
||||
"Launch at Login" = "登录时启动";
|
||||
"General" = "一般设置";
|
||||
"DockTile" = "程序坞图标";
|
||||
//"Notification" = "充电通知";
|
||||
"Blocklist" = "屏蔽设备";
|
||||
"AirBattery Settings" = "AirBattery 设置";
|
||||
"Hidden Device:" = "已隐藏的设备:";
|
||||
//"StatusBar" = "状态栏图标";
|
||||
"Dynamic Battery Icon" = "动态电池图标";
|
||||
"Show Percentage" = "显示百分比";
|
||||
"Show Percentage on" = "将百分比显示在";
|
||||
"Hide percentage when above" = "高于此电量自动隐藏百分比";
|
||||
"Show Built-in Battery" = "显示此 Mac 的电池";
|
||||
"Reverse Device List" = "颠倒设备列表顺序";
|
||||
"Widget" = "小组件";
|
||||
"No Device Found!" = "未发现任何设备!";
|
||||
@@ -74,9 +60,7 @@
|
||||
"\"%@\" remaining battery %d%%" = "\"%@\" 剩余电量 %d%%";
|
||||
"Fully Charged" = "电池电量充足";
|
||||
"\"%@\" battery has reached %d%%" = "\"%@\" 已充电至 %d%%";
|
||||
//"Notification Sound:" = "播放通知音效:";
|
||||
//"Low Battery Threshold:" = "电量过低阈值:";
|
||||
//"Fully Charged Threshold:" = "充电完成阈值:";
|
||||
"Snooze for 30 minutes" = "半小时后再提醒我";
|
||||
"Select a Device in Preferences" = "请在设置中选择需要显示的设备";
|
||||
"Single Device Widget" = "单设备小组件";
|
||||
"Refresh Interval (min)" = "数据更新间隔 (分钟)";
|
||||
@@ -95,12 +79,9 @@
|
||||
"Automatically download updates" = "自动下载程序更新";
|
||||
"Not Set" = "未指定";
|
||||
"Click Dock icon again to hide this panel" = "再次点击 Dock 图标收起此面板";
|
||||
//"Click to enter the device name" = "点此输入需要屏蔽的设备名称";
|
||||
"Scan your iPhone / iPad / Apple Watch / VisionPro and other iDevices in your local network." = "扫描局域网中所有属于您的 iPhone / iPad / Apple Watch / VisionPro 等设备.";
|
||||
"Scan your iPhone and iPad (Cellular) via Bluetooth." = "尝试通过蓝牙扫描周边属于您的 iPhone 或蜂窝版 iPad";
|
||||
"Read the battery status of the connected Apple Pencil through your iPad\n(It may take 10 minutes or longer to discover the Pencil for the first time)\n\nWARNING: This is a BETA feature and may drain your iPad's battery faster!" = "尝试读取已连接到 iPad 的 Apple Pencil 的电量信息\n(首次可能需要 10 分钟甚至更久才能读取到 Pencil)\n\n请注意: 这是一项测试版功能, 可能会加速 iPad 电池耗尽!";
|
||||
//"Guess if the iPhone / iPad or BLE device found by Bluetooth is charging" = "利用电量变化来推测通过蓝牙发现的 iPhone / iPad 或其他 BLE 设备";
|
||||
//"Get the battery usage of some Bluetooth peripherals (mouse, keyboard, headphone, etc.)\n\nPlease Note: Some devices cannot be listed even though macOS knows their battery usage" = "获取某些受支持的蓝牙设备的电量信息 (鼠标、键盘、耳机等)\n\n请注意: 有些设备无法被列出, 即使你可以在 macOS 内置的小组件中看到它";
|
||||
"Get the battery usage of some Bluetooth peripherals like mouse, keyboard, headphone or etc.\n\nIf some of your device is not shown, try enabling \"Discover more BT devices\" or \"Discover more BLE devices\"" = "获取某些受支持的蓝牙设备的电量信息 (鼠标、键盘、耳机等)\n\n如果部分设备没有显示出来, 请尝试启用\"发现更多常规蓝牙设备\" 或 \"发现更多低功耗蓝牙设备\"";
|
||||
"Get the battery usage of more third-party Bluetooth devices\n\nBattery data will be updated when devices are reconnected to the Mac or the Mac wakes up." = "获取更多第三方常规蓝牙设备的电量信息\n\n\仅当这些设备刚被连接时或 Mac 被唤醒时, 电池数据才会更新.";
|
||||
"Try to get the battery usage of any Bluetooth device that AirBattery can find\n\nWARNING: This is a BETA feature and may cause unexpected errors!" = "尝试扫描周边所有的 BLE 设备, 即使它可能不属于您\n\n请注意: 这是一项测试版功能, 可能会导致未知的错误!";
|
||||
@@ -131,7 +112,6 @@
|
||||
"Nearcast will broadcast your battery data within the local network." = "Nearcast 将会将会在本地局域网中对您的电量数据进行广播";
|
||||
"Your data has been encrypted using the group id, don't share it with others." = "所有被发送的数据内容均已经过加密, 所以请不要将你的小组 ID 交给他人";
|
||||
"Do not add too many Macs to a group, this can be tiring for the router!" = "请不要将太多 Mac 加入同一个 Nearcast 小组, 这可能会加重路由器的负担!";
|
||||
//"Enter text" = "请输入文本";
|
||||
"Add to List" = "添加到列表";
|
||||
"Cancel" = "取消";
|
||||
"Colorful Battery Icon" = "彩色电量图标";
|
||||
@@ -151,7 +131,6 @@
|
||||
"Battery alert for" = "设置电量提醒";
|
||||
"Notify me when battery charged above:" = "当设备充电至高于此电量时发出通知:";
|
||||
"Notify me when battery goes below:" = "当设备放电至低于此电量时发出通知:";
|
||||
"Dock" = "程序坞";
|
||||
"Displaying AirBattery on the Dock will consume more power, it is better to use Menu Bar mode or Widgets." = "在程序坞上显示电池信息会导致能耗增高,\n使用菜单栏模式或小组件可以降低性能占用.";
|
||||
"Inside" = "在图标内部";
|
||||
"Outside" = "在图标外部";
|
||||
@@ -165,15 +144,10 @@
|
||||
"Same as Nearbility" = "与 Nearbility 同步";
|
||||
"Reload" = "重载";
|
||||
"If you see a bluetooth pairing request from any device that isn't yours, add it to your blocklist!" = "如果您看到任何来自不属于您的设备的蓝牙配对请求, 将其加入屏蔽列表就能让它消失.";
|
||||
|
||||
//"Permission Required" = "需要授权";
|
||||
//"Open Settings" = "打开系统设置";
|
||||
"If some of your devices shows battery level in the Bluetooth menu, but AirBattery doesn't find it. Try disconnecting and reconnecting it, and wait a few minutes." = "如果某些设备在系统蓝牙菜单中有电量显示\n但是在 AirBattery 中没有显示出来的话\n请尝试断开然后重新连接它们并等待几分钟";
|
||||
"AirBattery Tips" = "AirBattery 小贴士";
|
||||
"Don't remind me again" = "不再提醒";
|
||||
"Allowlist Mode" = "白名单模式";
|
||||
//"Only the following BLE devices will be connected:" = "AirBattery 仅会尝试读取下列 BLE 设备:";
|
||||
//"The following BLE devices will be ignored:" = "AirBattery 将会忽略下列所有 BLE 设备:";
|
||||
"Only the following devices will be showed" = "AirBattery 仅会显示下列设备";
|
||||
"The following devices will be ignored" = "AirBattery 将会忽略下列设备";
|
||||
|
||||
|
||||
13
AirBattery/zh-Hant.lproj/Credits.rtf
Normal file
@@ -0,0 +1,13 @@
|
||||
{\rtf1\ansi\ansicpg936\cocoartf2822
|
||||
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset134 PingFangSC-Semibold;\f1\fnil\fcharset134 PingFangSC-Regular;}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
{\*\expandedcolortbl;;}
|
||||
\paperw12240\paperh15840\margl1440\margr1440\vieww9000\viewh8400\viewkind0
|
||||
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\partightenfactor0
|
||||
|
||||
\f0\b\fs24 \cf0 \
|
||||
\'d4\'da Mac \'c9\'cf\'ab\'40\'d6\'aa\'c4\'e3\'cb\'f9\'d3\'d0\'d1\'62\'d6\'c3\'b5\'c4\'eb\'8a\'b3\'d8\'d9\'59\'d3\'8d!\
|
||||
|
||||
\f1\b0\fs20 \
|
||||
\'d4\'ad\'ca\'bc\'b4\'61\'d3\'9a\'b9\'dc\'ec\'b6 {\field{\*\fldinst{HYPERLINK "https://github.com/lihaoyun6/AirBattery"}}{\fldrslt Github}}\
|
||||
}
|
||||
9
AirBattery/zh-Hant.lproj/InfoPlist.strings
Normal file
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
InfoPlist.strings
|
||||
AirBattery
|
||||
|
||||
Created by apple on 2024/2/11.
|
||||
|
||||
*/
|
||||
"NSBluetoothAlwaysUsageDescription" = "AirBattery使用藍芽來獲取周邊裝置的電池資訊";
|
||||
"NSLocalNetworkUsageDescription" = "AirBattery會透過區域網絡來獲取周邊裝置的電池資訊";
|
||||
157
AirBattery/zh-Hant.lproj/Localizable.strings
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
Localizable.strings
|
||||
AirBattery
|
||||
|
||||
Created by apple on 2023/9/7.
|
||||
|
||||
*/
|
||||
|
||||
"Appearance" = "圖示外觀";
|
||||
"Automatic" = "自動切換";
|
||||
"Light" = "淺色";
|
||||
"Dark" = "深色";
|
||||
"Settings..." = "偏好設定...";
|
||||
"Until Full:" = "距離充滿:";
|
||||
"Until Empty:" = "可用時長:";
|
||||
"About AirBattery" = "關於 AirBattery";
|
||||
" (Case)" = " (充電盒)";
|
||||
" mins ago" = " 分鐘前";
|
||||
"Percent" = "百分比值";
|
||||
"Device Icon" = "裝置圖示";
|
||||
"Built-in Battery Style" = "內建電池樣式";
|
||||
"Quit AirBattery" = "退出 AirBattery";
|
||||
"Show AirBattery" = "將 AirBattery 置於";
|
||||
"Dock" = "Dock";
|
||||
"Menu Bar" = "選單列";
|
||||
"Both" = "同時顯示";
|
||||
"None" = "隱藏圖示";
|
||||
"Carousel Mode" = "輪播模式";
|
||||
"Discover iOS devices via Network" = "透過區域網掃描 iOS 裝置";
|
||||
"Discover iOS devices via Bluetooth" = "透過藍芽掃描 iOS 裝置";
|
||||
"Apple Pencil from your iPad" = "從 iPad 讀取 Apple Pencil";
|
||||
"Discover BT and BLE devices" = "掃描常規和低功耗藍芽裝置";
|
||||
"Discover more BT devices" = "掃描更多常規藍芽裝置";
|
||||
"Discover more BLE devices" = "掃描更多低功耗藍芽裝置";
|
||||
"after 20min" = "20分鐘後";
|
||||
"after 40min" = "40分鐘後";
|
||||
"after 60min" = "60分鐘後";
|
||||
"Remove Offline Device" = "移除離線裝置";
|
||||
"Never" = "永不";
|
||||
"Hidden" = "不顯示";
|
||||
"AirBattery is not running\nLaunch the app to make the widget work" = "請先啟動 AirBattery 主程式以使小工具正常工作";
|
||||
"AirBattery is not running\nLaunch the app to make\nthe widget work" = "請先啟動 AirBattery 主程式\n以使小工具正常工作";
|
||||
"Displays battery usage for your devices from AirBattery" = "顯示由 AirBattery 收集到的電量資訊";
|
||||
"More ways to displays battery usage for your devices" = "以更多方式展示所有裝置的電量資訊";
|
||||
"Displays battery usage for your devices without percentage" = "以純圖形展示所有裝置的電量資訊";
|
||||
"Displays the battery usage of a specific device" = "顯示某臺特定裝置的電量資訊";
|
||||
"Batteries" = "電量資訊";
|
||||
"Launch at Login" = "登入時啟動";
|
||||
"General" = "一般設定";
|
||||
"Blocklist" = "遮蔽裝置";
|
||||
"AirBattery Settings" = "AirBattery 設定";
|
||||
"Hidden Device:" = "已隱藏的裝置:";
|
||||
"Dynamic Battery Icon" = "動態電池圖示";
|
||||
"Show Percentage" = "顯示百分比";
|
||||
"Hide percentage when above" = "高於此電量自動隱藏百分比";
|
||||
"Reverse Device List" = "顛倒裝置列表順序";
|
||||
"Widget" = "小工具";
|
||||
"No Device Found!" = "未發現任何裝置!";
|
||||
"Low Battery" = "電池電量不足";
|
||||
"\"%@\" remaining battery %d%%" = "\"%@\" 剩餘電量 %d%%";
|
||||
"Fully Charged" = "電池電量充足";
|
||||
"\"%@\" battery has reached %d%%" = "\"%@\" 已充電至 %d%%";
|
||||
"Snooze for 30 minutes" = "半小時後再提醒我";
|
||||
"Select a Device in Preferences" = "請在設定中選擇需要顯示的裝置";
|
||||
"Single Device Widget" = "單裝置小工具";
|
||||
"Refresh Interval (min)" = "資料更新間隔 (分鐘)";
|
||||
"Refresh Interval" = "內容重新整理間隔";
|
||||
"Earbud Merging Threshold" = "立體聲耳塞合併閾值";
|
||||
"Short" = "較短";
|
||||
"Medium" = "中等";
|
||||
"Long" = "較長";
|
||||
"Relaunch Required" = "AirBattery 需要重啟";
|
||||
"Relaunch AirBattery to apply this change" = "手動重啟 AirBattery 以應用此修改";
|
||||
"OK" = "好";
|
||||
"Searching: " = "正在搜尋: ";
|
||||
"Update" = "更新設定";
|
||||
"Check for Updates…" = "檢查程式更新…";
|
||||
"Automatically check for updates" = "自動檢查程式更新";
|
||||
"Automatically download updates" = "自動下載程式更新";
|
||||
"Not Set" = "未指定";
|
||||
"Click Dock icon again to hide this panel" = "再次點選 Dock 圖示收起此面板";
|
||||
"Scan your iPhone / iPad / Apple Watch / VisionPro and other iDevices in your local network." = "掃描區域網中所有屬於您的 iPhone / iPad / Apple Watch / VisionPro 等裝置.";
|
||||
"Scan your iPhone and iPad (Cellular) via Bluetooth." = "嘗試透過藍芽掃描周邊屬於您的 iPhone 或蜂窩版 iPad";
|
||||
"Read the battery status of the connected Apple Pencil through your iPad\n(It may take 10 minutes or longer to discover the Pencil for the first time)\n\nWARNING: This is a BETA feature and may drain your iPad's battery faster!" = "嘗試讀取已連線到 iPad 的 Apple Pencil 的電量資訊\n(首次可能需要 10 分鐘甚至更久才能讀取到 Pencil)\n\n請注意: 這是一項測試版功能, 可能會加速 iPad 電池耗盡!";
|
||||
"Get the battery usage of some Bluetooth peripherals like mouse, keyboard, headphone or etc.\n\nIf some of your device is not shown, try enabling \"Discover more BT devices\" or \"Discover more BLE devices\"" = "獲取某些受支援的藍芽裝置的電量資訊 (滑鼠、鍵盤、耳機等)\n\n如果部分裝置沒有顯示出來, 請嘗試啟用\"發現更多常規藍芽裝置\" 或 \"發現更多低功耗藍芽裝置\"";
|
||||
"Get the battery usage of more third-party Bluetooth devices\n\nBattery data will be updated when devices are reconnected to the Mac or the Mac wakes up." = "獲取更多第三方常規藍芽裝置的電量資訊\n\n\僅當這些裝置剛被連線時或 Mac 被喚醒時, 電池資料才會更新.";
|
||||
"Try to get the battery usage of any Bluetooth device that AirBattery can find\n\nWARNING: This is a BETA feature and may cause unexpected errors!" = "嘗試掃描周邊所有的 BLE 裝置, 即使它可能不屬於您\n\n請注意: 這是一項測試版功能, 可能會導致未知的錯誤!";
|
||||
"Show or hide this Mac's built-in battery in the Dock icon" = "在 Dock 圖示中顯示此 Mac 的內建電池, 或將其從 Dock 圖示上隱藏";
|
||||
"Cycle through all found devices in the Dock icon" = "在 Dock 圖示中迴圈顯示所有已發現的裝置";
|
||||
"If the difference in battery usage between the left and right earbuds is less than this value, AirBattery will show them as one device." = "若一副立體聲耳機的左右兩側的電量差距小於此值, AirBattery 會將它們合併顯示為一個裝置.";
|
||||
"System Default" = "跟隨系統預設";
|
||||
"System Default: Determined by macOS\n\nNearbility: Same as Nearbility setting" = "跟隨系統預設: 由 macOS 決定小工具何時更新\n\nNearbility: 與 Nearbility 更新頻率保持一致";
|
||||
"AirBattery battery usage widget" = "AirBattery 電量小工具";
|
||||
"Configuration" = "組態設定";
|
||||
"Enter Device Name" = "請輸入裝置名稱";
|
||||
"Right click to configure" = "右鍵單擊以配置此小工具";
|
||||
"Device Name Copied" = "裝置名複製成功";
|
||||
"Device name \"%@\" has been copied to the clipboard." = "裝置名 \"%@\" 已成功複製至剪貼簿";
|
||||
"Copy" = "複製";
|
||||
"Group ID Copied" = "小組 ID 複製成功";
|
||||
"Group ID has been copied to the clipboard." = "小組 ID 已成功複製至剪貼簿";
|
||||
"Reload All Widgets" = "重新整理所有小工具";
|
||||
"Default" = "預設";
|
||||
"Custom" = "自定義";
|
||||
"Enable Nearcast" = "啟用 Nearcast";
|
||||
"Group ID" = "小組 ID";
|
||||
"Invalid group ID" = "無效的小組 ID";
|
||||
"New" = "新建";
|
||||
"Group ID Copied" = "小組 ID 已複製";
|
||||
"Please create or enter a valid Group ID before use!" = "使用前請先建立或輸入一個有效的小組 ID";
|
||||
"Group ID copied. Please enter it on your other Mac to join this group." = "小組 ID 已複製到剪貼簿, 請在您的其他 Mac 上輸入它以加入此 Nearcast 小組";
|
||||
"Nearcast will broadcast your battery data within the local network." = "Nearcast 將會將會在本地區域網中對您的電量資料進行廣播";
|
||||
"Your data has been encrypted using the group id, don't share it with others." = "所有被髮送的資料內容均已經過加密, 所以請不要將你的小組 ID 交給他人";
|
||||
"Do not add too many Macs to a group, this can be tiring for the router!" = "請不要將太多 Mac 加入同一個 Nearcast 小組, 這可能會加重路由器的負擔!";
|
||||
"Add to List" = "新增到列表";
|
||||
"Cancel" = "取消";
|
||||
"Colorful Battery Icon" = "彩色電量圖示";
|
||||
"Transmit to..." = "將裝置傳送至...";
|
||||
"Transmitting" = "正在傳送裝置";
|
||||
"Transmission Failed" = "傳送裝置失敗";
|
||||
"Failed to disconnect %@!" = "無法斷開與 \"%@\" 的連線!";
|
||||
"No Available Peers" = "沒有可用的接收端";
|
||||
"Unknown Command" = "未知命令";
|
||||
"doesn't support command \"%@\"" = "不支援 \"%@\" 命令!";
|
||||
"Device Connected" = "裝置已連線";
|
||||
"%@ from %@" = "%@, 來自: %@";
|
||||
"Connection Failed" = "連線失敗";
|
||||
"cannot connect to your device!" = "無法連線指定的裝置!";
|
||||
"Save" = "儲存";
|
||||
"Delete" = "刪除";
|
||||
"Battery alert for" = "設定電量提醒";
|
||||
"Notify me when battery charged above:" = "當裝置充電至高於此電量時發出通知:";
|
||||
"Notify me when battery goes below:" = "當裝置放電至低於此電量時發出通知:";
|
||||
"Displaying AirBattery on the Dock will consume more power, it is better to use Menu Bar mode or Widgets." = "在 Dock 上顯示電池資訊會導致能耗增高,\n使用選單列模式或小工具可以降低效能佔用.";
|
||||
"Inside" = "在圖示內部";
|
||||
"Outside" = "在圖示外部";
|
||||
"Battery Icon Style" = "電池圖示樣式";
|
||||
"Menu Bar & Dock" = "選單列 & Dock";
|
||||
"Startup" = "啟動設定";
|
||||
"Scanner" = "掃描設定";
|
||||
"Others" = "其他設定";
|
||||
"Peer Info" = "節點資訊";
|
||||
"Local ID" = "本機 ID";
|
||||
"Same as Nearbility" = "與 Nearbility 同步";
|
||||
"Reload" = "過載";
|
||||
"If you see a bluetooth pairing request from any device that isn't yours, add it to your blocklist!" = "如果您看到任何來自不屬於您的裝置的藍芽配對請求, 將其加入遮蔽列表就能讓它消失.";
|
||||
"If some of your devices shows battery level in the Bluetooth menu, but AirBattery doesn't find it. Try disconnecting and reconnecting it, and wait a few minutes." = "如果某些裝置在系統藍芽選單中有電量顯示\n但是在 AirBattery 中沒有顯示出來的話\n請嘗試斷開然後重新連線它們並等待幾分鐘";
|
||||
"AirBattery Tips" = "AirBattery Tips";
|
||||
"Don't remind me again" = "不再提醒";
|
||||
"Allowlist Mode" = "白名單模式";
|
||||
"Only the following devices will be showed" = "AirBattery 僅會顯示下列裝置";
|
||||
"The following devices will be ignored" = "AirBattery 將會忽略下列裝置";
|
||||
|
||||
"Command Line Tool" = "命令列工具";
|
||||
"Uninstall" = "解除安裝";
|
||||
"Install" = "安裝";
|
||||
"After installation, you can run \"airbattery\" in yor terminal to list all devices." = "安裝此工具後, 在命令列中執行\"airbattery\"即可列出所有裝置.";
|
||||