Recently opened for sidebar navigation

This commit is contained in:
Arkadiusz Fal
2021-09-19 13:06:54 +02:00
parent 8571822f23
commit ee1cb924c9
16 changed files with 291 additions and 291 deletions

View File

@@ -3,12 +3,11 @@ import SwiftUI
final class NavigationState: ObservableObject {
enum TabSelection: Hashable {
case watchNow, subscriptions, popular, trending, playlists, channel(String), playlist(String), search
case watchNow, subscriptions, popular, trending, playlists, channel(String), playlist(String), recentlyOpened(String), search
}
@Published var tabSelection: TabSelection = .watchNow
@Published var showingVideoDetails = false
@Published var showingVideo = false
@Published var video: Video?
@@ -20,56 +19,14 @@ final class NavigationState: ObservableObject {
@Published var presentingUnsubscribeAlert = false
@Published var channelToUnsubscribe: Channel!
@Published var openChannels = Set<Channel>()
@Published var isChannelOpen = false
@Published var sidebarSectionChanged = false
func openChannel(_ channel: Channel) {
openChannels.insert(channel)
isChannelOpen = true
}
func closeChannel(_ channel: Channel) {
guard openChannels.remove(channel) != nil else {
return
}
isChannelOpen = !openChannels.isEmpty
if tabSelection == .channel(channel.id) {
tabSelection = .subscriptions
}
}
func showOpenChannel(_ id: Channel.ID) -> Bool {
if case .channel = tabSelection {
return false
} else {
return !openChannels.contains { $0.id == id }
}
}
func openVideoDetails(_ video: Video) {
self.video = video
showingVideoDetails = true
}
func closeVideoDetails() {
showingVideoDetails = false
video = nil
}
func playVideo(_ video: Video) {
self.video = video
showingVideo = true
}
func showVideoDetailsIfNeeded() {
showingVideoDetails = returnToDetails
returnToDetails = false
}
var tabSelectionOptionalBinding: Binding<TabSelection?> {
Binding<TabSelection?>(
get: {

116
Model/Recents.swift Normal file
View File

@@ -0,0 +1,116 @@
import Defaults
import Foundation
final class Recents: ObservableObject {
@Default(.recentlyOpened) var items
var isEmpty: Bool {
items.isEmpty
}
func clear() {
items = []
}
func clearQueries() {
items.removeAll { $0.type == .query }
}
func open(_ item: RecentItem) {
if !items.contains(where: { $0.id == item.id }) {
items.append(item)
}
}
func close(_ item: RecentItem) {
if let index = items.firstIndex(where: { $0.id == item.id }) {
items.remove(at: index)
}
}
var presentedChannel: Channel? {
if let recent = items.last(where: { $0.type == .channel }) {
return recent.channel
}
return nil
}
}
struct RecentItem: Defaults.Serializable, Identifiable {
static var bridge = RecentItemBridge()
enum ItemType: String {
case channel, query
}
var type: ItemType
var id: String
var title: String
var tag: String {
"recent\(type.rawValue.capitalized)\(id)"
}
var query: SearchQuery? {
guard type == .query else {
return nil
}
return SearchQuery(query: title)
}
var channel: Channel? {
guard type == .channel else {
return nil
}
return Channel(id: id, name: title)
}
init(type: ItemType, identifier: String, title: String) {
self.type = type
id = identifier
self.title = title
}
init(from channel: Channel) {
type = .channel
id = channel.id
title = channel.name
}
}
struct RecentItemBridge: Defaults.Bridge {
typealias Value = RecentItem
typealias Serializable = [String: String]
func serialize(_ value: Value?) -> Serializable? {
guard let value = value else {
return nil
}
return [
"type": value.type.rawValue,
"identifier": value.id,
"title": value.title
]
}
func deserialize(_ object: Serializable?) -> RecentItem? {
guard
let object = object,
let type = object["type"],
let identifier = object["identifier"],
let title = object["title"]
else {
return nil
}
return RecentItem(
type: .init(rawValue: type)!,
identifier: identifier,
title: title
)
}
}

View File

@@ -8,14 +8,11 @@ final class SearchState: ObservableObject {
@Published var querySuggestions = Store<[String]>()
@Default(.searchQuery) private var queryText
private var previousResource: Resource?
private var resource: Resource!
init() {
let newQuery = query
newQuery.query = queryText
query = newQuery
resource = InvidiousAPI.shared.search(newQuery)
@@ -53,7 +50,23 @@ final class SearchState: ObservableObject {
previousResource?.removeObservers(ownedBy: store)
previousResource = newResource
queryText = query.query
resource = newResource
resource.addObserver(store)
loadResourceIfNeededAndReplaceStore()
}
func resetQuery(_ query: SearchQuery) {
self.query = query
let newResource = InvidiousAPI.shared.search(query)
guard newResource != previousResource else {
return
}
store.replace([])
previousResource?.removeObservers(ownedBy: store)
previousResource = newResource
resource = newResource
resource.addObserver(store)