Changes applied: Still fucked but working

This commit is contained in:
Hariharan Mudaliar 2025-10-06 00:07:02 +05:30
commit 310dde6573
8 changed files with 18739 additions and 1538 deletions

View file

@ -355,7 +355,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = DynamicIsland/DynamicIsland.entitlements; CODE_SIGN_ENTITLEMENTS = DynamicIsland/DynamicIsland.entitlements;
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
@ -397,7 +397,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = DynamicIsland/DynamicIsland.entitlements; CODE_SIGN_ENTITLEMENTS = DynamicIsland/DynamicIsland.entitlements;
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -71,35 +71,28 @@ class SettingsWindowController: NSWindowController {
} }
func showWindow() { func showWindow() {
// Set app to regular mode first // Ensure window exists
NSApp.setActivationPolicy(.regular) _ = window
// If window is already visible, bring it to front properly // If window is already visible, bring it to front properly
if window?.isVisible == true { if window?.isVisible == true {
forceWindowToFront() NSApp.activate(ignoringOtherApps: true)
window?.orderFrontRegardless()
window?.makeKeyAndOrderFront(nil)
return return
} }
// Show the window with proper ordering // Show the window with proper ordering
window?.center()
forceWindowToFront()
}
private func forceWindowToFront() {
// Multi-step approach to ensure window gets focus
window?.orderFrontRegardless() window?.orderFrontRegardless()
window?.makeKeyAndOrderFront(nil) window?.makeKeyAndOrderFront(nil)
window?.center()
// Activate the app with maximum priority // Activate the app and ensure window gets focus
NSApp.activate(ignoringOtherApps: true) NSApp.activate(ignoringOtherApps: true)
// Double-check after a brief delay // Force window to front after activation
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in DispatchQueue.main.async { [weak self] in
guard let window = self?.window else { return } self?.window?.makeKeyAndOrderFront(nil)
if !window.isKeyWindow {
window.makeKeyAndOrderFront(nil)
NSApp.activate(ignoringOtherApps: true)
}
} }
} }

View file

