Reblogger button
This commit is contained in:
parent
c4abbc764e
commit
b2e56a1b9b
|
@ -248,6 +248,7 @@
|
||||||
"search.scope.tags" = "Hashtags";
|
"search.scope.tags" = "Hashtags";
|
||||||
"share-extension-error.no-account-found" = "No account found";
|
"share-extension-error.no-account-found" = "No account found";
|
||||||
"status.accessibility.view-author-profile" = "View author's profile";
|
"status.accessibility.view-author-profile" = "View author's profile";
|
||||||
|
"status.accessibility.view-reblogger-profile" = "View booster's profile";
|
||||||
"status.bookmark" = "Bookmark";
|
"status.bookmark" = "Bookmark";
|
||||||
"status.content-warning-abbreviation" = "CW";
|
"status.content-warning-abbreviation" = "CW";
|
||||||
"status.content-warning.accessibility" = "Content warning";
|
"status.content-warning.accessibility" = "Content warning";
|
||||||
|
|
|
@ -88,6 +88,15 @@ public extension StatusViewModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var rebloggerAvatarURL: URL {
|
||||||
|
if !identityContext.appPreferences.shouldReduceMotion,
|
||||||
|
identityContext.appPreferences.animateAvatars == .everywhere {
|
||||||
|
return statusService.status.account.avatar
|
||||||
|
} else {
|
||||||
|
return statusService.status.account.avatarStatic
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var time: String? { statusService.status.displayStatus.createdAt.timeAgo }
|
var time: String? { statusService.status.displayStatus.createdAt.timeAgo }
|
||||||
|
|
||||||
var accessibilityTime: String? { statusService.status.displayStatus.createdAt.accessibilityTimeAgo }
|
var accessibilityTime: String? { statusService.status.displayStatus.createdAt.accessibilityTimeAgo }
|
||||||
|
@ -209,6 +218,16 @@ public extension StatusViewModel {
|
||||||
.eraseToAnyPublisher())
|
.eraseToAnyPublisher())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func rebloggerAccountSelected() {
|
||||||
|
eventsSubject.send(
|
||||||
|
Just(.navigation(
|
||||||
|
.profile(
|
||||||
|
statusService.navigationService.profileService(
|
||||||
|
account: statusService.status.account))))
|
||||||
|
.setFailureType(to: Error.self)
|
||||||
|
.eraseToAnyPublisher())
|
||||||
|
}
|
||||||
|
|
||||||
func rebloggedBySelected() {
|
func rebloggedBySelected() {
|
||||||
eventsSubject.send(
|
eventsSubject.send(
|
||||||
Just(.navigation(.collection(statusService.rebloggedByService())))
|
Just(.navigation(.collection(statusService.rebloggedByService())))
|
||||||
|
|
|
@ -12,6 +12,7 @@ final class StatusView: UIView {
|
||||||
let avatarButton = UIButton()
|
let avatarButton = UIButton()
|
||||||
let infoIcon = UIImageView()
|
let infoIcon = UIImageView()
|
||||||
let infoLabel = UILabel()
|
let infoLabel = UILabel()
|
||||||
|
let rebloggerButton = UIButton()
|
||||||
let displayNameLabel = UILabel()
|
let displayNameLabel = UILabel()
|
||||||
let accountLabel = UILabel()
|
let accountLabel = UILabel()
|
||||||
let timeLabel = UILabel()
|
let timeLabel = UILabel()
|
||||||
|
@ -44,6 +45,7 @@ final class StatusView: UIView {
|
||||||
private let inReplyToView = UIView()
|
private let inReplyToView = UIView()
|
||||||
private let hasReplyFollowingView = UIView()
|
private let hasReplyFollowingView = UIView()
|
||||||
private var statusConfiguration: StatusContentConfiguration
|
private var statusConfiguration: StatusContentConfiguration
|
||||||
|
private var infoIconCenterYConstraint: NSLayoutConstraint?
|
||||||
private var cancellables = Set<AnyCancellable>()
|
private var cancellables = Set<AnyCancellable>()
|
||||||
|
|
||||||
init(configuration: StatusContentConfiguration) {
|
init(configuration: StatusContentConfiguration) {
|
||||||
|
@ -135,6 +137,7 @@ private extension StatusView {
|
||||||
containerStackView.spacing = .defaultSpacing
|
containerStackView.spacing = .defaultSpacing
|
||||||
|
|
||||||
infoIcon.tintColor = .secondaryLabel
|
infoIcon.tintColor = .secondaryLabel
|
||||||
|
infoIcon.contentMode = .scaleAspectFit
|
||||||
infoIcon.setContentCompressionResistancePriority(.required, for: .vertical)
|
infoIcon.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||||
|
|
||||||
sideStackView.axis = .vertical
|
sideStackView.axis = .vertical
|
||||||
|
@ -154,6 +157,16 @@ private extension StatusView {
|
||||||
infoLabel.setContentHuggingPriority(.required, for: .vertical)
|
infoLabel.setContentHuggingPriority(.required, for: .vertical)
|
||||||
mainStackView.addArrangedSubview(infoLabel)
|
mainStackView.addArrangedSubview(infoLabel)
|
||||||
|
|
||||||
|
rebloggerButton.setTitleColor(.secondaryLabel, for: .normal)
|
||||||
|
rebloggerButton.titleLabel?.font = .preferredFont(forTextStyle: .caption1)
|
||||||
|
rebloggerButton.titleLabel?.adjustsFontForContentSizeCategory = true
|
||||||
|
rebloggerButton.contentHorizontalAlignment = .leading
|
||||||
|
rebloggerButton.setContentHuggingPriority(.required, for: .vertical)
|
||||||
|
mainStackView.addArrangedSubview(rebloggerButton)
|
||||||
|
rebloggerButton.addAction(
|
||||||
|
UIAction { [weak self] _ in self?.statusConfiguration.viewModel.rebloggerAccountSelected() },
|
||||||
|
for: .touchUpInside)
|
||||||
|
|
||||||
displayNameLabel.font = .preferredFont(forTextStyle: .headline)
|
displayNameLabel.font = .preferredFont(forTextStyle: .headline)
|
||||||
displayNameLabel.adjustsFontForContentSizeCategory = true
|
displayNameLabel.adjustsFontForContentSizeCategory = true
|
||||||
displayNameLabel.setContentHuggingPriority(.required, for: .horizontal)
|
displayNameLabel.setContentHuggingPriority(.required, for: .horizontal)
|
||||||
|
@ -322,7 +335,6 @@ private extension StatusView {
|
||||||
avatarImageView.widthAnchor.constraint(equalToConstant: .avatarDimension),
|
avatarImageView.widthAnchor.constraint(equalToConstant: .avatarDimension),
|
||||||
avatarHeightConstraint,
|
avatarHeightConstraint,
|
||||||
sideStackView.widthAnchor.constraint(equalToConstant: .avatarDimension),
|
sideStackView.widthAnchor.constraint(equalToConstant: .avatarDimension),
|
||||||
infoIcon.centerYAnchor.constraint(equalTo: infoLabel.centerYAnchor),
|
|
||||||
avatarButton.leadingAnchor.constraint(equalTo: avatarImageView.leadingAnchor),
|
avatarButton.leadingAnchor.constraint(equalTo: avatarImageView.leadingAnchor),
|
||||||
avatarButton.topAnchor.constraint(equalTo: avatarImageView.topAnchor),
|
avatarButton.topAnchor.constraint(equalTo: avatarImageView.topAnchor),
|
||||||
avatarButton.bottomAnchor.constraint(equalTo: avatarImageView.bottomAnchor),
|
avatarButton.bottomAnchor.constraint(equalTo: avatarImageView.bottomAnchor),
|
||||||
|
@ -373,16 +385,31 @@ private extension StatusView {
|
||||||
inReplyToView.isHidden = !viewModel.configuration.isReplyInContext
|
inReplyToView.isHidden = !viewModel.configuration.isReplyInContext
|
||||||
hasReplyFollowingView.isHidden = !viewModel.configuration.hasReplyFollowing
|
hasReplyFollowingView.isHidden = !viewModel.configuration.hasReplyFollowing
|
||||||
|
|
||||||
if viewModel.isReblog {
|
if viewModel.isReblog, let titleLabel = rebloggerButton.titleLabel {
|
||||||
infoLabel.attributedText = "status.reblogged-by".localizedBolding(
|
let attributedTitle = "status.reblogged-by".localizedBolding(
|
||||||
displayName: viewModel.rebloggedByDisplayName,
|
displayName: viewModel.rebloggedByDisplayName,
|
||||||
emojis: viewModel.rebloggedByDisplayNameEmojis,
|
emojis: viewModel.rebloggedByDisplayNameEmojis,
|
||||||
label: infoLabel)
|
label: titleLabel)
|
||||||
|
let highlightedAttributedTitle = NSMutableAttributedString(attributedString: attributedTitle)
|
||||||
|
|
||||||
|
highlightedAttributedTitle.addAttribute(
|
||||||
|
.foregroundColor,
|
||||||
|
value: UIColor.tertiaryLabel,
|
||||||
|
range: .init(location: 0, length: highlightedAttributedTitle.length))
|
||||||
|
rebloggerButton.setAttributedTitle(
|
||||||
|
attributedTitle,
|
||||||
|
for: .normal)
|
||||||
|
rebloggerButton.setAttributedTitle(
|
||||||
|
highlightedAttributedTitle,
|
||||||
|
for: .highlighted)
|
||||||
|
|
||||||
|
infoIcon.centerYAnchor.constraint(equalTo: rebloggerButton.centerYAnchor).isActive = true
|
||||||
infoIcon.image = UIImage(
|
infoIcon.image = UIImage(
|
||||||
systemName: "arrow.2.squarepath",
|
systemName: "arrow.2.squarepath",
|
||||||
withConfiguration: UIImage.SymbolConfiguration(scale: .small))
|
withConfiguration: UIImage.SymbolConfiguration(scale: .small))
|
||||||
infoLabel.isHidden = false
|
infoLabel.isHidden = true
|
||||||
infoIcon.isHidden = false
|
infoIcon.isHidden = false
|
||||||
|
rebloggerButton.isHidden = false
|
||||||
} else if viewModel.configuration.isPinned {
|
} else if viewModel.configuration.isPinned {
|
||||||
let pinnedText: String
|
let pinnedText: String
|
||||||
|
|
||||||
|
@ -394,16 +421,21 @@ private extension StatusView {
|
||||||
}
|
}
|
||||||
|
|
||||||
infoLabel.text = pinnedText
|
infoLabel.text = pinnedText
|
||||||
|
infoIcon.centerYAnchor.constraint(equalTo: infoLabel.centerYAnchor).isActive = true
|
||||||
infoIcon.image = UIImage(
|
infoIcon.image = UIImage(
|
||||||
systemName: "pin",
|
systemName: "pin",
|
||||||
withConfiguration: UIImage.SymbolConfiguration(scale: .small))
|
withConfiguration: UIImage.SymbolConfiguration(scale: .small))
|
||||||
infoLabel.isHidden = false
|
infoLabel.isHidden = false
|
||||||
infoIcon.isHidden = false
|
infoIcon.isHidden = false
|
||||||
|
rebloggerButton.isHidden = true
|
||||||
} else {
|
} else {
|
||||||
infoLabel.text = nil
|
infoLabel.text = nil
|
||||||
infoIcon.image = nil
|
infoIcon.image = nil
|
||||||
infoLabel.isHidden = true
|
infoLabel.isHidden = true
|
||||||
infoIcon.isHidden = true
|
infoIcon.isHidden = true
|
||||||
|
rebloggerButton.setTitle(nil, for: .normal)
|
||||||
|
rebloggerButton.setImage(nil, for: .normal)
|
||||||
|
rebloggerButton.isHidden = true
|
||||||
}
|
}
|
||||||
|
|
||||||
mutableDisplayName.insert(emojis: viewModel.accountViewModel.emojis, view: displayNameLabel)
|
mutableDisplayName.insert(emojis: viewModel.accountViewModel.emojis, view: displayNameLabel)
|
||||||
|
@ -496,6 +528,11 @@ private extension StatusView {
|
||||||
|
|
||||||
let accessibilityAttributedLabel = NSMutableAttributedString(string: "")
|
let accessibilityAttributedLabel = NSMutableAttributedString(string: "")
|
||||||
|
|
||||||
|
if !rebloggerButton.isHidden,
|
||||||
|
let rebloggerAttributedText = rebloggerButton.attributedTitle(for: .normal) {
|
||||||
|
accessibilityAttributedLabel.appendWithSeparator(rebloggerAttributedText)
|
||||||
|
}
|
||||||
|
|
||||||
if !infoLabel.isHidden, let infoText = infoLabel.attributedText {
|
if !infoLabel.isHidden, let infoText = infoLabel.attributedText {
|
||||||
accessibilityAttributedLabel.appendWithSeparator(infoText)
|
accessibilityAttributedLabel.appendWithSeparator(infoText)
|
||||||
}
|
}
|
||||||
|
@ -755,6 +792,17 @@ private extension StatusView {
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if viewModel.isReblog {
|
||||||
|
actions.append(
|
||||||
|
UIAccessibilityCustomAction(
|
||||||
|
name: NSLocalizedString("status.accessibility.view-reblogger-profile",
|
||||||
|
comment: "")) { [weak self] _ in
|
||||||
|
self?.statusConfiguration.viewModel.rebloggerAccountSelected()
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
actions.append(
|
actions.append(
|
||||||
UIAccessibilityCustomAction(
|
UIAccessibilityCustomAction(
|
||||||
name: NSLocalizedString("accessibility.copy-text",
|
name: NSLocalizedString("accessibility.copy-text",
|
||||||
|
|
Loading…
Reference in New Issue