mirror of
https://github.com/yattee/yattee.git
synced 2025-12-16 04:58:15 +00:00
Cells view
This commit is contained in:
@@ -7,7 +7,7 @@ struct ChannelView: View {
|
||||
@Binding var tabSelection: TabSelection
|
||||
|
||||
var body: some View {
|
||||
VideosView(tabSelection: $tabSelection, videos: videos)
|
||||
VideosListView(tabSelection: $tabSelection, videos: videos)
|
||||
}
|
||||
|
||||
var listRowInsets: EdgeInsets {
|
||||
|
||||
@@ -15,7 +15,7 @@ struct PlayerView: View {
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
}
|
||||
.task {
|
||||
async {
|
||||
Task.init {
|
||||
provider.load()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,13 @@ import SwiftUI
|
||||
|
||||
struct PopularVideosView: View {
|
||||
@ObservedObject private var provider = PopularVideosProvider()
|
||||
@EnvironmentObject private var state: AppState
|
||||
|
||||
@Binding var tabSelection: TabSelection
|
||||
|
||||
var body: some View {
|
||||
VideosView(tabSelection: $tabSelection, videos: videos)
|
||||
.task {
|
||||
async {
|
||||
Task.init {
|
||||
provider.load()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ struct SearchView: View {
|
||||
|
||||
var body: some View {
|
||||
VideosView(tabSelection: $tabSelection, videos: videos)
|
||||
.environmentObject(state)
|
||||
.searchable(text: $query)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ struct SubscriptionsView: View {
|
||||
var body: some View {
|
||||
VideosView(tabSelection: $tabSelection, videos: videos)
|
||||
.task {
|
||||
async {
|
||||
Task.init {
|
||||
provider.load()
|
||||
}
|
||||
}
|
||||
|
||||
72
Apple TV/VideoCellView.swift
Normal file
72
Apple TV/VideoCellView.swift
Normal file
@@ -0,0 +1,72 @@
|
||||
import URLImage
|
||||
import URLImageStore
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct VideoCellView: View {
|
||||
var video: Video
|
||||
var body: some View {
|
||||
NavigationLink(destination: PlayerView(id: video.id)) {
|
||||
VStack(alignment: .leading) {
|
||||
ZStack(alignment: .trailing) {
|
||||
if let thumbnail = video.thumbnailURL {
|
||||
// to replace with AsyncImage when it is fixed with lazy views
|
||||
URLImage(thumbnail) { image in
|
||||
image
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: 550, height: 310)
|
||||
}
|
||||
.mask(RoundedRectangle(cornerRadius: 12))
|
||||
} else {
|
||||
Image(systemName: "exclamationmark.square")
|
||||
.frame(width: 550, height: 310)
|
||||
}
|
||||
|
||||
Text(video.author)
|
||||
.padding(8)
|
||||
.background(.thickMaterial)
|
||||
.mask(RoundedRectangle(cornerRadius: 12))
|
||||
.offset(x: -10, y: -120)
|
||||
.truncationMode(.middle)
|
||||
|
||||
if let time = video.playTime {
|
||||
Text(time)
|
||||
.fontWeight(.bold)
|
||||
.padding(8)
|
||||
.background(.thickMaterial)
|
||||
.mask(RoundedRectangle(cornerRadius: 12))
|
||||
.offset(x: -10, y: 115)
|
||||
}
|
||||
}
|
||||
.frame(width: 550, height: 310)
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Text(video.title)
|
||||
.bold()
|
||||
.lineLimit(2)
|
||||
.multilineTextAlignment(.leading)
|
||||
.padding(.horizontal)
|
||||
.padding(.bottom, 2)
|
||||
.frame(minHeight: 80, alignment: .top)
|
||||
.truncationMode(.middle)
|
||||
|
||||
HStack(spacing: 8) {
|
||||
Image(systemName: "calendar")
|
||||
Text(video.published)
|
||||
|
||||
if video.views != 0 {
|
||||
Image(systemName: "eye")
|
||||
Text(video.viewsCount)
|
||||
}
|
||||
}
|
||||
.padding([.horizontal, .bottom])
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
.frame(width: 550, alignment: .leading)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.padding(.vertical)
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import SwiftUI
|
||||
import URLImage
|
||||
import URLImageStore
|
||||
|
||||
struct VideoThumbnailView: View {
|
||||
struct VideoListRow: View {
|
||||
@Environment(\.isFocused) private var focused: Bool
|
||||
|
||||
var video: Video
|
||||
29
Apple TV/VideosCellsView.swift
Normal file
29
Apple TV/VideosCellsView.swift
Normal file
@@ -0,0 +1,29 @@
|
||||
import SwiftUI
|
||||
|
||||
struct VideosCellsView: View {
|
||||
@EnvironmentObject private var state: AppState
|
||||
|
||||
@State private var columns: Int
|
||||
|
||||
init(videos: [Video], columns: Int = 3) {
|
||||
self.videos = videos
|
||||
self.columns = columns
|
||||
}
|
||||
|
||||
var videos = [Video]()
|
||||
|
||||
var body: some View {
|
||||
ScrollView(.vertical) {
|
||||
LazyVGrid(columns: items, spacing: 10) {
|
||||
ForEach(videos) { video in
|
||||
VideoCellView(video: video)
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
||||
var items: [GridItem] {
|
||||
Array(repeating: .init(.fixed(600)), count: columns)
|
||||
}
|
||||
}
|
||||
46
Apple TV/VideosListView.swift
Normal file
46
Apple TV/VideosListView.swift
Normal file
@@ -0,0 +1,46 @@
|
||||
import SwiftUI
|
||||
|
||||
struct VideosListView: View {
|
||||
@EnvironmentObject private var state: AppState
|
||||
|
||||
@Binding var tabSelection: TabSelection
|
||||
|
||||
var videos: [Video]
|
||||
|
||||
var body: some View {
|
||||
Section {
|
||||
List {
|
||||
ForEach(videos) { video in
|
||||
VideoListRow(video: video)
|
||||
.contextMenu {
|
||||
if tabSelection == .channel {
|
||||
closeChannelButton(name: video.author)
|
||||
} else {
|
||||
openChannelButton(from: video)
|
||||
}
|
||||
}
|
||||
.listRowInsets(listRowInsets)
|
||||
}
|
||||
}
|
||||
.listStyle(GroupedListStyle())
|
||||
}
|
||||
}
|
||||
|
||||
func openChannelButton(from video: Video) -> some View {
|
||||
Button("\(video.author) Channel") {
|
||||
state.openChannel(from: video)
|
||||
tabSelection = .channel
|
||||
}
|
||||
}
|
||||
|
||||
func closeChannelButton(name: String) -> some View {
|
||||
Button("Close \(name) Channel") {
|
||||
tabSelection = .popular
|
||||
state.closeChannel()
|
||||
}
|
||||
}
|
||||
|
||||
var listRowInsets: EdgeInsets {
|
||||
EdgeInsets(top: .zero, leading: .zero, bottom: .zero, trailing: 30)
|
||||
}
|
||||
}
|
||||
@@ -4,43 +4,15 @@ struct VideosView: View {
|
||||
@EnvironmentObject private var state: AppState
|
||||
|
||||
@Binding var tabSelection: TabSelection
|
||||
|
||||
var videos: [Video]
|
||||
|
||||
var body: some View {
|
||||
Section {
|
||||
List {
|
||||
ForEach(videos) { video in
|
||||
VideoThumbnailView(video: video)
|
||||
.contextMenu {
|
||||
if tabSelection == .channel {
|
||||
closeChannelButton(name: video.author)
|
||||
} else {
|
||||
openChannelButton(from: video)
|
||||
}
|
||||
}
|
||||
.listRowInsets(listRowInsets)
|
||||
}
|
||||
Group {
|
||||
if state.profile.listing == .list {
|
||||
VideosListView(tabSelection: $tabSelection, videos: videos)
|
||||
} else {
|
||||
VideosCellsView(videos: videos, columns: state.profile.cellsColumns)
|
||||
}
|
||||
.listStyle(GroupedListStyle())
|
||||
}
|
||||
}
|
||||
|
||||
func openChannelButton(from video: Video) -> some View {
|
||||
Button("\(video.author) Channel") {
|
||||
state.openChannel(from: video)
|
||||
tabSelection = .channel
|
||||
}
|
||||
}
|
||||
|
||||
func closeChannelButton(name: String) -> some View {
|
||||
Button("Close \(name) Channel") {
|
||||
tabSelection = .popular
|
||||
state.closeChannel()
|
||||
}
|
||||
}
|
||||
|
||||
var listRowInsets: EdgeInsets {
|
||||
EdgeInsets(top: .zero, leading: .zero, bottom: .zero, trailing: 30)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user