Merge pull request #311 from LePips/thumb-images-and-fallback-imageview

This commit is contained in:
aiden 3 2022-01-18 09:56:18 -05:00 committed by GitHub
commit 37c91af038
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 105 additions and 35 deletions

View File

@ -92,6 +92,16 @@ public extension BaseItemDto {
return URL(string: urlString)! return URL(string: urlString)!
} }
func getThumbImage(maxWidth: Int) -> URL {
let x = UIScreen.main.nativeScale * CGFloat(maxWidth)
let urlString = ImageAPI.getItemImageWithRequestBuilder(itemId: id ?? "",
imageType: .thumb,
maxWidth: Int(x),
quality: 96).URLString
return URL(string: urlString)!
}
func getEpisodeLocator() -> String? { func getEpisodeLocator() -> String? {
if let seasonNo = parentIndexNumber, let episodeNo = indexNumber { if let seasonNo = parentIndexNumber, let episodeNo = indexNumber {
return L10n.seasonAndEpisode(String(seasonNo), String(episodeNo)) return L10n.seasonAndEpisode(String(seasonNo), String(episodeNo))
@ -119,6 +129,16 @@ public extension BaseItemDto {
return URL(string: urlString)! return URL(string: urlString)!
} }
func getSeriesThumbImage(maxWidth: Int) -> URL {
let x = UIScreen.main.nativeScale * CGFloat(maxWidth)
let urlString = ImageAPI.getItemImageWithRequestBuilder(itemId: seriesId ?? "",
imageType: .thumb,
maxWidth: Int(x),
quality: 96,
tag: seriesPrimaryImageTag).URLString
return URL(string: urlString)!
}
func getPrimaryImage(maxWidth: Int) -> URL { func getPrimaryImage(maxWidth: Int) -> URL {
let imageType = ImageType.primary let imageType = ImageType.primary
var imageTag = imageTags?[ImageType.primary.rawValue] ?? "" var imageTag = imageTags?[ImageType.primary.rawValue] ?? ""

View File

@ -10,26 +10,52 @@ import NukeUI
import SwiftUI import SwiftUI
struct ImageView: View { struct ImageView: View {
private let source: URL
@State
private var sources: [URL]
private var currentURL: URL? { sources.first }
private let blurhash: String private let blurhash: String
private let failureInitials: String private let failureInitials: String
init(src: URL, bh: String = "001fC^", failureInitials: String = "") { init(src: URL, bh: String = "001fC^", failureInitials: String = "") {
self.source = src self.sources = [src]
self.blurhash = bh self.blurhash = bh
self.failureInitials = failureInitials self.failureInitials = failureInitials
} }
// TODO: fix placeholder hash image init(sources: [URL], bh: String = "001fC^", failureInitials: String = "") {
assert(!sources.isEmpty, "Must supply at least one source")
self.sources = sources
self.blurhash = bh
self.failureInitials = failureInitials
}
// TODO: fix placeholder hash view
@ViewBuilder @ViewBuilder
private var placeholderImage: some View { private func placeholderView() -> some View {
Image(uiImage: UIImage(blurHash: blurhash, size: CGSize(width: 8, height: 8)) ?? // Image(uiImage: UIImage(blurHash: blurhash, size: CGSize(width: 8, height: 8)) ??
UIImage(blurHash: "001fC^", size: CGSize(width: 8, height: 8))!) // UIImage(blurHash: "001fC^", size: CGSize(width: 8, height: 8))!)
.resizable() // .resizable()
#if os(tvOS)
ZStack {
Color.black.ignoresSafeArea()
ProgressView()
}
#else
ZStack {
Color.gray.ignoresSafeArea()
ProgressView()
}
#endif
} }
@ViewBuilder @ViewBuilder
private var failureImage: some View { private func failureImage() -> some View {
ZStack { ZStack {
Rectangle() Rectangle()
.foregroundColor(Color(UIColor.darkGray)) .foregroundColor(Color(UIColor.darkGray))
@ -42,27 +68,20 @@ struct ImageView: View {
} }
var body: some View { var body: some View {
LazyImage(source: source) { state in if let u = currentURL {
if let image = state.image { LazyImage(source: u) { state in
image if let image = state.image {
} else if state.error != nil { image
failureImage } else if state.error != nil {
} else { failureImage().onAppear { sources.removeFirst() }
#if os(tvOS) } else {
ZStack { placeholderView()
Color.black.ignoresSafeArea() }
ProgressView()
}
#else
ZStack {
Color.gray.ignoresSafeArea()
ProgressView()
}
#endif
} }
.pipeline(ImagePipeline(configuration: .withDataCache))
.id(u)
} else {
failureImage()
} }
.pipeline(ImagePipeline(configuration: .withDataCache))
} }
} }

View File

@ -24,10 +24,17 @@ struct CinematicNextUpCardView: View {
ZStack(alignment: .bottomLeading) { ZStack(alignment: .bottomLeading) {
if item.itemType == .episode { if item.itemType == .episode {
ImageView(src: item.getSeriesBackdropImage(maxWidth: 350)) ImageView(sources: [
item.getSeriesThumbImage(maxWidth: 350),
item.getSeriesBackdropImage(maxWidth: 350),
])
.frame(width: 350, height: 210) .frame(width: 350, height: 210)
} else { } else {
ImageView(src: item.getBackdropImage(maxWidth: 350)) ImageView(sources: [
item.getThumbImage(maxWidth: 350),
item.getBackdropImage(maxWidth: 350),
],
bh: item.getBackdropImageBlurHash())
.frame(width: 350, height: 210) .frame(width: 350, height: 210)
} }

View File

@ -25,10 +25,17 @@ struct CinematicResumeCardView: View {
ZStack(alignment: .bottom) { ZStack(alignment: .bottom) {
if item.itemType == .episode { if item.itemType == .episode {
ImageView(src: item.getSeriesBackdropImage(maxWidth: 350)) ImageView(sources: [
item.getSeriesThumbImage(maxWidth: 350),
item.getSeriesBackdropImage(maxWidth: 350),
])
.frame(width: 350, height: 210) .frame(width: 350, height: 210)
} else { } else {
ImageView(src: item.getBackdropImage(maxWidth: 350)) ImageView(sources: [
item.getThumbImage(maxWidth: 350),
item.getBackdropImage(maxWidth: 350),
],
bh: item.getBackdropImageBlurHash())
.frame(width: 350, height: 210) .frame(width: 350, height: 210)
} }

View File

@ -27,9 +27,22 @@ struct ContinueWatchingView: View {
VStack(alignment: .leading) { VStack(alignment: .leading) {
ZStack { ZStack {
ImageView(src: item.getBackdropImage(maxWidth: 320), bh: item.getBackdropImageBlurHash()) Group {
.frame(width: 320, height: 180) if item.itemType == .episode {
.accessibilityIgnoresInvertColors() ImageView(sources: [
item.getSeriesThumbImage(maxWidth: 320),
item.getSeriesBackdropImage(maxWidth: 320),
])
.frame(width: 320, height: 180)
} else {
ImageView(sources: [
item.getThumbImage(maxWidth: 320),
item.getBackdropImage(maxWidth: 320),
])
.frame(width: 320, height: 180)
}
}
.accessibilityIgnoresInvertColors()
HStack { HStack {
VStack { VStack {

View File

@ -48,6 +48,8 @@ struct ItemViewDetailsView: View {
L10n.file.text L10n.file.text
.font(.subheadline) .font(.subheadline)
Text(viewModel.selectedVideoPlayerViewModel?.filename ?? "--") Text(viewModel.selectedVideoPlayerViewModel?.filename ?? "--")
.lineLimit(nil)
.fixedSize(horizontal: false, vertical: true)
.font(.subheadline) .font(.subheadline)
.foregroundColor(Color.secondary) .foregroundColor(Color.secondary)
} }
@ -67,6 +69,8 @@ struct ItemViewDetailsView: View {
Text(mediaItem.title) Text(mediaItem.title)
.font(.subheadline) .font(.subheadline)
Text(mediaItem.content) Text(mediaItem.content)
.lineLimit(nil)
.fixedSize(horizontal: false, vertical: true)
.font(.subheadline) .font(.subheadline)
.foregroundColor(Color.secondary) .foregroundColor(Color.secondary)
} }