More status actions

This commit is contained in:
Justin Mazzocchi 2021-01-10 19:12:06 -08:00
parent 015172b719
commit 96d96bd899
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
5 changed files with 84 additions and 9 deletions

View file

@ -156,16 +156,20 @@
"share-extension-error.no-account-found" = "No account found"; "share-extension-error.no-account-found" = "No account found";
"status.bookmark" = "Bookmark"; "status.bookmark" = "Bookmark";
"status.content-warning-abbreviation" = "CW"; "status.content-warning-abbreviation" = "CW";
"status.reblogged-by" = "%@ boosted"; "status.mute" = "Mute conversation";
"status.pin" = "Pin on profile";
"status.pinned-post" = "Pinned post"; "status.pinned-post" = "Pinned post";
"status.show-more" = "Show More";
"status.show-less" = "Show Less";
"status.poll.vote" = "Vote"; "status.poll.vote" = "Vote";
"status.poll.time-left" = "%@ left"; "status.poll.time-left" = "%@ left";
"status.poll.refresh" = "Refresh"; "status.poll.refresh" = "Refresh";
"status.poll.closed" = "Closed"; "status.poll.closed" = "Closed";
"status.reblogged-by" = "%@ boosted";
"status.show-more" = "Show More";
"status.show-less" = "Show Less";
"status.spoiler-text-placeholder" = "Write your warning here"; "status.spoiler-text-placeholder" = "Write your warning here";
"status.unbookmark" = "Unbookmark"; "status.unbookmark" = "Unbookmark";
"status.unmute" = "Unmute conversation";
"status.unpin" = "Unpin from profile";
"status.visibility.public" = "Public"; "status.visibility.public" = "Public";
"status.visibility.unlisted" = "Unlisted"; "status.visibility.unlisted" = "Unlisted";
"status.visibility.private" = "Followers-only"; "status.visibility.private" = "Followers-only";

View file

@ -12,6 +12,10 @@ public enum StatusEndpoint {
case unfavourite(id: Status.Id) case unfavourite(id: Status.Id)
case bookmark(id: Status.Id) case bookmark(id: Status.Id)
case unbookmark(id: Status.Id) case unbookmark(id: Status.Id)
case pin(id: Status.Id)
case unpin(id: Status.Id)
case mute(id: Status.Id)
case unmute(id: Status.Id)
case post(Components) case post(Components)
} }
@ -110,6 +114,14 @@ extension StatusEndpoint: Endpoint {
return [id, "bookmark"] return [id, "bookmark"]
case let .unbookmark(id): case let .unbookmark(id):
return [id, "unbookmark"] return [id, "unbookmark"]
case let .pin(id):
return [id, "pin"]
case let .unpin(id):
return [id, "unpin"]
case let .mute(id):
return [id, "mute"]
case let .unmute(id):
return [id, "unmute"]
case .post: case .post:
return [] return []
} }
@ -128,7 +140,7 @@ extension StatusEndpoint: Endpoint {
switch self { switch self {
case .status: case .status:
return .get return .get
case .reblog, .unreblog, .favourite, .unfavourite, .bookmark, .unbookmark, .post: default:
return .post return .post
} }
} }

View file

