Make progress on drag and drop. Reads feeds from pasteboard. This needs refactoring, though.
This commit is contained in:
parent
f29f690625
commit
089ffbd299
|
@ -26,6 +26,18 @@ extension Feed: PasteboardWriterOwner {
|
||||||
static let feedUTIInternal = "com.ranchero.NetNewsWire-Evergreen.internal.feed"
|
static let feedUTIInternal = "com.ranchero.NetNewsWire-Evergreen.internal.feed"
|
||||||
static let feedUTIInternalType = NSPasteboard.PasteboardType(rawValue: feedUTIInternal)
|
static let feedUTIInternalType = NSPasteboard.PasteboardType(rawValue: feedUTIInternal)
|
||||||
|
|
||||||
|
private struct Key {
|
||||||
|
|
||||||
|
static let url = "URL"
|
||||||
|
static let homePageURL = "homePageURL"
|
||||||
|
static let name = "name"
|
||||||
|
|
||||||
|
// Internal
|
||||||
|
static let accountID = "accountID"
|
||||||
|
static let feedID = "feedID"
|
||||||
|
static let editedName = "editedName"
|
||||||
|
}
|
||||||
|
|
||||||
init(feed: Feed) {
|
init(feed: Feed) {
|
||||||
|
|
||||||
self.feed = feed
|
self.feed = feed
|
||||||
|
@ -57,23 +69,20 @@ extension Feed: PasteboardWriterOwner {
|
||||||
|
|
||||||
return plist
|
return plist
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Dragged Feed
|
||||||
|
|
||||||
|
static func draggedFeeds(with pasteboard: NSPasteboard) -> Set<DraggedFeed>? {
|
||||||
|
guard let items = pasteboard.pasteboardItems else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
let feeds = items.compactMap { draggedFeed(with: $0) }
|
||||||
|
return feeds.isEmpty ? nil : Set(feeds)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension FeedPasteboardWriter {
|
private extension FeedPasteboardWriter {
|
||||||
|
|
||||||
private struct Key {
|
|
||||||
|
|
||||||
static let url = "URL"
|
|
||||||
static let homePageURL = "homePageURL"
|
|
||||||
static let name = "name"
|
|
||||||
|
|
||||||
// Internal
|
|
||||||
static let accountID = "accountID"
|
|
||||||
static let feedID = "feedID"
|
|
||||||
static let editedName = "editedName"
|
|
||||||
static let unreadCount = "unreadCount"
|
|
||||||
}
|
|
||||||
|
|
||||||
func exportDictionary() -> [String: String] {
|
func exportDictionary() -> [String: String] {
|
||||||
|
|
||||||
var d = [String: String]()
|
var d = [String: String]()
|
||||||
|
@ -100,11 +109,51 @@ private extension FeedPasteboardWriter {
|
||||||
if let editedName = feed.editedName {
|
if let editedName = feed.editedName {
|
||||||
d[Key.editedName] = editedName
|
d[Key.editedName] = editedName
|
||||||
}
|
}
|
||||||
if feed.unreadCount > 0 {
|
if let accountID = feed.account?.accountID {
|
||||||
d[Key.unreadCount] = feed.unreadCount
|
d[Key.accountID] = accountID
|
||||||
}
|
}
|
||||||
|
|
||||||
return d
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
static func draggedFeed(with dictionary: [String: String]) -> DraggedFeed? {
|
||||||
|
guard let url = dictionary[Key.url] else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
let homePageURL = dictionary[Key.homePageURL]
|
||||||
|
let name = dictionary[Key.name]
|
||||||
|
let accountID = dictionary[Key.accountID]
|
||||||
|
let feedID = dictionary[Key.feedID]
|
||||||
|
let editedName = dictionary[Key.editedName]
|
||||||
|
|
||||||
|
return DraggedFeed(url: url, feedID: feedID, homePageURL: homePageURL, name: name, editedName: editedName, accountID: accountID)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func draggedFeed(with pasteboardItem: NSPasteboardItem) -> DraggedFeed? {
|
||||||
|
|
||||||
|
// TODO: This needs to handle strings and URLs also.
|
||||||
|
var pasteboardType: NSPasteboard.PasteboardType?
|
||||||
|
if pasteboardItem.types.contains(FeedPasteboardWriter.feedUTIInternalType) {
|
||||||
|
pasteboardType = FeedPasteboardWriter.feedUTIInternalType
|
||||||
|
}
|
||||||
|
else if pasteboardItem.types.contains(FeedPasteboardWriter.feedUTIType) {
|
||||||
|
pasteboardType = FeedPasteboardWriter.feedUTIType
|
||||||
|
}
|
||||||
|
guard let foundType = pasteboardType else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let feedDictionary = pasteboardItem.propertyList(forType: foundType) as! [String: String]
|
||||||
|
return draggedFeed(with: feedDictionary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DraggedFeed: Hashable {
|
||||||
|
|
||||||
|
let url: String
|
||||||
|
let feedID: String?
|
||||||
|
let homePageURL: String?
|
||||||
|
let name: String?
|
||||||
|
let editedName: String?
|
||||||
|
let accountID: String?
|
||||||
|
}
|
||||||
|
|
|
@ -25,21 +25,21 @@ import Account
|
||||||
|
|
||||||
func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
|
func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
|
||||||
|
|
||||||
return nodeForItem(item as AnyObject?).numberOfChildNodes
|
return nodeForItem(item).numberOfChildNodes
|
||||||
}
|
}
|
||||||
|
|
||||||
func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
|
func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
|
||||||
|
|
||||||
return nodeForItem(item as AnyObject?).childNodes[index]
|
return nodeForItem(item).childNodes[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
|
func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
|
||||||
|
|
||||||
return nodeForItem(item as AnyObject?).canHaveChildNodes
|
return nodeForItem(item).canHaveChildNodes
|
||||||
}
|
}
|
||||||
|
|
||||||
func outlineView(_ outlineView: NSOutlineView, pasteboardWriterForItem item: Any) -> NSPasteboardWriting? {
|
func outlineView(_ outlineView: NSOutlineView, pasteboardWriterForItem item: Any) -> NSPasteboardWriting? {
|
||||||
let node = nodeForItem(item as AnyObject?)
|
let node = nodeForItem(item)
|
||||||
guard nodeRepresentsDraggableItem(node) else {
|
guard nodeRepresentsDraggableItem(node) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -49,10 +49,29 @@ import Account
|
||||||
// MARK: - Drag and Drop
|
// MARK: - Drag and Drop
|
||||||
|
|
||||||
func outlineView(_ outlineView: NSOutlineView, validateDrop info: NSDraggingInfo, proposedItem item: Any?, proposedChildIndex index: Int) -> NSDragOperation {
|
func outlineView(_ outlineView: NSOutlineView, validateDrop info: NSDraggingInfo, proposedItem item: Any?, proposedChildIndex index: Int) -> NSDragOperation {
|
||||||
|
let parentNode = nodeForItem(item)
|
||||||
|
if parentNode == treeController.rootNode {
|
||||||
|
return SidebarOutlineDataSource.dragOperationNone
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let draggedFeeds = FeedPasteboardWriter.draggedFeeds(with: info.draggingPasteboard()) else {
|
||||||
|
return SidebarOutlineDataSource.dragOperationNone
|
||||||
|
}
|
||||||
|
|
||||||
let draggingSourceOutlineView = info.draggingSource() as? NSOutlineView
|
let draggingSourceOutlineView = info.draggingSource() as? NSOutlineView
|
||||||
let isLocalDrop = draggingSourceOutlineView == outlineView
|
let isLocalDrop = draggingSourceOutlineView == outlineView
|
||||||
|
|
||||||
|
// // If NSOutlineViewDropOnItemIndex, retarget to parent of parent item, if possible.
|
||||||
|
// if index == NSOutlineViewDropOnItemIndex && !parentNode.canHaveChildNodes {
|
||||||
|
// guard let grandparentNode = parentNode.parent, grandparentNode.canHaveChildNodes else {
|
||||||
|
// return SidebarOutlineDataSource.dragOperationNone
|
||||||
|
// }
|
||||||
|
// outlineView.setDropItem(grandparentNode, dropChildIndex: NSOutlineViewDropOnItemIndex)
|
||||||
|
// return isLocalDrop ? .move : .copy
|
||||||
|
// }
|
||||||
|
|
||||||
if isLocalDrop {
|
if isLocalDrop {
|
||||||
return validateLocalDrop(info, proposedItem: item, proposedChildIndex: index)
|
return validateLocalDrop(draggedFeeds, proposedItem: item, proposedChildIndex: index)
|
||||||
}
|
}
|
||||||
return SidebarOutlineDataSource.dragOperationNone
|
return SidebarOutlineDataSource.dragOperationNone
|
||||||
}
|
}
|
||||||
|
@ -66,8 +85,7 @@ import Account
|
||||||
|
|
||||||
private extension SidebarOutlineDataSource {
|
private extension SidebarOutlineDataSource {
|
||||||
|
|
||||||
func nodeForItem(_ item: AnyObject?) -> Node {
|
func nodeForItem(_ item: Any?) -> Node {
|
||||||
|
|
||||||
if item == nil {
|
if item == nil {
|
||||||
return treeController.rootNode
|
return treeController.rootNode
|
||||||
}
|
}
|
||||||
|
@ -82,10 +100,10 @@ private extension SidebarOutlineDataSource {
|
||||||
return node.representedObject is Feed
|
return node.representedObject is Feed
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateLocalDrop(_ info: NSDraggingInfo, proposedItem item: Any?, proposedChildIndex index: Int) -> NSDragOperation {
|
func validateLocalDrop(_ draggedFeeds: Set<DraggedFeed>, proposedItem item: Any?, proposedChildIndex index: Int) -> NSDragOperation {
|
||||||
|
|
||||||
|
// let parentNode = nodeForItem(item)
|
||||||
|
|
||||||
// let node = nodeForItem(item)
|
|
||||||
return SidebarOutlineDataSource.dragOperationNone
|
return SidebarOutlineDataSource.dragOperationNone
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue