mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-29 08:04:32 +00:00
Merge pull request #298 from Ebullioscopic/bugfix/applemusic
Partial Resolution for Apple Music and Click Open Issues
This commit is contained in:
commit
d7d1d9df83
4 changed files with 115 additions and 35 deletions
|
|
@ -126,6 +126,7 @@ struct ContentView: View {
|
||||||
@State private var hoverTask: Task<Void, Never>?
|
@State private var hoverTask: Task<Void, Never>?
|
||||||
@State private var isHovering: Bool = false
|
@State private var isHovering: Bool = false
|
||||||
@State private var lastHapticTime: Date = Date()
|
@State private var lastHapticTime: Date = Date()
|
||||||
|
@State private var hoverClickMonitor: Any?
|
||||||
|
|
||||||
@State private var gestureProgress: CGFloat = .zero
|
@State private var gestureProgress: CGFloat = .zero
|
||||||
@State private var skipGestureActiveDirection: MusicManager.SkipDirection?
|
@State private var skipGestureActiveDirection: MusicManager.SkipDirection?
|
||||||
|
|
@ -271,6 +272,7 @@ struct ContentView: View {
|
||||||
}
|
}
|
||||||
.conditionalModifier(interactionsEnabled) { view in
|
.conditionalModifier(interactionsEnabled) { view in
|
||||||
view
|
view
|
||||||
|
.contentShape(currentNotchShape)
|
||||||
.onHover { hovering in
|
.onHover { hovering in
|
||||||
handleHover(hovering)
|
handleHover(hovering)
|
||||||
}
|
}
|
||||||
|
|
@ -389,12 +391,13 @@ struct ContentView: View {
|
||||||
// #endif
|
// #endif
|
||||||
// .keyboardShortcut("E", modifiers: .command)
|
// .keyboardShortcut("E", modifiers: .command)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
.frame(
|
.frame(
|
||||||
maxWidth: dynamicNotchSize.width,
|
maxWidth: dynamicNotchSize.width,
|
||||||
maxHeight: dynamicNotchSize.height + currentShadowPadding,
|
maxHeight: dynamicNotchSize.height + currentShadowPadding,
|
||||||
alignment: .top
|
alignment: .top
|
||||||
)
|
)
|
||||||
.environmentObject(privacyManager)
|
.environmentObject(privacyManager)
|
||||||
.onChange(of: dynamicNotchSize) { oldSize, newSize in
|
.onChange(of: dynamicNotchSize) { oldSize, newSize in
|
||||||
guard oldSize != newSize else { return }
|
guard oldSize != newSize else { return }
|
||||||
|
|
@ -424,6 +427,7 @@ struct ContentView: View {
|
||||||
releaseMusicControlWindowUpdates(after: musicControlResumeDelay)
|
releaseMusicControlWindowUpdates(after: musicControlResumeDelay)
|
||||||
enqueueMusicControlWindowSync(forceRefresh: true, delay: 0.05)
|
enqueueMusicControlWindowSync(forceRefresh: true, delay: 0.05)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
.onChange(of: musicControlWindowEnabled) { _, enabled in
|
.onChange(of: musicControlWindowEnabled) { _, enabled in
|
||||||
if enabled {
|
if enabled {
|
||||||
|
|
@ -502,6 +506,7 @@ struct ContentView: View {
|
||||||
}
|
}
|
||||||
.onDisappear {
|
.onDisappear {
|
||||||
hoverTask?.cancel()
|
hoverTask?.cancel()
|
||||||
|
stopHoverClickMonitor()
|
||||||
cancelMusicControlWindowSync()
|
cancelMusicControlWindowSync()
|
||||||
hideMusicControlWindow()
|
hideMusicControlWindow()
|
||||||
cancelMusicControlVisibilityTimer()
|
cancelMusicControlVisibilityTimer()
|
||||||
|
|
@ -1430,12 +1435,40 @@ struct ContentView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func startHoverClickMonitor() {
|
||||||
|
guard hoverClickMonitor == nil else { return }
|
||||||
|
hoverClickMonitor = NSEvent.addGlobalMonitorForEvents(matching: [.leftMouseDown]) { _ in
|
||||||
|
Task { @MainActor in
|
||||||
|
guard !lockScreenManager.isLocked else { return }
|
||||||
|
guard vm.notchState == .closed else { return }
|
||||||
|
guard isHovering else { return }
|
||||||
|
if Defaults[.enableHaptics] {
|
||||||
|
triggerHapticIfAllowed()
|
||||||
|
}
|
||||||
|
openNotch()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func stopHoverClickMonitor() {
|
||||||
|
if let hoverClickMonitor {
|
||||||
|
NSEvent.removeMonitor(hoverClickMonitor)
|
||||||
|
self.hoverClickMonitor = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Hover Management
|
// MARK: - Hover Management
|
||||||
|
|
||||||
/// Handle hover state changes with debouncing
|
/// Handle hover state changes with debouncing
|
||||||
private func handleHover(_ hovering: Bool) {
|
private func handleHover(_ hovering: Bool) {
|
||||||
hoverTask?.cancel()
|
hoverTask?.cancel()
|
||||||
|
|
||||||
|
if hovering {
|
||||||
|
startHoverClickMonitor()
|
||||||
|
} else {
|
||||||
|
stopHoverClickMonitor()
|
||||||
|
}
|
||||||
|
|
||||||
if hovering {
|
if hovering {
|
||||||
withAnimation(.bouncy.speed(1.2)) {
|
withAnimation(.bouncy.speed(1.2)) {
|
||||||
isHovering = true
|
isHovering = true
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,12 @@ struct DynamicNotchApp: App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final class FirstMouseHostingView<Content: View>: NSHostingView<Content> {
|
||||||
|
override func acceptsFirstMouse(for event: NSEvent?) -> Bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension AppDelegate {
|
extension AppDelegate {
|
||||||
static var shared: AppDelegate? {
|
static var shared: AppDelegate? {
|
||||||
NSApplication.shared.delegate as? AppDelegate
|
NSApplication.shared.delegate as? AppDelegate
|
||||||
|
|
@ -223,7 +229,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
|
|
||||||
window.animationBehavior = .none
|
window.animationBehavior = .none
|
||||||
|
|
||||||
window.contentView = NSHostingView(
|
window.contentView = FirstMouseHostingView(
|
||||||
rootView: ContentView()
|
rootView: ContentView()
|
||||||
.environmentObject(viewModel)
|
.environmentObject(viewModel)
|
||||||
.environmentObject(webcamManager)
|
.environmentObject(webcamManager)
|
||||||
|
|
|
||||||
|
|
@ -145,38 +145,78 @@ class AppleMusicController: MediaControllerProtocol {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func fetchPlaybackInfoAsync() async throws -> NSAppleEventDescriptor? {
|
private func fetchPlaybackInfoAsync() async throws -> NSAppleEventDescriptor? {
|
||||||
let script = """
|
if #available(macOS 26.0, *) {
|
||||||
tell application "Music"
|
let script = """
|
||||||
set isRunning to true
|
tell application "Music"
|
||||||
try
|
|
||||||
set playerState to player state is playing
|
|
||||||
set currentTrackName to name of current track
|
|
||||||
set currentTrackArtist to artist of current track
|
|
||||||
set currentTrackAlbum to album of current track
|
|
||||||
set trackPosition to player position
|
|
||||||
set trackDuration to duration of current track
|
|
||||||
set shuffleState to shuffle enabled
|
|
||||||
set repeatState to song repeat
|
|
||||||
if repeatState is off then
|
|
||||||
set repeatValue to 1
|
|
||||||
else if repeatState is one then
|
|
||||||
set repeatValue to 2
|
|
||||||
else if repeatState is all then
|
|
||||||
set repeatValue to 3
|
|
||||||
end if
|
|
||||||
|
|
||||||
try
|
try
|
||||||
set artData to data of artwork 1 of current track
|
set playerState to player state is playing
|
||||||
on error
|
set currentTrackName to name of current track
|
||||||
set artData to ""
|
set currentTrackArtist to artist of current track
|
||||||
end try
|
set currentTrackAlbum to album of current track
|
||||||
return {playerState, currentTrackName, currentTrackArtist, currentTrackAlbum, trackPosition, trackDuration, shuffleState, repeatValue, artData}
|
set trackPosition to player position
|
||||||
on error
|
set trackDuration to duration of current track
|
||||||
return {false, "Not Playing", "Unknown", "Unknown", 0, 0, false, 0, ""}
|
set shuffleState to shuffle enabled
|
||||||
end try
|
set repeatState to song repeat
|
||||||
end tell
|
if repeatState is off then
|
||||||
"""
|
set repeatValue to 1
|
||||||
|
else if repeatState is one then
|
||||||
|
set repeatValue to 2
|
||||||
|
else if repeatState is all then
|
||||||
|
set repeatValue to 3
|
||||||
|
end if
|
||||||
|
|
||||||
return try await AppleScriptHelper.execute(script)
|
set artData to ""
|
||||||
|
try
|
||||||
|
set libraryTrack to first track of playlist "Library" whose name is currentTrackName and artist is currentTrackArtist
|
||||||
|
set artData to data of artwork 1 of libraryTrack
|
||||||
|
on error
|
||||||
|
try
|
||||||
|
set artData to data of artwork 1 of current track
|
||||||
|
on error
|
||||||
|
set artData to ""
|
||||||
|
end try
|
||||||
|
end try
|
||||||
|
|
||||||
|
return {playerState, currentTrackName, currentTrackArtist, currentTrackAlbum, trackPosition, trackDuration, shuffleState, repeatValue, artData}
|
||||||
|
on error
|
||||||
|
return {false, "Not Playing", "Unknown", "Unknown", 0, 0, false, 0, ""}
|
||||||
|
end try
|
||||||
|
end tell
|
||||||
|
"""
|
||||||
|
return try await AppleScriptHelper.execute(script)
|
||||||
|
} else {
|
||||||
|
let script = """
|
||||||
|
tell application "Music"
|
||||||
|
set isRunning to true
|
||||||
|
try
|
||||||
|
set playerState to player state is playing
|
||||||
|
set currentTrackName to name of current track
|
||||||
|
set currentTrackArtist to artist of current track
|
||||||
|
set currentTrackAlbum to album of current track
|
||||||
|
set trackPosition to player position
|
||||||
|
set trackDuration to duration of current track
|
||||||
|
set shuffleState to shuffle enabled
|
||||||
|
set repeatState to song repeat
|
||||||
|
if repeatState is off then
|
||||||
|
set repeatValue to 1
|
||||||
|
else if repeatState is one then
|
||||||
|
set repeatValue to 2
|
||||||
|
else if repeatState is all then
|
||||||
|
set repeatValue to 3
|
||||||
|
end if
|
||||||
|
|
||||||
|
try
|
||||||
|
set artData to data of artwork 1 of current track
|
||||||
|
on error
|
||||||
|
set artData to ""
|
||||||
|
end try
|
||||||
|
return {playerState, currentTrackName, currentTrackArtist, currentTrackAlbum, trackPosition, trackDuration, shuffleState, repeatValue, artData}
|
||||||
|
on error
|
||||||
|
return {false, "Not Playing", "Unknown", "Unknown", 0, 0, false, 0, ""}
|
||||||
|
end try
|
||||||
|
end tell
|
||||||
|
"""
|
||||||
|
return try await AppleScriptHelper.execute(script)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,4 +64,5 @@ class DynamicIslandWindow: NSPanel {
|
||||||
override var canBecomeMain: Bool {
|
override var canBecomeMain: Bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue