fix timer; fix high cpu usage

This commit is contained in:
lihaoyun6
2024-06-13 00:54:31 +08:00
parent f6b2f5f365
commit b6e84d74ad
11 changed files with 78 additions and 79 deletions

View File

@@ -504,7 +504,7 @@
CODE_SIGN_ENTITLEMENTS = AirBatteryHelper/AirBatteryHelper.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 136;
CURRENT_PROJECT_VERSION = 137;
DEVELOPMENT_ASSET_PATHS = "\"AirBatteryHelper/Preview Content\"";
DEVELOPMENT_TEAM = L4T783637F;
ENABLE_HARDENED_RUNTIME = YES;
@@ -519,7 +519,7 @@
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 1.3.6;
MARKETING_VERSION = 1.3.7;
PRODUCT_BUNDLE_IDENTIFIER = com.lihaoyun6.AirBatteryHelper;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
@@ -538,7 +538,7 @@
CODE_SIGN_ENTITLEMENTS = AirBatteryHelper/AirBatteryHelper.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 136;
CURRENT_PROJECT_VERSION = 137;
DEVELOPMENT_ASSET_PATHS = "\"AirBatteryHelper/Preview Content\"";
DEVELOPMENT_TEAM = L4T783637F;
ENABLE_HARDENED_RUNTIME = YES;
@@ -553,7 +553,7 @@
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 1.3.6;
MARKETING_VERSION = 1.3.7;
PRODUCT_BUNDLE_IDENTIFIER = com.lihaoyun6.AirBatteryHelper;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
@@ -690,7 +690,7 @@
CODE_SIGN_ENTITLEMENTS = AirBattery/AirBattery.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 136;
CURRENT_PROJECT_VERSION = 137;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"AirBattery/Preview Content\"";
DEVELOPMENT_TEAM = L4T783637F;
@@ -707,7 +707,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 1.3.6;
MARKETING_VERSION = 1.3.7;
PRODUCT_BUNDLE_IDENTIFIER = com.lihaoyun6.AirBattery;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
@@ -724,7 +724,7 @@
CODE_SIGN_ENTITLEMENTS = AirBattery/AirBattery.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 136;
CURRENT_PROJECT_VERSION = 137;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"AirBattery/Preview Content\"";
DEVELOPMENT_TEAM = L4T783637F;
@@ -741,7 +741,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 1.3.6;
MARKETING_VERSION = 1.3.7;
PRODUCT_BUNDLE_IDENTIFIER = com.lihaoyun6.AirBattery;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
@@ -757,7 +757,7 @@
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_ENTITLEMENTS = widget/widget.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 136;
CURRENT_PROJECT_VERSION = 137;
DEVELOPMENT_TEAM = L4T783637F;
ENABLE_HARDENED_RUNTIME = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -773,7 +773,7 @@
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 1.3.6;
MARKETING_VERSION = 1.3.7;
PRODUCT_BUNDLE_IDENTIFIER = com.lihaoyun6.AirBattery.widget;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
@@ -791,7 +791,7 @@
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_ENTITLEMENTS = widget/widget.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 136;
CURRENT_PROJECT_VERSION = 137;
DEVELOPMENT_TEAM = L4T783637F;
ENABLE_HARDENED_RUNTIME = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -807,7 +807,7 @@
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 1.3.6;
MARKETING_VERSION = 1.3.7;
PRODUCT_BUNDLE_IDENTIFIER = com.lihaoyun6.AirBattery.widget;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;

View File

