mirror of
https://github.com/yattee/yattee.git
synced 2024-12-22 13:33:42 +00:00
Fix bookmarks
This commit is contained in:
parent
220aef65ce
commit
f1664d026c
18
Extensions/URL+ByReplacingYatteeProtocol.swift
Normal file
18
Extensions/URL+ByReplacingYatteeProtocol.swift
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension URL {
|
||||||
|
func byReplacingYatteeProtocol(with urlProtocol: String = "https") -> URL! {
|
||||||
|
var urlAbsoluteString = absoluteString
|
||||||
|
|
||||||
|
guard urlAbsoluteString.hasPrefix(Constants.yatteeProtocol) else {
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
urlAbsoluteString = String(urlAbsoluteString.dropFirst(Constants.yatteeProtocol.count))
|
||||||
|
if absoluteString.contains("://") {
|
||||||
|
return URL(string: urlAbsoluteString)
|
||||||
|
}
|
||||||
|
|
||||||
|
return URL(string: "\(urlProtocol)://\(urlAbsoluteString)")
|
||||||
|
}
|
||||||
|
}
|
@ -49,7 +49,7 @@ final class DocumentsModel: ObservableObject {
|
|||||||
|
|
||||||
var documentsDirectory: URL? {
|
var documentsDirectory: URL? {
|
||||||
if let url = try? fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) {
|
if let url = try? fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) {
|
||||||
return replacePrivateVar(url)
|
return standardizedURL(url)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -69,12 +69,12 @@ final class DocumentsModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isDocument(_ video: Video) -> Bool {
|
func isDocument(_ video: Video) -> Bool {
|
||||||
guard video.isLocal, let url = video.localStream?.localURL, let url = replacePrivateVar(url) else { return false }
|
guard video.isLocal, let url = video.localStream?.localURL, let url = standardizedURL(url) else { return false }
|
||||||
return isDocument(url)
|
return isDocument(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
func isDocument(_ url: URL) -> Bool {
|
func isDocument(_ url: URL) -> Bool {
|
||||||
guard let url = replacePrivateVar(url), let documentsDirectory else { return false }
|
guard let url = standardizedURL(url), let documentsDirectory else { return false }
|
||||||
return url.absoluteString.starts(with: documentsDirectory.absoluteString)
|
return url.absoluteString.starts(with: documentsDirectory.absoluteString)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ final class DocumentsModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func creationDate(_ video: Video) -> Date? {
|
func creationDate(_ video: Video) -> Date? {
|
||||||
guard video.isLocal, let url = video.localStream?.localURL, let url = replacePrivateVar(url) else { return nil }
|
guard video.isLocal, let url = video.localStream?.localURL, let url = standardizedURL(url) else { return nil }
|
||||||
return creationDate(url)
|
return creationDate(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ final class DocumentsModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func formattedCreationDate(_ video: Video) -> String? {
|
func formattedCreationDate(_ video: Video) -> String? {
|
||||||
guard video.isLocal, let url = video.localStream?.localURL, let url = replacePrivateVar(url) else { return nil }
|
guard video.isLocal, let url = video.localStream?.localURL, let url = standardizedURL(url) else { return nil }
|
||||||
return formattedCreationDate(url)
|
return formattedCreationDate(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ final class DocumentsModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func size(_ video: Video) -> Int? {
|
func size(_ video: Video) -> Int? {
|
||||||
guard video.isLocal, let url = video.localStream?.localURL, let url = replacePrivateVar(url) else { return nil }
|
guard video.isLocal, let url = video.localStream?.localURL, let url = standardizedURL(url) else { return nil }
|
||||||
return size(url)
|
return size(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +168,7 @@ final class DocumentsModel: ObservableObject {
|
|||||||
|
|
||||||
var canGoBack: Bool {
|
var canGoBack: Bool {
|
||||||
guard let directoryURL, let documentsDirectory else { return false }
|
guard let directoryURL, let documentsDirectory else { return false }
|
||||||
return replacePrivateVar(directoryURL) != documentsDirectory
|
return standardizedURL(directoryURL) != documentsDirectory
|
||||||
}
|
}
|
||||||
|
|
||||||
func goToURL(_ url: URL) {
|
func goToURL(_ url: URL) {
|
||||||
@ -187,9 +187,9 @@ final class DocumentsModel: ObservableObject {
|
|||||||
directoryURL?.deletingLastPathComponent()
|
directoryURL?.deletingLastPathComponent()
|
||||||
}
|
}
|
||||||
|
|
||||||
func replacePrivateVar(_ url: URL) -> URL? {
|
func standardizedURL(_ url: URL) -> URL? {
|
||||||
let urlStringWithPrivateVarRemoved = url.absoluteString.replacingFirstOccurrence(of: "/private/var/", with: "/var/")
|
let standardizedURL = NSString(string: url.absoluteString).standardizingPath
|
||||||
return URL(string: urlStringWithPrivateVarRemoved)
|
return URL(string: standardizedURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
func refresh() {
|
func refresh() {
|
||||||
|
@ -291,7 +291,9 @@ final class MPVBackend: PlayerBackend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if video.isLocal, video.localStreamIsFile {
|
if video.isLocal, video.localStreamIsFile {
|
||||||
_ = url.startAccessingSecurityScopedResource()
|
if url.startAccessingSecurityScopedResource() {
|
||||||
|
URLBookmarkModel.shared.saveBookmark(url)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.client.loadFile(url, sub: captions?.url, time: time, forceSeekable: stream.kind == .hls) { [weak self] _ in
|
self.client.loadFile(url, sub: captions?.url, time: time, forceSeekable: stream.kind == .hls) { [weak self] _ in
|
||||||
|
@ -18,13 +18,39 @@ struct URLBookmarkModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func saveBookmark(_ url: URL) {
|
func saveBookmark(_ url: URL) {
|
||||||
|
var urlForBookmark = url
|
||||||
|
if let yatteeSanitizedUrl = url.byReplacingYatteeProtocol() {
|
||||||
|
urlForBookmark = yatteeSanitizedUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
guard urlForBookmark.isFileURL else {
|
||||||
|
logger.error("trying to save bookmark for something that is not a file")
|
||||||
|
logger.error("not a file: \(urlForBookmark.absoluteString)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
guard let defaults = CacheModel.shared.bookmarksDefaults else {
|
guard let defaults = CacheModel.shared.bookmarksDefaults else {
|
||||||
logger.error("could not open bookmarks defaults")
|
logger.error("could not open bookmarks defaults")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let bookmarkData = try? urlForBookmark.bookmarkData(options: bookmarkCreationOptions, includingResourceValuesForKeys: nil, relativeTo: nil) {
|
||||||
|
defaults.set(bookmarkData, forKey: bookmarkKey(urlForBookmark))
|
||||||
|
logger.info("saved bookmark for \(bookmarkKey(urlForBookmark))")
|
||||||
|
} else {
|
||||||
|
logger.error("no bookmark data for \(urlForBookmark)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func saveBookmark(_ url: NSURL) {
|
||||||
guard url.isFileURL else {
|
guard url.isFileURL else {
|
||||||
logger.error("trying to save bookmark for something that is not a file")
|
logger.error("trying to save bookmark for something that is not a file")
|
||||||
|
logger.error("not a file: \(url.absoluteString)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let defaults = CacheModel.shared.bookmarksDefaults else {
|
||||||
|
logger.error("could not open bookmarks defaults")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,14 +63,19 @@ struct URLBookmarkModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func loadBookmark(_ url: URL) -> URL? {
|
func loadBookmark(_ url: URL) -> URL? {
|
||||||
logger.info("loading bookmark for \(bookmarkKey(url))")
|
var urlForBookmark = url
|
||||||
|
if let yatteeSanitizedUrl = url.byReplacingYatteeProtocol() {
|
||||||
|
urlForBookmark = yatteeSanitizedUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("loading bookmark for \(bookmarkKey(urlForBookmark))")
|
||||||
|
|
||||||
guard let defaults = CacheModel.shared.bookmarksDefaults else {
|
guard let defaults = CacheModel.shared.bookmarksDefaults else {
|
||||||
logger.error("could not open bookmarks defaults")
|
logger.error("could not open bookmarks defaults")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if let data = defaults.data(forKey: bookmarkKey(url)) {
|
if let data = defaults.data(forKey: bookmarkKey(urlForBookmark)) {
|
||||||
do {
|
do {
|
||||||
var isStale = false
|
var isStale = false
|
||||||
let url = try URL(
|
let url = try URL(
|
||||||
@ -54,9 +85,9 @@ struct URLBookmarkModel {
|
|||||||
bookmarkDataIsStale: &isStale
|
bookmarkDataIsStale: &isStale
|
||||||
)
|
)
|
||||||
if isStale {
|
if isStale {
|
||||||
saveBookmark(url)
|
saveBookmark(urlForBookmark)
|
||||||
}
|
}
|
||||||
logger.info("loaded bookmark for \(bookmarkKey(url))")
|
logger.info("loaded bookmark for \(bookmarkKey(urlForBookmark))")
|
||||||
|
|
||||||
return url
|
return url
|
||||||
} catch {
|
} catch {
|
||||||
@ -64,7 +95,7 @@ struct URLBookmarkModel {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.warning("could not find bookmark for \(bookmarkKey(url))")
|
logger.warning("could not find bookmark for \(bookmarkKey(urlForBookmark))")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,7 +124,11 @@ struct URLBookmarkModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func bookmarkKey(_ url: URL) -> String {
|
private func bookmarkKey(_ url: URL) -> String {
|
||||||
"\(Self.bookmarkPrefix)\(url.absoluteString)"
|
"\(Self.bookmarkPrefix)\(NSString(string: url.absoluteString).standardizingPath)"
|
||||||
|
}
|
||||||
|
|
||||||
|
private func bookmarkKey(_ url: NSURL) -> String {
|
||||||
|
"\(Self.bookmarkPrefix)\(url.standardizingPath?.absoluteString ?? "unknown")"
|
||||||
}
|
}
|
||||||
|
|
||||||
private func urlFromBookmark(_ key: String) -> URL? {
|
private func urlFromBookmark(_ key: String) -> URL? {
|
||||||
|
@ -1,52 +1,49 @@
|
|||||||
import Social
|
import Social
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import UniformTypeIdentifiers
|
||||||
|
|
||||||
final class ShareViewController: SLComposeServiceViewController {
|
final class ShareViewController: SLComposeServiceViewController {
|
||||||
override func viewWillAppear(_ animated: Bool) {
|
override func viewWillAppear(_ animated: Bool) {
|
||||||
super.viewWillAppear(animated)
|
super.viewWillAppear(animated)
|
||||||
|
|
||||||
openExtensionContextURLs()
|
openExtensionContextURLs()
|
||||||
|
|
||||||
extensionContext?.completeRequest(returningItems: [], completionHandler: nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func openExtensionContextURLs() {
|
private func openExtensionContextURLs() {
|
||||||
for item in extensionContext?.inputItems as! [NSExtensionItem] {
|
for item in extensionContext?.inputItems as! [NSExtensionItem] {
|
||||||
if let attachments = item.attachments {
|
if let attachments = item.attachments {
|
||||||
tryToOpenItemForPlainTextTypeIdentifier(attachments)
|
|
||||||
tryToOpenItemForUrlTypeIdentifier(attachments)
|
tryToOpenItemForUrlTypeIdentifier(attachments)
|
||||||
|
tryToOpenItemForPlainTextTypeIdentifier(attachments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func tryToOpenItemForPlainTextTypeIdentifier(_ attachments: [NSItemProvider]) {
|
private func tryToOpenItemForPlainTextTypeIdentifier(_ attachments: [NSItemProvider]) {
|
||||||
for itemProvider in attachments where itemProvider.hasItemConformingToTypeIdentifier("public.plain-text") {
|
for itemProvider in attachments {
|
||||||
itemProvider.loadItem(forTypeIdentifier: "public.plain-text", options: nil) { item, _ in
|
itemProvider.loadItem(forTypeIdentifier: UTType.plainText.identifier, options: nil) { item, _ in
|
||||||
if let url = (item as? String),
|
if let url = (item as? String),
|
||||||
let absoluteURL = URL(string: url)?.absoluteURL
|
let absoluteURL = URL(string: url)?.absoluteURL
|
||||||
{
|
{
|
||||||
URLBookmarkModel.shared.saveBookmark(absoluteURL)
|
|
||||||
if let url = URL(string: "yattee://\(absoluteURL.absoluteString)") {
|
if let url = URL(string: "yattee://\(absoluteURL.absoluteString)") {
|
||||||
self.open(url: url)
|
self.open(url: url)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.extensionContext?.completeRequest(returningItems: nil, completionHandler: nil)
|
self.extensionContext?.completeRequest(returningItems: nil, completionHandler: nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func tryToOpenItemForUrlTypeIdentifier(_ attachments: [NSItemProvider]) {
|
private func tryToOpenItemForUrlTypeIdentifier(_ attachments: [NSItemProvider]) {
|
||||||
for itemProvider in attachments where itemProvider.hasItemConformingToTypeIdentifier("public.url") {
|
for itemProvider in attachments {
|
||||||
itemProvider.loadItem(forTypeIdentifier: "public.url", options: nil) { item, _ in
|
itemProvider.loadItem(forTypeIdentifier: UTType.url.identifier, options: nil) { item, _ in
|
||||||
if let url = (item as? NSURL), let absoluteURL = url.absoluteURL {
|
if let url = (item as? NSURL), let absoluteURL = url.absoluteURL {
|
||||||
URLBookmarkModel.shared.saveBookmark(absoluteURL)
|
|
||||||
if let url = URL(string: "yattee://\(absoluteURL.absoluteString)") {
|
if let url = URL(string: "yattee://\(absoluteURL.absoluteString)") {
|
||||||
self.open(url: url)
|
self.open(url: url)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.extensionContext!.completeRequest(returningItems: nil, completionHandler: nil)
|
self.extensionContext!.completeRequest(returningItems: nil, completionHandler: nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,5 +2,6 @@ import Foundation
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct Constants {
|
struct Constants {
|
||||||
|
static let yatteeProtocol = "yattee://"
|
||||||
static let overlayAnimation = Animation.linear(duration: 0.2)
|
static let overlayAnimation = Animation.linear(duration: 0.2)
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ struct DocumentsView: View {
|
|||||||
NoDocumentsView()
|
NoDocumentsView()
|
||||||
} else {
|
} else {
|
||||||
ForEach(model.sortedDirectoryContents, id: \.absoluteString) { url in
|
ForEach(model.sortedDirectoryContents, id: \.absoluteString) { url in
|
||||||
let video = Video.local(model.replacePrivateVar(url) ?? url)
|
let video = Video.local(model.standardizedURL(url) ?? url)
|
||||||
PlayerQueueRow(
|
PlayerQueueRow(
|
||||||
item: PlayerQueueItem(video)
|
item: PlayerQueueItem(video)
|
||||||
)
|
)
|
||||||
|
@ -11,7 +11,7 @@ struct RecentDocumentsView: View {
|
|||||||
NoDocumentsView()
|
NoDocumentsView()
|
||||||
} else {
|
} else {
|
||||||
ForEach(recentDocuments, id: \.absoluteString) { url in
|
ForEach(recentDocuments, id: \.absoluteString) { url in
|
||||||
let video = Video.local(model.replacePrivateVar(url) ?? url)
|
let video = Video.local(model.standardizedURL(url) ?? url)
|
||||||
PlayerQueueRow(
|
PlayerQueueRow(
|
||||||
item: PlayerQueueItem(video)
|
item: PlayerQueueItem(video)
|
||||||
)
|
)
|
||||||
|
@ -95,7 +95,10 @@ struct ContentView: View {
|
|||||||
|
|
||||||
NavigationModel.shared.presentingOpenVideos = false
|
NavigationModel.shared.presentingOpenVideos = false
|
||||||
}
|
}
|
||||||
.onOpenURL(perform: OpenURLHandler.shared.handle)
|
.onOpenURL { url in
|
||||||
|
URLBookmarkModel.shared.saveBookmark(url)
|
||||||
|
OpenURLHandler.shared.handle(url)
|
||||||
|
}
|
||||||
.background(
|
.background(
|
||||||
EmptyView().sheet(isPresented: $navigation.presentingAddToPlaylist) {
|
EmptyView().sheet(isPresented: $navigation.presentingAddToPlaylist) {
|
||||||
AddToPlaylistView(video: navigation.videoToAddToPlaylist)
|
AddToPlaylistView(video: navigation.videoToAddToPlaylist)
|
||||||
|
@ -36,7 +36,7 @@ struct OpenURLHandler {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
guard let url = urlByReplacingYatteeProtocol(url) else { return }
|
guard let url = url.byReplacingYatteeProtocol() else { return }
|
||||||
|
|
||||||
let parser = URLParser(url: url)
|
let parser = URLParser(url: url)
|
||||||
|
|
||||||
@ -93,21 +93,6 @@ struct OpenURLHandler {
|
|||||||
navigation.presentingOpenVideos = false
|
navigation.presentingOpenVideos = false
|
||||||
}
|
}
|
||||||
|
|
||||||
private func urlByReplacingYatteeProtocol(_ url: URL, with urlProtocol: String = "https") -> URL! {
|
|
||||||
var urlAbsoluteString = url.absoluteString
|
|
||||||
|
|
||||||
guard urlAbsoluteString.hasPrefix(Self.yatteeProtocol) else {
|
|
||||||
return url
|
|
||||||
}
|
|
||||||
|
|
||||||
urlAbsoluteString = String(urlAbsoluteString.dropFirst(Self.yatteeProtocol.count))
|
|
||||||
if url.absoluteString.contains("://") {
|
|
||||||
return URL(string: urlAbsoluteString)
|
|
||||||
}
|
|
||||||
|
|
||||||
return URL(string: "\(urlProtocol)://\(urlAbsoluteString)")
|
|
||||||
}
|
|
||||||
|
|
||||||
private func handleFileURLOpen(_ parser: URLParser) {
|
private func handleFileURLOpen(_ parser: URLParser) {
|
||||||
guard let url = parser.fileURL else { return }
|
guard let url = parser.fileURL else { return }
|
||||||
|
|
||||||
|
@ -109,7 +109,10 @@ struct VideoPlayerView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.alert(isPresented: $navigation.presentingAlertInVideoPlayer) { navigation.alert }
|
.alert(isPresented: $navigation.presentingAlertInVideoPlayer) { navigation.alert }
|
||||||
.onOpenURL(perform: OpenURLHandler.shared.handle)
|
.onOpenURL { url in
|
||||||
|
URLBookmarkModel.shared.saveBookmark(url)
|
||||||
|
OpenURLHandler.shared.handle(url)
|
||||||
|
}
|
||||||
.frame(minWidth: 950, minHeight: 700)
|
.frame(minWidth: 950, minHeight: 700)
|
||||||
#else
|
#else
|
||||||
return GeometryReader { geometry in
|
return GeometryReader { geometry in
|
||||||
|
@ -911,6 +911,11 @@
|
|||||||
37FD43E42704847C0073EE42 /* View+Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD43E22704847C0073EE42 /* View+Fixtures.swift */; };
|
37FD43E42704847C0073EE42 /* View+Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD43E22704847C0073EE42 /* View+Fixtures.swift */; };
|
||||||
37FD43E52704847C0073EE42 /* View+Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD43E22704847C0073EE42 /* View+Fixtures.swift */; };
|
37FD43E52704847C0073EE42 /* View+Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD43E22704847C0073EE42 /* View+Fixtures.swift */; };
|
||||||
37FD43F02704A9C00073EE42 /* RecentsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C194C626F6A9C8005D3B96 /* RecentsModel.swift */; };
|
37FD43F02704A9C00073EE42 /* RecentsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C194C626F6A9C8005D3B96 /* RecentsModel.swift */; };
|
||||||
|
37FD77002932C4DA00D91A5F /* URL+ByReplacingYatteeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD76FF2932C4DA00D91A5F /* URL+ByReplacingYatteeProtocol.swift */; };
|
||||||
|
37FD77012932C4DA00D91A5F /* URL+ByReplacingYatteeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD76FF2932C4DA00D91A5F /* URL+ByReplacingYatteeProtocol.swift */; };
|
||||||
|
37FD77022932C4DA00D91A5F /* URL+ByReplacingYatteeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD76FF2932C4DA00D91A5F /* URL+ByReplacingYatteeProtocol.swift */; };
|
||||||
|
37FD77032932C5EC00D91A5F /* URL+ByReplacingYatteeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD76FF2932C4DA00D91A5F /* URL+ByReplacingYatteeProtocol.swift */; };
|
||||||
|
37FD77042932C5FC00D91A5F /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3754B01428B7F84D009717C8 /* Constants.swift */; };
|
||||||
37FEF11327EFD8580033912F /* PlaceholderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FEF11227EFD8580033912F /* PlaceholderCell.swift */; };
|
37FEF11327EFD8580033912F /* PlaceholderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FEF11227EFD8580033912F /* PlaceholderCell.swift */; };
|
||||||
37FEF11427EFD8580033912F /* PlaceholderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FEF11227EFD8580033912F /* PlaceholderCell.swift */; };
|
37FEF11427EFD8580033912F /* PlaceholderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FEF11227EFD8580033912F /* PlaceholderCell.swift */; };
|
||||||
37FEF11527EFD8580033912F /* PlaceholderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FEF11227EFD8580033912F /* PlaceholderCell.swift */; };
|
37FEF11527EFD8580033912F /* PlaceholderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FEF11227EFD8580033912F /* PlaceholderCell.swift */; };
|
||||||
@ -1367,6 +1372,7 @@
|
|||||||
37FB285D272225E800A57617 /* ContentItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentItemView.swift; sourceTree = "<group>"; };
|
37FB285D272225E800A57617 /* ContentItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentItemView.swift; sourceTree = "<group>"; };
|
||||||
37FD43DB270470B70073EE42 /* InstancesSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstancesSettings.swift; sourceTree = "<group>"; };
|
37FD43DB270470B70073EE42 /* InstancesSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstancesSettings.swift; sourceTree = "<group>"; };
|
||||||
37FD43E22704847C0073EE42 /* View+Fixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Fixtures.swift"; sourceTree = "<group>"; };
|
37FD43E22704847C0073EE42 /* View+Fixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Fixtures.swift"; sourceTree = "<group>"; };
|
||||||
|
37FD76FF2932C4DA00D91A5F /* URL+ByReplacingYatteeProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+ByReplacingYatteeProtocol.swift"; sourceTree = "<group>"; };
|
||||||
37FEF11227EFD8580033912F /* PlaceholderCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderCell.swift; sourceTree = "<group>"; };
|
37FEF11227EFD8580033912F /* PlaceholderCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderCell.swift; sourceTree = "<group>"; };
|
||||||
37FFC43F272734C3009FFD26 /* Throttle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Throttle.swift; sourceTree = "<group>"; };
|
37FFC43F272734C3009FFD26 /* Throttle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Throttle.swift; sourceTree = "<group>"; };
|
||||||
3DA101AD287C30F50027D920 /* DEVELOPMENT_TEAM.template.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = DEVELOPMENT_TEAM.template.xcconfig; sourceTree = "<group>"; };
|
3DA101AD287C30F50027D920 /* DEVELOPMENT_TEAM.template.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = DEVELOPMENT_TEAM.template.xcconfig; sourceTree = "<group>"; };
|
||||||
@ -2048,11 +2054,12 @@
|
|||||||
3782B95C2755858100990149 /* NSTextField+FocusRingType.swift */,
|
3782B95C2755858100990149 /* NSTextField+FocusRingType.swift */,
|
||||||
377ABC47286E5887009C986F /* Sequence+Unique.swift */,
|
377ABC47286E5887009C986F /* Sequence+Unique.swift */,
|
||||||
3782B9512755667600990149 /* String+Format.swift */,
|
3782B9512755667600990149 /* String+Format.swift */,
|
||||||
|
37270F1B28E06E3E00856150 /* String+Localizable.swift */,
|
||||||
377A20A82693C9A2002842B8 /* TypedContentAccessors.swift */,
|
377A20A82693C9A2002842B8 /* TypedContentAccessors.swift */,
|
||||||
37F7AB4C28A9361F00FB46B5 /* UIDevice+Cellular.swift */,
|
37F7AB4C28A9361F00FB46B5 /* UIDevice+Cellular.swift */,
|
||||||
370B79CB286279BA0045DB77 /* UIViewController+HideHomeIndicator.swift */,
|
370B79CB286279BA0045DB77 /* UIViewController+HideHomeIndicator.swift */,
|
||||||
|
37FD76FF2932C4DA00D91A5F /* URL+ByReplacingYatteeProtocol.swift */,
|
||||||
3743CA51270F284F00E4D32B /* View+Borders.swift */,
|
3743CA51270F284F00E4D32B /* View+Borders.swift */,
|
||||||
37270F1B28E06E3E00856150 /* String+Localizable.swift */,
|
|
||||||
);
|
);
|
||||||
path = Extensions;
|
path = Extensions;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -2812,8 +2819,10 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
37FD77042932C5FC00D91A5F /* Constants.swift in Sources */,
|
||||||
37095E8E291DD5FE00301883 /* CacheModel.swift in Sources */,
|
37095E8E291DD5FE00301883 /* CacheModel.swift in Sources */,
|
||||||
37095E82291DC85400301883 /* ShareViewController.swift in Sources */,
|
37095E82291DC85400301883 /* ShareViewController.swift in Sources */,
|
||||||
|
37FD77032932C5EC00D91A5F /* URL+ByReplacingYatteeProtocol.swift in Sources */,
|
||||||
37095E8D291DD5DA00301883 /* URLBookmarkModel.swift in Sources */,
|
37095E8D291DD5DA00301883 /* URLBookmarkModel.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
@ -2940,6 +2949,7 @@
|
|||||||
37E64DD126D597EB00C71877 /* SubscriptionsModel.swift in Sources */,
|
37E64DD126D597EB00C71877 /* SubscriptionsModel.swift in Sources */,
|
||||||
376578892685471400D4EA09 /* Playlist.swift in Sources */,
|
376578892685471400D4EA09 /* Playlist.swift in Sources */,
|
||||||
37B4E803277D0A72004BF56A /* AppDelegate.swift in Sources */,
|
37B4E803277D0A72004BF56A /* AppDelegate.swift in Sources */,
|
||||||
|
37FD77002932C4DA00D91A5F /* URL+ByReplacingYatteeProtocol.swift in Sources */,
|
||||||
373CFADB269663F1003CB2C6 /* Thumbnail.swift in Sources */,
|
373CFADB269663F1003CB2C6 /* Thumbnail.swift in Sources */,
|
||||||
3714166F267A8ACC006CA35D /* TrendingView.swift in Sources */,
|
3714166F267A8ACC006CA35D /* TrendingView.swift in Sources */,
|
||||||
3782B9522755667600990149 /* String+Format.swift in Sources */,
|
3782B9522755667600990149 /* String+Format.swift in Sources */,
|
||||||
@ -3089,6 +3099,7 @@
|
|||||||
37BE0BDC26A2367F0092E2DB /* AppleAVPlayerView.swift in Sources */,
|
37BE0BDC26A2367F0092E2DB /* AppleAVPlayerView.swift in Sources */,
|
||||||
3743CA53270F284F00E4D32B /* View+Borders.swift in Sources */,
|
3743CA53270F284F00E4D32B /* View+Borders.swift in Sources */,
|
||||||
37599F39272B4D740087F250 /* FavoriteButton.swift in Sources */,
|
37599F39272B4D740087F250 /* FavoriteButton.swift in Sources */,
|
||||||
|
37FD77012932C4DA00D91A5F /* URL+ByReplacingYatteeProtocol.swift in Sources */,
|
||||||
374924F129216C630017D862 /* VideoActions.swift in Sources */,
|
374924F129216C630017D862 /* VideoActions.swift in Sources */,
|
||||||
37C3A24627235DA70087A57A /* ChannelPlaylist.swift in Sources */,
|
37C3A24627235DA70087A57A /* ChannelPlaylist.swift in Sources */,
|
||||||
37CEE4BE2677B670005A1EFE /* SingleAssetStream.swift in Sources */,
|
37CEE4BE2677B670005A1EFE /* SingleAssetStream.swift in Sources */,
|
||||||
@ -3519,6 +3530,7 @@
|
|||||||
37C069802725C8D400F7F6CB /* CMTime+DefaultTimescale.swift in Sources */,
|
37C069802725C8D400F7F6CB /* CMTime+DefaultTimescale.swift in Sources */,
|
||||||
37EBD8CC27AF26C200F1C24B /* MPVBackend.swift in Sources */,
|
37EBD8CC27AF26C200F1C24B /* MPVBackend.swift in Sources */,
|
||||||
3711404126B206A6005B3555 /* SearchModel.swift in Sources */,
|
3711404126B206A6005B3555 /* SearchModel.swift in Sources */,
|
||||||
|
37FD77022932C4DA00D91A5F /* URL+ByReplacingYatteeProtocol.swift in Sources */,
|
||||||
37FEF11527EFD8580033912F /* PlaceholderCell.swift in Sources */,
|
37FEF11527EFD8580033912F /* PlaceholderCell.swift in Sources */,
|
||||||
37FD43F02704A9C00073EE42 /* RecentsModel.swift in Sources */,
|
37FD43F02704A9C00073EE42 /* RecentsModel.swift in Sources */,
|
||||||
379775952689365600DD52A8 /* Array+Next.swift in Sources */,
|
379775952689365600DD52A8 /* Array+Next.swift in Sources */,
|
||||||
|
Loading…
Reference in New Issue
Block a user