Merge pull request #713 from RyanRory/accessibility-ids-2

Add AccessibilityIDs
This commit is contained in:
RyanZhao 2022-12-06 15:15:19 +11:00 committed by GitHub
commit ff65c84504
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
40 changed files with 290 additions and 64 deletions

View file

@ -112,6 +112,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate {
private lazy var hangUpButton: UIButton = {
let result = UIButton(type: .custom)
result.accessibilityLabel = "End call button"
result.setImage(
UIImage(named: "EndCall")?
.withRenderingMode(.alwaysTemplate),

View file

@ -13,6 +13,8 @@ final class EditClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegat
let profileId: String
let role: GroupMember.Role
let profile: Profile?
let accessibilityLabel: String?
let accessibilityId: String?
}
private let threadId: String
@ -30,6 +32,8 @@ final class EditClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegat
private lazy var groupNameLabel: UILabel = {
let result: UILabel = UILabel()
result.accessibilityLabel = "Group name"
result.isAccessibilityElement = true
result.font = .boldSystemFont(ofSize: Values.veryLargeFontSize)
result.themeTextColor = .textPrimary
result.lineBreakMode = .byTruncatingTail
@ -44,12 +48,16 @@ final class EditClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegat
usesDefaultHeight: false
)
result.textAlignment = .center
result.isAccessibilityElement = true
result.accessibilityIdentifier = "Group name text field"
return result
}()
private lazy var addMembersButton: SessionButton = {
let result: SessionButton = SessionButton(style: .bordered, size: .medium)
result.accessibilityLabel = "Add members"
result.isAccessibilityElement = true
result.setTitle("vc_conversation_settings_invite_button_title".localized(), for: .normal)
result.addTarget(self, action: #selector(addMembers), for: UIControl.Event.touchUpInside)
result.contentEdgeInsets = UIEdgeInsets(top: 0, leading: Values.mediumSpacing, bottom: 0, trailing: Values.mediumSpacing)
@ -59,6 +67,9 @@ final class EditClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegat
@objc private lazy var tableView: UITableView = {
let result: UITableView = UITableView()
result.accessibilityLabel = "Contact"
result.accessibilityIdentifier = "Contact"
result.isAccessibilityElement = true
result.dataSource = self
result.delegate = self
result.separatorStyle = .none
@ -264,6 +275,12 @@ final class EditClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegat
}
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(handleDoneButtonTapped))
if isEditingGroupName {
doneButton.accessibilityLabel = "Accept name change"
}
else {
doneButton.accessibilityLabel = "Apply changes"
}
doneButton.themeTintColor = .textPrimary
navigationItem.rightBarButtonItem = doneButton
}
@ -343,7 +360,9 @@ final class EditClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegat
GroupMemberDisplayInfo(
profileId: profile.id,
role: .standard,
profile: profile
profile: profile,
accessibilityLabel: "Contact",
accessibilityId: "Contact"
)
}
self?.membersAndZombies = (self?.membersAndZombies ?? [])

View file

@ -48,6 +48,8 @@ final class NewClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegate
result.themeBorderColor = .borderSeparator
result.layer.cornerRadius = 13
result.delegate = self
result.accessibilityIdentifier = "Group name input"
result.isAccessibilityElement = true
return result
}()
@ -133,6 +135,8 @@ final class NewClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegate
result.translatesAutoresizingMaskIntoConstraints = false
result.setTitle("CREATE_GROUP_BUTTON_TITLE".localized(), for: .normal)
result.addTarget(self, action: #selector(createClosedGroup), for: .touchUpInside)
result.accessibilityIdentifier = "Create group"
result.isAccessibilityElement = true
result.set(.width, to: 160)
return result
@ -151,6 +155,8 @@ final class NewClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegate
let closeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "X"), style: .plain, target: self, action: #selector(close))
closeButton.themeTintColor = .textPrimary
navigationItem.rightBarButtonItem = closeButton
navigationItem.leftBarButtonItem?.accessibilityIdentifier = "Cancel"
navigationItem.leftBarButtonItem?.isAccessibilityElement = true
// Set up content
setUpViewHierarchy()
@ -204,8 +210,9 @@ final class NewClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegate
title: profile.displayName(),
rightAccessory: .radio(isSelected: { [weak self] in
self?.selectedContacts.contains(profile.id) == true
})
),
}),
accessibilityIdentifier: "Contact"
),
style: .edgeToEdge,
position: Position.with(indexPath.row, count: data[indexPath.section].elements.count)
)
@ -286,6 +293,7 @@ final class NewClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegate
explanation: message,
cancelTitle: "BUTTON_OK".localized(),
cancelStyle: .alert_text
)
)
present(modal, animated: true)

View file

