From 9a4e404389ef708780b92a0491ccb6838a1d573f Mon Sep 17 00:00:00 2001 From: Arkadiusz Fal Date: Fri, 5 Nov 2021 23:44:52 +0100 Subject: [PATCH] Fix favorites view redrawing --- Pearvidious.xcodeproj/project.pbxproj | 10 ++- Shared/Favorites/FavoriteItemView.swift | 68 +++++++++++-------- .../Favorites/FavoriteResourceObserver.swift | 22 ++++++ Shared/Favorites/FavoritesView.swift | 44 +----------- Shared/Videos/VideoCell.swift | 2 +- 5 files changed, 75 insertions(+), 71 deletions(-) create mode 100644 Shared/Favorites/FavoriteResourceObserver.swift diff --git a/Pearvidious.xcodeproj/project.pbxproj b/Pearvidious.xcodeproj/project.pbxproj index c9d15a59..18af5513 100644 --- a/Pearvidious.xcodeproj/project.pbxproj +++ b/Pearvidious.xcodeproj/project.pbxproj @@ -273,6 +273,9 @@ 37B17DA0268A1F89006AEE9B /* VideoContextMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B17D9F268A1F25006AEE9B /* VideoContextMenuView.swift */; }; 37B17DA1268A1F89006AEE9B /* VideoContextMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B17D9F268A1F25006AEE9B /* VideoContextMenuView.swift */; }; 37B17DA2268A1F8A006AEE9B /* VideoContextMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B17D9F268A1F25006AEE9B /* VideoContextMenuView.swift */; }; + 37B2631A2735EAAB00FE0D40 /* FavoriteResourceObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B263192735EAAB00FE0D40 /* FavoriteResourceObserver.swift */; }; + 37B2631B2735EAAB00FE0D40 /* FavoriteResourceObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B263192735EAAB00FE0D40 /* FavoriteResourceObserver.swift */; }; + 37B2631C2735EAAB00FE0D40 /* FavoriteResourceObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B263192735EAAB00FE0D40 /* FavoriteResourceObserver.swift */; }; 37B767DB2677C3CA0098BAA8 /* PlayerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B767DA2677C3CA0098BAA8 /* PlayerModel.swift */; }; 37B767DC2677C3CA0098BAA8 /* PlayerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B767DA2677C3CA0098BAA8 /* PlayerModel.swift */; }; 37B767DD2677C3CA0098BAA8 /* PlayerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B767DA2677C3CA0098BAA8 /* PlayerModel.swift */; }; @@ -607,6 +610,7 @@ 37AAF29F26741C97007FC770 /* SubscriptionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionsView.swift; sourceTree = ""; }; 37B044B626F7AB9000E1419D /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; 37B17D9F268A1F25006AEE9B /* VideoContextMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoContextMenuView.swift; sourceTree = ""; }; + 37B263192735EAAB00FE0D40 /* FavoriteResourceObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteResourceObserver.swift; sourceTree = ""; }; 37B767DA2677C3CA0098BAA8 /* PlayerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerModel.swift; sourceTree = ""; }; 37B81AF826D2C9A700675966 /* VideoPlayerSizeModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerSizeModifier.swift; sourceTree = ""; }; 37B81AFB26D2C9C900675966 /* VideoDetailsPaddingModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoDetailsPaddingModifier.swift; sourceTree = ""; }; @@ -957,9 +961,10 @@ 3788AC2126F683AB00F6BAA9 /* Favorites */ = { isa = PBXGroup; children = ( - 37BF661E27308884008CCFB0 /* DropFavoriteOutside.swift */, 37BF661B27308859008CCFB0 /* DropFavorite.swift */, + 37BF661E27308884008CCFB0 /* DropFavoriteOutside.swift */, 3788AC2626F6840700F6BAA9 /* FavoriteItemView.swift */, + 37B263192735EAAB00FE0D40 /* FavoriteResourceObserver.swift */, 37A9965D26D6F9B9006E3224 /* FavoritesView.swift */, ); path = Favorites; @@ -1756,6 +1761,7 @@ 37C3A24927235FAA0087A57A /* ChannelPlaylistCell.swift in Sources */, 373CFACB26966264003CB2C6 /* SearchQuery.swift in Sources */, 37141673267A8E10006CA35D /* Country.swift in Sources */, + 37B2631A2735EAAB00FE0D40 /* FavoriteResourceObserver.swift in Sources */, 3748186E26A769D60084E870 /* DetailBadge.swift in Sources */, 376BE50B27349108009AD608 /* BrowsingSettings.swift in Sources */, 37AAF2A026741C97007FC770 /* SubscriptionsView.swift in Sources */, @@ -1887,6 +1893,7 @@ 37732FF12703A26300F04329 /* AccountValidationStatus.swift in Sources */, 37BA794C26DC30EC002A0235 /* AppSidebarPlaylists.swift in Sources */, 37CC3F46270CE30600608308 /* PlayerQueueItem.swift in Sources */, + 37B2631B2735EAAB00FE0D40 /* FavoriteResourceObserver.swift in Sources */, 3700155C271B0D4D0049C794 /* PipedAPI.swift in Sources */, 376BE50C27349108009AD608 /* BrowsingSettings.swift in Sources */, 37D4B19826717E1500C925CA /* Video.swift in Sources */, @@ -2016,6 +2023,7 @@ 37484C3326FCB8F900287258 /* AccountValidator.swift in Sources */, 37CEE4C32677B697005A1EFE /* Stream.swift in Sources */, 37F64FE626FE70A60081B69E /* RedrawOnModifier.swift in Sources */, + 37B2631C2735EAAB00FE0D40 /* FavoriteResourceObserver.swift in Sources */, 37484C2B26FC83FF00287258 /* AccountForm.swift in Sources */, 37FB2860272225E800A57617 /* ContentItemView.swift in Sources */, 374C053727242D9F009BDDBE /* ServicesSettings.swift in Sources */, diff --git a/Shared/Favorites/FavoriteItemView.swift b/Shared/Favorites/FavoriteItemView.swift index 6f883972..78c8475b 100644 --- a/Shared/Favorites/FavoriteItemView.swift +++ b/Shared/Favorites/FavoriteItemView.swift @@ -3,42 +3,24 @@ import Siesta import SwiftUI import UniformTypeIdentifiers -final class FavoriteResourceObserver: ObservableObject, ResourceObserver { - @Published var videos = [Video]() - - func resourceChanged(_ resource: Resource, event _: ResourceEvent) { - if let videos: [Video] = resource.typedContent() { - self.videos = videos - } else if let channel: Channel = resource.typedContent() { - videos = channel.videos - } else if let playlist: ChannelPlaylist = resource.typedContent() { - videos = playlist.videos - } else if let playlist: Playlist = resource.typedContent() { - videos = playlist.videos - } - } -} - struct FavoriteItemView: View { let item: FavoriteItem - let resource: Resource? @StateObject private var store = FavoriteResourceObserver() - @Binding private var favorites: [FavoriteItem] + @Default(.favorites) private var favorites @Binding private var dragging: FavoriteItem? - @EnvironmentObject private var playlistsModel + @EnvironmentObject private var accounts + @EnvironmentObject private var playlists + + private var favoritesModel = FavoritesModel.shared init( item: FavoriteItem, - resource: Resource?, - favorites: Binding<[FavoriteItem]>, dragging: Binding ) { self.item = item - self.resource = resource - _favorites = favorites _dragging = dragging } @@ -47,10 +29,9 @@ struct FavoriteItemView: View { Text(label) .font(.title3.bold()) .foregroundColor(.secondary) - .contextMenu { Button { - FavoritesModel.shared.remove(item) + favoritesModel.remove(item) } label: { Label("Remove from Favorites", systemImage: "trash") } @@ -62,7 +43,7 @@ struct FavoriteItemView: View { .padding(.leading, 15) #endif - HorizontalCells(items: store.videos.map { ContentItem(video: $0) }) + HorizontalCells(items: store.contentItems) } .contentShape(Rectangle()) @@ -83,9 +64,40 @@ struct FavoriteItemView: View { #endif } - var label: String { + private var resource: Resource? { + switch item.section { + case .subscriptions: + if accounts.app.supportsSubscriptions { + return accounts.api.feed + } + + case .popular: + if accounts.app.supportsPopular { + return accounts.api.popular + } + + case let .trending(country, category): + let trendingCountry = Country(rawValue: country)! + let trendingCategory = category.isNil ? nil : TrendingCategory(rawValue: category!)! + + return accounts.api.trending(country: trendingCountry, category: trendingCategory) + + case let .channel(id, _): + return accounts.api.channelVideos(id) + + case let .channelPlaylist(id, _): + return accounts.api.channelPlaylist(id) + + case let .playlist(id): + return accounts.api.playlist(id) + } + + return nil + } + + private var label: String { if case let .playlist(id) = item.section { - return playlistsModel.find(id: id)?.title ?? "Playlist" + return playlists.find(id: id)?.title ?? "Playlist" } return item.section.label diff --git a/Shared/Favorites/FavoriteResourceObserver.swift b/Shared/Favorites/FavoriteResourceObserver.swift new file mode 100644 index 00000000..6b93c008 --- /dev/null +++ b/Shared/Favorites/FavoriteResourceObserver.swift @@ -0,0 +1,22 @@ +import Foundation +import Siesta + +final class FavoriteResourceObserver: ObservableObject, ResourceObserver { + @Published var videos = [Video]() + + func resourceChanged(_ resource: Resource, event _: ResourceEvent) { + if let videos: [Video] = resource.typedContent() { + self.videos = videos + } else if let channel: Channel = resource.typedContent() { + videos = channel.videos + } else if let playlist: ChannelPlaylist = resource.typedContent() { + videos = playlist.videos + } else if let playlist: Playlist = resource.typedContent() { + videos = playlist.videos + } + } + + var contentItems: [ContentItem] { + videos.map { ContentItem(video: $0) } + } +} diff --git a/Shared/Favorites/FavoritesView.swift b/Shared/Favorites/FavoritesView.swift index 9aca3279..261e5ec3 100644 --- a/Shared/Favorites/FavoritesView.swift +++ b/Shared/Favorites/FavoritesView.swift @@ -10,20 +10,12 @@ struct FavoritesView: View { @State private var dragging: FavoriteItem? @State private var presentingEditFavorites = false - @Default(.favorites) private var favorites - var body: some View { PlayerControlsView { ScrollView(.vertical, showsIndicators: false) { if !accounts.current.isNil { - VStack(alignment: .leading, spacing: 0) { - ForEach(favorites) { item in - VStack { - if let resource = resource(item) { - FavoriteItemView(item: item, resource: resource, favorites: $favorites, dragging: $dragging) - } - } - } + ForEach(Defaults[.favorites]) { item in + FavoriteItemView(item: item, dragging: $dragging) } #if os(tvOS) @@ -35,6 +27,7 @@ struct FavoritesView: View { #endif } } + .redrawOn(change: presentingEditFavorites) #if os(tvOS) .sheet(isPresented: $presentingEditFavorites) { EditFavorites() @@ -50,37 +43,6 @@ struct FavoritesView: View { #endif } } - - func resource(_ item: FavoriteItem) -> Resource? { - switch item.section { - case .subscriptions: - if accounts.app.supportsSubscriptions { - return accounts.api.feed - } - - case .popular: - if accounts.app.supportsPopular { - return accounts.api.popular - } - - case let .trending(country, category): - let trendingCountry = Country(rawValue: country)! - let trendingCategory = category.isNil ? nil : TrendingCategory(rawValue: category!)! - - return accounts.api.trending(country: trendingCountry, category: trendingCategory) - - case let .channel(id, _): - return accounts.api.channelVideos(id) - - case let .channelPlaylist(id, _): - return accounts.api.channelPlaylist(id) - - case let .playlist(id): - return accounts.api.playlist(id) - } - - return nil - } } struct Favorites_Previews: PreviewProvider { diff --git a/Shared/Videos/VideoCell.swift b/Shared/Videos/VideoCell.swift index 75ae0e06..5d2d05eb 100644 --- a/Shared/Videos/VideoCell.swift +++ b/Shared/Videos/VideoCell.swift @@ -267,7 +267,7 @@ struct VideoCell: View { } .retryOnAppear(false) .onFailure { _ in - thumbnails.insertUnloadable(url) + thumbnails.insertUnloadable(url) } .indicator(.activity)