Adding/removing videos to/from playlists

This commit is contained in:
Arkadiusz Fal
2021-07-09 16:53:53 +02:00
parent 31bd2f7fe6
commit f397b13720
12 changed files with 218 additions and 17 deletions

View 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()
}
}
}

View File

@@ -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")
}
}
}
}

View File

@@ -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
}

View File

@@ -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()
}
}
}
}

View File

@@ -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")

View File

@@ -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()
}
}
}