diff --git a/Backports/Refreshable+Backport.swift b/Backports/Refreshable+Backport.swift new file mode 100644 index 00000000..9f6da1c8 --- /dev/null +++ b/Backports/Refreshable+Backport.swift @@ -0,0 +1,11 @@ +import SwiftUI + +extension Backport where Content: View { + @ViewBuilder func refreshable(action: @Sendable @escaping () async -> Void) -> some View { + if #available(iOS 15.0, macOS 12.0, tvOS 15.0, *) { + content.refreshable(action: action) + } else { + content + } + } +} diff --git a/Shared/Trending/TrendingView.swift b/Shared/Trending/TrendingView.swift index 459a21f0..8314de7e 100644 --- a/Shared/Trending/TrendingView.swift +++ b/Shared/Trending/TrendingView.swift @@ -138,6 +138,12 @@ struct TrendingView: View { refreshControl.endRefreshing() } } + .backport + .refreshable { + resource.load().onFailure { error in + NavigationModel.shared.presentAlert(title: "Could not refresh Trending", message: error.userMessage) + } + } .navigationBarTitleDisplayMode(RefreshControl.navigationBarTitleDisplayMode) #endif #if !os(macOS) diff --git a/Shared/Views/PopularView.swift b/Shared/Views/PopularView.swift index 6fc73ffd..0a5faa18 100644 --- a/Shared/Views/PopularView.swift +++ b/Shared/Views/PopularView.swift @@ -44,6 +44,13 @@ struct PopularView: View { resource?.load().onCompletion { _ in refreshControl.endRefreshing() } + .onFailure { error in + NavigationModel.shared.presentAlert(title: "Could not refresh Trending", message: error.userMessage) + } + } + .backport + .refreshable { + resource?.load() } .navigationBarTitleDisplayMode(RefreshControl.navigationBarTitleDisplayMode) #endif diff --git a/Shared/Views/SubscriptionsView.swift b/Shared/Views/SubscriptionsView.swift index 8ba3ec12..ac80b5f1 100644 --- a/Shared/Views/SubscriptionsView.swift +++ b/Shared/Views/SubscriptionsView.swift @@ -30,6 +30,10 @@ struct SubscriptionsView: View { refreshControl.endRefreshing() } } + .backport + .refreshable { + loadResources(force: true) + } #endif } } @@ -79,6 +83,9 @@ struct SubscriptionsView: View { request.onCompletion { _ in onCompletion() } + .onFailure { error in + NavigationModel.shared.presentAlert(title: "Could not refresh Subscriptions", message: error.userMessage) + } } else { onCompletion() } diff --git a/Vendor/RefreshControl/RefreshControlModifier.swift b/Vendor/RefreshControl/RefreshControlModifier.swift index 355dfedb..c85704e8 100644 --- a/Vendor/RefreshControl/RefreshControlModifier.swift +++ b/Vendor/RefreshControl/RefreshControlModifier.swift @@ -17,7 +17,7 @@ struct RefreshControlModifier: ViewModifier { } func body(content: Content) -> some View { - if #available(iOS 16.0, macOS 13.0, tvOS 16.0, *) { + if #available(iOS 15.0, macOS 12.0, tvOS 15.0, *) { return content } else { return content diff --git a/Yattee.xcodeproj/project.pbxproj b/Yattee.xcodeproj/project.pbxproj index 23b8b247..b0ca9c64 100644 --- a/Yattee.xcodeproj/project.pbxproj +++ b/Yattee.xcodeproj/project.pbxproj @@ -350,6 +350,7 @@ 37579D5E27864F5F00FD0B98 /* Help.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37579D5C27864F5F00FD0B98 /* Help.swift */; }; 37579D5F27864F5F00FD0B98 /* Help.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37579D5C27864F5F00FD0B98 /* Help.swift */; }; 3758638A2721B0A9000CB14E /* ChannelCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3743B86727216D3600261544 /* ChannelCell.swift */; }; + 3759234628C26C7B00C052EC /* Refreshable+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3759234528C26C7B00C052EC /* Refreshable+Backport.swift */; }; 37599F30272B42810087F250 /* FavoriteItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37599F2F272B42810087F250 /* FavoriteItem.swift */; }; 37599F31272B42810087F250 /* FavoriteItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37599F2F272B42810087F250 /* FavoriteItem.swift */; }; 37599F32272B42810087F250 /* FavoriteItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37599F2F272B42810087F250 /* FavoriteItem.swift */; }; @@ -1109,6 +1110,7 @@ 3756C2A52861131100E4B059 /* NetworkState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkState.swift; sourceTree = ""; }; 3756C2A92861151C00E4B059 /* NetworkStateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkStateModel.swift; sourceTree = ""; }; 37579D5C27864F5F00FD0B98 /* Help.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Help.swift; sourceTree = ""; }; + 3759234528C26C7B00C052EC /* Refreshable+Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Refreshable+Backport.swift"; sourceTree = ""; }; 37599F2F272B42810087F250 /* FavoriteItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteItem.swift; sourceTree = ""; }; 37599F33272B44000087F250 /* FavoritesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoritesModel.swift; sourceTree = ""; }; 37599F37272B4D740087F250 /* FavoriteButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteButton.swift; sourceTree = ""; }; @@ -1688,6 +1690,7 @@ 3722AEBD274DA401005EA4D6 /* Backport.swift */, 3722AEBB274DA396005EA4D6 /* Badge+Backport.swift */, 37136CAB286273060095C0CF /* PersistentSystemOverlays+Backport.swift */, + 3759234528C26C7B00C052EC /* Refreshable+Backport.swift */, 37E80F3F287B472300561799 /* ScrollContentBackground+Backport.swift */, 3722AEBF274DAEB8005EA4D6 /* Tint+Backport.swift */, 3727B74927872A920021C15E /* VisualEffectBlur-iOS.swift */, @@ -2837,6 +2840,7 @@ 377ABC40286E4AD5009C986F /* InstancesManifest.swift in Sources */, 37BD07B52698AA4D003EBB87 /* ContentView.swift in Sources */, 37D2E0D428B67EFC00F64D52 /* Delay.swift in Sources */, + 3759234628C26C7B00C052EC /* Refreshable+Backport.swift in Sources */, 37130A5B277657090033018A /* Yattee.xcdatamodeld in Sources */, 37152EEA26EFEB95004FB96D /* LazyView.swift in Sources */, 3761ABFD26F0F8DE00AA496F /* EnvironmentValues.swift in Sources */,