Actions on status

This commit is contained in:
Justin Mazzocchi 2021-02-09 23:46:00 -08:00
parent 03095f5b9c
commit 1580fb0032
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
6 changed files with 193 additions and 57 deletions

View file

@ -8,6 +8,7 @@
"account.accept-follow-request-button.accessibility-label" = "Accept follow request"; "account.accept-follow-request-button.accessibility-label" = "Accept follow request";
"account.avatar.accessibility-label-%@" = "Avatar: %@"; "account.avatar.accessibility-label-%@" = "Avatar: %@";
"account.block" = "Block"; "account.block" = "Block";
"account.block-and-report" = "Block & report";
"account.block.confirm-%@" = "Block %@?"; "account.block.confirm-%@" = "Block %@?";
"account.domain-block-%@" = "Block domain %@"; "account.domain-block-%@" = "Block domain %@";
"account.domain-block.confirm-%@" = "Block domain %@?"; "account.domain-block.confirm-%@" = "Block domain %@?";

View file

@ -105,6 +105,22 @@ private extension ProfileViewController {
}) })
} }
if relationship.blocking {
actions.append(UIAction(
title: NSLocalizedString("account.unblock", comment: ""),
image: UIImage(systemName: "slash.circle"),
attributes: .destructive) { _ in
accountViewModel.confirmUnblock()
})
} else {
actions.append(UIAction(
title: NSLocalizedString("account.block", comment: ""),
image: UIImage(systemName: "slash.circle"),
attributes: .destructive) { _ in
accountViewModel.confirmBlock()
})
}
actions.append(UIAction( actions.append(UIAction(
title: NSLocalizedString("report", comment: ""), title: NSLocalizedString("report", comment: ""),
image: UIImage(systemName: "flag"), image: UIImage(systemName: "flag"),
@ -116,30 +132,6 @@ private extension ProfileViewController {
self.report(reportViewModel: reportViewModel) self.report(reportViewModel: reportViewModel)
}) })
if relationship.blocking {
actions.append(UIAction(
title: NSLocalizedString("account.unblock", comment: ""),
image: UIImage(systemName: "slash.circle"),
attributes: .destructive) { [weak self] _ in
self?.confirm(message: String.localizedStringWithFormat(
NSLocalizedString("account.unblock.confirm-%@", comment: ""),
accountViewModel.accountName)) {
accountViewModel.unblock()
}
})
} else {
actions.append(UIAction(
title: NSLocalizedString("account.block", comment: ""),
image: UIImage(systemName: "slash.circle"),
attributes: .destructive) { [weak self] _ in
self?.confirm(message: String.localizedStringWithFormat(
NSLocalizedString("account.block.confirm-%@", comment: ""),
accountViewModel.accountName)) {
accountViewModel.block()
}
})
}
if !accountViewModel.isLocal, let domain = accountViewModel.domain { if !accountViewModel.isLocal, let domain = accountViewModel.domain {
if relationship.domainBlocking { if relationship.domainBlocking {
actions.append(UIAction( actions.append(UIAction(
@ -147,12 +139,8 @@ private extension ProfileViewController {
NSLocalizedString("account.domain-unblock-%@", comment: ""), NSLocalizedString("account.domain-unblock-%@", comment: ""),
domain), domain),
image: UIImage(systemName: "slash.circle"), image: UIImage(systemName: "slash.circle"),
attributes: .destructive) { [weak self] _ in attributes: .destructive) { _ in
self?.confirm(message: String.localizedStringWithFormat( accountViewModel.confirmDomainUnblock(domain: domain)
NSLocalizedString("account.domain-unblock.confirm-%@", comment: ""),
domain)) {
accountViewModel.domainUnblock()
}
}) })
} else { } else {
actions.append(UIAction( actions.append(UIAction(
@ -160,30 +148,12 @@ private extension ProfileViewController {
NSLocalizedString("account.domain-block-%@", comment: ""), NSLocalizedString("account.domain-block-%@", comment: ""),
domain), domain),
image: UIImage(systemName: "slash.circle"), image: UIImage(systemName: "slash.circle"),
attributes: .destructive) { [weak self] _ in attributes: .destructive) { _ in
self?.confirm(message: String.localizedStringWithFormat( accountViewModel.confirmDomainBlock(domain: domain)
NSLocalizedString("account.domain-block.confirm-%@", comment: ""), })
domain)) {
accountViewModel.domainBlock()
}
})
} }
} }
return UIMenu(children: actions) return UIMenu(children: actions)
} }
func confirm(message: String, action: @escaping () -> Void) {
let alertController = UIAlertController(title: nil, message: message, preferredStyle: .alert)
let cancelAction = UIAlertAction(title: NSLocalizedString("cancel", comment: ""), style: .cancel, handler: nil)
let okAction = UIAlertAction(title: NSLocalizedString("ok", comment: ""), style: .destructive) { _ in
action()
}
alertController.addAction(cancelAction)
alertController.addAction(okAction)
present(alertController, animated: true)
}
} }

