feat: add post publish validate state binding

This commit is contained in:
CMK 2021-03-23 19:33:12 +08:00
parent b8e062c92e
commit 3eb2b916a7
3 changed files with 76 additions and 6 deletions

View File

@ -25,7 +25,7 @@ extension ComposeStatusItem: Hashable { }
extension ComposeStatusItem {
final class ComposeStatusAttribute: Equatable, Hashable {
private let id = UUID()
let avatarURL = CurrentValueSubject<URL?, Never>(nil)
let displayName = CurrentValueSubject<String?, Never>(nil)
let username = CurrentValueSubject<String?, Never>(nil)
@ -44,12 +44,32 @@ extension ComposeStatusItem {
}
}
protocol ComposeStatusItemDelegate: class {
func composePollAttribute(_ attribute: ComposeStatusItem.ComposePollAttribute, pollOptionDidChange: String?)
}
extension ComposeStatusItem {
final class ComposePollAttribute: Equatable, Hashable {
private let id = UUID()
var disposeBag = Set<AnyCancellable>()
weak var delegate: ComposeStatusItemDelegate?
let option = CurrentValueSubject<String, Never>("")
init() {
option
.sink { [weak self] option in
guard let self = self else { return }
self.delegate?.composePollAttribute(self, pollOptionDidChange: option)
}
.store(in: &disposeBag)
}
deinit {
disposeBag.removeAll()
}
static func == (lhs: ComposePollAttribute, rhs: ComposePollAttribute) -> Bool {
return lhs.id == rhs.id &&
lhs.option.value == rhs.option.value

View File

@ -629,7 +629,6 @@ extension ComposeViewController: PHPickerViewControllerDelegate {
pickerResult: result,
initalAuthenticationBox: viewModel.activeAuthenticationBox.value
)
service.delegate = viewModel
return service
}
viewModel.attachmentServices.value = viewModel.attachmentServices.value + attachmentServices
@ -649,7 +648,6 @@ extension ComposeViewController: UIImagePickerControllerDelegate & UINavigationC
image: image,
initalAuthenticationBox: viewModel.activeAuthenticationBox.value
)
attachmentService.delegate = viewModel
viewModel.attachmentServices.value = viewModel.attachmentServices.value + [attachmentService]
}
@ -673,7 +671,6 @@ extension ComposeViewController: UIDocumentPickerDelegate {
imageData: imageData,
initalAuthenticationBox: viewModel.activeAuthenticationBox.value
)
attachmentService.delegate = viewModel
viewModel.attachmentServices.value = viewModel.attachmentServices.value + [attachmentService]
} catch {
os_log("%{public}s[%{public}ld], %{public}s: %s", ((#file as NSString).lastPathComponent), #line, #function, error.localizedDescription)

View File

@ -104,19 +104,48 @@ final class ComposeViewModel {
.map { services in
services.allSatisfy { $0.uploadStateMachineSubject.value is MastodonAttachmentService.UploadState.Finish }
}
Publishers.CombineLatest4(
let isPollAttributeAllValid = pollAttributes
.map { pollAttributes in
pollAttributes.allSatisfy { attribute -> Bool in
!attribute.option.value.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
}
}
let isPublishBarButtonItemEnabledPrecondition1 = Publishers.CombineLatest4(
isComposeContentEmpty.eraseToAnyPublisher(),
isComposeContentValid.eraseToAnyPublisher(),
isMediaEmpty.eraseToAnyPublisher(),
isMediaUploadAllSuccess.eraseToAnyPublisher()
)
.map { isComposeContentEmpty, isComposeContentValid, isMediaEmpty, isMediaUploadAllSuccess in
.map { isComposeContentEmpty, isComposeContentValid, isMediaEmpty, isMediaUploadAllSuccess -> Bool in
if isMediaEmpty {
return isComposeContentValid && !isComposeContentEmpty
} else {
return isComposeContentValid && isMediaUploadAllSuccess
}
}
.eraseToAnyPublisher()
let isPublishBarButtonItemEnabledPrecondition2 = Publishers.CombineLatest4(
isComposeContentEmpty.eraseToAnyPublisher(),
isComposeContentValid.eraseToAnyPublisher(),
isPollComposing.eraseToAnyPublisher(),
isPollAttributeAllValid.eraseToAnyPublisher()
)
.map { isComposeContentEmpty, isComposeContentValid, isPollComposing, isPollAttributeAllValid -> Bool in
if isPollComposing {
return isComposeContentValid && !isComposeContentEmpty && isPollAttributeAllValid
} else {
return isComposeContentValid && !isComposeContentEmpty
}
}
.eraseToAnyPublisher()
Publishers.CombineLatest(
isPublishBarButtonItemEnabledPrecondition1,
isPublishBarButtonItemEnabledPrecondition2
)
.map { $0 && $1 }
.assign(to: \.value, on: isPublishBarButtonItemEnabled)
.store(in: &disposeBag)
@ -201,6 +230,22 @@ final class ComposeViewModel {
}
.store(in: &disposeBag)
// bind delegate
attachmentServices
.sink { [weak self] attachmentServices in
guard let self = self else { return }
attachmentServices.forEach { $0.delegate = self }
}
.store(in: &disposeBag)
pollAttributes
.sink { [weak self] pollAttributes in
guard let self = self else { return }
pollAttributes.forEach { $0.delegate = self }
}
.store(in: &disposeBag)
// bind compose toolbar UI state
Publishers.CombineLatest(
isPollComposing.eraseToAnyPublisher(),
attachmentServices.eraseToAnyPublisher()
@ -235,3 +280,11 @@ extension ComposeViewModel: MastodonAttachmentServiceDelegate {
attachmentServices.value = attachmentServices.value
}
}
// MARK: - ComposeStatusAttributeDelegate
extension ComposeViewModel: ComposeStatusItemDelegate {
func composePollAttribute(_ attribute: ComposeStatusItem.ComposePollAttribute, pollOptionDidChange: String?) {
// trigger update
pollAttributes.value = pollAttributes.value
}
}