mirror of
https://github.com/yattee/yattee.git
synced 2024-12-22 13:33:42 +00:00
Add placeholders
This commit is contained in:
parent
70b55ec2b2
commit
ae4796a4c5
@ -10,7 +10,7 @@ extension Thumbnail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static var fixturesHost: String {
|
private static var fixturesHost: String {
|
||||||
"https://invidious.home.arekf.net"
|
"https://invidious.snopyta.org"
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func fixtureUrl(videoId: String, quality: Thumbnail.Quality) -> URL {
|
private static func fixtureUrl(videoId: String, quality: Thumbnail.Quality) -> URL {
|
||||||
|
@ -7,7 +7,7 @@ extension Video {
|
|||||||
|
|
||||||
return Video(
|
return Video(
|
||||||
videoID: UUID().uuidString,
|
videoID: UUID().uuidString,
|
||||||
title: "Relaxing Piano Music that will make you feel amazingly good",
|
title: "Relaxing Piano Music to feel good",
|
||||||
author: "Fancy Videotuber",
|
author: "Fancy Videotuber",
|
||||||
length: 582,
|
length: 582,
|
||||||
published: "7 years ago",
|
published: "7 years ago",
|
||||||
|
@ -232,6 +232,8 @@ final class PipedAPI: Service, ObservableObject, VideosAPI {
|
|||||||
if let channel = extractChannel(from: content) {
|
if let channel = extractChannel(from: content) {
|
||||||
return ContentItem(channel: channel)
|
return ContentItem(channel: channel)
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -74,6 +74,8 @@ extension VideosAPI {
|
|||||||
case .playlist:
|
case .playlist:
|
||||||
urlComponents.path = "/playlist"
|
urlComponents.path = "/playlist"
|
||||||
queryItems.append(.init(name: "list", value: item.playlist.id))
|
queryItems.append(.init(name: "list", value: item.playlist.id))
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !time.isNil, time!.seconds.isFinite {
|
if !time.isNil, time!.seconds.isFinite {
|
||||||
|
@ -2,7 +2,7 @@ import Foundation
|
|||||||
|
|
||||||
struct ContentItem: Identifiable {
|
struct ContentItem: Identifiable {
|
||||||
enum ContentType: String {
|
enum ContentType: String {
|
||||||
case video, playlist, channel
|
case video, playlist, channel, placeholder
|
||||||
|
|
||||||
private var sortOrder: Int {
|
private var sortOrder: Int {
|
||||||
switch self {
|
switch self {
|
||||||
@ -35,6 +35,6 @@ struct ContentItem: Identifiable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var contentType: ContentType {
|
var contentType: ContentType {
|
||||||
video.isNil ? (channel.isNil ? .playlist : .channel) : .video
|
video.isNil ? (channel.isNil ? (playlist.isNil ? .placeholder : .playlist) : .channel) : .video
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -234,7 +234,7 @@ struct SearchView: View {
|
|||||||
}
|
}
|
||||||
.edgesIgnoringSafeArea(.horizontal)
|
.edgesIgnoringSafeArea(.horizontal)
|
||||||
#else
|
#else
|
||||||
VerticalCells(items: items)
|
VerticalCells(items: items, allowEmpty: state.query.isEmpty)
|
||||||
.environment(\.loadMoreContentHandler) { state.loadNextPage() }
|
.environment(\.loadMoreContentHandler) { state.loadNextPage() }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ struct HorizontalCells: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView(.horizontal, showsIndicators: false) {
|
ScrollView(.horizontal, showsIndicators: false) {
|
||||||
LazyHStack(spacing: 20) {
|
LazyHStack(spacing: 20) {
|
||||||
ForEach(items) { item in
|
ForEach(contentItems) { item in
|
||||||
ContentItemView(item: item)
|
ContentItemView(item: item)
|
||||||
.environment(\.horizontalCells, true)
|
.environment(\.horizontalCells, true)
|
||||||
.onAppear { loadMoreContentItemsIfNeeded(current: item) }
|
.onAppear { loadMoreContentItemsIfNeeded(current: item) }
|
||||||
@ -36,6 +36,14 @@ struct HorizontalCells: View {
|
|||||||
.edgesIgnoringSafeArea(.horizontal)
|
.edgesIgnoringSafeArea(.horizontal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var contentItems: [ContentItem] {
|
||||||
|
items.isEmpty ? placeholders : items
|
||||||
|
}
|
||||||
|
|
||||||
|
var placeholders: [ContentItem] {
|
||||||
|
(0 ..< 9).map { _ in .init() }
|
||||||
|
}
|
||||||
|
|
||||||
func loadMoreContentItemsIfNeeded(current item: ContentItem) {
|
func loadMoreContentItemsIfNeeded(current item: ContentItem) {
|
||||||
let thresholdIndex = items.index(items.endIndex, offsetBy: -5)
|
let thresholdIndex = items.index(items.endIndex, offsetBy: -5)
|
||||||
if items.firstIndex(where: { $0.id == item.id }) == thresholdIndex {
|
if items.firstIndex(where: { $0.id == item.id }) == thresholdIndex {
|
||||||
|
@ -9,11 +9,12 @@ struct VerticalCells: View {
|
|||||||
@Environment(\.loadMoreContentHandler) private var loadMoreContentHandler
|
@Environment(\.loadMoreContentHandler) private var loadMoreContentHandler
|
||||||
|
|
||||||
var items = [ContentItem]()
|
var items = [ContentItem]()
|
||||||
|
var allowEmpty = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView(.vertical, showsIndicators: scrollViewShowsIndicators) {
|
ScrollView(.vertical, showsIndicators: scrollViewShowsIndicators) {
|
||||||
LazyVGrid(columns: columns, alignment: .center) {
|
LazyVGrid(columns: columns, alignment: .center) {
|
||||||
ForEach(items.sorted { $0 < $1 }) { item in
|
ForEach(contentItems) { item in
|
||||||
ContentItemView(item: item)
|
ContentItemView(item: item)
|
||||||
.onAppear { loadMoreContentItemsIfNeeded(current: item) }
|
.onAppear { loadMoreContentItemsIfNeeded(current: item) }
|
||||||
}
|
}
|
||||||
@ -27,6 +28,14 @@ struct VerticalCells: View {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var contentItems: [ContentItem] {
|
||||||
|
items.isEmpty ? (allowEmpty ? items : placeholders) : items.sorted { $0 < $1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
var placeholders: [ContentItem] {
|
||||||
|
(0 ..< 9).map { _ in .init() }
|
||||||
|
}
|
||||||
|
|
||||||
func loadMoreContentItemsIfNeeded(current item: ContentItem) {
|
func loadMoreContentItemsIfNeeded(current item: ContentItem) {
|
||||||
let thresholdIndex = items.index(items.endIndex, offsetBy: -5)
|
let thresholdIndex = items.index(items.endIndex, offsetBy: -5)
|
||||||
if items.firstIndex(where: { $0.id == item.id }) == thresholdIndex {
|
if items.firstIndex(where: { $0.id == item.id }) == thresholdIndex {
|
||||||
|
@ -11,8 +11,10 @@ struct ContentItemView: View {
|
|||||||
ChannelPlaylistCell(playlist: item.playlist)
|
ChannelPlaylistCell(playlist: item.playlist)
|
||||||
case .channel:
|
case .channel:
|
||||||
ChannelCell(channel: item.channel)
|
ChannelCell(channel: item.channel)
|
||||||
default:
|
case .video:
|
||||||
VideoCell(video: item.video)
|
VideoCell(video: item.video)
|
||||||
|
default:
|
||||||
|
PlaceholderCell()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
16
Shared/Views/PlaceholderCell.swift
Normal file
16
Shared/Views/PlaceholderCell.swift
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import Defaults
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct PlaceholderCell: View {
|
||||||
|
var body: some View {
|
||||||
|
VideoCell(video: .fixture)
|
||||||
|
.redacted(reason: .placeholder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PlaceholderCell_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
PlaceholderCell()
|
||||||
|
.injectFixtureEnvironmentObjects()
|
||||||
|
}
|
||||||
|
}
|
@ -590,6 +590,9 @@
|
|||||||
37FD43E42704847C0073EE42 /* View+Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD43E22704847C0073EE42 /* View+Fixtures.swift */; };
|
37FD43E42704847C0073EE42 /* View+Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD43E22704847C0073EE42 /* View+Fixtures.swift */; };
|
||||||
37FD43E52704847C0073EE42 /* View+Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD43E22704847C0073EE42 /* View+Fixtures.swift */; };
|
37FD43E52704847C0073EE42 /* View+Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD43E22704847C0073EE42 /* View+Fixtures.swift */; };
|
||||||
37FD43F02704A9C00073EE42 /* RecentsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C194C626F6A9C8005D3B96 /* RecentsModel.swift */; };
|
37FD43F02704A9C00073EE42 /* RecentsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C194C626F6A9C8005D3B96 /* RecentsModel.swift */; };
|
||||||
|
37FEF11327EFD8580033912F /* PlaceholderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FEF11227EFD8580033912F /* PlaceholderCell.swift */; };
|
||||||
|
37FEF11427EFD8580033912F /* PlaceholderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FEF11227EFD8580033912F /* PlaceholderCell.swift */; };
|
||||||
|
37FEF11527EFD8580033912F /* PlaceholderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FEF11227EFD8580033912F /* PlaceholderCell.swift */; };
|
||||||
37FFC440272734C3009FFD26 /* Throttle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FFC43F272734C3009FFD26 /* Throttle.swift */; };
|
37FFC440272734C3009FFD26 /* Throttle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FFC43F272734C3009FFD26 /* Throttle.swift */; };
|
||||||
37FFC441272734C3009FFD26 /* Throttle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FFC43F272734C3009FFD26 /* Throttle.swift */; };
|
37FFC441272734C3009FFD26 /* Throttle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FFC43F272734C3009FFD26 /* Throttle.swift */; };
|
||||||
37FFC442272734C3009FFD26 /* Throttle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FFC43F272734C3009FFD26 /* Throttle.swift */; };
|
37FFC442272734C3009FFD26 /* Throttle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FFC43F272734C3009FFD26 /* Throttle.swift */; };
|
||||||
@ -822,6 +825,7 @@
|
|||||||
37FB285D272225E800A57617 /* ContentItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentItemView.swift; sourceTree = "<group>"; };
|
37FB285D272225E800A57617 /* ContentItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentItemView.swift; sourceTree = "<group>"; };
|
||||||
37FD43DB270470B70073EE42 /* InstancesSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstancesSettings.swift; sourceTree = "<group>"; };
|
37FD43DB270470B70073EE42 /* InstancesSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstancesSettings.swift; sourceTree = "<group>"; };
|
||||||
37FD43E22704847C0073EE42 /* View+Fixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Fixtures.swift"; sourceTree = "<group>"; };
|
37FD43E22704847C0073EE42 /* View+Fixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Fixtures.swift"; sourceTree = "<group>"; };
|
||||||
|
37FEF11227EFD8580033912F /* PlaceholderCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderCell.swift; sourceTree = "<group>"; };
|
||||||
37FFC43F272734C3009FFD26 /* Throttle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Throttle.swift; sourceTree = "<group>"; };
|
37FFC43F272734C3009FFD26 /* Throttle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Throttle.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
@ -1005,6 +1009,7 @@
|
|||||||
37B17D9F268A1F25006AEE9B /* VideoContextMenuView.swift */,
|
37B17D9F268A1F25006AEE9B /* VideoContextMenuView.swift */,
|
||||||
37E70922271CD43000D34DDE /* WelcomeScreen.swift */,
|
37E70922271CD43000D34DDE /* WelcomeScreen.swift */,
|
||||||
3769C02D2779F18600DDB3EA /* PlaceholderProgressView.swift */,
|
3769C02D2779F18600DDB3EA /* PlaceholderProgressView.swift */,
|
||||||
|
37FEF11227EFD8580033912F /* PlaceholderCell.swift */,
|
||||||
);
|
);
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -2021,6 +2026,7 @@
|
|||||||
37C3A24927235FAA0087A57A /* ChannelPlaylistCell.swift in Sources */,
|
37C3A24927235FAA0087A57A /* ChannelPlaylistCell.swift in Sources */,
|
||||||
373CFACB26966264003CB2C6 /* SearchQuery.swift in Sources */,
|
373CFACB26966264003CB2C6 /* SearchQuery.swift in Sources */,
|
||||||
37141673267A8E10006CA35D /* Country.swift in Sources */,
|
37141673267A8E10006CA35D /* Country.swift in Sources */,
|
||||||
|
37FEF11327EFD8580033912F /* PlaceholderCell.swift in Sources */,
|
||||||
37B2631A2735EAAB00FE0D40 /* FavoriteResourceObserver.swift in Sources */,
|
37B2631A2735EAAB00FE0D40 /* FavoriteResourceObserver.swift in Sources */,
|
||||||
3748186E26A769D60084E870 /* DetailBadge.swift in Sources */,
|
3748186E26A769D60084E870 /* DetailBadge.swift in Sources */,
|
||||||
376BE50B27349108009AD608 /* BrowsingSettings.swift in Sources */,
|
376BE50B27349108009AD608 /* BrowsingSettings.swift in Sources */,
|
||||||
@ -2167,6 +2173,7 @@
|
|||||||
3748186726A7627F0084E870 /* Video+Fixtures.swift in Sources */,
|
3748186726A7627F0084E870 /* Video+Fixtures.swift in Sources */,
|
||||||
3784B23E2728B85300B09468 /* ShareButton.swift in Sources */,
|
3784B23E2728B85300B09468 /* ShareButton.swift in Sources */,
|
||||||
37BE0BDA26A214630092E2DB /* PlayerViewController.swift in Sources */,
|
37BE0BDA26A214630092E2DB /* PlayerViewController.swift in Sources */,
|
||||||
|
37FEF11427EFD8580033912F /* PlaceholderCell.swift in Sources */,
|
||||||
37E64DD226D597EB00C71877 /* SubscriptionsModel.swift in Sources */,
|
37E64DD226D597EB00C71877 /* SubscriptionsModel.swift in Sources */,
|
||||||
374108D1272B11B2006C5CC8 /* PictureInPictureDelegate.swift in Sources */,
|
374108D1272B11B2006C5CC8 /* PictureInPictureDelegate.swift in Sources */,
|
||||||
37C7A1D6267BFD9D0010EAD6 /* SponsorBlockSegment.swift in Sources */,
|
37C7A1D6267BFD9D0010EAD6 /* SponsorBlockSegment.swift in Sources */,
|
||||||
@ -2392,6 +2399,7 @@
|
|||||||
374C053727242D9F009BDDBE /* SponsorBlockSettings.swift in Sources */,
|
374C053727242D9F009BDDBE /* SponsorBlockSettings.swift in Sources */,
|
||||||
37C069802725C8D400F7F6CB /* CMTime+DefaultTimescale.swift in Sources */,
|
37C069802725C8D400F7F6CB /* CMTime+DefaultTimescale.swift in Sources */,
|
||||||
3711404126B206A6005B3555 /* SearchModel.swift in Sources */,
|
3711404126B206A6005B3555 /* SearchModel.swift in Sources */,
|
||||||
|
37FEF11527EFD8580033912F /* PlaceholderCell.swift in Sources */,
|
||||||
37FD43F02704A9C00073EE42 /* RecentsModel.swift in Sources */,
|
37FD43F02704A9C00073EE42 /* RecentsModel.swift in Sources */,
|
||||||
379775952689365600DD52A8 /* Array+Next.swift in Sources */,
|
379775952689365600DD52A8 /* Array+Next.swift in Sources */,
|
||||||
3705B180267B4DFB00704544 /* TrendingCountry.swift in Sources */,
|
3705B180267B4DFB00704544 /* TrendingCountry.swift in Sources */,
|
||||||
|
Loading…
Reference in New Issue
Block a user