BugFix: Multiple object creation

This commit is contained in:
Hariharan Mudaliar 2025-09-06 19:43:40 +05:30
commit f4bcb96906
8 changed files with 202 additions and 33 deletions

View file

@ -112,9 +112,14 @@ class AppDelegate: NSObject, NSApplicationDelegate {
// Cancel any pending window size updates
windowSizeUpdateWorkItem?.cancel()
print("🚪 Application terminating - ensuring system HUD is restored...")
// Re-enable system HUD on app termination
SystemOSDManager.enableSystemHUD()
// Give it time to complete
usleep(500000) // 500ms
NotificationCenter.default.removeObserver(self)
}

View file

@ -14,7 +14,7 @@ struct DynamicIslandHeader: View {
@ObservedObject var batteryModel = BatteryStatusViewModel.shared
@ObservedObject var coordinator = DynamicIslandViewCoordinator.shared
@ObservedObject var clipboardManager = ClipboardManager.shared
@StateObject var tvm = TrayDrop.shared
@ObservedObject var tvm = TrayDrop.shared
@State private var showClipboardPopover = false
@State private var showColorPickerPopover = false

View file

@ -3,7 +3,7 @@ import SwiftUI
struct NotchShelfView: View {
@EnvironmentObject var vm: DynamicIslandViewModel
@StateObject var tvm = TrayDrop.shared
@ObservedObject var tvm = TrayDrop.shared
var body: some View {
HStack {

View file

@ -13,7 +13,7 @@ struct DropItemView: View {
let item: TrayDrop.DropItem
@EnvironmentObject var vm: DynamicIslandViewModel
@ObservedObject var coordinator = DynamicIslandViewCoordinator.shared
@StateObject var tvm = TrayDrop.shared
@ObservedObject var tvm = TrayDrop.shared
@State var hover = false

View file

@ -0,0 +1,83 @@
//
// SystemHUDDebugger.swift
// DynamicIsland
//
// Debug utility for System HUD functionality
// Created by GitHub Copilot on 06/09/25.
//
import Foundation
class SystemHUDDebugger {
/// Test system HUD functionality and print status
public static func testSystemHUD() {
print("\n🔍 === System HUD Debug Report ===")
// Check current OSDUIHelper status
let isRunning = SystemOSDManager.isOSDUIHelperRunning()
print("📊 OSDUIHelper Status: \(isRunning ? "✅ Running" : "❌ Not running")")
// Test disable
print("🔇 Testing disable...")
SystemOSDManager.disableSystemHUD()
// Wait and check
usleep(500000)
let isRunningAfterDisable = SystemOSDManager.isOSDUIHelperRunning()
print("📊 After disable: \(isRunningAfterDisable ? "✅ Running (stopped)" : "❌ Not running")")
// Test enable
print("🔊 Testing re-enable...")
SystemOSDManager.enableSystemHUD()
// Wait and check
usleep(1000000)
let isRunningAfterEnable = SystemOSDManager.isOSDUIHelperRunning()
print("📊 After re-enable: \(isRunningAfterEnable ? "✅ Running" : "❌ Not running")")
print("🔍 === End Debug Report ===\n")
if !isRunningAfterEnable {
print("⚠️ WARNING: System HUD may not be working properly!")
print("💡 Try pressing volume keys to test system HUD functionality")
}
}
/// Force restart OSDUIHelper using multiple methods
public static func forceRestartOSDUIHelper() {
print("🔄 Force restarting OSDUIHelper...")
// Method 1: Kill and kickstart
SystemOSDManager.enableSystemHUD()
// Method 2: Try launchctl bootstrap (more aggressive)
do {
let bootstrap = Process()
bootstrap.executableURL = URL(fileURLWithPath: "/bin/launchctl")
bootstrap.arguments = ["bootstrap", "gui/\(getuid())", "/System/Library/LaunchAgents/com.apple.OSDUIHelper.plist"]
try bootstrap.run()
bootstrap.waitUntilExit()
print("✅ Bootstrap method completed")
} catch {
print("❌ Bootstrap method failed: \(error)")
}
// Method 3: Try direct service restart
do {
let restart = Process()
restart.executableURL = URL(fileURLWithPath: "/bin/launchctl")
restart.arguments = ["restart", "gui/\(getuid())/com.apple.OSDUIHelper"]
try restart.run()
restart.waitUntilExit()
print("✅ Restart method completed")
} catch {
print("❌ Restart method failed: \(error)")
}
// Check final status
usleep(1000000)
let finalStatus = SystemOSDManager.isOSDUIHelperRunning()
print("📊 Final OSDUIHelper status: \(finalStatus ? "✅ Running" : "❌ Not running")")
}
}

View file

@ -10,16 +10,13 @@ import Cocoa
import Foundation
import Defaults
class SystemChangesObserver: ObservableObject {
class SystemChangesObserver {
private var oldVolume: Float
private var oldMuted: Bool
private var oldBrightness: Float = 0
private weak var coordinator: DynamicIslandViewCoordinator?
@Default(.enableSystemHUD) var enableSystemHUD
@Default(.enableVolumeHUD) var enableVolumeHUD
@Default(.enableBrightnessHUD) var enableBrightnessHUD
private var timer: Timer?
init(coordinator: DynamicIslandViewCoordinator) {
self.coordinator = coordinator
@ -34,18 +31,18 @@ class SystemChangesObserver: ObservableObject {
}
func startObserving() {
guard enableSystemHUD else { return }
guard Defaults[.enableSystemHUD] else { return }
createObservers()
createTimerForContinuousChangesCheck(with: 0.2)
}
private func createTimerForContinuousChangesCheck(with seconds: TimeInterval) {
let timer = Timer(
timer = Timer(
timeInterval: seconds, target: self, selector: #selector(checkChanges), userInfo: nil,
repeats: true)
let mainLoop = RunLoop.main
mainLoop.add(timer, forMode: .common)
mainLoop.add(timer!, forMode: .common)
}
private func createObservers() {
@ -63,7 +60,7 @@ class SystemChangesObserver: ObservableObject {
}
@objc func showVolumeHUD() {
guard enableSystemHUD && enableVolumeHUD else { return }
guard Defaults[.enableSystemHUD] && Defaults[.enableVolumeHUD] else { return }
if oldVolume == 0.0 || oldVolume == 1.0 {
sendVolumeNotification(value: oldVolume)
@ -72,7 +69,7 @@ class SystemChangesObserver: ObservableObject {
}
@objc func showBrightnessHUD() {
guard enableSystemHUD && enableBrightnessHUD else { return }
guard Defaults[.enableSystemHUD] && Defaults[.enableBrightnessHUD] else { return }
if oldBrightness == 0.0 || oldBrightness == 1.0 {
sendBrightnessNotification(value: oldBrightness)
@ -81,7 +78,7 @@ class SystemChangesObserver: ObservableObject {
}
@objc func checkChanges() {
guard enableSystemHUD else { return }
guard Defaults[.enableSystemHUD] else { return }
checkBrightnessChanges()
checkVolumeChanges()
@ -93,7 +90,7 @@ class SystemChangesObserver: ObservableObject {
}
private func checkVolumeChanges() {
guard enableVolumeHUD else { return }
guard Defaults[.enableVolumeHUD] else { return }
let newVolume = SystemVolumeManager.getOutputVolume()
let newMuted = SystemVolumeManager.isMuted()
@ -110,7 +107,7 @@ class SystemChangesObserver: ObservableObject {
}
private func checkBrightnessChanges() {
guard enableBrightnessHUD else { return }
guard Defaults[.enableBrightnessHUD] else { return }
if NSScreen.screens.count == 0 {
return
@ -148,6 +145,12 @@ class SystemChangesObserver: ObservableObject {
}
deinit {
stopObserving()
}
func stopObserving() {
timer?.invalidate()
timer = nil
NotificationCenter.default.removeObserver(self)
}
}

View file

@ -7,31 +7,38 @@
import Foundation
import Defaults
import Combine
class SystemHUDManager: ObservableObject {
class SystemHUDManager {
static let shared = SystemHUDManager()
private var changesObserver: SystemChangesObserver?
private weak var coordinator: DynamicIslandViewCoordinator?
@Default(.enableSystemHUD) var enableSystemHUD {
didSet {
Task { @MainActor in
if enableSystemHUD {
await startSystemHUD()
} else {
await stopSystemHUD()
}
}
}
private init() {
// Set up observer for settings changes
setupSettingsObserver()
}
private init() {}
private func setupSettingsObserver() {
// Use Defaults publisher instead of @Default property wrapper
Defaults.publisher(.enableSystemHUD, options: []).sink { [weak self] change in
Task { @MainActor in
if change.newValue {
await self?.startSystemHUD()
} else {
await self?.stopSystemHUD()
}
}
}.store(in: &cancellables)
}
private var cancellables = Set<AnyCancellable>()
func setup(coordinator: DynamicIslandViewCoordinator) {
self.coordinator = coordinator
if enableSystemHUD {
if Defaults[.enableSystemHUD] {
Task { @MainActor in
await startSystemHUD()
}
@ -56,6 +63,7 @@ class SystemHUDManager: ObservableObject {
@MainActor
private func stopSystemHUD() async {
changesObserver?.stopObserving()
changesObserver = nil
// Re-enable system HUD
@ -65,18 +73,36 @@ class SystemHUDManager: ObservableObject {
}
private func disableSystemHUD() {
print("🔇 Disabling system HUD (OSDUIHelper running: \(SystemOSDManager.isOSDUIHelperRunning()))")
// Disable the system HUD using SystemOSDManager
SystemOSDManager.disableSystemHUD()
}
private func enableOriginalSystemHUD() {
print("🔊 Re-enabling system HUD (OSDUIHelper running: \(SystemOSDManager.isOSDUIHelperRunning()))")
// Re-enable the system HUD using SystemOSDManager
SystemOSDManager.enableSystemHUD()
// Verify it's working after a short delay
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
let isRunning = SystemOSDManager.isOSDUIHelperRunning()
print("🔍 OSDUIHelper status after re-enable: \(isRunning ? "✅ Running" : "❌ Not running")")
}
}
deinit {
print("🧹 SystemHUDManager deinitializing - ensuring system HUD is restored")
cancellables.removeAll()
Task { @MainActor in
await stopSystemHUD()
}
// Also call the emergency restore as backup
SystemHUDDebugger.forceRestartOSDUIHelper()
}
/// Emergency restore function - call this if system HUD is not working
public static func emergencyRestoreSystemHUD() {
print("🚨 Emergency system HUD restore initiated")
SystemHUDDebugger.forceRestartOSDUIHelper()
}
}

View file

@ -14,13 +14,41 @@ class SystemOSDManager {
/// Re-enables the system HUD by restarting OSDUIHelper
public static func enableSystemHUD() {
do {
let task = Process()
task.executableURL = URL(fileURLWithPath: "/usr/bin/killall")
task.arguments = ["-9", "OSDUIHelper"]
try task.run()
print("System HUD re-enabled")
// First, stop any existing OSDUIHelper process
let stopTask = Process()
stopTask.executableURL = URL(fileURLWithPath: "/usr/bin/killall")
stopTask.arguments = ["-9", "OSDUIHelper"]
try stopTask.run()
stopTask.waitUntilExit()
// Small delay to ensure process is fully stopped
usleep(200000) // 200ms
// Then kickstart it again to ensure it's running properly
let kickstart = Process()
kickstart.executableURL = URL(fileURLWithPath: "/bin/launchctl")
kickstart.arguments = ["kickstart", "gui/\(getuid())/com.apple.OSDUIHelper"]
try kickstart.run()
kickstart.waitUntilExit()
// Additional delay to ensure service is fully started
usleep(300000) // 300ms
print("✅ System HUD re-enabled")
} catch {
NSLog("Error while trying to re-enable OSDUIHelper. \(error)")
NSLog("❌ Error while trying to re-enable OSDUIHelper: \(error)")
// Fallback: Try to restart the service using launchctl load
do {
let fallbackTask = Process()
fallbackTask.executableURL = URL(fileURLWithPath: "/bin/launchctl")
fallbackTask.arguments = ["load", "-w", "/System/Library/LaunchAgents/com.apple.OSDUIHelper.plist"]
try fallbackTask.run()
fallbackTask.waitUntilExit()
print("✅ System HUD re-enabled via fallback method")
} catch {
NSLog("❌ Fallback method also failed: \(error)")
}
}
}
@ -39,9 +67,33 @@ class SystemOSDManager {
task.executableURL = URL(fileURLWithPath: "/usr/bin/killall")
task.arguments = ["-STOP", "OSDUIHelper"]
try task.run()
print("System HUD disabled")
task.waitUntilExit()
print("✅ System HUD disabled")
} catch {
NSLog("Error while trying to hide OSDUIHelper. Please create an issue on GitHub. Error: \(error)")
NSLog("❌ Error while trying to hide OSDUIHelper: \(error)")
}
}
/// Check if OSDUIHelper is currently running
public static func isOSDUIHelperRunning() -> Bool {
let task = Process()
task.executableURL = URL(fileURLWithPath: "/usr/bin/pgrep")
task.arguments = ["OSDUIHelper"]
let pipe = Pipe()
task.standardOutput = pipe
do {
try task.run()
task.waitUntilExit()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines)
return task.terminationStatus == 0 && !output!.isEmpty
} catch {
return false
}
}
}