1
0
mirror of https://github.com/yattee/yattee.git synced 2025-04-28 16:00:33 +05:30

Video details toolbar and inspector settings

This commit is contained in:
Arkadiusz Fal 2022-11-13 23:36:46 +01:00
parent 7cc3cd950b
commit 041a28e7a0
8 changed files with 97 additions and 9 deletions

View File

@ -100,7 +100,9 @@ extension Defaults.Keys {
static let chargingNonCellularProfile = Key<QualityProfile.ID>("chargingNonCellularProfile", default: chargingNonCellularProfileDefault) static let chargingNonCellularProfile = Key<QualityProfile.ID>("chargingNonCellularProfile", default: chargingNonCellularProfileDefault)
static let forceAVPlayerForLiveStreams = Key<Bool>("forceAVPlayerForLiveStreams", default: true) static let forceAVPlayerForLiveStreams = Key<Bool>("forceAVPlayerForLiveStreams", default: true)
static let playerSidebar = Key<PlayerSidebarSetting>("playerSidebar", default: PlayerSidebarSetting.defaultValue) static let playerSidebar = Key<PlayerSidebarSetting>("playerSidebar", default: .defaultValue)
static let showInspector = Key<ShowInspectorSetting>("showInspector", default: .onlyLocal)
static let detailsToolbarPosition = Key<DetailsToolbarPositionSetting>("detailsToolbarPosition", default: .center)
static let playerInstanceID = Key<Instance.ID?>("playerInstance") static let playerInstanceID = Key<Instance.ID?>("playerInstance")
#if os(iOS) #if os(iOS)
@ -329,3 +331,19 @@ enum ThumbnailsQuality: String, CaseIterable, Defaults.Serializable {
enum SystemControlsCommands: String, CaseIterable, Defaults.Serializable { enum SystemControlsCommands: String, CaseIterable, Defaults.Serializable {
case seek, restartAndAdvanceToNext case seek, restartAndAdvanceToNext
} }
enum ShowInspectorSetting: String, Defaults.Serializable {
case always, onlyLocal
}
enum DetailsToolbarPositionSetting: String, CaseIterable, Defaults.Serializable {
case left, center, right
var needsLeftSpacer: Bool {
self == .center || self == .right
}
var needsRightSpacer: Bool {
self == .center || self == .left
}
}

View File

@ -75,7 +75,7 @@ struct InspectorView: View {
Text(detail) Text(detail)
.foregroundColor(.secondary) .foregroundColor(.secondary)
Spacer() Spacer()
let value = Text(value) let value = Text(value).lineLimit(1)
if #available(iOS 15.0, macOS 12.0, *) { if #available(iOS 15.0, macOS 12.0, *) {
value value
#if !os(tvOS) #if !os(tvOS)

View File

@ -83,8 +83,9 @@ struct VideoActions: View {
Text(name) Text(name)
.foregroundColor(.secondary) .foregroundColor(.secondary)
.font(.caption2) .font(.caption2)
.allowsTightening(true)
} }
.padding(.horizontal, 10) .padding(.horizontal, 6)
.padding(.vertical, 5) .padding(.vertical, 5)
.contentShape(Rectangle()) .contentShape(Rectangle())
} }

View File

