mirror of
https://github.com/yattee/yattee.git
synced 2024-12-22 13:33:42 +00:00
Fix favorites view redrawing
This commit is contained in:
parent
ef9143263f
commit
9a4e404389
@ -273,6 +273,9 @@
|
|||||||
37B17DA0268A1F89006AEE9B /* VideoContextMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B17D9F268A1F25006AEE9B /* VideoContextMenuView.swift */; };
|
37B17DA0268A1F89006AEE9B /* VideoContextMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B17D9F268A1F25006AEE9B /* VideoContextMenuView.swift */; };
|
||||||
37B17DA1268A1F89006AEE9B /* 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 */; };
|
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 */; };
|
37B767DB2677C3CA0098BAA8 /* PlayerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B767DA2677C3CA0098BAA8 /* PlayerModel.swift */; };
|
||||||
37B767DC2677C3CA0098BAA8 /* 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 */; };
|
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 = "<group>"; };
|
37AAF29F26741C97007FC770 /* SubscriptionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionsView.swift; sourceTree = "<group>"; };
|
||||||
37B044B626F7AB9000E1419D /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
|
37B044B626F7AB9000E1419D /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
|
||||||
37B17D9F268A1F25006AEE9B /* VideoContextMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoContextMenuView.swift; sourceTree = "<group>"; };
|
37B17D9F268A1F25006AEE9B /* VideoContextMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoContextMenuView.swift; sourceTree = "<group>"; };
|
||||||
|
37B263192735EAAB00FE0D40 /* FavoriteResourceObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteResourceObserver.swift; sourceTree = "<group>"; };
|
||||||
37B767DA2677C3CA0098BAA8 /* PlayerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerModel.swift; sourceTree = "<group>"; };
|
37B767DA2677C3CA0098BAA8 /* PlayerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerModel.swift; sourceTree = "<group>"; };
|
||||||
37B81AF826D2C9A700675966 /* VideoPlayerSizeModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerSizeModifier.swift; sourceTree = "<group>"; };
|
37B81AF826D2C9A700675966 /* VideoPlayerSizeModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerSizeModifier.swift; sourceTree = "<group>"; };
|
||||||
37B81AFB26D2C9C900675966 /* VideoDetailsPaddingModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoDetailsPaddingModifier.swift; sourceTree = "<group>"; };
|
37B81AFB26D2C9C900675966 /* VideoDetailsPaddingModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoDetailsPaddingModifier.swift; sourceTree = "<group>"; };
|
||||||
@ -957,9 +961,10 @@
|
|||||||
3788AC2126F683AB00F6BAA9 /* Favorites */ = {
|
3788AC2126F683AB00F6BAA9 /* Favorites */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
37BF661E27308884008CCFB0 /* DropFavoriteOutside.swift */,
|
|
||||||
37BF661B27308859008CCFB0 /* DropFavorite.swift */,
|
37BF661B27308859008CCFB0 /* DropFavorite.swift */,
|
||||||
|
37BF661E27308884008CCFB0 /* DropFavoriteOutside.swift */,
|
||||||
3788AC2626F6840700F6BAA9 /* FavoriteItemView.swift */,
|
3788AC2626F6840700F6BAA9 /* FavoriteItemView.swift */,
|
||||||
|
37B263192735EAAB00FE0D40 /* FavoriteResourceObserver.swift */,
|
||||||
37A9965D26D6F9B9006E3224 /* FavoritesView.swift */,
|
37A9965D26D6F9B9006E3224 /* FavoritesView.swift */,
|
||||||
);
|
);
|
||||||
path = Favorites;
|
path = Favorites;
|
||||||
@ -1756,6 +1761,7 @@
|
|||||||
37C3A24927235FAA0087A57A /* ChannelPlaylistCell.swift in Sources */,
|
37C3A24927235FAA0087A57A /* ChannelPlaylistCell.swift in Sources */,
|
||||||
373CFACB26966264003CB2C6 /* SearchQuery.swift in Sources */,
|
373CFACB26966264003CB2C6 /* SearchQuery.swift in Sources */,
|
||||||
37141673267A8E10006CA35D /* Country.swift in Sources */,
|
37141673267A8E10006CA35D /* Country.swift in Sources */,
|
||||||
|
37B2631A2735EAAB00FE0D40 /* FavoriteResourceObserver.swift in Sources */,
|
||||||
3748186E26A769D60084E870 /* DetailBadge.swift in Sources */,
|
3748186E26A769D60084E870 /* DetailBadge.swift in Sources */,
|
||||||
376BE50B27349108009AD608 /* BrowsingSettings.swift in Sources */,
|
376BE50B27349108009AD608 /* BrowsingSettings.swift in Sources */,
|
||||||
37AAF2A026741C97007FC770 /* SubscriptionsView.swift in Sources */,
|
37AAF2A026741C97007FC770 /* SubscriptionsView.swift in Sources */,
|
||||||
@ -1887,6 +1893,7 @@
|
|||||||
37732FF12703A26300F04329 /* AccountValidationStatus.swift in Sources */,
|
37732FF12703A26300F04329 /* AccountValidationStatus.swift in Sources */,
|
||||||
37BA794C26DC30EC002A0235 /* AppSidebarPlaylists.swift in Sources */,
|
37BA794C26DC30EC002A0235 /* AppSidebarPlaylists.swift in Sources */,
|
||||||
37CC3F46270CE30600608308 /* PlayerQueueItem.swift in Sources */,
|
37CC3F46270CE30600608308 /* PlayerQueueItem.swift in Sources */,
|
||||||
|
37B2631B2735EAAB00FE0D40 /* FavoriteResourceObserver.swift in Sources */,
|
||||||
3700155C271B0D4D0049C794 /* PipedAPI.swift in Sources */,
|
3700155C271B0D4D0049C794 /* PipedAPI.swift in Sources */,
|
||||||
376BE50C27349108009AD608 /* BrowsingSettings.swift in Sources */,
|
376BE50C27349108009AD608 /* BrowsingSettings.swift in Sources */,
|
||||||
37D4B19826717E1500C925CA /* Video.swift in Sources */,
|
37D4B19826717E1500C925CA /* Video.swift in Sources */,
|
||||||
@ -2016,6 +2023,7 @@
|
|||||||
37484C3326FCB8F900287258 /* AccountValidator.swift in Sources */,
|
37484C3326FCB8F900287258 /* AccountValidator.swift in Sources */,
|
||||||
37CEE4C32677B697005A1EFE /* Stream.swift in Sources */,
|
37CEE4C32677B697005A1EFE /* Stream.swift in Sources */,
|
||||||
37F64FE626FE70A60081B69E /* RedrawOnModifier.swift in Sources */,
|
37F64FE626FE70A60081B69E /* RedrawOnModifier.swift in Sources */,
|
||||||
|
37B2631C2735EAAB00FE0D40 /* FavoriteResourceObserver.swift in Sources */,
|
||||||
37484C2B26FC83FF00287258 /* AccountForm.swift in Sources */,
|
37484C2B26FC83FF00287258 /* AccountForm.swift in Sources */,
|
||||||
37FB2860272225E800A57617 /* ContentItemView.swift in Sources */,
|
37FB2860272225E800A57617 /* ContentItemView.swift in Sources */,
|
||||||
374C053727242D9F009BDDBE /* ServicesSettings.swift in Sources */,
|
374C053727242D9F009BDDBE /* ServicesSettings.swift in Sources */,
|
||||||
|
@ -3,42 +3,24 @@ import Siesta
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import UniformTypeIdentifiers
|
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 {
|
struct FavoriteItemView: View {
|
||||||
let item: FavoriteItem
|
let item: FavoriteItem
|
||||||
let resource: Resource?
|
|
||||||
|
|
||||||
@StateObject private var store = FavoriteResourceObserver()
|
@StateObject private var store = FavoriteResourceObserver()
|
||||||
|
|
||||||
@Binding private var favorites: [FavoriteItem]
|
@Default(.favorites) private var favorites
|
||||||
@Binding private var dragging: FavoriteItem?
|
@Binding private var dragging: FavoriteItem?
|
||||||
|
|
||||||
@EnvironmentObject<PlaylistsModel> private var playlistsModel
|
@EnvironmentObject<AccountsModel> private var accounts
|
||||||
|
@EnvironmentObject<PlaylistsModel> private var playlists
|
||||||
|
|
||||||
|
private var favoritesModel = FavoritesModel.shared
|
||||||
|
|
||||||
init(
|
init(
|
||||||
item: FavoriteItem,
|
item: FavoriteItem,
|
||||||
resource: Resource?,
|
|
||||||
favorites: Binding<[FavoriteItem]>,
|
|
||||||
dragging: Binding<FavoriteItem?>
|
dragging: Binding<FavoriteItem?>
|
||||||
) {
|
) {
|
||||||
self.item = item
|
self.item = item
|
||||||
self.resource = resource
|
|
||||||
_favorites = favorites
|
|
||||||
_dragging = dragging
|
_dragging = dragging
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,10 +29,9 @@ struct FavoriteItemView: View {
|
|||||||
Text(label)
|
Text(label)
|
||||||
.font(.title3.bold())
|
.font(.title3.bold())
|
||||||
.foregroundColor(.secondary)
|
.foregroundColor(.secondary)
|
||||||
|
|
||||||
.contextMenu {
|
.contextMenu {
|
||||||
Button {
|
Button {
|
||||||
FavoritesModel.shared.remove(item)
|
favoritesModel.remove(item)
|
||||||
} label: {
|
} label: {
|
||||||
Label("Remove from Favorites", systemImage: "trash")
|
Label("Remove from Favorites", systemImage: "trash")
|
||||||
}
|
}
|
||||||
@ -62,7 +43,7 @@ struct FavoriteItemView: View {
|
|||||||
.padding(.leading, 15)
|
.padding(.leading, 15)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HorizontalCells(items: store.videos.map { ContentItem(video: $0) })
|
HorizontalCells(items: store.contentItems)
|
||||||
}
|
}
|
||||||
|
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
@ -83,9 +64,40 @@ struct FavoriteItemView: View {
|
|||||||
#endif
|
#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 {
|
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
|
return item.section.label
|
||||||
|
22
Shared/Favorites/FavoriteResourceObserver.swift
Normal file
22
Shared/Favorites/FavoriteResourceObserver.swift
Normal file
@ -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) }
|
||||||
|
}
|
||||||
|
}
|
@ -10,20 +10,12 @@ struct FavoritesView: View {
|
|||||||
@State private var dragging: FavoriteItem?
|
@State private var dragging: FavoriteItem?
|
||||||
@State private var presentingEditFavorites = false
|
@State private var presentingEditFavorites = false
|
||||||
|
|
||||||
@Default(.favorites) private var favorites
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
PlayerControlsView {
|
PlayerControlsView {
|
||||||
ScrollView(.vertical, showsIndicators: false) {
|
ScrollView(.vertical, showsIndicators: false) {
|
||||||
if !accounts.current.isNil {
|
if !accounts.current.isNil {
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
ForEach(Defaults[.favorites]) { item in
|
||||||
ForEach(favorites) { item in
|
FavoriteItemView(item: item, dragging: $dragging)
|
||||||
VStack {
|
|
||||||
if let resource = resource(item) {
|
|
||||||
FavoriteItemView(item: item, resource: resource, favorites: $favorites, dragging: $dragging)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
@ -35,6 +27,7 @@ struct FavoritesView: View {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.redrawOn(change: presentingEditFavorites)
|
||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
.sheet(isPresented: $presentingEditFavorites) {
|
.sheet(isPresented: $presentingEditFavorites) {
|
||||||
EditFavorites()
|
EditFavorites()
|
||||||
@ -50,37 +43,6 @@ struct FavoritesView: View {
|
|||||||
#endif
|
#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 {
|
struct Favorites_Previews: PreviewProvider {
|
||||||
|
@ -267,7 +267,7 @@ struct VideoCell: View {
|
|||||||
}
|
}
|
||||||
.retryOnAppear(false)
|
.retryOnAppear(false)
|
||||||
.onFailure { _ in
|
.onFailure { _ in
|
||||||
thumbnails.insertUnloadable(url)
|
thumbnails.insertUnloadable(url)
|
||||||
}
|
}
|
||||||
.indicator(.activity)
|
.indicator(.activity)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user