mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +00:00
Merge pull request #439 from macanoclothing-blip/title_and_artist_name_on_non_notch
add an option to see the title and artist name on non notch display
This commit is contained in:
commit
baaf70900c
5 changed files with 92 additions and 65 deletions
|
|
@ -1249,6 +1249,14 @@ struct ContentView: View {
|
||||||
.foregroundStyle(timerManager.timerColor)
|
.foregroundStyle(timerManager.timerColor)
|
||||||
.padding(.trailing, 8)
|
.padding(.trailing, 8)
|
||||||
.opacity((coordinator.expandingView.show && coordinator.expandingView.type == .timer && Defaults[.enableSneakPeek] && Defaults[.sneakPeekStyles] == .inline) ? 1 : 0)
|
.opacity((coordinator.expandingView.show && coordinator.expandingView.type == .timer && Defaults[.enableSneakPeek] && Defaults[.sneakPeekStyles] == .inline) ? 1 : 0)
|
||||||
|
} else if Defaults[.showSongMetadataInClosedNotch] && isNonNotchScreen && !musicManager.songTitle.isEmpty {
|
||||||
|
MarqueeText(
|
||||||
|
.constant("\(musicManager.songTitle) • \(musicManager.artistName)"),
|
||||||
|
textColor: Defaults[.coloredSpectrogram] ? Color(nsColor: musicManager.avgColor) : Color.gray,
|
||||||
|
minDuration: 3,
|
||||||
|
frameWidth: max(0, effectiveCenterWidth - 16)
|
||||||
|
)
|
||||||
|
.padding(.horizontal, 8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.clipped()
|
.clipped()
|
||||||
|
|
|
||||||
|
|
@ -2551,7 +2551,6 @@
|
||||||
},
|
},
|
||||||
"±10 Seconds" : {
|
"±10 Seconds" : {
|
||||||
"comment" : "Display name for the \"±10 Seconds\" music skip behavior option.",
|
"comment" : "Display name for the \"±10 Seconds\" music skip behavior option.",
|
||||||
"extractionState" : "stale",
|
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ko" : {
|
"ko" : {
|
||||||
|
|
@ -3555,7 +3554,6 @@
|
||||||
},
|
},
|
||||||
"Accent" : {
|
"Accent" : {
|
||||||
"comment" : "Display name for the caps lock indicator tint mode.",
|
"comment" : "Display name for the caps lock indicator tint mode.",
|
||||||
"extractionState" : "stale",
|
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ko" : {
|
"ko" : {
|
||||||
|
|
@ -4179,7 +4177,6 @@
|
||||||
},
|
},
|
||||||
"Adaptive gradient" : {
|
"Adaptive gradient" : {
|
||||||
"comment" : "Display name for the timer icon color mode: adaptive gradient.",
|
"comment" : "Display name for the timer icon color mode: adaptive gradient.",
|
||||||
"extractionState" : "stale",
|
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ko" : {
|
"ko" : {
|
||||||
|
|
@ -6299,7 +6296,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Amazon Music" : {
|
"Amazon Music" : {
|
||||||
"extractionState" : "stale",
|
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"tr" : {
|
"tr" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
|
|
@ -6738,7 +6734,6 @@
|
||||||
},
|
},
|
||||||
"Apple Music" : {
|
"Apple Music" : {
|
||||||
"comment" : "Media controller type for Apple Music",
|
"comment" : "Media controller type for Apple Music",
|
||||||
"extractionState" : "stale",
|
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ko" : {
|
"ko" : {
|
||||||
|
|
@ -7796,7 +7791,6 @@
|
||||||
},
|
},
|
||||||
"Bar" : {
|
"Bar" : {
|
||||||
"comment" : "Name of the timer progress style that shows a horizontal bar.",
|
"comment" : "Name of the timer progress style that shows a horizontal bar.",
|
||||||
"extractionState" : "stale",
|
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ko" : {
|
"ko" : {
|
||||||
|
|
@ -12933,6 +12927,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Compact" : {
|
||||||
|
"comment" : "Title for the compact battery notification style.",
|
||||||
|
"isCommentAutoGenerated" : true
|
||||||
|
},
|
||||||
"Compact keeps the alert inline. Standard uses the taller full-charge HUD with the charging animation." : {
|
"Compact keeps the alert inline. Standard uses the taller full-charge HUD with the charging animation." : {
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
@ -16517,7 +16515,6 @@
|
||||||
},
|
},
|
||||||
"Digital" : {
|
"Digital" : {
|
||||||
"comment" : "The display name for the \"Digital\" reminder presentation style.",
|
"comment" : "The display name for the \"Digital\" reminder presentation style.",
|
||||||
"extractionState" : "stale",
|
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ko" : {
|
"ko" : {
|
||||||
|
|
@ -23770,7 +23767,6 @@
|
||||||
},
|
},
|
||||||
"Green" : {
|
"Green" : {
|
||||||
"comment" : "Display name for the green caps lock indicator tint mode.",
|
"comment" : "Display name for the green caps lock indicator tint mode.",
|
||||||
"extractionState" : "stale",
|
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ko" : {
|
"ko" : {
|
||||||
|
|
@ -34015,7 +34011,6 @@
|
||||||
},
|
},
|
||||||
"Now Playing" : {
|
"Now Playing" : {
|
||||||
"comment" : "Name of the media controller type for the \"Now Playing\" option.",
|
"comment" : "Name of the media controller type for the \"Now Playing\" option.",
|
||||||
"extractionState" : "stale",
|
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ko" : {
|
"ko" : {
|
||||||
|
|
@ -34928,7 +34923,6 @@
|
||||||
},
|
},
|
||||||
"Panel" : {
|
"Panel" : {
|
||||||
"comment" : "Display name for the clipboard display mode \"Panel\".",
|
"comment" : "Display name for the clipboard display mode \"Panel\".",
|
||||||
"extractionState" : "stale",
|
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ko" : {
|
"ko" : {
|
||||||
|
|
@ -39206,7 +39200,6 @@
|
||||||
},
|
},
|
||||||
"Ring" : {
|
"Ring" : {
|
||||||
"comment" : "The name of the timer progress style that shows a ring shape.",
|
"comment" : "The name of the timer progress style that shows a ring shape.",
|
||||||
"extractionState" : "stale",
|
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ko" : {
|
"ko" : {
|
||||||
|
|
@ -40959,7 +40952,6 @@
|
||||||
},
|
},
|
||||||
"Separate Tab" : {
|
"Separate Tab" : {
|
||||||
"comment" : "Display name for the clipboard display mode option to open the clipboard in a separate tab.",
|
"comment" : "Display name for the clipboard display mode option to open the clipboard in a separate tab.",
|
||||||
"extractionState" : "stale",
|
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ko" : {
|
"ko" : {
|
||||||
|
|
@ -43612,6 +43604,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Show song title and artist on non-notch displays" : {
|
||||||
|
|
||||||
},
|
},
|
||||||
"Show start time after event begins" : {
|
"Show start time after event begins" : {
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
|
|
@ -43803,7 +43798,6 @@
|
||||||
},
|
},
|
||||||
"Shows screen assistant as a dropdown attached to the AI button" : {
|
"Shows screen assistant as a dropdown attached to the AI button" : {
|
||||||
"comment" : "Description of the screen assistant display mode option that shows the screen assistant as a dropdown attached to the AI button.",
|
"comment" : "Description of the screen assistant display mode option that shows the screen assistant as a dropdown attached to the AI button.",
|
||||||
"extractionState" : "stale",
|
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ko" : {
|
"ko" : {
|
||||||
|
|
@ -43834,7 +43828,6 @@
|
||||||
},
|
},
|
||||||
"Shows screen assistant in a floating panel near the notch" : {
|
"Shows screen assistant in a floating panel near the notch" : {
|
||||||
"comment" : "Description of the screen assistant display mode option that shows the screen assistant in a floating panel near the notch.",
|
"comment" : "Description of the screen assistant display mode option that shows the screen assistant in a floating panel near the notch.",
|
||||||
"extractionState" : "stale",
|
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ko" : {
|
"ko" : {
|
||||||
|
|
@ -44124,7 +44117,6 @@
|
||||||
},
|
},
|
||||||
"Skip forward or backward by ten seconds" : {
|
"Skip forward or backward by ten seconds" : {
|
||||||
"comment" : "Description of a music skip behavior option.",
|
"comment" : "Description of a music skip behavior option.",
|
||||||
"extractionState" : "stale",
|
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ko" : {
|
"ko" : {
|
||||||
|
|
@ -44900,7 +44892,6 @@
|
||||||
},
|
},
|
||||||
"Spotify" : {
|
"Spotify" : {
|
||||||
"comment" : "Spotify media controller type.",
|
"comment" : "Spotify media controller type.",
|
||||||
"extractionState" : "stale",
|
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ko" : {
|
"ko" : {
|
||||||
|
|
@ -45181,7 +45172,6 @@
|
||||||
},
|
},
|
||||||
"Standard previous/next track controls" : {
|
"Standard previous/next track controls" : {
|
||||||
"comment" : "Description of the music skip behavior option to use standard previous/next track controls.",
|
"comment" : "Description of the music skip behavior option to use standard previous/next track controls.",
|
||||||
"extractionState" : "stale",
|
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ko" : {
|
"ko" : {
|
||||||
|
|
@ -48514,7 +48504,6 @@
|
||||||
},
|
},
|
||||||
"Track Skip" : {
|
"Track Skip" : {
|
||||||
"comment" : "Display name for the \"Track Skip\" music skip behavior.",
|
"comment" : "Display name for the \"Track Skip\" music skip behavior.",
|
||||||
"extractionState" : "stale",
|
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ko" : {
|
"ko" : {
|
||||||
|
|
@ -52390,7 +52379,6 @@
|
||||||
},
|
},
|
||||||
"Youtube Music" : {
|
"Youtube Music" : {
|
||||||
"comment" : "Spotify music service.",
|
"comment" : "Spotify music service.",
|
||||||
"extractionState" : "stale",
|
|
||||||
"isCommentAutoGenerated" : true,
|
"isCommentAutoGenerated" : true,
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ko" : {
|
"ko" : {
|
||||||
|
|
|
||||||
|
|
@ -46,9 +46,9 @@ struct MarqueeText: View {
|
||||||
let minDuration: Double
|
let minDuration: Double
|
||||||
let frameWidth: CGFloat
|
let frameWidth: CGFloat
|
||||||
|
|
||||||
@State private var animate = false
|
|
||||||
@State private var textSize: CGSize = .zero
|
@State private var textSize: CGSize = .zero
|
||||||
@State private var offset: CGFloat = 0
|
@State private var offset: CGFloat = 0
|
||||||
|
@State private var isAnimating: Bool = false
|
||||||
|
|
||||||
init(_ text: Binding<String>, font: Font = .body, nsFont: NSFont.TextStyle = .body, textColor: Color = .primary, backgroundColor: Color = .clear, minDuration: Double = 3.0, frameWidth: CGFloat = 200) {
|
init(_ text: Binding<String>, font: Font = .body, nsFont: NSFont.TextStyle = .body, textColor: Color = .primary, backgroundColor: Color = .clear, minDuration: Double = 3.0, frameWidth: CGFloat = 200) {
|
||||||
_text = text
|
_text = text
|
||||||
|
|
@ -65,7 +65,6 @@ struct MarqueeText: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
GeometryReader { geometry in
|
|
||||||
ZStack(alignment: .leading) {
|
ZStack(alignment: .leading) {
|
||||||
HStack(spacing: 20) {
|
HStack(spacing: 20) {
|
||||||
Text(text)
|
Text(text)
|
||||||
|
|
@ -76,44 +75,70 @@ struct MarqueeText: View {
|
||||||
.font(font)
|
.font(font)
|
||||||
.foregroundColor(textColor)
|
.foregroundColor(textColor)
|
||||||
.fixedSize(horizontal: true, vertical: false)
|
.fixedSize(horizontal: true, vertical: false)
|
||||||
.offset(x: self.animate ? offset : 0)
|
.offset(x: offset)
|
||||||
.animation(
|
|
||||||
self.animate ?
|
|
||||||
.linear(duration: Double(textSize.width / 30))
|
|
||||||
.delay(minDuration)
|
|
||||||
.repeatForever(autoreverses: false) : .none,
|
|
||||||
value: self.animate
|
|
||||||
)
|
|
||||||
.background(backgroundColor)
|
.background(backgroundColor)
|
||||||
.modifier(MeasureSizeModifier())
|
.modifier(MeasureSizeModifier())
|
||||||
.onPreferenceChange(SizePreferenceKey.self) { size in
|
.onPreferenceChange(SizePreferenceKey.self) { size in
|
||||||
self.textSize = CGSize(width: size.width / 2, height: NSFont.preferredFont(forTextStyle: nsFont).pointSize)
|
self.textSize = CGSize(width: size.width / 2, height: NSFont.preferredFont(forTextStyle: nsFont).pointSize)
|
||||||
self.animate = false
|
resetAndStart()
|
||||||
self.offset = 0
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.02){
|
|
||||||
if needsScrolling {
|
|
||||||
self.animate = true
|
|
||||||
self.offset = -(textSize.width + 20)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.onChange(of: text) { _, _ in
|
.onChange(of: text) { _, _ in
|
||||||
// Reset animation when text changes
|
resetAndStart()
|
||||||
self.animate = false
|
|
||||||
self.offset = 0
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.02){
|
|
||||||
if needsScrolling {
|
|
||||||
self.animate = true
|
|
||||||
self.offset = -(textSize.width + 20)
|
|
||||||
}
|
}
|
||||||
|
.onAppear {
|
||||||
|
resetAndStart()
|
||||||
}
|
}
|
||||||
|
.onDisappear {
|
||||||
|
isAnimating = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(width: frameWidth, alignment: .leading)
|
.frame(width: frameWidth, alignment: .leading)
|
||||||
.clipped()
|
.clipped()
|
||||||
}
|
|
||||||
.frame(height: textSize.height * 1.3)
|
.frame(height: textSize.height * 1.3)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func resetAndStart() {
|
||||||
|
isAnimating = false
|
||||||
|
withAnimation(.none) {
|
||||||
|
offset = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||||
|
if needsScrolling {
|
||||||
|
isAnimating = true
|
||||||
|
startAnimationLoop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func startAnimationLoop() {
|
||||||
|
guard isAnimating && needsScrolling else { return }
|
||||||
|
|
||||||
|
// Duration based on speed (approx 30 pts per second)
|
||||||
|
let duration = Double(textSize.width / 30)
|
||||||
|
|
||||||
|
// 1. Initial/Restart Pause
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + minDuration) {
|
||||||
|
guard isAnimating else { return }
|
||||||
|
|
||||||
|
// 2. Linear Move
|
||||||
|
withAnimation(.linear(duration: duration)) {
|
||||||
|
offset = -(textSize.width + 20) // Text width + spacing
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Wait for move to finish
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + duration) {
|
||||||
|
guard isAnimating else { return }
|
||||||
|
|
||||||
|
// 4. Snap back instantly
|
||||||
|
withAnimation(.none) {
|
||||||
|
offset = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Repeat
|
||||||
|
startAnimationLoop()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2937,6 +2937,11 @@ struct Media: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Defaults.Toggle(key: .showSongMetadataInClosedNotch) {
|
||||||
|
Text("Show song title and artist on non-notch displays")
|
||||||
|
}
|
||||||
|
.settingsHighlight(id: highlightID("Show song title and artist in closed notch"))
|
||||||
} header: {
|
} header: {
|
||||||
Text("Media playback live activity")
|
Text("Media playback live activity")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1332,4 +1332,5 @@ extension Defaults.Keys {
|
||||||
let fallback = MusicAuxiliaryControl.alternative(excluding: current)
|
let fallback = MusicAuxiliaryControl.alternative(excluding: current)
|
||||||
Defaults[.musicAuxRightControl] = fallback
|
Defaults[.musicAuxRightControl] = fallback
|
||||||
}
|
}
|
||||||
|
static let showSongMetadataInClosedNotch = Key<Bool>("showSongMetadataInClosedNotch", default: false)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue