From 2053b6b0cdb6e5ec5d56810bb92355e5535c70d0 Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Fri, 19 May 2023 14:27:51 +1000 Subject: [PATCH 1/2] Added some accessibility info Fixed an issue where the Display Picture update modal wouldn't rendering animated images actually animating --- Session/Settings/SettingsViewModel.swift | 34 +++++++-- .../SessionUtil/SessionUtil.swift | 4 +- .../Components/ConfirmationModal.swift | 76 +++++++++++++++---- 3 files changed, 88 insertions(+), 26 deletions(-) diff --git a/Session/Settings/SettingsViewModel.swift b/Session/Settings/SettingsViewModel.swift index 9f0178bf7..f38e36281 100644 --- a/Session/Settings/SettingsViewModel.swift +++ b/Session/Settings/SettingsViewModel.swift @@ -3,6 +3,7 @@ import Foundation import Combine import GRDB +import YYImage import DifferenceKit import SessionUIKit import SessionMessagingKit @@ -155,9 +156,7 @@ class SettingsViewModel: SessionTableViewModel { - let userSessionId: String = self.userSessionId - - return navState + navState .map { [weak self] navState -> [NavItem] in switch navState { case .standard: @@ -488,21 +487,31 @@ class SettingsViewModel: SessionTableViewModel Bool { - // TODO: Need to set this timestamp to the correct date - guard Date().timeIntervalSince1970 < 1893456000 else { return true } + // TODO: Need to set this timestamp to the correct date (currently start of 2030) +// guard Date().timeIntervalSince1970 < 1893456000 else { return true } guard !SessionUtil.hasCheckedMigrationsCompleted.wrappedValue else { return SessionUtil.userConfigsEnabledIgnoringFeatureFlag } diff --git a/SessionUIKit/Components/ConfirmationModal.swift b/SessionUIKit/Components/ConfirmationModal.swift index 8d76907cb..60389c909 100644 --- a/SessionUIKit/Components/ConfirmationModal.swift +++ b/SessionUIKit/Components/ConfirmationModal.swift @@ -1,6 +1,7 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import UIKit +import YYImage import SessionUtilitiesKit // FIXME: Refactor as part of the Groups Rebuild @@ -41,6 +42,12 @@ public class ConfirmationModal: Modal { let result: UIView = UIView() result.isHidden = true + let gestureRecogniser: UITapGestureRecognizer = UITapGestureRecognizer( + target: self, + action: #selector(imageViewTapped) + ) + result.addGestureRecognizer(gestureRecogniser) + return result }() @@ -50,6 +57,18 @@ public class ConfirmationModal: Modal { result.contentMode = .scaleAspectFill result.set(.width, to: ConfirmationModal.imageSize) result.set(.height, to: ConfirmationModal.imageSize) + result.isHidden = true + + return result + }() + + private lazy var animatedImageView: YYAnimatedImageView = { + let result: YYAnimatedImageView = YYAnimatedImageView() + result.clipsToBounds = true + result.contentMode = .scaleAspectFill + result.set(.width, to: ConfirmationModal.imageSize) + result.set(.height, to: ConfirmationModal.imageSize) + result.isHidden = true return result }() @@ -84,12 +103,6 @@ public class ConfirmationModal: Modal { right: Values.largeSpacing ) - let gestureRecogniser: UITapGestureRecognizer = UITapGestureRecognizer( - target: self, - action: #selector(bodyTapped) - ) - result.addGestureRecognizer(gestureRecogniser) - return result }() @@ -115,6 +128,9 @@ public class ConfirmationModal: Modal { bottom: 6, right: 6 ) + result.isAccessibilityElement = true + result.accessibilityIdentifier = "Close button" + result.accessibilityLabel = "Close button" result.set(.width, to: ConfirmationModal.closeSize) result.set(.height, to: ConfirmationModal.closeSize) result.addTarget(self, action: #selector(close), for: .touchUpInside) @@ -146,6 +162,11 @@ public class ConfirmationModal: Modal { imageView.pin(.top, to: .top, of: imageViewContainer, withInset: 15) imageView.pin(.bottom, to: .bottom, of: imageViewContainer, withInset: -15) + imageViewContainer.addSubview(animatedImageView) + animatedImageView.center(.horizontal, in: imageViewContainer) + animatedImageView.pin(.top, to: .top, of: imageViewContainer, withInset: 15) + animatedImageView.pin(.bottom, to: .bottom, of: imageViewContainer, withInset: -15) + mainStackView.pin(to: contentView) closeButton.pin(.top, to: .top, of: contentView, withInset: 8) closeButton.pin(.right, to: .right, of: contentView, withInset: -8) @@ -185,15 +206,32 @@ public class ConfirmationModal: Modal { explanationLabel.attributedText = attributedText explanationLabel.isHidden = false - case .image(let placeholder, let value, let style, let onClick): + case .image(let placeholder, let value, let animatedValue, let style, let accessibility, let onClick): + imageViewContainer.isAccessibilityElement = (accessibility != nil) + imageViewContainer.accessibilityIdentifier = accessibility?.identifier + imageViewContainer.accessibilityLabel = accessibility?.label mainStackView.spacing = 0 - imageView.image = (value ?? placeholder) - imageView.layer.cornerRadius = (style == .circular ? - (ConfirmationModal.imageSize / 2) : - 0 - ) imageViewContainer.isHidden = false internalOnBodyTap = onClick + + if let animatedValue: YYImage = animatedValue { + imageView.isHidden = true + animatedImageView.image = animatedValue + animatedImageView.isHidden = false + animatedImageView.layer.cornerRadius = (style == .circular ? + (ConfirmationModal.imageSize / 2) : + 0 + ) + } + else { + animatedImageView.isHidden = true + imageView.image = (value ?? placeholder) + imageView.isHidden = false + imageView.layer.cornerRadius = (style == .circular ? + (ConfirmationModal.imageSize / 2) : + 0 + ) + } } confirmButton.accessibilityLabel = info.confirmAccessibility?.label @@ -219,7 +257,7 @@ public class ConfirmationModal: Modal { // MARK: - Interaction - @objc private func bodyTapped() { + @objc private func imageViewTapped() { internalOnBodyTap?() } @@ -407,7 +445,9 @@ public extension ConfirmationModal.Info { case image( placeholder: UIImage?, value: UIImage?, + animatedValue: YYImage?, style: ImageStyle, + accessibility: Accessibility?, onClick: (() -> ()) ) @@ -431,11 +471,13 @@ public extension ConfirmationModal.Info { // lhsOptions.map { "\($0.0)-\($0.1)" } == rhsValue.map { "\($0.0)-\($0.1)" } // ) - case (.image(let lhsPlaceholder, let lhsValue, let lhsStyle, _), .image(let rhsPlaceholder, let rhsValue, let rhsStyle, _)): + case (.image(let lhsPlaceholder, let lhsValue, let lhsAnimatedValue, let lhsStyle, let lhsAccessibility, _), .image(let rhsPlaceholder, let rhsValue, let rhsAnimatedValue, let rhsStyle, let rhsAccessibility, _)): return ( lhsPlaceholder == rhsPlaceholder && lhsValue == rhsValue && - lhsStyle == rhsStyle + lhsAnimatedValue == rhsAnimatedValue && + lhsStyle == rhsStyle && + lhsAccessibility == rhsAccessibility ) default: return false @@ -448,10 +490,12 @@ public extension ConfirmationModal.Info { case .text(let text): text.hash(into: &hasher) case .attributedText(let text): text.hash(into: &hasher) - case .image(let placeholder, let value, let style, _): + case .image(let placeholder, let value, let animatedValue, let style, let accessibility, _): placeholder.hash(into: &hasher) value.hash(into: &hasher) + animatedValue.hash(into: &hasher) style.hash(into: &hasher) + accessibility.hash(into: &hasher) } } } From 19eddd79a10e8223942322a98b6ba2c340b9284e Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Fri, 19 May 2023 14:55:35 +1000 Subject: [PATCH 2/2] Fixed an issue where non-visible messages were causing their conversations to appear Fixed a crash when trying to unsend a message --- Podfile | 1 + Podfile.lock | 2 +- .../Conversations/ConversationVC+Interaction.swift | 6 ++++-- .../Jobs/Types/ConfigurationSyncJob.swift | 2 +- .../Sending & Receiving/MessageReceiver.swift | 14 +++++++++++++- 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/Podfile b/Podfile index 1f8b96f72..d9f7d9613 100644 --- a/Podfile +++ b/Podfile @@ -94,6 +94,7 @@ abstract_target 'GlobalDependencies' do target 'SessionUIKit' do pod 'GRDB.swift/SQLCipher' pod 'DifferenceKit' + pod 'YYImage/libwebp', git: 'https://github.com/signalapp/YYImage' end end diff --git a/Podfile.lock b/Podfile.lock index 0d70b673b..051db4dda 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -212,6 +212,6 @@ SPEC CHECKSUMS: YYImage: f1ddd15ac032a58b78bbed1e012b50302d318331 ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb -PODFILE CHECKSUM: f461937f78a0482496fea6fc4b2bb5d1351fe044 +PODFILE CHECKSUM: 5a4993725a7d48be883663a52df2a5de45d2d099 COCOAPODS: 1.11.3 diff --git a/Session/Conversations/ConversationVC+Interaction.swift b/Session/Conversations/ConversationVC+Interaction.swift index ab105ca12..bdf4a4399 100644 --- a/Session/Conversations/ConversationVC+Interaction.swift +++ b/Session/Conversations/ConversationVC+Interaction.swift @@ -1791,8 +1791,10 @@ extension ConversationVC: // Show a loading indicator Deferred { Future { resolver in - ModalActivityIndicatorViewController.present(fromViewController: viewController, canCancel: false) { _ in - resolver(Result.success(())) + DispatchQueue.main.async { + ModalActivityIndicatorViewController.present(fromViewController: viewController, canCancel: false) { _ in + resolver(Result.success(())) + } } } } diff --git a/SessionMessagingKit/Jobs/Types/ConfigurationSyncJob.swift b/SessionMessagingKit/Jobs/Types/ConfigurationSyncJob.swift index bd7e183e1..7be4b4a3a 100644 --- a/SessionMessagingKit/Jobs/Types/ConfigurationSyncJob.swift +++ b/SessionMessagingKit/Jobs/Types/ConfigurationSyncJob.swift @@ -175,7 +175,7 @@ public extension ConfigurationSyncJob { static func enqueue(_ db: Database, publicKey: String) { // FIXME: Remove this once `useSharedUtilForUserConfig` is permanent - guard SessionUtil.userConfigsEnabled else { + guard SessionUtil.userConfigsEnabled(db) else { // If we don't have a userKeyPair (or name) yet then there is no need to sync the // configuration as the user doesn't fully exist yet (this will get triggered on // the first launch of a fresh install due to the migrations getting run and a few diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift index d4ab2e3c7..ba5f4263b 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift @@ -282,10 +282,22 @@ public enum MessageReceiver { threadId: String, message: Message ) throws { - // When handling any non-typing indicator message we want to make sure the thread becomes + // When handling any message type which has related UI we want to make sure the thread becomes // visible (the only other spot this flag gets set is when sending messages) switch message { + case is ReadReceipt: break case is TypingIndicator: break + case is ConfigurationMessage: break + case is UnsendRequest: break + + case let message as ClosedGroupControlMessage: + // Only re-show a legacy group conversation if we are going to add a control text message + switch message.kind { + case .new, .encryptionKeyPair, .encryptionKeyPairRequest: return + default: break + } + + fallthrough default: // Only update the `shouldBeVisible` flag if the thread is currently not visible