mirror of
https://github.com/yattee/yattee.git
synced 2025-10-27 02:22:07 +00:00
Playlists support
This commit is contained in:
72
Apple TV/PlaylistsView.swift
Normal file
72
Apple TV/PlaylistsView.swift
Normal file
@@ -0,0 +1,72 @@
|
||||
import SwiftUI
|
||||
|
||||
struct PlaylistsView: View {
|
||||
@EnvironmentObject private var state: AppState
|
||||
|
||||
@Binding var tabSelection: TabSelection
|
||||
|
||||
@ObservedObject private var provider = PlaylistsProvider()
|
||||
|
||||
@State private var selectedPlaylist: Playlist?
|
||||
|
||||
var body: some View {
|
||||
Section {
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
HStack(alignment: .top) {
|
||||
Spacer()
|
||||
|
||||
selectPlaylistButton
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(.bottom, 5)
|
||||
|
||||
VStack {
|
||||
if selectedPlaylist != nil {
|
||||
VideosView(tabSelection: $tabSelection, videos: selectedPlaylist!.videos)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.task {
|
||||
Task {
|
||||
provider.load { playlists in
|
||||
selectedPlaylist = playlists.first
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var playlists: [Playlist] {
|
||||
if provider.playlists.isEmpty {
|
||||
provider.load()
|
||||
}
|
||||
|
||||
return provider.playlists
|
||||
}
|
||||
|
||||
var selectPlaylistButton: some View {
|
||||
Button(selectedPlaylist?.title ?? "Select playlist") {
|
||||
guard selectedPlaylist != nil else {
|
||||
return
|
||||
}
|
||||
|
||||
selectedPlaylist = playlists.next(after: selectedPlaylist!)
|
||||
}
|
||||
.contextMenu {
|
||||
ForEach(provider.playlists) { playlist in
|
||||
Button(playlist.title) {
|
||||
selectedPlaylist = playlist
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Array where Element: Equatable {
|
||||
func next(after element: Element) -> Element? {
|
||||
let idx = firstIndex(of: element)!
|
||||
let next = index(after: idx)
|
||||
|
||||
return self[next == endIndex ? startIndex : next]
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import SwiftUI
|
||||
|
||||
struct TrendingCategorySelectionView: View {
|
||||
@Environment(\.presentationMode) private var presentationMode
|
||||
|
||||
@Binding var selectedCategory: TrendingCategory
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
VisualEffectView(effect: UIBlurEffect(style: .dark))
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Spacer()
|
||||
|
||||
ForEach(TrendingCategory.allCases) { category in
|
||||
Button(category.name) {
|
||||
selectedCategory = category
|
||||
presentationMode.wrappedValue.dismiss()
|
||||
}
|
||||
}
|
||||
.frame(width: 800)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,14 @@ import SwiftUI
|
||||
|
||||
struct TrendingView: View {
|
||||
@EnvironmentObject private var state: AppState
|
||||
@EnvironmentObject private var trendingState: TrendingState
|
||||
|
||||
@Binding var tabSelection: TabSelection
|
||||
|
||||
@ObservedObject private var videosProvider = TrendingVideosProvider()
|
||||
|
||||
@State private var selectingCategory = false
|
||||
@SceneStorage("category") var category: TrendingCategory = .default
|
||||
@SceneStorage("country") var country: Country = .pl
|
||||
|
||||
@State private var selectingCountry = false
|
||||
|
||||
var body: some View {
|
||||
@@ -31,35 +32,35 @@ struct TrendingView: View {
|
||||
}
|
||||
|
||||
var videos: [Video] {
|
||||
videosProvider.load(category: trendingState.category, country: trendingState.country)
|
||||
videosProvider.load(category: category, country: country)
|
||||
|
||||
return videosProvider.videos
|
||||
}
|
||||
|
||||
var categoryButton: some View {
|
||||
Button(trendingState.category.name) {
|
||||
trendingState.category = trendingState.category.next()
|
||||
Button(category.name) {
|
||||
category = category.next()
|
||||
}
|
||||
.contextMenu {
|
||||
ForEach(TrendingCategory.allCases) { category in
|
||||
Button(category.name) {
|
||||
trendingState.category = category
|
||||
self.category = category
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var countryFlag: some View {
|
||||
Text(trendingState.country.flag)
|
||||
Text(country.flag)
|
||||
.font(.system(size: 60))
|
||||
}
|
||||
|
||||
var countryButton: some View {
|
||||
Button(trendingState.country.rawValue) {
|
||||
Button(country.rawValue) {
|
||||
selectingCountry.toggle()
|
||||
}
|
||||
.fullScreenCover(isPresented: $selectingCountry) {
|
||||
TrendingCountrySelectionView(selectedCountry: $trendingState.country)
|
||||
TrendingCountrySelectionView(selectedCountry: $country)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,17 +51,21 @@ struct VideoCellView: View {
|
||||
.frame(minHeight: 80, alignment: .top)
|
||||
.truncationMode(.middle)
|
||||
|
||||
HStack(spacing: 8) {
|
||||
Image(systemName: "calendar")
|
||||
Text(video.published)
|
||||
if !video.published.isEmpty || video.views != 0 {
|
||||
HStack(spacing: 8) {
|
||||
if !video.published.isEmpty {
|
||||
Image(systemName: "calendar")
|
||||
Text(video.published)
|
||||
}
|
||||
|
||||
if video.views != 0 {
|
||||
Image(systemName: "eye")
|
||||
Text(video.viewsCount)
|
||||
if video.views != 0 {
|
||||
Image(systemName: "eye")
|
||||
Text(video.viewsCount)
|
||||
}
|
||||
}
|
||||
.padding([.horizontal, .bottom])
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
.padding([.horizontal, .bottom])
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
.frame(width: 550, alignment: .leading)
|
||||
|
||||
@@ -38,17 +38,21 @@ struct VideoListRow: View {
|
||||
.bold()
|
||||
.lineLimit(1)
|
||||
|
||||
HStack(spacing: 8) {
|
||||
Image(systemName: "calendar")
|
||||
Text(video.published)
|
||||
if !video.published.isEmpty || video.views != 0 {
|
||||
HStack(spacing: 8) {
|
||||
if !video.published.isEmpty {
|
||||
Image(systemName: "calendar")
|
||||
Text(video.published)
|
||||
}
|
||||
|
||||
if video.views != 0 {
|
||||
Image(systemName: "eye")
|
||||
Text(video.viewsCount)
|
||||
if video.views != 0 {
|
||||
Image(systemName: "eye")
|
||||
Text(video.viewsCount)
|
||||
}
|
||||
}
|
||||
.foregroundColor(.secondary)
|
||||
.padding(.top)
|
||||
}
|
||||
.foregroundColor(.secondary)
|
||||
.padding(.top)
|
||||
}
|
||||
.padding()
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ struct VideosCellsView: View {
|
||||
var videos = [Video]()
|
||||
|
||||
var body: some View {
|
||||
ScrollView(.vertical) {
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
LazyVGrid(columns: items, spacing: 10) {
|
||||
ForEach(videos) { video in
|
||||
VideoCellView(video: video)
|
||||
|
||||
Reference in New Issue
Block a user