Bell button

This commit is contained in:
Justin Mazzocchi 2021-02-25 22:22:40 -08:00
parent 2bab10b0fb
commit 5749225786
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
7 changed files with 77 additions and 8 deletions

View file

@ -290,6 +290,12 @@ extension ContentDatabase {
} }
} }
migrator.registerMigration("1.0.0-notifying") { db in
try db.alter(table: "relationship") { t in
t.add(column: "notifying", .boolean)
}
}
return migrator return migrator
} }
} }

View file

@ -34,6 +34,7 @@
"account.mute.confirm.duration" = "Duration"; "account.mute.confirm.duration" = "Duration";
"account.mute.target-%@" = "Mute %@"; "account.mute.target-%@" = "Mute %@";
"account.muted" = "Muted"; "account.muted" = "Muted";
"account.notify" = "Turn on notifications";
"account.reject-follow-request-button.accessibility-label" = "Reject follow request"; "account.reject-follow-request-button.accessibility-label" = "Reject follow request";
"account.request" = "Request"; "account.request" = "Request";
"account.request.cancel" = "Cancel follow request"; "account.request.cancel" = "Cancel follow request";
@ -51,6 +52,7 @@
"account.unfollow.confirm-%@" = "Unfollow %@?"; "account.unfollow.confirm-%@" = "Unfollow %@?";
"account.unmute" = "Unmute"; "account.unmute" = "Unmute";
"account.unmute.confirm-%@" = "Unmute %@?"; "account.unmute.confirm-%@" = "Unmute %@?";
"account.unnotify" = "Turn off notifications";
"activity.open-in-default-browser" = "Open in default browser"; "activity.open-in-default-browser" = "Open in default browser";
"add" = "Add"; "add" = "Add";
"apns-default-message" = "New notification"; "apns-default-message" = "New notification";

View file

