ASCollectionView for iOS Live TV channnels
This commit is contained in:
parent
bc8f5e95d9
commit
aba2e48072
|
@ -286,6 +286,7 @@
|
|||
C4BE07892728448B003F4AD1 /* LiveTVChannelsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BE07872728448B003F4AD1 /* LiveTVChannelsCoordinator.swift */; };
|
||||
C4BE078C272844AF003F4AD1 /* LiveTVChannelsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BE078A272844AF003F4AD1 /* LiveTVChannelsView.swift */; };
|
||||
C4BE078E27298818003F4AD1 /* LiveTVHomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BE078D27298817003F4AD1 /* LiveTVHomeView.swift */; };
|
||||
C4D0CE4B2848570700345D11 /* ASCollectionView in Frameworks */ = {isa = PBXBuildFile; productRef = C4D0CE4A2848570700345D11 /* ASCollectionView */; };
|
||||
C4E5081B2703F82A0045C9AB /* LibraryListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E508172703E8190045C9AB /* LibraryListView.swift */; };
|
||||
C4E5081D2703F8370045C9AB /* LibrarySearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E5081C2703F8370045C9AB /* LibrarySearchView.swift */; };
|
||||
C4E5598928124C10003DECA5 /* LiveTVChannelItemElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E5598828124C10003DECA5 /* LiveTVChannelItemElement.swift */; };
|
||||
|
@ -945,6 +946,7 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C4D0CE4B2848570700345D11 /* ASCollectionView in Frameworks */,
|
||||
62666E3E27E503FA00EC0ECD /* MediaAccessibility.framework in Frameworks */,
|
||||
62666DFF27E5016400EC0ECD /* CFNetwork.framework in Frameworks */,
|
||||
E13DD3D327168E65009D4DAF /* Defaults in Frameworks */,
|
||||
|
@ -1960,6 +1962,7 @@
|
|||
E1002B672793CFBA00E47059 /* Algorithms */,
|
||||
62666E3827E502CE00EC0ECD /* SwizzleSwift */,
|
||||
E1101176281B1E8A006A3584 /* Puppy */,
|
||||
C4D0CE4A2848570700345D11 /* ASCollectionView */,
|
||||
);
|
||||
productName = JellyfinPlayer;
|
||||
productReference = 5377CBF1263B596A003A4E83 /* Swiftfin iOS.app */;
|
||||
|
@ -2054,6 +2057,7 @@
|
|||
E1002B662793CFBA00E47059 /* XCRemoteSwiftPackageReference "swift-algorithms" */,
|
||||
62666E3727E502CE00EC0ECD /* XCRemoteSwiftPackageReference "SwizzleSwift" */,
|
||||
E1101175281B1E8A006A3584 /* XCRemoteSwiftPackageReference "Puppy" */,
|
||||
C4D0CE492848570700345D11 /* XCRemoteSwiftPackageReference "ASCollectionView" */,
|
||||
);
|
||||
productRefGroup = 5377CBF2263B596A003A4E83 /* Products */;
|
||||
projectDirPath = "";
|
||||
|
@ -3117,6 +3121,14 @@
|
|||
kind = branch;
|
||||
};
|
||||
};
|
||||
C4D0CE492848570700345D11 /* XCRemoteSwiftPackageReference "ASCollectionView" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/apptekstudios/ASCollectionView";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 2.0.0;
|
||||
};
|
||||
};
|
||||
E1002B662793CFBA00E47059 /* XCRemoteSwiftPackageReference "swift-algorithms" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/apple/swift-algorithms.git";
|
||||
|
@ -3253,6 +3265,11 @@
|
|||
package = 62C29E9A26D0FE4100C1D2E7 /* XCRemoteSwiftPackageReference "stinsen" */;
|
||||
productName = Stinsen;
|
||||
};
|
||||
C4D0CE4A2848570700345D11 /* ASCollectionView */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = C4D0CE492848570700345D11 /* XCRemoteSwiftPackageReference "ASCollectionView" */;
|
||||
productName = ASCollectionView;
|
||||
};
|
||||
E1002B672793CFBA00E47059 /* Algorithms */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = E1002B662793CFBA00E47059 /* XCRemoteSwiftPackageReference "swift-algorithms" */;
|
||||
|
|
|
@ -18,6 +18,15 @@
|
|||
"version" : "0.6.4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "ascollectionview",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apptekstudios/ASCollectionView",
|
||||
"state" : {
|
||||
"revision" : "4288744ba484c1062c109c0f28d72b629d321d55",
|
||||
"version" : "2.1.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "combineext",
|
||||
"kind" : "remoteSourceControl",
|
||||
|
@ -45,6 +54,15 @@
|
|||
"version" : "6.2.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "differencekit",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/ra1028/DifferenceKit",
|
||||
"state" : {
|
||||
"revision" : "62745d7780deef4a023a792a1f8f763ec7bf9705",
|
||||
"version" : "1.2.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "gifu",
|
||||
"kind" : "remoteSourceControl",
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
// Copyright (c) 2022 Jellyfin & Jellyfin Contributors
|
||||
//
|
||||
|
||||
import ASCollectionView
|
||||
import Foundation
|
||||
import JellyfinAPI
|
||||
import SwiftUI
|
||||
|
@ -20,19 +21,34 @@ struct LiveTVChannelsView: View {
|
|||
var viewModel = LiveTVChannelsViewModel()
|
||||
@State
|
||||
private var isPortrait = false
|
||||
|
||||
private var columns: Int {
|
||||
if UIDevice.current.userInterfaceIdiom == .pad {
|
||||
return 2
|
||||
} else {
|
||||
if isPortrait {
|
||||
return 1
|
||||
} else {
|
||||
return 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
if viewModel.isLoading == true {
|
||||
ProgressView()
|
||||
} else if !viewModel.rows.isEmpty {
|
||||
CollectionView(rows: viewModel.rows) { _, _ in
|
||||
createGridLayout()
|
||||
} cell: { indexPath, cell in
|
||||
makeCellView(indexPath: indexPath, cell: cell)
|
||||
} supplementaryView: { _, indexPath in
|
||||
EmptyView()
|
||||
.accessibilityIdentifier("\(indexPath.section).\(indexPath.row)")
|
||||
}
|
||||
} else if !viewModel.channelPrograms.isEmpty {
|
||||
ASCollectionView(data: viewModel.channelPrograms, dataID: \.self)
|
||||
{ channelProgram, _ in
|
||||
makeCellView(channelProgram)
|
||||
}
|
||||
.layout
|
||||
{
|
||||
.grid(
|
||||
layoutMode: .fixedNumberOfColumns(columns),
|
||||
itemSpacing: 16,
|
||||
lineSpacing: 4,
|
||||
itemSize: .absolute(144))
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.ignoresSafeArea()
|
||||
.onAppear {
|
||||
|
@ -58,22 +74,21 @@ struct LiveTVChannelsView: View {
|
|||
}
|
||||
|
||||
@ViewBuilder
|
||||
func makeCellView(indexPath: IndexPath, cell: LiveTVChannelRowCell) -> some View {
|
||||
let item = cell.item
|
||||
let channel = item.channel
|
||||
let currentProgramDisplayText = item.currentProgram?
|
||||
func makeCellView(_ channelProgram: LiveTVChannelProgram) -> some View {
|
||||
let channel = channelProgram.channel
|
||||
let currentProgramDisplayText = channelProgram.currentProgram?
|
||||
.programDisplayText(timeFormatter: viewModel.timeFormatter) ?? LiveTVChannelViewProgram(timeDisplay: "", title: "")
|
||||
let nextItems = item.programs.filter { program in
|
||||
let nextItems = channelProgram.programs.filter { program in
|
||||
guard let start = program.startDate else {
|
||||
return false
|
||||
}
|
||||
guard let currentStart = item.currentProgram?.startDate else {
|
||||
guard let currentStart = channelProgram.currentProgram?.startDate else {
|
||||
return false
|
||||
}
|
||||
return start > currentStart
|
||||
}
|
||||
LiveTVChannelItemWideElement(channel: channel,
|
||||
currentProgram: item.currentProgram,
|
||||
currentProgram: channelProgram.currentProgram,
|
||||
currentProgramText: currentProgramDisplayText,
|
||||
nextProgramsText: nextProgramsDisplayText(nextItems: nextItems,
|
||||
timeFormatter: viewModel.timeFormatter),
|
||||
|
@ -88,62 +103,6 @@ struct LiveTVChannelsView: View {
|
|||
})
|
||||
}
|
||||
|
||||
private func createGridLayout() -> NSCollectionLayoutSection {
|
||||
if UIDevice.current.userInterfaceIdiom == .pad {
|
||||
let itemSize = NSCollectionLayoutSize(widthDimension: .absolute((UIScreen.main.bounds.width / 2) - 16),
|
||||
heightDimension: .fractionalHeight(1))
|
||||
let item = NSCollectionLayoutItem(layoutSize: itemSize)
|
||||
item.edgeSpacing = NSCollectionLayoutEdgeSpacing(leading: .flexible(0), top: nil,
|
||||
trailing: .flexible(2), bottom: .flexible(2))
|
||||
let item2 = NSCollectionLayoutItem(layoutSize: itemSize)
|
||||
item2.edgeSpacing = NSCollectionLayoutEdgeSpacing(leading: nil, top: nil,
|
||||
trailing: .flexible(0), bottom: .flexible(2))
|
||||
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
|
||||
heightDimension: .absolute(144))
|
||||
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize,
|
||||
subitems: [item, item2])
|
||||
let section = NSCollectionLayoutSection(group: group)
|
||||
return section
|
||||
} else {
|
||||
if isPortrait {
|
||||
let itemSize = NSCollectionLayoutSize(widthDimension: .absolute(UIScreen.main.bounds.width - 32),
|
||||
heightDimension: .fractionalHeight(1))
|
||||
let item = NSCollectionLayoutItem(layoutSize: itemSize)
|
||||
item.edgeSpacing = NSCollectionLayoutEdgeSpacing(leading: .flexible(0), top: nil,
|
||||
trailing: .flexible(2), bottom: .flexible(2))
|
||||
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
|
||||
heightDimension: .absolute(144))
|
||||
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize,
|
||||
subitems: [item])
|
||||
let section = NSCollectionLayoutSection(group: group)
|
||||
return section
|
||||
} else {
|
||||
|
||||
let scenes = UIApplication.shared.connectedScenes
|
||||
let windowScene = scenes.first as? UIWindowScene
|
||||
var width = (UIScreen.main.bounds.width / 2) - 32
|
||||
if let safeArea = windowScene?.keyWindow?.safeAreaInsets {
|
||||
width = (UIScreen.main.bounds.width / 2) - safeArea.left - safeArea.right
|
||||
}
|
||||
|
||||
let itemSize = NSCollectionLayoutSize(widthDimension: .absolute(width),
|
||||
heightDimension: .fractionalHeight(1))
|
||||
let item = NSCollectionLayoutItem(layoutSize: itemSize)
|
||||
item.edgeSpacing = NSCollectionLayoutEdgeSpacing(leading: .flexible(0), top: nil,
|
||||
trailing: .flexible(2), bottom: .flexible(2))
|
||||
let item2 = NSCollectionLayoutItem(layoutSize: itemSize)
|
||||
item2.edgeSpacing = NSCollectionLayoutEdgeSpacing(leading: nil, top: nil,
|
||||
trailing: .flexible(0), bottom: .flexible(2))
|
||||
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
|
||||
heightDimension: .absolute(144))
|
||||
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize,
|
||||
subitems: [item, item2])
|
||||
let section = NSCollectionLayoutSection(group: group)
|
||||
return section
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func checkOrientation() {
|
||||
let scenes = UIApplication.shared.connectedScenes
|
||||
let windowScene = scenes.first as? UIWindowScene
|
||||
|
|
Loading…
Reference in New Issue