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

Bringing back abstracted file sharing into kDrive #1006

Merged
merged 26 commits into from
Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ec36542
chore: Bump Core / Core UI
adrien-coye Jul 19, 2023
c5cd3f4
refactor(FileImportHelper): WIP using new abstract file handling methods
adrien-coye Jul 19, 2023
210537d
fix(FileImportHelper): convert heic to jpg on the fly
adrien-coye Jul 20, 2023
ac093d2
fix: issues with coliding extensions
adrien-coye Jul 21, 2023
a73bc94
Merge branch 'master' into shareExtensionAbstractCode
adrien-coye Jul 21, 2023
ea1c3e0
chore: bump Core, some clean
adrien-coye Jul 26, 2023
b597551
refactor: removed Throttler type, using Combine instead
adrien-coye Jul 27, 2023
dbddd72
feat: initial import from app speed improvement on large collection o…
adrien-coye Jul 27, 2023
e464058
feat: initial preprocess on import from app speed improvement on larg…
adrien-coye Jul 27, 2023
f547919
chore: bump core
adrien-coye Jul 28, 2023
c2d16be
fix(UploadCountManager): Setup combine earlier to work as expected
adrien-coye Jul 28, 2023
d4de971
Merge branch 'master' into shareExtensionAbstractCode
adrien-coye Jul 28, 2023
c2be5a9
chore: bump core
adrien-coye Aug 3, 2023
7124cee
fix(PHAsset): use edit date instead of FullSizeRender when importing …
adrien-coye Aug 4, 2023
1510ca8
refactor(PHAsset): factorise code
adrien-coye Aug 4, 2023
3da0c08
refactor(PhotoLibraryUploader): split class for readability
adrien-coye Aug 4, 2023
0f98b8c
refactor(PhotoLibraryUploader): Shared asset name generation with PHA…
adrien-coye Aug 4, 2023
1948749
chore: cleanup
adrien-coye Aug 7, 2023
e96a0e4
fix(PhotoLibraryUploader+Scan): request photo from creation date _and…
adrien-coye Aug 7, 2023
d6f4496
chore: pre-merge
adrien-coye Aug 8, 2023
3399c1d
Merge branch 'master' into shareExtensionAbstractCode
adrien-coye Aug 8, 2023
751821e
chore: post-merge
adrien-coye Aug 8, 2023
193b726
Update kDrive/Utils/UploadCountManager.swift
adrien-coye Aug 8, 2023
3af46c3
Merge branch 'master' into shareExtensionAbstractCode
adrien-coye Aug 8, 2023
3eba111
chore: Bump ios-core
adrien-coye Aug 10, 2023
4624ab8
fix: update to new Endpoint API
adrien-coye Aug 10, 2023
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
4 changes: 2 additions & 2 deletions .package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/Infomaniak/ios-core",
"state" : {
"revision" : "f0442baed7595fbd59119e5ae2ddcd82fee3832b",
"version" : "4.1.11"
"revision" : "4a3f3dec751c23e4b00d063496a8fda10e63bd0a",
"version" : "4.1.13"
}
},
{
Expand Down
2 changes: 1 addition & 1 deletion Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import ProjectDescriptionHelpers
let project = Project(name: "kDrive",
packages: [
.package(url: "https://github.com/Alamofire/Alamofire", .upToNextMajor(from: "5.2.2")),
.package(url: "https://github.com/Infomaniak/ios-core", .upToNextMajor(from: "4.1.11")),
.package(url: "https://github.com/Infomaniak/ios-core", .upToNextMajor(from: "4.1.13")),
.package(url: "https://github.com/Infomaniak/ios-core-ui", .upToNextMajor(from: "2.5.2")),
.package(url: "https://github.com/Infomaniak/ios-login", .upToNextMajor(from: "4.0.0")),
.package(url: "https://github.com/Infomaniak/ios-dependency-injection", .upToNextMajor(from: "1.1.9")),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class DraggableFileListViewModel {
}

@MainActor
class DroppableFileListViewModel {
final class DroppableFileListViewModel {
@LazyInjectService var fileImportHelper: FileImportHelper

var driveFileManager: DriveFileManager
Expand Down Expand Up @@ -135,10 +135,16 @@ class DroppableFileListViewModel {
guard !importedFiles.isEmpty else {
return
}
do {
try fileImportHelper.upload(files: importedFiles, in: frozenDestination, drive: driveFileManager.drive)
} catch {
Task {

let drive = driveFileManager.drive
Task {
do {
try await self.fileImportHelper.upload(
files: importedFiles,
in: frozenDestination,
drive: drive
)
} catch {
UIConstants.showSnackBarIfNeeded(error: error)
}
}
Expand Down
34 changes: 21 additions & 13 deletions kDrive/UI/Controller/Files/Save File/SaveFileViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -484,21 +484,29 @@ extension SaveFileViewController: FooterButtonDelegate {
return
}

let message: String
do {
try fileImportHelper.upload(files: items, in: selectedDirectory, drive: selectedDriveFileManager.drive)
guard !items.isEmpty else {
navigationController?.dismiss(animated: true)
return
}
message = items.count > 1 ? KDriveResourcesStrings.Localizable
.allUploadInProgressPlural(items.count) : KDriveResourcesStrings.Localizable.allUploadInProgress(items[0].name)
} catch {
message = error.localizedDescription
let items = items
guard !items.isEmpty else {
navigationController?.dismiss(animated: true)
return
}

navigationController?.dismiss(animated: true) {
UIConstants.showSnackBar(message: message)
Task {
let message: String
do {
try await fileImportHelper.upload(files: items, in: selectedDirectory, drive: selectedDriveFileManager.drive)

message = items.count > 1 ? KDriveResourcesStrings.Localizable
.allUploadInProgressPlural(items.count) : KDriveResourcesStrings.Localizable
.allUploadInProgress(items[0].name)
} catch {
message = error.localizedDescription
}

Task { @MainActor in
self.navigationController?.dismiss(animated: true) {
UIConstants.showSnackBar(message: message)
}
}
}
}
}
30 changes: 20 additions & 10 deletions kDrive/Utils/UploadCountManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import Combine
import Foundation
import InfomaniakDI
import kDriveCore
Expand All @@ -26,7 +27,11 @@ final class UploadCountManager {

private let driveFileManager: DriveFileManager
private let didUploadCountChange: () -> Void
private let uploadCountThrottler = Throttler<Int>(timeInterval: 1, queue: .main)

/// Something to debounce upload count events
private let uploadCountSubject = PassthroughSubject<Int, Never>()
private var uploadCountObserver: AnyCancellable?

private let observeQueue = DispatchQueue(label: "com.infomaniak.drive.uploadThrottler",
qos: .utility, autoreleaseFrequency: .workItem)

Expand All @@ -41,11 +46,19 @@ final class UploadCountManager {
init(driveFileManager: DriveFileManager, didUploadCountChange: @escaping () -> Void) {
self.driveFileManager = driveFileManager
self.didUploadCountChange = didUploadCountChange
uploadCountObserver = uploadCountSubject
.throttle(for: .seconds(1), scheduler: DispatchQueue.main, latest: true)
.sink { newUploadCount in
self.uploadCount = newUploadCount
self.didUploadCountChange()
}

updateUploadCount()
observeUploads()
}

deinit {
uploadCountObserver?.cancel()
uploadsObserver?.invalidate()
}

Expand All @@ -58,19 +71,16 @@ final class UploadCountManager {
private func observeUploads() {
guard uploadsObserver == nil else { return }

uploadCountThrottler.handler = { [weak self] newUploadCount in
self?.uploadCount = newUploadCount
self?.didUploadCountChange()
}

uploadsObserver = uploadQueue
.getUploadingFiles(userId: userId, driveIds: driveIds)
.observe(on: observeQueue) { [weak self] change in
guard let self else {
return
}

switch change {
case .initial(let results):
self?.uploadCountThrottler.call(results.count)
case .update(let results, deletions: _, insertions: _, modifications: _):
self?.uploadCountThrottler.call(results.count)
case .initial(let results), .update(let results, deletions: _, insertions: _, modifications: _):
self.uploadCountSubject.send(results.count)
case .error(let error):
print(error)
}
Expand Down
10 changes: 2 additions & 8 deletions kDriveCore/Data/Api/Endpoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,7 @@ public extension Endpoint {
URLQueryItem(name: "per_page", value: "\(Endpoint.itemsPerPage)")
]

return Endpoint(hostKeypath: hostKeypath,
path: path,
queryItems: (queryItems ?? []) + paginationQueryItems,
apiEnvironment: apiEnvironment)
return Endpoint(host: host, path: path, queryItems: (queryItems ?? []) + paginationQueryItems)
}

func sorted(by sortTypes: [SortType] = [.type, .nameAZ]) -> Endpoint {
Expand All @@ -76,10 +73,7 @@ public extension Endpoint {
sortQueryItems
.append(contentsOf: sortTypes.map { URLQueryItem(name: "order_for[\($0.value.apiValue)]", value: $0.value.order) })

return Endpoint(hostKeypath: hostKeypath,
path: path,
queryItems: (queryItems ?? []) + sortQueryItems,
apiEnvironment: apiEnvironment)
return Endpoint(host: host, path: path, queryItems: (queryItems ?? []) + sortQueryItems)
}
}

Expand Down
2 changes: 2 additions & 0 deletions kDriveCore/Data/Cache/DriveFileManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public final class DriveFileManager {
public let importDirectoryURL: URL
public let groupDirectoryURL: URL
public var cacheDirectoryURL: URL
public var tmpDirectoryURL: URL
public let openInPlaceDirectoryURL: URL?
public let rootID = 1
public let currentUploadDbVersion: UInt64 = 14
Expand Down Expand Up @@ -131,6 +132,7 @@ public final class DriveFileManager {
groupDirectoryURL = pathProvider.groupDirectoryURL
rootDocumentsURL = pathProvider.realmRootURL
importDirectoryURL = pathProvider.importDirectoryURL
tmpDirectoryURL = pathProvider.tmpDirectoryURL
cacheDirectoryURL = pathProvider.cacheDirectoryURL
openInPlaceDirectoryURL = pathProvider.openInPlaceDirectoryURL

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
Infomaniak kDrive - iOS App
Copyright (C) 2023 Infomaniak Network SA

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import Foundation
import Photos

public extension PhotoLibraryUploader {
/// Wrapper type to map an "UploadFile" to a "PHAsset"
struct PicturesAssets {
/// Collection of primary keys of "UploadFile"
public let filesPrimaryKeys: [String]

/// collection of PHAsset
public let assets: PHFetchResult<PHAsset>
}

func getPicturesToRemove() -> PicturesAssets? {
Log.photoLibraryUploader("getPicturesToRemove")
// Check that we have photo sync enabled with the delete option
guard let settings, settings.deleteAssetsAfterImport else {
Log.photoLibraryUploader("no settings")
return nil
}

var toRemoveFileIDs = [String]()
var toRemoveAssets = PHFetchResult<PHAsset>()
BackgroundRealm.uploads.execute { realm in
toRemoveFileIDs = uploadQueue
.getUploadedFiles(using: realm)
.filter("rawType = %@", UploadFileType.phAsset.rawValue)
.map(\.id)
toRemoveAssets = PHAsset.fetchAssets(withLocalIdentifiers: toRemoveFileIDs, options: nil)
}

guard toRemoveAssets.count >= Self.removeAssetsCountThreshold,
uploadQueue.operationQueue.operationCount == 0 else {
return nil
}

return PicturesAssets(filesPrimaryKeys: toRemoveFileIDs, assets: toRemoveAssets)
}

func removePicturesFromPhotoLibrary(_ toRemoveItems: PicturesAssets) {
Log.photoLibraryUploader("removePicturesFromPhotoLibrary toRemoveItems:\(toRemoveItems.filesPrimaryKeys.count)")
PHPhotoLibrary.shared().performChanges {
PHAssetChangeRequest.deleteAssets(toRemoveItems.assets)
} completionHandler: { success, _ in
guard success else {
return
}

BackgroundRealm.uploads.execute { realm in
do {
try realm.write {
let filesInContext = realm
.objects(UploadFile.self)
.filter("id IN %@", toRemoveItems.filesPrimaryKeys)
.filter { $0.isInvalidated == false }
realm.delete(filesInContext)
}
Log.photoLibraryUploader("removePicturesFromPhotoLibrary success")
} catch {
Log.photoLibraryUploader("removePicturesFromPhotoLibrary error:\(error)", level: .error)
}
}
}
}
}
Loading
Loading