Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[fix/improve_photo_upload_responsiveness] More reliable photo upload #548

Merged
merged 30 commits into from
Dec 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0d50a47
#516 truncate middle of file name instead of tail (#517)
hosy Oct 7, 2019
c8d779d
new app version and build version
hosy Oct 7, 2019
461f8cd
Started implementing more secure photo upload
mneuwert Oct 7, 2019
15bc127
Added a fix for background media playback
mneuwert Oct 7, 2019
897c055
Fixed naming of uploaded edited photos
mneuwert Oct 7, 2019
73008c8
Merge remote-tracking branch 'origin/release/1.1.1' into fix/improve_…
mneuwert Oct 8, 2019
618dbda
Changes to the mechanism of storing pending PHAsset IDs
mneuwert Oct 8, 2019
e8f6077
Pending media upload task added
mneuwert Oct 9, 2019
c8905e5
Updated with latest sdk version
mneuwert Oct 18, 2019
b3c1f32
Uploading multiple assets within OCCore.schedul(inCoreQueue:) block
mneuwert Oct 21, 2019
bd97e97
Fixed some issues with uploading pending assets
mneuwert Oct 21, 2019
a667a2d
Reworked media uploads
mneuwert Oct 24, 2019
0d5950d
Small fixes
mneuwert Oct 24, 2019
b798981
Refactored PendingMediaUploadTaskExtension class
mneuwert Oct 25, 2019
d6e49e4
Removed unccessary scheduling of tasks in the next run loop iteration
mneuwert Oct 25, 2019
7d04ea5
Modal UI presented when media files are imported
mneuwert Oct 29, 2019
e0398c0
Fixed some review findings
mneuwert Oct 31, 2019
58cf97f
Addressed review findings
mneuwert Oct 31, 2019
c53a027
Ignoring fastlane sub-folder
mneuwert Oct 31, 2019
bb80b4b
Merge branch 'milestone/1.2' into fix/improve_photo_upload_responsive…
mneuwert Oct 31, 2019
b1463cf
Fixed some compiler warnings
mneuwert Oct 31, 2019
2a8a001
Fixed the issue with overwriting asset downloads
mneuwert Nov 18, 2019
40f6170
Added OCActivitiy publishing to MediaUploadQueue
mneuwert Nov 18, 2019
3c882ce
Refactored media upload related OCActivity into separate class
mneuwert Nov 19, 2019
5aac386
First working implementation of refactored MediaUploadQueue
mneuwert Nov 22, 2019
2af1d1f
Removing stored upload jobs upon activity cancellation
mneuwert Nov 22, 2019
897fb64
MediaUploadQueue:
felix-schwarz Nov 28, 2019
d2be04c
- Remove duplicate file
felix-schwarz Nov 28, 2019
1c7a287
Merge remote-tracking branch 'origin/milestone/1.2' into fix/improve_…
felix-schwarz Nov 28, 2019
674334a
Fixed problem with updating key-value store for every single media asset
mneuwert Dec 5, 2019
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
12 changes: 12 additions & 0 deletions ownCloud.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,13 @@
39E98B3E22797D1B009911F1 /* PublicLinkTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39E98B3D22797D1B009911F1 /* PublicLinkTableViewController.swift */; };
39E98B452279ACF5009911F1 /* PublicLinkEditTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39E98B442279ACF5009911F1 /* PublicLinkEditTableViewController.swift */; };
46B9D336BF7FE50321823888 /* Pods_ownCloudScreenshotsTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 54199937F74A129BC74DEB0A /* Pods_ownCloudScreenshotsTests.framework */; };
4C05D8A5238708D40073EF50 /* MediaUploadStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C05D8A4238708D40073EF50 /* MediaUploadStorage.swift */; };
4C11EE5B22E88D4200B84869 /* InstantMediaUploadTaskExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C11EE5A22E88D4200B84869 /* InstantMediaUploadTaskExtension.swift */; };
4C1561E8222321E0009C4EF3 /* PhotoSelectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1561E7222321E0009C4EF3 /* PhotoSelectionViewController.swift */; };
4C1561EF22232357009C4EF3 /* PhotoSelectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1561EE22232357009C4EF3 /* PhotoSelectionViewCell.swift */; };
4C16CBA7226F0F1A00D67BB6 /* FileTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C16CBA6226F0F1900D67BB6 /* FileTests.swift */; };
4C235CEE21F88C0300A989A8 /* UIViewController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C235CED21F88C0300A989A8 /* UIViewController+Extension.swift */; };
4C3E17DB234DBF9A000D7BA8 /* PendingMediaUploadTaskExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3E17DA234DBF9A000D7BA8 /* PendingMediaUploadTaskExtension.swift */; };
4C464BEF2187AF1500D30602 /* PDFThumbnailCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C464BE12187AF1400D30602 /* PDFThumbnailCollectionViewCell.swift */; };
4C464BF02187AF1500D30602 /* PDFTocTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C464BE82187AF1400D30602 /* PDFTocTableViewController.swift */; };
4C464BF12187AF1500D30602 /* PDFTocTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C464BE92187AF1400D30602 /* PDFTocTableViewCell.swift */; };
Expand All @@ -95,6 +97,7 @@
4C7295D8228C384E00FA4E68 /* LogFilesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C7295D7228C384E00FA4E68 /* LogFilesViewController.swift */; };
4C82D07022C9387300835F0B /* MediaDisplayViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C82D06F22C9387300835F0B /* MediaDisplayViewController.swift */; };
4C88041822E78D790016CBA9 /* MediaFilesSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C88041722E78D790016CBA9 /* MediaFilesSettings.swift */; };
4C96463C238489E4003278B7 /* MediaUploadActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C96463B238489E4003278B7 /* MediaUploadActivity.swift */; };
4C9BFA2323158C3F0059CA3E /* PreviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C9BFA2223158C3F0059CA3E /* PreviewViewController.swift */; };
4CAF783C2282FD40000C85CF /* FileManager+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CAF783B2282FD40000C85CF /* FileManager+Extension.swift */; };
4CB8ADDE22DF5D3700F1FEBC /* PHPhotoLibrary+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB8ADDD22DF5D3700F1FEBC /* PHPhotoLibrary+Extension.swift */; };
Expand Down Expand Up @@ -669,11 +672,13 @@
39E98B442279ACF5009911F1 /* PublicLinkEditTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublicLinkEditTableViewController.swift; sourceTree = "<group>"; };
3D753147564B1E4F47826109 /* Pods-ownCloud Screenshots Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ownCloud Screenshots Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ownCloud Screenshots Tests/Pods-ownCloud Screenshots Tests.debug.xcconfig"; sourceTree = "<group>"; };
42866B2892DC9EDC65D844E7 /* Pods_ownCloud_Screenshots_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ownCloud_Screenshots_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
4C05D8A4238708D40073EF50 /* MediaUploadStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadStorage.swift; sourceTree = "<group>"; };
4C11EE5A22E88D4200B84869 /* InstantMediaUploadTaskExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstantMediaUploadTaskExtension.swift; sourceTree = "<group>"; };
4C1561E7222321E0009C4EF3 /* PhotoSelectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoSelectionViewController.swift; sourceTree = "<group>"; };
4C1561EE22232357009C4EF3 /* PhotoSelectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoSelectionViewCell.swift; sourceTree = "<group>"; };
4C16CBA6226F0F1900D67BB6 /* FileTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileTests.swift; sourceTree = "<group>"; };
4C235CED21F88C0300A989A8 /* UIViewController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extension.swift"; sourceTree = "<group>"; };
4C3E17DA234DBF9A000D7BA8 /* PendingMediaUploadTaskExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PendingMediaUploadTaskExtension.swift; sourceTree = "<group>"; };
4C464BE12187AF1400D30602 /* PDFThumbnailCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PDFThumbnailCollectionViewCell.swift; sourceTree = "<group>"; };
4C464BE82187AF1400D30602 /* PDFTocTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PDFTocTableViewController.swift; sourceTree = "<group>"; };
4C464BE92187AF1400D30602 /* PDFTocTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PDFTocTableViewCell.swift; sourceTree = "<group>"; };
Expand All @@ -691,6 +696,7 @@
4C7295D7228C384E00FA4E68 /* LogFilesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogFilesViewController.swift; sourceTree = "<group>"; };
4C82D06F22C9387300835F0B /* MediaDisplayViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaDisplayViewController.swift; sourceTree = "<group>"; };
4C88041722E78D790016CBA9 /* MediaFilesSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaFilesSettings.swift; sourceTree = "<group>"; };
4C96463B238489E4003278B7 /* MediaUploadActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadActivity.swift; sourceTree = "<group>"; };
4C9BFA2223158C3F0059CA3E /* PreviewViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewViewController.swift; sourceTree = "<group>"; };
4CAF783B2282FD40000C85CF /* FileManager+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileManager+Extension.swift"; sourceTree = "<group>"; };
4CB8ADDD22DF5D3700F1FEBC /* PHPhotoLibrary+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PHPhotoLibrary+Extension.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1246,6 +1252,7 @@
4C51727622DE04BD001BC97F /* BackgroundFetchUpdateTaskAction.swift */,
4C51727722DE04BD001BC97F /* ScheduledTaskManager.swift */,
4C11EE5A22E88D4200B84869 /* InstantMediaUploadTaskExtension.swift */,
4C3E17DA234DBF9A000D7BA8 /* PendingMediaUploadTaskExtension.swift */,
);
path = Tasks;
sourceTree = "<group>";
Expand All @@ -1264,6 +1271,8 @@
4CB8ADDD22DF5D3700F1FEBC /* PHPhotoLibrary+Extension.swift */,
4CB8ADE222DF6BA700F1FEBC /* PHAsset+Upload.swift */,
4CC4A21822FB4F4C00AE7E2C /* MediaUploadQueue.swift */,
4C96463B238489E4003278B7 /* MediaUploadActivity.swift */,
4C05D8A4238708D40073EF50 /* MediaUploadStorage.swift */,
);
path = "PhotoKit Extensions";
sourceTree = "<group>";
Expand Down Expand Up @@ -2603,6 +2612,7 @@
4C9BFA2323158C3F0059CA3E /* PreviewViewController.swift in Sources */,
DC1B2709209CF0D3004715E1 /* CertificateViewController.swift in Sources */,
DC248C67213E7DB00067FE94 /* NSLayoutConstraint+Extension.swift in Sources */,
4C3E17DB234DBF9A000D7BA8 /* PendingMediaUploadTaskExtension.swift in Sources */,
6E586CFC2199A72600F680C4 /* OpenInAction.swift in Sources */,
DC136582208223F000FC0F60 /* OCBookmark+Extension.swift in Sources */,
23D77FCD212BFBD100DE76F1 /* NamingViewController.swift in Sources */,
Expand Down Expand Up @@ -2642,11 +2652,13 @@
DC85572C20513B8C00189B9A /* ServerListTableViewController.swift in Sources */,
233BDEA0204FEFE500C06732 /* AppDelegate.swift in Sources */,
4C51727E22DE04BD001BC97F /* BackgroundFetchUpdateTaskAction.swift in Sources */,
4C05D8A5238708D40073EF50 /* MediaUploadStorage.swift in Sources */,
236735A621217C3500E5834A /* MoreViewController.swift in Sources */,
39E2FE0021FF814A00F0117F /* ThemeRoundedButton.swift in Sources */,
23957A6D209AFFE8003C8537 /* MoreSettingsSection.swift in Sources */,
4C464BEF2187AF1500D30602 /* PDFThumbnailCollectionViewCell.swift in Sources */,
232B01F62126B10900366FA0 /* MoreStaticTableViewController.swift in Sources */,
4C96463C238489E4003278B7 /* MediaUploadActivity.swift in Sources */,
6E91F37E21ECA6FD009436D2 /* CopyAction.swift in Sources */,
4CC4A21922FB4F4C00AE7E2C /* MediaUploadQueue.swift in Sources */,
593BAB97209F8A0500023634 /* AppLockManager.swift in Sources */,
Expand Down
41 changes: 26 additions & 15 deletions ownCloud/AVFoundation Extensions/AVAsset+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,39 @@
import AVFoundation

