diff --git a/Model/Applications/PipedAPI.swift b/Model/Applications/PipedAPI.swift index b70bc29f..924b7455 100644 --- a/Model/Applications/PipedAPI.swift +++ b/Model/Applications/PipedAPI.swift @@ -360,7 +360,7 @@ final class PipedAPI: Service, ObservableObject, VideosAPI { } return ChannelPlaylist( id: id, - title: details["name"]!.stringValue, + title: details["name"]?.stringValue ?? "", thumbnailURL: thumbnailURL, channel: extractChannel(from: json)!, videos: videos, diff --git a/Shared/Playlists/AddToPlaylistView.swift b/Shared/Playlists/AddToPlaylistView.swift index 22ab57c9..a47d3773 100644 --- a/Shared/Playlists/AddToPlaylistView.swift +++ b/Shared/Playlists/AddToPlaylistView.swift @@ -9,6 +9,7 @@ struct AddToPlaylistView: View { @State private var error = "" @State private var presentingErrorAlert = false + @State private var submitButtonDisabled = false @Environment(\.colorScheme) private var colorScheme @Environment(\.presentationMode) private var presentationMode @@ -122,7 +123,7 @@ struct AddToPlaylistView: View { HStack { Spacer() Button("Add to Playlist", action: addToPlaylist) - .disabled(selectedPlaylist.isNil) + .disabled(submitButtonDisabled || selectedPlaylist.isNil) .padding(.top, 30) .alert(isPresented: $presentingErrorAlert) { Alert( @@ -165,6 +166,8 @@ struct AddToPlaylistView: View { Defaults[.lastUsedPlaylistID] = id + submitButtonDisabled = true + model.addVideo( playlistID: id, videoID: video.videoID, @@ -174,6 +177,7 @@ struct AddToPlaylistView: View { onFailure: { requestError in error = "(\(requestError.httpStatusCode ?? -1)) \(requestError.userMessage)" presentingErrorAlert = true + submitButtonDisabled = false } ) } diff --git a/Shared/Playlists/PlaylistFormView.swift b/Shared/Playlists/PlaylistFormView.swift index d6180f78..a1a0aef8 100644 --- a/Shared/Playlists/PlaylistFormView.swift +++ b/Shared/Playlists/PlaylistFormView.swift @@ -125,13 +125,15 @@ struct PlaylistFormView: View { .disabled(editing && !accounts.app.userPlaylistsAreEditable) } - HStack { - Text("Visibility") - .frame(maxWidth: .infinity, alignment: .leading) + if accounts.app.userPlaylistsHaveVisibility { + HStack { + Text("Visibility") + .frame(maxWidth: .infinity, alignment: .leading) - visibilityFormItem + visibilityFormItem + } + .padding(.top, 10) } - .padding(.top, 10) HStack { Spacer() diff --git a/Shared/Playlists/PlaylistsView.swift b/Shared/Playlists/PlaylistsView.swift index 62efc6ed..0a3deaae 100644 --- a/Shared/Playlists/PlaylistsView.swift +++ b/Shared/Playlists/PlaylistsView.swift @@ -11,6 +11,8 @@ struct PlaylistsView: View { @State private var showingEditPlaylist = false @State private var editedPlaylist: Playlist? + @StateObject private var store = Store() + @EnvironmentObject private var accounts @EnvironmentObject private var player @EnvironmentObject private var model @@ -18,7 +20,36 @@ struct PlaylistsView: View { @Namespace private var focusNamespace var items: [ContentItem] { - ContentItem.array(of: currentPlaylist?.videos ?? []) + var videos = currentPlaylist?.videos ?? [] + + if videos.isEmpty { + videos = store.item?.videos ?? [] + if !player.accounts.app.userPlaylistsEndpointIncludesVideos { + var i = 0 + + for index in videos.indices { + var video = videos[index] + video.indexID = "\(i)" + i += 1 + videos[index] = video + } + } + } + + return ContentItem.array(of: videos) + } + + private var resource: Resource? { + guard !player.accounts.app.userPlaylistsEndpointIncludesVideos, + let playlist = currentPlaylist + else { + return nil + } + + let resource = player.accounts.api.playlist(playlist.id) + resource?.addObserver(store) + + return resource } var body: some View { @@ -112,10 +143,17 @@ struct PlaylistsView: View { #endif .onAppear { model.load() + resource?.load() } .onChange(of: accounts.current) { _ in model.load(force: true) } + .onChange(of: selectedPlaylistID) { _ in + resource?.load() + } + .onChange(of: model.reloadPlaylists) { _ in + resource?.load() + } #if os(iOS) .navigationBarTitleDisplayMode(RefreshControl.navigationBarTitleDisplayMode) #endif