mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +00:00
Working button remapping
This commit is contained in:
parent
9f57cc0a38
commit
40bcbb1c7f
6 changed files with 124 additions and 32 deletions
|
|
@ -361,6 +361,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
|
|
||||||
// Migrate legacy progress bar settings
|
// Migrate legacy progress bar settings
|
||||||
Defaults.Keys.migrateProgressBarStyle()
|
Defaults.Keys.migrateProgressBarStyle()
|
||||||
|
Defaults.Keys.migrateMusicAuxControls()
|
||||||
|
|
||||||
// Initialize idle animations (load bundled + built-in face)
|
// Initialize idle animations (load bundled + built-in face)
|
||||||
idleAnimationManager.initializeDefaultAnimations()
|
idleAnimationManager.initializeDefaultAnimations()
|
||||||
|
|
|
||||||
|
|
@ -10497,6 +10497,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Left button" : {
|
||||||
|
"comment" : "A label for a picker that lets the user select a control for the left button on a media player.",
|
||||||
|
"isCommentAutoGenerated" : true
|
||||||
|
},
|
||||||
"License key" : {
|
"License key" : {
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"fr" : {
|
"fr" : {
|
||||||
|
|
@ -15403,10 +15407,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Replace repeat button with media output control" : {
|
|
||||||
"comment" : "A toggle that allows users to replace the repeat button with a media output control.",
|
|
||||||
"isCommentAutoGenerated" : true
|
|
||||||
},
|
|
||||||
"Replaces system HUD notifications with Dynamic Island displays." : {
|
"Replaces system HUD notifications with Dynamic Island displays." : {
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
@ -15582,6 +15582,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Right button" : {
|
||||||
|
"comment" : "A label for the right button in the media controls picker.",
|
||||||
|
"isCommentAutoGenerated" : true
|
||||||
|
},
|
||||||
"Rotation:" : {
|
"Rotation:" : {
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"fr" : {
|
"fr" : {
|
||||||
|
|
@ -16791,6 +16795,10 @@
|
||||||
},
|
},
|
||||||
"Show floating pause/stop controls" : {
|
"Show floating pause/stop controls" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Show media output control in other layouts" : {
|
||||||
|
"comment" : "A toggle that lets the user enable or disable the media output control in layouts other than the home screen.",
|
||||||
|
"isCommentAutoGenerated" : true
|
||||||
},
|
},
|
||||||
"Show on a specific display" : {
|
"Show on a specific display" : {
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,8 @@ import AppKit
|
||||||
struct MinimalisticMusicPlayerView: View {
|
struct MinimalisticMusicPlayerView: View {
|
||||||
@EnvironmentObject var vm: DynamicIslandViewModel
|
@EnvironmentObject var vm: DynamicIslandViewModel
|
||||||
let albumArtNamespace: Namespace.ID
|
let albumArtNamespace: Namespace.ID
|
||||||
@Default(.showMediaOutputControl) var showMediaOutputControl
|
@Default(.musicAuxLeftControl) private var leftAuxControl
|
||||||
|
@Default(.musicAuxRightControl) private var rightAuxControl
|
||||||
@ObservedObject private var reminderManager = ReminderLiveActivityManager.shared
|
@ObservedObject private var reminderManager = ReminderLiveActivityManager.shared
|
||||||
@Default(.enableReminderLiveActivity) private var enableReminderLiveActivity
|
@Default(.enableReminderLiveActivity) private var enableReminderLiveActivity
|
||||||
@Default(.enableLyrics) private var enableLyrics
|
@Default(.enableLyrics) private var enableLyrics
|
||||||
|
|
@ -601,9 +602,7 @@ private struct MinimalisticReminderDetailsView: View {
|
||||||
private var playbackControls: some View {
|
private var playbackControls: some View {
|
||||||
HStack(spacing: 16) {
|
HStack(spacing: 16) {
|
||||||
if Defaults[.showShuffleAndRepeat] {
|
if Defaults[.showShuffleAndRepeat] {
|
||||||
controlButton(icon: "shuffle", isActive: musicManager.isShuffled) {
|
auxButton(for: leftAuxControl)
|
||||||
Task { await musicManager.toggleShuffle() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
controlButton(icon: "backward.fill", size: 18) {
|
controlButton(icon: "backward.fill", size: 18) {
|
||||||
|
|
@ -616,16 +615,8 @@ private struct MinimalisticReminderDetailsView: View {
|
||||||
Task { await musicManager.nextTrack() }
|
Task { await musicManager.nextTrack() }
|
||||||
}
|
}
|
||||||
|
|
||||||
// (lyrics toggle removed from UI; controlled via Settings -> Media -> Enable Lyrics)
|
|
||||||
|
|
||||||
if Defaults[.showShuffleAndRepeat] {
|
if Defaults[.showShuffleAndRepeat] {
|
||||||
if showMediaOutputControl {
|
auxButton(for: rightAuxControl)
|
||||||
MinimalisticMediaOutputButton()
|
|
||||||
} else {
|
|
||||||
controlButton(icon: repeatIcon, isActive: musicManager.repeatMode != .off) {
|
|
||||||
Task { await musicManager.toggleRepeat() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity, alignment: .center)
|
.frame(maxWidth: .infinity, alignment: .center)
|
||||||
|
|
@ -657,6 +648,26 @@ private struct MinimalisticReminderDetailsView: View {
|
||||||
action: action
|
action: action
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
private func auxButton(for control: MusicAuxiliaryControl) -> some View {
|
||||||
|
switch control {
|
||||||
|
case .shuffle:
|
||||||
|
controlButton(icon: "shuffle", isActive: musicManager.isShuffled) {
|
||||||
|
Task { await musicManager.toggleShuffle() }
|
||||||
|
}
|
||||||
|
case .repeatMode:
|
||||||
|
controlButton(icon: repeatIcon, isActive: musicManager.repeatMode != .off) {
|
||||||
|
Task { await musicManager.toggleRepeat() }
|
||||||
|
}
|
||||||
|
case .mediaOutput:
|
||||||
|
MinimalisticMediaOutputButton()
|
||||||
|
case .lyrics:
|
||||||
|
controlButton(icon: enableLyrics ? "quote.bubble.fill" : "quote.bubble", isActive: enableLyrics) {
|
||||||
|
enableLyrics.toggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
private struct MinimalisticMediaOutputButton: View {
|
private struct MinimalisticMediaOutputButton: View {
|
||||||
@ObservedObject private var routeManager = AudioRouteManager.shared
|
@ObservedObject private var routeManager = AudioRouteManager.shared
|
||||||
@StateObject private var volumeModel = MediaOutputVolumeViewModel()
|
@StateObject private var volumeModel = MediaOutputVolumeViewModel()
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,9 @@ struct MusicControlsView: View {
|
||||||
@State private var dragging: Bool = false
|
@State private var dragging: Bool = false
|
||||||
@State private var lastDragged: Date = .distantPast
|
@State private var lastDragged: Date = .distantPast
|
||||||
let showShuffleAndRepeat: Bool
|
let showShuffleAndRepeat: Bool
|
||||||
@Default(.showMediaOutputControl) private var showMediaOutputControl
|
@Default(.musicAuxLeftControl) private var leftAuxControl
|
||||||
|
@Default(.musicAuxRightControl) private var rightAuxControl
|
||||||
|
@Default(.enableLyrics) private var enableLyrics
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
|
|
@ -213,12 +215,7 @@ struct MusicControlsView: View {
|
||||||
private var playbackControls: some View {
|
private var playbackControls: some View {
|
||||||
HStack(spacing: 8) {
|
HStack(spacing: 8) {
|
||||||
if showShuffleAndRepeat {
|
if showShuffleAndRepeat {
|
||||||
HoverButton(
|
auxButton(for: leftAuxControl)
|
||||||
icon: "shuffle", iconColor: musicManager.isShuffled ? .red : .white,
|
|
||||||
scale: .medium
|
|
||||||
) {
|
|
||||||
MusicManager.shared.toggleShuffle()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
HoverButton(icon: "backward.fill", scale: .medium) {
|
HoverButton(icon: "backward.fill", scale: .medium) {
|
||||||
MusicManager.shared.previousTrack()
|
MusicManager.shared.previousTrack()
|
||||||
|
|
@ -230,13 +227,7 @@ struct MusicControlsView: View {
|
||||||
MusicManager.shared.nextTrack()
|
MusicManager.shared.nextTrack()
|
||||||
}
|
}
|
||||||
if showShuffleAndRepeat {
|
if showShuffleAndRepeat {
|
||||||
if showMediaOutputControl {
|
auxButton(for: rightAuxControl)
|
||||||
MediaOutputPickerButton()
|
|
||||||
} else {
|
|
||||||
HoverButton(icon: repeatIcon, iconColor: repeatIconColor, scale: .medium) {
|
|
||||||
MusicManager.shared.toggleRepeat()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity, alignment: .center)
|
.frame(maxWidth: .infinity, alignment: .center)
|
||||||
|
|
@ -261,6 +252,38 @@ struct MusicControlsView: View {
|
||||||
return .red
|
return .red
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
private func auxButton(for control: MusicAuxiliaryControl) -> some View {
|
||||||
|
switch control {
|
||||||
|
case .shuffle:
|
||||||
|
HoverButton(
|
||||||
|
icon: "shuffle",
|
||||||
|
iconColor: musicManager.isShuffled ? .red : .white,
|
||||||
|
scale: .medium
|
||||||
|
) {
|
||||||
|
MusicManager.shared.toggleShuffle()
|
||||||
|
}
|
||||||
|
case .repeatMode:
|
||||||
|
HoverButton(
|
||||||
|
icon: repeatIcon,
|
||||||
|
iconColor: repeatIconColor,
|
||||||
|
scale: .medium
|
||||||
|
) {
|
||||||
|
MusicManager.shared.toggleRepeat()
|
||||||
|
}
|
||||||
|
case .mediaOutput:
|
||||||
|
MediaOutputPickerButton()
|
||||||
|
case .lyrics:
|
||||||
|
HoverButton(
|
||||||
|
icon: enableLyrics ? "quote.bubble.fill" : "quote.bubble",
|
||||||
|
iconColor: enableLyrics ? .accentColor : .white,
|
||||||
|
scale: .medium
|
||||||
|
) {
|
||||||
|
enableLyrics.toggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Main View
|
// MARK: - Main View
|
||||||
|
|
|
||||||
|
|
@ -855,6 +855,8 @@ struct Media: View {
|
||||||
@Default(.sneakPeekStyles) var sneakPeekStyles
|
@Default(.sneakPeekStyles) var sneakPeekStyles
|
||||||
@Default(.enableMinimalisticUI) var enableMinimalisticUI
|
@Default(.enableMinimalisticUI) var enableMinimalisticUI
|
||||||
@Default(.showShuffleAndRepeat) private var showShuffleAndRepeat
|
@Default(.showShuffleAndRepeat) private var showShuffleAndRepeat
|
||||||
|
@Default(.musicAuxLeftControl) private var musicAuxLeftControl
|
||||||
|
@Default(.musicAuxRightControl) private var musicAuxRightControl
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Form {
|
Form {
|
||||||
|
|
@ -896,9 +898,21 @@ struct Media: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Defaults.Toggle(key: .showMediaOutputControl) {
|
Defaults.Toggle(key: .showMediaOutputControl) {
|
||||||
Text("Replace repeat button with media output control")
|
Text("Show media output control in other layouts")
|
||||||
}
|
}
|
||||||
.disabled(!showShuffleAndRepeat)
|
.disabled(!showShuffleAndRepeat)
|
||||||
|
if showShuffleAndRepeat {
|
||||||
|
Picker("Left button", selection: $musicAuxLeftControl) {
|
||||||
|
ForEach(MusicAuxiliaryControl.allCases) { control in
|
||||||
|
Text(control.displayName).tag(control)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Picker("Right button", selection: $musicAuxRightControl) {
|
||||||
|
ForEach(MusicAuxiliaryControl.allCases) { control in
|
||||||
|
Text(control.displayName).tag(control)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} header: {
|
} header: {
|
||||||
Text("Media controls")
|
Text("Media controls")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -196,6 +196,28 @@ enum ProgressBarStyle: String, CaseIterable, Identifiable, Defaults.Serializable
|
||||||
var id: String { self.rawValue }
|
var id: String { self.rawValue }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum MusicAuxiliaryControl: String, CaseIterable, Identifiable, Defaults.Serializable {
|
||||||
|
case shuffle
|
||||||
|
case repeatMode
|
||||||
|
case mediaOutput
|
||||||
|
case lyrics
|
||||||
|
|
||||||
|
var id: String { rawValue }
|
||||||
|
|
||||||
|
var displayName: String {
|
||||||
|
switch self {
|
||||||
|
case .shuffle:
|
||||||
|
return "Shuffle"
|
||||||
|
case .repeatMode:
|
||||||
|
return "Repeat"
|
||||||
|
case .mediaOutput:
|
||||||
|
return "Media Output"
|
||||||
|
case .lyrics:
|
||||||
|
return "Lyrics Toggle"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum TimerIconColorMode: String, CaseIterable, Identifiable, Defaults.Serializable {
|
enum TimerIconColorMode: String, CaseIterable, Identifiable, Defaults.Serializable {
|
||||||
case adaptive = "Adaptive"
|
case adaptive = "Adaptive"
|
||||||
case solid = "Solid"
|
case solid = "Solid"
|
||||||
|
|
@ -372,6 +394,9 @@ extension Defaults.Keys {
|
||||||
static let waitInterval = Key<Double>("waitInterval", default: 3)
|
static let waitInterval = Key<Double>("waitInterval", default: 3)
|
||||||
static let showShuffleAndRepeat = Key<Bool>("showShuffleAndRepeat", default: false)
|
static let showShuffleAndRepeat = Key<Bool>("showShuffleAndRepeat", default: false)
|
||||||
static let showMediaOutputControl = Key<Bool>("showMediaOutputControl", default: false)
|
static let showMediaOutputControl = Key<Bool>("showMediaOutputControl", default: false)
|
||||||
|
static let musicAuxLeftControl = Key<MusicAuxiliaryControl>("musicAuxLeftControl", default: .shuffle)
|
||||||
|
static let musicAuxRightControl = Key<MusicAuxiliaryControl>("musicAuxRightControl", default: .repeatMode)
|
||||||
|
static let didMigrateMusicAuxControls = Key<Bool>("didMigrateMusicAuxControls", default: false)
|
||||||
// Enable lock screen media widget (shows the standalone panel when screen is locked)
|
// Enable lock screen media widget (shows the standalone panel when screen is locked)
|
||||||
static let enableLockScreenMediaWidget = Key<Bool>("enableLockScreenMediaWidget", default: true)
|
static let enableLockScreenMediaWidget = Key<Bool>("enableLockScreenMediaWidget", default: true)
|
||||||
static let enableLockScreenWeatherWidget = Key<Bool>("enableLockScreenWeatherWidget", default: true)
|
static let enableLockScreenWeatherWidget = Key<Bool>("enableLockScreenWeatherWidget", default: true)
|
||||||
|
|
@ -552,4 +577,14 @@ extension Defaults.Keys {
|
||||||
Defaults[.progressBarStyle] = .gradient
|
Defaults[.progressBarStyle] = .gradient
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func migrateMusicAuxControls() {
|
||||||
|
guard Defaults[.didMigrateMusicAuxControls] == false else { return }
|
||||||
|
|
||||||
|
if Defaults[.showMediaOutputControl] {
|
||||||
|
Defaults[.musicAuxRightControl] = .mediaOutput
|
||||||
|
}
|
||||||
|
|
||||||
|
Defaults[.didMigrateMusicAuxControls] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue