Change in the slider and added +10 -10 controls

This commit is contained in:
Hariharan Mudaliar 2025-11-20 13:17:16 +05:30
commit d88d9acb60
8 changed files with 497 additions and 228 deletions

View file

@ -361,21 +361,32 @@ struct MusicSliderView: View {
let isPlaying: Bool
let isLiveStream: Bool
var onValueChange: (Double) -> Void
var labelLayout: TimeLabelLayout = .stacked
var trailingLabel: TrailingLabel = .duration
var restingTrackHeight: CGFloat = 5
var draggingTrackHeight: CGFloat = 9
enum TimeLabelLayout {
case stacked
case inline
}
enum TrailingLabel {
case duration
case remaining
}
var body: some View {
VStack {
sliderContent
.frame(height: 10, alignment: .center)
if !isLiveStream {
HStack {
Text(timeString(from: sliderValue))
Spacer()
Text(timeString(from: duration))
Group {
if isLiveStream {
liveStreamView
} else {
switch labelLayout {
case .stacked:
stackedContent
case .inline:
inlineContent
}
.fontWeight(.medium)
.foregroundColor(timeLabelColor)
.font(.caption)
}
}
.onChange(of: currentDate) { newDate in
@ -390,23 +401,73 @@ struct MusicSliderView: View {
}
}
private var stackedContent: some View {
VStack(spacing: 6) {
sliderCore
.frame(height: sliderFrameHeight)
HStack {
Text(timeString(from: sliderValue))
Spacer()
Text(trailingTimeText)
}
.fontWeight(.medium)
.foregroundColor(timeLabelColor)
.font(.caption)
}
}
private var inlineContent: some View {
HStack(spacing: 10) {
Text(timeString(from: sliderValue))
.font(inlineLabelFont)
.foregroundColor(timeLabelColor)
.frame(width: 42, alignment: .leading)
sliderCore
.frame(height: sliderFrameHeight)
.frame(maxWidth: .infinity)
Text(trailingTimeText)
.font(inlineLabelFont)
.foregroundColor(timeLabelColor)
.frame(width: 48, alignment: .trailing)
}
}
@ViewBuilder
private var sliderContent: some View {
if isLiveStream {
private var liveStreamView: some View {
switch labelLayout {
case .stacked:
LiveStreamProgressIndicator(tint: sliderTint)
.frame(maxWidth: .infinity)
} else {
CustomSlider(
value: $sliderValue,
range: 0 ... duration,
color: sliderTint,
dragging: $dragging,
lastDragged: $lastDragged,
onValueChange: onValueChange
)
.frame(height: sliderFrameHeight)
case .inline:
HStack(spacing: 10) {
Spacer()
.frame(width: 42)
LiveStreamProgressIndicator(tint: sliderTint)
.frame(maxWidth: .infinity)
.frame(height: sliderFrameHeight)
Spacer()
.frame(width: 48)
}
}
}
private var sliderCore: some View {
CustomSlider(
value: $sliderValue,
range: 0 ... duration,
color: sliderTint,
dragging: $dragging,
lastDragged: $lastDragged,
onValueChange: onValueChange,
restingTrackHeight: restingTrackHeight,
draggingTrackHeight: draggingTrackHeight
)
}
private var sliderTint: Color {
switch Defaults[.sliderColor] {
case .albumArt:
@ -424,6 +485,24 @@ struct MusicSliderView: View {
: .gray
}
private var trailingTimeText: String {
switch trailingLabel {
case .duration:
return timeString(from: duration)
case .remaining:
let remaining = max(duration - sliderValue, 0)
return "-" + timeString(from: remaining)
}
}
private var inlineLabelFont: Font {
.system(size: 11, weight: .medium, design: .monospaced)
}
private var sliderFrameHeight: CGFloat {
max(restingTrackHeight, draggingTrackHeight)
}
func timeString(from seconds: Double) -> String {
let totalMinutes = Int(seconds) / 60
let remainingSeconds = Int(seconds) % 60
@ -448,11 +527,13 @@ struct CustomSlider: View {
@Binding var lastDragged: Date
var onValueChange: ((Double) -> Void)?
var thumbSize: CGFloat = 12
var restingTrackHeight: CGFloat = 5
var draggingTrackHeight: CGFloat = 9
var body: some View {
GeometryReader { geometry in
let width = geometry.size.width
let height = CGFloat(dragging ? 9 : 5)
let trackHeight = CGFloat(dragging ? draggingTrackHeight : restingTrackHeight)
let rangeSpan = range.upperBound - range.lowerBound
let progress = rangeSpan == .zero ? 0 : (value - range.lowerBound) / rangeSpan
@ -462,15 +543,15 @@ struct CustomSlider: View {
// Background track
Rectangle()
.fill(.gray.opacity(0.3))
.frame(height: height)
.frame(height: trackHeight)
// Filled track
Rectangle()
.fill(color)
.frame(width: filledTrackWidth, height: height)
.frame(width: filledTrackWidth, height: trackHeight)
}
.cornerRadius(height / 2)
.frame(height: 10)
.cornerRadius(trackHeight / 2)
.frame(height: max(restingTrackHeight, draggingTrackHeight))
.contentShape(Rectangle())
.highPriorityGesture(
DragGesture(minimumDistance: 0)