mirror of
https://github.com/yattee/yattee.git
synced 2024-12-22 05:23:41 +00:00
Videos cache model
This commit is contained in:
parent
0c960c2461
commit
64146b26c2
@ -41,10 +41,8 @@ final class AccountsModel: ObservableObject {
|
|||||||
return piped
|
return piped
|
||||||
case .invidious:
|
case .invidious:
|
||||||
return invidious
|
return invidious
|
||||||
case .peerTube:
|
|
||||||
return peerTube
|
|
||||||
default:
|
default:
|
||||||
return nil
|
return peerTube
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import SwiftyJSON
|
import Logging
|
||||||
|
|
||||||
struct CacheModel {
|
struct CacheModel {
|
||||||
static var shared = CacheModel()
|
static var shared = CacheModel()
|
||||||
static let bookmarksGroup = "group.stream.yattee.app.bookmarks"
|
|
||||||
|
|
||||||
|
let logger = Logger(label: "stream.yattee.cache")
|
||||||
|
|
||||||
|
static let bookmarksGroup = "group.stream.yattee.app.bookmarks"
|
||||||
let bookmarksDefaults = UserDefaults(suiteName: Self.bookmarksGroup)
|
let bookmarksDefaults = UserDefaults(suiteName: Self.bookmarksGroup)
|
||||||
|
|
||||||
func removeAll() {
|
func removeAll() {
|
37
Model/Cache/VideosCacheModel.swift
Normal file
37
Model/Cache/VideosCacheModel.swift
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import Cache
|
||||||
|
import Foundation
|
||||||
|
import Logging
|
||||||
|
import SwiftyJSON
|
||||||
|
|
||||||
|
struct VideosCacheModel {
|
||||||
|
static let shared = VideosCacheModel()
|
||||||
|
let logger = Logger(label: "stream.yattee.cache.videos")
|
||||||
|
|
||||||
|
static let jsonToDataTransformer: (JSON) -> Data = { try! $0.rawData() }
|
||||||
|
static let jsonFromDataTransformer: (Data) -> JSON = { try! JSON(data: $0) }
|
||||||
|
static let jsonTransformer = Transformer(toData: jsonToDataTransformer, fromData: jsonFromDataTransformer)
|
||||||
|
|
||||||
|
static let videosStorageDiskConfig = DiskConfig(name: "videos")
|
||||||
|
static let vidoesStorageMemoryConfig = MemoryConfig()
|
||||||
|
|
||||||
|
let videosStorage = try! Storage<String, JSON>(
|
||||||
|
diskConfig: Self.videosStorageDiskConfig,
|
||||||
|
memoryConfig: Self.vidoesStorageMemoryConfig,
|
||||||
|
transformer: Self.jsonTransformer
|
||||||
|
)
|
||||||
|
|
||||||
|
func storeVideo(_ video: Video) {
|
||||||
|
logger.info("caching \(video.cacheKey)")
|
||||||
|
try? videosStorage.setObject(video.json, forKey: video.cacheKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func retrieveVideo(_ cacheKey: String) -> Video? {
|
||||||
|
logger.info("retrieving cache for \(cacheKey)")
|
||||||
|
|
||||||
|
if let json = try? videosStorage.object(forKey: cacheKey) {
|
||||||
|
return Video.from(json)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
@ -109,4 +109,18 @@ struct Channel: Identifiable, Hashable {
|
|||||||
guard contentType != .videos, contentType != .playlists else { return true }
|
guard contentType != .videos, contentType != .playlists else { return true }
|
||||||
return tabs.contains { $0.contentType == contentType }
|
return tabs.contains { $0.contentType == contentType }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var json: JSON {
|
||||||
|
[
|
||||||
|
"id": id,
|
||||||
|
"name": name
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
static func from(_ json: JSON) -> Self {
|
||||||
|
.init(
|
||||||
|
id: json["id"].stringValue,
|
||||||
|
name: json["name"].stringValue
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,11 @@ extension PlayerModel {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let video = VideosCacheModel.shared.retrieveVideo(watch.video.cacheKey) {
|
||||||
|
historyVideos.append(video)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
guard let api = playerAPI(watch.video) else { return }
|
guard let api = playerAPI(watch.video) else { return }
|
||||||
|
|
||||||
api.video(watch.videoID)
|
api.video(watch.videoID)
|
||||||
@ -28,6 +33,7 @@ extension PlayerModel {
|
|||||||
guard let self else { return }
|
guard let self else { return }
|
||||||
|
|
||||||
if let video: Video = response.typedContent() {
|
if let video: Video = response.typedContent() {
|
||||||
|
VideosCacheModel.shared.storeVideo(video)
|
||||||
self.historyVideos.append(video)
|
self.historyVideos.append(video)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ extension PlayerModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func playerAPI(_ video: Video) -> VideosAPI! {
|
func playerAPI(_ video: Video) -> VideosAPI! {
|
||||||
guard let url = video.instanceURL else { return nil }
|
guard let url = video.instanceURL else { return accounts.api }
|
||||||
switch video.app {
|
switch video.app {
|
||||||
case .local:
|
case .local:
|
||||||
return nil
|
return nil
|
||||||
|
@ -34,6 +34,7 @@ extension PlayerModel {
|
|||||||
.load()
|
.load()
|
||||||
.onSuccess { response in
|
.onSuccess { response in
|
||||||
if let video: Video = response.typedContent() {
|
if let video: Video = response.typedContent() {
|
||||||
|
VideosCacheModel.shared.storeVideo(video)
|
||||||
guard video.videoID == self.currentVideo?.videoID else {
|
guard video.videoID == self.currentVideo?.videoID else {
|
||||||
self.logger.info("ignoring loaded streams from \(instance.description) as current video has changed")
|
self.logger.info("ignoring loaded streams from \(instance.description) as current video has changed")
|
||||||
return
|
return
|
||||||
|
@ -36,4 +36,18 @@ struct Thumbnail {
|
|||||||
self.url = url
|
self.url = url
|
||||||
self.quality = quality
|
self.quality = quality
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var json: JSON {
|
||||||
|
[
|
||||||
|
"url": url.absoluteString,
|
||||||
|
"quality": quality.rawValue
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
static func from(_ json: JSON) -> Self {
|
||||||
|
.init(
|
||||||
|
url: URL(string: json["url"].stringValue)!,
|
||||||
|
quality: .init(rawValue: json["quality"].stringValue) ?? .default
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,6 +119,71 @@ struct Video: Identifiable, Equatable, Hashable {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var cacheKey: String {
|
||||||
|
switch app {
|
||||||
|
case .local:
|
||||||
|
return videoID
|
||||||
|
case .invidious:
|
||||||
|
return "youtube-\(videoID)"
|
||||||
|
case .piped:
|
||||||
|
return "youtube-\(videoID)"
|
||||||
|
case .peerTube:
|
||||||
|
return "peertube-\(instanceURL?.absoluteString ?? "unknown-instance")-\(videoID)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var json: JSON {
|
||||||
|
let dateFormatter = ISO8601DateFormatter()
|
||||||
|
let publishedAt = self.publishedAt == nil ? "" : dateFormatter.string(from: self.publishedAt!)
|
||||||
|
return [
|
||||||
|
"instanceID": instanceID ?? "",
|
||||||
|
"app": app.rawValue,
|
||||||
|
"instanceURL": instanceURL?.absoluteString ?? "",
|
||||||
|
"id": id,
|
||||||
|
"videoID": videoID,
|
||||||
|
"videoURL": videoURL?.absoluteString ?? "",
|
||||||
|
"title": title,
|
||||||
|
"author": author,
|
||||||
|
"length": length,
|
||||||
|
"published": published,
|
||||||
|
"views": views,
|
||||||
|
"description": description ?? "",
|
||||||
|
"genre": genre ?? "",
|
||||||
|
"channel": channel.json.object,
|
||||||
|
"thumbnails": thumbnails.compactMap { $0.json.object },
|
||||||
|
"indexID": indexID ?? "",
|
||||||
|
"live": live,
|
||||||
|
"upcoming": upcoming,
|
||||||
|
"publishedAt": publishedAt
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
static func from(_ json: JSON) -> Self {
|
||||||
|
let dateFormatter = ISO8601DateFormatter()
|
||||||
|
|
||||||
|
return Video(
|
||||||
|
instanceID: json["instanceID"].stringValue,
|
||||||
|
app: .init(rawValue: json["app"].stringValue) ?? AccountsModel.shared.current.app ?? .local,
|
||||||
|
instanceURL: URL(string: json["instanceURL"].stringValue) ?? AccountsModel.shared.current.instance.apiURL,
|
||||||
|
id: json["id"].stringValue,
|
||||||
|
videoID: json["videoID"].stringValue,
|
||||||
|
videoURL: json["videoURL"].url,
|
||||||
|
title: json["title"].stringValue,
|
||||||
|
author: json["author"].stringValue,
|
||||||
|
length: json["length"].doubleValue,
|
||||||
|
published: json["published"].stringValue,
|
||||||
|
views: json["views"].intValue,
|
||||||
|
description: json["description"].string,
|
||||||
|
genre: json["genre"].string,
|
||||||
|
channel: Channel.from(json["channel"]),
|
||||||
|
thumbnails: json["thumbnails"].arrayValue.compactMap { Thumbnail.from($0) },
|
||||||
|
indexID: json["indexID"].stringValue,
|
||||||
|
live: json["live"].boolValue,
|
||||||
|
upcoming: json["upcoming"].boolValue,
|
||||||
|
publishedAt: dateFormatter.date(from: json["publishedAt"].stringValue)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
var instance: Instance! {
|
var instance: Instance! {
|
||||||
if let instance = InstancesModel.shared.find(instanceID) {
|
if let instance = InstancesModel.shared.find(instanceID) {
|
||||||
return instance
|
return instance
|
||||||
|
@ -91,12 +91,12 @@ extension Watch {
|
|||||||
var video: Video {
|
var video: Video {
|
||||||
let url = URL(string: videoID)
|
let url = URL(string: videoID)
|
||||||
|
|
||||||
if app == nil || !Video.VideoID.isValid(videoID) {
|
if !Video.VideoID.isValid(videoID) {
|
||||||
if let url {
|
if let url {
|
||||||
return .local(url)
|
return .local(url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Video(app: app, instanceURL: instanceURL, videoID: videoID)
|
return Video(app: app ?? AccountsModel.shared.current.app ?? .local, instanceURL: instanceURL, videoID: videoID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,6 +346,7 @@
|
|||||||
374C0540272472C0009BDDBE /* PlayerSponsorBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374C053E272472C0009BDDBE /* PlayerSponsorBlock.swift */; };
|
374C0540272472C0009BDDBE /* PlayerSponsorBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374C053E272472C0009BDDBE /* PlayerSponsorBlock.swift */; };
|
||||||
374C0541272472C0009BDDBE /* PlayerSponsorBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374C053E272472C0009BDDBE /* PlayerSponsorBlock.swift */; };
|
374C0541272472C0009BDDBE /* PlayerSponsorBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374C053E272472C0009BDDBE /* PlayerSponsorBlock.swift */; };
|
||||||
374C0543272496E4009BDDBE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374C0542272496E4009BDDBE /* AppDelegate.swift */; };
|
374C0543272496E4009BDDBE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374C0542272496E4009BDDBE /* AppDelegate.swift */; };
|
||||||
|
374D11E72943C56300CB4350 /* Cache in Frameworks */ = {isa = PBXBuildFile; productRef = 374D11E62943C56300CB4350 /* Cache */; };
|
||||||
374DE88028BB896C0062BBF2 /* PlayerDragGesture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374DE87F28BB896C0062BBF2 /* PlayerDragGesture.swift */; };
|
374DE88028BB896C0062BBF2 /* PlayerDragGesture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374DE87F28BB896C0062BBF2 /* PlayerDragGesture.swift */; };
|
||||||
374DE88128BB896C0062BBF2 /* PlayerDragGesture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374DE87F28BB896C0062BBF2 /* PlayerDragGesture.swift */; };
|
374DE88128BB896C0062BBF2 /* PlayerDragGesture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374DE87F28BB896C0062BBF2 /* PlayerDragGesture.swift */; };
|
||||||
374DE88328BB8A280062BBF2 /* PlayerOrientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374DE88228BB8A280062BBF2 /* PlayerOrientation.swift */; };
|
374DE88328BB8A280062BBF2 /* PlayerOrientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374DE88228BB8A280062BBF2 /* PlayerOrientation.swift */; };
|
||||||
@ -544,6 +545,11 @@
|
|||||||
377E17142928265900894889 /* ListRowSeparator+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377E17132928265900894889 /* ListRowSeparator+Backport.swift */; };
|
377E17142928265900894889 /* ListRowSeparator+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377E17132928265900894889 /* ListRowSeparator+Backport.swift */; };
|
||||||
377E17152928265900894889 /* ListRowSeparator+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377E17132928265900894889 /* ListRowSeparator+Backport.swift */; };
|
377E17152928265900894889 /* ListRowSeparator+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377E17132928265900894889 /* ListRowSeparator+Backport.swift */; };
|
||||||
377E17162928265900894889 /* ListRowSeparator+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377E17132928265900894889 /* ListRowSeparator+Backport.swift */; };
|
377E17162928265900894889 /* ListRowSeparator+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377E17132928265900894889 /* ListRowSeparator+Backport.swift */; };
|
||||||
|
377F9F74294403770043F856 /* Cache in Frameworks */ = {isa = PBXBuildFile; productRef = 377F9F73294403770043F856 /* Cache */; };
|
||||||
|
377F9F76294403880043F856 /* Cache in Frameworks */ = {isa = PBXBuildFile; productRef = 377F9F75294403880043F856 /* Cache */; };
|
||||||
|
377F9F7B294403F20043F856 /* VideosCacheModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377F9F7A294403F20043F856 /* VideosCacheModel.swift */; };
|
||||||
|
377F9F7C294403F20043F856 /* VideosCacheModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377F9F7A294403F20043F856 /* VideosCacheModel.swift */; };
|
||||||
|
377F9F7D294403F20043F856 /* VideosCacheModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377F9F7A294403F20043F856 /* VideosCacheModel.swift */; };
|
||||||
377FC7D5267A080300A6BBAF /* SwiftyJSON in Frameworks */ = {isa = PBXBuildFile; productRef = 377FC7D4267A080300A6BBAF /* SwiftyJSON */; };
|
377FC7D5267A080300A6BBAF /* SwiftyJSON in Frameworks */ = {isa = PBXBuildFile; productRef = 377FC7D4267A080300A6BBAF /* SwiftyJSON */; };
|
||||||
377FC7DB267A080300A6BBAF /* Logging in Frameworks */ = {isa = PBXBuildFile; productRef = 377FC7DA267A080300A6BBAF /* Logging */; };
|
377FC7DB267A080300A6BBAF /* Logging in Frameworks */ = {isa = PBXBuildFile; productRef = 377FC7DA267A080300A6BBAF /* Logging */; };
|
||||||
377FC7DC267A081800A6BBAF /* PopularView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AAF27D26737323007FC770 /* PopularView.swift */; };
|
377FC7DC267A081800A6BBAF /* PopularView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AAF27D26737323007FC770 /* PopularView.swift */; };
|
||||||
@ -1222,6 +1228,7 @@
|
|||||||
377ABC43286E4B74009C986F /* ManifestedInstance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManifestedInstance.swift; sourceTree = "<group>"; };
|
377ABC43286E4B74009C986F /* ManifestedInstance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManifestedInstance.swift; sourceTree = "<group>"; };
|
||||||
377ABC47286E5887009C986F /* Sequence+Unique.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Sequence+Unique.swift"; sourceTree = "<group>"; };
|
377ABC47286E5887009C986F /* Sequence+Unique.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Sequence+Unique.swift"; sourceTree = "<group>"; };
|
||||||
377E17132928265900894889 /* ListRowSeparator+Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ListRowSeparator+Backport.swift"; sourceTree = "<group>"; };
|
377E17132928265900894889 /* ListRowSeparator+Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ListRowSeparator+Backport.swift"; sourceTree = "<group>"; };
|
||||||
|
377F9F7A294403F20043F856 /* VideosCacheModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideosCacheModel.swift; sourceTree = "<group>"; };
|
||||||
377FF88A291A60310028EB0B /* OpenVideosModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenVideosModel.swift; sourceTree = "<group>"; };
|
377FF88A291A60310028EB0B /* OpenVideosModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenVideosModel.swift; sourceTree = "<group>"; };
|
||||||
377FF88E291A99580028EB0B /* HistoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryView.swift; sourceTree = "<group>"; };
|
377FF88E291A99580028EB0B /* HistoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryView.swift; sourceTree = "<group>"; };
|
||||||
37824309291E58D6005DEC1C /* Open in Yattee.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Open in Yattee.entitlements"; sourceTree = "<group>"; };
|
37824309291E58D6005DEC1C /* Open in Yattee.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Open in Yattee.entitlements"; sourceTree = "<group>"; };
|
||||||
@ -1426,6 +1433,7 @@
|
|||||||
3736A21A286BB72300C9E5EE /* libmpv.xcframework in Frameworks */,
|
3736A21A286BB72300C9E5EE /* libmpv.xcframework in Frameworks */,
|
||||||
3765917C27237D21009F956E /* PINCache in Frameworks */,
|
3765917C27237D21009F956E /* PINCache in Frameworks */,
|
||||||
37BD07B72698AB2E003EBB87 /* Defaults in Frameworks */,
|
37BD07B72698AB2E003EBB87 /* Defaults in Frameworks */,
|
||||||
|
377F9F74294403770043F856 /* Cache in Frameworks */,
|
||||||
3736A20C286BB72300C9E5EE /* libavutil.xcframework in Frameworks */,
|
3736A20C286BB72300C9E5EE /* libavutil.xcframework in Frameworks */,
|
||||||
37FB285627220D9000A57617 /* SDWebImagePINPlugin in Frameworks */,
|
37FB285627220D9000A57617 /* SDWebImagePINPlugin in Frameworks */,
|
||||||
3736A212286BB72300C9E5EE /* libswresample.xcframework in Frameworks */,
|
3736A212286BB72300C9E5EE /* libswresample.xcframework in Frameworks */,
|
||||||
@ -1465,6 +1473,7 @@
|
|||||||
370F4FC927CC16CB001B35DC /* libssl.3.dylib in Frameworks */,
|
370F4FC927CC16CB001B35DC /* libssl.3.dylib in Frameworks */,
|
||||||
3703206827D2BB45007A0CB8 /* Defaults in Frameworks */,
|
3703206827D2BB45007A0CB8 /* Defaults in Frameworks */,
|
||||||
3703206A27D2BB49007A0CB8 /* Alamofire in Frameworks */,
|
3703206A27D2BB49007A0CB8 /* Alamofire in Frameworks */,
|
||||||
|
374D11E72943C56300CB4350 /* Cache in Frameworks */,
|
||||||
370F4FD427CC16CB001B35DC /* libfreetype.6.dylib in Frameworks */,
|
370F4FD427CC16CB001B35DC /* libfreetype.6.dylib in Frameworks */,
|
||||||
3797104B28D3D18800D5F53C /* SDWebImageSwiftUI in Frameworks */,
|
3797104B28D3D18800D5F53C /* SDWebImageSwiftUI in Frameworks */,
|
||||||
370F4FE227CC16CB001B35DC /* libXdmcp.6.dylib in Frameworks */,
|
370F4FE227CC16CB001B35DC /* libXdmcp.6.dylib in Frameworks */,
|
||||||
@ -1526,6 +1535,7 @@
|
|||||||
37FB2849272207F000A57617 /* SDWebImageWebPCoder in Frameworks */,
|
37FB2849272207F000A57617 /* SDWebImageWebPCoder in Frameworks */,
|
||||||
3736A20D286BB72300C9E5EE /* libavutil.xcframework in Frameworks */,
|
3736A20D286BB72300C9E5EE /* libavutil.xcframework in Frameworks */,
|
||||||
3736A213286BB72300C9E5EE /* libswresample.xcframework in Frameworks */,
|
3736A213286BB72300C9E5EE /* libswresample.xcframework in Frameworks */,
|
||||||
|
377F9F76294403880043F856 /* Cache in Frameworks */,
|
||||||
37FB285427220D8400A57617 /* SDWebImagePINPlugin in Frameworks */,
|
37FB285427220D8400A57617 /* SDWebImagePINPlugin in Frameworks */,
|
||||||
3732BFD028B83763009F3F4D /* KeychainAccess in Frameworks */,
|
3732BFD028B83763009F3F4D /* KeychainAccess in Frameworks */,
|
||||||
3772003927E8EEB700CB2475 /* AVFoundation.framework in Frameworks */,
|
3772003927E8EEB700CB2475 /* AVFoundation.framework in Frameworks */,
|
||||||
@ -1963,6 +1973,15 @@
|
|||||||
path = Modifiers;
|
path = Modifiers;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
377F9F79294403DC0043F856 /* Cache */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
37F5E8B9291BEF69006C15F5 /* CacheModel.swift */,
|
||||||
|
377F9F7A294403F20043F856 /* VideosCacheModel.swift */,
|
||||||
|
);
|
||||||
|
path = Cache;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
377FC7D1267A080300A6BBAF /* Frameworks */ = {
|
377FC7D1267A080300A6BBAF /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -2187,11 +2206,11 @@
|
|||||||
children = (
|
children = (
|
||||||
3743B86627216A1E00261544 /* Accounts */,
|
3743B86627216A1E00261544 /* Accounts */,
|
||||||
3743B864272169E200261544 /* Applications */,
|
3743B864272169E200261544 /* Applications */,
|
||||||
|
377F9F79294403DC0043F856 /* Cache */,
|
||||||
3743B86527216A0600261544 /* Player */,
|
3743B86527216A0600261544 /* Player */,
|
||||||
3751BA8127E69131007B1A60 /* ReturnYouTubeDislike */,
|
3751BA8127E69131007B1A60 /* ReturnYouTubeDislike */,
|
||||||
37FB283F2721B20800A57617 /* Search */,
|
37FB283F2721B20800A57617 /* Search */,
|
||||||
374C0539272436DA009BDDBE /* SponsorBlock */,
|
374C0539272436DA009BDDBE /* SponsorBlock */,
|
||||||
37F5E8B9291BEF69006C15F5 /* CacheModel.swift */,
|
|
||||||
3776ADD5287381240078EBC4 /* Captions.swift */,
|
3776ADD5287381240078EBC4 /* Captions.swift */,
|
||||||
37AAF28F26740715007FC770 /* Channel.swift */,
|
37AAF28F26740715007FC770 /* Channel.swift */,
|
||||||
37C3A24427235DA70087A57A /* ChannelPlaylist.swift */,
|
37C3A24427235DA70087A57A /* ChannelPlaylist.swift */,
|
||||||
@ -2405,6 +2424,7 @@
|
|||||||
3799AC0828B03CED001376F9 /* ActiveLabel */,
|
3799AC0828B03CED001376F9 /* ActiveLabel */,
|
||||||
375B8AB028B57F4200397B31 /* KeychainAccess */,
|
375B8AB028B57F4200397B31 /* KeychainAccess */,
|
||||||
3797104828D3D10600D5F53C /* SDWebImageSwiftUI */,
|
3797104828D3D10600D5F53C /* SDWebImageSwiftUI */,
|
||||||
|
377F9F73294403770043F856 /* Cache */,
|
||||||
);
|
);
|
||||||
productName = "Yattee (iOS)";
|
productName = "Yattee (iOS)";
|
||||||
productReference = 37D4B0C92671614900C925CA /* Yattee.app */;
|
productReference = 37D4B0C92671614900C925CA /* Yattee.app */;
|
||||||
@ -2441,6 +2461,7 @@
|
|||||||
372AA413286D06A10000B1DC /* Repeat */,
|
372AA413286D06A10000B1DC /* Repeat */,
|
||||||
375B8AB628B583BD00397B31 /* KeychainAccess */,
|
375B8AB628B583BD00397B31 /* KeychainAccess */,
|
||||||
3797104A28D3D18800D5F53C /* SDWebImageSwiftUI */,
|
3797104A28D3D18800D5F53C /* SDWebImageSwiftUI */,
|
||||||
|
374D11E62943C56300CB4350 /* Cache */,
|
||||||
);
|
);
|
||||||
productName = "Yattee (macOS)";
|
productName = "Yattee (macOS)";
|
||||||
productReference = 37D4B0CF2671614900C925CA /* Yattee.app */;
|
productReference = 37D4B0CF2671614900C925CA /* Yattee.app */;
|
||||||
@ -2518,6 +2539,7 @@
|
|||||||
37E80F42287B7AAF00561799 /* SwiftUIPager */,
|
37E80F42287B7AAF00561799 /* SwiftUIPager */,
|
||||||
3732BFCF28B83763009F3F4D /* KeychainAccess */,
|
3732BFCF28B83763009F3F4D /* KeychainAccess */,
|
||||||
3797104C28D3D19100D5F53C /* SDWebImageSwiftUI */,
|
3797104C28D3D19100D5F53C /* SDWebImageSwiftUI */,
|
||||||
|
377F9F75294403880043F856 /* Cache */,
|
||||||
);
|
);
|
||||||
productName = Yattee;
|
productName = Yattee;
|
||||||
productReference = 37D4B158267164AE00C925CA /* Yattee.app */;
|
productReference = 37D4B158267164AE00C925CA /* Yattee.app */;
|
||||||
@ -2626,6 +2648,7 @@
|
|||||||
3799AC0728B03CEC001376F9 /* XCRemoteSwiftPackageReference "ActiveLabel.swift" */,
|
3799AC0728B03CEC001376F9 /* XCRemoteSwiftPackageReference "ActiveLabel.swift" */,
|
||||||
375B8AAF28B57F4200397B31 /* XCRemoteSwiftPackageReference "KeychainAccess" */,
|
375B8AAF28B57F4200397B31 /* XCRemoteSwiftPackageReference "KeychainAccess" */,
|
||||||
3797104728D3D10600D5F53C /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */,
|
3797104728D3D10600D5F53C /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */,
|
||||||
|
374D11E52943C56300CB4350 /* XCRemoteSwiftPackageReference "Cache" */,
|
||||||
);
|
);
|
||||||
productRefGroup = 37D4B0CA2671614900C925CA /* Products */;
|
productRefGroup = 37D4B0CA2671614900C925CA /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
@ -3089,6 +3112,7 @@
|
|||||||
3784CDE227772EE40055BBF2 /* Watch.swift in Sources */,
|
3784CDE227772EE40055BBF2 /* Watch.swift in Sources */,
|
||||||
37FB285E272225E800A57617 /* ContentItemView.swift in Sources */,
|
37FB285E272225E800A57617 /* ContentItemView.swift in Sources */,
|
||||||
3797758B2689345500DD52A8 /* Store.swift in Sources */,
|
3797758B2689345500DD52A8 /* Store.swift in Sources */,
|
||||||
|
377F9F7B294403F20043F856 /* VideosCacheModel.swift in Sources */,
|
||||||
37B795902771DAE0001CF27B /* OpenURLHandler.swift in Sources */,
|
37B795902771DAE0001CF27B /* OpenURLHandler.swift in Sources */,
|
||||||
37732FF02703A26300F04329 /* AccountValidationStatus.swift in Sources */,
|
37732FF02703A26300F04329 /* AccountValidationStatus.swift in Sources */,
|
||||||
);
|
);
|
||||||
@ -3284,6 +3308,7 @@
|
|||||||
37599F31272B42810087F250 /* FavoriteItem.swift in Sources */,
|
37599F31272B42810087F250 /* FavoriteItem.swift in Sources */,
|
||||||
3730F75A2733481E00F385FC /* RelatedView.swift in Sources */,
|
3730F75A2733481E00F385FC /* RelatedView.swift in Sources */,
|
||||||
37E04C0F275940FB00172673 /* VerticalScrollingFix.swift in Sources */,
|
37E04C0F275940FB00172673 /* VerticalScrollingFix.swift in Sources */,
|
||||||
|
377F9F7C294403F20043F856 /* VideosCacheModel.swift in Sources */,
|
||||||
374924E4292141320017D862 /* InspectorView.swift in Sources */,
|
374924E4292141320017D862 /* InspectorView.swift in Sources */,
|
||||||
375168D72700FDB8008F96A6 /* Debounce.swift in Sources */,
|
375168D72700FDB8008F96A6 /* Debounce.swift in Sources */,
|
||||||
37D526DF2720AC4400ED2F5E /* VideosAPI.swift in Sources */,
|
37D526DF2720AC4400ED2F5E /* VideosAPI.swift in Sources */,
|
||||||
@ -3515,6 +3540,7 @@
|
|||||||
3744A96228B99ADD005DE0A7 /* PlayerControlsLayout.swift in Sources */,
|
3744A96228B99ADD005DE0A7 /* PlayerControlsLayout.swift in Sources */,
|
||||||
377A20AB2693C9A2002842B8 /* TypedContentAccessors.swift in Sources */,
|
377A20AB2693C9A2002842B8 /* TypedContentAccessors.swift in Sources */,
|
||||||
3748186826A7627F0084E870 /* Video+Fixtures.swift in Sources */,
|
3748186826A7627F0084E870 /* Video+Fixtures.swift in Sources */,
|
||||||
|
377F9F7D294403F20043F856 /* VideosCacheModel.swift in Sources */,
|
||||||
37C3A253272366440087A57A /* ChannelPlaylistView.swift in Sources */,
|
37C3A253272366440087A57A /* ChannelPlaylistView.swift in Sources */,
|
||||||
378AE945274EF00A006A4EE1 /* Color+Background.swift in Sources */,
|
378AE945274EF00A006A4EE1 /* Color+Background.swift in Sources */,
|
||||||
3743CA54270F284F00E4D32B /* View+Borders.swift in Sources */,
|
3743CA54270F284F00E4D32B /* View+Borders.swift in Sources */,
|
||||||
@ -4458,6 +4484,14 @@
|
|||||||
minimumVersion = 0.6.0;
|
minimumVersion = 0.6.0;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
374D11E52943C56300CB4350 /* XCRemoteSwiftPackageReference "Cache" */ = {
|
||||||
|
isa = XCRemoteSwiftPackageReference;
|
||||||
|
repositoryURL = "https://github.com/hyperoslo/Cache.git";
|
||||||
|
requirement = {
|
||||||
|
branch = master;
|
||||||
|
kind = branch;
|
||||||
|
};
|
||||||
|
};
|
||||||
375B8AAF28B57F4200397B31 /* XCRemoteSwiftPackageReference "KeychainAccess" */ = {
|
375B8AAF28B57F4200397B31 /* XCRemoteSwiftPackageReference "KeychainAccess" */ = {
|
||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
repositoryURL = "https://github.com/kishikawakatsumi/KeychainAccess.git";
|
repositoryURL = "https://github.com/kishikawakatsumi/KeychainAccess.git";
|
||||||
@ -4638,6 +4672,11 @@
|
|||||||
package = 375B8AAF28B57F4200397B31 /* XCRemoteSwiftPackageReference "KeychainAccess" */;
|
package = 375B8AAF28B57F4200397B31 /* XCRemoteSwiftPackageReference "KeychainAccess" */;
|
||||||
productName = KeychainAccess;
|
productName = KeychainAccess;
|
||||||
};
|
};
|
||||||
|
374D11E62943C56300CB4350 /* Cache */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = 374D11E52943C56300CB4350 /* XCRemoteSwiftPackageReference "Cache" */;
|
||||||
|
productName = Cache;
|
||||||
|
};
|
||||||
375B8AB028B57F4200397B31 /* KeychainAccess */ = {
|
375B8AB028B57F4200397B31 /* KeychainAccess */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = 375B8AAF28B57F4200397B31 /* XCRemoteSwiftPackageReference "KeychainAccess" */;
|
package = 375B8AAF28B57F4200397B31 /* XCRemoteSwiftPackageReference "KeychainAccess" */;
|
||||||
@ -4683,6 +4722,16 @@
|
|||||||
package = 37BADCA32699FB72009BE4FB /* XCRemoteSwiftPackageReference "Alamofire" */;
|
package = 37BADCA32699FB72009BE4FB /* XCRemoteSwiftPackageReference "Alamofire" */;
|
||||||
productName = Alamofire;
|
productName = Alamofire;
|
||||||
};
|
};
|
||||||
|
377F9F73294403770043F856 /* Cache */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = 374D11E52943C56300CB4350 /* XCRemoteSwiftPackageReference "Cache" */;
|
||||||
|
productName = Cache;
|
||||||
|
};
|
||||||
|
377F9F75294403880043F856 /* Cache */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = 374D11E52943C56300CB4350 /* XCRemoteSwiftPackageReference "Cache" */;
|
||||||
|
productName = Cache;
|
||||||
|
};
|
||||||
377FC7D4267A080300A6BBAF /* SwiftyJSON */ = {
|
377FC7D4267A080300A6BBAF /* SwiftyJSON */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = 37D4B19B2671817900C925CA /* XCRemoteSwiftPackageReference "SwiftyJSON" */;
|
package = 37D4B19B2671817900C925CA /* XCRemoteSwiftPackageReference "SwiftyJSON" */;
|
||||||
|
@ -18,6 +18,15 @@
|
|||||||
"version" : "5.6.2"
|
"version" : "5.6.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"identity" : "cache",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/hyperoslo/Cache.git",
|
||||||
|
"state" : {
|
||||||
|
"branch" : "master",
|
||||||
|
"revision" : "eeaf771d8d2e8247fbd6da2e27c986d99803fb1f"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"identity" : "defaults",
|
"identity" : "defaults",
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
|
Loading…
Reference in New Issue
Block a user