Skip to content

Commit

Permalink
feat: toggle between duration and time remaining
Browse files Browse the repository at this point in the history
  • Loading branch information
godly-devotion committed Mar 28, 2024
1 parent e847002 commit 45086e1
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 16 deletions.
17 changes: 14 additions & 3 deletions Front Row/Support/Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,19 @@ extension NSSize {
}
}

extension Double {
var asTimecode: String {
Duration.seconds(self).formatted(.time(pattern: .hourMinuteSecond(padHourToLength: 0)))
extension TimeInterval {
/// Returns value as timecode string.
/// - Parameter longestTime: Used to determine if hour should be displayed
/// - Returns: 0:00 or 0:00:00
///
func asTimecode(using longestTime: TimeInterval) -> String {
let hasHour = (longestTime / 3600.0) > 1.0
if hasHour {
return Duration.seconds(self).formatted(
.time(pattern: .hourMinuteSecond(padHourToLength: 0)))
} else {
return Duration.seconds(self).formatted(
.time(pattern: .minuteSecond(padMinuteToLength: 2)))
}
}
}
9 changes: 6 additions & 3 deletions Front Row/Support/PlayEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ import SwiftUI

private(set) var duration: TimeInterval = 0.0

private(set) var timeRemaining: TimeInterval = 0.0

private var _isMuted = false

var isMuted: Bool {
Expand Down Expand Up @@ -285,9 +287,10 @@ import SwiftUI
guard let self else { return }
_currentTime = time.seconds

guard let seconds = player.currentItem?.duration.seconds else { return }
guard !seconds.isNaN && !seconds.isInfinite else { return }
duration = seconds
guard let duration = player.currentItem?.duration.seconds else { return }
guard !duration.isNaN && !duration.isInfinite else { return }
self.duration = duration
timeRemaining = duration - _currentTime
}
}

Expand Down
34 changes: 25 additions & 9 deletions Front Row/Views/PlayerControlsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import SwiftUI

struct PlayerControlsView: View {
@Environment(PlayEngine.self) private var playEngine: PlayEngine
private let foregroundColor = Color.white.opacity(0.8)
@AppStorage("ShowTimeRemaining") var showTimeRemaining = true
private let foregroundColor = Color.white.opacity(0.7)
private let disabledControlTextColor = Color(nsColor: NSColor.disabledControlTextColor)

var body: some View {
@Bindable var playEngine = playEngine
Expand Down Expand Up @@ -62,20 +64,34 @@ struct PlayerControlsView: View {
.disabled(!playEngine.isLoaded)

// MARK: Current time
Text(verbatim: playEngine.currentTime.asTimecode)
Text(verbatim: playEngine.currentTime.asTimecode(using: playEngine.duration))
.font(.system(size: 11))
.foregroundStyle(foregroundColor)
.frame(width: 50, alignment: .center)
.foregroundStyle(playEngine.isLoaded ? foregroundColor : disabledControlTextColor)
.frame(minWidth: 50, alignment: .center)

// MARK: Seek slider
SeekSliderView(value: $playEngine.currentTime, maxValue: playEngine.duration)
.disabled(!playEngine.isLoaded)

// MARK: Time remaining
Text(verbatim: playEngine.duration.asTimecode)
.font(.system(size: 11))
.foregroundStyle(foregroundColor)
.frame(width: 50, alignment: .center)
// MARK: Time remaining or Duration
Text(
verbatim: showTimeRemaining
? "-\(playEngine.timeRemaining.asTimecode(using: playEngine.duration))"
: playEngine.duration.asTimecode(using: playEngine.duration)
)
.font(.system(size: 11))
.foregroundStyle(playEngine.isLoaded ? foregroundColor : disabledControlTextColor)
.frame(minWidth: 50, alignment: .center)
.onHover { inside in
if inside {
NSCursor.pointingHand.push()
} else {
NSCursor.pop()
}
}
.onTapGesture {
showTimeRemaining.toggle()
}
}
.padding([.horizontal], 16)
.padding([.vertical], 8)
Expand Down
2 changes: 1 addition & 1 deletion Front Row/Views/SeekSliderView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ struct SeekSliderView: NSViewRepresentable {
knobRect.width,
knobHeight)
let path = NSBezierPath(roundedRect: rect, xRadius: knobRadius, yRadius: knobRadius)
NSColor.white.withAlphaComponent(0.8).setFill()
NSColor.white.withAlphaComponent(0.7).setFill()
path.fill()
}

Expand Down

0 comments on commit 45086e1

Please sign in to comment.