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

feat: External links download all progres UI #1375

Open
wants to merge 4 commits into
base: externalLinks-famousLastFivePercent
Choose a base branch
from
Open
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
10 changes: 8 additions & 2 deletions kDrive/UI/Controller/Files/File List/FileListViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ enum FileListBarButtonType {
case photoSort
case addFolder
case downloadAll
case downloadingAll
case addToMyDrive
}

Expand Down Expand Up @@ -164,8 +165,6 @@ class FileListViewModel: SelectDelegate {
listStyle = FileListOptions.instance.currentStyle
isRefreshing = false
isLoading = false
currentLeftBarButtons = configuration.leftBarButtons
currentRightBarButtons = configuration.rightBarButtons

if self.currentDirectory.isRoot {
if let rootTitle = configuration.rootTitle {
Expand Down Expand Up @@ -199,6 +198,13 @@ class FileListViewModel: SelectDelegate {
currentDirectory: self.currentDirectory
)
}

loadButtonsConfiguration()
}

func loadButtonsConfiguration() {
currentLeftBarButtons = configuration.leftBarButtons
currentRightBarButtons = configuration.rightBarButtons
}

func updateRealmObservation() {
Expand Down
24 changes: 20 additions & 4 deletions kDrive/UI/Controller/Menu/Share/PublicShareViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,14 @@ final class PublicShareViewModel: InMemoryFileListViewModel {
}

override func barButtonPressed(sender: Any?, type: FileListBarButtonType) {
guard downloadObserver == nil,
let publicShareProxy else {
guard let publicShareProxy else {
return
}

if type == .downloadAll {
downloadAll(sender: sender, publicShareProxy: publicShareProxy)
} else if type == .downloadingAll {
cancelDownloadAll()
} else if type == .addToMyDrive {
addToMyDrive(sender: sender, publicShareProxy: publicShareProxy)
} else if type == .cancel, !(multipleSelectionViewModel?.isMultipleSelectionEnabled ?? true) {
Expand All @@ -100,24 +101,34 @@ final class PublicShareViewModel: InMemoryFileListViewModel {
}
}

private func cancelDownloadAll() {
DownloadQueue.instance.cancelFileOperation(for: currentDirectory.id)
clearDownloadObserver()
configuration.rightBarButtons = [.downloadAll]
loadButtonsConfiguration()
}

private func downloadAll(sender: Any?, publicShareProxy: PublicShareProxy) {
let button = sender as? UIButton
button?.isEnabled = false
configuration.rightBarButtons = [.downloadingAll]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it is cleaner to change the configuration and refresh than write directly to the ViewModel state.

loadButtonsConfiguration()

downloadObserver = DownloadQueue.instance
.observeFileDownloaded(self, fileId: currentDirectory.id) { [weak self] _, error in
Task { @MainActor in
defer {
button?.isEnabled = true
self?.configuration.rightBarButtons = [.downloadAll]
self?.loadButtonsConfiguration()
}

guard let self = self else {
return
}

defer {
self.downloadObserver?.cancel()
self.downloadObserver = nil
self.clearDownloadObserver()
}

guard error == nil else {
Expand Down Expand Up @@ -148,6 +159,11 @@ final class PublicShareViewModel: InMemoryFileListViewModel {
publicShareProxy: publicShareProxy)
}

private func clearDownloadObserver() {
downloadObserver?.cancel()
downloadObserver = nil
}

private func addToMyDrive(sender: Any?, publicShareProxy: PublicShareProxy) {
guard accountManager.currentAccount != nil else {
router.showUpsaleFloatingPanel()
Expand Down
15 changes: 15 additions & 0 deletions kDrive/UI/View/Files/FileListBarButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,26 @@ final class FileListBarButton: UIBarButtonItem {
let image = KDriveResourcesAsset.download.image
self.init(image: image, style: .plain, target: target, action: action)
accessibilityLabel = KDriveResourcesStrings.Localizable.buttonDownload
case .downloadingAll:
self.init(title: nil, style: .plain, target: target, action: action)

let activityView = UIActivityIndicatorView(style: .medium)
activityView.startAnimating()

let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(cancelDownloadPressed))
activityView.addGestureRecognizer(tapGestureRecognizer)

customView = activityView
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having an action matching our pattern of calling on a UITabBarItem with a custom view was not trivial.

case .addToMyDrive:
let image = KDriveResourcesAsset.drive.image
self.init(image: image, style: .plain, target: target, action: action)
accessibilityLabel = KDriveResourcesStrings.Localizable.buttonAddToKDrive
}
self.type = type
}

@objc private func cancelDownloadPressed() {
guard let targetObject = target as? NSObject, let action else { return }
targetObject.perform(action, with: self)
}
}
30 changes: 25 additions & 5 deletions kDriveCore/Data/DownloadQueue/DownloadQueue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,11 @@ public final class DownloadQueue: ParallelismHeuristicDelegate {

OperationQueueHelper.disableIdleTimer(true)

let operation = DownloadAuthenticatedOperation(file: file, driveFileManager: driveFileManager, urlSession: self.foregroundSession)
let operation = DownloadAuthenticatedOperation(
file: file,
driveFileManager: driveFileManager,
urlSession: self.foregroundSession
)
operation.completionBlock = {
self.dispatchQueue.async {
self.fileOperationsInQueue.removeValue(forKey: fileId)
Expand Down Expand Up @@ -292,14 +296,30 @@ public final class DownloadQueue: ParallelismHeuristicDelegate {
operationQueue.cancelAllOperations()
}

/// Check if a file is been uploaded
///
/// Thread safe
/// Lookup O(1) as Dictionary backed
public func cancelArchiveOperation(for archiveId: String) {
guard let operation = archiveOperation(for: archiveId) else {
return
}
operation.cancel()
archiveOperationsInQueue.removeValue(forKey: archiveId)
}

public func cancelFileOperation(for fileId: Int) {
guard let operation = operation(for: fileId) else {
return
}
operation.cancel()
fileOperationsInQueue.removeValue(forKey: fileId)
}

public func operation(for fileId: Int) -> DownloadFileOperationable? {
return fileOperationsInQueue[fileId]
}

public func archiveOperation(for archiveId: String) -> DownloadArchiveOperation? {
return archiveOperationsInQueue[archiveId]
}

public func hasOperation(for fileId: Int) -> Bool {
return operation(for: fileId) != nil
}
Expand Down
Loading