View file

@ -158,6 +158,20 @@ class TableViewController: UITableViewController {
} }
extension TableViewController { extension TableViewController {
func confirm(message: String, style: UIAlertAction.Style = .default, action: @escaping () -> Void) {
let alertController = UIAlertController(title: nil, message: message, preferredStyle: .alert)
let cancelAction = UIAlertAction(title: NSLocalizedString("cancel", comment: ""), style: .cancel, handler: nil)
let okAction = UIAlertAction(title: NSLocalizedString("ok", comment: ""), style: style) { _ in
action()
}
alertController.addAction(cancelAction)
alertController.addAction(okAction)
present(alertController, animated: true)
}
func report(reportViewModel: ReportViewModel) { func report(reportViewModel: ReportViewModel) {
let reportViewController = ReportViewController(viewModel: reportViewModel) let reportViewController = ReportViewController(viewModel: reportViewModel)
let navigationController = UINavigationController(rootViewController: reportViewController) let navigationController = UINavigationController(rootViewController: reportViewController)
@ -412,6 +426,7 @@ private extension TableViewController {
} }
} }
// swiftlint:disable:next cyclomatic_complexity
func handle(event: CollectionItemEvent) { func handle(event: CollectionItemEvent) {
switch event { switch event {
case .ignorableOutput: case .ignorableOutput:
@ -428,6 +443,14 @@ private extension TableViewController {
compose(inReplyToViewModel: inReplyToViewModel, redraft: redraft) compose(inReplyToViewModel: inReplyToViewModel, redraft: redraft)
case let .confirmDelete(statusViewModel, redraft): case let .confirmDelete(statusViewModel, redraft):
confirmDelete(statusViewModel: statusViewModel, redraft: redraft) confirmDelete(statusViewModel: statusViewModel, redraft: redraft)
case let .confirmBlock(accountViewModel):
confirmBlock(accountViewModel: accountViewModel)
case let .confirmUnblock(accountViewModel):
confirmUnblock(accountViewModel: accountViewModel)
case let .confirmDomainBlock(accountViewModel):
confirmDomainBlock(accountViewModel: accountViewModel)
case let .confirmDomainUnblock(accountViewModel):
confirmDomainUnblock(accountViewModel: accountViewModel)
case let .report(reportViewModel): case let .report(reportViewModel):
report(reportViewModel: reportViewModel) report(reportViewModel: reportViewModel)
case let .accountListEdit(accountViewModel, edit): case let .accountListEdit(accountViewModel, edit):
@ -548,6 +571,59 @@ private extension TableViewController {
present(alertController, animated: true) present(alertController, animated: true)
} }
func confirmBlock(accountViewModel: AccountViewModel) {
let alertController = UIAlertController(
title: nil,
message: String.localizedStringWithFormat(
NSLocalizedString("account.block.confirm-%@", comment: ""),
accountViewModel.accountName), preferredStyle: .alert)
let blockAction = UIAlertAction(title: NSLocalizedString("account.block", comment: ""),
style: .destructive) { _ in
accountViewModel.block()
}
let blockAndReportAction = UIAlertAction(title: NSLocalizedString("account.block-and-report", comment: ""),
style: .destructive) { [weak self] _ in
accountViewModel.block()
self?.report(reportViewModel: accountViewModel.reportViewModel())
}
let cancelAction = UIAlertAction(title: NSLocalizedString("cancel", comment: ""), style: .cancel) { _ in }
alertController.addAction(blockAction)
alertController.addAction(blockAndReportAction)
alertController.addAction(cancelAction)
present(alertController, animated: true)
}
func confirmUnblock(accountViewModel: AccountViewModel) {
confirm(message: String.localizedStringWithFormat(
NSLocalizedString("account.unblock.confirm-%@", comment: ""),
accountViewModel.accountName)) {
accountViewModel.unblock()
}
}
func confirmDomainBlock(accountViewModel: AccountViewModel) {
guard let domain = accountViewModel.domain else { return }
confirm(message: String.localizedStringWithFormat(
NSLocalizedString("account.domain-block.confirm-%@", comment: ""),
domain),
style: .destructive) {
accountViewModel.domainBlock()
}
}
func confirmDomainUnblock(accountViewModel: AccountViewModel) {
guard let domain = accountViewModel.domain else { return }
confirm(message: String.localizedStringWithFormat(
NSLocalizedString("account.domain-unblock.confirm-%@", comment: ""),
domain)) {
accountViewModel.domainUnblock()
}
}
func accountListEdit(accountViewModel: AccountViewModel, edit: CollectionItemEvent.AccountListEdit) { func accountListEdit(accountViewModel: AccountViewModel, edit: CollectionItemEvent.AccountListEdit) {
viewModel.applyAccountListEdit(viewModel: accountViewModel, edit: edit) viewModel.applyAccountListEdit(viewModel: accountViewModel, edit: edit)
} }

View file

@ -11,6 +11,10 @@ public enum CollectionItemEvent {
case attachment(AttachmentViewModel, StatusViewModel) case attachment(AttachmentViewModel, StatusViewModel)
case compose(inReplyTo: StatusViewModel?, redraft: Status?) case compose(inReplyTo: StatusViewModel?, redraft: Status?)
case confirmDelete(StatusViewModel, redraft: Bool) case confirmDelete(StatusViewModel, redraft: Bool)
case confirmBlock(AccountViewModel)
case confirmUnblock(AccountViewModel)
case confirmDomainBlock(AccountViewModel)
case confirmDomainUnblock(AccountViewModel)
case report(ReportViewModel) case report(ReportViewModel)
case share(URL) case share(URL)
case accountListEdit(AccountViewModel, AccountListEdit) case accountListEdit(AccountViewModel, AccountListEdit)

View file

@ -111,10 +111,18 @@ public extension AccountViewModel {
ignorableOutputEvent(accountService.showReblogs()) ignorableOutputEvent(accountService.showReblogs())
} }
func confirmBlock() {
eventsSubject.send(Just(.confirmBlock(self)).setFailureType(to: Error.self).eraseToAnyPublisher())
}
func block() { func block() {
ignorableOutputEvent(accountService.block()) ignorableOutputEvent(accountService.block())
} }
func confirmUnblock() {
eventsSubject.send(Just(.confirmUnblock(self)).setFailureType(to: Error.self).eraseToAnyPublisher())
}
func unblock() { func unblock() {
ignorableOutputEvent(accountService.unblock()) ignorableOutputEvent(accountService.unblock())
} }
@ -147,10 +155,18 @@ public extension AccountViewModel {
accountListEdit(accountService.rejectFollowRequest(), event: .rejectFollowRequest) accountListEdit(accountService.rejectFollowRequest(), event: .rejectFollowRequest)
} }
func confirmDomainBlock(domain: String) {
eventsSubject.send(Just(.confirmDomainBlock(self)).setFailureType(to: Error.self).eraseToAnyPublisher())
}
func domainBlock() { func domainBlock() {
ignorableOutputEvent(accountService.domainBlock()) ignorableOutputEvent(accountService.domainBlock())
} }
func confirmDomainUnblock(domain: String) {
eventsSubject.send(Just(.confirmDomainUnblock(self)).setFailureType(to: Error.self).eraseToAnyPublisher())
}
func domainUnblock() { func domainUnblock() {
ignorableOutputEvent(accountService.domainUnblock()) ignorableOutputEvent(accountService.domainUnblock())
} }

View file

@ -625,10 +625,11 @@ private extension StatusView {
accessibilityCustomActions = accessibilityCustomActions(viewModel: viewModel) accessibilityCustomActions = accessibilityCustomActions(viewModel: viewModel)
} }
// swiftlint:enable function_body_length
func menu(viewModel: StatusViewModel) -> UIMenu { func menu(viewModel: StatusViewModel) -> UIMenu {
var menuItems = [ var sections = [UIMenu]()
var firstSectionItems = [
UIAction( UIAction(
title: viewModel.bookmarked title: viewModel.bookmarked
? NSLocalizedString("status.unbookmark", comment: "") ? NSLocalizedString("status.unbookmark", comment: "")
@ -639,7 +640,7 @@ private extension StatusView {
] ]
if let pinned = viewModel.pinned { if let pinned = viewModel.pinned {
menuItems.append(UIAction( firstSectionItems.append(UIAction(
title: pinned title: pinned
? NSLocalizedString("status.unpin", comment: "") ? NSLocalizedString("status.unpin", comment: "")
: NSLocalizedString("status.pin", comment: ""), : NSLocalizedString("status.pin", comment: ""),
@ -648,8 +649,12 @@ private extension StatusView {
}) })
} }
sections.append(UIMenu(options: .displayInline, children: firstSectionItems))
var secondSectionItems = [UIAction]()
if viewModel.isMine { if viewModel.isMine {
menuItems += [ secondSectionItems += [
UIAction( UIAction(
title: viewModel.muted title: viewModel.muted
? NSLocalizedString("status.unmute", comment: "") ? NSLocalizedString("status.unmute", comment: "")
@ -671,16 +676,80 @@ private extension StatusView {
} }
] ]
} else { } else {
menuItems.append(UIAction( if let relationship = viewModel.accountViewModel.relationship {
if relationship.muting {
secondSectionItems.append(UIAction(
title: NSLocalizedString("account.unmute", comment: ""),
image: UIImage(systemName: "speaker")) { _ in
viewModel.accountViewModel.unmute()
})
} else {
secondSectionItems.append(UIAction(
title: NSLocalizedString("account.mute", comment: ""),
image: UIImage(systemName: "speaker.slash")) { _ in
viewModel.accountViewModel.mute()
})
}
if relationship.blocking {
secondSectionItems.append(UIAction(
title: NSLocalizedString("account.unblock", comment: ""),
image: UIImage(systemName: "slash.circle"),
attributes: .destructive) { _ in
// viewModel.accountViewModel.unblock()
viewModel.accountViewModel.confirmUnblock()
})
} else {
secondSectionItems.append(UIAction(
title: NSLocalizedString("account.block", comment: ""),
image: UIImage(systemName: "slash.circle"),
attributes: .destructive) { _ in
viewModel.accountViewModel.confirmBlock()
})
}
}
secondSectionItems.append(UIAction(
title: NSLocalizedString("report", comment: ""), title: NSLocalizedString("report", comment: ""),
image: UIImage(systemName: "flag"), image: UIImage(systemName: "flag"),
attributes: .destructive) { _ in attributes: .destructive) { _ in
viewModel.reportStatus() viewModel.reportStatus()
}) })
sections.append(UIMenu(options: .displayInline, children: secondSectionItems))
if !viewModel.accountViewModel.isLocal,
let domain = viewModel.accountViewModel.domain,
let relationship = viewModel.accountViewModel.relationship {
let domainBlockAction: UIAction
if relationship.domainBlocking {
domainBlockAction = UIAction(
title: String.localizedStringWithFormat(
NSLocalizedString("account.domain-unblock-%@", comment: ""),
domain),
image: UIImage(systemName: "slash.circle"),
attributes: .destructive) { _ in
viewModel.accountViewModel.confirmDomainUnblock(domain: domain)
}
} else {
domainBlockAction = UIAction(
title: String.localizedStringWithFormat(
NSLocalizedString("account.domain-block-%@", comment: ""),
domain),
image: UIImage(systemName: "slash.circle"),
attributes: .destructive) { _ in
viewModel.accountViewModel.confirmDomainBlock(domain: domain)
}
}
sections.append(UIMenu(options: .displayInline, children: [domainBlockAction]))
}
} }
return UIMenu(children: menuItems) return UIMenu(children: sections)
} }
// swiftlint:enable function_body_length
func setButtonImages(scale: UIImage.SymbolScale) { func setButtonImages(scale: UIImage.SymbolScale) {
let visibility = statusConfiguration.viewModel.visibility let visibility = statusConfiguration.viewModel.visibility