mirror of
https://github.com/yattee/yattee.git
synced 2025-10-30 04:01:56 +00:00
Adding/removing videos to/from playlists
This commit is contained in:
97
Apple TV/AddToPlaylistView.swift
Normal file
97
Apple TV/AddToPlaylistView.swift
Normal file
@@ -0,0 +1,97 @@
|
||||
import Defaults
|
||||
import Siesta
|
||||
import SwiftUI
|
||||
|
||||
struct AddToPlaylistView: View {
|
||||
@ObservedObject private var store = Store<[Playlist]>()
|
||||
|
||||
@State private var selectedPlaylist: Playlist?
|
||||
|
||||
@Default(.videoIDToAddToPlaylist) private var videoID
|
||||
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
var resource: Resource {
|
||||
InvidiousAPI.shared.playlists
|
||||
}
|
||||
|
||||
init() {
|
||||
resource.addObserver(store)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
Spacer()
|
||||
|
||||
VStack {
|
||||
Spacer()
|
||||
|
||||
if !resource.isLoading && store.collection.isEmpty {
|
||||
CoverSectionView("You have no Playlists", inline: true) {
|
||||
Text("Open \"Playlists\" tab to create new one")
|
||||
.foregroundColor(.secondary)
|
||||
.multilineTextAlignment(.center)
|
||||
}
|
||||
Button("Go back") {
|
||||
dismiss()
|
||||
}
|
||||
.padding()
|
||||
} else if !store.collection.isEmpty {
|
||||
CoverSectionView("Add to Playlist", inline: true) { selectPlaylistButton }
|
||||
|
||||
CoverSectionRowView {
|
||||
Button("Add", action: addToPlaylist)
|
||||
.disabled(currentPlaylist == nil)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.frame(maxWidth: 1200)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.background(.thinMaterial)
|
||||
.onAppear {
|
||||
resource.loadIfNeeded()?.onSuccess { _ in
|
||||
selectedPlaylist = store.collection.first
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var selectPlaylistButton: some View {
|
||||
Button(currentPlaylist?.title ?? "Select playlist") {
|
||||
guard currentPlaylist != nil else {
|
||||
return
|
||||
}
|
||||
|
||||
self.selectedPlaylist = store.collection.next(after: currentPlaylist!)
|
||||
}
|
||||
.contextMenu {
|
||||
ForEach(store.collection) { playlist in
|
||||
Button(playlist.title) {
|
||||
self.selectedPlaylist = playlist
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var currentPlaylist: Playlist? {
|
||||
selectedPlaylist ?? store.collection.first
|
||||
}
|
||||
|
||||
func addToPlaylist() {
|
||||
guard currentPlaylist != nil else {
|
||||
return
|
||||
}
|
||||
|
||||
let resource = InvidiousAPI.shared.playlistVideos(currentPlaylist!.id)
|
||||
let body = ["videoId": videoID]
|
||||
|
||||
resource.request(.post, json: body).onSuccess { _ in
|
||||
Defaults.reset(.videoIDToAddToPlaylist)
|
||||
InvidiousAPI.shared.playlists.load()
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ struct PlaylistsView: View {
|
||||
@ObservedObject private var store = Store<[Playlist]>()
|
||||
|
||||
@Default(.selectedPlaylistID) private var selectedPlaylistID
|
||||
@State private var selectedPlaylist: Playlist?
|
||||
|
||||
@State private var showingNewPlaylist = false
|
||||
@State private var createdPlaylist: Playlist?
|
||||
@@ -26,18 +25,37 @@ struct PlaylistsView: View {
|
||||
Section {
|
||||
VStack(alignment: .center, spacing: 2) {
|
||||
HStack {
|
||||
selectPlaylistButton
|
||||
if store.collection.isEmpty {
|
||||
Text("No Playlists")
|
||||
.foregroundColor(.secondary)
|
||||
} else {
|
||||
Text("Current Playlist")
|
||||
.foregroundColor(.secondary)
|
||||
|
||||
selectPlaylistButton
|
||||
}
|
||||
|
||||
if currentPlaylist != nil {
|
||||
editPlaylistButton
|
||||
}
|
||||
|
||||
newPlaylistButton
|
||||
.padding(.leading, 40)
|
||||
}
|
||||
.scaleEffect(0.85)
|
||||
|
||||
if currentPlaylist != nil {
|
||||
VideosView(videos: currentPlaylist!.videos)
|
||||
if currentPlaylist!.videos.isEmpty {
|
||||
Spacer()
|
||||
|
||||
Text("Playlist is empty\n\nTap and hold on a video and then tap \"Add to Playlist\"")
|
||||
.foregroundColor(.secondary)
|
||||
.multilineTextAlignment(.center)
|
||||
|
||||
Spacer()
|
||||
} else {
|
||||
VideosView(videos: currentPlaylist!.videos)
|
||||
}
|
||||
} else {
|
||||
Spacer()
|
||||
}
|
||||
@@ -57,7 +75,6 @@ struct PlaylistsView: View {
|
||||
}
|
||||
|
||||
func selectPlaylist(_ id: String?) {
|
||||
selectedPlaylist = store.collection.first { $0.id == id }
|
||||
selectedPlaylistID = id
|
||||
}
|
||||
|
||||
@@ -86,7 +103,7 @@ struct PlaylistsView: View {
|
||||
}
|
||||
|
||||
var currentPlaylist: Playlist? {
|
||||
selectedPlaylist ?? store.collection.first
|
||||
store.collection.first { $0.id == selectedPlaylistID } ?? store.collection.first
|
||||
}
|
||||
|
||||
var selectPlaylistButton: some View {
|
||||
@@ -111,13 +128,19 @@ struct PlaylistsView: View {
|
||||
self.editedPlaylist = self.currentPlaylist
|
||||
self.showingEditPlaylist = true
|
||||
}) {
|
||||
Image(systemName: "pencil")
|
||||
HStack(spacing: 8) {
|
||||
Image(systemName: "pencil")
|
||||
Text("Edit")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var newPlaylistButton: some View {
|
||||
Button(action: { self.showingNewPlaylist = true }) {
|
||||
Image(systemName: "plus")
|
||||
HStack(spacing: 8) {
|
||||
Image(systemName: "plus")
|
||||
Text("New Playlist")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,14 @@ struct TrendingView: View {
|
||||
Section {
|
||||
VStack(alignment: .center, spacing: 2) {
|
||||
HStack {
|
||||
Text("Category")
|
||||
.foregroundColor(.secondary)
|
||||
|
||||
categoryButton
|
||||
|
||||
Text("Country")
|
||||
.foregroundColor(.secondary)
|
||||
|
||||
countryFlag
|
||||
countryButton
|
||||
}
|
||||
|
||||
@@ -9,6 +9,9 @@ struct VideoContextMenuView: View {
|
||||
@Default(.openVideoID) var openVideoID
|
||||
@Default(.showingVideoDetails) var showDetails
|
||||
|
||||
@Default(.showingAddToPlaylist) var showingAddToPlaylist
|
||||
@Default(.videoIDToAddToPlaylist) var videoIDToAddToPlaylist
|
||||
|
||||
var body: some View {
|
||||
if tabSelection == .channel {
|
||||
closeChannelButton(from: video)
|
||||
@@ -16,9 +19,12 @@ struct VideoContextMenuView: View {
|
||||
openChannelButton(from: video)
|
||||
}
|
||||
|
||||
Button("Open video details") {
|
||||
openVideoID = video.id
|
||||
showDetails = true
|
||||
openVideoDetailsButton
|
||||
|
||||
if tabSelection == .playlists {
|
||||
removeFromPlaylistButton
|
||||
} else {
|
||||
addToPlaylistButton
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,4 +40,27 @@ struct VideoContextMenuView: View {
|
||||
Defaults.reset(.openChannel)
|
||||
}
|
||||
}
|
||||
|
||||
var openVideoDetailsButton: some View {
|
||||
Button("Open video details") {
|
||||
openVideoID = video.id
|
||||
showDetails = true
|
||||
}
|
||||
}
|
||||
|
||||
var addToPlaylistButton: some View {
|
||||
Button("Add to playlist...") {
|
||||
videoIDToAddToPlaylist = video.id
|
||||
showingAddToPlaylist = true
|
||||
}
|
||||
}
|
||||
|
||||
var removeFromPlaylistButton: some View {
|
||||
Button("Remove from playlist", role: .destructive) {
|
||||
let resource = InvidiousAPI.shared.playlistVideo(Defaults[.selectedPlaylistID]!, video.indexID!)
|
||||
resource.request(.delete).onSuccess { _ in
|
||||
InvidiousAPI.shared.playlists.load()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ struct VideoDetailsView: View {
|
||||
|
||||
HStack {
|
||||
NavigationLink(destination: PlayerView(id: video.id)) {
|
||||
HStack(spacing: 10) {
|
||||
HStack(spacing: 8) {
|
||||
Image(systemName: "play.rectangle.fill")
|
||||
|
||||
Text("Play")
|
||||
|
||||
@@ -7,15 +7,20 @@ struct VideosView: View {
|
||||
@Default(.layout) var layout
|
||||
@Default(.tabSelection) var tabSelection
|
||||
|
||||
@Default(.showingAddToPlaylist) var showingAddToPlaylist
|
||||
|
||||
var videos: [Video]
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
VStack {
|
||||
if layout == .cells {
|
||||
VideosCellsView(videos: videos, columns: self.profile.cellsColumns)
|
||||
} else {
|
||||
VideosListView(videos: videos)
|
||||
}
|
||||
}
|
||||
.fullScreenCover(isPresented: $showingAddToPlaylist) {
|
||||
AddToPlaylistView()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user