extension AVAsset {
func exportVideo(targetURL:URL, type:AVFileType, completion:@escaping (_ success:Bool) -> Void) {
func exportVideo(targetURL:URL, type:AVFileType) -> Bool {
if self.isExportable {

let group = DispatchGroup()
let preset = AVAssetExportPresetHighestQuality
var compatiblePreset = false
var exportSuccess = false

group.enter()
AVAssetExportSession.determineCompatibility(ofExportPreset: preset, with: self, outputFileType: type, completionHandler: { (isCompatible) in
if !isCompatible {
completion(false)
}})
compatiblePreset = isCompatible
group.leave()
})

guard let export = AVAssetExportSession(asset: self, presetName: preset) else {
completion(false)
return
}
if compatiblePreset {
guard let export = AVAssetExportSession(asset: self, presetName: preset) else {
return false
}
// Configure export session
export.outputFileType = type
export.outputURL = targetURL

export.outputFileType = type
export.outputURL = targetURL
export.exportAsynchronously {
completion( export.status == .completed )
// Start export
group.enter()
export.exportAsynchronously {
exportSuccess = (export.status == .completed)
felix-schwarz marked this conversation as resolved.
Show resolved Hide resolved
group.leave()
}
}
} else {
completion(false)

group.wait()
return exportSuccess
}

return false
}
}
9 changes: 7 additions & 2 deletions ownCloud/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,20 +73,25 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
OCExtensionManager.shared.addExtension(UploadFileAction.actionExtension)
OCExtensionManager.shared.addExtension(UploadMediaAction.actionExtension)
OCExtensionManager.shared.addExtension(UnshareAction.actionExtension)
OCExtensionManager.shared.addExtension(BackgroundFetchUpdateTaskAction.taskExtension)
OCExtensionManager.shared.addExtension(InstantMediaUploadTaskExtension.taskExtension)
OCExtensionManager.shared.addExtension(MakeAvailableOfflineAction.actionExtension)
OCExtensionManager.shared.addExtension(MakeUnavailableOfflineAction.actionExtension)
OCExtensionManager.shared.addExtension(CollaborateAction.actionExtension)
OCExtensionManager.shared.addExtension(LinksAction.actionExtension)
OCExtensionManager.shared.addExtension(FavoriteAction.actionExtension)
OCExtensionManager.shared.addExtension(UnfavoriteAction.actionExtension)
// OCExtensionManager.shared.addExtension(ScanAction.actionExtension)

