mirror of
https://github.com/yattee/yattee.git
synced 2024-12-22 13:33:42 +00:00
Adding search queries to favorites
This commit is contained in:
parent
afcefc2e54
commit
ef5ac0ec65
@ -9,6 +9,7 @@ struct FavoriteItem: Codable, Equatable, Identifiable, Defaults.Serializable {
|
||||
case channel(String, String)
|
||||
case playlist(String)
|
||||
case channelPlaylist(String, String)
|
||||
case searchQuery(String, String, String, String)
|
||||
|
||||
var label: String {
|
||||
switch self {
|
||||
@ -24,6 +25,19 @@ struct FavoriteItem: Codable, Equatable, Identifiable, Defaults.Serializable {
|
||||
return name
|
||||
case let .channelPlaylist(_, name):
|
||||
return name
|
||||
case let .searchQuery(text, date, duration, order):
|
||||
var label = "Search: \"\(text)\""
|
||||
if !date.isEmpty, let date = SearchQuery.Date(rawValue: date), date != .any {
|
||||
label += " from \(date == .today ? date.name : " this \(date.name)")"
|
||||
}
|
||||
if !order.isEmpty, let order = SearchQuery.SortOrder(rawValue: order), order != .relevance {
|
||||
label += " by \(order.name)"
|
||||
}
|
||||
if !duration.isEmpty {
|
||||
label += " (\(duration))"
|
||||
}
|
||||
|
||||
return label
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
@ -36,7 +36,10 @@ extension Defaults.Keys {
|
||||
static let sponsorBlockCategories = Key<Set<String>>("sponsorBlockCategories", default: Set(SponsorBlockAPI.categories))
|
||||
|
||||
static let favorites = Key<[FavoriteItem]>("favorites", default: [
|
||||
.init(section: .trending("US", nil))
|
||||
.init(section: .trending("US", nil)),
|
||||
.init(section: .searchQuery("World Discoveries", "", "", "")),
|
||||
.init(section: .searchQuery("Full Body Workout", "", "", "")),
|
||||
.init(section: .searchQuery("Apple Pie Recipes", "", "", ""))
|
||||
])
|
||||
|
||||
static let channelOnThumbnail = Key<Bool>("channelOnThumbnail", default: true)
|
||||
|
@ -105,6 +105,14 @@ struct FavoriteItemView: View {
|
||||
|
||||
case let .playlist(id):
|
||||
return accounts.api.playlist(id)
|
||||
|
||||
case let .searchQuery(text, date, duration, order):
|
||||
return accounts.api.search(.init(
|
||||
query: text,
|
||||
sortBy: SearchQuery.SortOrder(rawValue: order) ?? .uploadDate,
|
||||
date: SearchQuery.Date(rawValue: date),
|
||||
duration: SearchQuery.Duration(rawValue: duration)
|
||||
))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -2,21 +2,19 @@ import Foundation
|
||||
import Siesta
|
||||
|
||||
final class FavoriteResourceObserver: ObservableObject, ResourceObserver {
|
||||
@Published var videos = [Video]()
|
||||
@Published var contentItems = [ContentItem]()
|
||||
|
||||
func resourceChanged(_ resource: Resource, event _: ResourceEvent) {
|
||||
if let videos: [Video] = resource.typedContent() {
|
||||
self.videos = videos
|
||||
contentItems = videos.map { ContentItem(video: $0) }
|
||||
} else if let channel: Channel = resource.typedContent() {
|
||||
videos = channel.videos
|
||||
contentItems = channel.videos.map { ContentItem(video: $0) }
|
||||
} else if let playlist: ChannelPlaylist = resource.typedContent() {
|
||||
videos = playlist.videos
|
||||
contentItems = playlist.videos.map { ContentItem(video: $0) }
|
||||
} else if let playlist: Playlist = resource.typedContent() {
|
||||
videos = playlist.videos
|
||||
contentItems = playlist.videos.map { ContentItem(video: $0) }
|
||||
} else if let items: [ContentItem] = resource.typedContent() {
|
||||
contentItems = items
|
||||
}
|
||||
}
|
||||
|
||||
var contentItems: [ContentItem] {
|
||||
videos.map { ContentItem(video: $0) }
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,8 @@ struct SearchView: View {
|
||||
@State private var recentsDebounce = Debounce()
|
||||
#endif
|
||||
|
||||
@State private var favoriteItem: FavoriteItem?
|
||||
|
||||
@Environment(\.navigationStyle) private var navigationStyle
|
||||
|
||||
@EnvironmentObject<AccountsModel> private var accounts
|
||||
@ -42,10 +44,19 @@ struct SearchView: View {
|
||||
} else {
|
||||
#if os(tvOS)
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
HStack(spacing: 0) {
|
||||
if accounts.app.supportsSearchFilters {
|
||||
filtersHorizontalStack
|
||||
}
|
||||
|
||||
if let favoriteItem = favoriteItem {
|
||||
FavoriteButton(item: favoriteItem)
|
||||
.id(favoriteItem.id)
|
||||
.labelStyle(.iconOnly)
|
||||
.font(.system(size: 25))
|
||||
}
|
||||
}
|
||||
|
||||
HorizontalCells(items: items)
|
||||
}
|
||||
.edgesIgnoringSafeArea(.horizontal)
|
||||
@ -68,6 +79,13 @@ struct SearchView: View {
|
||||
.toolbar {
|
||||
#if !os(tvOS)
|
||||
ToolbarItemGroup(placement: toolbarPlacement) {
|
||||
#if os(macOS)
|
||||
if let favoriteItem = favoriteItem {
|
||||
FavoriteButton(item: favoriteItem)
|
||||
.id(favoriteItem.id)
|
||||
}
|
||||
#endif
|
||||
|
||||
if accounts.app.supportsSearchFilters {
|
||||
Section {
|
||||
#if os(macOS)
|
||||
@ -84,9 +102,20 @@ struct SearchView: View {
|
||||
#endif
|
||||
}
|
||||
.transaction { t in t.animation = .none }
|
||||
}
|
||||
|
||||
#if os(iOS)
|
||||
Spacer()
|
||||
|
||||
if let favoriteItem = favoriteItem {
|
||||
FavoriteButton(item: favoriteItem)
|
||||
.id(favoriteItem.id)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
#endif
|
||||
|
||||
if accounts.app.supportsSearchFilters {
|
||||
filtersMenu
|
||||
}
|
||||
}
|
||||
@ -96,6 +125,7 @@ struct SearchView: View {
|
||||
if query != nil {
|
||||
state.queryText = query!.query
|
||||
state.resetQuery(query!)
|
||||
updateFavoriteItem()
|
||||
}
|
||||
|
||||
if !videos.isEmpty {
|
||||
@ -120,7 +150,10 @@ struct SearchView: View {
|
||||
recentsDebounce.invalidate()
|
||||
|
||||
searchDebounce.debouncing(2) {
|
||||
state.changeQuery { query in query.query = newQuery }
|
||||
state.changeQuery { query in
|
||||
query.query = newQuery
|
||||
updateFavoriteItem()
|
||||
}
|
||||
}
|
||||
|
||||
recentsDebounce.debouncing(10) {
|
||||
@ -131,15 +164,25 @@ struct SearchView: View {
|
||||
.onSubmit(of: .search) {
|
||||
state.changeQuery { query in query.query = state.queryText }
|
||||
recents.addQuery(state.queryText)
|
||||
updateFavoriteItem()
|
||||
}
|
||||
.onChange(of: searchSortOrder) { order in
|
||||
state.changeQuery { query in query.sortBy = order }
|
||||
state.changeQuery { query in
|
||||
query.sortBy = order
|
||||
updateFavoriteItem()
|
||||
}
|
||||
}
|
||||
.onChange(of: searchDate) { date in
|
||||
state.changeQuery { query in query.date = date }
|
||||
state.changeQuery { query in
|
||||
query.date = date
|
||||
updateFavoriteItem()
|
||||
}
|
||||
}
|
||||
.onChange(of: searchDuration) { duration in
|
||||
state.changeQuery { query in query.duration = duration }
|
||||
state.changeQuery { query in
|
||||
query.duration = duration
|
||||
updateFavoriteItem()
|
||||
}
|
||||
}
|
||||
#if !os(tvOS)
|
||||
.navigationTitle("Search")
|
||||
@ -192,6 +235,7 @@ struct SearchView: View {
|
||||
Button(item.title) {
|
||||
state.queryText = item.title
|
||||
state.changeQuery { query in query.query = item.title }
|
||||
updateFavoriteItem()
|
||||
}
|
||||
#if os(iOS)
|
||||
.swipeActions(edge: .trailing) {
|
||||
@ -312,21 +356,21 @@ struct SearchView: View {
|
||||
.foregroundColor(.secondary)
|
||||
searchSortOrderButton
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .trailing)
|
||||
.frame(maxWidth: 300, alignment: .trailing)
|
||||
|
||||
HStack(spacing: 30) {
|
||||
Text("Duration")
|
||||
.foregroundColor(.secondary)
|
||||
searchDurationButton
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.frame(maxWidth: 300)
|
||||
|
||||
HStack(spacing: 30) {
|
||||
Text("Date")
|
||||
.foregroundColor(.secondary)
|
||||
searchDateButton
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.frame(maxWidth: 300, alignment: .leading)
|
||||
}
|
||||
.font(.system(size: 30))
|
||||
}
|
||||
@ -348,8 +392,16 @@ struct SearchView: View {
|
||||
.foregroundColor(filtersActive ? .accentColor : .secondary)
|
||||
.transaction { t in t.animation = .none }
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
private func updateFavoriteItem() {
|
||||
favoriteItem = FavoriteItem(section: .searchQuery(
|
||||
state.query.query,
|
||||
state.query.date?.rawValue ?? "",
|
||||
state.query.duration?.rawValue ?? "",
|
||||
state.query.sortBy.rawValue
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
struct SearchView_Previews: PreviewProvider {
|
||||
|
@ -64,7 +64,7 @@ struct EditFavorites: View {
|
||||
.padding(.trailing, 40)
|
||||
|
||||
HStack {
|
||||
Text("Add more Channels and Playlists to your Favorites using button")
|
||||
Text("Add Channels, Playlists and Searches to Favorites using")
|
||||
Button {} label: {
|
||||
Label("Add to Favorites", systemImage: "heart")
|
||||
.labelStyle(.iconOnly)
|
||||
|
Loading…
Reference in New Issue
Block a user