yattee/Model/RecentsModel.swift

170 lines
3.7 KiB
Swift
Raw Normal View History

2021-09-19 11:06:54 +00:00
import Defaults
import Foundation
2021-09-25 12:17:58 +00:00
final class RecentsModel: ObservableObject {
static var shared = RecentsModel()
2021-09-19 11:06:54 +00:00
@Default(.recentlyOpened) var items
@Default(.saveRecents) var saveRecents
2022-05-29 18:26:56 +00:00
2021-09-19 11:06:54 +00:00
func clear() {
items = []
}
func clearQueries() {
items.removeAll { $0.type == .query }
}
func add(_ item: RecentItem) {
if !saveRecents {
clear()
if item.type == .query {
return
}
}
if let index = items.firstIndex(where: { $0.id == item.id }) {
items.remove(at: index)
2021-09-19 11:06:54 +00:00
}
items.append(item)
2021-09-19 11:06:54 +00:00
}
func close(_ item: RecentItem) {
if let index = items.firstIndex(where: { $0.id == item.id }) {
items.remove(at: index)
}
}
func addQuery(_ query: String) {
if !query.isEmpty {
NavigationModel.shared.tabSelection = .search
add(.init(from: query))
}
2021-09-25 12:17:58 +00:00
}
2021-09-19 11:06:54 +00:00
var presentedChannel: Channel? {
if let recent = items.last(where: { $0.type == .channel }) {
return recent.channel
}
return nil
}
2021-10-22 23:04:03 +00:00
var presentedPlaylist: ChannelPlaylist? {
if let recent = items.last(where: { $0.type == .playlist }) {
return recent.playlist
}
return nil
}
static func symbolSystemImage(_ name: String) -> String {
let firstLetter = name.first?.lowercased()
let regex = #"^[a-z0-9]$"#
let symbolName = firstLetter?.range(of: regex, options: .regularExpression) != nil ? firstLetter! : "questionmark"
return "\(symbolName).circle"
}
2021-09-19 11:06:54 +00:00
}
struct RecentItem: Defaults.Serializable, Identifiable {
static var bridge = RecentItemBridge()
enum ItemType: String {
2021-10-22 23:04:03 +00:00
case channel, playlist, query
2021-09-19 11:06:54 +00:00
}
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)
}
2021-10-22 23:04:03 +00:00
var playlist: ChannelPlaylist? {
guard type == .playlist else {
return nil
}
return ChannelPlaylist(id: id, title: title)
}
2021-09-19 11:06:54 +00:00
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
}
2021-09-19 12:42:47 +00:00
init(from query: String) {
type = .query
id = query
title = query
}
2021-10-22 23:04:03 +00:00
init(from playlist: ChannelPlaylist) {
type = .playlist
id = playlist.id
title = playlist.title
}
2021-09-19 11:06:54 +00:00
}
struct RecentItemBridge: Defaults.Bridge {
typealias Value = RecentItem
typealias Serializable = [String: String]
func serialize(_ value: Value?) -> Serializable? {
2022-09-28 14:27:01 +00:00
guard let value else {
2021-09-19 11:06:54 +00:00
return nil
}
return [
"type": value.type.rawValue,
"identifier": value.id,
"title": value.title
]
}
2021-09-25 08:18:22 +00:00
func deserialize(_ object: Serializable?) -> Value? {
2021-09-19 11:06:54 +00:00
guard
2022-09-28 14:27:01 +00:00
let object,
2021-09-19 11:06:54 +00:00
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
)
}
}