if #available(iOS 13.0, *), UIDevice.current.isIpad() {
OCExtensionManager.shared.addExtension(DiscardSceneAction.actionExtension)
OCExtensionManager.shared.addExtension(OpenSceneAction.actionExtension)
}

// Task extensions
OCExtensionManager.shared.addExtension(BackgroundFetchUpdateTaskAction.taskExtension)
OCExtensionManager.shared.addExtension(InstantMediaUploadTaskExtension.taskExtension)
OCExtensionManager.shared.addExtension(PendingMediaUploadTaskExtension.taskExtension)

// Theming
Theme.shared.activeCollection = ThemeCollection(with: ThemeStyle.preferredStyle)

// Licenses
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,11 @@ class UploadMediaAction: UploadBaseAction {
photoAlbumViewController.selectionCallback = {(assets) in
self.completed()

guard let rootItem = self.context.items.first else { return }
guard let path = self.context.items.first?.path else { return }

MediaUploadQueue.shared.uploadAssets(assets, with: self.core, at: rootItem, progressHandler: { (progress) in
if progress.isFinished || progress.isCancelled {
self.unpublish(progress: progress)
} else {
self.publish(progress: progress)
}
})
guard let bookmark = OCBookmarkManager.lastBookmarkSelectedForConnection else { return }

MediaUploadQueue.shared.addUploads(assets, for: bookmark, at: path)
}
let navigationController = ThemeNavigationController(rootViewController: photoAlbumViewController)

Expand Down
11 changes: 0 additions & 11 deletions ownCloud/Client/ClientRootViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -224,17 +224,6 @@ class ClientRootViewController: UITabBarController, UINavigationControllerDelega
}
}

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