@ -10,6 +10,7 @@ extension ContextMenuVC {
let isEmojiAction: Bool
let isEmojiPlus: Bool
let isDismissAction: Bool
let accessibilityLabel: String?
let work: () -> Void
// MARK: - Initialization
@ -20,6 +21,7 @@ extension ContextMenuVC {
isEmojiAction: Bool = false,
isEmojiPlus: Bool = false,
isDismissAction: Bool = false,
accessibilityLabel: String? = nil,
work: @escaping () -> Void
) {
self.icon = icon
@ -27,6 +29,7 @@ extension ContextMenuVC {
self.isEmojiAction = isEmojiAction
self.isEmojiPlus = isEmojiPlus
self.isDismissAction = isDismissAction
self.accessibilityLabel = accessibilityLabel
self.work = work
}
@ -35,7 +38,8 @@ extension ContextMenuVC {
static func reply(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
return Action(
icon: UIImage(named: "ic_reply"),
title: "context_menu_reply".localized()
title: "context_menu_reply".localized(),
accessibilityLabel: "Reply to message"
) { delegate?.reply(cellViewModel) }
}
@ -56,14 +60,16 @@ extension ContextMenuVC {
static func delete(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
return Action(
icon: UIImage(named: "ic_trash"),
title: "TXT_DELETE_TITLE".localized()
title: "TXT_DELETE_TITLE".localized(),
accessibilityLabel: "Delete message"
) { delegate?.delete(cellViewModel) }
}
static func save(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
return Action(
icon: UIImage(named: "ic_download"),
title: "context_menu_save".localized()
title: "context_menu_save".localized(),
accessibilityLabel: "Save attachment"
) { delegate?.save(cellViewModel) }
}

View file

@ -40,7 +40,7 @@ extension ContextMenuVC {
self.dismiss = dismiss
super.init(frame: CGRect.zero)
self.accessibilityLabel = action.accessibilityLabel
setUpViewHierarchy()
}

View file

@ -69,6 +69,8 @@ extension ConversationVC:
title: "modal_call_permission_request_title".localized(),
explanation: "modal_call_permission_request_explanation".localized(),
confirmTitle: "vc_settings_title".localized(),
confirmAccessibilityLabel: "Settings",
cancelAccessibilityLabel: "Cancel",
dismissOnConfirm: false // Custom dismissal logic
) { [weak self] _ in
self?.dismiss(animated: true) {
@ -135,6 +137,8 @@ extension ConversationVC:
range: (message as NSString).range(of: self.viewModel.threadData.displayName)
),
confirmTitle: "modal_blocked_button_title".localized(),
confirmAccessibilityLabel: "Confirm block",
cancelAccessibilityLabel: "Cancel block",
dismissOnConfirm: false // Custom dismissal logic
) { [weak self] _ in
self?.viewModel.unblockContact()
@ -854,6 +858,8 @@ extension ConversationVC:
range: (message as NSString).range(of: cellViewModel.authorName)
),
confirmTitle: "modal_download_button_title".localized(),
confirmAccessibilityLabel: "Download media",
cancelAccessibilityLabel: "Don't download media",
dismissOnConfirm: false // Custom dismissal logic
) { [weak self] _ in
self?.viewModel.trustContact()

View file

@ -196,8 +196,11 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl
lazy var blockedBanner: InfoBanner = {
let result: InfoBanner = InfoBanner(
message: self.viewModel.blockedBannerMessage,
backgroundColor: .danger
backgroundColor: .danger,
messageLabelAccessibilityLabel: "Blocked banner text"
)
result.accessibilityLabel = "Blocked banner"
result.isAccessibilityElement = true
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(unblock))
result.addGestureRecognizer(tapGestureRecognizer)
@ -245,6 +248,8 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl
private lazy var messageRequestAcceptButton: UIButton = {
let result: SessionButton = SessionButton(style: .bordered, size: .medium)
result.accessibilityLabel = "Accept message request"
result.isAccessibilityElement = true
result.translatesAutoresizingMaskIntoConstraints = false
result.setTitle("TXT_DELETE_ACCEPT".localized(), for: .normal)
result.addTarget(self, action: #selector(acceptMessageRequest), for: .touchUpInside)
@ -254,6 +259,8 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl
private lazy var messageRequestDeleteButton: UIButton = {
let result: SessionButton = SessionButton(style: .destructive, size: .medium)
result.accessibilityLabel = "Decline message request"
result.isAccessibilityElement = true
result.translatesAutoresizingMaskIntoConstraints = false
result.setTitle("TXT_DECLINE_TITLE".localized(), for: .normal)
result.addTarget(self, action: #selector(deleteMessageRequest), for: .touchUpInside)
@ -263,6 +270,7 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl
private lazy var messageRequestBlockButton: UIButton = {
let result: UIButton = UIButton()
result.accessibilityLabel = "Block message request"
result.translatesAutoresizingMaskIntoConstraints = false
result.clipsToBounds = true
result.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
@ -1099,7 +1107,7 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl
profilePictureView.addGestureRecognizer(tapGestureRecognizer)
let settingsButtonItem: UIBarButtonItem = UIBarButtonItem(customView: profilePictureView)
settingsButtonItem.accessibilityLabel = "Settings button"
settingsButtonItem.accessibilityLabel = "More options"
settingsButtonItem.isAccessibilityElement = true
if SessionCall.isEnabled && !threadData.threadIsNoteToSelf {
@ -1109,6 +1117,7 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl
target: self,
action: #selector(startCall)
)
callButton.accessibilityLabel = "Call button"
navigationItem.rightBarButtonItems = [settingsButtonItem, callButton]
}
@ -1118,7 +1127,7 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl
default:
let rightBarButtonItem: UIBarButtonItem = UIBarButtonItem(image: UIImage(named: "Gear"), style: .plain, target: self, action: #selector(openSettings))
rightBarButtonItem.accessibilityLabel = "Settings button"
rightBarButtonItem.accessibilityLabel = "More options"
rightBarButtonItem.isAccessibilityElement = true
navigationItem.rightBarButtonItems = [rightBarButtonItem]

View file

@ -26,28 +26,28 @@ final class ExpandingAttachmentsButton: UIView, InputViewButtonDelegate {
// MARK: UI Components
lazy var gifButton: InputViewButton = {
let result = InputViewButton(icon: #imageLiteral(resourceName: "actionsheet_gif_black"), delegate: self, hasOpaqueBackground: true)
result.accessibilityLabel = "accessibility_gif_button".localized()
result.accessibilityLabel = "GIF button"
return result
}()
lazy var gifButtonContainer = container(for: gifButton)
lazy var documentButton: InputViewButton = {
let result = InputViewButton(icon: #imageLiteral(resourceName: "actionsheet_document_black"), delegate: self, hasOpaqueBackground: true)
result.accessibilityLabel = "accessibility_document_button".localized()
result.accessibilityLabel = "Documents folder"
return result
}()
lazy var documentButtonContainer = container(for: documentButton)
lazy var libraryButton: InputViewButton = {
let result = InputViewButton(icon: #imageLiteral(resourceName: "actionsheet_camera_roll_black"), delegate: self, hasOpaqueBackground: true)
result.accessibilityLabel = "accessibility_library_button".localized()
result.accessibilityLabel = "Images folder"
return result
}()
lazy var libraryButtonContainer = container(for: libraryButton)
lazy var cameraButton: InputViewButton = {
let result = InputViewButton(icon: #imageLiteral(resourceName: "actionsheet_camera_black"), delegate: self, hasOpaqueBackground: true)
result.accessibilityLabel = "accessibility_camera_button".localized()
result.accessibilityLabel = "Select camera button"
return result
}()

View file

@ -50,12 +50,18 @@ final class InputView: UIView, InputViewButtonDelegate, InputTextViewDelegate, M
// MARK: - UI
private var bottomStackView: UIStackView?
private lazy var attachmentsButton = ExpandingAttachmentsButton(delegate: delegate)
private lazy var attachmentsButton: ExpandingAttachmentsButton = {
let result = ExpandingAttachmentsButton(delegate: delegate)
result.accessibilityLabel = "Attachments button"
result.isAccessibilityElement = true
return result
}()
private lazy var voiceMessageButton: InputViewButton = {
let result = InputViewButton(icon: #imageLiteral(resourceName: "Microphone"), delegate: self)
result.accessibilityLabel = "VOICE_MESSAGE_TOO_SHORT_ALERT_TITLE".localized()
result.accessibilityHint = "VOICE_MESSAGE_TOO_SHORT_ALERT_MESSAGE".localized()
result.accessibilityLabel = "New voice message"
result.isAccessibilityElement = true
return result
}()
@ -63,7 +69,8 @@ final class InputView: UIView, InputViewButtonDelegate, InputTextViewDelegate, M
private lazy var sendButton: InputViewButton = {
let result = InputViewButton(icon: #imageLiteral(resourceName: "ArrowUp"), isSendButton: true, delegate: self)
result.isHidden = true
result.accessibilityLabel = "ATTACHMENT_APPROVAL_SEND_BUTTON".localized()
result.accessibilityLabel = "Send message button"
result.isAccessibilityElement = true
return result
}()
@ -78,6 +85,8 @@ final class InputView: UIView, InputViewButtonDelegate, InputTextViewDelegate, M
private lazy var mentionsViewContainer: UIView = {
let result: UIView = UIView()
result.accessibilityLabel = "Mentions list"
result.isAccessibilityElement = true
result.alpha = 0
let backgroundView = UIView()
@ -107,7 +116,11 @@ final class InputView: UIView, InputViewButtonDelegate, InputTextViewDelegate, M
// setUpViewHierarchy() for why these values are the way they are.
let adjustment = (InputViewButton.expandedSize - InputViewButton.size) / 2
let maxWidth = UIScreen.main.bounds.width - 2 * InputViewButton.expandedSize - 2 * Values.smallSpacing - 2 * (Values.mediumSpacing - adjustment)
return InputTextView(delegate: self, maxWidth: maxWidth)
let result = InputTextView(delegate: self, maxWidth: maxWidth)
result.accessibilityLabel = "Message input box"
result.isAccessibilityElement = true
return result
}()
private lazy var disabledInputLabel: UILabel = {

View file

@ -24,6 +24,7 @@ final class MentionSelectionView: UIView, UITableViewDataSource, UITableViewDele
private lazy var tableView: UITableView = {
let result: UITableView = UITableView()
result.accessibilityLabel = "Contact"
result.dataSource = self
result.delegate = self
result.separatorStyle = .none

View file

@ -12,7 +12,7 @@ final class MediaPlaceholderView: UIView {
init(cellViewModel: MessageViewModel, textColor: ThemeValue) {
super.init(frame: CGRect.zero)
self.accessibilityLabel = "Untrusted attachment message"
setUpViewHierarchy(cellViewModel: cellViewModel, textColor: textColor)
}

View file

@ -70,6 +70,8 @@ final class InfoMessageCell: MessageCell {
) {
guard cellViewModel.variant.isInfoMessage else { return }
self.accessibilityIdentifier = "Configuration message"
self.isAccessibilityElement = true
self.viewModel = cellViewModel
let icon: UIImage? = {

View file

@ -144,6 +144,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
internal lazy var messageStatusImageView: UIImageView = {
let result = UIImageView()
result.accessibilityLabel = "Message sent status tick"
result.contentMode = .scaleAspectFit
result.layer.cornerRadius = VisibleMessageCell.messageStatusImageViewSize / 2
result.layer.masksToBounds = true
@ -268,7 +269,9 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
lastSearchText: String?
) {
self.viewModel = cellViewModel
self.bubbleView.accessibilityIdentifier = "Message Body"
self.bubbleView.isAccessibilityElement = true
self.bubbleView.accessibilityLabel = cellViewModel.body
// We want to add spacing between "clusters" of messages to indicate that time has
// passed (even if there wasn't enough time to warrant showing a date header)
let shouldAddTopInset: Bool = (

View file

@ -120,7 +120,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
NavItem(
id: .done,
systemItem: .done,
accessibilityIdentifier: "Done button"
accessibilityIdentifier: "Done"
) { [weak self] in
self?.setIsEditing(false)
@ -151,7 +151,8 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
NavItem(
id: .edit,
systemItem: .edit,
accessibilityIdentifier: "Edit button"
accessibilityIdentifier: "Edit button",
accessibilityLabel: "Edit user nickname"
) { [weak self] in self?.setIsEditing(true) }
]
}
@ -240,6 +241,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
"vc_conversation_settings_copy_session_id_button_title".localized()
),
accessibilityIdentifier: "\(ThreadSettingsViewModel.self).copy_thread_id",
accessibilityLabel: "Copy Session ID",
onTap: {
switch threadVariant {
case .contact, .closedGroup:
@ -275,6 +277,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
),
title: MediaStrings.allMedia,
accessibilityIdentifier: "\(ThreadSettingsViewModel.self).all_media",
accessibilityLabel: "All media",
onTap: { [weak self] in
self?.transitionToScreen(
MediaGalleryViewModel.createAllMediaViewController(
@ -294,6 +297,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
),
title: "CONVERSATION_SETTINGS_SEARCH".localized(),
accessibilityIdentifier: "\(ThreadSettingsViewModel.self).search",
accessibilityLabel: "Search",
onTap: { [weak self] in
self?.didTriggerSearch()
}
@ -344,6 +348,8 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
"DISAPPEARING_MESSAGES_SUBTITLE_OFF".localized()
),
accessibilityIdentifier: "\(ThreadSettingsViewModel.self).disappearing_messages",
accessibilityLabel: "Disappearing messages",
leftAccessoryAccessibilityLabel: "Timer icon",
onTap: { [weak self] in
self?.transitionToScreen(
SessionTableViewController(
@ -365,7 +371,8 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
.withRenderingMode(.alwaysTemplate)
),
title: "EDIT_GROUP_ACTION".localized(),
accessibilityIdentifier: "\(ThreadSettingsViewModel.self).edit_group",
accessibilityIdentifier: "Edit group",
accessibilityLabel: "Edit group",
onTap: { [weak self] in
self?.transitionToScreen(EditClosedGroupVC(threadId: threadId))
}
@ -380,7 +387,8 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
.withRenderingMode(.alwaysTemplate)
),
title: "LEAVE_GROUP_ACTION".localized(),
accessibilityIdentifier: "\(ThreadSettingsViewModel.self).leave_group",
accessibilityIdentifier: "Leave group",
accessibilityLabel: "Leave group",
confirmationInfo: ConfirmationModal.Info(
title: "CONFIRM_LEAVE_GROUP_TITLE".localized(),
explanation: (currentUserIsClosedGroupMember ?
@ -436,7 +444,8 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
threadViewModel.threadVariant != .closedGroup ||
currentUserIsClosedGroupMember
),
accessibilityIdentifier: "\(ThreadSettingsViewModel.self).notify_for_mentions_only",
accessibilityIdentifier: "Mentions only notification setting",
accessibilityLabel: "Mentions only",
onTap: {
let newValue: Bool = !(threadViewModel.threadOnlyNotifyForMentions == true)
@ -469,6 +478,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
currentUserIsClosedGroupMember
),
accessibilityIdentifier: "\(ThreadSettingsViewModel.self).mute",
accessibilityLabel: "Mute notifications",
onTap: {
dependencies.storage.writeAsync { db in
let currentValue: TimeInterval? = try SessionThread
@ -505,6 +515,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
.boolValue(threadViewModel.threadIsBlocked == true)
),
accessibilityIdentifier: "\(ThreadSettingsViewModel.self).block",
accessibilityLabel: "Block",
confirmationInfo: ConfirmationModal.Info(
title: {
guard threadViewModel.threadIsBlocked == true else {
@ -527,6 +538,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
"BLOCK_LIST_UNBLOCK_BUTTON".localized() :
"BLOCK_LIST_BLOCK_BUTTON".localized()
),
confirmAccessibilityLabel: "Confirm block",
confirmStyle: .danger,
cancelStyle: .alert_text
),
@ -665,7 +677,10 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
) :
nil
),
accessibilityLabel: oldBlockedState == false ? "User blocked" : "Confirm unblock",
accessibilityId: "OK",
cancelTitle: "BUTTON_OK".localized(),
cancelAccessibilityLabel: "OK",
cancelStyle: .alert_text
)
)

View file

@ -22,6 +22,8 @@ final class ConversationTitleView: UIView {
private lazy var titleLabel: UILabel = {
let result: UILabel = UILabel()
result.accessibilityIdentifier = "Username"
result.isAccessibilityElement = true
result.font = .boldSystemFont(ofSize: Values.mediumFontSize)
result.themeTextColor = .textPrimary
result.lineBreakMode = .byTruncatingTail
@ -124,6 +126,7 @@ final class ConversationTitleView: UIView {
)
self.titleLabel.text = name
self.titleLabel.accessibilityLabel = name
self.titleLabel.font = .boldSystemFont(
ofSize: (shouldHaveSubtitle ?
Values.mediumFontSize :

View file

@ -4,10 +4,10 @@ import UIKit
import SessionUIKit
final class InfoBanner: UIView {
init(message: String, backgroundColor: ThemeValue) {
init(message: String, backgroundColor: ThemeValue, messageLabelAccessibilityLabel: String? = nil) {
super.init(frame: CGRect.zero)
setUpViewHierarchy(message: message, backgroundColor: backgroundColor)
setUpViewHierarchy(message: message, backgroundColor: backgroundColor, messageLabelAccessibilityLabel: messageLabelAccessibilityLabel)
}
override init(frame: CGRect) {
@ -18,10 +18,11 @@ final class InfoBanner: UIView {
preconditionFailure("Use init(coder:) instead.")
}
private func setUpViewHierarchy(message: String, backgroundColor: ThemeValue) {
private func setUpViewHierarchy(message: String, backgroundColor: ThemeValue, messageLabelAccessibilityLabel: String?) {
themeBackgroundColor = backgroundColor
let label: UILabel = UILabel()
label.accessibilityLabel = messageLabelAccessibilityLabel
label.font = .boldSystemFont(ofSize: Values.smallFontSize)
label.text = message
label.themeTextColor = .textPrimary

View file

@ -42,6 +42,7 @@ final class HomeVC: BaseVC, UITableViewDataSource, UITableViewDelegate, SeedRemi
private lazy var seedReminderView: SeedReminderView = {
let result = SeedReminderView(hasContinueButton: true)
result.accessibilityLabel = "Recovery phrase reminder"
let title = "You're almost finished! 80%"
result.subtitle = "view_seed_reminder_subtitle_1".localized()
result.setProgress(0.8, animated: false)
@ -107,6 +108,8 @@ final class HomeVC: BaseVC, UITableViewDataSource, UITableViewDelegate, SeedRemi
result.set(.height, to: HomeVC.newConversationButtonSize)
let button = UIButton()
button.accessibilityLabel = "New conversation button"
button.isAccessibilityElement = true
button.clipsToBounds = true
button.setImage(
UIImage(named: "Plus")?
@ -463,7 +466,9 @@ final class HomeVC: BaseVC, UITableViewDataSource, UITableViewDelegate, SeedRemi
// Profile picture view
let profilePictureSize = Values.verySmallProfilePictureSize
let profilePictureView = ProfilePictureView()
profilePictureView.accessibilityLabel = "Settings button"
profilePictureView.accessibilityIdentifier = "User settings"
profilePictureView.accessibilityLabel = "User settings"
profilePictureView.isAccessibilityElement = true
profilePictureView.size = profilePictureSize
profilePictureView.update(
publicKey: getUserHexEncodedPublicKey(),
@ -482,7 +487,6 @@ final class HomeVC: BaseVC, UITableViewDataSource, UITableViewDelegate, SeedRemi
// Container view
let profilePictureViewContainer = UIView()
profilePictureViewContainer.accessibilityLabel = "Settings button"
profilePictureViewContainer.addSubview(profilePictureView)
profilePictureView.autoPinEdgesToSuperviewEdges()
profilePictureViewContainer.addSubview(pathStatusView)
@ -491,7 +495,6 @@ final class HomeVC: BaseVC, UITableViewDataSource, UITableViewDelegate, SeedRemi
// Left bar button item
let leftBarButtonItem = UIBarButtonItem(customView: profilePictureViewContainer)
leftBarButtonItem.accessibilityLabel = "Settings button"
leftBarButtonItem.isAccessibilityElement = true
navigationItem.leftBarButtonItem = leftBarButtonItem
@ -521,6 +524,8 @@ final class HomeVC: BaseVC, UITableViewDataSource, UITableViewDelegate, SeedRemi
case .messageRequests:
let threadViewModel: SessionThreadViewModel = section.elements[indexPath.row]
let cell: MessageRequestsCell = tableView.dequeue(type: MessageRequestsCell.self, for: indexPath)
cell.accessibilityIdentifier = "Message requests banner"
cell.isAccessibilityElement = true
cell.update(with: Int(threadViewModel.threadUnreadCount ?? 0))
return cell
@ -528,6 +533,8 @@ final class HomeVC: BaseVC, UITableViewDataSource, UITableViewDelegate, SeedRemi
let threadViewModel: SessionThreadViewModel = section.elements[indexPath.row]
let cell: FullConversationCell = tableView.dequeue(type: FullConversationCell.self, for: indexPath)
cell.update(with: threadViewModel)
cell.accessibilityIdentifier = "Conversation list item"
cell.accessibilityLabel = threadViewModel.displayName
return cell
default: preconditionFailure("Other sections should have no content")

View file

@ -311,6 +311,8 @@ class MessageRequestsViewController: BaseVC, UITableViewDelegate, UITableViewDat
case .threads:
let threadViewModel: SessionThreadViewModel = section.elements[indexPath.row]
let cell: FullConversationCell = tableView.dequeue(type: FullConversationCell.self, for: indexPath)
cell.accessibilityIdentifier = "Message request"
cell.isAccessibilityElement = true
cell.update(with: threadViewModel)
return cell

View file

@ -14,8 +14,21 @@ final class NewConversationVC: BaseVC, ThemedNavigation, UITableViewDelegate, UI
var navigationBackground: ThemeValue { .newConversation_background }
private lazy var newDMButton: NewConversationButton = NewConversationButton(icon: #imageLiteral(resourceName: "Message"), title: "vc_create_private_chat_title".localized())
private lazy var newGroupButton: NewConversationButton = NewConversationButton(icon: #imageLiteral(resourceName: "Group"), title: "vc_create_closed_group_title".localized())
private lazy var newDMButton: NewConversationButton = {
let result = NewConversationButton(icon: #imageLiteral(resourceName: "Message"), title: "vc_create_private_chat_title".localized())
result.accessibilityIdentifier = "New direct message"
result.isAccessibilityElement = true
return result
}()
private lazy var newGroupButton: NewConversationButton = {
let result = NewConversationButton(icon: #imageLiteral(resourceName: "Group"), title: "vc_create_closed_group_title".localized())
result.accessibilityLabel = "Create group"
result.isAccessibilityElement = true
return result
}()
private lazy var joinCommunityButton: NewConversationButton = NewConversationButton(icon: #imageLiteral(resourceName: "Globe"), title: "vc_join_public_chat_title".localized(), shouldShowSeparator: false)
private lazy var buttonStackView: UIStackView = {

View file

@ -253,6 +253,7 @@ private final class EnterPublicKeyVC: UIViewController {
let result = TextView(placeholder: "vc_enter_public_key_text_field_hint".localized()) { [weak self] text in
self?.nextButton.isEnabled = !text.isEmpty
}
result.accessibilityLabel = "Session id input box"
result.autocapitalizationType = .none
return result
@ -389,12 +390,15 @@ private final class EnterPublicKeyVC: UIViewController {
)
result.alpha = (isKeyboardShowing ? 1 : 0)
result.isHidden = !isKeyboardShowing
result.accessibilityLabel = "Next"
result.isAccessibilityElement = true
return result
}()
private lazy var nextButton: SessionButton = {
let result = SessionButton(style: .bordered, size: .large)
result.accessibilityLabel = "Next"
result.isAccessibilityElement = true
result.setTitle("next".localized(), for: .normal)
result.isEnabled = false
result.addTarget(self, action: #selector(startNewDMIfPossible), for: .touchUpInside)

View file

@ -455,6 +455,7 @@ import SignalUtilitiesKit
result.addArrangedSubview(cancelButton)
let doneButton = createButton(title: CommonStrings.doneButton, action: #selector(donePressed))
doneButton.accessibilityLabel = "Done"
result.addArrangedSubview(doneButton)
return result

View file

@ -215,6 +215,7 @@ class SendMediaNavigationController: UINavigationController {
private lazy var mediaLibraryViewController: ImagePickerGridController = {
let vc = ImagePickerGridController()
vc.delegate = self
vc.collectionView.accessibilityLabel = "Images"
return vc
}()

View file

@ -15,8 +15,9 @@ final class DisplayNameVC: BaseVC {
private lazy var displayNameTextField: TextField = {
let result = TextField(placeholder: "vc_display_name_text_field_hint".localized())
result.accessibilityLabel = "Enter display name"
result.isAccessibilityElement = true
result.themeBorderColor = .textPrimary
result.accessibilityLabel = "Display name text field"
return result
}()
@ -56,6 +57,7 @@ final class DisplayNameVC: BaseVC {
// Set up register button
let registerButton = SessionButton(style: .filled, size: .large)
registerButton.accessibilityLabel = "Continue"
registerButton.setTitle("continue_2".localized(), for: UIControl.State.normal)
registerButton.addTarget(self, action: #selector(register), for: UIControl.Event.touchUpInside)

View file

@ -16,6 +16,7 @@ final class LandingVC: BaseVC {
private lazy var registerButton: SessionButton = {
let result = SessionButton(style: .filled, size: .large)
result.accessibilityLabel = "Create session ID"
result.setTitle("vc_landing_register_button_title".localized(), for: .normal)
result.addTarget(self, action: #selector(register), for: .touchUpInside)
@ -63,6 +64,7 @@ final class LandingVC: BaseVC {
// Link button
let linkButton = UIButton()
linkButton.accessibilityLabel = "Link a device"
linkButton.titleLabel?.font = .boldSystemFont(ofSize: Values.smallFontSize)
linkButton.setTitle("vc_landing_link_button_title".localized(), for: .normal)
linkButton.setThemeTitleColor(.textPrimary, for: .normal)

View file

@ -194,7 +194,7 @@ private final class RecoveryPhraseVC: UIViewController {
private lazy var mnemonicTextView: TextView = {
let result = TextView(placeholder: "vc_restore_seed_text_field_hint".localized())
result.themeBorderColor = .textPrimary
result.accessibilityLabel = "Recovery phrase text view"
result.accessibilityLabel = "Enter your recovery phrase"
return result
}()
@ -232,6 +232,7 @@ private final class RecoveryPhraseVC: UIViewController {
// Continue button
let continueButton = SessionButton(style: .filled, size: .large)
continueButton.accessibilityLabel = "Link device"
continueButton.setTitle("continue_2".localized(), for: UIControl.State.normal)
continueButton.addTarget(self, action: #selector(handleContinueButtonTapped), for: UIControl.Event.touchUpInside)

View file

@ -69,6 +69,7 @@ final class PNModeVC: BaseVC, OptionViewDelegate {
// Set up register button
let registerButton = SessionButton(style: .filled, size: .large)
registerButton.accessibilityLabel = "Continue with settings"
registerButton.setTitle("continue_2".localized(), for: .normal)
registerButton.addTarget(self, action: #selector(register), for: UIControl.Event.touchUpInside)

View file

@ -17,7 +17,8 @@ final class RegisterVC : BaseVC {
let result = UILabel()
result.font = Fonts.spaceMono(ofSize: isIPhone5OrSmaller ? Values.mediumFontSize : 20)
result.themeTextColor = .textPrimary
result.accessibilityLabel = "Session ID label"
result.accessibilityLabel = "Session ID"
result.isAccessibilityElement = true
result.lineBreakMode = .byCharWrapping
result.numberOfLines = 0
@ -26,6 +27,8 @@ final class RegisterVC : BaseVC {
private lazy var copyPublicKeyButton: SessionButton = {
let result = SessionButton(style: .bordered, size: .large)
result.accessibilityLabel = "Copy"
result.isAccessibilityElement = true
result.setTitle("copy".localized(), for: .normal)
result.addTarget(self, action: #selector(copyPublicKey), for: .touchUpInside)
@ -86,6 +89,7 @@ final class RegisterVC : BaseVC {
// Set up register button
let registerButton = SessionButton(style: .filled, size: .large)
registerButton.accessibilityLabel = "Continue"
registerButton.setTitle("continue_2".localized(), for: .normal)
registerButton.addTarget(self, action: #selector(register), for: UIControl.Event.touchUpInside)
@ -167,6 +171,9 @@ final class RegisterVC : BaseVC {
private func updatePublicKeyLabel() {
let hexEncodedPublicKey = x25519KeyPair.hexEncodedPublicKey
publicKeyLabel.accessibilityLabel = hexEncodedPublicKey
publicKeyLabel.accessibilityIdentifier = "Session ID generated"
publicKeyLabel.isAccessibilityElement = true
let characterCount = hexEncodedPublicKey.count
var count = 0
let limit = 32
@ -202,6 +209,8 @@ final class RegisterVC : BaseVC {
@objc private func copyPublicKey() {
UIPasteboard.general.string = x25519KeyPair.hexEncodedPublicKey
copyPublicKeyButton.isUserInteractionEnabled = false
copyPublicKeyButton.accessibilityLabel = "Copy session id"
copyPublicKeyButton.isAccessibilityElement = true
UIView.transition(with: copyPublicKeyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
self.copyPublicKeyButton.setTitle("copied".localized(), for: .normal)
}, completion: nil)

View file

@ -82,6 +82,8 @@ final class SeedReminderView: UIView {
// Set up button
let button = SessionButton(style: .bordered, size: .small)
button.accessibilityLabel = "Continue"
button.isAccessibilityElement = true
button.setTitle("continue_2".localized(), for: UIControl.State.normal)
button.set(.width, to: 96)
button.addTarget(self, action: #selector(handleContinueButtonTapped), for: UIControl.Event.touchUpInside)

View file

@ -46,6 +46,9 @@ final class SeedVC: BaseVC {
private lazy var mnemonicLabel: UILabel = {
let result = UILabel()
result.accessibilityIdentifier = "Recovery Phrase"
result.accessibilityLabel = mnemonic
result.isAccessibilityElement = true
result.font = Fonts.spaceMono(ofSize: Values.mediumFontSize)
result.themeTextColor = .primary
result.textAlignment = .center
@ -72,6 +75,8 @@ final class SeedVC: BaseVC {
// Set up navigation bar buttons
let closeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "X"), style: .plain, target: self, action: #selector(close))
closeButton.accessibilityLabel = "Navigate up"
closeButton.isAccessibilityElement = true
closeButton.themeTintColor = .textPrimary
navigationItem.leftBarButtonItem = closeButton

View file

@ -189,11 +189,13 @@ class PrivacySettingsViewModel: SessionTableViewModel<PrivacySettingsViewModel.N
title: "PRIVACY_CALLS_TITLE".localized(),
subtitle: "PRIVACY_CALLS_DESCRIPTION".localized(),
rightAccessory: .toggle(.settingBool(key: .areCallsEnabled)),
accessibilityLabel: "Allow voice and video calls",
confirmationInfo: ConfirmationModal.Info(
title: "PRIVACY_CALLS_WARNING_TITLE".localized(),
explanation: "PRIVACY_CALLS_WARNING_DESCRIPTION".localized(),
stateToShow: .whenDisabled,
confirmTitle: "continue_2".localized(),
confirmAccessibilityLabel: "Enable",
confirmStyle: .textPrimary,
onConfirm: { _ in Permissions.requestMicrophonePermissionIfNeeded() }
),

View file

@ -124,7 +124,7 @@ class SettingsViewModel: SessionTableViewModel<SettingsViewModel.NavButton, Sett
NavItem(
id: .done,
systemItem: .done,
accessibilityIdentifier: "Done button"
accessibilityIdentifier: "Done"
) { [weak self] in
let updatedNickname: String = (self?.editedDisplayName ?? "")
.trimmingCharacters(in: .whitespacesAndNewlines)
@ -214,6 +214,7 @@ class SettingsViewModel: SessionTableViewModel<SettingsViewModel.NavButton, Sett
run: { [weak self] button in
self?.copySessionId(profile.id, button: button)
}
),
SessionCell.Accessory.ThreadInfoStyle.Action(
title: "share".localized(),
@ -393,13 +394,15 @@ class SettingsViewModel: SessionTableViewModel<SettingsViewModel.NavButton, Sett
message: nil,
preferredStyle: .actionSheet
)
actionSheet.addAction(UIAlertAction(
let action = UIAlertAction(
title: "MEDIA_FROM_LIBRARY_BUTTON".localized(),
style: .default,
handler: { [weak self] _ in
self?.showPhotoLibraryForAvatar()
}
))
)
action.accessibilityLabel = "Photo library"
actionSheet.addAction(action)
actionSheet.addAction(UIAlertAction(title: "cancel".localized(), style: .cancel, handler: nil))
self.transitionToScreen(actionSheet, transitionType: .present)
@ -494,6 +497,8 @@ class SettingsViewModel: SessionTableViewModel<SettingsViewModel.NavButton, Sett
DispatchQueue.main.async {
button.isUserInteractionEnabled = false
UIView.transition(
with: button,
duration: 0.25,

View file

@ -17,6 +17,9 @@ extension SessionCell {
let isEnabled: Bool
let shouldHaveBackground: Bool
let accessibilityIdentifier: String?
let accessibilityLabel: String?
let leftAccessoryAccessibilityLabel: String?
let rightAccessoryAccessibilityLabel: String?
let confirmationInfo: ConfirmationModal.Info?
let onTap: ((UIView?) -> Void)?
@ -41,6 +44,9 @@ extension SessionCell {
isEnabled: Bool = true,
shouldHaveBackground: Bool = true,
accessibilityIdentifier: String? = nil,
accessibilityLabel: String? = nil,
leftAccessoryAccessibilityLabel: String? = nil,
rightAccessoryAccessibilityLabel: String? = nil,
confirmationInfo: ConfirmationModal.Info? = nil,
onTap: ((UIView?) -> Void)?
) {
@ -55,6 +61,9 @@ extension SessionCell {
self.isEnabled = isEnabled
self.shouldHaveBackground = shouldHaveBackground
self.accessibilityIdentifier = accessibilityIdentifier
self.accessibilityLabel = accessibilityLabel
self.leftAccessoryAccessibilityLabel = leftAccessoryAccessibilityLabel
self.rightAccessoryAccessibilityLabel = rightAccessoryAccessibilityLabel
self.confirmationInfo = confirmationInfo
self.onTap = onTap
}
@ -71,6 +80,9 @@ extension SessionCell {
isEnabled: Bool = true,
shouldHaveBackground: Bool = true,
accessibilityIdentifier: String? = nil,
accessibilityLabel: String? = nil,
leftAccessoryAccessibilityLabel: String? = nil,
rightAccessoryAccessibilityLabel: String? = nil,
confirmationInfo: ConfirmationModal.Info? = nil,
onTap: (() -> Void)? = nil
) {
@ -85,6 +97,9 @@ extension SessionCell {
self.isEnabled = isEnabled
self.shouldHaveBackground = shouldHaveBackground
self.accessibilityIdentifier = accessibilityIdentifier
self.accessibilityLabel = accessibilityLabel
self.leftAccessoryAccessibilityLabel = leftAccessoryAccessibilityLabel
self.rightAccessoryAccessibilityLabel = rightAccessoryAccessibilityLabel
self.confirmationInfo = confirmationInfo
self.onTap = (onTap != nil ? { _ in onTap?() } : nil)
}
@ -104,6 +119,9 @@ extension SessionCell {
isEnabled.hash(into: &hasher)
shouldHaveBackground.hash(into: &hasher)
accessibilityIdentifier.hash(into: &hasher)
accessibilityLabel.hash(into: &hasher)
leftAccessoryAccessibilityLabel.hash(into: &hasher)
rightAccessoryAccessibilityLabel.hash(into: &hasher)
confirmationInfo.hash(into: &hasher)
}
@ -118,7 +136,10 @@ extension SessionCell {
lhs.extraAction == rhs.extraAction &&
lhs.isEnabled == rhs.isEnabled &&
lhs.shouldHaveBackground == rhs.shouldHaveBackground &&
lhs.accessibilityIdentifier == rhs.accessibilityIdentifier
lhs.accessibilityIdentifier == rhs.accessibilityIdentifier &&
lhs.accessibilityLabel == rhs.accessibilityLabel &&
lhs.leftAccessoryAccessibilityLabel == rhs.leftAccessoryAccessibilityLabel &&
lhs.rightAccessoryAccessibilityLabel == rhs.rightAccessoryAccessibilityLabel
)
}
}

View file

@ -12,6 +12,7 @@ extension SessionTableViewModel {
let style: UIBarButtonItem.Style
let systemItem: UIBarButtonItem.SystemItem?
let accessibilityIdentifier: String
let accessibilityLabel: String?
let action: (() -> Void)?
// MARK: - Initialization
@ -20,6 +21,7 @@ extension SessionTableViewModel {
id: NavItemId,
systemItem: UIBarButtonItem.SystemItem?,
accessibilityIdentifier: String,
accessibilityLabel: String? = nil,
action: (() -> Void)? = nil
) {
self.id = id
@ -27,6 +29,7 @@ extension SessionTableViewModel {
self.style = .plain
self.systemItem = systemItem
self.accessibilityIdentifier = accessibilityIdentifier
self.accessibilityLabel = accessibilityLabel
self.action = action
}
@ -35,6 +38,7 @@ extension SessionTableViewModel {
image: UIImage?,
style: UIBarButtonItem.Style,
accessibilityIdentifier: String,
accessibilityLabel: String? = nil,
action: (() -> Void)? = nil
) {
self.id = id
@ -42,6 +46,7 @@ extension SessionTableViewModel {
self.style = style
self.systemItem = nil
self.accessibilityIdentifier = accessibilityIdentifier
self.accessibilityLabel = accessibilityLabel
self.action = action
}
@ -54,7 +59,8 @@ extension SessionTableViewModel {
style: style,
target: nil,
action: nil,
accessibilityIdentifier: accessibilityIdentifier
accessibilityIdentifier: accessibilityIdentifier,
accessibilityLabel: accessibilityLabel
)
}
@ -62,7 +68,8 @@ extension SessionTableViewModel {
barButtonSystemItem: systemItem,
target: nil,
action: nil,
accessibilityIdentifier: accessibilityIdentifier
accessibilityIdentifier: accessibilityIdentifier,
accessibilityLabel: accessibilityLabel
)
}

View file

@ -48,7 +48,10 @@ final class UserSelectionVC: BaseVC, UITableViewDataSource, UITableViewDelegate
setNavBarTitle(navBarTitle)
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(handleDoneButtonTapped))
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(handleDoneButtonTapped))
doneButton.accessibilityLabel = "Done"
navigationItem.rightBarButtonItem = doneButton
view.addSubview(tableView)
tableView.pin(to: view)
}
@ -69,7 +72,8 @@ final class UserSelectionVC: BaseVC, UITableViewDataSource, UITableViewDelegate
title: profile.displayName(),
rightAccessory: .radio(isSelected: { [weak self] in
self?.selectedUsers.contains(profile.id) == true
})
}),
accessibilityIdentifier: "Contact"
),
style: .edgeToEdge,
position: Position.with(indexPath.row, count: users.count)

View file

@ -52,6 +52,8 @@ class SessionAvatarCell: UITableViewCell {
fileprivate let profilePictureView: ProfilePictureView = {
let view: ProfilePictureView = ProfilePictureView()
view.accessibilityLabel = "Profile picture"
view.isAccessibilityElement = true
view.translatesAutoresizingMaskIntoConstraints = false
view.size = Values.largeProfilePictureSize
@ -61,7 +63,7 @@ class SessionAvatarCell: UITableViewCell {
fileprivate let displayNameContainer: UIView = {
let view: UIView = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.accessibilityLabel = "Edit name text field"
view.accessibilityLabel = "Username"
view.isAccessibilityElement = true
return view
@ -69,6 +71,7 @@ class SessionAvatarCell: UITableViewCell {
private lazy var displayNameLabel: UILabel = {
let label: UILabel = UILabel()
label.isAccessibilityElement = true
label.translatesAutoresizingMaskIntoConstraints = false
label.font = .ows_mediumFont(withSize: Values.veryLargeFontSize)
label.themeTextColor = .textPrimary
@ -83,7 +86,9 @@ class SessionAvatarCell: UITableViewCell {
let textField: TextField = TextField(placeholder: "Enter a name", usesDefaultHeight: false)
textField.translatesAutoresizingMaskIntoConstraints = false
textField.textAlignment = .center
textField.accessibilityLabel = "Edit name text field"
textField.accessibilityIdentifier = "Nickname"
textField.accessibilityLabel = "Nickname"
textField.isAccessibilityElement = true
textField.alpha = 0
return textField
@ -98,6 +103,7 @@ class SessionAvatarCell: UITableViewCell {
private let descriptionLabel: SRCopyableLabel = {
let label: SRCopyableLabel = SRCopyableLabel()
label.accessibilityLabel = "Session ID"
label.translatesAutoresizingMaskIntoConstraints = false
label.themeTextColor = .textPrimary
label.textAlignment = .center

View file

@ -225,7 +225,8 @@ extension SessionCell {
public func update(
with accessory: Accessory?,
tintColor: ThemeValue,
isEnabled: Bool
isEnabled: Bool,
accessibilityLabel: String?
) {
guard let accessory: Accessory = accessory else { return }
@ -234,6 +235,7 @@ extension SessionCell {
switch accessory {
case .icon(let image, let iconSize, let customTint, let shouldFill):
imageView.accessibilityLabel = accessibilityLabel
imageView.image = image
imageView.themeTintColor = (customTint ?? tintColor)
imageView.contentMode = (shouldFill ? .scaleAspectFill : .scaleAspectFit)
@ -256,6 +258,7 @@ extension SessionCell {
case .iconAsync(let iconSize, let customTint, let shouldFill, let setter):
setter(imageView)
imageView.accessibilityLabel = accessibilityLabel
imageView.themeTintColor = (customTint ?? tintColor)
imageView.contentMode = (shouldFill ? .scaleAspectFill : .scaleAspectFit)
imageView.isHidden = false
@ -276,6 +279,7 @@ extension SessionCell {
imageViewConstraints.forEach { $0.isActive = true }
case .toggle(let dataSource):
toggleSwitch.accessibilityLabel = accessibilityLabel
toggleSwitch.isHidden = false
toggleSwitch.isEnabled = isEnabled
toggleSwitchConstraints.forEach { $0.isActive = true }
@ -287,6 +291,7 @@ extension SessionCell {
}
case .dropDown(let dataSource):
dropDownLabel.accessibilityLabel = accessibilityLabel
dropDownLabel.text = dataSource.currentStringValue
dropDownStackView.isHidden = false
dropDownStackViewConstraints.forEach { $0.isActive = true }
@ -302,6 +307,7 @@ extension SessionCell {
)
radioBorderView.layer.cornerRadius = (size.borderSize / 2)
radioView.accessibilityLabel = accessibilityLabel
radioView.alpha = (wasOldSelection ? 0.3 : 1)
radioView.isHidden = (!isSelected && !storedSelection)
radioView.themeBackgroundColor = (isSelected || wasOldSelection ?
@ -322,12 +328,14 @@ extension SessionCell {
radioBorderViewConstraints.forEach { $0.isActive = true }
case .highlightingBackgroundLabel(let title):
highlightingBackgroundLabel.accessibilityLabel = accessibilityLabel
highlightingBackgroundLabel.text = title
highlightingBackgroundLabel.themeTextColor = tintColor
highlightingBackgroundLabel.isHidden = false
highlightingBackgroundLabelConstraints.forEach { $0.isActive = true }
case .profile(let profileId, let profile):
profilePictureView.accessibilityLabel = accessibilityLabel
profilePictureView.update(
publicKey: profileId,
profile: profile,
@ -338,6 +346,7 @@ extension SessionCell {
case .customView(let viewGenerator):
let generatedView: UIView = viewGenerator()
generatedView.accessibilityLabel = accessibilityLabel
addSubview(generatedView)
generatedView.pin(.top, to: .top, of: self)

View file

@ -308,6 +308,8 @@ public class SessionCell: UITableViewCell {
self.subtitleExtraView = info.subtitleExtraViewGenerator?()
self.onExtraActionTap = info.extraAction?.onTap
self.accessibilityIdentifier = info.accessibilityIdentifier
self.accessibilityLabel = info.accessibilityLabel
self.isAccessibilityElement = true
let leftFitToEdge: Bool = (info.leftAccessory?.shouldFitToEdge == true)
let rightFitToEdge: Bool = (!leftFitToEdge && info.rightAccessory?.shouldFitToEdge == true)
@ -315,12 +317,14 @@ public class SessionCell: UITableViewCell {
leftAccessoryView.update(
with: info.leftAccessory,
tintColor: info.tintColor,
isEnabled: info.isEnabled
isEnabled: info.isEnabled,
accessibilityLabel: info.leftAccessoryAccessibilityLabel
)
rightAccessoryView.update(
with: info.rightAccessory,
tintColor: info.tintColor,
isEnabled: info.isEnabled
isEnabled: info.isEnabled,
accessibilityLabel: info.rightAccessoryAccessibilityLabel
)
rightAccessoryFillConstraint.isActive = rightFitToEdge
contentStackView.layoutMargins = UIEdgeInsets(

View file

@ -228,7 +228,7 @@ class ThreadSettingsViewModelSpec: QuickSpec {
ParentType.NavItem(
id: .cancel,
systemItem: .cancel,
accessibilityIdentifier: "Cancel button"
accessibilityIdentifier: "Cancel"
)
]))
expect(viewModel.rightNavItems.firstValue())
@ -236,7 +236,7 @@ class ThreadSettingsViewModelSpec: QuickSpec {
ParentType.NavItem(
id: .done,
systemItem: .done,
accessibilityIdentifier: "Done button"
accessibilityIdentifier: "Done"
)
]))
}
@ -369,7 +369,7 @@ class ThreadSettingsViewModelSpec: QuickSpec {
ParentType.NavItem(
id: .done,
systemItem: .done,
accessibilityIdentifier: "Done button"
accessibilityIdentifier: "Done"
)
]))
}

View file

@ -21,10 +21,14 @@ public class ConfirmationModal: Modal {
let title: String
let explanation: String?
let attributedExplanation: NSAttributedString?
let accessibilityLabel: String?
let accessibilityId: String?
public let stateToShow: State
let confirmTitle: String?
let confirmAccessibilityLabel: String?
let confirmStyle: ThemeValue
let cancelTitle: String
let cancelAccessibilityLabel: String?
let cancelStyle: ThemeValue
let dismissOnConfirm: Bool
let onConfirm: ((UIViewController) -> ())?
@ -36,10 +40,14 @@ public class ConfirmationModal: Modal {
title: String,
explanation: String? = nil,
attributedExplanation: NSAttributedString? = nil,
accessibilityLabel: String? = nil,
accessibilityId: String? = nil,
stateToShow: State = .always,
confirmTitle: String? = nil,
confirmAccessibilityLabel: String? = nil,
confirmStyle: ThemeValue = .alert_text,
cancelTitle: String = "TXT_CANCEL_TITLE".localized(),
cancelAccessibilityLabel: String? = nil,
cancelStyle: ThemeValue = .danger,
dismissOnConfirm: Bool = true,
onConfirm: ((UIViewController) -> ())? = nil,
@ -48,10 +56,14 @@ public class ConfirmationModal: Modal {
self.title = title
self.explanation = explanation
self.attributedExplanation = attributedExplanation
self.accessibilityLabel = accessibilityLabel
self.accessibilityId = accessibilityId
self.stateToShow = stateToShow
self.confirmTitle = confirmTitle
self.confirmAccessibilityLabel = confirmAccessibilityLabel
self.confirmStyle = confirmStyle
self.cancelTitle = cancelTitle
self.cancelAccessibilityLabel = cancelAccessibilityLabel
self.cancelStyle = cancelStyle
self.dismissOnConfirm = dismissOnConfirm
self.onConfirm = onConfirm
@ -67,10 +79,14 @@ public class ConfirmationModal: Modal {
return Info(
title: self.title,
explanation: self.explanation,
attributedExplanation: self.attributedExplanation,
accessibilityLabel: self.accessibilityLabel,
stateToShow: self.stateToShow,
confirmTitle: self.confirmTitle,
confirmAccessibilityLabel: self.confirmAccessibilityLabel,
confirmStyle: self.confirmStyle,
cancelTitle: self.cancelTitle,
cancelAccessibilityLabel: self.cancelAccessibilityLabel,
cancelStyle: self.cancelStyle,
dismissOnConfirm: self.dismissOnConfirm,
onConfirm: (onConfirm ?? self.onConfirm),
@ -85,10 +101,13 @@ public class ConfirmationModal: Modal {
lhs.title == rhs.title &&
lhs.explanation == rhs.explanation &&
lhs.attributedExplanation == rhs.attributedExplanation &&
lhs.accessibilityLabel == rhs.accessibilityLabel &&
lhs.stateToShow == rhs.stateToShow &&
lhs.confirmTitle == rhs.confirmTitle &&
lhs.confirmAccessibilityLabel == rhs.confirmAccessibilityLabel &&
lhs.confirmStyle == rhs.confirmStyle &&
lhs.cancelTitle == rhs.cancelTitle &&
lhs.cancelAccessibilityLabel == rhs.cancelAccessibilityLabel &&
lhs.cancelStyle == rhs.cancelStyle &&
lhs.dismissOnConfirm == rhs.dismissOnConfirm
)
@ -98,10 +117,13 @@ public class ConfirmationModal: Modal {
title.hash(into: &hasher)
explanation.hash(into: &hasher)
attributedExplanation.hash(into: &hasher)
accessibilityLabel.hash(into: &hasher)
stateToShow.hash(into: &hasher)
confirmTitle.hash(into: &hasher)
confirmAccessibilityLabel.hash(into: &hasher)
confirmStyle.hash(into: &hasher)
cancelTitle.hash(into: &hasher)
cancelAccessibilityLabel.hash(into: &hasher)
cancelStyle.hash(into: &hasher)
dismissOnConfirm.hash(into: &hasher)
}
@ -207,11 +229,20 @@ public class ConfirmationModal: Modal {
info.explanation == nil &&
info.attributedExplanation == nil
)
confirmButton.accessibilityLabel = info.confirmAccessibilityLabel
confirmButton.accessibilityIdentifier = info.confirmAccessibilityLabel
confirmButton.isAccessibilityElement = true
confirmButton.setTitle(info.confirmTitle, for: .normal)
confirmButton.setThemeTitleColor(info.confirmStyle, for: .normal)
confirmButton.isHidden = (info.confirmTitle == nil)
cancelButton.accessibilityLabel = info.cancelAccessibilityLabel
cancelButton.accessibilityIdentifier = info.cancelAccessibilityLabel
cancelButton.isAccessibilityElement = true
cancelButton.setTitle(info.cancelTitle, for: .normal)
cancelButton.setThemeTitleColor(info.cancelStyle, for: .normal)
self.accessibilityLabel = info.accessibilityLabel
self.contentView.accessibilityIdentifier = info.accessibilityId
}
required init?(coder: NSCoder) {

View file

@ -291,43 +291,43 @@ public extension UIBezierPath {
@objc
public extension UIBarButtonItem {
convenience init(image: UIImage?, style: UIBarButtonItem.Style, target: Any?, action: Selector?, accessibilityIdentifier: String) {
convenience init(image: UIImage?, style: UIBarButtonItem.Style, target: Any?, action: Selector?, accessibilityIdentifier: String, accessibilityLabel: String? = nil) {
self.init(image: image, style: style, target: target, action: action)
self.accessibilityIdentifier = accessibilityIdentifier
self.accessibilityLabel = accessibilityIdentifier
self.accessibilityLabel = accessibilityLabel == nil ? accessibilityIdentifier : accessibilityLabel
self.isAccessibilityElement = true
}
convenience init(image: UIImage?, landscapeImagePhone: UIImage?, style: UIBarButtonItem.Style, target: Any?, action: Selector?, accessibilityIdentifier: String) {
convenience init(image: UIImage?, landscapeImagePhone: UIImage?, style: UIBarButtonItem.Style, target: Any?, action: Selector?, accessibilityIdentifier: String, accessibilityLabel: String? = nil) {
self.init(image: image, landscapeImagePhone: landscapeImagePhone, style: style, target: target, action: action)
self.accessibilityIdentifier = accessibilityIdentifier
self.accessibilityLabel = accessibilityIdentifier
self.accessibilityLabel = accessibilityLabel == nil ? accessibilityIdentifier : accessibilityLabel
self.isAccessibilityElement = true
}
convenience init(title: String?, style: UIBarButtonItem.Style, target: Any?, action: Selector?, accessibilityIdentifier: String) {
convenience init(title: String?, style: UIBarButtonItem.Style, target: Any?, action: Selector?, accessibilityIdentifier: String, accessibilityLabel: String? = nil) {
self.init(title: title, style: style, target: target, action: action)
self.accessibilityIdentifier = accessibilityIdentifier
self.accessibilityLabel = accessibilityIdentifier
self.accessibilityLabel = accessibilityLabel == nil ? accessibilityIdentifier : accessibilityLabel
self.isAccessibilityElement = true
}
convenience init(barButtonSystemItem systemItem: UIBarButtonItem.SystemItem, target: Any?, action: Selector?, accessibilityIdentifier: String) {
convenience init(barButtonSystemItem systemItem: UIBarButtonItem.SystemItem, target: Any?, action: Selector?, accessibilityIdentifier: String, accessibilityLabel: String? = nil) {
self.init(barButtonSystemItem: systemItem, target: target, action: action)
self.accessibilityIdentifier = accessibilityIdentifier
self.accessibilityLabel = accessibilityIdentifier
self.accessibilityLabel = accessibilityLabel == nil ? accessibilityIdentifier : accessibilityLabel
self.isAccessibilityElement = true
}
convenience init(customView: UIView, accessibilityIdentifier: String) {
convenience init(customView: UIView, accessibilityIdentifier: String, accessibilityLabel: String? = nil) {
self.init(customView: customView)
self.accessibilityIdentifier = accessibilityIdentifier
self.accessibilityLabel = accessibilityIdentifier
self.accessibilityLabel = accessibilityLabel == nil ? accessibilityIdentifier : accessibilityLabel
self.isAccessibilityElement = true
}
}