Add list views for channels, playlists and placeholders

This commit is contained in:
Arkadiusz Fal 2022-12-13 11:40:08 +01:00
parent d38a507be5
commit 1cd2dbe5f7
11 changed files with 332 additions and 43 deletions

View File

@ -45,14 +45,6 @@ struct ChannelCell: View {
var labelContent: some View { var labelContent: some View {
VStack { VStack {
HStack(alignment: .top, spacing: 3) {
Image(systemName: "person.crop.rectangle")
Text("Channel".localized().uppercased())
.fontWeight(.light)
.opacity(0.6)
}
.foregroundColor(.secondary)
WebImage(url: channel.thumbnailURL, options: [.lowPriority]) WebImage(url: channel.thumbnailURL, options: [.lowPriority])
.resizable() .resizable()
.placeholder { .placeholder {

View File

@ -0,0 +1,97 @@
import SwiftUI
struct ChannelListItem: View {
var channel: Channel
@Environment(\.inChannelView) private var inChannelView
@Environment(\.inNavigationView) private var inNavigationView
@Environment(\.navigationStyle) private var navigationStyle
var body: some View {
channelControl
.contentShape(Rectangle())
}
@ViewBuilder private var channelControl: some View {
if !channel.name.isEmpty {
#if os(tvOS)
channelButton
#else
if navigationStyle == .tab, inNavigationView {
channelNavigationLink
} else {
channelButton
}
#endif
}
}
@ViewBuilder private var channelNavigationLink: some View {
NavigationLink(destination: ChannelVideosView(channel: channel)) {
label
}
}
@ViewBuilder private var channelButton: some View {
Button {
guard !inChannelView else { return }
NavigationModel.shared.openChannel(
channel,
navigationStyle: navigationStyle
)
} label: {
label
}
#if os(tvOS)
.buttonStyle(.card)
#else
.buttonStyle(.plain)
#endif
.help("\(channel.name) Channel")
}
@ViewBuilder private var displayAuthor: some View {
if !channel.name.isEmpty {
Text(channel.name)
.fontWeight(.semibold)
}
}
private var label: some View {
HStack(alignment: .top, spacing: 12) {
VStack {
ChannelAvatarView(channel: channel)
#if os(tvOS)
.frame(width: 90, height: 90)
#else
.frame(width: 60, height: 60)
#endif
}
.frame(width: thumbnailWidth)
displayAuthor
.multilineTextAlignment(.leading)
}
.frame(maxWidth: .infinity, alignment: .leading)
#if os(tvOS)
.frame(minHeight: 120)
#else
.frame(minHeight: 60)
#endif
}
private var thumbnailWidth: Double {
#if os(tvOS)
250
#else
100
#endif
}
}
struct ChannelListItem_Previews: PreviewProvider {
static var previews: some View {
ChannelListItem(channel: Video.fixture.channel)
}
}

View File

@ -29,14 +29,6 @@ struct ChannelPlaylistCell: View {
var content: some View { var content: some View {
VStack { VStack {
HStack(alignment: .top, spacing: 3) {
Image(systemName: "list.and.film")
Text("Playlist".localized().uppercased())
.fontWeight(.light)
.opacity(0.6)
}
.foregroundColor(.secondary)
WebImage(url: playlist.thumbnailURL, options: [.lowPriority]) WebImage(url: playlist.thumbnailURL, options: [.lowPriority])
.resizable() .resizable()
.placeholder { .placeholder {

View File

@ -0,0 +1,104 @@
import SwiftUI
struct ChannelPlaylistListItem: View {
var playlist: ChannelPlaylist
@Environment(\.inNavigationView) private var inNavigationView
@Environment(\.navigationStyle) private var navigationStyle
var body: some View {
playlistControl
.contentShape(Rectangle())
}
var thumbnailView: some View {
ThumbnailView(url: playlist.thumbnailURL)
#if os(tvOS)
.frame(width: 250, height: 140)
#else
.frame(width: 100, height: 60)
#endif
.clipShape(RoundedRectangle(cornerRadius: 2))
}
@ViewBuilder private var playlistControl: some View {
#if os(tvOS)
playlistButton
#else
if navigationStyle == .tab, inNavigationView {
playlistNavigationLink
} else {
playlistButton
}
#endif
}
@ViewBuilder private var playlistNavigationLink: some View {
NavigationLink(destination: ChannelPlaylistView(playlist: playlist)) {
label
}
}
@ViewBuilder private var playlistButton: some View {
Button {
NavigationModel.shared.openChannelPlaylist(
playlist,
navigationStyle: navigationStyle
)
} label: {
label
}
#if os(tvOS)
.buttonStyle(.card)
#else
.buttonStyle(.plain)
#endif
.help("\(playlist.title) playlist")
}
@ViewBuilder private var displayTitle: some View {
Text(playlist.title)
.fontWeight(.semibold)
}
private var label: some View {
HStack(alignment: .top, spacing: 12) {
VStack {
thumbnailView
}
.frame(width: thumbnailWidth)
#if os(tvOS)
.frame(minHeight: 100)
#else
.frame(minHeight: 60)
#endif
VStack(alignment: .leading) {
displayTitle
Text("\(playlist.videosCount ?? playlist.videos.count) videos")
.font(.caption)
.foregroundColor(.secondary)
}
.frame(maxWidth: .infinity, alignment: .leading)
.multilineTextAlignment(.leading)
}
#if os(tvOS)
.padding(.vertical)
#endif
.frame(maxWidth: .infinity, alignment: .leading)
}
private var thumbnailWidth: Double {
#if os(tvOS)
250
#else
100
#endif
}
}
struct ChannelPlaylistListItem_Previews: PreviewProvider {
static var previews: some View {
ChannelPlaylistListItem(playlist: ChannelPlaylist.fixture)
}
}

View File

@ -43,9 +43,14 @@ struct ChannelPlaylistView: View {
#if os(tvOS) #if os(tvOS)
HStack { HStack {
if let playlist = presentedPlaylist { if let playlist = presentedPlaylist {
ThumbnailView(url: store.item?.thumbnailURL ?? playlist.thumbnailURL)
.frame(width: 140, height: 80)
.clipShape(RoundedRectangle(cornerRadius: 2))
Text(playlist.title) Text(playlist.title)
.font(.title2) .font(.headline)
.frame(alignment: .leading) .frame(alignment: .leading)
.lineLimit(1)
Spacer() Spacer()
@ -129,6 +134,7 @@ struct ChannelPlaylistView: View {
ThumbnailView(url: store.item?.thumbnailURL ?? playlist?.thumbnailURL) ThumbnailView(url: store.item?.thumbnailURL ?? playlist?.thumbnailURL)
.frame(width: 60, height: 30) .frame(width: 60, height: 30)
.clipShape(RoundedRectangle(cornerRadius: 2)) .clipShape(RoundedRectangle(cornerRadius: 2))
Text(label) Text(label)
.font(.headline) .font(.headline)
.foregroundColor(.primary) .foregroundColor(.primary)

View File

@ -50,7 +50,7 @@ struct ChannelVideosView: View {
thumbnail thumbnail
Text(navigationTitle) Text(navigationTitle)
.font(.title2) .font(.headline)
.frame(alignment: .leading) .frame(alignment: .leading)
Spacer() Spacer()

View File

@ -9,12 +9,24 @@ struct ContentItemView: View {
Group { Group {
switch item.contentType { switch item.contentType {
case .video: case .video:
videoItem(item.video)
case .channel:
channelItem(item.channel)
case .playlist:
playlistItem(item.playlist)
default:
placeholderItem()
}
}
}
@ViewBuilder func videoItem(_ video: Video) -> some View {
if listingStyle == .cells { if listingStyle == .cells {
VideoCell(video: item.video) VideoCell(video: video)
} else { } else {
PlayerQueueRow(item: .init(item.video)) PlayerQueueRow(item: .init(video))
.contextMenu { .contextMenu {
VideoContextMenuView(video: item.video) VideoContextMenuView(video: video)
} }
#if os(tvOS) #if os(tvOS)
.padding(.horizontal, 30) .padding(.horizontal, 30)
@ -24,13 +36,50 @@ struct ContentItemView: View {
Divider() Divider()
#endif #endif
} }
case .playlist:
ChannelPlaylistCell(playlist: item.playlist)
case .channel:
ChannelCell(channel: item.channel)
default:
PlaceholderCell()
} }
@ViewBuilder func playlistItem(_ playlist: ChannelPlaylist) -> some View {
if listingStyle == .cells {
ChannelPlaylistCell(playlist: playlist)
} else {
ChannelPlaylistListItem(playlist: playlist)
#if os(tvOS)
.padding(.horizontal, 30)
#endif
#if !os(tvOS)
Divider()
#endif
}
}
@ViewBuilder func channelItem(_ channel: Channel) -> some View {
if listingStyle == .cells {
ChannelCell(channel: channel)
} else {
ChannelListItem(channel: channel)
#if os(tvOS)
.padding(.horizontal, 30)
#endif
#if !os(tvOS)
Divider()
#endif
}
}
@ViewBuilder func placeholderItem() -> some View {
if listingStyle == .cells {
PlaceholderCell()
} else {
PlaceholderListItem()
#if os(tvOS)
.padding(.horizontal, 30)
#endif
#if !os(tvOS)
Divider()
#endif
} }
} }
} }

View File

@ -0,0 +1,15 @@
import Defaults
import SwiftUI
struct PlaceholderListItem: View {
var body: some View {
VideoBanner(id: UUID().uuidString, video: .fixture)
.redacted(reason: .placeholder)
}
}
struct PlaceholderListItem_Previews: PreviewProvider {
static var previews: some View {
PlaceholderListItem()
}
}

View File

@ -142,6 +142,9 @@
370F4FFF27CC1756001B35DC /* libxcb.1.1.0.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 370F4FB027CC16CA001B35DC /* libxcb.1.1.0.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 370F4FFF27CC1756001B35DC /* libxcb.1.1.0.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 370F4FB027CC16CA001B35DC /* libxcb.1.1.0.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
370F500027CC1756001B35DC /* libXdmcp.6.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 370F4FC727CC16CB001B35DC /* libXdmcp.6.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 370F500027CC1756001B35DC /* libXdmcp.6.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 370F4FC727CC16CB001B35DC /* libXdmcp.6.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
370F500C27CC1821001B35DC /* MPVViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C2211C27ADA33300305B41 /* MPVViewController.swift */; }; 370F500C27CC1821001B35DC /* MPVViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C2211C27ADA33300305B41 /* MPVViewController.swift */; };
3710A55529488C7D006F8025 /* PlaceholderListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3710A55429488C7D006F8025 /* PlaceholderListItem.swift */; };
3710A55629488C7D006F8025 /* PlaceholderListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3710A55429488C7D006F8025 /* PlaceholderListItem.swift */; };
3710A55729488C7D006F8025 /* PlaceholderListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3710A55429488C7D006F8025 /* PlaceholderListItem.swift */; };
3711403F26B206A6005B3555 /* SearchModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3711403E26B206A6005B3555 /* SearchModel.swift */; }; 3711403F26B206A6005B3555 /* SearchModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3711403E26B206A6005B3555 /* SearchModel.swift */; };
3711404026B206A6005B3555 /* SearchModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3711403E26B206A6005B3555 /* SearchModel.swift */; }; 3711404026B206A6005B3555 /* SearchModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3711403E26B206A6005B3555 /* SearchModel.swift */; };
3711404126B206A6005B3555 /* SearchModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3711403E26B206A6005B3555 /* SearchModel.swift */; }; 3711404126B206A6005B3555 /* SearchModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3711403E26B206A6005B3555 /* SearchModel.swift */; };
@ -740,6 +743,13 @@
37BD07C82698B71C003EBB87 /* AppTabNavigation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37D4B0C32671614700C925CA /* AppTabNavigation.swift */; }; 37BD07C82698B71C003EBB87 /* AppTabNavigation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37D4B0C32671614700C925CA /* AppTabNavigation.swift */; };
37BD07C92698FBDB003EBB87 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BD07B42698AA4D003EBB87 /* ContentView.swift */; }; 37BD07C92698FBDB003EBB87 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BD07B42698AA4D003EBB87 /* ContentView.swift */; };
37BD672426F13D65004BE0C1 /* AppSidebarPlaylists.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BA794A26DC30EC002A0235 /* AppSidebarPlaylists.swift */; }; 37BD672426F13D65004BE0C1 /* AppSidebarPlaylists.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BA794A26DC30EC002A0235 /* AppSidebarPlaylists.swift */; };
37BDFF1929487B99000C6404 /* PlaylistVideosView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BA793A26DB8EE4002A0235 /* PlaylistVideosView.swift */; };
37BDFF1B29487C5A000C6404 /* ChannelListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BDFF1A29487C5A000C6404 /* ChannelListItem.swift */; };
37BDFF1C29487C5A000C6404 /* ChannelListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BDFF1A29487C5A000C6404 /* ChannelListItem.swift */; };
37BDFF1D29487C5A000C6404 /* ChannelListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BDFF1A29487C5A000C6404 /* ChannelListItem.swift */; };
37BDFF1F29488117000C6404 /* ChannelPlaylistListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BDFF1E29488117000C6404 /* ChannelPlaylistListItem.swift */; };
37BDFF2029488117000C6404 /* ChannelPlaylistListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BDFF1E29488117000C6404 /* ChannelPlaylistListItem.swift */; };
37BDFF2129488117000C6404 /* ChannelPlaylistListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BDFF1E29488117000C6404 /* ChannelPlaylistListItem.swift */; };
37BE0BCF26A0E2D50092E2DB /* VideoPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE0BCE26A0E2D50092E2DB /* VideoPlayerView.swift */; }; 37BE0BCF26A0E2D50092E2DB /* VideoPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE0BCE26A0E2D50092E2DB /* VideoPlayerView.swift */; };
37BE0BD026A0E2D50092E2DB /* VideoPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE0BCE26A0E2D50092E2DB /* VideoPlayerView.swift */; }; 37BE0BD026A0E2D50092E2DB /* VideoPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE0BCE26A0E2D50092E2DB /* VideoPlayerView.swift */; };
37BE0BD126A0E2D50092E2DB /* VideoPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE0BCE26A0E2D50092E2DB /* VideoPlayerView.swift */; }; 37BE0BD126A0E2D50092E2DB /* VideoPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE0BCE26A0E2D50092E2DB /* VideoPlayerView.swift */; };
@ -1119,6 +1129,7 @@
370F4FC727CC16CB001B35DC /* libXdmcp.6.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libXdmcp.6.dylib; sourceTree = "<group>"; }; 370F4FC727CC16CB001B35DC /* libXdmcp.6.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libXdmcp.6.dylib; sourceTree = "<group>"; };
370F4FC827CC16CB001B35DC /* libbrotlicommon.1.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libbrotlicommon.1.dylib; sourceTree = "<group>"; }; 370F4FC827CC16CB001B35DC /* libbrotlicommon.1.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libbrotlicommon.1.dylib; sourceTree = "<group>"; };
370F500A27CC176F001B35DC /* BridgingHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BridgingHeader.h; sourceTree = "<group>"; }; 370F500A27CC176F001B35DC /* BridgingHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BridgingHeader.h; sourceTree = "<group>"; };
3710A55429488C7D006F8025 /* PlaceholderListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderListItem.swift; sourceTree = "<group>"; };
3711403E26B206A6005B3555 /* SearchModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchModel.swift; sourceTree = "<group>"; }; 3711403E26B206A6005B3555 /* SearchModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchModel.swift; sourceTree = "<group>"; };
3712643B2865FF4500D77974 /* Shared Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Shared Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 3712643B2865FF4500D77974 /* Shared Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Shared Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
37130A5A277657090033018A /* Yattee.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Yattee.xcdatamodel; sourceTree = "<group>"; }; 37130A5A277657090033018A /* Yattee.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Yattee.xcdatamodel; sourceTree = "<group>"; };
@ -1343,6 +1354,8 @@
37BD07B42698AA4D003EBB87 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; }; 37BD07B42698AA4D003EBB87 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
37BD07BA2698AB60003EBB87 /* AppSidebarNavigation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSidebarNavigation.swift; sourceTree = "<group>"; }; 37BD07BA2698AB60003EBB87 /* AppSidebarNavigation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSidebarNavigation.swift; sourceTree = "<group>"; };
37BD07C42698ADEE003EBB87 /* Yattee.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Yattee.entitlements; sourceTree = "<group>"; }; 37BD07C42698ADEE003EBB87 /* Yattee.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Yattee.entitlements; sourceTree = "<group>"; };
37BDFF1A29487C5A000C6404 /* ChannelListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelListItem.swift; sourceTree = "<group>"; };
37BDFF1E29488117000C6404 /* ChannelPlaylistListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelPlaylistListItem.swift; sourceTree = "<group>"; };
37BE0BCE26A0E2D50092E2DB /* VideoPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerView.swift; sourceTree = "<group>"; }; 37BE0BCE26A0E2D50092E2DB /* VideoPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerView.swift; sourceTree = "<group>"; };
37BE0BD226A1D4780092E2DB /* AppleAVPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleAVPlayerView.swift; sourceTree = "<group>"; }; 37BE0BD226A1D4780092E2DB /* AppleAVPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleAVPlayerView.swift; sourceTree = "<group>"; };
37BE0BD526A1D4A90092E2DB /* AppleAVPlayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleAVPlayerViewController.swift; sourceTree = "<group>"; }; 37BE0BD526A1D4A90092E2DB /* AppleAVPlayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleAVPlayerViewController.swift; sourceTree = "<group>"; };
@ -1771,6 +1784,7 @@
373CFAEE2697A78B003CB2C6 /* AddToPlaylistView.swift */, 373CFAEE2697A78B003CB2C6 /* AddToPlaylistView.swift */,
373CFAEA26975CBF003CB2C6 /* PlaylistFormView.swift */, 373CFAEA26975CBF003CB2C6 /* PlaylistFormView.swift */,
376578902685490700D4EA09 /* PlaylistsView.swift */, 376578902685490700D4EA09 /* PlaylistsView.swift */,
37BA793A26DB8EE4002A0235 /* PlaylistVideosView.swift */,
); );
path = Playlists; path = Playlists;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1791,11 +1805,6 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
37E6D79F2944CD3800550C3D /* CacheStatusHeader.swift */, 37E6D79F2944CD3800550C3D /* CacheStatusHeader.swift */,
3776924D294630110055EC18 /* ChannelAvatarView.swift */,
3743B86727216D3600261544 /* ChannelCell.swift */,
37C3A24827235FAA0087A57A /* ChannelPlaylistCell.swift */,
37C3A250272366440087A57A /* ChannelPlaylistView.swift */,
37BA793E26DB8F97002A0235 /* ChannelVideosView.swift */,
37FB285D272225E800A57617 /* ContentItemView.swift */, 37FB285D272225E800A57617 /* ContentItemView.swift */,
372CFD14285F2E2A00B0B54B /* ControlsBar.swift */, 372CFD14285F2E2A00B0B54B /* ControlsBar.swift */,
3748186D26A769D60084E870 /* DetailBadge.swift */, 3748186D26A769D60084E870 /* DetailBadge.swift */,
@ -1808,7 +1817,6 @@
3763C988290C7A50004D3B5F /* OpenVideosView.swift */, 3763C988290C7A50004D3B5F /* OpenVideosView.swift */,
37FEF11227EFD8580033912F /* PlaceholderCell.swift */, 37FEF11227EFD8580033912F /* PlaceholderCell.swift */,
3769C02D2779F18600DDB3EA /* PlaceholderProgressView.swift */, 3769C02D2779F18600DDB3EA /* PlaceholderProgressView.swift */,
37BA793A26DB8EE4002A0235 /* PlaylistVideosView.swift */,
37AAF27D26737323007FC770 /* PopularView.swift */, 37AAF27D26737323007FC770 /* PopularView.swift */,
371CC76F29468BDC00979C1A /* SettingsButtons.swift */, 371CC76F29468BDC00979C1A /* SettingsButtons.swift */,
37F7D82B289EB05F00E2B3D0 /* SettingsPickerModifier.swift */, 37F7D82B289EB05F00E2B3D0 /* SettingsPickerModifier.swift */,
@ -1816,6 +1824,7 @@
376B2E0626F920D600B1D64D /* SignInRequiredView.swift */, 376B2E0626F920D600B1D64D /* SignInRequiredView.swift */,
37B17D9F268A1F25006AEE9B /* VideoContextMenuView.swift */, 37B17D9F268A1F25006AEE9B /* VideoContextMenuView.swift */,
37E70922271CD43000D34DDE /* WelcomeScreen.swift */, 37E70922271CD43000D34DDE /* WelcomeScreen.swift */,
3710A55429488C7D006F8025 /* PlaceholderListItem.swift */,
); );
path = Views; path = Views;
sourceTree = "<group>"; sourceTree = "<group>";
@ -2123,6 +2132,20 @@
path = Extensions; path = Extensions;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
37BDFF1829487B74000C6404 /* Channels */ = {
isa = PBXGroup;
children = (
3776924D294630110055EC18 /* ChannelAvatarView.swift */,
3743B86727216D3600261544 /* ChannelCell.swift */,
37BDFF1A29487C5A000C6404 /* ChannelListItem.swift */,
37C3A24827235FAA0087A57A /* ChannelPlaylistCell.swift */,
37BDFF1E29488117000C6404 /* ChannelPlaylistListItem.swift */,
37C3A250272366440087A57A /* ChannelPlaylistView.swift */,
37BA793E26DB8F97002A0235 /* ChannelVideosView.swift */,
);
path = Channels;
sourceTree = "<group>";
};
37BE0BD826A214500092E2DB /* macOS */ = { 37BE0BD826A214500092E2DB /* macOS */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -2192,6 +2215,7 @@
37D4B0C12671614700C925CA /* Shared */ = { 37D4B0C12671614700C925CA /* Shared */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
37BDFF1829487B74000C6404 /* Channels */,
37494EA329200AD4000DF176 /* Documents */, 37494EA329200AD4000DF176 /* Documents */,
3788AC2126F683AB00F6BAA9 /* Home */, 3788AC2126F683AB00F6BAA9 /* Home */,
3761AC0526F0F96100AA496F /* Modifiers */, 3761AC0526F0F96100AA496F /* Modifiers */,
@ -3031,6 +3055,7 @@
37C0698227260B2100F7F6CB /* ThumbnailsModel.swift in Sources */, 37C0698227260B2100F7F6CB /* ThumbnailsModel.swift in Sources */,
37BC50A82778A84700510953 /* HistorySettings.swift in Sources */, 37BC50A82778A84700510953 /* HistorySettings.swift in Sources */,
37DD9DB12785D58D00539416 /* RefreshControl.swift in Sources */, 37DD9DB12785D58D00539416 /* RefreshControl.swift in Sources */,
37BDFF1F29488117000C6404 /* ChannelPlaylistListItem.swift in Sources */,
371CC76C29466F5A00979C1A /* AccountsViewModel.swift in Sources */, 371CC76C29466F5A00979C1A /* AccountsViewModel.swift in Sources */,
37B4E805277D0AB4004BF56A /* Orientation.swift in Sources */, 37B4E805277D0AB4004BF56A /* Orientation.swift in Sources */,
37DD87C7271C9CFE0027CBF9 /* PlayerStreams.swift in Sources */, 37DD87C7271C9CFE0027CBF9 /* PlayerStreams.swift in Sources */,
@ -3177,6 +3202,7 @@
37599F30272B42810087F250 /* FavoriteItem.swift in Sources */, 37599F30272B42810087F250 /* FavoriteItem.swift in Sources */,
374924E729215FB60017D862 /* TapRecognizerViewModifier.swift in Sources */, 374924E729215FB60017D862 /* TapRecognizerViewModifier.swift in Sources */,
373197D92732015300EF734F /* RelatedView.swift in Sources */, 373197D92732015300EF734F /* RelatedView.swift in Sources */,
3710A55529488C7D006F8025 /* PlaceholderListItem.swift in Sources */,
37F4AD1B28612B23004D0F66 /* OpeningStream.swift in Sources */, 37F4AD1B28612B23004D0F66 /* OpeningStream.swift in Sources */,
373CFAEB26975CBF003CB2C6 /* PlaylistFormView.swift in Sources */, 373CFAEB26975CBF003CB2C6 /* PlaylistFormView.swift in Sources */,
372915E62687E3B900F5A35B /* Defaults.swift in Sources */, 372915E62687E3B900F5A35B /* Defaults.swift in Sources */,
@ -3209,6 +3235,7 @@
37C0697A2725C09E00F7F6CB /* PlayerQueueItemBridge.swift in Sources */, 37C0697A2725C09E00F7F6CB /* PlayerQueueItemBridge.swift in Sources */,
379B0253287A1CDF001015B5 /* OrientationTracker.swift in Sources */, 379B0253287A1CDF001015B5 /* OrientationTracker.swift in Sources */,
37E80F3C287B107F00561799 /* VideoDetailsOverlay.swift in Sources */, 37E80F3C287B107F00561799 /* VideoDetailsOverlay.swift in Sources */,
37BDFF1B29487C5A000C6404 /* ChannelListItem.swift in Sources */,
370B79C9286279810045DB77 /* NSObject+Swizzle.swift in Sources */, 370B79C9286279810045DB77 /* NSObject+Swizzle.swift in Sources */,
3776924E294630110055EC18 /* ChannelAvatarView.swift in Sources */, 3776924E294630110055EC18 /* ChannelAvatarView.swift in Sources */,
37D4B0E42671614900C925CA /* YatteeApp.swift in Sources */, 37D4B0E42671614900C925CA /* YatteeApp.swift in Sources */,
@ -3416,6 +3443,7 @@
37B2631B2735EAAB00FE0D40 /* FavoriteResourceObserver.swift in Sources */, 37B2631B2735EAAB00FE0D40 /* FavoriteResourceObserver.swift in Sources */,
3700155C271B0D4D0049C794 /* PipedAPI.swift in Sources */, 3700155C271B0D4D0049C794 /* PipedAPI.swift in Sources */,
376BE50C27349108009AD608 /* BrowsingSettings.swift in Sources */, 376BE50C27349108009AD608 /* BrowsingSettings.swift in Sources */,
3710A55629488C7D006F8025 /* PlaceholderListItem.swift in Sources */,
37EBD8CB27AF26C200F1C24B /* MPVBackend.swift in Sources */, 37EBD8CB27AF26C200F1C24B /* MPVBackend.swift in Sources */,
37D4B19826717E1500C925CA /* Video.swift in Sources */, 37D4B19826717E1500C925CA /* Video.swift in Sources */,
371B7E5D27596B8400D21217 /* Comment.swift in Sources */, 371B7E5D27596B8400D21217 /* Comment.swift in Sources */,
@ -3434,9 +3462,11 @@
37D4B0E52671614900C925CA /* YatteeApp.swift in Sources */, 37D4B0E52671614900C925CA /* YatteeApp.swift in Sources */,
37130A60277657300033018A /* PersistenceController.swift in Sources */, 37130A60277657300033018A /* PersistenceController.swift in Sources */,
37E8B0F127B326F30024006F /* Comparable+Clamped.swift in Sources */, 37E8B0F127B326F30024006F /* Comparable+Clamped.swift in Sources */,
37BDFF1C29487C5A000C6404 /* ChannelListItem.swift in Sources */,
37EBD8C727AF26B300F1C24B /* AVPlayerBackend.swift in Sources */, 37EBD8C727AF26B300F1C24B /* AVPlayerBackend.swift in Sources */,
37BD07C12698AD3B003EBB87 /* TrendingCountry.swift in Sources */, 37BD07C12698AD3B003EBB87 /* TrendingCountry.swift in Sources */,
37BA794026DB8F97002A0235 /* ChannelVideosView.swift in Sources */, 37BA794026DB8F97002A0235 /* ChannelVideosView.swift in Sources */,
37BDFF2029488117000C6404 /* ChannelPlaylistListItem.swift in Sources */,
3711404026B206A6005B3555 /* SearchModel.swift in Sources */, 3711404026B206A6005B3555 /* SearchModel.swift in Sources */,
37484C2A26FC83FF00287258 /* AccountForm.swift in Sources */, 37484C2A26FC83FF00287258 /* AccountForm.swift in Sources */,
37BE0BD026A0E2D50092E2DB /* VideoPlayerView.swift in Sources */, 37BE0BD026A0E2D50092E2DB /* VideoPlayerView.swift in Sources */,
@ -3558,6 +3588,7 @@
3718B9A32921A96A0003DB2E /* VideoDetailsToolbar.swift in Sources */, 3718B9A32921A96A0003DB2E /* VideoDetailsToolbar.swift in Sources */,
37F4AE7426828F0900BD60EA /* VerticalCells.swift in Sources */, 37F4AE7426828F0900BD60EA /* VerticalCells.swift in Sources */,
376578872685429C00D4EA09 /* CaseIterable+Next.swift in Sources */, 376578872685429C00D4EA09 /* CaseIterable+Next.swift in Sources */,
37BDFF1D29487C5A000C6404 /* ChannelListItem.swift in Sources */,
37D4B1802671650A00C925CA /* YatteeApp.swift in Sources */, 37D4B1802671650A00C925CA /* YatteeApp.swift in Sources */,
3748187026A769D60084E870 /* DetailBadge.swift in Sources */, 3748187026A769D60084E870 /* DetailBadge.swift in Sources */,
3741A32C27E7EFFD00D266D1 /* PlayerControls.swift in Sources */, 3741A32C27E7EFFD00D266D1 /* PlayerControls.swift in Sources */,
@ -3572,6 +3603,7 @@
37F0F4EC286F397E00C06C2E /* SettingsModel.swift in Sources */, 37F0F4EC286F397E00C06C2E /* SettingsModel.swift in Sources */,
3776925429463C310055EC18 /* PlaylistsCacheModel.swift in Sources */, 3776925429463C310055EC18 /* PlaylistsCacheModel.swift in Sources */,
37BD07C92698FBDB003EBB87 /* ContentView.swift in Sources */, 37BD07C92698FBDB003EBB87 /* ContentView.swift in Sources */,
37BDFF2129488117000C6404 /* ChannelPlaylistListItem.swift in Sources */,
37BC50AA2778A84700510953 /* HistorySettings.swift in Sources */, 37BC50AA2778A84700510953 /* HistorySettings.swift in Sources */,
37F13B64285E43C000B137E4 /* ControlsOverlay.swift in Sources */, 37F13B64285E43C000B137E4 /* ControlsOverlay.swift in Sources */,
376B2E0926F920D600B1D64D /* SignInRequiredView.swift in Sources */, 376B2E0926F920D600B1D64D /* SignInRequiredView.swift in Sources */,
@ -3613,6 +3645,7 @@
37F5E8B8291BE9D0006C15F5 /* URLBookmarkModel.swift in Sources */, 37F5E8B8291BE9D0006C15F5 /* URLBookmarkModel.swift in Sources */,
37A5DBCA285E371400CA4DD1 /* ControlBackgroundModifier.swift in Sources */, 37A5DBCA285E371400CA4DD1 /* ControlBackgroundModifier.swift in Sources */,
37E80F46287B7AEC00561799 /* PlayerQueueView.swift in Sources */, 37E80F46287B7AEC00561799 /* PlayerQueueView.swift in Sources */,
37BDFF1929487B99000C6404 /* PlaylistVideosView.swift in Sources */,
37C0698427260B2100F7F6CB /* ThumbnailsModel.swift in Sources */, 37C0698427260B2100F7F6CB /* ThumbnailsModel.swift in Sources */,
374924DC2921050B0017D862 /* LocationsSettings.swift in Sources */, 374924DC2921050B0017D862 /* LocationsSettings.swift in Sources */,
37D6025B28C17375009E8D98 /* PlaybackStatsView.swift in Sources */, 37D6025B28C17375009E8D98 /* PlaybackStatsView.swift in Sources */,
@ -3669,6 +3702,7 @@
37BA795126DC3E0E002A0235 /* Int+Format.swift in Sources */, 37BA795126DC3E0E002A0235 /* Int+Format.swift in Sources */,
3748186C26A764FB0084E870 /* Thumbnail+Fixtures.swift in Sources */, 3748186C26A764FB0084E870 /* Thumbnail+Fixtures.swift in Sources */,
3744A96228B99ADD005DE0A7 /* PlayerControlsLayout.swift in Sources */, 3744A96228B99ADD005DE0A7 /* PlayerControlsLayout.swift in Sources */,
3710A55729488C7D006F8025 /* PlaceholderListItem.swift in Sources */,
377A20AB2693C9A2002842B8 /* TypedContentAccessors.swift in Sources */, 377A20AB2693C9A2002842B8 /* TypedContentAccessors.swift in Sources */,
3748186826A7627F0084E870 /* Video+Fixtures.swift in Sources */, 3748186826A7627F0084E870 /* Video+Fixtures.swift in Sources */,
377F9F7D294403F20043F856 /* VideosCacheModel.swift in Sources */, 377F9F7D294403F20043F856 /* VideosCacheModel.swift in Sources */,