if MediaUploadQueue.isMediaUploadPendingFlagSet(for: self.bookmark) {
let unfinishedUploadAlert = ThemedAlertController(with: "Warning".localized,
message: "Media upload in the previous session was incomplete since the application was terminated".localized)
self.present(unfinishedUploadAlert, animated: true, completion: nil)
MediaUploadQueue.resetUploadPendingFlag(for: self.bookmark)
}
}

var closeClientCompletionHandler : (() -> Void)?

func closeClient(completion: (() -> Void)? = nil) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ class MediaDisplayViewController : DisplayViewController {
deinit {
playerStatusObservation?.invalidate()
playerItemStatusObservation?.invalidate()
NotificationCenter.default.removeObserver(self)

NotificationCenter.default.removeObserver(self, name: UIApplication.didEnterBackgroundNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: UIApplication.willEnterForegroundNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: Notification.Name.AVPlayerItemDidPlayToEndTime, object: nil)
}

override func viewDidLoad() {
Expand Down
2 changes: 1 addition & 1 deletion ownCloud/FileLists/FileListTableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ class FileListTableViewController: UITableViewController, ClientItemCellDelegate
}
}

func open(item: OCItem, animated: Bool, pushViewController: Bool = true) -> ClientQueryViewController? {
@discardableResult func open(item: OCItem, animated: Bool, pushViewController: Bool = true) -> ClientQueryViewController? {
if let core = self.core {
if #available(iOS 13.0, *) {
if let tabBarController = self.tabBarController as? ClientRootViewController {
Expand Down
60 changes: 60 additions & 0 deletions ownCloud/PhotoKit Extensions/MediaUploadActivity.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//
// MediaUploadActivity.swift
// ownCloud
//
// Created by Michael Neuwert on 19.11.2019.
// Copyright © 2019 ownCloud GmbH. All rights reserved.
//

/*
* Copyright (C) 2019, ownCloud GmbH.
*
* This code is covered by the GNU Public License Version 3.
*
* For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/
* You should have received a copy of this license along with this program. If not, see <http://www.gnu.org/licenses/gpl-3.0.en.html>.
*
*/

import ownCloudSDK

class MediaUploadActivity : OCActivity {

var isCancelled: Bool {
if let progress = self.progress {
return progress.isCancelled
}
return false
}

init(identifier: String, assetCount:Int) {
super.init(identifier: identifier)
self.isCancellable = true
self.localizedDescription = "Media import".localized

if assetCount <= 0 {
self.progress = Progress.indeterminate()
} else {
self.progress = Progress(totalUnitCount: Int64(assetCount))
self.updateStatusMessage()
}
}

public func updateAfterSingleFinishedUpload() {
guard let progress = self.progress else { return }
guard progress.isIndeterminate == false else { return }

self.progress?.completedUnitCount += 1
self.updateStatusMessage()
}

// MARK: - Private helper methods

private func updateStatusMessage() {
if let progress = self.progress, progress.isIndeterminate == false {
let total = progress.totalUnitCount
let current = progress.completedUnitCount
self.localizedStatusMessage = String(format: "%@ of %@".localized, "\(current)", "\(total)")
}
}
}
Loading