diff --git a/Shared/Views/BlurHashView.swift b/Shared/Views/BlurHashView.swift new file mode 100644 index 00000000..9e8d3805 --- /dev/null +++ b/Shared/Views/BlurHashView.swift @@ -0,0 +1,61 @@ +// +// Swiftfin is subject to the terms of the Mozilla Public +// License, v2.0. If a copy of the MPL was not distributed with this +// file, you can obtain one at https://mozilla.org/MPL/2.0/. +// +// Copyright (c) 2022 Jellyfin & Jellyfin Contributors +// + +import SwiftUI +import UIKit + +struct BlurHashView: UIViewRepresentable { + + let blurHash: String + + func makeUIView(context: Context) -> UIBlurHashView { + return UIBlurHashView(blurHash) + } + + func updateUIView(_ uiView: UIBlurHashView, context: Context) {} +} + +class UIBlurHashView: UIView { + + private let imageView: UIImageView + + init(_ blurHash: String) { + let imageView = UIImageView() + imageView.translatesAutoresizingMaskIntoConstraints = false + self.imageView = imageView + + super.init(frame: .zero) + + computeBlurHashImageAsync(blurHash: blurHash) { blurImage in + DispatchQueue.main.async { + self.imageView.image = blurImage + self.imageView.setNeedsDisplay() + } + } + + addSubview(imageView) + + NSLayoutConstraint.activate([ + imageView.topAnchor.constraint(equalTo: topAnchor), + imageView.bottomAnchor.constraint(equalTo: bottomAnchor), + imageView.leftAnchor.constraint(equalTo: leftAnchor), + imageView.rightAnchor.constraint(equalTo: rightAnchor), + ]) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func computeBlurHashImageAsync(blurHash: String, _ completion: @escaping (UIImage?) -> Void) { + DispatchQueue.global(qos: .utility).async { + let image = UIImage(blurHash: blurHash, size: .Circle(radius: 12)) + completion(image) + } + } +} diff --git a/Shared/Views/LiveTVChannelItemElement.swift b/Shared/Views/LiveTVChannelItemElement.swift index f9472a50..f8671a25 100644 --- a/Shared/Views/LiveTVChannelItemElement.swift +++ b/Shared/Views/LiveTVChannelItemElement.swift @@ -29,7 +29,7 @@ struct LiveTVChannelItemElement: View { .font(.footnote) .frame(alignment: .trailing) }.frame(alignment: .top) - ImageView(src: channel.getPrimaryImage(maxWidth: 125)) + ImageView(channel.getPrimaryImage(maxWidth: 125)) .frame(width: 125, alignment: .center) .offset(x: 0, y: -32) Text(channel.name ?? "?") diff --git a/Swiftfin tvOS/Components/EpisodesRowView/EpisodesRowCard.swift b/Swiftfin tvOS/Components/EpisodesRowView/EpisodesRowCard.swift index 0f27d13d..5d00f1e2 100644 --- a/Swiftfin tvOS/Components/EpisodesRowView/EpisodesRowCard.swift +++ b/Swiftfin tvOS/Components/EpisodesRowView/EpisodesRowCard.swift @@ -21,8 +21,8 @@ struct EpisodeRowCard: View { Button { itemRouter.route(to: \.item, episode) } label: { - ImageView(src: episode.getBackdropImage(maxWidth: 550), - bh: episode.getBackdropImageBlurHash()) + ImageView(episode.getBackdropImage(maxWidth: 550), + blurHash: episode.getBackdropImageBlurHash()) .mask(Rectangle().frame(width: 550, height: 308)) .frame(width: 550, height: 308) } diff --git a/Swiftfin tvOS/Components/HomeCinematicView/CinematicNextUpCardView.swift b/Swiftfin tvOS/Components/HomeCinematicView/CinematicNextUpCardView.swift index d21d2c71..c31a89f9 100644 --- a/Swiftfin tvOS/Components/HomeCinematicView/CinematicNextUpCardView.swift +++ b/Swiftfin tvOS/Components/HomeCinematicView/CinematicNextUpCardView.swift @@ -34,7 +34,7 @@ struct CinematicNextUpCardView: View { item.getThumbImage(maxWidth: 350), item.getBackdropImage(maxWidth: 350), ], - bh: item.getBackdropImageBlurHash()) + blurHash: item.getBackdropImageBlurHash()) .frame(width: 350, height: 210) } diff --git a/Swiftfin tvOS/Components/HomeCinematicView/CinematicResumeCardView.swift b/Swiftfin tvOS/Components/HomeCinematicView/CinematicResumeCardView.swift index a129a4df..21914da3 100644 --- a/Swiftfin tvOS/Components/HomeCinematicView/CinematicResumeCardView.swift +++ b/Swiftfin tvOS/Components/HomeCinematicView/CinematicResumeCardView.swift @@ -35,7 +35,7 @@ struct CinematicResumeCardView: View { item.getThumbImage(maxWidth: 350), item.getBackdropImage(maxWidth: 350), ], - bh: item.getBackdropImageBlurHash()) + blurHash: item.getBackdropImageBlurHash()) .frame(width: 350, height: 210) } diff --git a/Swiftfin tvOS/Components/LandscapeItemElement.swift b/Swiftfin tvOS/Components/LandscapeItemElement.swift index efae06e9..a5217b96 100644 --- a/Swiftfin tvOS/Components/LandscapeItemElement.swift +++ b/Swiftfin tvOS/Components/LandscapeItemElement.swift @@ -46,9 +46,9 @@ struct LandscapeItemElement: View { var body: some View { VStack { - ImageView(src: item.type == "Episode" && !(inSeasonView ?? false) ? item.getSeriesBackdropImage(maxWidth: 445) : item + ImageView(item.type == "Episode" && !(inSeasonView ?? false) ? item.getSeriesBackdropImage(maxWidth: 445) : item .getBackdropImage(maxWidth: 445), - bh: item.type == "Episode" ? item.getSeriesBackdropImageBlurHash() : item.getBackdropImageBlurHash()) + blurHash: item.type == "Episode" ? item.getSeriesBackdropImageBlurHash() : item.getBackdropImageBlurHash()) .frame(width: 445, height: 250) .cornerRadius(10) .ignoresSafeArea() diff --git a/Swiftfin tvOS/Components/PortraitItemElement.swift b/Swiftfin tvOS/Components/PortraitItemElement.swift index 044ca526..1f7d6323 100644 --- a/Swiftfin tvOS/Components/PortraitItemElement.swift +++ b/Swiftfin tvOS/Components/PortraitItemElement.swift @@ -21,8 +21,8 @@ struct PortraitItemElement: View { var body: some View { VStack { - ImageView(src: item.type == "Episode" ? item.getSeriesPrimaryImage(maxWidth: 200) : item.getPrimaryImage(maxWidth: 200), - bh: item.type == "Episode" ? item.getSeriesPrimaryImageBlurHash() : item.getPrimaryImageBlurHash()) + ImageView(item.type == "Episode" ? item.getSeriesPrimaryImage(maxWidth: 200) : item.getPrimaryImage(maxWidth: 200), + blurHash: item.type == "Episode" ? item.getSeriesPrimaryImageBlurHash() : item.getPrimaryImageBlurHash()) .frame(width: 200, height: 300) .cornerRadius(10) .shadow(radius: focused ? 10.0 : 0) diff --git a/Swiftfin tvOS/Components/PortraitItemsRowView.swift b/Swiftfin tvOS/Components/PortraitItemsRowView.swift index 6d0c43d7..a3e89660 100644 --- a/Swiftfin tvOS/Components/PortraitItemsRowView.swift +++ b/Swiftfin tvOS/Components/PortraitItemsRowView.swift @@ -45,7 +45,7 @@ struct PortraitItemsRowView: View { Button { selectedAction(item) } label: { - ImageView(src: item.portraitHeaderViewURL(maxWidth: 257)) + ImageView(item.portraitHeaderViewURL(maxWidth: 257)) .frame(width: 257, height: 380) } .frame(height: 380) diff --git a/Swiftfin tvOS/Components/PublicUserButton.swift b/Swiftfin tvOS/Components/PublicUserButton.swift index 4b07dfe9..1f4868d9 100644 --- a/Swiftfin tvOS/Components/PublicUserButton.swift +++ b/Swiftfin tvOS/Components/PublicUserButton.swift @@ -20,7 +20,7 @@ struct PublicUserButton: View { var body: some View { VStack { if publicUser.primaryImageTag != nil { - ImageView(src: URL(string: "\(SessionManager.main.currentLogin.server.currentURI)/Users/\(publicUser.id ?? "")/Images/Primary?width=500&quality=80&tag=\(publicUser.primaryImageTag!)")!) + ImageView(URL(string: "\(SessionManager.main.currentLogin.server.currentURI)/Users/\(publicUser.id ?? "")/Images/Primary?width=500&quality=80&tag=\(publicUser.primaryImageTag!)")!) .frame(width: 250, height: 250) .cornerRadius(125.0) } else { diff --git a/Swiftfin tvOS/Views/ContinueWatchingView/ContinueWatchingCard.swift b/Swiftfin tvOS/Views/ContinueWatchingView/ContinueWatchingCard.swift index daac3470..2b7cf408 100644 --- a/Swiftfin tvOS/Views/ContinueWatchingView/ContinueWatchingCard.swift +++ b/Swiftfin tvOS/Views/ContinueWatchingView/ContinueWatchingCard.swift @@ -23,10 +23,10 @@ struct ContinueWatchingCard: View { ZStack(alignment: .bottom) { if item.itemType == .episode { - ImageView(src: item.getSeriesBackdropImage(maxWidth: 500)) + ImageView(item.getSeriesBackdropImage(maxWidth: 500)) .frame(width: 500, height: 281.25) } else { - ImageView(src: item.getBackdropImage(maxWidth: 500)) + ImageView(item.getBackdropImage(maxWidth: 500)) .frame(width: 500, height: 281.25) } diff --git a/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicCollectionItemView.swift b/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicCollectionItemView.swift index c17bfdf9..d82fb6a7 100644 --- a/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicCollectionItemView.swift +++ b/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicCollectionItemView.swift @@ -24,8 +24,8 @@ struct CinematicCollectionItemView: View { var body: some View { ZStack { - ImageView(src: viewModel.item.getBackdropImage(maxWidth: 1920), - bh: viewModel.item.getBackdropImageBlurHash()) + ImageView(viewModel.item.getBackdropImage(maxWidth: 1920), + blurHash: viewModel.item.getBackdropImageBlurHash()) .ignoresSafeArea() ScrollView { diff --git a/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicEpisodeItemView.swift b/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicEpisodeItemView.swift index 8ce92dd3..13d1360f 100644 --- a/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicEpisodeItemView.swift +++ b/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicEpisodeItemView.swift @@ -32,8 +32,8 @@ struct CinematicEpisodeItemView: View { var body: some View { ZStack { - ImageView(src: viewModel.item.getBackdropImage(maxWidth: 1920), - bh: viewModel.item.getBackdropImageBlurHash()) + ImageView(viewModel.item.getBackdropImage(maxWidth: 1920), + blurHash: viewModel.item.getBackdropImageBlurHash()) .frame(height: UIScreen.main.bounds.height - 10) .ignoresSafeArea() diff --git a/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicItemAboutView.swift b/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicItemAboutView.swift index 6e6230b3..151b0e20 100644 --- a/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicItemAboutView.swift +++ b/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicItemAboutView.swift @@ -17,7 +17,7 @@ struct CinematicItemAboutView: View { var body: some View { HStack(alignment: .top, spacing: 10) { - ImageView(src: viewModel.item.portraitHeaderViewURL(maxWidth: 257)) + ImageView(viewModel.item.portraitHeaderViewURL(maxWidth: 257)) .portraitPoster(width: 257) ZStack(alignment: .topLeading) { diff --git a/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicMovieItemView.swift b/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicMovieItemView.swift index b8982cb0..efd04c5a 100644 --- a/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicMovieItemView.swift +++ b/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicMovieItemView.swift @@ -24,8 +24,8 @@ struct CinematicMovieItemView: View { var body: some View { ZStack { - ImageView(src: viewModel.item.getBackdropImage(maxWidth: 1920), - bh: viewModel.item.getBackdropImageBlurHash()) + ImageView(viewModel.item.getBackdropImage(maxWidth: 1920), + blurHash: viewModel.item.getBackdropImageBlurHash()) .ignoresSafeArea() ScrollView { diff --git a/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicSeasonItemView.swift b/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicSeasonItemView.swift index e6e18eeb..aec16c2a 100644 --- a/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicSeasonItemView.swift +++ b/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicSeasonItemView.swift @@ -23,7 +23,7 @@ struct CinematicSeasonItemView: View { var body: some View { ZStack { - ImageView(src: viewModel.item.getBackdropImage(maxWidth: 1920), bh: viewModel.item.getBackdropImageBlurHash()) + ImageView(viewModel.item.getBackdropImage(maxWidth: 1920), blurHash: viewModel.item.getBackdropImageBlurHash()) .ignoresSafeArea() ScrollView { diff --git a/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicSeriesItemView.swift b/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicSeriesItemView.swift index 0d2fb619..06930f7a 100644 --- a/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicSeriesItemView.swift +++ b/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicSeriesItemView.swift @@ -23,7 +23,7 @@ struct CinematicSeriesItemView: View { var body: some View { ZStack { - ImageView(src: viewModel.item.getBackdropImage(maxWidth: 1920), bh: viewModel.item.getBackdropImageBlurHash()) + ImageView(viewModel.item.getBackdropImage(maxWidth: 1920), blurHash: viewModel.item.getBackdropImageBlurHash()) .ignoresSafeArea() ScrollView { diff --git a/Swiftfin tvOS/Views/ItemView/CompactItemView/EpisodeItemView.swift b/Swiftfin tvOS/Views/ItemView/CompactItemView/EpisodeItemView.swift index b6fc94b3..e50c2698 100644 --- a/Swiftfin tvOS/Views/ItemView/CompactItemView/EpisodeItemView.swift +++ b/Swiftfin tvOS/Views/ItemView/CompactItemView/EpisodeItemView.swift @@ -45,7 +45,7 @@ struct EpisodeItemView: View { var body: some View { ZStack { - ImageView(src: viewModel.item.getBackdropImage(maxWidth: 1920), bh: viewModel.item.getBackdropImageBlurHash()) + ImageView(viewModel.item.getBackdropImage(maxWidth: 1920), blurHash: viewModel.item.getBackdropImageBlurHash()) .opacity(0.4) .ignoresSafeArea() LazyVStack(alignment: .leading) { diff --git a/Swiftfin tvOS/Views/ItemView/CompactItemView/MovieItemView.swift b/Swiftfin tvOS/Views/ItemView/CompactItemView/MovieItemView.swift index cb19aba6..e52498e5 100644 --- a/Swiftfin tvOS/Views/ItemView/CompactItemView/MovieItemView.swift +++ b/Swiftfin tvOS/Views/ItemView/CompactItemView/MovieItemView.swift @@ -50,7 +50,7 @@ struct MovieItemView: View { var body: some View { ZStack { - ImageView(src: viewModel.item.getBackdropImage(maxWidth: 1920), bh: viewModel.item.getBackdropImageBlurHash()) + ImageView(viewModel.item.getBackdropImage(maxWidth: 1920), blurHash: viewModel.item.getBackdropImageBlurHash()) .opacity(0.4) .ignoresSafeArea() ScrollView { diff --git a/Swiftfin tvOS/Views/ItemView/CompactItemView/SeasonItemView.swift b/Swiftfin tvOS/Views/ItemView/CompactItemView/SeasonItemView.swift index 33a40736..b01aba83 100644 --- a/Swiftfin tvOS/Views/ItemView/CompactItemView/SeasonItemView.swift +++ b/Swiftfin tvOS/Views/ItemView/CompactItemView/SeasonItemView.swift @@ -25,7 +25,7 @@ struct SeasonItemView: View { var body: some View { ZStack { - ImageView(src: viewModel.item.getSeriesBackdropImage(maxWidth: 1920), bh: viewModel.item.getSeriesBackdropImageBlurHash()) + ImageView(viewModel.item.getSeriesBackdropImage(maxWidth: 1920), blurHash: viewModel.item.getSeriesBackdropImageBlurHash()) .opacity(0.4) .ignoresSafeArea() ScrollView { diff --git a/Swiftfin tvOS/Views/ItemView/CompactItemView/SeriesItemView.swift b/Swiftfin tvOS/Views/ItemView/CompactItemView/SeriesItemView.swift index 53ac05bb..b9752602 100644 --- a/Swiftfin tvOS/Views/ItemView/CompactItemView/SeriesItemView.swift +++ b/Swiftfin tvOS/Views/ItemView/CompactItemView/SeriesItemView.swift @@ -53,7 +53,7 @@ struct SeriesItemView: View { var body: some View { ZStack { - ImageView(src: viewModel.item.getBackdropImage(maxWidth: 1920), bh: viewModel.item.getBackdropImageBlurHash()) + ImageView(viewModel.item.getBackdropImage(maxWidth: 1920), blurHash: viewModel.item.getBackdropImageBlurHash()) .opacity(0.4) .ignoresSafeArea() ScrollView { diff --git a/Swiftfin tvOS/Views/LatestMediaView.swift b/Swiftfin tvOS/Views/LatestMediaView.swift index c2cc6f87..07a3af34 100644 --- a/Swiftfin tvOS/Views/LatestMediaView.swift +++ b/Swiftfin tvOS/Views/LatestMediaView.swift @@ -34,7 +34,7 @@ struct LatestMediaView: View { Button { homeRouter.route(to: \.modalItem, item) } label: { - ImageView(src: item.portraitHeaderViewURL(maxWidth: 257)) + ImageView(item.portraitHeaderViewURL(maxWidth: 257)) .frame(width: 257, height: 380) } .frame(height: 380) diff --git a/Swiftfin tvOS/Views/NextUpView/NextUpCard.swift b/Swiftfin tvOS/Views/NextUpView/NextUpCard.swift index 8e3e9083..27ffcc68 100644 --- a/Swiftfin tvOS/Views/NextUpView/NextUpCard.swift +++ b/Swiftfin tvOS/Views/NextUpView/NextUpCard.swift @@ -21,10 +21,10 @@ struct NextUpCard: View { homeRouter.route(to: \.modalItem, item) } label: { if item.itemType == .episode { - ImageView(src: item.getSeriesBackdropImage(maxWidth: 500)) + ImageView(item.getSeriesBackdropImage(maxWidth: 500)) .frame(width: 500, height: 281.25) } else { - ImageView(src: item.getBackdropImage(maxWidth: 500)) + ImageView(item.getBackdropImage(maxWidth: 500)) .frame(width: 500, height: 281.25) } } diff --git a/Swiftfin tvOS/Views/VideoPlayer/Overlays/SmallMenuOverlay.swift b/Swiftfin tvOS/Views/VideoPlayer/Overlays/SmallMenuOverlay.swift index 010cf779..78af9836 100644 --- a/Swiftfin tvOS/Views/VideoPlayer/Overlays/SmallMenuOverlay.swift +++ b/Swiftfin tvOS/Views/VideoPlayer/Overlays/SmallMenuOverlay.swift @@ -329,7 +329,7 @@ struct SmallMediaStreamSelectionView: View { Button { viewModel.playerOverlayDelegate?.didSelectChapter(viewModel.chapters[chapterIndex]) } label: { - ImageView(src: chapterImages[chapterIndex]) + ImageView(chapterImages[chapterIndex]) .cornerRadius(10) .frame(width: 350, height: 210) } diff --git a/Swiftfin.xcodeproj/project.pbxproj b/Swiftfin.xcodeproj/project.pbxproj index cb21589b..4975c6ff 100644 --- a/Swiftfin.xcodeproj/project.pbxproj +++ b/Swiftfin.xcodeproj/project.pbxproj @@ -292,6 +292,8 @@ E103A6A5278A82E500820EC7 /* HomeCinematicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E103A6A4278A82E500820EC7 /* HomeCinematicView.swift */; }; E103A6A7278AB6D700820EC7 /* CinematicResumeCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E103A6A6278AB6D700820EC7 /* CinematicResumeCardView.swift */; }; E103A6A9278AB6FF00820EC7 /* CinematicNextUpCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E103A6A8278AB6FF00820EC7 /* CinematicNextUpCardView.swift */; }; + E1047E2027E584AF00CB0D4A /* BlurHashView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1047E1F27E584AF00CB0D4A /* BlurHashView.swift */; }; + E1047E2127E584AF00CB0D4A /* BlurHashView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1047E1F27E584AF00CB0D4A /* BlurHashView.swift */; }; E107BB9327880A8F00354E07 /* CollectionItemViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E107BB9227880A8F00354E07 /* CollectionItemViewModel.swift */; }; E107BB9427880A8F00354E07 /* CollectionItemViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E107BB9227880A8F00354E07 /* CollectionItemViewModel.swift */; }; E107BB972788104100354E07 /* CinematicCollectionItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E107BB952788104100354E07 /* CinematicCollectionItemView.swift */; }; @@ -760,6 +762,7 @@ E103A6A4278A82E500820EC7 /* HomeCinematicView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeCinematicView.swift; sourceTree = ""; }; E103A6A6278AB6D700820EC7 /* CinematicResumeCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CinematicResumeCardView.swift; sourceTree = ""; }; E103A6A8278AB6FF00820EC7 /* CinematicNextUpCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CinematicNextUpCardView.swift; sourceTree = ""; }; + E1047E1F27E584AF00CB0D4A /* BlurHashView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlurHashView.swift; sourceTree = ""; }; E107BB9227880A8F00354E07 /* CollectionItemViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionItemViewModel.swift; sourceTree = ""; }; E107BB952788104100354E07 /* CinematicCollectionItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CinematicCollectionItemView.swift; sourceTree = ""; }; E10C0940278B8DAB009DBF93 /* PortraitItemSize.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PortraitItemSize.swift; sourceTree = ""; }; @@ -1748,6 +1751,7 @@ E1AD105326D96F5A003E4A08 /* Views */ = { isa = PBXGroup; children = ( + E1047E1F27E584AF00CB0D4A /* BlurHashView.swift */, 531AC8BE26750DE20091C7EB /* ImageView.swift */, 621338B22660A07800A81A2A /* LazyView.swift */, C4E52304272CE68800654268 /* LiveTVChannelItemElement.swift */, @@ -2243,6 +2247,7 @@ C4BE078C272844AF003F4AD1 /* LiveTVChannelsView.swift in Sources */, E1D4BF852719D25A00A11E64 /* TrackLanguage.swift in Sources */, 53272532268BF09D0035FBF1 /* MediaViewActionButton.swift in Sources */, + E1047E2127E584AF00CB0D4A /* BlurHashView.swift in Sources */, 531690F0267ABF72005D8AB9 /* NextUpView.swift in Sources */, E193D53427193F7F00900D82 /* HomeCoordinator.swift in Sources */, E193D5502719430400900D82 /* ServerDetailView.swift in Sources */, @@ -2390,6 +2395,7 @@ E1EBCB42278BD174009FE6E9 /* TruncatedTextView.swift in Sources */, 62133890265F83A900A81A2A /* LibraryListView.swift in Sources */, 62C29EA326D1030F00C1D2E7 /* ConnectToServerCoodinator.swift in Sources */, + E1047E2027E584AF00CB0D4A /* BlurHashView.swift in Sources */, 62E632DA267D2BC40063E547 /* LatestMediaViewModel.swift in Sources */, E1AD105C26D9ABDD003E4A08 /* PillHStackView.swift in Sources */, 625CB56F2678C23300530A6E /* HomeView.swift in Sources */, diff --git a/Swiftfin.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Swiftfin.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index fac5a82a..c3e87965 100644 --- a/Swiftfin.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Swiftfin.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -50,8 +50,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/kaishin/Gifu", "state" : { - "revision" : "51f2eab32903e336f590c013267cfa4d7f8b06c4", - "version" : "3.3.1" + "revision" : "0ffe24744cc3d82ab9edece53670d0352c6d5507", + "version" : "3.3.0" } }, { @@ -66,7 +66,7 @@ { "identity" : "nuke", "kind" : "remoteSourceControl", - "location" : "https://github.com/kean/Nuke", + "location" : "https://github.com/kean/Nuke.git", "state" : { "revision" : "78fa963b8491fc520791d8c2a509f1b8593d8aae", "version" : "10.7.1" @@ -140,8 +140,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/siteline/SwiftUI-Introspect", "state" : { - "revision" : "f2616860a41f9d9932da412a8978fec79c06fe24", - "version" : "0.1.4" + "revision" : "2e09be8af614401bc9f87d40093ec19ce56ccaf2", + "version" : "0.1.3" } }, { diff --git a/Swiftfin/Components/EpisodesRowView/EpisodeRowCard.swift b/Swiftfin/Components/EpisodesRowView/EpisodeRowCard.swift index ef5de88f..f18e2604 100644 --- a/Swiftfin/Components/EpisodesRowView/EpisodeRowCard.swift +++ b/Swiftfin/Components/EpisodesRowView/EpisodeRowCard.swift @@ -23,8 +23,8 @@ struct EpisodeRowCard: View { HStack(alignment: .top) { VStack(alignment: .leading) { - ImageView(src: episode.getBackdropImage(maxWidth: 200), - bh: episode.getBackdropImageBlurHash()) + ImageView(episode.getBackdropImage(maxWidth: 200), + blurHash: episode.getBackdropImageBlurHash()) .mask(Rectangle().frame(width: 200, height: 112).cornerRadius(10)) .frame(width: 200, height: 112) .overlay { diff --git a/Swiftfin/Components/PortraitHStackView.swift b/Swiftfin/Components/PortraitHStackView.swift index cbfb01f5..de120c3c 100644 --- a/Swiftfin/Components/PortraitHStackView.swift +++ b/Swiftfin/Components/PortraitHStackView.swift @@ -43,8 +43,8 @@ struct PortraitImageHStackView: View { selectedAction(item) } label: { VStack(alignment: horizontalAlignment) { - ImageView(src: item.imageURLConstructor(maxWidth: Int(maxWidth)), - bh: item.blurHash, + ImageView(item.imageURLConstructor(maxWidth: Int(maxWidth)), + blurHash: item.blurHash, failureInitials: item.failureInitials) .portraitPoster(width: maxWidth) .shadow(radius: 4, y: 2) diff --git a/Swiftfin/Views/ItemView/Landscape/ItemLandscapeMainView.swift b/Swiftfin/Views/ItemView/Landscape/ItemLandscapeMainView.swift index 8ef58c0e..14001bcc 100644 --- a/Swiftfin/Views/ItemView/Landscape/ItemLandscapeMainView.swift +++ b/Swiftfin/Views/ItemView/Landscape/ItemLandscapeMainView.swift @@ -24,8 +24,8 @@ struct ItemLandscapeMainView: View { // MARK: Sidebar Image VStack { - ImageView(src: viewModel.item.portraitHeaderViewURL(maxWidth: 130), - bh: viewModel.item.getPrimaryImageBlurHash()) + ImageView(viewModel.item.portraitHeaderViewURL(maxWidth: 130), + blurHash: viewModel.item.getPrimaryImageBlurHash()) .frame(width: 130, height: 195) .cornerRadius(10) .accessibilityIgnoresInvertColors() @@ -95,8 +95,8 @@ struct ItemLandscapeMainView: View { ZStack { // MARK: Backdrop - ImageView(src: viewModel.item.getBackdropImage(maxWidth: 200), - bh: viewModel.item.getBackdropImageBlurHash()) + ImageView(viewModel.item.getBackdropImage(maxWidth: 200), + blurHash: viewModel.item.getBackdropImageBlurHash()) .opacity(0.3) .edgesIgnoringSafeArea(.all) .blur(radius: 8) diff --git a/Swiftfin/Views/ItemView/Portrait/ItemPortraitHeaderOverlayView.swift b/Swiftfin/Views/ItemView/Portrait/ItemPortraitHeaderOverlayView.swift index 18eddbf5..d9cba8eb 100644 --- a/Swiftfin/Views/ItemView/Portrait/ItemPortraitHeaderOverlayView.swift +++ b/Swiftfin/Views/ItemView/Portrait/ItemPortraitHeaderOverlayView.swift @@ -24,8 +24,8 @@ struct PortraitHeaderOverlayView: View { // MARK: Portrait Image - ImageView(src: viewModel.item.portraitHeaderViewURL(maxWidth: 130), - bh: viewModel.item.getPrimaryImageBlurHash()) + ImageView(viewModel.item.portraitHeaderViewURL(maxWidth: 130), + blurHash: viewModel.item.getPrimaryImageBlurHash()) .portraitPoster(width: 130) .accessibilityIgnoresInvertColors() diff --git a/Swiftfin/Views/ItemView/Portrait/ItemPortraitMainView.swift b/Swiftfin/Views/ItemView/Portrait/ItemPortraitMainView.swift index fbb4692b..da47995c 100644 --- a/Swiftfin/Views/ItemView/Portrait/ItemPortraitMainView.swift +++ b/Swiftfin/Views/ItemView/Portrait/ItemPortraitMainView.swift @@ -19,8 +19,8 @@ struct ItemPortraitMainView: View { // MARK: portraitHeaderView var portraitHeaderView: some View { - ImageView(src: viewModel.item.getBackdropImage(maxWidth: Int(UIScreen.main.bounds.width)), - bh: viewModel.item.getBackdropImageBlurHash()) + ImageView(viewModel.item.getBackdropImage(maxWidth: Int(UIScreen.main.bounds.width)), + blurHash: viewModel.item.getBackdropImageBlurHash()) .opacity(0.4) .blur(radius: 2.0) .accessibilityIgnoresInvertColors() diff --git a/Swiftfin/Views/LibraryListView.swift b/Swiftfin/Views/LibraryListView.swift index a7ebe468..eedbe6c1 100644 --- a/Swiftfin/Views/LibraryListView.swift +++ b/Swiftfin/Views/LibraryListView.swift @@ -54,7 +54,7 @@ struct LibraryListView: View { title: library.name ?? "")) } label: { ZStack { - ImageView(src: library.getPrimaryImage(maxWidth: 500), bh: library.getPrimaryImageBlurHash()) + ImageView(library.getPrimaryImage(maxWidth: 500), blurHash: library.getPrimaryImageBlurHash()) .opacity(0.4) .accessibilityIgnoresInvertColors() HStack { diff --git a/Swiftfin/Views/VideoPlayer/Overlays/VLCPlayerChapterOverlayView.swift b/Swiftfin/Views/VideoPlayer/Overlays/VLCPlayerChapterOverlayView.swift index f0887f6b..0ffc67e6 100644 --- a/Swiftfin/Views/VideoPlayer/Overlays/VLCPlayerChapterOverlayView.swift +++ b/Swiftfin/Views/VideoPlayer/Overlays/VLCPlayerChapterOverlayView.swift @@ -48,7 +48,7 @@ struct VLCPlayerChapterOverlayView: View { Button { viewModel.playerOverlayDelegate?.didSelectChapter(viewModel.chapters[chapterIndex]) } label: { - ImageView(src: chapterImages[chapterIndex]) + ImageView(chapterImages[chapterIndex]) .cornerRadius(10) .frame(width: 150, height: 100) .overlay {