@ -11,6 +11,7 @@ public struct Relationship: Codable, Hashable {
public let muting: Bool public let muting: Bool
@DecodableDefault.False public private(set) var mutingNotifications: Bool @DecodableDefault.False public private(set) var mutingNotifications: Bool
@DecodableDefault.False public private(set) var showingReblogs: Bool @DecodableDefault.False public private(set) var showingReblogs: Bool
public let notifying: Bool?
public let blocking: Bool public let blocking: Bool
public let domainBlocking: Bool public let domainBlocking: Bool
@DecodableDefault.False public private(set) var blockedBy: Bool @DecodableDefault.False public private(set) var blockedBy: Bool

View file

@ -5,7 +5,7 @@ import HTTP
import Mastodon import Mastodon
public enum RelationshipEndpoint { public enum RelationshipEndpoint {
case accountsFollow(id: Account.Id, showReblogs: Bool? = nil) case accountsFollow(id: Account.Id, showReblogs: Bool? = nil, notify: Bool? = nil)
case accountsUnfollow(id: Account.Id) case accountsUnfollow(id: Account.Id)
case accountsBlock(id: Account.Id) case accountsBlock(id: Account.Id)
case accountsUnblock(id: Account.Id) case accountsUnblock(id: Account.Id)
@ -32,7 +32,7 @@ extension RelationshipEndpoint: Endpoint {
public var pathComponentsInContext: [String] { public var pathComponentsInContext: [String] {
switch self { switch self {
case let .accountsFollow(id, _): case let .accountsFollow(id, _, _):
return [id, "follow"] return [id, "follow"]
case let .accountsUnfollow(id): case let .accountsUnfollow(id):
return [id, "unfollow"] return [id, "unfollow"]
@ -59,12 +59,18 @@ extension RelationshipEndpoint: Endpoint {
public var queryParameters: [URLQueryItem] { public var queryParameters: [URLQueryItem] {
switch self { switch self {
case let .accountsFollow(_, showReblogs): case let .accountsFollow(_, showReblogs, notify):
var params = [URLQueryItem]()
if let showReblogs = showReblogs { if let showReblogs = showReblogs {
return [URLQueryItem(name: "reblogs", value: String(showReblogs))] params.append(URLQueryItem(name: "reblogs", value: String(showReblogs)))
} else {
return []
} }
if let notify = notify {
params.append(URLQueryItem(name: "notify", value: String(notify)))
}
return params
default: default:
return [] return []
} }

View file

@ -51,6 +51,14 @@ public extension AccountService {
relationshipAction(.accountsFollow(id: account.id, showReblogs: true)) relationshipAction(.accountsFollow(id: account.id, showReblogs: true))
} }
func notify() -> AnyPublisher<Never, Error> {
relationshipAction(.accountsFollow(id: account.id, notify: true))
}
func unnotify() -> AnyPublisher<Never, Error> {
relationshipAction(.accountsFollow(id: account.id, notify: false))
}
func block() -> AnyPublisher<Never, Error> { func block() -> AnyPublisher<Never, Error> {
relationshipAction(.accountsBlock(id: account.id)) relationshipAction(.accountsBlock(id: account.id))
.collect() .collect()

View file

@ -137,6 +137,14 @@ public extension AccountViewModel {
ignorableOutputEvent(accountService.showReblogs()) ignorableOutputEvent(accountService.showReblogs())
} }
func notify() {
ignorableOutputEvent(accountService.notify())
}
func unnotify() {
ignorableOutputEvent(accountService.unnotify())
}
func confirmBlock() { func confirmBlock() {
eventsSubject.send(Just(.confirmBlock(self)).setFailureType(to: Error.self).eraseToAnyPublisher()) eventsSubject.send(Just(.confirmBlock(self)).setFailureType(to: Error.self).eraseToAnyPublisher())
} }

View file

@ -15,6 +15,8 @@ final class AccountHeaderView: UIView {
let relationshipButtonsStackView = UIStackView() let relationshipButtonsStackView = UIStackView()
let followButton = UIButton(type: .system) let followButton = UIButton(type: .system)
let unfollowButton = UIButton(type: .system) let unfollowButton = UIButton(type: .system)
let notifyButton = UIButton()
let unnotifyButton = UIButton()
let displayNameLabel = AnimatedAttachmentLabel() let displayNameLabel = AnimatedAttachmentLabel()
let accountStackView = UIStackView() let accountStackView = UIStackView()
let accountLabel = UILabel() let accountLabel = UILabel()
@ -69,6 +71,19 @@ final class AccountHeaderView: UIView {
comment: ""), comment: ""),
for: .normal) for: .normal)
if relationship.following, let notifying = relationship.notifying {
if notifying {
notifyButton.isHidden = true
unnotifyButton.isHidden = false
} else {
notifyButton.isHidden = false
unnotifyButton.isHidden = true
}
} else {
notifyButton.isHidden = true
unnotifyButton.isHidden = true
}
relationshipButtonsStackView.isHidden = false relationshipButtonsStackView.isHidden = false
unavailableLabel.isHidden = !relationship.blockedBy unavailableLabel.isHidden = !relationship.blockedBy
} else { } else {
@ -201,7 +216,7 @@ final class AccountHeaderView: UIView {
override func layoutSubviews() { override func layoutSubviews() {
super.layoutSubviews() super.layoutSubviews()
for button in [followButton, unfollowButton] { for button in [followButton, unfollowButton, notifyButton, unnotifyButton] {
let inset = (followButton.bounds.height - (button.titleLabel?.bounds.height ?? 0)) / 2 let inset = (followButton.bounds.height - (button.titleLabel?.bounds.height ?? 0)) / 2
button.contentEdgeInsets = .init(top: 0, left: inset, bottom: 0, right: inset) button.contentEdgeInsets = .init(top: 0, left: inset, bottom: 0, right: inset)
@ -284,7 +299,7 @@ private extension AccountHeaderView {
relationshipButtonsStackView.spacing = .defaultSpacing relationshipButtonsStackView.spacing = .defaultSpacing
relationshipButtonsStackView.addArrangedSubview(UIView()) relationshipButtonsStackView.addArrangedSubview(UIView())
for button in [followButton, unfollowButton] { for button in [followButton, unfollowButton, notifyButton, unnotifyButton] {
relationshipButtonsStackView.addArrangedSubview(button) relationshipButtonsStackView.addArrangedSubview(button)
button.titleLabel?.font = .preferredFont(forTextStyle: .headline) button.titleLabel?.font = .preferredFont(forTextStyle: .headline)
button.titleLabel?.adjustsFontForContentSizeCategory = true button.titleLabel?.adjustsFontForContentSizeCategory = true
@ -296,6 +311,7 @@ private extension AccountHeaderView {
systemName: "person.badge.plus", systemName: "person.badge.plus",
withConfiguration: UIImage.SymbolConfiguration(scale: .small)), withConfiguration: UIImage.SymbolConfiguration(scale: .small)),
for: .normal) for: .normal)
followButton.isHidden = true
followButton.addAction( followButton.addAction(
UIAction { [weak self] _ in self?.viewModel.accountViewModel?.follow() }, UIAction { [weak self] _ in self?.viewModel.accountViewModel?.follow() },
for: .touchUpInside) for: .touchUpInside)
@ -306,10 +322,32 @@ private extension AccountHeaderView {
withConfiguration: UIImage.SymbolConfiguration(scale: .small)), withConfiguration: UIImage.SymbolConfiguration(scale: .small)),
for: .normal) for: .normal)
unfollowButton.setTitle(NSLocalizedString("account.unfollow", comment: ""), for: .normal) unfollowButton.setTitle(NSLocalizedString("account.unfollow", comment: ""), for: .normal)
unfollowButton.isHidden = true
unfollowButton.addAction( unfollowButton.addAction(
UIAction { [weak self] _ in self?.viewModel.accountViewModel?.confirmUnfollow() }, UIAction { [weak self] _ in self?.viewModel.accountViewModel?.confirmUnfollow() },
for: .touchUpInside) for: .touchUpInside)
notifyButton.setImage(
UIImage(systemName: "bell",
withConfiguration: UIImage.SymbolConfiguration(scale: .large)),
for: .normal)
notifyButton.accessibilityLabel = NSLocalizedString("account.notify", comment: "")
notifyButton.tintColor = .secondaryLabel
notifyButton.isHidden = true
notifyButton.addAction(
UIAction { [weak self] _ in self?.viewModel.accountViewModel?.notify() },
for: .touchUpInside)
unnotifyButton.setImage(
UIImage(systemName: "bell.fill",
withConfiguration: UIImage.SymbolConfiguration(scale: .large)),
for: .normal)
unnotifyButton.accessibilityLabel = NSLocalizedString("account.unnotify", comment: "")
unnotifyButton.isHidden = true
unnotifyButton.addAction(
UIAction { [weak self] _ in self?.viewModel.accountViewModel?.unnotify() },
for: .touchUpInside)
addSubview(baseStackView) addSubview(baseStackView)
baseStackView.translatesAutoresizingMaskIntoConstraints = false baseStackView.translatesAutoresizingMaskIntoConstraints = false
baseStackView.axis = .vertical baseStackView.axis = .vertical