Minor UI improvements, state saving

This commit is contained in:
Arkadiusz Fal 2021-06-28 17:02:13 +02:00
parent b840974f08
commit f7d0e2131c
10 changed files with 52 additions and 60 deletions

View File

@ -1,22 +1,28 @@
import Defaults
import Siesta
import SwiftUI
struct SearchView: View {
@State private var query = ""
@Default(.searchQuery) var query
@ObservedObject private var store = Store<[Video]>()
var body: some View {
VideosView(videos: store.collection)
.searchable(text: $query)
.onAppear {
queryChanged(new: query)
}
.onChange(of: query) { newQuery in
queryChanged(query, newQuery)
queryChanged(old: query, new: newQuery)
}
}
func queryChanged(_ old: String, _ new: String) {
let oldResource = resource(old)
func queryChanged(old: String? = nil, new: String) {
if old != nil {
let oldResource = resource(old!)
oldResource.removeObservers(ownedBy: store)
}
let resource = resource(new)
resource.addObserver(store)

View File

@ -2,8 +2,6 @@ import Siesta
import SwiftUI
struct TrendingView: View {
@EnvironmentObject private var state: AppState
@State private var category: TrendingCategory = .default
@State private var country: Country = .pl
@State private var selectingCountry = false

View File

@ -2,7 +2,7 @@ import SwiftUI
import URLImage
import URLImageStore
struct VideoListRow: View {
struct VideoListRowView: View {
@Environment(\.isFocused) private var focused: Bool
var video: Video

View File

@ -1,8 +1,6 @@
import SwiftUI
struct VideosCellsView: View {
@EnvironmentObject private var state: AppState
@State private var columns: Int
init(videos: [Video], columns: Int = 3) {

View File

@ -2,8 +2,6 @@ import Defaults
import SwiftUI
struct VideosListView: View {
@EnvironmentObject private var state: AppState
@Default(.tabSelection) var tabSelection
var videos: [Video]
@ -12,7 +10,7 @@ struct VideosListView: View {
Section {
List {
ForEach(videos) { video in
VideoListRow(video: video)
VideoListRowView(video: video)
.contextMenu {
if tabSelection == .channel {
closeChannelButton(name: video.author)
@ -29,15 +27,14 @@ struct VideosListView: View {
func openChannelButton(from video: Video) -> some View {
Button("\(video.author) Channel") {
state.openChannel(from: video)
Defaults[.openChannel] = Channel.from(video: video)
tabSelection = .channel
}
}
func closeChannelButton(name: String) -> some View {
Button("Close \(name) Channel") {
tabSelection = .popular
state.closeChannel()
Defaults.reset(.openChannel)
}
}

View File

@ -1,20 +0,0 @@
import AVFoundation
import Foundation
final class AppState: ObservableObject {
@Published var showingChannel = false
@Published var channelID: String = ""
@Published var channel: String = ""
func openChannel(from video: Video) {
channel = video.author
channelID = video.channelID
showingChannel = true
}
func closeChannel() {
showingChannel = false
channel = ""
channelID = ""
}
}

12
Model/Channel.swift Normal file
View File

@ -0,0 +1,12 @@
import AVFoundation
import Defaults
import Foundation
struct Channel: Codable, Defaults.Serializable {
var id: String
var name: String
static func from(video: Video) -> Channel {
Channel(id: video.channelID, name: video.author)
}
}

View File

@ -51,8 +51,8 @@
377FC7DF267A082200A6BBAF /* VideosListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AAF29926740A01007FC770 /* VideosListView.swift */; };
377FC7E0267A082600A6BBAF /* ChannelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AAF2892673AB89007FC770 /* ChannelView.swift */; };
377FC7E1267A082600A6BBAF /* ChannelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AAF2892673AB89007FC770 /* ChannelView.swift */; };
377FC7E2267A084A00A6BBAF /* VideoListRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37D4B18B26717B3800C925CA /* VideoListRow.swift */; };
377FC7E3267A084A00A6BBAF /* VideoListRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37D4B18B26717B3800C925CA /* VideoListRow.swift */; };
377FC7E2267A084A00A6BBAF /* VideoListRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37D4B18B26717B3800C925CA /* VideoListRowView.swift */; };
377FC7E3267A084A00A6BBAF /* VideoListRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37D4B18B26717B3800C925CA /* VideoListRowView.swift */; };
377FC7E4267A084E00A6BBAF /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AAF27F26737550007FC770 /* SearchView.swift */; };
377FC7E5267A084E00A6BBAF /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AAF27F26737550007FC770 /* SearchView.swift */; };
377FC7E6267A085600A6BBAF /* PlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37D4B1822671681B00C925CA /* PlayerView.swift */; };
@ -77,9 +77,9 @@
37AAF27E26737323007FC770 /* PopularVideosView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AAF27D26737323007FC770 /* PopularVideosView.swift */; };
37AAF28026737550007FC770 /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AAF27F26737550007FC770 /* SearchView.swift */; };
37AAF28A2673AB89007FC770 /* ChannelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AAF2892673AB89007FC770 /* ChannelView.swift */; };
37AAF29026740715007FC770 /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AAF28F26740715007FC770 /* AppState.swift */; };
37AAF29126740715007FC770 /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AAF28F26740715007FC770 /* AppState.swift */; };
37AAF29226740715007FC770 /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AAF28F26740715007FC770 /* AppState.swift */; };
37AAF29026740715007FC770 /* Channel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AAF28F26740715007FC770 /* Channel.swift */; };
37AAF29126740715007FC770 /* Channel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AAF28F26740715007FC770 /* Channel.swift */; };
37AAF29226740715007FC770 /* Channel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AAF28F26740715007FC770 /* Channel.swift */; };
37AAF2942674086B007FC770 /* TabSelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AAF2932674086B007FC770 /* TabSelection.swift */; };
37AAF2952674086B007FC770 /* TabSelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AAF2932674086B007FC770 /* TabSelection.swift */; };
37AAF2962674086B007FC770 /* TabSelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AAF2932674086B007FC770 /* TabSelection.swift */; };
@ -127,7 +127,7 @@
37D4B1812671653A00C925CA /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37D4B0C32671614700C925CA /* ContentView.swift */; };
37D4B1842671684E00C925CA /* PlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37D4B1822671681B00C925CA /* PlayerView.swift */; };
37D4B1862671691600C925CA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 37D4B0C42671614800C925CA /* Assets.xcassets */; };
37D4B18E26717B3800C925CA /* VideoListRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37D4B18B26717B3800C925CA /* VideoListRow.swift */; };
37D4B18E26717B3800C925CA /* VideoListRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37D4B18B26717B3800C925CA /* VideoListRowView.swift */; };
37D4B19126717C6900C925CA /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = 37D4B19026717C6900C925CA /* Alamofire */; };
37D4B19726717E1500C925CA /* Video.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37D4B19626717E1500C925CA /* Video.swift */; };
37D4B19826717E1500C925CA /* Video.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37D4B19626717E1500C925CA /* Video.swift */; };
@ -192,7 +192,7 @@
37AAF27D26737323007FC770 /* PopularVideosView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PopularVideosView.swift; sourceTree = "<group>"; };
37AAF27F26737550007FC770 /* SearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = "<group>"; };
37AAF2892673AB89007FC770 /* ChannelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelView.swift; sourceTree = "<group>"; };
37AAF28F26740715007FC770 /* AppState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppState.swift; sourceTree = "<group>"; };
37AAF28F26740715007FC770 /* Channel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Channel.swift; sourceTree = "<group>"; };
37AAF2932674086B007FC770 /* TabSelection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabSelection.swift; sourceTree = "<group>"; };
37AAF29926740A01007FC770 /* VideosListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideosListView.swift; sourceTree = "<group>"; };
37AAF29F26741C97007FC770 /* SubscriptionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionsView.swift; sourceTree = "<group>"; };
@ -218,7 +218,7 @@
37D4B171267164B000C925CA /* Tests Apple TV.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Tests Apple TV.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
37D4B175267164B000C925CA /* PearvidiousUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PearvidiousUITests.swift; sourceTree = "<group>"; };
37D4B1822671681B00C925CA /* PlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerView.swift; sourceTree = "<group>"; };
37D4B18B26717B3800C925CA /* VideoListRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoListRow.swift; sourceTree = "<group>"; };
37D4B18B26717B3800C925CA /* VideoListRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoListRowView.swift; sourceTree = "<group>"; };
37D4B19626717E1500C925CA /* Video.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Video.swift; sourceTree = "<group>"; };
37D4B1AE26729DEB00C925CA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
37EAD86A267B9C5600D9E01B /* SponsorBlockAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SponsorBlockAPI.swift; sourceTree = "<group>"; };
@ -300,8 +300,8 @@
37C7A9022679058300E721B4 /* Extensions */ = {
isa = PBXGroup;
children = (
376578842685429C00D4EA09 /* CaseIterable+Next.swift */,
379775922689365600DD52A8 /* Array+Next.swift */,
376578842685429C00D4EA09 /* CaseIterable+Next.swift */,
);
path = Extensions;
sourceTree = "<group>";
@ -327,10 +327,10 @@
37D4B0C32671614700C925CA /* ContentView.swift */,
37141672267A8E10006CA35D /* Country.swift */,
372915E52687E3B900F5A35B /* Defaults.swift */,
372915E92687EBA500F5A35B /* ListingLayout.swift */,
37D4B0C22671614700C925CA /* PearvidiousApp.swift */,
37AAF2932674086B007FC770 /* TabSelection.swift */,
37D4B0C42671614800C925CA /* Assets.xcassets */,
372915E92687EBA500F5A35B /* ListingLayout.swift */,
);
path = Shared;
sourceTree = "<group>";
@ -378,7 +378,7 @@
3705B17F267B4DFB00704544 /* TrendingCountrySelectionView.swift */,
3714166E267A8ACC006CA35D /* TrendingView.swift */,
37F4AE752682908700BD60EA /* VideoCellView.swift */,
37D4B18B26717B3800C925CA /* VideoListRow.swift */,
37D4B18B26717B3800C925CA /* VideoListRowView.swift */,
37F4AE7126828F0900BD60EA /* VideosCellsView.swift */,
37AAF29926740A01007FC770 /* VideosListView.swift */,
371231832683E62F0000B307 /* VideosView.swift */,
@ -400,8 +400,8 @@
37D4B1B72672CFE300C925CA /* Model */ = {
isa = PBXGroup;
children = (
37AAF28F26740715007FC770 /* AppState.swift */,
37CEE4BC2677B670005A1EFE /* AudioVideoStream.swift */,
37AAF28F26740715007FC770 /* Channel.swift */,
37977582268922F600DD52A8 /* InvidiousAPI.swift */,
37B767DA2677C3CA0098BAA8 /* PlayerState.swift */,
376578882685471400D4EA09 /* Playlist.swift */,
@ -687,8 +687,8 @@
37CEE4B52677B628005A1EFE /* StreamType.swift in Sources */,
37C7A1DC267CE9D90010EAD6 /* Profile.swift in Sources */,
3714166F267A8ACC006CA35D /* TrendingView.swift in Sources */,
377FC7E3267A084A00A6BBAF /* VideoListRow.swift in Sources */,
37AAF29026740715007FC770 /* AppState.swift in Sources */,
377FC7E3267A084A00A6BBAF /* VideoListRowView.swift in Sources */,
37AAF29026740715007FC770 /* Channel.swift in Sources */,
37AAF2942674086B007FC770 /* TabSelection.swift in Sources */,
377FC7E9267A085D00A6BBAF /* PlayerViewController.swift in Sources */,
377FC7E5267A084E00A6BBAF /* SearchView.swift in Sources */,
@ -727,9 +727,9 @@
37EAD870267B9ED100D9E01B /* Segment.swift in Sources */,
37CEE4B62677B628005A1EFE /* StreamType.swift in Sources */,
37141670267A8ACC006CA35D /* TrendingView.swift in Sources */,
377FC7E2267A084A00A6BBAF /* VideoListRow.swift in Sources */,
377FC7E2267A084A00A6BBAF /* VideoListRowView.swift in Sources */,
3765788A2685471400D4EA09 /* Playlist.swift in Sources */,
37AAF29126740715007FC770 /* AppState.swift in Sources */,
37AAF29126740715007FC770 /* Channel.swift in Sources */,
37AAF2952674086B007FC770 /* TabSelection.swift in Sources */,
372915E72687E3B900F5A35B /* Defaults.swift in Sources */,
376578922685490700D4EA09 /* PlaylistsView.swift in Sources */,
@ -788,13 +788,13 @@
37D4B1802671650A00C925CA /* PearvidiousApp.swift in Sources */,
371231852683E7820000B307 /* VideosView.swift in Sources */,
37141671267A8ACC006CA35D /* TrendingView.swift in Sources */,
37AAF29226740715007FC770 /* AppState.swift in Sources */,
37AAF29226740715007FC770 /* Channel.swift in Sources */,
37EAD86D267B9C5600D9E01B /* SponsorBlockAPI.swift in Sources */,
3765788B2685471400D4EA09 /* Playlist.swift in Sources */,
37C7A1DE267CE9D90010EAD6 /* Profile.swift in Sources */,
3741B5302676213400125C5E /* PlayerViewController.swift in Sources */,
37B767DD2677C3CA0098BAA8 /* PlayerState.swift in Sources */,
37D4B18E26717B3800C925CA /* VideoListRow.swift in Sources */,
37D4B18E26717B3800C925CA /* VideoListRowView.swift in Sources */,
37AAF27E26737323007FC770 /* PopularVideosView.swift in Sources */,
37AAF29A26740A01007FC770 /* VideosListView.swift in Sources */,
37AAF2962674086B007FC770 /* TabSelection.swift in Sources */,

View File

@ -2,7 +2,7 @@ import Defaults
import SwiftUI
struct ContentView: View {
@StateObject private var state = AppState()
@Default(.openChannel) var channel
@StateObject private var profile = Profile()
var body: some View {
@ -16,9 +16,9 @@ struct ContentView: View {
.tabItem { Text("Popular") }
.tag(TabSelection.popular)
if !state.channelID.isEmpty {
ChannelView(id: state.channelID)
.tabItem { Text("\(state.channel) Channel") }
if channel != nil {
ChannelView(id: channel!.id)
.tabItem { Text("\(channel!.name) Channel") }
.tag(TabSelection.channel)
}
@ -34,10 +34,9 @@ struct ContentView: View {
.tabItem { Image(systemName: "magnifyingglass") }
.tag(TabSelection.search)
}
}
.environmentObject(state)
.environmentObject(profile)
}
}
var tabSelection: Binding<TabSelection> {
Binding(

View File

@ -3,4 +3,6 @@ import Defaults
extension Defaults.Keys {
static let layout = Key<ListingLayout>("listingLayout", default: .cells)
static let tabSelection = Key<TabSelection>("tabSelection", default: .subscriptions)
static let searchQuery = Key<String>("searchQuery", default: "")
static let openChannel = Key<Channel?>("openChannel")
}