@ -56,6 +56,22 @@ public extension StatusService {
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }
func togglePinned() -> AnyPublisher<Never, Error> {
mastodonAPIClient.request(status.displayStatus.pinned ?? false
? StatusEndpoint.unpin(id: status.displayStatus.id)
: StatusEndpoint.pin(id: status.displayStatus.id))
.flatMap(contentDatabase.insert(status:))
.eraseToAnyPublisher()
}
func toggleMuted() -> AnyPublisher<Never, Error> {
mastodonAPIClient.request(status.displayStatus.muted
? StatusEndpoint.unmute(id: status.displayStatus.id)
: StatusEndpoint.mute(id: status.displayStatus.id))
.flatMap(contentDatabase.insert(status:))
.eraseToAnyPublisher()
}
func rebloggedByService() -> AccountListService { func rebloggedByService() -> AccountListService {
AccountListService( AccountListService(
endpoint: .rebloggedBy(id: status.id), endpoint: .rebloggedBy(id: status.id),

View file

@ -47,6 +47,8 @@ public final class StatusViewModel: CollectionItemViewModel, AttachmentsRenderin
} }
public extension StatusViewModel { public extension StatusViewModel {
var isMine: Bool { statusService.status.displayStatus.account.id == identification.identity.account?.id }
var shouldShowContent: Bool { var shouldShowContent: Bool {
guard spoilerText != "" else { return true } guard spoilerText != "" else { return true }
@ -113,6 +115,10 @@ public extension StatusViewModel {
var sensitive: Bool { statusService.status.displayStatus.sensitive } var sensitive: Bool { statusService.status.displayStatus.sensitive }
var pinned: Bool? { statusService.status.displayStatus.pinned }
var muted: Bool { statusService.status.displayStatus.muted }
var sharingURL: URL? { statusService.status.displayStatus.url } var sharingURL: URL? { statusService.status.displayStatus.url }
var isPollExpired: Bool { statusService.status.displayStatus.poll?.expired ?? true } var isPollExpired: Bool { statusService.status.displayStatus.poll?.expired ?? true }
@ -231,6 +237,20 @@ public extension StatusViewModel {
.eraseToAnyPublisher()) .eraseToAnyPublisher())
} }
func togglePinned() {
eventsSubject.send(
statusService.togglePinned()
.map { _ in .ignorableOutput }
.eraseToAnyPublisher())
}
func toggleMuted() {
eventsSubject.send(
statusService.toggleMuted()
.map { _ in .ignorableOutput }
.eraseToAnyPublisher())
}
func attachmentSelected(viewModel: AttachmentViewModel) { func attachmentSelected(viewModel: AttachmentViewModel) {
eventsSubject.send(Just(.attachment(viewModel, self)).setFailureType(to: Error.self).eraseToAnyPublisher()) eventsSubject.send(Just(.attachment(viewModel, self)).setFailureType(to: Error.self).eraseToAnyPublisher())
} }

View file

@ -398,21 +398,44 @@ private extension StatusView {
// swiftlint:enable function_body_length // swiftlint:enable function_body_length
func menu(viewModel: StatusViewModel) -> UIMenu { func menu(viewModel: StatusViewModel) -> UIMenu {
UIMenu(children: [ var menuItems = [
UIAction( UIAction(
title: viewModel.bookmarked title: viewModel.bookmarked
? NSLocalizedString("status.unbookmark", comment: "") ? NSLocalizedString("status.unbookmark", comment: "")
: NSLocalizedString("status.bookmark", comment: ""), : NSLocalizedString("status.bookmark", comment: ""),
image: UIImage(systemName: "bookmark")) { _ in image: UIImage(systemName: "bookmark")) { _ in
viewModel.toggleBookmarked() viewModel.toggleBookmarked()
}, }
UIAction( ]
if let pinned = viewModel.pinned {
menuItems.append(UIAction(
title: pinned
? NSLocalizedString("status.unpin", comment: "")
: NSLocalizedString("status.pin", comment: ""),
image: UIImage(systemName: "pin")) { _ in
viewModel.togglePinned()
})
}
if viewModel.isMine {
menuItems.append(UIAction(
title: viewModel.muted
? NSLocalizedString("status.unmute", comment: "")
: NSLocalizedString("status.mute", comment: ""),
image: UIImage(systemName: viewModel.muted ? "speaker" : "speaker.slash")) { _ in
viewModel.toggleMuted()
})
} else {
menuItems.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()
} })
]) }
return UIMenu(children: menuItems)
} }
func setButtonImages(scale: UIImage.SymbolScale) { func setButtonImages(scale: UIImage.SymbolScale) {