@@ -34,7 +34,7 @@ struct AirBatteryApp: App {
}
class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
//static let shared = AppDelegate()
static let shared = AppDelegate()
@AppStorage("showOn") var showOn = "both"
@AppStorage("machineType") var machineType = "Mac"
@AppStorage("deviceName") var deviceName = "Mac"
@@ -219,7 +219,13 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
NSApp.dockTile.display()
}
@objc func blank() {}
func setStatusBar(width: Double) {
let iconView = NSHostingView(rootView: mainBatteryView())
iconView.frame = NSRect(x: 0, y: 0, width: width, height: 21.5)
statusBarItem.button?.subviews.removeAll()
statusBarItem.button?.addSubview(iconView)
statusBarItem.button?.frame = iconView.frame
}
/*@objc func statusBarButtonClicked(_ sender: NSStatusBarButton) {
let event = NSApp.currentEvent!
@@ -300,6 +306,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
}
@objc func openSettingPanel() {
dockWindow.orderOut(nil)
NSApp.activate(ignoringOtherApps: true)
if #available(macOS 14, *) {
NSApp.mainMenu?.items.first?.submenu?.item(at: 2)?.performAction()
@@ -308,6 +315,9 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
} else {
NSApp.sendAction(Selector(("showPreferencesWindow:")), to: nil, from: nil)
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
NSApp.windows.first(where: { $0.title == "AirBattery Settings".local })?.level = .floating
}
}
/*func getMenu(fromDock: Bool = false) {

View File

@@ -120,7 +120,7 @@ class BLEBattery: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
func startScan() {
//
let interval = TimeInterval(10.0 * updateInterval)
let interval = TimeInterval(20.0 * updateInterval)
scanTimer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(scan), userInfo: nil, repeats: true)
print(" Start scanning BLE devices...")
//

View File

@@ -14,7 +14,7 @@ class IDeviceBattery {
@AppStorage("updateInterval") var updateInterval = 1.0
func startScan() {
let interval = TimeInterval(10.0 * updateInterval)
let interval = TimeInterval(20.0 * updateInterval)
scanTimer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(scanDevices), userInfo: nil, repeats: true)
print(" Start scanning iDevice devices...")
Thread.detachNewThread {
@@ -41,14 +41,14 @@ class IDeviceBattery {
}
for id in usbDevices {
if let d = AirBatteryModel.getByID(id) {
if (Double(Date().timeIntervalSince1970) - d.lastUpdate) > 50 * updateInterval { writeBatteryInfo(id, "") }
if (Double(Date().timeIntervalSince1970) - d.lastUpdate) > 60 * updateInterval { writeBatteryInfo(id, "") }
} else {
writeBatteryInfo(id, "")
}
}
for id in netDevices {
if let d = AirBatteryModel.getByID(id) {
if (Double(Date().timeIntervalSince1970) - d.lastUpdate) > 50 * updateInterval { writeBatteryInfo(id, "-n") }
if (Double(Date().timeIntervalSince1970) - d.lastUpdate) > 60 * updateInterval { writeBatteryInfo(id, "-n") }
} else {
writeBatteryInfo(id, "-n")
}

View File

@@ -19,7 +19,7 @@ class MagicBattery {
@AppStorage("deviceName") var deviceName = "Mac"
func startScan() {
let interval = TimeInterval(10.0 * updateInterval)
let interval = TimeInterval(60.0 * updateInterval)
scanTimer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(scanDevices), userInfo: nil, repeats: true)
print(" Start scanning Magic devices...")
Thread.detachNewThread {

View File

@@ -9,11 +9,12 @@ import CryptoKit
import SystemConfiguration
import UserNotifications
let dockTimer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
let alertTimer = Timer.publish(every: 300, on: .main, in: .common).autoconnect()
let widgetDataTimer = Timer.publish(every: 25, on: .main, in: .common).autoconnect()
let widgetInterval = UserDefaults.standard.integer(forKey: "widgetInterval")
let updateInterval = UserDefaults.standard.double(forKey: "updateInterval")
let dockTimer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
let alertTimer = Timer.publish(every: 300, on: .main, in: .common).autoconnect()
let widgetDataTimer = Timer.publish(every: TimeInterval(24 * updateInterval), on: .main, in: .common).autoconnect()
let nearCastTimer = Timer.publish(every: TimeInterval(60 * updateInterval + Double(arc4random_uniform(10)) - Double(arc4random_uniform(10))), on: .main, in: .common).autoconnect()
let widgetViewTimer = Timer.publish(every: TimeInterval(60 * (widgetInterval != 0 ? Double(abs(widgetInterval)) : updateInterval)), on: .main, in: .common).autoconnect()
let macList = ["MacBookPro1,1":"macbook.gen1", "MacBookPro1,2":"macbook.gen1", "MacBookPro2,1":"macbook.gen1", "MacBookPro2,2":"macbook.gen1", "MacBookPro3,1":"macbook.gen1", "MacBookPro4,1":"macbook.gen1", "MacBookPro5,1":"macbook.gen1", "MacBookPro5,2":"macbook.gen1", "MacBookPro5,3":"macbook.gen1", "MacBookPro5,4":"macbook.gen1", "MacBookPro5,5":"macbook.gen1", "MacBookPro6,1":"macbook.gen1", "MacBookPro6,2":"macbook.gen1", "MacBookPro7,1":"macbook.gen1", "MacBookPro8,1":"macbook.gen1", "MacBookPro8,2":"macbook.gen1", "MacBookPro8,3":"macbook.gen1", "MacBookPro9,1":"macbook.gen1", "MacBookPro9,2":"macbook.gen1", "MacBookPro10,1":"macbook.gen1", "MacBookPro10,2":"macbook.gen1", "MacBookPro11,1":"macbook.gen1", "MacBookPro11,2":"macbook.gen1", "MacBookPro11,3":"macbook.gen1", "MacBookPro11,4":"macbook.gen1", "MacBookPro11,5":"macbook.gen1", "MacBookPro12,1":"macbook.gen1", "MacBookPro13,1":"macbook.gen1", "MacBookPro13,2":"macbook.gen1", "MacBookPro13,3":"macbook.gen1", "MacBookPro14,1":"macbook.gen1", "MacBookPro14,2":"macbook.gen1", "MacBookPro14,3":"macbook.gen1", "MacBookPro15,1":"macbook.gen1", "MacBookPro15,2":"macbook.gen1", "MacBookPro15,3":"macbook.gen1", "MacBookPro15,4":"macbook.gen1", "MacBookPro16,1":"macbook.gen1", "MacBookPro16,2":"macbook.gen1", "MacBookPro16,3":"macbook.gen1", "MacBookPro16,4":"macbook.gen1", "MacBookPro17,1":"macbook.gen1", "MacBookPro18,1":"macbook", "MacBookPro18,2":"macbook", "MacBookPro18,3":"macbook", "MacBookPro18,4":"macbook", "Mac14,5":"macbook", "Mac14,6":"macbook", "Mac14,7":"macbook.gen1", "Mac14,9":"macbook", "Mac14,10":"macbook", "Mac15,3":"macbook", "Mac15,6":"macbook", "Mac15,7":"macbook", "Mac15,8":"macbook", "Mac15,9":"macbook", "Mac15,10":"macbook", "Mac15,11":"macbook"]

View File

@@ -80,25 +80,17 @@ struct mainBatteryView: View {
}
.compositingGroup()
.onReceive(dockTimer) { t in
func setStatusBar(width: Double) {
let iconView = NSHostingView(rootView: mainBatteryView())
iconView.frame = NSRect(x: 0, y: 0, width: width, height: 21.5)
statusBarItem.button?.subviews.removeAll()
statusBarItem.button?.addSubview(iconView)
statusBarItem.button?.frame = iconView.frame
}
item = InternalBattery.status
let width = statusBarItem.button?.frame.size.width
if statusBarBattPercent {
if hidePercentWhenFull && item.batteryLevel >= 90 {
if width != 42 { setStatusBar(width: 42) }
if width != 42 { AppDelegate.shared.setStatusBar(width: 42) }
} else {
if width != 76 { setStatusBar(width: 76) }
if width != 76 { AppDelegate.shared.setStatusBar(width: 76) }
}
} else {
if width != 42 { setStatusBar(width: 42) }
if width != 42 { AppDelegate.shared.setStatusBar(width: 42) }
}
}
}

View File

@@ -175,7 +175,12 @@ struct MultiBatteryView: View {
}
.frame(width: 128, height: 128, alignment: .center)
.onReceive(alertTimer) {_ in batteryAlert() }
.onReceive(widgetDataTimer) {_ in AirBatteryModel.writeData() }
.onReceive(widgetDataTimer) {_ in
if let result = process(path: "/usr/sbin/system_profiler", arguments: ["SPBluetoothDataType", "-json"]) {
SPBluetoothDataModel.data = result
}
AirBatteryModel.writeData()
}
.onReceive(widgetViewTimer) {_ in if widgetInterval != -1 { WidgetCenter.shared.reloadAllTimelines() }}
.onReceive(nearCastTimer) {_ in
if nearCast && ncGroupID != ""{
@@ -193,37 +198,37 @@ struct MultiBatteryView: View {
}
}
.onReceive(dockTimer) { t in
if showOn == "both" || showOn == "dock" { NSApp.dockTile.display() }
InternalBattery.status = getPowerState()
let windows = NSApplication.shared.windows
for w in windows { if w.level.rawValue == 0 || w.level.rawValue == 3 { w.level = .floating } }
//for w in NSApplication.shared.windows { if w.level.rawValue == 0 || w.level.rawValue == 3 { w.level = .floating } }
if let result = process(path: "/usr/sbin/system_profiler", arguments: ["SPBluetoothDataType", "-json"]) { SPBluetoothDataModel.data = result }
darkMode = getDarkMode()
var list = AirBatteryModel.getAll()
let ibStatus = InternalBattery.status
let now = Double(t.timeIntervalSince1970)
if rollingMode == "off" { rollCount = 1 }
if ibStatus.hasBattery && showThisMac != "hidden" { list.insert(ib2ab(ibStatus), at: 0) }
batteryList = sliceList(data: list, length: 4, count: rollCount)
if batteryList == []{
rollCount = 1
if showOn == "both" || showOn == "dock" {
darkMode = getDarkMode()
var list = AirBatteryModel.getAll()
let ibStatus = InternalBattery.status
let now = Double(t.timeIntervalSince1970)
if rollingMode == "off" { rollCount = 1 }
if ibStatus.hasBattery && showThisMac != "hidden" { list.insert(ib2ab(ibStatus), at: 0) }
batteryList = sliceList(data: list, length: 4, count: rollCount)
}
if now - lastTime >= 20 && (rollingMode == "on" || rollingMode == "auto") {
if rollingMode == "auto" {
if list.count > 4 {
if batteryList == []{
rollCount = 1
batteryList = sliceList(data: list, length: 4, count: rollCount)
}
if now - lastTime >= 20 && (rollingMode == "on" || rollingMode == "auto") {
if rollingMode == "auto" {
if list.count > 4 {
lastTime = now
rollCount = rollCount + 1
}
} else {
lastTime = now
rollCount = rollCount + 1
}
} else {
lastTime = now
rollCount = rollCount + 1
}
NSApp.dockTile.display()
}
}
}
@@ -288,7 +293,7 @@ struct popover: View {
.onHover{ hovering in overQuitButton = hovering }
} else {
Button(action: {
if let window = NSApp.windows.first(where: { $0.title == "AirBattery Dock Window" }) { window.orderOut(nil) }
AppDelegate.shared.dockWindow.orderOut(nil)
}, label: {
Image(systemName: "minus.circle")
.font(.system(size: 14, weight: .light))
@@ -301,8 +306,8 @@ struct popover: View {
}
Button(action: {
if let window = NSApp.windows.first(where: { $0.title == "AirBattery Dock Window" }) { window.orderOut(nil) }
NSApp.orderFrontStandardAboutPanel(nil)
AppDelegate.shared.dockWindow.orderOut(nil)
AppDelegate.shared.openAboutPanel()
}, label: {
Image(systemName: "info.circle")
.font(.system(size: 14, weight: .light))
@@ -314,16 +319,7 @@ struct popover: View {
.onHover{ hovering in overInfoButton = hovering }
Button(action: {
if let window = NSApp.windows.first(where: { $0.title == "AirBattery Dock Window" }) { window.orderOut(nil) }
NSApp.activate(ignoringOtherApps: true)
if #available(macOS 14, *) {
NSApp.mainMenu?.items.first?.submenu?.item(at: 2)?.performAction()
}else if #available(macOS 13, *) {
NSApp.sendAction(Selector(("showSettingsWindow:")), to: nil, from: nil)
} else {
NSApp.sendAction(Selector(("showPreferencesWindow:")), to: nil, from: nil)
}
NSApp.activate(ignoringOtherApps: true)
AppDelegate.shared.openSettingPanel()
}, label: {
Image(systemName: "gearshape")
.font(.system(size: 13.6, weight: .light))

View File

@@ -273,11 +273,11 @@ struct SettingsView: View {
Text("Nearcast will send data in the LAN at the same interval as the Nearbility engine.\nYour data has been encrypted, so please do not tell your Group ID to others.")
.foregroundColor(.secondary)
.multilineTextAlignment(.center)
.opacity(0.5)
.opacity(0.6)
.padding(.top, 10).padding(.bottom, 1)
Text("Do not add too many Macs to a group, this can be tiring for the router!")
.foregroundColor(.orange)
.opacity(0.5)
.opacity(0.7)
}
.navigationTitle("AirBattery Settings")
.tabItem {

View File

@@ -35,11 +35,11 @@ brew install lihaoyun6/tap/airbattery
- If necessary, you can hide certain devices in the Dock menu or status bar menu, and unhide them at any time.
## Q&A
**1. Why isn't my iPhone/iPad displayed?**
> Please make sure the iPhone/iPad has trusted this Mac ***(and connected the Mac with a data cable at least once while AirBattery is running to pair)***. Then just make sure it is on the same LAN as the Mac.
**1. Why is my iPhone / iPad / Apple Watch not showing up?**
> Please make sure the iPhone / iPad has trusted this Mac ***(and connected the Mac with a data cable at least once while AirBattery is running to pair)***. Then just make sure it is on the same LAN as the Mac.
**2. Does my Apple Watch need to be pre-connected?**
> No, when AirBattery detects your iPhone via WiFi or cable, it will automatically read the battery information of the Apple Watch paired with it **(iPhone discovered via Bluetooth does not support reading the watch battery!)**
> No, when AirBattery detects a paired iPhone via WiFi or USB, it will automatically read the battery data of the Apple Watch paired with it **(iPhone discovered via Bluetooth does not support reading the watch battery!)**
**3. Why do some device name have a ⚠️ symbol?**
> If this symbol appears, it means that the device has not updated its battery information for more than ten minutes, and may be offline or turned off.

View File

@@ -35,11 +35,11 @@ brew install lihaoyun6/tap/airbattery
- 如有需要, 可以在 Dock 栏菜单或状态栏菜单中隐藏某些设备, 亦可随时解除隐藏.
## 常见问题
**1. 为什么我的 iPhone/iPad 没有显示?**
> 请确保 iPhone/iPad 已信任此 Mac ***(且至少在 AirBattery 运行状态下使用数据线连接 Mac 一次以进行配对)***. 之后只需确保其与 Mac 处于同一局域网中即可.
**1. 为什么我的 iPhone / iPad / Apple Watch 没有显示出来?**
> 请确保 iPhone / iPad 已信任此 Mac ***(且至少在 AirBattery 运行状态下使用数据线连接 Mac 一次以进行配对)***. 之后只需确保其与 Mac 处于同一局域网中即可.
**2. 我的 Apple Watch 也需要进行预连接吗?**
> 不需要, 一旦 AirBattery 通过 WiFi 或数据线检测到您的 iPhone, 将会自动读取与其配对的 Apple Watch 的电量信息 **(通过蓝牙发现的 iPhone 不支持读取手表电量!)**
> 不需要, 一旦 AirBattery 通过 WiFi 或 USB 发现任何已配对的 iPhone, 将会自动读取与其配对的 Apple Watch 的电量信息 **(通过蓝牙发现的 iPhone 不支持读取手表电量!)**
**3. 为什么某些设备名称前有一个⚠️符号?**
> 出现这个符号, 说明此设备已经超过十分钟以上没有更新过电量信息, 可能已离线或关闭.