diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index 0bb7267c7..548ea5027 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -6064,7 +6064,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 393; + CURRENT_PROJECT_VERSION = 395; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; @@ -6137,7 +6137,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 393; + CURRENT_PROJECT_VERSION = 395; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = SUQ8J2PCT7; ENABLE_NS_ASSERTIONS = NO; @@ -6203,7 +6203,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 393; + CURRENT_PROJECT_VERSION = 395; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; @@ -6277,7 +6277,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 393; + CURRENT_PROJECT_VERSION = 395; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = SUQ8J2PCT7; ENABLE_NS_ASSERTIONS = NO; @@ -7205,7 +7205,7 @@ CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 393; + CURRENT_PROJECT_VERSION = 395; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -7277,7 +7277,7 @@ CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 393; + CURRENT_PROJECT_VERSION = 395; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", diff --git a/Session/Conversations/Context Menu/ContextMenuVC+Action.swift b/Session/Conversations/Context Menu/ContextMenuVC+Action.swift index 0fae55d11..04e652f8f 100644 --- a/Session/Conversations/Context Menu/ContextMenuVC+Action.swift +++ b/Session/Conversations/Context Menu/ContextMenuVC+Action.swift @@ -57,14 +57,17 @@ extension ContextMenuVC { static func copy(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action { return Action( icon: UIImage(named: "ic_copy"), - title: "copy".localized() + title: "copy".localized(), + accessibilityLabel: "Copy text" ) { delegate?.copy(cellViewModel) } } static func copySessionID(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action { return Action( icon: UIImage(named: "ic_copy"), - title: "vc_conversation_settings_copy_session_id_button_title".localized() + title: "vc_conversation_settings_copy_session_id_button_title".localized(), + accessibilityLabel: "Copy Session ID" + ) { delegate?.copySessionID(cellViewModel) } } @@ -87,14 +90,16 @@ extension ContextMenuVC { static func ban(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action { return Action( icon: UIImage(named: "ic_block"), - title: "context_menu_ban_user".localized() + title: "context_menu_ban_user".localized(), + accessibilityLabel: "Ban user" ) { delegate?.ban(cellViewModel) } } static func banAndDeleteAllMessages(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action { return Action( icon: UIImage(named: "ic_block"), - title: "context_menu_ban_and_delete_all".localized() + title: "context_menu_ban_and_delete_all".localized(), + accessibilityLabel: "Ban user and delete" ) { delegate?.banAndDeleteAllMessages(cellViewModel) } } @@ -107,7 +112,8 @@ extension ContextMenuVC { static func emojiPlusButton(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action { return Action( - isEmojiPlus: true + isEmojiPlus: true, + accessibilityLabel: "Add emoji" ) { delegate?.showFullEmojiKeyboard(cellViewModel) } } diff --git a/Session/Conversations/ConversationVC+Interaction.swift b/Session/Conversations/ConversationVC+Interaction.swift index efdc3ef47..a46a21118 100644 --- a/Session/Conversations/ConversationVC+Interaction.swift +++ b/Session/Conversations/ConversationVC+Interaction.swift @@ -1644,6 +1644,23 @@ extension ConversationVC: let thread: SessionThread = try SessionThread.fetchOne(db, id: threadId) else { return } + if + let quote = try? interaction.quote.fetchOne(db), + let quotedAttachment = try? quote.attachment.fetchOne(db), + quotedAttachment.isVisualMedia, + quotedAttachment.downloadUrl == Attachment.nonMediaQuoteFileId, + let quotedInteraction = try? quote.originalInteraction.fetchOne(db) + { + let attachment = try? quotedInteraction.attachments.fetchAll(db).first + try quote.with( + attachmentId: attachment?.cloneAsQuoteThumbnail()?.inserted(db).id + ).update(db) + } + + // Remove message sending jobs for the same interaction in database + // Prevent the same message being sent twice + try Job.filter(Job.Columns.interactionId == interaction.id).deleteAll(db) + try MessageSender.send( db, interaction: interaction, @@ -1902,7 +1919,11 @@ extension ConversationVC: } let actionSheet: UIAlertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) - actionSheet.addAction(UIAlertAction(title: "delete_message_for_me".localized(), style: .destructive) { [weak self] _ in + actionSheet.addAction(UIAlertAction( + title: "delete_message_for_me".localized(), + accessibilityIdentifier: "Delete for me", + style: .destructive + ) { [weak self] _ in Storage.shared.writeAsync { db in _ = try Interaction .filter(id: cellViewModel.id) @@ -1931,6 +1952,7 @@ extension ConversationVC: ) } }(), + accessibilityIdentifier: "Delete for everyone", style: .destructive ) { [weak self] _ in deleteRemotely( diff --git a/Session/Conversations/Input View/ExpandingAttachmentsButton.swift b/Session/Conversations/Input View/ExpandingAttachmentsButton.swift index cff2fda71..85757803b 100644 --- a/Session/Conversations/Input View/ExpandingAttachmentsButton.swift +++ b/Session/Conversations/Input View/ExpandingAttachmentsButton.swift @@ -26,28 +26,31 @@ 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 = "GIF button" - + result.accessibilityIdentifier = "GIF button" + result.isAccessibilityElement = true 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 = "Documents folder" + result.accessibilityIdentifier = "Documents folder" + result.isAccessibilityElement = true 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 = "Images folder" + result.accessibilityIdentifier = "Images folder" + result.isAccessibilityElement = true 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 = "Select camera button" + result.accessibilityIdentifier = "Select camera button" + result.isAccessibilityElement = true return result }() diff --git a/Session/Conversations/Input View/InputView.swift b/Session/Conversations/Input View/InputView.swift index 2709d61e6..8101060d1 100644 --- a/Session/Conversations/Input View/InputView.swift +++ b/Session/Conversations/Input View/InputView.swift @@ -54,6 +54,7 @@ final class InputView: UIView, InputViewButtonDelegate, InputTextViewDelegate, M private lazy var attachmentsButton: ExpandingAttachmentsButton = { let result = ExpandingAttachmentsButton(delegate: delegate) result.accessibilityLabel = "Attachments button" + result.accessibilityIdentifier = "Attachments button" result.isAccessibilityElement = true return result @@ -62,6 +63,7 @@ final class InputView: UIView, InputViewButtonDelegate, InputTextViewDelegate, M private lazy var voiceMessageButton: InputViewButton = { let result = InputViewButton(icon: #imageLiteral(resourceName: "Microphone"), delegate: self) result.accessibilityLabel = "New voice message" + result.accessibilityIdentifier = "New voice message" result.isAccessibilityElement = true return result @@ -70,6 +72,7 @@ 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.accessibilityIdentifier = "Send message button" result.accessibilityLabel = "Send message button" result.isAccessibilityElement = true @@ -87,6 +90,7 @@ final class InputView: UIView, InputViewButtonDelegate, InputTextViewDelegate, M private lazy var mentionsViewContainer: UIView = { let result: UIView = UIView() result.accessibilityLabel = "Mentions list" + result.accessibilityIdentifier = "Mentions list" result.isAccessibilityElement = true result.alpha = 0 @@ -119,6 +123,7 @@ final class InputView: UIView, InputViewButtonDelegate, InputTextViewDelegate, M let maxWidth = UIScreen.main.bounds.width - 2 * InputViewButton.expandedSize - 2 * Values.smallSpacing - 2 * (Values.mediumSpacing - adjustment) let result = InputTextView(delegate: self, maxWidth: maxWidth) result.accessibilityLabel = "Message input box" + result.accessibilityIdentifier = "Message input box" result.isAccessibilityElement = true return result diff --git a/Session/Conversations/Message Cells/Content Views/DeletedMessageView.swift b/Session/Conversations/Message Cells/Content Views/DeletedMessageView.swift index dd7d01d48..6d1882ecc 100644 --- a/Session/Conversations/Message Cells/Content Views/DeletedMessageView.swift +++ b/Session/Conversations/Message Cells/Content Views/DeletedMessageView.swift @@ -13,7 +13,8 @@ final class DeletedMessageView: UIView { init(textColor: ThemeValue) { super.init(frame: CGRect.zero) - + accessibilityIdentifier = "Deleted message" + isAccessibilityElement = true setUpViewHierarchy(textColor: textColor) } diff --git a/Session/Conversations/Message Cells/Content Views/MediaPlaceholderView.swift b/Session/Conversations/Message Cells/Content Views/MediaPlaceholderView.swift index 754ded084..56eb87aef 100644 --- a/Session/Conversations/Message Cells/Content Views/MediaPlaceholderView.swift +++ b/Session/Conversations/Message Cells/Content Views/MediaPlaceholderView.swift @@ -12,7 +12,8 @@ final class MediaPlaceholderView: UIView { init(cellViewModel: MessageViewModel, textColor: ThemeValue) { super.init(frame: CGRect.zero) - self.accessibilityLabel = "Untrusted attachment message" + self.accessibilityIdentifier = "Untrusted attachment message" + self.isAccessibilityElement = true setUpViewHierarchy(cellViewModel: cellViewModel, textColor: textColor) } diff --git a/Session/Conversations/Message Cells/Content Views/QuoteView.swift b/Session/Conversations/Message Cells/Content Views/QuoteView.swift index 2ee2f9068..ebd726a1c 100644 --- a/Session/Conversations/Message Cells/Content Views/QuoteView.swift +++ b/Session/Conversations/Message Cells/Content Views/QuoteView.swift @@ -144,7 +144,7 @@ final class QuoteView: UIView { .messageBubble_outgoingText : .messageBubble_incomingText ) - case .draft: return .messageBubble_outgoingText + case .draft: return .textPrimary } }() imageView.contentMode = .center @@ -156,10 +156,7 @@ final class QuoteView: UIView { mainStackView.addArrangedSubview(imageView) if (body ?? "").isEmpty { - body = (attachment.isImage ? - "Image" : - (isAudio ? "Audio" : "Document") - ) + body = attachment.shortDescription } // Generate the thumbnail if needed @@ -223,10 +220,10 @@ final class QuoteView: UIView { } .defaulting( to: attachment.map { - NSAttributedString(string: MIMETypeUtil.isAudio($0.contentType) ? "Audio" : "Document") + NSAttributedString(string: $0.shortDescription, attributes: [ .foregroundColor: textColor ]) } ) - .defaulting(to: NSAttributedString(string: "Document")) + .defaulting(to: NSAttributedString(string: "QUOTED_MESSAGE_NOT_FOUND".localized(), attributes: [ .foregroundColor: textColor ])) } // Label stack view diff --git a/Session/Conversations/Message Cells/Content Views/VoiceMessageView.swift b/Session/Conversations/Message Cells/Content Views/VoiceMessageView.swift index cdae7fa07..af2f386f8 100644 --- a/Session/Conversations/Message Cells/Content Views/VoiceMessageView.swift +++ b/Session/Conversations/Message Cells/Content Views/VoiceMessageView.swift @@ -98,7 +98,8 @@ public final class VoiceMessageView: UIView { init() { super.init(frame: CGRect.zero) - + self.accessibilityIdentifier = "Voice message" + self.isAccessibilityElement = true setUpViewHierarchy() } diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index ce6898c5b..591d3ade6 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -150,15 +150,17 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate { internal lazy var messageStatusLabel: UILabel = { let result = UILabel() + result.accessibilityIdentifier = "Message sent status" result.accessibilityLabel = "Message sent status" result.font = .systemFont(ofSize: Values.verySmallFontSize) - result.themeTextColor = .messageBubble_deliveryStatus + result.themeTextColor = .messageBubble_deliveryStatus return result }() internal lazy var messageStatusImageView: UIImageView = { let result = UIImageView() + result.accessibilityIdentifier = "Message sent status tick" result.accessibilityLabel = "Message sent status tick" result.contentMode = .scaleAspectFit result.themeTintColor = .messageBubble_deliveryStatus @@ -425,6 +427,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate { messageStatusLabel.text = statusText messageStatusLabel.themeTextColor = tintColor messageStatusImageView.image = image + messageStatusLabel.accessibilityIdentifier = "Message sent status: \(statusText ?? "invalid")" messageStatusImageView.themeTintColor = tintColor messageStatusContainerView.isHidden = ( cellViewModel.variant != .standardOutgoing || @@ -470,6 +473,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate { subview.removeFromSuperview() } albumView = nil + albumView = nil bodyTappableLabel = nil // Handle the deleted state first (it's much simpler than the others) @@ -541,7 +545,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate { let quoteView: QuoteView = QuoteView( for: .regular, authorId: quote.authorId, - quotedText: quote.body ?? "QUOTED_MESSAGE_NOT_FOUND".localized(), + quotedText: quote.body, threadVariant: cellViewModel.threadVariant, currentUserPublicKey: cellViewModel.currentUserPublicKey, currentUserBlindedPublicKey: cellViewModel.currentUserBlindedPublicKey, @@ -770,15 +774,15 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate { // MARK: - Interaction - override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - if let bodyTappableLabel = bodyTappableLabel { - let btIngetBodyTappableLabelCoordinates = convert(point, to: bodyTappableLabel) - if bodyTappableLabel.bounds.contains(btIngetBodyTappableLabelCoordinates) { - return bodyTappableLabel - } - } - return super.hitTest(point, with: event) - } +// override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { +// if let bodyTappableLabel = bodyTappableLabel { +// let btIngetBodyTappableLabelCoordinates = convert(point, to: bodyTappableLabel) +// if bodyTappableLabel.bounds.contains(btIngetBodyTappableLabelCoordinates) { +// return bodyTappableLabel +// } +// } +// return super.hitTest(point, with: event) +// } override func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true // Needed for the pan gesture recognizer to work with the table view's pan gesture recognizer diff --git a/Session/Conversations/Settings/ThreadSettingsViewModel.swift b/Session/Conversations/Settings/ThreadSettingsViewModel.swift index 72dec8e88..4e9b28e21 100644 --- a/Session/Conversations/Settings/ThreadSettingsViewModel.swift +++ b/Session/Conversations/Settings/ThreadSettingsViewModel.swift @@ -206,6 +206,10 @@ class ThreadSettingsViewModel: SessionTableViewModel Void = { [weak self] complete in self?.displayNameTextField.text = self?.originalInputValue + self?.displayNameContainer.accessibilityLabel = self?.displayNameLabel.text } if animated { diff --git a/SessionMessagingKit/Database/Models/Attachment.swift b/SessionMessagingKit/Database/Models/Attachment.swift index 72b8ff0c6..fc004c92e 100644 --- a/SessionMessagingKit/Database/Models/Attachment.swift +++ b/SessionMessagingKit/Database/Models/Attachment.swift @@ -787,6 +787,13 @@ extension Attachment { public var isText: Bool { MIMETypeUtil.isText(contentType) } public var isMicrosoftDoc: Bool { MIMETypeUtil.isMicrosoftDoc(contentType) } + public var shortDescription: String { + if isImage { return "Image" } + if isAudio { return "Audio" } + if isVideo { return "Video" } + return "Document" + } + public func readDataFromFile() throws -> Data? { guard let filePath: String = self.originalFilePath else { return nil diff --git a/SessionMessagingKit/Database/Models/Quote.swift b/SessionMessagingKit/Database/Models/Quote.swift index af92ee454..1b702ecf1 100644 --- a/SessionMessagingKit/Database/Models/Quote.swift +++ b/SessionMessagingKit/Database/Models/Quote.swift @@ -76,6 +76,26 @@ public struct Quote: Codable, Equatable, Hashable, FetchableRecord, PersistableR } } +// MARK: - Mutation + +public extension Quote { + func with( + interactionId: Int64? = nil, + authorId: String? = nil, + timestampMs: Int64? = nil, + body: String? = nil, + attachmentId: String? = nil + ) -> Quote { + return Quote( + interactionId: interactionId ?? self.interactionId, + authorId: authorId ?? self.authorId, + timestampMs: timestampMs ?? self.timestampMs, + body: body ?? self.body, + attachmentId: attachmentId ?? self.attachmentId + ) + } +} + // MARK: - Protobuf public extension Quote { diff --git a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+ClosedGroups.swift b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+ClosedGroups.swift index 669e46de0..5a5321554 100644 --- a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+ClosedGroups.swift +++ b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+ClosedGroups.swift @@ -420,7 +420,7 @@ extension MessageReceiver { // Delete the members to remove try GroupMember .filter(GroupMember.Columns.groupId == id) - .filter(updatedMemberIds.contains(GroupMember.Columns.profileId)) + .filter(membersToRemove.map{ $0.profileId }.contains(GroupMember.Columns.profileId)) .deleteAll(db) if didAdminLeave || sender == userPublicKey { diff --git a/SessionMessagingKit/Shared Models/SessionThreadViewModel.swift b/SessionMessagingKit/Shared Models/SessionThreadViewModel.swift index 461ec56b8..9c8c8e441 100644 --- a/SessionMessagingKit/Shared Models/SessionThreadViewModel.swift +++ b/SessionMessagingKit/Shared Models/SessionThreadViewModel.swift @@ -904,7 +904,7 @@ public extension SessionThreadViewModel { LEFT JOIN \(OpenGroup.self) ON \(openGroup[.threadId]) = \(thread[.id]) LEFT JOIN \(ClosedGroup.self) ON \(closedGroup[.threadId]) = \(thread[.id]) LEFT JOIN \(GroupMember.self) AS \(ViewModel.currentUserIsClosedGroupMemberKey) ON ( - \(SQL("\(ViewModel.currentUserIsClosedGroupMemberKey).\(groupMemberRoleColumnLiteral) = \(GroupMember.Role.standard)")) AND + \(SQL("\(ViewModel.currentUserIsClosedGroupMemberKey).\(groupMemberRoleColumnLiteral) != \(GroupMember.Role.zombie)")) AND \(ViewModel.currentUserIsClosedGroupMemberKey).\(groupMemberGroupIdColumnLiteral) = \(closedGroup[.threadId]) AND \(SQL("\(ViewModel.currentUserIsClosedGroupMemberKey).\(groupMemberProfileIdColumnLiteral) = \(userPublicKey)")) ) diff --git a/SessionUIKit/Components/ConfirmationModal.swift b/SessionUIKit/Components/ConfirmationModal.swift index d98dd9f5f..2ffe5947a 100644 --- a/SessionUIKit/Components/ConfirmationModal.swift +++ b/SessionUIKit/Components/ConfirmationModal.swift @@ -22,7 +22,7 @@ public class ConfirmationModal: Modal { let explanation: String? let attributedExplanation: NSAttributedString? let accessibilityLabel: String? - let accessibilityId: String? + let accessibilityIdentifier: String? public let stateToShow: State let confirmTitle: String? let confirmAccessibilityLabel: String? @@ -57,7 +57,7 @@ public class ConfirmationModal: Modal { self.explanation = explanation self.attributedExplanation = attributedExplanation self.accessibilityLabel = accessibilityLabel - self.accessibilityId = accessibilityId + self.accessibilityIdentifier = accessibilityId self.stateToShow = stateToShow self.confirmTitle = confirmTitle self.confirmAccessibilityLabel = confirmAccessibilityLabel @@ -241,8 +241,8 @@ public class ConfirmationModal: Modal { cancelButton.setTitle(info.cancelTitle, for: .normal) cancelButton.setThemeTitleColor(info.cancelStyle, for: .normal) - self.accessibilityLabel = info.accessibilityLabel - self.contentView.accessibilityIdentifier = info.accessibilityId + self.contentView.accessibilityLabel = info.accessibilityLabel + self.contentView.accessibilityIdentifier = info.accessibilityIdentifier } required init?(coder: NSCoder) { diff --git a/SignalUtilitiesKit/Media Viewing & Editing/Attachment Approval/AttachmentTextToolbar.swift b/SignalUtilitiesKit/Media Viewing & Editing/Attachment Approval/AttachmentTextToolbar.swift index 532d363ec..f290c43f5 100644 --- a/SignalUtilitiesKit/Media Viewing & Editing/Attachment Approval/AttachmentTextToolbar.swift +++ b/SignalUtilitiesKit/Media Viewing & Editing/Attachment Approval/AttachmentTextToolbar.swift @@ -58,6 +58,8 @@ class AttachmentTextToolbar: UIView, UITextViewDelegate { self.themeBackgroundColor = .clear textView.delegate = self + textView.accessibilityIdentifier = "Text input box" + textView.isAccessibilityElement = true let sendTitle = NSLocalizedString("ATTACHMENT_APPROVAL_SEND_BUTTON", comment: "Label for 'send' button in the 'attachment approval' dialog.") sendButton.setTitle(sendTitle, for: .normal) @@ -66,6 +68,8 @@ class AttachmentTextToolbar: UIView, UITextViewDelegate { sendButton.titleLabel?.font = .boldSystemFont(ofSize: Values.mediumFontSize) sendButton.titleLabel?.textAlignment = .center sendButton.themeTintColor = .textPrimary + sendButton.accessibilityIdentifier = "Send button" + sendButton.isAccessibilityElement = true // Increase hit area of send button sendButton.contentEdgeInsets = UIEdgeInsets(top: 6, left: 8, bottom: 6, right: 8) diff --git a/SignalUtilitiesKit/Shared View Controllers/ModalActivityIndicatorViewController.swift b/SignalUtilitiesKit/Shared View Controllers/ModalActivityIndicatorViewController.swift index 07d12166d..0cb3d92ba 100644 --- a/SignalUtilitiesKit/Shared View Controllers/ModalActivityIndicatorViewController.swift +++ b/SignalUtilitiesKit/Shared View Controllers/ModalActivityIndicatorViewController.swift @@ -40,6 +40,8 @@ public class ModalActivityIndicatorViewController: OWSViewController { result.set(.width, to: 64) result.set(.height, to: 64) + result.accessibilityIdentifier = "Loading animation" + ThemeManager.onThemeChange(observer: result) { [weak result] theme, _ in guard let textPrimary: UIColor = theme.color(for: .textPrimary) else { return }