mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +00:00
Remapping functionality
This commit is contained in:
parent
d451ea34fd
commit
96dde9d555
9 changed files with 687 additions and 399 deletions
|
|
@ -447,6 +447,8 @@ extension Defaults.Keys {
|
|||
static let musicAuxLeftControl = Key<MusicAuxiliaryControl>("musicAuxLeftControl", default: .shuffle)
|
||||
static let musicAuxRightControl = Key<MusicAuxiliaryControl>("musicAuxRightControl", default: .repeatMode)
|
||||
static let didMigrateMusicAuxControls = Key<Bool>("didMigrateMusicAuxControls", default: false)
|
||||
static let musicControlSlots = Key<[MusicControlButton]>("musicControlSlots", default: MusicControlButton.defaultLayout)
|
||||
static let didMigrateMusicControlSlots = Key<Bool>("didMigrateMusicControlSlots", default: false)
|
||||
static let musicSkipBehavior = Key<MusicSkipBehavior>("musicSkipBehavior", default: .track)
|
||||
static let musicControlWindowEnabled = Key<Bool>("musicControlWindowEnabled", default: false)
|
||||
// Enable lock screen media widget (shows the standalone panel when screen is locked)
|
||||
|
|
@ -668,6 +670,27 @@ extension Defaults.Keys {
|
|||
normalizeMusicAuxControls()
|
||||
}
|
||||
|
||||
static func migrateMusicControlSlots() {
|
||||
guard Defaults[.didMigrateMusicControlSlots] == false else { return }
|
||||
|
||||
let allowMediaOutput = Defaults[.showMediaOutputControl]
|
||||
let baseLayout: [MusicControlButton]
|
||||
|
||||
if Defaults[.showShuffleAndRepeat] {
|
||||
var slots = MusicControlButton.defaultLayout
|
||||
let left = MusicControlButton(auxiliaryControl: Defaults[.musicAuxLeftControl])
|
||||
let right = MusicControlButton(auxiliaryControl: Defaults[.musicAuxRightControl])
|
||||
slots[0] = left
|
||||
slots[4] = right
|
||||
baseLayout = slots
|
||||
} else {
|
||||
baseLayout = MusicControlButton.minimalLayout
|
||||
}
|
||||
|
||||
Defaults[.musicControlSlots] = baseLayout.normalized(allowingMediaOutput: allowMediaOutput)
|
||||
Defaults[.didMigrateMusicControlSlots] = true
|
||||
}
|
||||
|
||||
private static func normalizeMusicAuxControls() {
|
||||
guard Defaults[.musicAuxLeftControl] == Defaults[.musicAuxRightControl] else { return }
|
||||
|
||||
|
|
|
|||
136
DynamicIsland/models/MusicControlButton.swift
Normal file
136
DynamicIsland/models/MusicControlButton.swift
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
import Defaults
|
||||
|
||||
enum MusicControlButton: String, CaseIterable, Identifiable, Codable, Defaults.Serializable {
|
||||
case shuffle
|
||||
case trackBackward
|
||||
case playPause
|
||||
case trackForward
|
||||
case repeatMode
|
||||
case mediaOutput
|
||||
case lyrics
|
||||
case seekBackward
|
||||
case seekForward
|
||||
case none
|
||||
|
||||
static let slotCount = 5
|
||||
|
||||
static let defaultLayout: [MusicControlButton] = [
|
||||
.shuffle,
|
||||
.trackBackward,
|
||||
.playPause,
|
||||
.trackForward,
|
||||
.repeatMode
|
||||
]
|
||||
|
||||
static let minimalLayout: [MusicControlButton] = [
|
||||
.none,
|
||||
.trackBackward,
|
||||
.playPause,
|
||||
.trackForward,
|
||||
.none
|
||||
]
|
||||
|
||||
static let pickerOptions: [MusicControlButton] = [
|
||||
.trackBackward,
|
||||
.playPause,
|
||||
.trackForward,
|
||||
.seekBackward,
|
||||
.seekForward,
|
||||
.shuffle,
|
||||
.repeatMode,
|
||||
.lyrics,
|
||||
.mediaOutput
|
||||
]
|
||||
|
||||
var id: String { rawValue }
|
||||
|
||||
var label: String {
|
||||
switch self {
|
||||
case .shuffle:
|
||||
return "Shuffle"
|
||||
case .trackBackward:
|
||||
return "Previous Track"
|
||||
case .playPause:
|
||||
return "Play / Pause"
|
||||
case .trackForward:
|
||||
return "Next Track"
|
||||
case .repeatMode:
|
||||
return "Repeat"
|
||||
case .mediaOutput:
|
||||
return "Media Output"
|
||||
case .lyrics:
|
||||
return "Lyrics"
|
||||
case .seekBackward:
|
||||
return "Rewind 10s"
|
||||
case .seekForward:
|
||||
return "Forward 10s"
|
||||
case .none:
|
||||
return "Empty Slot"
|
||||
}
|
||||
}
|
||||
|
||||
var iconName: String {
|
||||
switch self {
|
||||
case .shuffle:
|
||||
return "shuffle"
|
||||
case .trackBackward:
|
||||
return "backward.fill"
|
||||
case .playPause:
|
||||
return "playpause"
|
||||
case .trackForward:
|
||||
return "forward.fill"
|
||||
case .repeatMode:
|
||||
return "repeat"
|
||||
case .mediaOutput:
|
||||
return "speaker.wave.2"
|
||||
case .lyrics:
|
||||
return "quote.bubble"
|
||||
case .seekBackward:
|
||||
return "gobackward.10"
|
||||
case .seekForward:
|
||||
return "goforward.10"
|
||||
case .none:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
var prefersLargeScale: Bool {
|
||||
self == .playPause
|
||||
}
|
||||
}
|
||||
|
||||
extension Array where Element == MusicControlButton {
|
||||
func normalized(allowingMediaOutput: Bool) -> [MusicControlButton] {
|
||||
var sanitized = map { button -> MusicControlButton in
|
||||
if button == .mediaOutput && !allowingMediaOutput {
|
||||
return .none
|
||||
}
|
||||
return button
|
||||
}
|
||||
|
||||
if sanitized.count < MusicControlButton.slotCount {
|
||||
sanitized.append(contentsOf: Array(repeating: .none, count: MusicControlButton.slotCount - sanitized.count))
|
||||
}
|
||||
|
||||
if sanitized.count > MusicControlButton.slotCount {
|
||||
sanitized = Array(sanitized.prefix(MusicControlButton.slotCount))
|
||||
}
|
||||
|
||||
return sanitized
|
||||
}
|
||||
}
|
||||
|
||||
extension MusicControlButton {
|
||||
init(auxiliaryControl: MusicAuxiliaryControl) {
|
||||
switch auxiliaryControl {
|
||||
case .shuffle:
|
||||
self = .shuffle
|
||||
case .repeatMode:
|
||||
self = .repeatMode
|
||||
case .mediaOutput:
|
||||
self = .mediaOutput
|
||||
case .lyrics:
|
||||
self = .lyrics
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue