2017-11-08 06:14:58 +01:00
|
|
|
//
|
2018-09-20 22:29:01 +02:00
|
|
|
// PasteboardFeed.swift
|
2018-08-29 07:18:24 +02:00
|
|
|
// NetNewsWire
|
2017-11-08 06:14:58 +01:00
|
|
|
//
|
2018-09-20 22:29:01 +02:00
|
|
|
// Created by Brent Simmons on 9/20/18.
|
|
|
|
// Copyright © 2018 Ranchero Software. All rights reserved.
|
2017-11-08 06:14:58 +01:00
|
|
|
//
|
|
|
|
|
2018-02-03 07:51:32 +01:00
|
|
|
import AppKit
|
2018-07-24 03:29:08 +02:00
|
|
|
import Articles
|
2018-07-28 21:16:14 +02:00
|
|
|
import Account
|
2018-02-12 07:10:28 +01:00
|
|
|
import RSCore
|
|
|
|
|
2019-11-15 03:11:41 +01:00
|
|
|
typealias PasteboardWebFeedDictionary = [String: String]
|
2018-09-20 22:29:01 +02:00
|
|
|
|
2019-11-15 03:11:41 +01:00
|
|
|
struct PasteboardWebFeed: Hashable {
|
2018-09-20 22:29:01 +02:00
|
|
|
|
|
|
|
private struct Key {
|
|
|
|
static let url = "URL"
|
|
|
|
static let homePageURL = "homePageURL"
|
|
|
|
static let name = "name"
|
|
|
|
|
|
|
|
// Internal
|
|
|
|
static let accountID = "accountID"
|
2019-05-27 22:11:16 +02:00
|
|
|
static let accountType = "accountType"
|
2019-11-15 03:11:41 +01:00
|
|
|
static let webFeedID = "webFeedID"
|
2018-09-20 22:29:01 +02:00
|
|
|
static let editedName = "editedName"
|
|
|
|
}
|
|
|
|
|
|
|
|
let url: String
|
2019-11-15 03:11:41 +01:00
|
|
|
let webFeedID: String?
|
2018-09-20 22:29:01 +02:00
|
|
|
let homePageURL: String?
|
|
|
|
let name: String?
|
|
|
|
let editedName: String?
|
|
|
|
let accountID: String?
|
2019-05-27 22:11:16 +02:00
|
|
|
let accountType: AccountType?
|
2018-09-22 20:54:02 +02:00
|
|
|
let isLocalFeed: Bool
|
2018-09-20 22:29:01 +02:00
|
|
|
|
2019-11-15 03:11:41 +01:00
|
|
|
init(url: String, webFeedID: String?, homePageURL: String?, name: String?, editedName: String?, accountID: String?, accountType: AccountType?) {
|
2018-09-22 06:37:20 +02:00
|
|
|
self.url = url.rs_normalizedURL()
|
2019-11-15 03:11:41 +01:00
|
|
|
self.webFeedID = webFeedID
|
2018-09-22 06:37:20 +02:00
|
|
|
self.homePageURL = homePageURL?.rs_normalizedURL()
|
2018-09-20 22:29:01 +02:00
|
|
|
self.name = name
|
|
|
|
self.editedName = editedName
|
|
|
|
self.accountID = accountID
|
2019-05-27 22:11:16 +02:00
|
|
|
self.accountType = accountType
|
2018-09-22 20:54:02 +02:00
|
|
|
self.isLocalFeed = accountID != nil
|
2018-09-20 22:29:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - Reading
|
|
|
|
|
2019-11-15 03:11:41 +01:00
|
|
|
init?(dictionary: PasteboardWebFeedDictionary) {
|
2018-09-20 22:29:01 +02:00
|
|
|
guard let url = dictionary[Key.url] else {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
let homePageURL = dictionary[Key.homePageURL]
|
|
|
|
let name = dictionary[Key.name]
|
|
|
|
let accountID = dictionary[Key.accountID]
|
2019-11-15 03:11:41 +01:00
|
|
|
let webFeedID = dictionary[Key.webFeedID]
|
2018-09-20 22:29:01 +02:00
|
|
|
let editedName = dictionary[Key.editedName]
|
|
|
|
|
2019-05-27 22:11:16 +02:00
|
|
|
var accountType: AccountType? = nil
|
|
|
|
if let accountTypeString = dictionary[Key.accountType], let accountTypeInt = Int(accountTypeString) {
|
|
|
|
accountType = AccountType(rawValue: accountTypeInt)
|
|
|
|
}
|
|
|
|
|
2019-11-15 03:11:41 +01:00
|
|
|
self.init(url: url, webFeedID: webFeedID, homePageURL: homePageURL, name: name, editedName: editedName, accountID: accountID, accountType: accountType)
|
2018-09-20 22:29:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
init?(pasteboardItem: NSPasteboardItem) {
|
|
|
|
var pasteboardType: NSPasteboard.PasteboardType?
|
2019-11-15 03:11:41 +01:00
|
|
|
if pasteboardItem.types.contains(WebFeedPasteboardWriter.webFeedUTIInternalType) {
|
|
|
|
pasteboardType = WebFeedPasteboardWriter.webFeedUTIInternalType
|
2018-09-20 22:29:01 +02:00
|
|
|
}
|
2019-11-15 03:11:41 +01:00
|
|
|
else if pasteboardItem.types.contains(WebFeedPasteboardWriter.webFeedUTIType) {
|
|
|
|
pasteboardType = WebFeedPasteboardWriter.webFeedUTIType
|
2018-09-20 22:29:01 +02:00
|
|
|
}
|
2018-09-22 06:37:20 +02:00
|
|
|
if let foundType = pasteboardType {
|
2019-11-15 03:11:41 +01:00
|
|
|
if let feedDictionary = pasteboardItem.propertyList(forType: foundType) as? PasteboardWebFeedDictionary {
|
2018-09-22 06:37:20 +02:00
|
|
|
self.init(dictionary: feedDictionary)
|
|
|
|
return
|
|
|
|
}
|
2018-09-20 22:29:01 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-09-22 06:37:20 +02:00
|
|
|
// Check for URL or a string that may be a URL.
|
|
|
|
if pasteboardItem.types.contains(.URL) {
|
|
|
|
pasteboardType = .URL
|
|
|
|
}
|
|
|
|
else if pasteboardItem.types.contains(.string) {
|
|
|
|
pasteboardType = .string
|
|
|
|
}
|
|
|
|
if let foundType = pasteboardType {
|
|
|
|
if let possibleURLString = pasteboardItem.string(forType: foundType) {
|
|
|
|
if possibleURLString.rs_stringMayBeURL() {
|
2019-11-15 03:11:41 +01:00
|
|
|
self.init(url: possibleURLString, webFeedID: nil, homePageURL: nil, name: nil, editedName: nil, accountID: nil, accountType: nil)
|
2018-09-22 06:37:20 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2018-09-20 22:29:01 +02:00
|
|
|
}
|
|
|
|
|
2018-09-22 06:37:20 +02:00
|
|
|
return nil
|
2018-09-20 22:29:01 +02:00
|
|
|
}
|
|
|
|
|
2019-11-15 03:11:41 +01:00
|
|
|
static func pasteboardFeeds(with pasteboard: NSPasteboard) -> Set<PasteboardWebFeed>? {
|
2018-09-20 22:29:01 +02:00
|
|
|
guard let items = pasteboard.pasteboardItems else {
|
|
|
|
return nil
|
|
|
|
}
|
2019-11-15 03:11:41 +01:00
|
|
|
let webFeeds = items.compactMap { PasteboardWebFeed(pasteboardItem: $0) }
|
|
|
|
return webFeeds.isEmpty ? nil : Set(webFeeds)
|
2018-09-20 22:29:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - Writing
|
|
|
|
|
2019-11-15 03:11:41 +01:00
|
|
|
func exportDictionary() -> PasteboardWebFeedDictionary {
|
|
|
|
var d = PasteboardWebFeedDictionary()
|
2018-09-20 22:29:01 +02:00
|
|
|
d[Key.url] = url
|
|
|
|
d[Key.homePageURL] = homePageURL ?? ""
|
|
|
|
if let nameForDisplay = editedName ?? name {
|
|
|
|
d[Key.name] = nameForDisplay
|
|
|
|
}
|
|
|
|
return d
|
|
|
|
}
|
|
|
|
|
2019-11-15 03:11:41 +01:00
|
|
|
func internalDictionary() -> PasteboardWebFeedDictionary {
|
|
|
|
var d = PasteboardWebFeedDictionary()
|
|
|
|
d[PasteboardWebFeed.Key.webFeedID] = webFeedID
|
|
|
|
d[PasteboardWebFeed.Key.url] = url
|
2018-09-20 22:29:01 +02:00
|
|
|
if let homePageURL = homePageURL {
|
2019-11-15 03:11:41 +01:00
|
|
|
d[PasteboardWebFeed.Key.homePageURL] = homePageURL
|
2018-09-20 22:29:01 +02:00
|
|
|
}
|
|
|
|
if let name = name {
|
2019-11-15 03:11:41 +01:00
|
|
|
d[PasteboardWebFeed.Key.name] = name
|
2018-09-20 22:29:01 +02:00
|
|
|
}
|
|
|
|
if let editedName = editedName {
|
2019-11-15 03:11:41 +01:00
|
|
|
d[PasteboardWebFeed.Key.editedName] = editedName
|
2018-09-20 22:29:01 +02:00
|
|
|
}
|
|
|
|
if let accountID = accountID {
|
2019-11-15 03:11:41 +01:00
|
|
|
d[PasteboardWebFeed.Key.accountID] = accountID
|
2018-09-20 22:29:01 +02:00
|
|
|
}
|
2019-05-27 22:11:16 +02:00
|
|
|
if let accountType = accountType {
|
2019-11-15 03:11:41 +01:00
|
|
|
d[PasteboardWebFeed.Key.accountType] = String(accountType.rawValue)
|
2019-05-27 22:11:16 +02:00
|
|
|
}
|
2018-09-20 22:29:01 +02:00
|
|
|
return d
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-15 03:11:41 +01:00
|
|
|
extension WebFeed: PasteboardWriterOwner {
|
2018-02-12 07:10:28 +01:00
|
|
|
|
|
|
|
public var pasteboardWriter: NSPasteboardWriting {
|
2019-11-15 03:11:41 +01:00
|
|
|
return WebFeedPasteboardWriter(webFeed: self)
|
2018-02-12 07:10:28 +01:00
|
|
|
}
|
|
|
|
}
|
2017-11-08 06:14:58 +01:00
|
|
|
|
2019-11-15 03:11:41 +01:00
|
|
|
@objc final class WebFeedPasteboardWriter: NSObject, NSPasteboardWriting {
|
2017-11-08 06:14:58 +01:00
|
|
|
|
2019-11-15 03:11:41 +01:00
|
|
|
private let webFeed: WebFeed
|
|
|
|
static let webFeedUTI = "com.ranchero.webFeed"
|
|
|
|
static let webFeedUTIType = NSPasteboard.PasteboardType(rawValue: webFeedUTI)
|
|
|
|
static let webFeedUTIInternal = "com.ranchero.NetNewsWire-Evergreen.internal.webFeed"
|
|
|
|
static let webFeedUTIInternalType = NSPasteboard.PasteboardType(rawValue: webFeedUTIInternal)
|
2017-11-08 06:14:58 +01:00
|
|
|
|
2018-09-20 06:49:13 +02:00
|
|
|
|
2019-11-15 03:11:41 +01:00
|
|
|
init(webFeed: WebFeed) {
|
|
|
|
self.webFeed = webFeed
|
2017-11-08 06:14:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - NSPasteboardWriting
|
|
|
|
|
|
|
|
func writableTypes(for pasteboard: NSPasteboard) -> [NSPasteboard.PasteboardType] {
|
|
|
|
|
2019-11-15 03:11:41 +01:00
|
|
|
return [WebFeedPasteboardWriter.webFeedUTIType, .URL, .string, WebFeedPasteboardWriter.webFeedUTIInternalType]
|
2017-11-08 06:14:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func pasteboardPropertyList(forType type: NSPasteboard.PasteboardType) -> Any? {
|
|
|
|
|
|
|
|
let plist: Any?
|
|
|
|
|
|
|
|
switch type {
|
|
|
|
case .string:
|
2019-11-15 03:11:41 +01:00
|
|
|
plist = webFeed.nameForDisplay
|
2017-11-08 06:14:58 +01:00
|
|
|
case .URL:
|
2019-11-15 03:11:41 +01:00
|
|
|
plist = webFeed.url
|
|
|
|
case WebFeedPasteboardWriter.webFeedUTIType:
|
2019-02-06 06:00:10 +01:00
|
|
|
plist = exportDictionary
|
2019-11-15 03:11:41 +01:00
|
|
|
case WebFeedPasteboardWriter.webFeedUTIInternalType:
|
2019-02-06 06:00:10 +01:00
|
|
|
plist = internalDictionary
|
2017-11-08 06:14:58 +01:00
|
|
|
default:
|
|
|
|
plist = nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return plist
|
|
|
|
}
|
2018-09-20 06:49:13 +02:00
|
|
|
}
|
|
|
|
|
2019-11-15 03:11:41 +01:00
|
|
|
private extension WebFeedPasteboardWriter {
|
2017-11-08 06:14:58 +01:00
|
|
|
|
2019-11-15 03:11:41 +01:00
|
|
|
var pasteboardFeed: PasteboardWebFeed {
|
|
|
|
return PasteboardWebFeed(url: webFeed.url, webFeedID: webFeed.webFeedID, homePageURL: webFeed.homePageURL, name: webFeed.name, editedName: webFeed.editedName, accountID: webFeed.account?.accountID, accountType: webFeed.account?.type)
|
2019-02-06 06:00:10 +01:00
|
|
|
}
|
|
|
|
|
2019-11-15 03:11:41 +01:00
|
|
|
var exportDictionary: PasteboardWebFeedDictionary {
|
2018-09-20 22:29:01 +02:00
|
|
|
return pasteboardFeed.exportDictionary()
|
2017-11-08 06:14:58 +01:00
|
|
|
}
|
|
|
|
|
2019-11-15 03:11:41 +01:00
|
|
|
var internalDictionary: PasteboardWebFeedDictionary {
|
2018-09-20 22:29:01 +02:00
|
|
|
return pasteboardFeed.internalDictionary()
|
2018-09-20 06:49:13 +02:00
|
|
|
}
|
|
|
|
}
|