Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Video Player Settings Cleanup #1199

Closed
wants to merge 10 commits into from
6 changes: 0 additions & 6 deletions Shared/Coordinators/SettingsCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ final class SettingsCoordinator: NavigationCoordinatable {
@Route(.push)
var log = makeLog
@Route(.push)
var nativePlayerSettings = makeNativePlayerSettings
@Route(.push)
var maximumBitrateSettings = makeMaximumBitrateSettings
@Route(.push)
var quickConnect = makeQuickConnectAuthorize
Expand Down Expand Up @@ -69,10 +67,6 @@ final class SettingsCoordinator: NavigationCoordinatable {
#endif

#if os(iOS)
@ViewBuilder
func makeNativePlayerSettings() -> some View {
NativeVideoPlayerSettingsView()
}

@ViewBuilder
func makeMaximumBitrateSettings() -> some View {
Expand Down
19 changes: 17 additions & 2 deletions Shared/Coordinators/VideoPlayerSettingsCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ final class VideoPlayerSettingsCoordinator: NavigationCoordinatable {
@Route(.push)
var fontPicker = makeFontPicker

#if os(iOS)
#if os(tvOS)
@Route(.push)
var resumeOffset = makeResumeOffset
@Route(.push)
var subtitleSize = makeSubtitleSize
#elseif os(iOS)
@Route(.push)
var gestureSettings = makeGestureSettings
@Route(.push)
Expand All @@ -30,7 +35,17 @@ final class VideoPlayerSettingsCoordinator: NavigationCoordinatable {
FontPickerView(selection: selection)
}

#if os(iOS)
#if os(tvOS)

func makeResumeOffset(selection: Binding<Int>) -> some View {
ResumeOffsetPickerView(selection: selection)
}

func makeSubtitleSize(selection: Binding<Int>) -> some View {
SubtitleSizePickerView(selection: selection)
}

#elseif os(iOS)

@ViewBuilder
func makeGestureSettings() -> some View {
Expand Down
28 changes: 22 additions & 6 deletions Shared/Strings/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ internal enum L10n {
internal static let bugsAndFeatures = L10n.tr("Localizable", "bugsAndFeatures", fallback: "Bugs and Features")
/// Buttons
internal static let buttons = L10n.tr("Localizable", "buttons", fallback: "Buttons")
/// Customize which playback buttons are active and adjust their size
internal static let buttonsDescription = L10n.tr("Localizable", "buttonsDescription", fallback: "Customize which playback buttons are active and adjust their size")
/// Cancel
internal static let cancel = L10n.tr("Localizable", "cancel", fallback: "Cancel")
/// Cannot connect to host
Expand Down Expand Up @@ -384,8 +386,8 @@ internal enum L10n {
}
/// Password
internal static let password = L10n.tr("Localizable", "password", fallback: "Password")
/// Pause on background
internal static let pauseOnBackground = L10n.tr("Localizable", "pauseOnBackground", fallback: "Pause on background")
/// Pause on Background
internal static let pauseOnBackground = L10n.tr("Localizable", "pauseOnBackground", fallback: "Pause on Background")
/// People
internal static let people = L10n.tr("Localizable", "people", fallback: "People")
/// Play
Expand All @@ -404,6 +406,10 @@ internal enum L10n {
internal static let playbackSpeed = L10n.tr("Localizable", "playbackSpeed", fallback: "Playback Speed")
/// Played
internal static let played = L10n.tr("Localizable", "played", fallback: "Played")
/// Player Controls
internal static let playerControls = L10n.tr("Localizable", "playerControls", fallback: "Player Controls")
/// Customize playback controls and gestures
internal static let playerControlsDescription = L10n.tr("Localizable", "playerControlsDescription", fallback: "Customize playback controls and gestures")
/// Player Gestures Lock Gesture Enabled
internal static let playerGesturesLockGestureEnabled = L10n.tr("Localizable", "playerGesturesLockGestureEnabled", fallback: "Player Gestures Lock Gesture Enabled")
/// Play From Beginning
Expand All @@ -412,8 +418,8 @@ internal enum L10n {
internal static let playNext = L10n.tr("Localizable", "playNext", fallback: "Play Next")
/// Play Next Item
internal static let playNextItem = L10n.tr("Localizable", "playNextItem", fallback: "Play Next Item")
/// Play on active
internal static let playOnActive = L10n.tr("Localizable", "playOnActive", fallback: "Play on active")
/// Play on Active
internal static let playOnActive = L10n.tr("Localizable", "playOnActive", fallback: "Play on Active")
/// Play Previous Item
internal static let playPreviousItem = L10n.tr("Localizable", "playPreviousItem", fallback: "Play Previous Item")
/// Posters
Expand Down Expand Up @@ -498,8 +504,8 @@ internal enum L10n {
internal static let resume5SecondOffset = L10n.tr("Localizable", "resume5SecondOffset", fallback: "Resume 5 Second Offset")
/// Resume Offset
internal static let resumeOffset = L10n.tr("Localizable", "resumeOffset", fallback: "Resume Offset")
/// Resume content seconds before the recorded resume time
internal static let resumeOffsetDescription = L10n.tr("Localizable", "resumeOffsetDescription", fallback: "Resume content seconds before the recorded resume time")
/// Set the media playback to rewind by the offset amount in seconds when resuming
internal static let resumeOffsetDescription = L10n.tr("Localizable", "resumeOffsetDescription", fallback: "Set the media playback to rewind by the offset amount in seconds when resuming")
/// Resume Offset
internal static let resumeOffsetTitle = L10n.tr("Localizable", "resumeOffsetTitle", fallback: "Resume Offset")
/// Retrieving media information
Expand Down Expand Up @@ -598,6 +604,8 @@ internal enum L10n {
internal static let slider = L10n.tr("Localizable", "slider", fallback: "Slider")
/// Slider Color
internal static let sliderColor = L10n.tr("Localizable", "sliderColor", fallback: "Slider Color")
/// Customize the timeline slider for media playback
internal static let sliderDescription = L10n.tr("Localizable", "sliderDescription", fallback: "Customize the timeline slider for media playback")
/// Slider Type
internal static let sliderType = L10n.tr("Localizable", "sliderType", fallback: "Slider Type")
/// Smaller
Expand All @@ -622,6 +630,10 @@ internal enum L10n {
internal static let subtitle = L10n.tr("Localizable", "subtitle", fallback: "Subtitle")
/// Subtitle Color
internal static let subtitleColor = L10n.tr("Localizable", "subtitleColor", fallback: "Subtitle Color")
/// Customize text-based subtitles font and color
internal static let subtitleDescriptionIOS = L10n.tr("Localizable", "subtitleDescriptionIOS", fallback: "Customize text-based subtitles font and color")
/// Customize text-based subtitles font
internal static let subtitleDescriptionTVOS = L10n.tr("Localizable", "subtitleDescriptionTVOS", fallback: "Customize text-based subtitles font")
/// Subtitle Font
internal static let subtitleFont = L10n.tr("Localizable", "subtitleFont", fallback: "Subtitle Font")
/// Subtitle Offset
Expand All @@ -646,6 +658,8 @@ internal enum L10n {
internal static let testSize = L10n.tr("Localizable", "testSize", fallback: "Test Size")
/// Timestamp
internal static let timestamp = L10n.tr("Localizable", "timestamp", fallback: "Timestamp")
/// Adjust how the current timestamp is shown during playback
internal static let timestampDescription = L10n.tr("Localizable", "timestampDescription", fallback: "Adjust how the current timestamp is shown during playback")
/// Timestamp Type
internal static let timestampType = L10n.tr("Localizable", "timestampType", fallback: "Timestamp Type")
/// Too Many Redirects
Expand All @@ -654,6 +668,8 @@ internal enum L10n {
internal static let trailingValue = L10n.tr("Localizable", "trailingValue", fallback: "Trailing Value")
/// Transition
internal static let transition = L10n.tr("Localizable", "transition", fallback: "Transition")
/// Configure how Swiftfin manages transitions between foreground and background while media is playing
internal static let transitionDescription = L10n.tr("Localizable", "transitionDescription", fallback: "Configure how Swiftfin manages transitions between foreground and background while media is playing")
/// Try again
internal static let tryAgain = L10n.tr("Localizable", "tryAgain", fallback: "Try again")
/// TV Shows
Expand Down
44 changes: 25 additions & 19 deletions Swiftfin tvOS/Components/StepperView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ struct StepperView<Value: CustomStringConvertible & Strideable>: View {
@Binding
private var value: Value

@State
private var updatedValue: Value

@Environment(\.presentationMode)
private var presentationMode

private var title: String
private var description: String?
private var range: ClosedRange<Value>
Expand All @@ -36,16 +42,17 @@ struct StepperView<Value: CustomStringConvertible & Strideable>: View {
}
.frame(maxHeight: .infinity)

formatter(value).text
formatter(updatedValue).text
.font(.title)
.frame(height: 250)

VStack {

HStack {
Button {
guard value >= range.lowerBound else { return }
value = value.advanced(by: -step)
if updatedValue > range.lowerBound {
updatedValue = max(updatedValue.advanced(by: -step), range.lowerBound)
value = updatedValue
}
} label: {
Image(systemName: "minus")
.font(.title2.weight(.bold))
Expand All @@ -54,8 +61,10 @@ struct StepperView<Value: CustomStringConvertible & Strideable>: View {
.buttonStyle(.card)

Button {
guard value <= range.upperBound else { return }
value = value.advanced(by: step)
if updatedValue < range.upperBound {
updatedValue = min(updatedValue.advanced(by: step), range.upperBound)
value = updatedValue
}
} label: {
Image(systemName: "plus")
.font(.title2.weight(.bold))
Expand All @@ -64,10 +73,8 @@ struct StepperView<Value: CustomStringConvertible & Strideable>: View {
.buttonStyle(.card)
}

Button {
onCloseSelected()
} label: {
Text("Close")
Button(L10n.close) {
presentationMode.wrappedValue.dismiss()
}

Spacer()
Expand All @@ -86,15 +93,14 @@ extension StepperView {
range: ClosedRange<Value>,
step: Value.Stride
) {
self.init(
value: value,
title: title,
description: description,
range: range,
step: step,
formatter: { $0.description },
onCloseSelected: {}
)
self._value = value
self._updatedValue = State(initialValue: value.wrappedValue)
self.title = title
self.description = description
self.range = range
self.step = step
self.formatter = { $0.description }
self.onCloseSelected = {}
}

func valueFormatter(_ formatter: @escaping (Value) -> String) -> Self {
Expand Down
1 change: 1 addition & 0 deletions Swiftfin tvOS/Views/FontPickerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,6 @@ struct FontPickerView: View {
}
}
.withDescriptionTopPadding()
.navigationTitle(L10n.subtitleFont)
}
}
28 changes: 28 additions & 0 deletions Swiftfin tvOS/Views/ResumeOffsetPickerView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// Swiftfin is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
//

import Defaults
import SwiftUI

struct ResumeOffsetPickerView: View {

@Binding
var selection: Int

var body: some View {
StepperView(
title: L10n.resumeOffset,
value: $selection,
range: 0 ... 30,
step: 1
)
.valueFormatter {
$0.secondLabel
}
}
}
94 changes: 0 additions & 94 deletions Swiftfin tvOS/Views/SettingsView/VideoPlayerSettingsView.swift

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// Swiftfin is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
//

import Defaults
import SwiftUI

extension VideoPlayerSettingsView {
struct PlayerControlsSection: View {
@Default(.VideoPlayer.jumpBackwardLength)
private var jumpBackwardLength
@Default(.VideoPlayer.jumpForwardLength)
private var jumpForwardLength

@EnvironmentObject
private var router: VideoPlayerSettingsCoordinator.Router

var body: some View {
Section {
InlineEnumToggle(title: L10n.jumpBackwardLength, selection: $jumpBackwardLength)

InlineEnumToggle(title: L10n.jumpForwardLength, selection: $jumpForwardLength)
} header: {
L10n.playerControls.text
} footer: {
L10n.playerControlsDescription.text
}
}
}
}
Loading
Loading