From 79a5aba87d5c9cb51b4b6f9105121e8270d85b69 Mon Sep 17 00:00:00 2001 From: kean Date: Wed, 24 Apr 2024 17:41:04 -0400 Subject: [PATCH] Add global retry button --- .../Post/PostMediaUploadStatusView.swift | 43 +++++++------------ .../Post/PostMediaUploadViewModel.swift | 25 ++++++----- .../PrepublishingViewController.swift | 4 +- .../Post/Prepublishing/PublishButton.swift | 2 +- 4 files changed, 31 insertions(+), 43 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Post/PostMediaUploadStatusView.swift b/WordPress/Classes/ViewRelated/Post/PostMediaUploadStatusView.swift index d5f06ad06a48..7bda95f5353c 100644 --- a/WordPress/Classes/ViewRelated/Post/PostMediaUploadStatusView.swift +++ b/WordPress/Classes/ViewRelated/Post/PostMediaUploadStatusView.swift @@ -8,13 +8,22 @@ struct PostMediaUploadStatusView: View { var body: some View { contents - .toolbar { - ToolbarItem(placement: .cancellationAction) { - Button(Strings.close, action: onCloseTapped) + .toolbar { + ToolbarItem(placement: .topBarLeading) { + Button(Strings.close, action: onCloseTapped) + } + ToolbarItem(placement: .topBarTrailing) { + Menu { + Button(action: viewModel.buttonRetryTapped) { + Label(Strings.retryUploads, systemImage: "arrow.clockwise") + }.disabled(viewModel.isButtonRetryDisabled) + } label: { + Image(systemName: "ellipsis") + } + } } - } - .navigationTitle(Strings.title) - .navigationBarTitleDisplayMode(.inline) + .navigationTitle(Strings.title) + .navigationBarTitleDisplayMode(.inline) } @ViewBuilder @@ -59,11 +68,9 @@ private struct MediaUploadStatusView: View { switch viewModel.state { case .uploading: MediaUploadProgressView(progress: viewModel.fractionCompleted) - makeMenu() case .failed: Image(systemName: "exclamationmark.circle.fill") .foregroundStyle(.red) - makeMenu() case .uploaded: Image(systemName: "checkmark.circle.fill") .foregroundStyle(.secondary.opacity(0.33)) @@ -73,23 +80,6 @@ private struct MediaUploadStatusView: View { await viewModel.loadThumbnail() } } - - @ViewBuilder - private func makeMenu() -> some View { - Menu { - Button(action: viewModel.buttonRetryTapped) { - Label(Strings.retry, systemImage: "arrow.clockwise") - } - Button(role: .destructive, action: viewModel.buttonRemoveTapped) { - Label(Strings.remove, systemImage: "trash") - } - } label: { - Image(systemName: "ellipsis") - .font(.footnote) - .foregroundStyle(.secondary.opacity(0.75)) - } - .buttonStyle(.plain) - } } struct MediaUploadProgressView: View { @@ -133,6 +123,5 @@ private enum Strings { static let title = NSLocalizedString("postMediaUploadStatusView.title", value: "Media Uploads", comment: "Title for post media upload status view") static let empty = NSLocalizedString("postMediaUploadStatusView.noPendingUploads", value: "No pending uploads", comment: "Placeholder text in postMediaUploadStatusView when no uploads remain") static let close = NSLocalizedString("postMediaUploadStatusView.close", value: "Close", comment: "Close button in postMediaUploadStatusView") - static let retry = NSLocalizedString("postMediaUploadStatusView.retry", value: "Retry", comment: "Retry upload button in postMediaUploadStatusView") - static let remove = NSLocalizedString("postMediaUploadStatusView.remove", value: "Remove", comment: "Remove media button in postMediaUploadStatusView") + static let retryUploads = NSLocalizedString("postMediaUploadStatusView.retryUploads", value: "Retry Uploads", comment: "Retry upload button in postMediaUploadStatusView") } diff --git a/WordPress/Classes/ViewRelated/Post/PostMediaUploadViewModel.swift b/WordPress/Classes/ViewRelated/Post/PostMediaUploadViewModel.swift index 069ad1eac284..e2f941e2f56d 100644 --- a/WordPress/Classes/ViewRelated/Post/PostMediaUploadViewModel.swift +++ b/WordPress/Classes/ViewRelated/Post/PostMediaUploadViewModel.swift @@ -17,6 +17,10 @@ final class PostMediaUploadViewModel: ObservableObject { private weak var timer: Timer? private var cancellables: [AnyCancellable] = [] + var isButtonRetryDisabled: Bool { + !(uploads.contains(where: { $0.error != nil })) + } + deinit { timer?.invalidate() } @@ -59,6 +63,12 @@ final class PostMediaUploadViewModel: ObservableObject { fractionCompleted = uploads.map(\.fractionCompleted).reduce(0, +) / Double(uploads.count) completedUploadsCount = uploads.filter(\.isCompleted).count } + + func buttonRetryTapped() { + for upload in uploads { + upload.retry() + } + } } /// Manages individual media upload. @@ -133,7 +143,7 @@ final class MediaUploadViewModel: ObservableObject, Identifiable { self.state = media.isUploadNeeded ? .uploading : .uploaded self.fileSize = media.filesize?.int64Value ?? 0 // Should never be `0` - if let error = media.error, MediaCoordinator.isTerminalError(error) { + if media.remoteStatus == .failed, let error = media.error, MediaCoordinator.isTerminalError(error) { self.details = error.localizedDescription self.state = .failed(error) return // No retry @@ -157,7 +167,7 @@ final class MediaUploadViewModel: ObservableObject, Identifiable { } } - private func retry() { + fileprivate func retry() { retryTimer = nil coordinator.retryMedia(media) } @@ -184,17 +194,6 @@ final class MediaUploadViewModel: ObservableObject, Identifiable { // Continue showing placeholder } } - - // MARK: - Menu - - func buttonRetryTapped() { - retry() - } - - func buttonRemoveTapped() { - coordinator.cancelUploadAndDeleteMedia(media) - // TODO: notify Gutenberg or update the post in a different way - } } private extension Media { diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift index 307138bcc48c..a3609b006c72 100644 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift @@ -437,8 +437,8 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource guard !viewModel.isCompleted else { return nil } - if let error = viewModel.uploads.lazy.map(\.error).first { - return .failed(title: Strings.mediaUploadFailedTitle, details: error?.localizedDescription) { [weak self] in + if let error = viewModel.uploads.lazy.compactMap(\.error).first { + return .failed(title: Strings.mediaUploadFailedTitle, details: error.localizedDescription) { [weak self] in self?.buttonShowUploadInfoTapped() } } diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing/PublishButton.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing/PublishButton.swift index cc7c2ec0b810..36323adda086 100644 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing/PublishButton.swift +++ b/WordPress/Classes/ViewRelated/Post/Prepublishing/PublishButton.swift @@ -101,7 +101,7 @@ struct PublishButton: View { } private enum Constants { - static let accessoryViewWidth: CGFloat = 22 + static let accessoryViewWidth: CGFloat = 20 } final class PublishButtonViewModel: ObservableObject {