forked from zelo72/mastodon-ios
feat: make image attachments uploading in the queue
This commit is contained in:
parent
d64a06aa9d
commit
c35fcfb08f
|
@ -147,8 +147,9 @@ extension ComposeViewController {
|
|||
])
|
||||
|
||||
collectionView.delegate = self
|
||||
let longPressReorderGesture = UILongPressGestureRecognizer(target: self, action: #selector(ComposeViewController.longPressReorderGestureHandler(_:)))
|
||||
collectionView.addGestureRecognizer(longPressReorderGesture)
|
||||
// Note: do not allow reorder due to the images display order following the upload time
|
||||
// let longPressReorderGesture = UILongPressGestureRecognizer(target: self, action: #selector(ComposeViewController.longPressReorderGestureHandler(_:)))
|
||||
// collectionView.addGestureRecognizer(longPressReorderGesture)
|
||||
viewModel.setupDiffableDataSource(
|
||||
for: collectionView,
|
||||
dependency: self,
|
||||
|
@ -321,7 +322,7 @@ extension ComposeViewController {
|
|||
dismiss(animated: true, completion: nil)
|
||||
}
|
||||
|
||||
|
||||
/* Do not allow reorder image due to image display order following the update time
|
||||
@objc private func longPressReorderGestureHandler(_ sender: UILongPressGestureRecognizer) {
|
||||
switch(sender.state) {
|
||||
case .began:
|
||||
|
@ -347,6 +348,7 @@ extension ComposeViewController {
|
|||
collectionView.cancelInteractiveMovement()
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -24,27 +24,29 @@ extension ComposeViewModel {
|
|||
textEditorViewTextAttributesDelegate: textEditorViewTextAttributesDelegate,
|
||||
composeStatusAttachmentTableViewCellDelegate: composeStatusAttachmentTableViewCellDelegate
|
||||
)
|
||||
|
||||
// Note: do not allow reorder due to the images display order following the upload time
|
||||
// diffableDataSource.reorderingHandlers.canReorderItem = { item in
|
||||
// switch item {
|
||||
// case .attachment: return true
|
||||
// default: return false
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// diffableDataSource.reorderingHandlers.didReorder = { [weak self] transaction in
|
||||
// guard let self = self else { return }
|
||||
//
|
||||
// let items = transaction.finalSnapshot.itemIdentifiers
|
||||
// var attachmentServices: [MastodonAttachmentService] = []
|
||||
// for item in items {
|
||||
// guard case let .attachment(attachmentService) = item else { continue }
|
||||
// attachmentServices.append(attachmentService)
|
||||
// }
|
||||
// self.attachmentServices.value = attachmentServices
|
||||
// }
|
||||
//
|
||||
|
||||
diffableDataSource.reorderingHandlers.canReorderItem = { item in
|
||||
switch item {
|
||||
case .attachment: return true
|
||||
default: return false
|
||||
}
|
||||
|
||||
}
|
||||
diffableDataSource.reorderingHandlers.didReorder = { [weak self] transaction in
|
||||
guard let self = self else { return }
|
||||
|
||||
let items = transaction.finalSnapshot.itemIdentifiers
|
||||
var attachmentServices: [MastodonAttachmentService] = []
|
||||
for item in items {
|
||||
guard case let .attachment(attachmentService) = item else { continue }
|
||||
attachmentServices.append(attachmentService)
|
||||
}
|
||||
self.attachmentServices.value = attachmentServices
|
||||
}
|
||||
self.diffableDataSource = diffableDataSource
|
||||
|
||||
var snapshot = NSDiffableDataSourceSnapshot<ComposeStatusSection, ComposeStatusItem>()
|
||||
snapshot.appendSections([.repliedTo, .status, .attachment])
|
||||
switch composeKind {
|
||||
|
|
|
@ -137,7 +137,7 @@ final class ComposeViewModel {
|
|||
}
|
||||
.store(in: &disposeBag)
|
||||
|
||||
// bind snapshot
|
||||
// bind snapshot and drive service upload state
|
||||
attachmentServices
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] attachmentServices in
|
||||
|
@ -154,6 +154,26 @@ final class ComposeViewModel {
|
|||
snapshot.appendItems(items, toSection: .attachment)
|
||||
|
||||
diffableDataSource.apply(snapshot)
|
||||
|
||||
// make image upload in the queue
|
||||
for attachmentService in attachmentServices {
|
||||
// skip when prefix N task when task finish OR fail OR uploading
|
||||
guard let currentState = attachmentService.uploadStateMachine.currentState else { break }
|
||||
if currentState is MastodonAttachmentService.UploadState.Fail {
|
||||
continue
|
||||
}
|
||||
if currentState is MastodonAttachmentService.UploadState.Finish {
|
||||
continue
|
||||
}
|
||||
if currentState is MastodonAttachmentService.UploadState.Uploading {
|
||||
break
|
||||
}
|
||||
// trigger uploading one by one
|
||||
if currentState is MastodonAttachmentService.UploadState.Initial {
|
||||
attachmentService.uploadStateMachine.enter(MastodonAttachmentService.UploadState.Uploading.self)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
}
|
||||
|
|
|
@ -31,8 +31,15 @@ extension MastodonAttachmentService.UploadState {
|
|||
class Initial: MastodonAttachmentService.UploadState {
|
||||
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
|
||||
guard service?.authenticationBox != nil else { return false }
|
||||
guard service?.imageData.value != nil else { return false }
|
||||
return stateClass == Uploading.self
|
||||
if stateClass == Initial.self {
|
||||
return true
|
||||
}
|
||||
|
||||
if service?.imageData.value != nil {
|
||||
return stateClass == Uploading.self
|
||||
} else {
|
||||
return stateClass == Fail.self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -64,15 +64,14 @@ final class MastodonAttachmentService {
|
|||
switch completion {
|
||||
case .failure(let error):
|
||||
self.error.value = error
|
||||
self.uploadStateMachine.enter(UploadState.Fail.self)
|
||||
case .finished:
|
||||
break
|
||||
}
|
||||
} receiveValue: { [weak self] imageData in
|
||||
guard let self = self else { return }
|
||||
self.imageData.value = imageData
|
||||
|
||||
// Try pre-upload attachment for current active user
|
||||
self.uploadStateMachine.enter(UploadState.Uploading.self)
|
||||
self.uploadStateMachine.enter(UploadState.Initial.self)
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
}
|
||||
|
@ -89,9 +88,7 @@ final class MastodonAttachmentService {
|
|||
setupServiceObserver()
|
||||
|
||||
imageData.value = image.jpegData(compressionQuality: 0.75)
|
||||
|
||||
// Try pre-upload attachment for current active user
|
||||
uploadStateMachine.enter(UploadState.Uploading.self)
|
||||
uploadStateMachine.enter(UploadState.Initial.self)
|
||||
}
|
||||
|
||||
init(
|
||||
|
@ -106,9 +103,7 @@ final class MastodonAttachmentService {
|
|||
setupServiceObserver()
|
||||
|
||||
self.imageData.value = imageData
|
||||
|
||||
// Try pre-upload attachment for current active user
|
||||
uploadStateMachine.enter(UploadState.Uploading.self)
|
||||
uploadStateMachine.enter(UploadState.Initial.self)
|
||||
}
|
||||
|
||||
private func setupServiceObserver() {
|
||||
|
|
Loading…
Reference in New Issue