mirror of
https://github.com/yattee/yattee.git
synced 2026-01-03 02:12:31 +00:00
Creating playlists
This commit is contained in:
@@ -1,17 +1,17 @@
|
||||
import SwiftUI
|
||||
|
||||
struct OptionRowView<Content: View>: View {
|
||||
let label: String
|
||||
struct CoverSectionRowView<Content: View>: View {
|
||||
let label: String?
|
||||
let controlView: Content
|
||||
|
||||
init(_ label: String, @ViewBuilder controlView: @escaping () -> Content) {
|
||||
init(_ label: String? = nil, @ViewBuilder controlView: @escaping () -> Content) {
|
||||
self.label = label
|
||||
self.controlView = controlView()
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
Text(label)
|
||||
Text(label ?? "")
|
||||
Spacer()
|
||||
controlView
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import SwiftUI
|
||||
|
||||
struct OptionsSectionView<Content: View>: View {
|
||||
struct CoverSectionView<Content: View>: View {
|
||||
let title: String?
|
||||
|
||||
let rowsView: Content
|
||||
74
Apple TV/NewPlaylistView.swift
Normal file
74
Apple TV/NewPlaylistView.swift
Normal file
@@ -0,0 +1,74 @@
|
||||
import SwiftUI
|
||||
import SwiftyJSON
|
||||
|
||||
struct NewPlaylistView: View {
|
||||
@State private var name = ""
|
||||
@State private var visibility = PlaylistVisibility.public
|
||||
|
||||
@State private var valid = false
|
||||
|
||||
@Binding var createdPlaylist: Playlist?
|
||||
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
Spacer()
|
||||
|
||||
VStack {
|
||||
Spacer()
|
||||
|
||||
CoverSectionView("New Playlist") {
|
||||
CoverSectionRowView("Name") {
|
||||
TextField("Playlist Name", text: $name, onCommit: validate)
|
||||
.frame(maxWidth: 450)
|
||||
}
|
||||
|
||||
CoverSectionRowView("Visibility") { visibilityButton }
|
||||
}
|
||||
|
||||
CoverSectionRowView {
|
||||
Button("Create", action: createPlaylistAndDismiss).disabled(!valid)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.frame(maxWidth: 800)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.background(.thinMaterial)
|
||||
.onAppear {
|
||||
createdPlaylist = nil
|
||||
}
|
||||
}
|
||||
|
||||
func validate() {
|
||||
valid = !name.isEmpty
|
||||
}
|
||||
|
||||
func createPlaylistAndDismiss() {
|
||||
let resource = InvidiousAPI.shared.playlists
|
||||
let body = ["title": name, "privacy": visibility.rawValue]
|
||||
|
||||
resource.request(.post, json: body).onSuccess { response in
|
||||
if let playlist: Playlist = response.typedContent() {
|
||||
createdPlaylist = playlist
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var visibilityButton: some View {
|
||||
Button(self.visibility.name) {
|
||||
self.visibility = self.visibility.next()
|
||||
}
|
||||
.contextMenu {
|
||||
ForEach(PlaylistVisibility.allCases) { visibility in
|
||||
Button(visibility.name) {
|
||||
self.visibility = visibility
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,12 +18,12 @@ struct OptionsView: View {
|
||||
|
||||
tabSelectionOptions
|
||||
|
||||
OptionsSectionView("View Options") {
|
||||
OptionRowView("Show videos as") { nextLayoutButton }
|
||||
CoverSectionView("View Options") {
|
||||
CoverSectionRowView("Show videos as") { nextLayoutButton }
|
||||
}
|
||||
|
||||
OptionsSectionView(divider: false) {
|
||||
OptionRowView("Close View Options") { Button("Close") { dismiss() } }
|
||||
CoverSectionView(divider: false) {
|
||||
CoverSectionRowView("Close View Options") { Button("Close") { dismiss() } }
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
@@ -6,6 +6,9 @@ struct PlaylistsView: View {
|
||||
|
||||
@State private var selectedPlaylist: Playlist?
|
||||
|
||||
@State private var showingNewPlaylist = false
|
||||
@State private var createdPlaylist: Playlist?
|
||||
|
||||
var resource: Resource {
|
||||
InvidiousAPI.shared.playlists
|
||||
}
|
||||
@@ -17,8 +20,12 @@ struct PlaylistsView: View {
|
||||
var body: some View {
|
||||
Section {
|
||||
VStack(alignment: .center, spacing: 2) {
|
||||
selectPlaylistButton
|
||||
.scaleEffect(0.85)
|
||||
HStack {
|
||||
selectPlaylistButton
|
||||
|
||||
newPlaylistButton
|
||||
}
|
||||
.scaleEffect(0.85)
|
||||
|
||||
if currentPlaylist != nil {
|
||||
VideosView(videos: currentPlaylist!.videos)
|
||||
@@ -27,11 +34,24 @@ struct PlaylistsView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
.fullScreenCover(isPresented: $showingNewPlaylist, onDismiss: selectCreatedPlaylist) {
|
||||
NewPlaylistView(createdPlaylist: $createdPlaylist)
|
||||
}
|
||||
.onAppear {
|
||||
resource.loadIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
func selectCreatedPlaylist() {
|
||||
guard createdPlaylist != nil else {
|
||||
return
|
||||
}
|
||||
|
||||
resource.load().onSuccess { _ in
|
||||
self.selectedPlaylist = store.collection.first { $0 == createdPlaylist }
|
||||
}
|
||||
}
|
||||
|
||||
var currentPlaylist: Playlist? {
|
||||
selectedPlaylist ?? store.collection.first
|
||||
}
|
||||
@@ -52,4 +72,10 @@ struct PlaylistsView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var newPlaylistButton: some View {
|
||||
Button(action: { self.showingNewPlaylist = true }) {
|
||||
Image(systemName: "plus")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@ struct SearchOptionsView: View {
|
||||
@Default(.searchDuration) private var searchDuration
|
||||
|
||||
var body: some View {
|
||||
OptionsSectionView("Search Options") {
|
||||
OptionRowView("Sort By") { searchSortOrderButton }
|
||||
OptionRowView("Upload date") { searchDateButton }
|
||||
OptionRowView("Duration") { searchDurationButton }
|
||||
CoverSectionView("Search Options") {
|
||||
CoverSectionRowView("Sort By") { searchSortOrderButton }
|
||||
CoverSectionRowView("Upload date") { searchDateButton }
|
||||
CoverSectionRowView("Duration") { searchDurationButton }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,19 +47,17 @@ struct SearchOptionsView: View {
|
||||
|
||||
var searchDurationButton: some View {
|
||||
Button(self.searchDuration?.name ?? "All") {
|
||||
let duration = Defaults[.searchDuration]
|
||||
|
||||
Defaults[.searchDuration] = duration == nil ? SearchDuration.allCases.first : duration!.next(nilAtEnd: true)
|
||||
self.searchDuration = self.searchDuration == nil ? SearchDuration.allCases.first : self.searchDuration!.next(nilAtEnd: true)
|
||||
}
|
||||
.contextMenu {
|
||||
ForEach(SearchDuration.allCases) { searchDuration in
|
||||
Button(searchDuration.name) {
|
||||
Defaults[.searchDuration] = searchDuration
|
||||
self.searchDuration = searchDuration
|
||||
}
|
||||
}
|
||||
|
||||
Button("Reset") {
|
||||
Defaults.reset(.searchDuration)
|
||||
self.searchDuration = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user