Implement drag and drop feed arrangement.
This commit is contained in:
parent
56d43f8f2d
commit
f818a1618f
|
@ -90,6 +90,9 @@
|
||||||
515D4FC123257A3200EE1167 /* FolderTreeControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97A11ED9F180007D329B /* FolderTreeControllerDelegate.swift */; };
|
515D4FC123257A3200EE1167 /* FolderTreeControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97A11ED9F180007D329B /* FolderTreeControllerDelegate.swift */; };
|
||||||
515D4FCA23257CB500EE1167 /* Node-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97971ED9EFAA007D329B /* Node-Extensions.swift */; };
|
515D4FCA23257CB500EE1167 /* Node-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97971ED9EFAA007D329B /* Node-Extensions.swift */; };
|
||||||
515D4FCC2325815A00EE1167 /* SafariExt.js in Resources */ = {isa = PBXBuildFile; fileRef = 515D4FCB2325815A00EE1167 /* SafariExt.js */; };
|
515D4FCC2325815A00EE1167 /* SafariExt.js in Resources */ = {isa = PBXBuildFile; fileRef = 515D4FCB2325815A00EE1167 /* SafariExt.js */; };
|
||||||
|
51627A6723861DA3007B3B4B /* MasterFeedViewController+Drag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51627A6623861DA3007B3B4B /* MasterFeedViewController+Drag.swift */; };
|
||||||
|
51627A6923861DED007B3B4B /* MasterFeedViewController+Drop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51627A6823861DED007B3B4B /* MasterFeedViewController+Drop.swift */; };
|
||||||
|
51627A6B238629D8007B3B4B /* MasterFeedDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51627A6A238629D8007B3B4B /* MasterFeedDataSource.swift */; };
|
||||||
516A093723609A3600EAE89B /* SettingsAccountTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 516A091D23609A3600EAE89B /* SettingsAccountTableViewCell.xib */; };
|
516A093723609A3600EAE89B /* SettingsAccountTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 516A091D23609A3600EAE89B /* SettingsAccountTableViewCell.xib */; };
|
||||||
516A09392360A2AE00EAE89B /* SettingsAccountTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 516A09382360A2AE00EAE89B /* SettingsAccountTableViewCell.swift */; };
|
516A09392360A2AE00EAE89B /* SettingsAccountTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 516A09382360A2AE00EAE89B /* SettingsAccountTableViewCell.swift */; };
|
||||||
516A093B2360A4A000EAE89B /* SettingsTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 516A093A2360A4A000EAE89B /* SettingsTableViewCell.xib */; };
|
516A093B2360A4A000EAE89B /* SettingsTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 516A093A2360A4A000EAE89B /* SettingsTableViewCell.xib */; };
|
||||||
|
@ -212,7 +215,6 @@
|
||||||
51C452AF2265108300C03939 /* ArticleArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F204DF1FAACBB30076E152 /* ArticleArray.swift */; };
|
51C452AF2265108300C03939 /* ArticleArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F204DF1FAACBB30076E152 /* ArticleArray.swift */; };
|
||||||
51C452B42265141B00C03939 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51C452B32265141B00C03939 /* WebKit.framework */; };
|
51C452B42265141B00C03939 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51C452B32265141B00C03939 /* WebKit.framework */; };
|
||||||
51C452B82265178500C03939 /* styleSheet.css in Resources */ = {isa = PBXBuildFile; fileRef = 51C452B72265178500C03939 /* styleSheet.css */; };
|
51C452B82265178500C03939 /* styleSheet.css in Resources */ = {isa = PBXBuildFile; fileRef = 51C452B72265178500C03939 /* styleSheet.css */; };
|
||||||
51CC9B3E231720B2000E842F /* MasterFeedDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51CC9B3D231720B2000E842F /* MasterFeedDataSource.swift */; };
|
|
||||||
51CE1C0923621EDA005548FC /* RefreshProgressView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 51CE1C0823621EDA005548FC /* RefreshProgressView.xib */; };
|
51CE1C0923621EDA005548FC /* RefreshProgressView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 51CE1C0823621EDA005548FC /* RefreshProgressView.xib */; };
|
||||||
51CE1C0B23622007005548FC /* RefreshProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51CE1C0A23622006005548FC /* RefreshProgressView.swift */; };
|
51CE1C0B23622007005548FC /* RefreshProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51CE1C0A23622006005548FC /* RefreshProgressView.swift */; };
|
||||||
51CE1C712367721A005548FC /* testURLsOfCurrentArticle.applescript in Sources */ = {isa = PBXBuildFile; fileRef = 84F9EADB213660A100CF2DE4 /* testURLsOfCurrentArticle.applescript */; };
|
51CE1C712367721A005548FC /* testURLsOfCurrentArticle.applescript in Sources */ = {isa = PBXBuildFile; fileRef = 84F9EADB213660A100CF2DE4 /* testURLsOfCurrentArticle.applescript */; };
|
||||||
|
@ -1266,6 +1268,9 @@
|
||||||
515D4FCB2325815A00EE1167 /* SafariExt.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = SafariExt.js; sourceTree = "<group>"; };
|
515D4FCB2325815A00EE1167 /* SafariExt.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = SafariExt.js; sourceTree = "<group>"; };
|
||||||
515D4FCD2325909200EE1167 /* NetNewsWire_iOS_ShareExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NetNewsWire_iOS_ShareExtension.entitlements; sourceTree = "<group>"; };
|
515D4FCD2325909200EE1167 /* NetNewsWire_iOS_ShareExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NetNewsWire_iOS_ShareExtension.entitlements; sourceTree = "<group>"; };
|
||||||
515D4FCE2325B3D000EE1167 /* NetNewsWire_iOSshareextension_target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = NetNewsWire_iOSshareextension_target.xcconfig; sourceTree = "<group>"; };
|
515D4FCE2325B3D000EE1167 /* NetNewsWire_iOSshareextension_target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = NetNewsWire_iOSshareextension_target.xcconfig; sourceTree = "<group>"; };
|
||||||
|
51627A6623861DA3007B3B4B /* MasterFeedViewController+Drag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MasterFeedViewController+Drag.swift"; sourceTree = "<group>"; };
|
||||||
|
51627A6823861DED007B3B4B /* MasterFeedViewController+Drop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MasterFeedViewController+Drop.swift"; sourceTree = "<group>"; };
|
||||||
|
51627A6A238629D8007B3B4B /* MasterFeedDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MasterFeedDataSource.swift; sourceTree = "<group>"; };
|
||||||
516A091D23609A3600EAE89B /* SettingsAccountTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SettingsAccountTableViewCell.xib; sourceTree = "<group>"; };
|
516A091D23609A3600EAE89B /* SettingsAccountTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SettingsAccountTableViewCell.xib; sourceTree = "<group>"; };
|
||||||
516A09382360A2AE00EAE89B /* SettingsAccountTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsAccountTableViewCell.swift; sourceTree = "<group>"; };
|
516A09382360A2AE00EAE89B /* SettingsAccountTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsAccountTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
516A093A2360A4A000EAE89B /* SettingsTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SettingsTableViewCell.xib; sourceTree = "<group>"; };
|
516A093A2360A4A000EAE89B /* SettingsTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SettingsTableViewCell.xib; sourceTree = "<group>"; };
|
||||||
|
@ -1326,7 +1331,6 @@
|
||||||
51C4528B2265095F00C03939 /* AddFolderViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddFolderViewController.swift; sourceTree = "<group>"; };
|
51C4528B2265095F00C03939 /* AddFolderViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddFolderViewController.swift; sourceTree = "<group>"; };
|
||||||
51C452B32265141B00C03939 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/WebKit.framework; sourceTree = DEVELOPER_DIR; };
|
51C452B32265141B00C03939 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/WebKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||||
51C452B72265178500C03939 /* styleSheet.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = styleSheet.css; sourceTree = "<group>"; };
|
51C452B72265178500C03939 /* styleSheet.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = styleSheet.css; sourceTree = "<group>"; };
|
||||||
51CC9B3D231720B2000E842F /* MasterFeedDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MasterFeedDataSource.swift; sourceTree = "<group>"; };
|
|
||||||
51CE1C0823621EDA005548FC /* RefreshProgressView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RefreshProgressView.xib; sourceTree = "<group>"; };
|
51CE1C0823621EDA005548FC /* RefreshProgressView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RefreshProgressView.xib; sourceTree = "<group>"; };
|
||||||
51CE1C0A23622006005548FC /* RefreshProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshProgressView.swift; sourceTree = "<group>"; };
|
51CE1C0A23622006005548FC /* RefreshProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshProgressView.swift; sourceTree = "<group>"; };
|
||||||
51D6A5BB23199C85001C27D8 /* MasterTimelineDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MasterTimelineDataSource.swift; sourceTree = "<group>"; };
|
51D6A5BB23199C85001C27D8 /* MasterTimelineDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MasterTimelineDataSource.swift; sourceTree = "<group>"; };
|
||||||
|
@ -1875,7 +1879,9 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
51C45264226508F600C03939 /* MasterFeedViewController.swift */,
|
51C45264226508F600C03939 /* MasterFeedViewController.swift */,
|
||||||
51CC9B3D231720B2000E842F /* MasterFeedDataSource.swift */,
|
51627A6A238629D8007B3B4B /* MasterFeedDataSource.swift */,
|
||||||
|
51627A6623861DA3007B3B4B /* MasterFeedViewController+Drag.swift */,
|
||||||
|
51627A6823861DED007B3B4B /* MasterFeedViewController+Drop.swift */,
|
||||||
51CE1C0A23622006005548FC /* RefreshProgressView.swift */,
|
51CE1C0A23622006005548FC /* RefreshProgressView.swift */,
|
||||||
51CE1C0823621EDA005548FC /* RefreshProgressView.xib */,
|
51CE1C0823621EDA005548FC /* RefreshProgressView.xib */,
|
||||||
51C45260226508F600C03939 /* Cell */,
|
51C45260226508F600C03939 /* Cell */,
|
||||||
|
@ -3976,6 +3982,7 @@
|
||||||
51F85BF722749FA100C787DC /* UIFont-Extensions.swift in Sources */,
|
51F85BF722749FA100C787DC /* UIFont-Extensions.swift in Sources */,
|
||||||
51C452AF2265108300C03939 /* ArticleArray.swift in Sources */,
|
51C452AF2265108300C03939 /* ArticleArray.swift in Sources */,
|
||||||
51C4528E2265099C00C03939 /* SmartFeedsController.swift in Sources */,
|
51C4528E2265099C00C03939 /* SmartFeedsController.swift in Sources */,
|
||||||
|
51627A6B238629D8007B3B4B /* MasterFeedDataSource.swift in Sources */,
|
||||||
51102165233A7D6C0007A5F7 /* ArticleExtractorButton.swift in Sources */,
|
51102165233A7D6C0007A5F7 /* ArticleExtractorButton.swift in Sources */,
|
||||||
5141E7392373C18B0013FF27 /* WebFeedInspectorViewController.swift in Sources */,
|
5141E7392373C18B0013FF27 /* WebFeedInspectorViewController.swift in Sources */,
|
||||||
5108F6D42375EEEF001ABC45 /* TimelinePreviewTableViewController.swift in Sources */,
|
5108F6D42375EEEF001ABC45 /* TimelinePreviewTableViewController.swift in Sources */,
|
||||||
|
@ -4001,6 +4008,7 @@
|
||||||
51934CCE2310792F006127BE /* ActivityManager.swift in Sources */,
|
51934CCE2310792F006127BE /* ActivityManager.swift in Sources */,
|
||||||
5108F6B72375E612001ABC45 /* CacheCleaner.swift in Sources */,
|
5108F6B72375E612001ABC45 /* CacheCleaner.swift in Sources */,
|
||||||
518651DA235621840078E021 /* ImageTransition.swift in Sources */,
|
518651DA235621840078E021 /* ImageTransition.swift in Sources */,
|
||||||
|
51627A6923861DED007B3B4B /* MasterFeedViewController+Drop.swift in Sources */,
|
||||||
514219372352510100E07E2C /* ImageScrollView.swift in Sources */,
|
514219372352510100E07E2C /* ImageScrollView.swift in Sources */,
|
||||||
516AE9B32371C372007DEEAA /* MasterFeedTableViewSectionHeaderLayout.swift in Sources */,
|
516AE9B32371C372007DEEAA /* MasterFeedTableViewSectionHeaderLayout.swift in Sources */,
|
||||||
51C4529B22650A1000C03939 /* FaviconDownloader.swift in Sources */,
|
51C4529B22650A1000C03939 /* FaviconDownloader.swift in Sources */,
|
||||||
|
@ -4012,12 +4020,12 @@
|
||||||
51C4529F22650A1900C03939 /* AuthorAvatarDownloader.swift in Sources */,
|
51C4529F22650A1900C03939 /* AuthorAvatarDownloader.swift in Sources */,
|
||||||
5108F6D22375EED2001ABC45 /* TimelineCustomizerViewController.swift in Sources */,
|
5108F6D22375EED2001ABC45 /* TimelineCustomizerViewController.swift in Sources */,
|
||||||
519E743D22C663F900A78E47 /* SceneDelegate.swift in Sources */,
|
519E743D22C663F900A78E47 /* SceneDelegate.swift in Sources */,
|
||||||
51CC9B3E231720B2000E842F /* MasterFeedDataSource.swift in Sources */,
|
|
||||||
FFD43E412340F488009E5CA3 /* UndoAvailableAlertController.swift in Sources */,
|
FFD43E412340F488009E5CA3 /* UndoAvailableAlertController.swift in Sources */,
|
||||||
51C452A322650A1E00C03939 /* HTMLMetadataDownloader.swift in Sources */,
|
51C452A322650A1E00C03939 /* HTMLMetadataDownloader.swift in Sources */,
|
||||||
51C4528D2265095F00C03939 /* AddFolderViewController.swift in Sources */,
|
51C4528D2265095F00C03939 /* AddFolderViewController.swift in Sources */,
|
||||||
51C452782265091600C03939 /* MasterTimelineCellData.swift in Sources */,
|
51C452782265091600C03939 /* MasterTimelineCellData.swift in Sources */,
|
||||||
5148F4552336DB7000F8CD8B /* MasterTimelineTitleView.swift in Sources */,
|
5148F4552336DB7000F8CD8B /* MasterTimelineTitleView.swift in Sources */,
|
||||||
|
51627A6723861DA3007B3B4B /* MasterFeedViewController+Drag.swift in Sources */,
|
||||||
51FFF0C4235EE8E5002762AA /* VibrantButton.swift in Sources */,
|
51FFF0C4235EE8E5002762AA /* VibrantButton.swift in Sources */,
|
||||||
513228FC233037630033D4ED /* Reachability.swift in Sources */,
|
513228FC233037630033D4ED /* Reachability.swift in Sources */,
|
||||||
51C45259226508D300C03939 /* AppDefaults.swift in Sources */,
|
51C45259226508D300C03939 /* AppDefaults.swift in Sources */,
|
||||||
|
|
|
@ -14,12 +14,10 @@ import Account
|
||||||
class MasterFeedDataSource: UITableViewDiffableDataSource<Node, Node> {
|
class MasterFeedDataSource: UITableViewDiffableDataSource<Node, Node> {
|
||||||
|
|
||||||
private var coordinator: SceneCoordinator!
|
private var coordinator: SceneCoordinator!
|
||||||
private var errorHandler: ((Error) -> ())!
|
|
||||||
|
|
||||||
init(coordinator: SceneCoordinator, errorHandler: @escaping (Error) -> (), tableView: UITableView, cellProvider: @escaping UITableViewDiffableDataSource<Node, Node>.CellProvider) {
|
init(coordinator: SceneCoordinator, tableView: UITableView, cellProvider: @escaping UITableViewDiffableDataSource<Node, Node>.CellProvider) {
|
||||||
super.init(tableView: tableView, cellProvider: cellProvider)
|
super.init(tableView: tableView, cellProvider: cellProvider)
|
||||||
self.coordinator = coordinator
|
self.coordinator = coordinator
|
||||||
self.errorHandler = errorHandler
|
|
||||||
self.defaultRowAnimation = .middle
|
self.defaultRowAnimation = .middle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,140 +28,4 @@ class MasterFeedDataSource: UITableViewDiffableDataSource<Node, Node> {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
|
|
||||||
guard let node = itemIdentifier(for: indexPath) else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return node.representedObject is WebFeed
|
|
||||||
}
|
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
|
|
||||||
|
|
||||||
guard let sourceNode = itemIdentifier(for: sourceIndexPath), let webFeed = sourceNode.representedObject as? WebFeed else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Based on the drop we have to determine a node to start looking for a parent container.
|
|
||||||
let destNode: Node = {
|
|
||||||
if destinationIndexPath.row == 0 {
|
|
||||||
return coordinator.rootNode.childAtIndex(destinationIndexPath.section)!
|
|
||||||
} else {
|
|
||||||
let movementAdjustment = sourceIndexPath > destinationIndexPath ? 1 : 0
|
|
||||||
let adjustedDestIndexPath = IndexPath(row: destinationIndexPath.row - movementAdjustment, section: destinationIndexPath.section)
|
|
||||||
return itemIdentifier(for: adjustedDestIndexPath)!
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Now we start looking for the parent container
|
|
||||||
let destParentNode: Node? = {
|
|
||||||
if destNode.representedObject is Container {
|
|
||||||
return destNode
|
|
||||||
} else {
|
|
||||||
if destNode.parent?.representedObject is Container {
|
|
||||||
return destNode.parent!
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Move the Web Feed
|
|
||||||
guard let source = sourceNode.parent?.representedObject as? Container, let destination = destParentNode?.representedObject as? Container else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if sameAccount(sourceNode, destParentNode!) {
|
|
||||||
moveWebFeedInAccount(feed: webFeed, sourceContainer: source, destinationContainer: destination)
|
|
||||||
} else {
|
|
||||||
moveWebFeedBetweenAccounts(feed: webFeed, sourceContainer: source, destinationContainer: destination)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private func sameAccount(_ node: Node, _ parentNode: Node) -> Bool {
|
|
||||||
if let accountID = nodeAccountID(node), let parentAccountID = nodeAccountID(parentNode) {
|
|
||||||
if accountID == parentAccountID {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private func nodeAccount(_ node: Node) -> Account? {
|
|
||||||
if let account = node.representedObject as? Account {
|
|
||||||
return account
|
|
||||||
} else if let folder = node.representedObject as? Folder {
|
|
||||||
return folder.account
|
|
||||||
} else if let webFeed = node.representedObject as? WebFeed {
|
|
||||||
return webFeed.account
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private func nodeAccountID(_ node: Node) -> String? {
|
|
||||||
return nodeAccount(node)?.accountID
|
|
||||||
}
|
|
||||||
|
|
||||||
func moveWebFeedInAccount(feed: WebFeed, sourceContainer: Container, destinationContainer: Container) {
|
|
||||||
BatchUpdate.shared.start()
|
|
||||||
sourceContainer.account?.moveWebFeed(feed, from: sourceContainer, to: destinationContainer) { result in
|
|
||||||
BatchUpdate.shared.end()
|
|
||||||
switch result {
|
|
||||||
case .success:
|
|
||||||
break
|
|
||||||
case .failure(let error):
|
|
||||||
self.errorHandler(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func moveWebFeedBetweenAccounts(feed: WebFeed, sourceContainer: Container, destinationContainer: Container) {
|
|
||||||
|
|
||||||
if let existingFeed = destinationContainer.account?.existingWebFeed(withURL: feed.url) {
|
|
||||||
|
|
||||||
BatchUpdate.shared.start()
|
|
||||||
destinationContainer.account?.addWebFeed(existingFeed, to: destinationContainer) { result in
|
|
||||||
switch result {
|
|
||||||
case .success:
|
|
||||||
sourceContainer.account?.removeWebFeed(feed, from: sourceContainer) { result in
|
|
||||||
BatchUpdate.shared.end()
|
|
||||||
switch result {
|
|
||||||
case .success:
|
|
||||||
break
|
|
||||||
case .failure(let error):
|
|
||||||
self.errorHandler(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case .failure(let error):
|
|
||||||
BatchUpdate.shared.end()
|
|
||||||
self.errorHandler(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
BatchUpdate.shared.start()
|
|
||||||
destinationContainer.account?.createWebFeed(url: feed.url, name: feed.editedName, container: destinationContainer) { result in
|
|
||||||
switch result {
|
|
||||||
case .success:
|
|
||||||
sourceContainer.account?.removeWebFeed(feed, from: sourceContainer) { result in
|
|
||||||
BatchUpdate.shared.end()
|
|
||||||
switch result {
|
|
||||||
case .success:
|
|
||||||
break
|
|
||||||
case .failure(let error):
|
|
||||||
self.errorHandler(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case .failure(let error):
|
|
||||||
BatchUpdate.shared.end()
|
|
||||||
self.errorHandler(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
//
|
||||||
|
// MasterFeedViewController+Drag.swift
|
||||||
|
// NetNewsWire-iOS
|
||||||
|
//
|
||||||
|
// Created by Maurice Parker on 11/20/19.
|
||||||
|
// Copyright © 2019 Ranchero Software. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import MobileCoreServices
|
||||||
|
import Account
|
||||||
|
|
||||||
|
extension MasterFeedViewController: UITableViewDragDelegate {
|
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
|
||||||
|
guard let node = dataSource.itemIdentifier(for: indexPath), let webFeed = node.representedObject as? WebFeed else {
|
||||||
|
return [UIDragItem]()
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = webFeed.url.data(using: .utf8)
|
||||||
|
let itemProvider = NSItemProvider()
|
||||||
|
|
||||||
|
itemProvider.registerDataRepresentation(forTypeIdentifier: kUTTypeURL as String, visibility: .all) { completion in
|
||||||
|
completion(data, nil)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let dragItem = UIDragItem(itemProvider: itemProvider)
|
||||||
|
dragItem.localObject = node
|
||||||
|
return [dragItem]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -17,7 +17,7 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner {
|
||||||
private var refreshProgressView: RefreshProgressView?
|
private var refreshProgressView: RefreshProgressView?
|
||||||
private var addNewItemButton: UIBarButtonItem!
|
private var addNewItemButton: UIBarButtonItem!
|
||||||
|
|
||||||
private lazy var dataSource = makeDataSource()
|
lazy var dataSource = makeDataSource()
|
||||||
var undoableCommands = [UndoableCommand]()
|
var undoableCommands = [UndoableCommand]()
|
||||||
weak var coordinator: SceneCoordinator!
|
weak var coordinator: SceneCoordinator!
|
||||||
|
|
||||||
|
@ -38,8 +38,6 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner {
|
||||||
navigationController?.navigationBar.prefersLargeTitles = true
|
navigationController?.navigationBar.prefersLargeTitles = true
|
||||||
}
|
}
|
||||||
|
|
||||||
navigationItem.rightBarButtonItem = editButtonItem
|
|
||||||
|
|
||||||
// Set the bar button item so that it doesn't show on the timeline view
|
// Set the bar button item so that it doesn't show on the timeline view
|
||||||
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
|
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
|
||||||
|
|
||||||
|
@ -51,6 +49,9 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner {
|
||||||
|
|
||||||
tableView.register(MasterFeedTableViewSectionHeader.self, forHeaderFooterViewReuseIdentifier: "SectionHeader")
|
tableView.register(MasterFeedTableViewSectionHeader.self, forHeaderFooterViewReuseIdentifier: "SectionHeader")
|
||||||
tableView.dataSource = dataSource
|
tableView.dataSource = dataSource
|
||||||
|
tableView.dragDelegate = self
|
||||||
|
tableView.dropDelegate = self
|
||||||
|
tableView.dragInteractionEnabled = true
|
||||||
resetEstimatedRowHeight()
|
resetEstimatedRowHeight()
|
||||||
tableView.separatorStyle = .none
|
tableView.separatorStyle = .none
|
||||||
|
|
||||||
|
@ -630,7 +631,7 @@ private extension MasterFeedViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeDataSource() -> UITableViewDiffableDataSource<Node, Node> {
|
func makeDataSource() -> UITableViewDiffableDataSource<Node, Node> {
|
||||||
return MasterFeedDataSource(coordinator: coordinator, errorHandler: ErrorHandler.present(self), tableView: tableView, cellProvider: { [weak self] tableView, indexPath, node in
|
return MasterFeedDataSource(coordinator: coordinator, tableView: tableView, cellProvider: { [weak self] tableView, indexPath, node in
|
||||||
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! MasterFeedTableViewCell
|
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! MasterFeedTableViewCell
|
||||||
self?.configure(cell, node)
|
self?.configure(cell, node)
|
||||||
return cell
|
return cell
|
||||||
|
|
Loading…
Reference in New Issue