1
0
mirror of https://github.com/yattee/yattee.git synced 2024-12-15 06:40:32 +05:30
yattee/Shared/Player/Video Details/VideoActions.swift

226 lines
8.6 KiB
Swift
Raw Normal View History

2022-11-13 23:22:15 +05:30
import Defaults
import SwiftUI
struct VideoActions: View {
2022-12-19 15:59:18 +05:30
enum Action: String, CaseIterable {
case share
case addToPlaylist
case subscribe
2023-04-22 20:03:08 +05:30
case fullScreen
case pip
#if os(iOS)
case lockOrientation
#endif
case restart
case advanceToNextItem
case musicMode
2022-12-19 15:59:18 +05:30
case settings
case hide
case close
}
@ObservedObject private var accounts = AccountsModel.shared
var navigation = NavigationModel.shared
2022-12-11 20:45:42 +05:30
@ObservedObject private var subscriptions = SubscribedChannelsModel.shared
@ObservedObject private var player = PlayerModel.shared
2022-11-13 23:22:15 +05:30
var video: Video?
@Default(.playerActionsButtonLabelStyle) private var playerActionsButtonLabelStyle
2022-12-19 15:59:18 +05:30
@Default(.actionButtonShareEnabled) private var actionButtonShareEnabled
@Default(.actionButtonAddToPlaylistEnabled) private var actionButtonAddToPlaylistEnabled
@Default(.actionButtonSubscribeEnabled) private var actionButtonSubscribeEnabled
@Default(.actionButtonSettingsEnabled) private var actionButtonSettingsEnabled
2023-04-22 20:03:08 +05:30
@Default(.actionButtonFullScreenEnabled) private var actionButtonFullScreenEnabled
@Default(.actionButtonPipEnabled) private var actionButtonPipEnabled
@Default(.actionButtonLockOrientationEnabled) private var actionButtonLockOrientationEnabled
@Default(.actionButtonRestartEnabled) private var actionButtonRestartEnabled
@Default(.actionButtonAdvanceToNextItemEnabled) private var actionButtonAdvanceToNextItemEnabled
@Default(.actionButtonMusicModeEnabled) private var actionButtonMusicModeEnabled
2022-12-19 15:59:18 +05:30
@Default(.actionButtonHideEnabled) private var actionButtonHideEnabled
@Default(.actionButtonCloseEnabled) private var actionButtonCloseEnabled
2022-11-13 23:22:15 +05:30
var body: some View {
2022-12-19 00:09:03 +05:30
HStack(spacing: 6) {
2022-12-19 15:59:18 +05:30
ForEach(Action.allCases, id: \.self) { action in
actionBody(action)
.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
2023-04-22 20:03:08 +05:30
case .fullScreen:
return actionButtonFullScreenEnabled
case .pip:
return actionButtonPipEnabled
#if os(iOS)
case .lockOrientation:
return actionButtonLockOrientationEnabled
#endif
case .restart:
return actionButtonRestartEnabled
case .advanceToNextItem:
return actionButtonAdvanceToNextItemEnabled
case .musicMode:
return actionButtonMusicModeEnabled
2022-12-19 15:59:18 +05:30
case .hide:
return actionButtonHideEnabled
case .close:
return actionButtonCloseEnabled
}
}
2022-11-13 23:22:15 +05:30
2022-12-19 15:59:18 +05:30
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
2023-04-24 15:39:22 +05:30
case .fullScreen:
return video != nil
case .pip:
return video != nil
2023-04-22 20:03:08 +05:30
case .advanceToNextItem:
return player.isAdvanceToNextItemAvailable
2023-04-24 15:39:22 +05:30
case .restart:
return video != nil
case .musicMode:
return video != nil
2022-12-19 15:59:18 +05:30
default:
return true
}
}
@ViewBuilder func actionBody(_ action: Action) -> some View {
if isVisible(action) {
Group {
switch action {
case .share:
2022-12-19 18:05:37 +05:30
#if os(tvOS)
EmptyView()
#else
ShareButton(contentItem: .init(video: video)) {
actionButton("Share", systemImage: "square.and.arrow.up")
}
#endif
2022-12-19 15:59:18 +05:30
case .addToPlaylist:
actionButton("Add", systemImage: "text.badge.plus") {
guard let video else { return }
navigation.presentAddToPlaylist(video)
2022-11-14 04:10:18 +05:30
}
2022-12-19 15:59:18 +05:30
case .subscribe:
if let channel = video?.channel,
subscriptions.isSubscribing(channel.id)
{
actionButton("Unsubscribe", systemImage: "xmark.circle") {
#if os(tvOS)
subscriptions.unsubscribe(channel.id)
#else
navigation.presentUnsubscribeAlert(channel, subscriptions: subscriptions)
#endif
}
} else {
actionButton("Subscribe", systemImage: "star.circle") {
guard let video else { return }
2022-11-14 02:25:19 +05:30
2022-12-19 15:59:18 +05:30
subscriptions.subscribe(video.channel.id) {
navigation.sidebarSectionChanged.toggle()
}
2022-11-13 23:22:15 +05:30
}
2022-11-14 02:25:19 +05:30
}
2023-04-22 20:03:08 +05:30
case .fullScreen:
actionButton("Fullscreen", systemImage: player.fullscreenImage, action: player.toggleFullScreenAction)
case .pip:
actionButton("PiP", systemImage: player.pipImage, action: player.togglePiPAction)
#if os(iOS)
case .lockOrientation:
actionButton("Lock", systemImage: player.lockOrientationImage, active: player.lockedOrientation != nil, action: player.lockOrientationAction)
#endif
case .restart:
actionButton("Replay", systemImage: "backward.end.fill", action: player.replayAction)
case .advanceToNextItem:
actionButton("Next", systemImage: "forward.fill") {
player.advanceToNextItem()
}
case .musicMode:
actionButton("Music", systemImage: "music.note", active: player.musicMode, action: player.toggleMusicMode)
2022-12-19 15:59:18 +05:30
case .settings:
actionButton("Settings", systemImage: "gear") {
withAnimation(ControlOverlaysModel.animation) {
2022-12-22 01:46:47 +05:30
#if os(tvOS)
ControlOverlaysModel.shared.show()
#else
navigation.presentingPlaybackSettings = true
#endif
2022-12-19 15:59:18 +05:30
}
}
case .hide:
actionButton("Hide", systemImage: "chevron.down") {
player.hide(animate: true)
}
case .close:
actionButton("Close", systemImage: "xmark") {
2023-04-22 17:26:25 +05:30
player.closeCurrentItem()
2022-11-13 23:22:15 +05:30
}
}
}
2022-12-19 15:59:18 +05:30
.disabled(!isActionable(action))
}
}
2022-11-13 23:22:15 +05:30
func actionButton(
_ name: String,
systemImage: String,
2023-04-22 20:03:08 +05:30
active: Bool = false,
2022-11-13 23:22:15 +05:30
action: @escaping () -> Void = {}
) -> some View {
Button(action: action) {
VStack(spacing: 3) {
Image(systemName: systemImage)
.frame(width: 20, height: 20)
2023-04-22 20:03:08 +05:30
.foregroundColor(active ? Color("AppRedColor") : .accentColor)
if playerActionsButtonLabelStyle.text {
2022-11-19 04:36:13 +05:30
Text(name.localized())
2023-04-22 20:03:08 +05:30
.foregroundColor(active ? Color("AppRedColor") : .secondary)
.font(.caption2)
.allowsTightening(true)
}
2022-11-13 23:22:15 +05:30
}
.padding(.horizontal, playerActionsButtonLabelStyle.text ? 6 : 12)
.padding(.vertical, playerActionsButtonLabelStyle.text ? 5 : 10)
2022-11-13 23:22:15 +05:30
.contentShape(Rectangle())
}
.buttonStyle(.plain)
.accessibilityLabel(Text(name))
}
}
struct VideoActions_Previews: PreviewProvider {
static var previews: some View {
VideoActions()
.injectFixtureEnvironmentObjects()
}
}