Add placeholders

This commit is contained in:
Arkadiusz Fal 2022-03-27 12:49:57 +02:00
parent 70b55ec2b2
commit ae4796a4c5
11 changed files with 55 additions and 8 deletions

View File

@ -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 {

View File

@ -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",

View File

@ -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

View File

@ -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 {

View File

@ -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
} }
} }

View File

@ -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

View File

@ -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 {

View File

@ -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 {

View File

@ -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()
} }
} }
} }

View 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()
}
}

View File

@ -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 */,