mirror of
https://github.com/mastodon/mastodon-ios
synced 2025-04-11 22:58:02 +02:00
Merge pull request #502 from j-f1/a11y-post-links
Add accessibility actions for links/mentions/hashtags in posts
This commit is contained in:
commit
ceee4bcf48
@ -136,6 +136,12 @@
|
|||||||
"vote": "Vote",
|
"vote": "Vote",
|
||||||
"closed": "Closed"
|
"closed": "Closed"
|
||||||
},
|
},
|
||||||
|
"meta_entity": {
|
||||||
|
"url": "Link: %s",
|
||||||
|
"hashtag": "Hastag %s",
|
||||||
|
"mention": "Show Profile: %s",
|
||||||
|
"email": "Email address: %s"
|
||||||
|
},
|
||||||
"actions": {
|
"actions": {
|
||||||
"reply": "Reply",
|
"reply": "Reply",
|
||||||
"reblog": "Reblog",
|
"reblog": "Reblog",
|
||||||
|
@ -136,6 +136,12 @@
|
|||||||
"vote": "Vote",
|
"vote": "Vote",
|
||||||
"closed": "Closed"
|
"closed": "Closed"
|
||||||
},
|
},
|
||||||
|
"meta_entity": {
|
||||||
|
"url": "Link: %s",
|
||||||
|
"hashtag": "Hastag %s",
|
||||||
|
"mention": "Show Profile: %s",
|
||||||
|
"email": "Email address: %s"
|
||||||
|
},
|
||||||
"actions": {
|
"actions": {
|
||||||
"reply": "Reply",
|
"reply": "Reply",
|
||||||
"reblog": "Reblog",
|
"reblog": "Reblog",
|
||||||
|
@ -99,6 +99,10 @@ extension StatusTableViewCell {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override var accessibilityCustomActions: [UIAccessibilityCustomAction]? {
|
||||||
|
get { statusView.accessibilityCustomActions }
|
||||||
|
set { }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - AdaptiveContainerMarginTableViewCell
|
// MARK: - AdaptiveContainerMarginTableViewCell
|
||||||
|
@ -314,6 +314,24 @@ public enum L10n {
|
|||||||
/// Undo reblog
|
/// Undo reblog
|
||||||
public static let unreblog = L10n.tr("Localizable", "Common.Controls.Status.Actions.Unreblog")
|
public static let unreblog = L10n.tr("Localizable", "Common.Controls.Status.Actions.Unreblog")
|
||||||
}
|
}
|
||||||
|
public enum MetaEntity {
|
||||||
|
/// Email address: %@
|
||||||
|
public static func email(_ p1: Any) -> String {
|
||||||
|
return L10n.tr("Localizable", "Common.Controls.Status.MetaEntity.Email", String(describing: p1))
|
||||||
|
}
|
||||||
|
/// Hastag %@
|
||||||
|
public static func hashtag(_ p1: Any) -> String {
|
||||||
|
return L10n.tr("Localizable", "Common.Controls.Status.MetaEntity.Hashtag", String(describing: p1))
|
||||||
|
}
|
||||||
|
/// Show Profile: %@
|
||||||
|
public static func mention(_ p1: Any) -> String {
|
||||||
|
return L10n.tr("Localizable", "Common.Controls.Status.MetaEntity.Mention", String(describing: p1))
|
||||||
|
}
|
||||||
|
/// Link: %@
|
||||||
|
public static func url(_ p1: Any) -> String {
|
||||||
|
return L10n.tr("Localizable", "Common.Controls.Status.MetaEntity.Url", String(describing: p1))
|
||||||
|
}
|
||||||
|
}
|
||||||
public enum Poll {
|
public enum Poll {
|
||||||
/// Closed
|
/// Closed
|
||||||
public static let closed = L10n.tr("Localizable", "Common.Controls.Status.Poll.Closed")
|
public static let closed = L10n.tr("Localizable", "Common.Controls.Status.Poll.Closed")
|
||||||
|
@ -108,6 +108,10 @@ Please check your internet connection.";
|
|||||||
"Common.Controls.Status.Actions.Unreblog" = "Undo reblog";
|
"Common.Controls.Status.Actions.Unreblog" = "Undo reblog";
|
||||||
"Common.Controls.Status.ContentWarning" = "Content Warning";
|
"Common.Controls.Status.ContentWarning" = "Content Warning";
|
||||||
"Common.Controls.Status.MediaContentWarning" = "Tap anywhere to reveal";
|
"Common.Controls.Status.MediaContentWarning" = "Tap anywhere to reveal";
|
||||||
|
"Common.Controls.Status.MetaEntity.Email" = "Email address: %@";
|
||||||
|
"Common.Controls.Status.MetaEntity.Hashtag" = "Hastag %@";
|
||||||
|
"Common.Controls.Status.MetaEntity.Mention" = "Show Profile: %@";
|
||||||
|
"Common.Controls.Status.MetaEntity.Url" = "Link: %@";
|
||||||
"Common.Controls.Status.Poll.Closed" = "Closed";
|
"Common.Controls.Status.Poll.Closed" = "Closed";
|
||||||
"Common.Controls.Status.Poll.Vote" = "Vote";
|
"Common.Controls.Status.Poll.Vote" = "Vote";
|
||||||
"Common.Controls.Status.SensitiveContent" = "Sensitive Content";
|
"Common.Controls.Status.SensitiveContent" = "Sensitive Content";
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// MetaEntity+Accessibility.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Jed Fox on 2022-11-03.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Meta
|
||||||
|
import MastodonLocalization
|
||||||
|
|
||||||
|
extension Meta.Entity {
|
||||||
|
var accessibilityCustomActionLabel: String? {
|
||||||
|
switch meta {
|
||||||
|
case .url(_, trimmed: _, url: let url, userInfo: _):
|
||||||
|
return L10n.Common.Controls.Status.MetaEntity.url(url)
|
||||||
|
case .hashtag(_, hashtag: let hashtag, userInfo: _):
|
||||||
|
return L10n.Common.Controls.Status.MetaEntity.hashtag(hashtag)
|
||||||
|
case .mention(_, mention: let mention, userInfo: _):
|
||||||
|
return L10n.Common.Controls.Status.MetaEntity.mention(mention)
|
||||||
|
case .email(let email, userInfo: _):
|
||||||
|
return L10n.Common.Controls.Status.MetaEntity.email(email)
|
||||||
|
// emoji are not actionable
|
||||||
|
case .emoji:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -315,7 +315,6 @@ extension StatusView.ViewModel {
|
|||||||
statusView.contentMetaText.configure(
|
statusView.contentMetaText.configure(
|
||||||
content: content
|
content: content
|
||||||
)
|
)
|
||||||
statusView.contentMetaText.textView.accessibilityLabel = content.string
|
|
||||||
statusView.contentMetaText.textView.accessibilityTraits = [.staticText]
|
statusView.contentMetaText.textView.accessibilityTraits = [.staticText]
|
||||||
statusView.contentMetaText.textView.accessibilityElementsHidden = false
|
statusView.contentMetaText.textView.accessibilityElementsHidden = false
|
||||||
} else {
|
} else {
|
||||||
@ -727,8 +726,23 @@ extension StatusView.ViewModel {
|
|||||||
statusView.accessibilityLabel = accessibilityLabel
|
statusView.accessibilityLabel = accessibilityLabel
|
||||||
}
|
}
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
|
|
||||||
|
Publishers.CombineLatest(
|
||||||
|
$content,
|
||||||
|
$isContentReveal.removeDuplicates()
|
||||||
|
)
|
||||||
|
.map { content, isRevealed in
|
||||||
|
guard isRevealed, let entities = content?.entities else { return [] }
|
||||||
|
return entities.compactMap { entity in
|
||||||
|
guard let name = entity.accessibilityCustomActionLabel else { return nil }
|
||||||
|
return UIAccessibilityCustomAction(name: name) { action in
|
||||||
|
statusView.delegate?.statusView(statusView, metaText: statusView.contentMetaText, didSelectMeta: entity.meta)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.assign(to: \.accessibilityCustomActions, on: statusView.contentMetaText.textView)
|
||||||
|
.store(in: &disposeBag)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -547,6 +547,13 @@ extension StatusView {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension StatusView {
|
||||||
|
public override var accessibilityCustomActions: [UIAccessibilityCustomAction]? {
|
||||||
|
get { contentMetaText.textView.accessibilityCustomActions }
|
||||||
|
set { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - AdaptiveContainerView
|
// MARK: - AdaptiveContainerView
|
||||||
extension StatusView: AdaptiveContainerView {
|
extension StatusView: AdaptiveContainerView {
|
||||||
public func updateContainerViewComponentsLayoutMarginsRelativeArrangementBehavior(isEnabled: Bool) {
|
public func updateContainerViewComponentsLayoutMarginsRelativeArrangementBehavior(isEnabled: Bool) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user