Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 76 additions & 20 deletions ownCloud/Settings/LogFilesViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
*/

import UIKit
import CoreServices

import ownCloudSDK
import ownCloudApp
import ownCloudAppShared

class LogFileTableViewCell : ThemeTableViewCell {
Expand Down Expand Up @@ -57,7 +60,7 @@ extension OCLogFileRecord {
}
}

class LogFilesViewController : UITableViewController, Themeable {
class LogFilesViewController : UITableViewController, UITableViewDragDelegate, Themeable {

var logRecords = [OCLogFileRecord]()

Expand Down Expand Up @@ -87,6 +90,8 @@ class LogFilesViewController : UITableViewController, Themeable {
super.viewDidLoad()
Theme.shared.register(client: self, applyImmediately: true)
self.tableView.register(LogFileTableViewCell.self, forCellReuseIdentifier: LogFileTableViewCell.identifier)
self.tableView.dragDelegate = self
self.tableView.dragInteractionEnabled = true
self.title = "Log Files".localized
}

Expand Down Expand Up @@ -165,6 +170,40 @@ class LogFilesViewController : UITableViewController, Themeable {
]
}

// MARK: - Table view drag & drop support
func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
if DisplaySettings.shared.preventDraggingFiles {
return [UIDragItem]()
}

var logURL : URL?
var logName : String?

provideLogURL(at: indexPath, makeNamedCopy: false) { (url, name, completionHandler) in
logURL = url
logName = name

// Since we use false for makeNamedCopy, this should be safe
completionHandler?()
}

if let logURL = logURL {
let itemProvider = NSItemProvider()
itemProvider.registerFileRepresentation(forTypeIdentifier: kUTTypeUTF8PlainText as String, fileOptions: [], visibility: .all, loadHandler: { (completionHandler) -> Progress? in
completionHandler(logURL, true, nil)
return nil
})
itemProvider.suggestedName = logName

let dragItem = UIDragItem(itemProvider: itemProvider)

return [dragItem]
}

return [UIDragItem]()
}


// MARK: - Private Helpers

private func populateLogFileList() {
Expand All @@ -179,8 +218,8 @@ class LogFilesViewController : UITableViewController, Themeable {
self.tableView.reloadData()
}
}

