mirror of
https://github.com/yattee/yattee.git
synced 2024-12-23 05:53:41 +00:00
Actions buttons settings
This commit is contained in:
parent
636e8205fe
commit
5d4983d6d2
@ -188,6 +188,16 @@ extension Defaults.Keys {
|
|||||||
static let playerActionsButtonLabelStyle = Key<ButtonLabelStyle>("playerActionsButtonLabelStyle", default: .iconAndText)
|
static let playerActionsButtonLabelStyle = Key<ButtonLabelStyle>("playerActionsButtonLabelStyle", default: .iconAndText)
|
||||||
|
|
||||||
static let systemControlsCommands = Key<SystemControlsCommands>("systemControlsCommands", default: .restartAndAdvanceToNext)
|
static let systemControlsCommands = Key<SystemControlsCommands>("systemControlsCommands", default: .restartAndAdvanceToNext)
|
||||||
|
static let actionButtonShareEnabled = Key<Bool>("actionButtonShareEnabled", default: true)
|
||||||
|
static let actionButtonAddToPlaylistEnabled = Key<Bool>("actionButtonAddToPlaylistEnabled", default: true)
|
||||||
|
static let actionButtonSubscribeEnabled = Key<Bool>("actionButtonSubscribeEnabled", default: false)
|
||||||
|
static let actionButtonSettingsEnabled = Key<Bool>("actionButtonSettingsEnabled", default: true)
|
||||||
|
static let actionButtonNextEnabled = Key<Bool>("actionButtonNextEnabled", default: true)
|
||||||
|
static let actionButtonHideEnabled = Key<Bool>("actionButtonHideEnabled", default: false)
|
||||||
|
static let actionButtonCloseEnabled = Key<Bool>("actionButtonCloseEnabled", default: true)
|
||||||
|
|
||||||
|
static let actionButtonNextQueueCountEnabled = Key<Bool>("actionButtonNextQueueCountEnabled", default: true)
|
||||||
|
|
||||||
static let mpvCacheSecs = Key<String>("mpvCacheSecs", default: "120")
|
static let mpvCacheSecs = Key<String>("mpvCacheSecs", default: "120")
|
||||||
static let mpvCachePauseWait = Key<String>("mpvCachePauseWait", default: "3")
|
static let mpvCachePauseWait = Key<String>("mpvCachePauseWait", default: "3")
|
||||||
static let mpvEnableLogging = Key<Bool>("mpvEnableLogging", default: false)
|
static let mpvEnableLogging = Key<Bool>("mpvEnableLogging", default: false)
|
||||||
|
@ -2,6 +2,16 @@ import Defaults
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct VideoActions: View {
|
struct VideoActions: View {
|
||||||
|
enum Action: String, CaseIterable {
|
||||||
|
case share
|
||||||
|
case addToPlaylist
|
||||||
|
case subscribe
|
||||||
|
case settings
|
||||||
|
case next
|
||||||
|
case hide
|
||||||
|
case close
|
||||||
|
}
|
||||||
|
|
||||||
@ObservedObject private var accounts = AccountsModel.shared
|
@ObservedObject private var accounts = AccountsModel.shared
|
||||||
var navigation = NavigationModel.shared
|
var navigation = NavigationModel.shared
|
||||||
@ObservedObject private var subscriptions = SubscribedChannelsModel.shared
|
@ObservedObject private var subscriptions = SubscribedChannelsModel.shared
|
||||||
@ -12,60 +22,112 @@ struct VideoActions: View {
|
|||||||
@Default(.openWatchNextOnClose) private var openWatchNextOnClose
|
@Default(.openWatchNextOnClose) private var openWatchNextOnClose
|
||||||
@Default(.playerActionsButtonLabelStyle) private var playerActionsButtonLabelStyle
|
@Default(.playerActionsButtonLabelStyle) private var playerActionsButtonLabelStyle
|
||||||
|
|
||||||
|
@Default(.actionButtonShareEnabled) private var actionButtonShareEnabled
|
||||||
|
@Default(.actionButtonAddToPlaylistEnabled) private var actionButtonAddToPlaylistEnabled
|
||||||
|
@Default(.actionButtonSubscribeEnabled) private var actionButtonSubscribeEnabled
|
||||||
|
@Default(.actionButtonSettingsEnabled) private var actionButtonSettingsEnabled
|
||||||
|
@Default(.actionButtonNextEnabled) private var actionButtonNextEnabled
|
||||||
|
@Default(.actionButtonHideEnabled) private var actionButtonHideEnabled
|
||||||
|
@Default(.actionButtonCloseEnabled) private var actionButtonCloseEnabled
|
||||||
|
@Default(.actionButtonNextQueueCountEnabled) private var actionButtonNextQueueCountEnabled
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack(spacing: 6) {
|
HStack(spacing: 6) {
|
||||||
if let video {
|
ForEach(Action.allCases, id: \.self) { action in
|
||||||
#if !os(tvOS)
|
actionBody(action)
|
||||||
if video.isShareable {
|
.frame(maxWidth: .infinity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.frame(height: 50)
|
||||||
|
.borderBottom(height: 0.5, color: Color("ControlsBorderColor"))
|
||||||
|
.foregroundColor(.accentColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isVisible(_ action: Action) -> Bool {
|
||||||
|
switch action {
|
||||||
|
case .share:
|
||||||
|
return actionButtonShareEnabled
|
||||||
|
case .addToPlaylist:
|
||||||
|
return actionButtonAddToPlaylistEnabled
|
||||||
|
case .subscribe:
|
||||||
|
return actionButtonSubscribeEnabled
|
||||||
|
case .settings:
|
||||||
|
return actionButtonSettingsEnabled
|
||||||
|
case .next:
|
||||||
|
return actionButtonNextEnabled
|
||||||
|
case .hide:
|
||||||
|
return actionButtonHideEnabled
|
||||||
|
case .close:
|
||||||
|
return actionButtonCloseEnabled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isActionable(_ action: Action) -> Bool {
|
||||||
|
switch action {
|
||||||
|
case .share:
|
||||||
|
return video?.isShareable ?? false
|
||||||
|
case .addToPlaylist:
|
||||||
|
return !(video?.isLocal ?? true)
|
||||||
|
case .subscribe:
|
||||||
|
return !(video?.isLocal ?? true) && accounts.signedIn && accounts.app.supportsSubscriptions
|
||||||
|
case .settings:
|
||||||
|
return video != nil
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewBuilder func actionBody(_ action: Action) -> some View {
|
||||||
|
if isVisible(action) {
|
||||||
|
Group {
|
||||||
|
switch action {
|
||||||
|
case .share:
|
||||||
ShareButton(contentItem: .init(video: video)) {
|
ShareButton(contentItem: .init(video: video)) {
|
||||||
actionButton("Share", systemImage: "square.and.arrow.up")
|
actionButton("Share", systemImage: "square.and.arrow.up")
|
||||||
}
|
}
|
||||||
|
case .addToPlaylist:
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if !video.isLocal {
|
|
||||||
if accounts.signedIn, accounts.app.supportsUserPlaylists {
|
|
||||||
actionButton("Add", systemImage: "text.badge.plus") {
|
actionButton("Add", systemImage: "text.badge.plus") {
|
||||||
|
guard let video else { return }
|
||||||
navigation.presentAddToPlaylist(video)
|
navigation.presentAddToPlaylist(video)
|
||||||
}
|
}
|
||||||
Spacer()
|
case .subscribe:
|
||||||
}
|
if let channel = video?.channel,
|
||||||
if accounts.signedIn, accounts.app.supportsSubscriptions {
|
subscriptions.isSubscribing(channel.id)
|
||||||
if subscriptions.isSubscribing(video.channel.id) {
|
{
|
||||||
actionButton("Unsubscribe", systemImage: "xmark.circle") {
|
actionButton("Unsubscribe", systemImage: "xmark.circle") {
|
||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
subscriptions.unsubscribe(video.channel.id)
|
subscriptions.unsubscribe(channel.id)
|
||||||
#else
|
#else
|
||||||
navigation.presentUnsubscribeAlert(video.channel, subscriptions: subscriptions)
|
navigation.presentUnsubscribeAlert(channel, subscriptions: subscriptions)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
actionButton("Subscribe", systemImage: "star.circle") {
|
actionButton("Subscribe", systemImage: "star.circle") {
|
||||||
|
guard let video else { return }
|
||||||
|
|
||||||
subscriptions.subscribe(video.channel.id) {
|
subscriptions.subscribe(video.channel.id) {
|
||||||
navigation.sidebarSectionChanged.toggle()
|
navigation.sidebarSectionChanged.toggle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Spacer()
|
case .settings:
|
||||||
|
actionButton("Settings", systemImage: "gear") {
|
||||||
|
withAnimation(ControlOverlaysModel.animation) {
|
||||||
|
ControlOverlaysModel.shared.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
case .next:
|
||||||
Spacer()
|
actionButton(nextLabel, systemImage: Constants.nextSystemImage) {
|
||||||
}
|
|
||||||
actionButton("Next", systemImage: Constants.nextSystemImage) {
|
|
||||||
WatchNextViewModel.shared.userInteractedOpen(player.currentItem)
|
WatchNextViewModel.shared.userInteractedOpen(player.currentItem)
|
||||||
}
|
}
|
||||||
|
case .hide:
|
||||||
Spacer()
|
|
||||||
|
|
||||||
actionButton("Hide", systemImage: "chevron.down") {
|
actionButton("Hide", systemImage: "chevron.down") {
|
||||||
player.hide(animate: true)
|
player.hide(animate: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer()
|
case .close:
|
||||||
|
|
||||||
actionButton("Close", systemImage: "xmark") {
|
actionButton("Close", systemImage: "xmark") {
|
||||||
if openWatchNextOnClose {
|
if openWatchNextOnClose {
|
||||||
player.pause()
|
player.pause()
|
||||||
@ -75,12 +137,17 @@ struct VideoActions: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.horizontal)
|
}
|
||||||
.multilineTextAlignment(.center)
|
.disabled(!isActionable(action))
|
||||||
.frame(maxWidth: .infinity)
|
}
|
||||||
.frame(height: 50)
|
}
|
||||||
.borderBottom(height: 0.5, color: Color("ControlsBorderColor"))
|
|
||||||
.foregroundColor(.accentColor)
|
var nextLabel: String {
|
||||||
|
if actionButtonNextQueueCountEnabled, !player.queue.isEmpty {
|
||||||
|
return "\("Next".localized()) • \(player.queue.count)"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Next".localized()
|
||||||
}
|
}
|
||||||
|
|
||||||
func actionButton(
|
func actionButton(
|
||||||
|
@ -33,6 +33,14 @@ struct PlayerSettings: View {
|
|||||||
@Default(.openWatchNextOnFinishedWatching) private var openWatchNextOnFinishedWatching
|
@Default(.openWatchNextOnFinishedWatching) private var openWatchNextOnFinishedWatching
|
||||||
@Default(.openWatchNextOnFinishedWatchingDelay) private var openWatchNextOnFinishedWatchingDelay
|
@Default(.openWatchNextOnFinishedWatchingDelay) private var openWatchNextOnFinishedWatchingDelay
|
||||||
|
|
||||||
|
@Default(.actionButtonShareEnabled) private var actionButtonShareEnabled
|
||||||
|
@Default(.actionButtonSubscribeEnabled) private var actionButtonSubscribeEnabled
|
||||||
|
@Default(.actionButtonNextEnabled) private var actionButtonNextEnabled
|
||||||
|
@Default(.actionButtonCloseEnabled) private var actionButtonCloseEnabled
|
||||||
|
@Default(.actionButtonAddToPlaylistEnabled) private var actionButtonAddToPlaylistEnabled
|
||||||
|
@Default(.actionButtonSettingsEnabled) private var actionButtonSettingsEnabled
|
||||||
|
@Default(.actionButtonHideEnabled) private var actionButtonHideEnabled
|
||||||
|
@Default(.actionButtonNextQueueCountEnabled) private var actionButtonNextQueueCountEnabled
|
||||||
@ObservedObject private var accounts = AccountsModel.shared
|
@ObservedObject private var accounts = AccountsModel.shared
|
||||||
private var player = PlayerModel.shared
|
private var player = PlayerModel.shared
|
||||||
|
|
||||||
@ -75,6 +83,13 @@ struct PlayerSettings: View {
|
|||||||
systemControlsCommandsPicker
|
systemControlsCommandsPicker
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !os(tvOS)
|
||||||
|
Section(header: SettingsHeader(text: "Actions Buttons")) {
|
||||||
|
actionButtonToggles
|
||||||
|
}
|
||||||
|
actionButtonNextQueueCountEnabledToggle
|
||||||
|
#endif
|
||||||
|
|
||||||
Section(header: SettingsHeader(text: "Watch Next")) {
|
Section(header: SettingsHeader(text: "Watch Next")) {
|
||||||
openWatchNextOnFinishedWatchingToggle
|
openWatchNextOnFinishedWatchingToggle
|
||||||
openWatchNextOnFinishedWatchingDelayTextField
|
openWatchNextOnFinishedWatchingDelayTextField
|
||||||
@ -210,6 +225,24 @@ struct PlayerSettings: View {
|
|||||||
.multilineTextAlignment(.trailing)
|
.multilineTextAlignment(.trailing)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ViewBuilder private var actionButtonToggles: some View {
|
||||||
|
actionButtonToggle("Share", $actionButtonShareEnabled)
|
||||||
|
actionButtonToggle("Add to Playlist", $actionButtonAddToPlaylistEnabled)
|
||||||
|
actionButtonToggle("Subscribe/Unsubscribe", $actionButtonSubscribeEnabled)
|
||||||
|
actionButtonToggle("Settings", $actionButtonSettingsEnabled)
|
||||||
|
actionButtonToggle("Watch Next", $actionButtonNextEnabled)
|
||||||
|
actionButtonToggle("Hide player", $actionButtonHideEnabled)
|
||||||
|
actionButtonToggle("Close video", $actionButtonCloseEnabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func actionButtonToggle(_ name: String, _ value: Binding<Bool>) -> some View {
|
||||||
|
Toggle(name, isOn: value)
|
||||||
|
}
|
||||||
|
|
||||||
|
var actionButtonNextQueueCountEnabledToggle: some View {
|
||||||
|
Toggle("Show queue items count in Watch Next button label", isOn: $actionButtonNextQueueCountEnabled)
|
||||||
|
}
|
||||||
|
|
||||||
private var sidebarPicker: some View {
|
private var sidebarPicker: some View {
|
||||||
Picker("Sidebar", selection: $playerSidebar) {
|
Picker("Sidebar", selection: $playerSidebar) {
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
|
@ -21,8 +21,10 @@ struct ShareButton<LabelView: View>: View {
|
|||||||
|
|
||||||
@ViewBuilder var body: some View {
|
@ViewBuilder var body: some View {
|
||||||
// TODO: this should work with other content item types
|
// TODO: this should work with other content item types
|
||||||
if let video = contentItem.video, !video.localStreamIsFile {
|
|
||||||
Menu {
|
Menu {
|
||||||
|
if let video = contentItem.video,
|
||||||
|
!video.localStreamIsFile
|
||||||
|
{
|
||||||
if video.localStreamIsRemoteURL {
|
if video.localStreamIsRemoteURL {
|
||||||
remoteURLAction
|
remoteURLAction
|
||||||
} else {
|
} else {
|
||||||
@ -32,6 +34,7 @@ struct ShareButton<LabelView: View>: View {
|
|||||||
youtubeActions
|
youtubeActions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} label: {
|
} label: {
|
||||||
label
|
label
|
||||||
}
|
}
|
||||||
@ -40,7 +43,6 @@ struct ShareButton<LabelView: View>: View {
|
|||||||
.frame(maxWidth: 60)
|
.frame(maxWidth: 60)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private var instanceActions: some View {
|
private var instanceActions: some View {
|
||||||
Group {
|
Group {
|
||||||
|
Loading…
Reference in New Issue
Block a user