@ -5,97 +5,107 @@
// Created by Richard Kunkli on 21/08/2024. // Created by Richard Kunkli on 21/08/2024.
// //
import SwiftUI
import AppKit import AppKit
import SwiftUI
extension View {
func panGesture(direction: PanDirection, action: @escaping (CGFloat, NSEvent.Phase) -> Void) -> some View {
background(
PanGestureView(direction: direction, action: action)
.frame(maxWidth: 0, maxHeight: 0)
)
}
}
struct PanGestureView: NSViewRepresentable {
let direction: PanDirection
let action: (CGFloat, NSEvent.Phase) -> Void
func makeNSView(context: Context) -> NSView {
let view = NSView()
NSEvent.addLocalMonitorForEvents(matching: [.scrollWheel]) { event in
if event.window == view.window {
context.coordinator.handleEvent(event)
}
return event
}
return view
}
func updateNSView(_ nsView: NSView, context: Context) {
}
func makeCoordinator() -> Coordinator {
Coordinator(direction: direction, action: action)
}
class Coordinator: NSObject {
let direction: PanDirection
let action: (CGFloat, NSEvent.Phase) -> Void
var accumulatedScrollDeltaX: CGFloat = 0
var accumulatedScrollDeltaY: CGFloat = 0
init(direction: PanDirection, action: @escaping (CGFloat, NSEvent.Phase) -> Void) {
self.direction = direction
self.action = action
}
@objc func handleEvent(_ event: NSEvent) {
if event.type == .scrollWheel {
accumulatedScrollDeltaX += event.scrollingDeltaX
accumulatedScrollDeltaY += event.scrollingDeltaY
switch direction {
case .down:
if accumulatedScrollDeltaY > 0 {
handle()
}
case .up:
if accumulatedScrollDeltaY < 0 {
handle()
}
case .left:
if accumulatedScrollDeltaX < 0 {
handle()
}
case .right:
if accumulatedScrollDeltaX > 0 {
handle()
}
}
func handle() {
if (direction == .left || direction == .right) {
action(abs(accumulatedScrollDeltaX), event.phase)
} else {
action(abs(accumulatedScrollDeltaY), event.phase)
}
}
if event.phase == .ended {
accumulatedScrollDeltaY = 0
accumulatedScrollDeltaX = 0
}
}
}
}
}
enum PanDirection { enum PanDirection {
case left case left, right, up, down
case right
case up var isHorizontal: Bool { self == .left || self == .right }
case down var sign: CGFloat { (self == .right || self == .down) ? 1 : -1 }
func signed(from translation: CGSize) -> CGFloat { (isHorizontal ? translation.width : translation.height) * sign }
func signed(deltaX: CGFloat, deltaY: CGFloat) -> CGFloat { (isHorizontal ? deltaX : deltaY) * sign }
}
extension View {
func panGesture(direction: PanDirection, threshold: CGFloat = 4, action: @escaping (CGFloat, NSEvent.Phase) -> Void) -> some View {
self
.gesture(
DragGesture(minimumDistance: 0)
.onChanged { value in
let s = direction.signed(from: value.translation)
guard s > 0, s.magnitude >= threshold else { return }
action(s.magnitude, .changed)
}
.onEnded { _ in action(0, .ended) }
)
.background(ScrollMonitor(direction: direction, threshold: threshold, action: action))
}
}
private struct ScrollMonitor: NSViewRepresentable {
let direction: PanDirection
let threshold: CGFloat
let action: (CGFloat, NSEvent.Phase) -> Void
func makeNSView(context: Context) -> NSView {
let view = NSView()
context.coordinator.installMonitor(on: view)
return view
}
func updateNSView(_ nsView: NSView, context: Context) {}
static func dismantleNSView(_ nsView: NSView, coordinator: Coordinator) { coordinator.removeMonitor() }
func makeCoordinator() -> Coordinator {
Coordinator(direction: direction, threshold: threshold, action: action)
}
@MainActor final class Coordinator: NSObject {
private let direction: PanDirection
private let threshold: CGFloat
private let action: (CGFloat, NSEvent.Phase) -> Void
private var monitor: Any?
private var accumulated: CGFloat = 0
private var active = false
private let noiseThreshold: CGFloat = 0.2
init(direction: PanDirection, threshold: CGFloat, action: @escaping (CGFloat, NSEvent.Phase) -> Void) {
self.direction = direction
self.threshold = threshold
self.action = action
}
func installMonitor(on view: NSView) {
removeMonitor()
monitor = NSEvent.addLocalMonitorForEvents(matching: [.scrollWheel]) { [weak self, weak view] event in
guard let self = self, event.window === view?.window else { return event }
self.handleScroll(event)
return event
}
}
func removeMonitor() {
if let monitor = monitor {
NSEvent.removeMonitor(monitor)
self.monitor = nil
}
accumulated = 0
active = false
}
private func handleScroll(_ event: NSEvent) {
if event.phase == .ended || event.momentumPhase == .ended {
if active {
action(accumulated.magnitude, .ended)
} else {
action(0, .ended)
}
active = false
accumulated = 0
return
}
let s = direction.signed(deltaX: event.scrollingDeltaX, deltaY: event.scrollingDeltaY)
guard s.magnitude > noiseThreshold else { return }
accumulated = s > 0 ? accumulated + s : 0
if !active && accumulated >= threshold {
active = true
action(accumulated.magnitude, .began)
} else if active {
action(accumulated.magnitude, .changed)
}
}
}
} }

View file

@ -1,6 +1,6 @@
import Cocoa import Cocoa
class DynamicIslandStatusMenu: NSMenu { class StatusBarMenu: NSMenu {
var statusItem: NSStatusItem! var statusItem: NSStatusItem!
@ -11,7 +11,6 @@ class DynamicIslandStatusMenu: NSMenu {
convenience init() { convenience init() {
self.init(title: "DynamicIsland") self.init(title: "DynamicIsland")
setupStatusItem()
} }
required init(coder: NSCoder) { required init(coder: NSCoder) {
@ -23,22 +22,14 @@ class DynamicIslandStatusMenu: NSMenu {
// Initialize the status item // Initialize the status item
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
// Set the menu bar icon
if let button = statusItem.button { if let button = statusItem.button {
button.image = NSImage(systemSymbolName: "music.note", accessibilityDescription: "DynamicIsland") button.image = NSImage(named: "logo")
button.action = #selector(showMenu)
} }
// Set up the menu // Set up the menu
self.addItem(NSMenuItem(title: "Quit", action: #selector(quitAction), keyEquivalent: "q")) self.addItem(NSMenuItem(title: "Quit", action: #selector(NSApp.terminate(_:)), keyEquivalent: "q"))
statusItem.menu = self statusItem.menu = self
} }
@objc func showMenu() {
// Handle menu show action
}
@objc func quitAction() {
NSApp.terminate(nil)
}
} }

View file

@ -27,3 +27,18 @@ struct PlaybackState {
var lastUpdated: Date = Date.distantPast var lastUpdated: Date = Date.distantPast
var artwork: Data? var artwork: Data?
} }
extension PlaybackState: Equatable {
static func == (lhs: PlaybackState, rhs: PlaybackState) -> Bool {
return lhs.bundleIdentifier == rhs.bundleIdentifier
&& lhs.isPlaying == rhs.isPlaying
&& lhs.title == rhs.title
&& lhs.artist == rhs.artist
&& lhs.album == rhs.album
&& lhs.currentTime == rhs.currentTime
&& lhs.duration == rhs.duration
&& lhs.isShuffled == rhs.isShuffled
&& lhs.repeatMode == rhs.repeatMode
&& lhs.artwork == rhs.artwork
}
}

View file

@ -9,13 +9,12 @@ import Defaults
import MacroVisionKit import MacroVisionKit
import SwiftUI import SwiftUI
@MainActor
class FullscreenMediaDetector: ObservableObject { class FullscreenMediaDetector: ObservableObject {
static let shared = FullscreenMediaDetector() static let shared = FullscreenMediaDetector()
private let detector: MacroVisionKit private let detector: MacroVisionKit
@ObservedObject private var musicManager = MusicManager.shared @ObservedObject private var musicManager = MusicManager.shared
@MainActor @Published private(set) var fullscreenStatus: [String: Bool] = [:]
@Published private(set) var fullscreenStatus: [String: Bool] = [:] private var notificationTask: Task<Void, Never>?
private init() { private init() {
self.detector = MacroVisionKit.shared self.detector = MacroVisionKit.shared
@ -25,17 +24,34 @@ class FullscreenMediaDetector: ObservableObject {
} }
private func setupNotificationObservers() { private func setupNotificationObservers() {
let nc = NSWorkspace.shared.notificationCenter notificationTask = Task { @Sendable [weak self] in
nc.addObserver(self, selector: #selector(handleChange), await withTaskGroup(of: Void.self) { group in
name: NSWorkspace.activeSpaceDidChangeNotification, object: nil) group.addTask {
nc.addObserver(self, selector: #selector(handleChange), let activeSpaceNotifications = NSWorkspace.shared.notificationCenter.notifications(
name: NSApplication.didChangeScreenParametersNotification, object: nil) named: NSWorkspace.activeSpaceDidChangeNotification
)
for await _ in activeSpaceNotifications {
await self?.handleChange()
}
}
group.addTask {
let screenParameterNotifications = NSWorkspace.shared.notificationCenter.notifications(
named: NSApplication.didChangeScreenParametersNotification
)
for await _ in screenParameterNotifications {
await self?.handleChange()
}
}
}
}
} }
@objc private func handleChange() { private func handleChange() async {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { try? await Task.sleep(for: .milliseconds(500))
self.updateFullScreenStatus() self.updateFullScreenStatus()
}
} }
private func updateFullScreenStatus() { private func updateFullScreenStatus() {