private func shareLogRecord(at indexPath:IndexPath, sender: UITableViewCell) {
private func provideLogURL(at indexPath: IndexPath, makeNamedCopy: Bool, completionHandler: (_ fileURL: URL?, _ name: String?, _ doneBlock: (()->Void)?) -> Void) {
let logRecord = self.logRecords[indexPath.row]

// Create a file name for sharing with format ownCloud_<date>_<time>.log.txt
Expand All @@ -192,31 +231,48 @@ class LogFilesViewController : UITableViewController, Themeable {

}
let shareableFileName = "ownCloud_" + time + ".log.txt"

if makeNamedCopy {
let shareableLogURL = FileManager.default.temporaryDirectory.appendingPathComponent(shareableFileName)

do {
if FileManager.default.fileExists(atPath: shareableLogURL.path) {
try FileManager.default.removeItem(at: shareableLogURL)
}

let shareableLogURL = FileManager.default.temporaryDirectory.appendingPathComponent(shareableFileName)
try FileManager.default.copyItem(atPath: logRecord.url.path, toPath: shareableLogURL.path)
} catch {
Log.error("Error providing copy of log \(logRecord.url.path) at \(shareableLogURL.path): \(error)")
}

completionHandler(shareableLogURL, shareableFileName, {
try? FileManager.default.removeItem(at: shareableLogURL)
})
} else {
completionHandler(logRecord.url, shareableFileName, nil)
}
}

do {
if FileManager.default.fileExists(atPath: shareableLogURL.path) {
try FileManager.default.removeItem(at: shareableLogURL)
private func shareLogRecord(at indexPath:IndexPath, sender: UITableViewCell) {
provideLogURL(at: indexPath, makeNamedCopy: true) { (shareableLogURL, fileName, completionHandler) in
guard let shareableLogURL = shareableLogURL else {
completionHandler?()
return
}

try FileManager.default.copyItem(atPath: logRecord.url.path, toPath: shareableLogURL.path)
} catch {
}
let shareViewController = UIActivityViewController(activityItems: [shareableLogURL], applicationActivities:nil)

let shareViewController = UIActivityViewController(activityItems: [shareableLogURL], applicationActivities:nil)
shareViewController.completionWithItemsHandler = { (_, _, _, _) in
do {
try FileManager.default.removeItem(at: shareableLogURL)
} catch {
shareViewController.completionWithItemsHandler = { (_, _, _, _) in
completionHandler?()
}

if UIDevice.current.isIpad {
shareViewController.popoverPresentationController?.sourceView = sender
shareViewController.popoverPresentationController?.sourceRect = sender.frame
}
}

if UIDevice.current.isIpad {
shareViewController.popoverPresentationController?.sourceView = sender
shareViewController.popoverPresentationController?.sourceRect = sender.frame
self.present(shareViewController, animated: true, completion: nil)
}
self.present(shareViewController, animated: true, completion: nil)
}

private func removeLogRecord(at indexPath:IndexPath) {
Expand Down
113 changes: 91 additions & 22 deletions ownCloudAppShared/Client/File Lists/ClientQueryViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ open class ClientQueryViewController: QueryFileListTableViewController, UIDropIn
weak public var clientRootViewController : UIViewController?

private var _actionProgressHandler : ActionProgressHandler?

private let ItemDataUTI = "com.owncloud.ios-app.item-data"

// MARK: - Init & Deinit
public override convenience init(core inCore: OCCore, query inQuery: OCQuery) {
Expand Down Expand Up @@ -476,10 +478,38 @@ extension ClientQueryViewController: UITableViewDropDelegate {
}
}
}
// Import Items from outside
} else {
guard let UTI = item.dragItem.itemProvider.registeredTypeIdentifiers.last else { return }
item.dragItem.itemProvider.loadFileRepresentation(forTypeIdentifier: UTI) { (url, _ error) in
// Import Items from outside
let typeIdentifiers = item.dragItem.itemProvider.registeredTypeIdentifiers
let preferredUTIs = [
kUTTypeImage,
kUTTypeMovie,
kUTTypePDF,
kUTTypeData
]
var useUTI : String?
var useIndex : Int = Int.max

for typeIdentifier in typeIdentifiers {
if typeIdentifier != ItemDataUTI, !typeIdentifier.hasPrefix("dyn.") {
for preferredUTI in preferredUTIs {
let conforms = UTTypeConformsTo(typeIdentifier as CFString, preferredUTI)

// Log.log("\(preferredUTI) vs \(typeIdentifier) -> \(conforms)")

if conforms {
if let utiIndex = preferredUTIs.index(of: preferredUTI), utiIndex < useIndex {
useUTI = typeIdentifier
useIndex = utiIndex
}
}
}
}
}

guard let loadUTI = useUTI else { return }

item.dragItem.itemProvider.loadFileRepresentation(forTypeIdentifier: loadUTI) { (url, _ error) in
guard let url = url else { return }
self.upload(itemURL: url, name: url.lastPathComponent)
}
Expand Down Expand Up @@ -561,38 +591,77 @@ extension ClientQueryViewController: UITableViewDragDelegate {

public func itemForDragging(draggingValue : OCItemDraggingValue) -> UIDragItem? {
let item = draggingValue.item
if let core = self.core {
switch item.type {

guard let core = self.core else {
return nil
}

switch item.type {
case .collection:
guard let data = item.serializedData() else { return nil }
let itemProvider = NSItemProvider(item: data as NSData, typeIdentifier: kUTTypeData as String)

let itemProvider = NSItemProvider(item: data as NSData, typeIdentifier: ItemDataUTI)
let dragItem = UIDragItem(itemProvider: itemProvider)

dragItem.localObject = draggingValue

return dragItem

case .file:
guard let itemMimeType = item.mimeType else { return nil }

let mimeTypeCF = itemMimeType as CFString
guard let rawUti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeTypeCF, nil)?.takeRetainedValue() as String? else { return nil }

let itemProvider = NSItemProvider()

itemProvider.suggestedName = item.name

itemProvider.registerFileRepresentation(forTypeIdentifier: rawUti, fileOptions: [], visibility: .all, loadHandler: { [weak core] (completionHandler) -> Progress? in
var progress : Progress?

guard let core = core else {
completionHandler(nil, false, NSError(domain: OCErrorDomain, code: Int(OCError.internal.rawValue), userInfo: nil))
return nil
}

if let localFileURL = core.localCopy(of: item) {
// Provide local copies directly
completionHandler(localFileURL, true, nil)
} else {
// Otherwise download the file and provide it when done
progress = core.downloadItem(item, options: [
.returnImmediatelyIfOfflineOrUnavailable : true,
.addTemporaryClaimForPurpose : OCCoreClaimPurpose.view.rawValue
], resultHandler: { [weak self] (error, core, item, file) in
guard error == nil, let fileURL = file?.url else {
completionHandler(nil, false, error)
return
}

completionHandler(fileURL, true, nil)

guard let rawUti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeTypeCF, nil)?.takeRetainedValue() else { return nil }
if let claim = file?.claim, let item = item, let self = self {
self.core?.remove(claim, on: item, afterDeallocationOf: [fileURL])
}
})
}

return progress
})

if let fileData = NSData(contentsOf: core.localURL(for: item)) {
let rawUtiString = rawUti as String
let itemProvider = NSItemProvider(item: fileData, typeIdentifier: rawUtiString)
itemProvider.suggestedName = item.name
let dragItem = UIDragItem(itemProvider: itemProvider)
dragItem.localObject = draggingValue
return dragItem
} else {
itemProvider.registerDataRepresentation(forTypeIdentifier: ItemDataUTI, visibility: .ownProcess) { (completionHandler) -> Progress? in
guard let data = item.serializedData() else { return nil }
let itemProvider = NSItemProvider(item: data as NSData, typeIdentifier: kUTTypeData as String)
let dragItem = UIDragItem(itemProvider: itemProvider)
dragItem.localObject = draggingValue
return dragItem
completionHandler(data, nil)

return nil
}
}
}

return nil
let dragItem = UIDragItem(itemProvider: itemProvider)
dragItem.localObject = draggingValue

return dragItem
}
}
}

Expand Down