@ -31,6 +31,7 @@ struct VideoDetails: View {
@EnvironmentObject<RecentsModel> private var recents @EnvironmentObject<RecentsModel> private var recents
@EnvironmentObject<SubscriptionsModel> private var subscriptions @EnvironmentObject<SubscriptionsModel> private var subscriptions
@Default(.detailsToolbarPosition) private var detailsToolbarPosition
@Default(.playerSidebar) private var playerSidebar @Default(.playerSidebar) private var playerSidebar
var video: Video? { var video: Video? {
@ -56,12 +57,17 @@ struct VideoDetails: View {
.transition(.fade) .transition(.fade)
HStack(alignment: .center) { HStack(alignment: .center) {
Spacer() if detailsToolbarPosition.needsLeftSpacer { Spacer() }
VideoDetailsToolbar(video: video, page: $page, sidebarQueue: sidebarQueue) VideoDetailsToolbar(video: video, page: $page, sidebarQueue: sidebarQueue)
Spacer()
if detailsToolbarPosition.needsRightSpacer { Spacer() }
} }
.padding(.leading, detailsToolbarPosition == .left ? 10 : 0)
.padding(.trailing, detailsToolbarPosition == .right ? 10 : 0)
#if os(iOS) #if os(iOS)
.offset(y: bottomPadding ? -SafeArea.insets.bottom : 0) .offset(y: bottomPadding ? -SafeArea.insets.bottom : 0)
#endif #endif
} }
.onChange(of: player.currentItem) { newItem in .onChange(of: player.currentItem) { newItem in

View File

@ -1,3 +1,4 @@
import Defaults
import Foundation import Foundation
struct VideoDetailsTool: Identifiable { struct VideoDetailsTool: Identifiable {
@ -18,7 +19,7 @@ struct VideoDetailsTool: Identifiable {
case .info: case .info:
return video != nil && !video!.isLocal return video != nil && !video!.isLocal
case .inspector: case .inspector:
return false return video == nil || Defaults[.showInspector] == .always || video!.isLocal
case .chapters: case .chapters:
return video != nil && !video!.chapters.isEmpty return video != nil && !video!.chapters.isEmpty
case .comments: case .comments:

View File

@ -2,7 +2,7 @@ import Defaults
import SwiftUI import SwiftUI
struct VideoDetailsToolbar: View { struct VideoDetailsToolbar: View {
static let lowOpacity = 0.33 static let lowOpacity = 0.5
var video: Video? var video: Video?
@Binding var page: VideoDetails.DetailsPage @Binding var page: VideoDetails.DetailsPage
var sidebarQueue: Bool var sidebarQueue: Bool
@ -123,6 +123,7 @@ struct VideoDetailsToolbar: View {
{ {
Text(tool.wrappedValue.name) Text(tool.wrappedValue.name)
.font(.system(size: 14).bold()) .font(.system(size: 14).bold())
.padding(.trailing, 4)
.foregroundColor(.white) .foregroundColor(.white)
.allowsTightening(true) .allowsTightening(true)
.lineLimit(1) .lineLimit(1)
@ -136,7 +137,18 @@ struct VideoDetailsToolbar: View {
) )
} }
var visibleToolsCount: Int {
tools.filter { $0.isAvailable(for: video, sidebarQueue: sidebarQueue) }.count
}
var activeToolID: VideoDetailsTool.ID { var activeToolID: VideoDetailsTool.ID {
activeTool?.id ?? "queue" activeTool?.id ?? "queue"
} }
} }
struct VideoDetailsToolbar_Previews: PreviewProvider {
static var previews: some View {
VideoDetailsToolbar(page: .constant(.queue), sidebarQueue: false)
.injectFixtureEnvironmentObjects()
}
}

View File

@ -6,6 +6,9 @@ struct PlayerSettings: View {
@Default(.playerInstanceID) private var playerInstanceID @Default(.playerInstanceID) private var playerInstanceID
@Default(.playerSidebar) private var playerSidebar @Default(.playerSidebar) private var playerSidebar
@Default(.playerDetailsPageButtonLabelStyle) private var playerDetailsPageButtonLabelStyle
@Default(.detailsToolbarPosition) private var detailsToolbarPosition
@Default(.showInspector) private var showInspector
@Default(.playerControlsLayout) private var playerControlsLayout @Default(.playerControlsLayout) private var playerControlsLayout
@Default(.fullScreenPlayerControlsLayout) private var fullScreenPlayerControlsLayout @Default(.fullScreenPlayerControlsLayout) private var fullScreenPlayerControlsLayout
@Default(.horizontalPlayerGestureEnabled) private var horizontalPlayerGestureEnabled @Default(.horizontalPlayerGestureEnabled) private var horizontalPlayerGestureEnabled
@ -106,6 +109,19 @@ struct PlayerSettings: View {
} }
} }
#if !os(tvOS)
Section(header: SettingsHeader(text: "Video Details").padding(.bottom, videoDetailsHeaderPadding)) {
SettingsHeader(text: "Buttons labels".localized(), secondary: true)
detailsButtonLabelStylePicker
SettingsHeader(text: "Show Inspector".localized(), secondary: true)
showInspectorPicker
SettingsHeader(text: "Pages toolbar position".localized(), secondary: true)
detailsToolbarPositionPicker
}
#endif
#if os(iOS) #if os(iOS)
Section(header: SettingsHeader(text: "Orientation".localized())) { Section(header: SettingsHeader(text: "Orientation".localized())) {
if idiom == .pad { if idiom == .pad {
@ -127,6 +143,14 @@ struct PlayerSettings: View {
} }
} }
private var videoDetailsHeaderPadding: Double {
#if os(macOS)
5.0
#else
0.0
#endif
}
private var sourcePicker: some View { private var sourcePicker: some View {
Picker("Source", selection: $playerInstanceID) { Picker("Source", selection: $playerInstanceID) {
Text("Instance of current account").tag(String?.none) Text("Instance of current account").tag(String?.none)
@ -172,6 +196,31 @@ struct PlayerSettings: View {
.modifier(SettingsPickerModifier()) .modifier(SettingsPickerModifier())
} }
private var detailsButtonLabelStylePicker: some View {
Picker("Buttons labels", selection: $playerDetailsPageButtonLabelStyle) {
Text("Show only icons").tag(PlayerDetailsPageButtonLabelStyle.iconOnly)
Text("Show icons and text when space permits").tag(PlayerDetailsPageButtonLabelStyle.iconAndText)
}
.modifier(SettingsPickerModifier())
}
private var showInspectorPicker: some View {
Picker("Inspector visibility", selection: $showInspector) {
Text("Always").tag(ShowInspectorSetting.always)
Text("Only for local files and URLs").tag(ShowInspectorSetting.onlyLocal)
}
.modifier(SettingsPickerModifier())
}
private var detailsToolbarPositionPicker: some View {
Picker("Pages toolbar position", selection: $detailsToolbarPosition) {
ForEach(DetailsToolbarPositionSetting.allCases, id: \.self) { setting in
Text(setting.rawValue.capitalized).tag(setting)
}
}
.modifier(SettingsPickerModifier())
}
private var horizontalPlayerGestureEnabledToggle: some View { private var horizontalPlayerGestureEnabledToggle: some View {
Toggle("Seek with horizontal swipe on video", isOn: $horizontalPlayerGestureEnabled) Toggle("Seek with horizontal swipe on video", isOn: $horizontalPlayerGestureEnabled)
} }
@ -287,6 +336,7 @@ struct PlayerSettings_Previews: PreviewProvider {
VStack(alignment: .leading) { VStack(alignment: .leading) {
PlayerSettings() PlayerSettings()
} }
.frame(minHeight: 800)
.injectFixtureEnvironmentObjects() .injectFixtureEnvironmentObjects()
} }
} }

View File

@ -223,7 +223,7 @@ struct SettingsView: View {
case .browsing: case .browsing:
return 580 return 580
case .player: case .player:
return 680 return 850
case .quality: case .quality:
return 420 return 420
case .history: case .history: