diff --git a/Session/Conversations/Input View/VoiceMessageRecordingView.swift b/Session/Conversations/Input View/VoiceMessageRecordingView.swift index 25a1985fa..9d782e387 100644 --- a/Session/Conversations/Input View/VoiceMessageRecordingView.swift +++ b/Session/Conversations/Input View/VoiceMessageRecordingView.swift @@ -62,7 +62,7 @@ final class VoiceMessageRecordingView: UIView { private lazy var chevronImageView: UIImageView = { let result: UIImageView = UIImageView( - image: (Dependencies.unsafeNonInjected.isRTL ? + image: (Dependencies.isRTL ? UIImage(named: "small_chevron_left")?.withHorizontallyFlippedOrientation() : UIImage(named: "small_chevron_left") )? @@ -276,9 +276,9 @@ final class VoiceMessageRecordingView: UIView { // MARK: - Interaction func handleLongPressMoved(to location: CGPoint) { - if ((!Dependencies.unsafeNonInjected.isRTL && location.x < bounds.center.x) || (Dependencies.unsafeNonInjected.isRTL && location.x > bounds.center.x)) { + if ((!Dependencies.isRTL && location.x < bounds.center.x) || (Dependencies.isRTL && location.x > bounds.center.x)) { let translationX = location.x - bounds.center.x - let sign: CGFloat = (Dependencies.unsafeNonInjected.isRTL ? 1 : -1) + let sign: CGFloat = (Dependencies.isRTL ? 1 : -1) let chevronDamping: CGFloat = 4 let labelDamping: CGFloat = 3 let chevronX = (chevronDamping * (sqrt(abs(translationX)) / sqrt(chevronDamping))) * sign diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index 501755196..0fa952860 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -364,7 +364,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate { // Flip horizontally for RTL languages replyIconImageView.transform = CGAffineTransform.identity .scaledBy( - x: (Dependencies.unsafeNonInjected.isRTL ? -1 : 1), + x: (Dependencies.isRTL ? -1 : 1), y: 1 ) @@ -803,8 +803,8 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate { // Only allow swipes to the left; allowing swipes to the right gets in the way of // the default iOS swipe to go back gesture guard - (Dependencies.unsafeNonInjected.isRTL && v.x > 0) || - (!Dependencies.unsafeNonInjected.isRTL && v.x < 0) + (Dependencies.isRTL && v.x > 0) || + (!Dependencies.isRTL && v.x < 0) else { return false } return abs(v.x) > abs(v.y) // It has to be more horizontal than vertical @@ -941,8 +941,8 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate { .translation(in: self) .x .clamp( - (Dependencies.unsafeNonInjected.isRTL ? 0 : -CGFloat.greatestFiniteMagnitude), - (Dependencies.unsafeNonInjected.isRTL ? CGFloat.greatestFiniteMagnitude : 0) + (Dependencies.isRTL ? 0 : -CGFloat.greatestFiniteMagnitude), + (Dependencies.isRTL ? CGFloat.greatestFiniteMagnitude : 0) ) switch gestureRecognizer.state { @@ -951,7 +951,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate { case .changed: // The idea here is to asymptotically approach a maximum drag distance let damping: CGFloat = 20 - let sign: CGFloat = (Dependencies.unsafeNonInjected.isRTL ? 1 : -1) + let sign: CGFloat = (Dependencies.isRTL ? 1 : -1) let x = (damping * (sqrt(abs(translationX)) / sqrt(damping))) * sign viewsToMoveForReply.forEach { $0.transform = CGAffineTransform(translationX: x, y: 0) } @@ -1206,7 +1206,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate { // we only highlight those cases) normalizedBody .ranges( - of: (Dependencies.unsafeNonInjected.isRTL ? + of: (Dependencies.isRTL ? "(\(part.lowercased()))(^|[^a-zA-Z0-9])" : "(^|[^a-zA-Z0-9])(\(part.lowercased()))" ), diff --git a/Session/Media Viewing & Editing/SendMediaNavigationController.swift b/Session/Media Viewing & Editing/SendMediaNavigationController.swift index 8820431f6..594cc1fa7 100644 --- a/Session/Media Viewing & Editing/SendMediaNavigationController.swift +++ b/Session/Media Viewing & Editing/SendMediaNavigationController.swift @@ -647,7 +647,7 @@ private class DoneButton: UIView { private lazy var chevron: UIView = { let image: UIImage = { - guard Dependencies.unsafeNonInjected.isRTL else { return #imageLiteral(resourceName: "small_chevron_right") } + guard Dependencies.isRTL else { return #imageLiteral(resourceName: "small_chevron_right") } return #imageLiteral(resourceName: "small_chevron_left") }() diff --git a/Session/Meta/AppDelegate.swift b/Session/Meta/AppDelegate.swift index 173d5f0f9..d10921636 100644 --- a/Session/Meta/AppDelegate.swift +++ b/Session/Meta/AppDelegate.swift @@ -642,7 +642,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD let rootViewControllerSetupComplete: (UIViewController) -> () = { [weak self, dependencies] rootViewController in /// `MainAppContext.determineDeviceRTL` uses UIKit to retrime `isRTL` so must be run on the main thread to prevent /// lag/crashes on background threads - dependencies.setIsRTLRetriever(requiresMainThread: true) { MainAppContext.determineDeviceRTL() } + Dependencies.setIsRTLRetriever(requiresMainThread: true) { MainAppContext.determineDeviceRTL() } /// Setup the `TopBannerController` let presentedViewController: UIViewController? = self?.window?.rootViewController?.presentedViewController diff --git a/Session/Settings/AppearanceViewController.swift b/Session/Settings/AppearanceViewController.swift index a980cdda4..9e40ec540 100644 --- a/Session/Settings/AppearanceViewController.swift +++ b/Session/Settings/AppearanceViewController.swift @@ -108,7 +108,7 @@ final class AppearanceViewController: BaseVC { trailing: Values.largeSpacing ) - if Dependencies.unsafeNonInjected.isRTL { + if Dependencies.isRTL { result.transform = CGAffineTransform.identity.scaledBy(x: -1, y: 1) } diff --git a/Session/Shared/FullConversationCell.swift b/Session/Shared/FullConversationCell.swift index c68265f15..f50399009 100644 --- a/Session/Shared/FullConversationCell.swift +++ b/Session/Shared/FullConversationCell.swift @@ -741,7 +741,7 @@ public final class FullConversationCell: UITableViewCell, SwipeActionOptimisticC // with the term so we use the regex below to ensure we only highlight those cases) normalizedSnippet .ranges( - of: (Dependencies.unsafeNonInjected.isRTL ? + of: (Dependencies.isRTL ? "(\(part.lowercased()))(^|[^a-zA-Z0-9])" : // stringlint:disable "(^|[^a-zA-Z0-9])(\(part.lowercased()))" // stringlint:disable ), diff --git a/SessionNotificationServiceExtension/NotificationServiceExtension.swift b/SessionNotificationServiceExtension/NotificationServiceExtension.swift index 3055d9ac3..40ab8d536 100644 --- a/SessionNotificationServiceExtension/NotificationServiceExtension.swift +++ b/SessionNotificationServiceExtension/NotificationServiceExtension.swift @@ -55,7 +55,7 @@ public final class NotificationServiceExtension: UNNotificationServiceExtension /// Create the context if we don't have it (needed before _any_ interaction with the database) if !dependencies[singleton: .appContext].isValid { dependencies.set(singleton: .appContext, to: NotificationServiceExtensionContext(using: dependencies)) - dependencies.setIsRTLRetriever(requiresMainThread: false) { + Dependencies.setIsRTLRetriever(requiresMainThread: false) { NotificationServiceExtensionContext.determineDeviceRTL() } } diff --git a/SessionShareExtension/ShareNavController.swift b/SessionShareExtension/ShareNavController.swift index 140913b6b..66668a97b 100644 --- a/SessionShareExtension/ShareNavController.swift +++ b/SessionShareExtension/ShareNavController.swift @@ -37,7 +37,7 @@ final class ShareNavController: UINavigationController, ShareViewDelegate { /// to override it results in the share context crashing so ensure it doesn't exist first) if !dependencies[singleton: .appContext].isValid { dependencies.set(singleton: .appContext, to: ShareAppExtensionContext(rootViewController: self, using: dependencies)) - dependencies.setIsRTLRetriever(requiresMainThread: false) { ShareAppExtensionContext.determineDeviceRTL() } + Dependencies.setIsRTLRetriever(requiresMainThread: false) { ShareAppExtensionContext.determineDeviceRTL() } } guard !SNUtilitiesKit.isRunningTests else { return } diff --git a/SessionUtilitiesKit/Dependency Injection/Dependencies.swift b/SessionUtilitiesKit/Dependency Injection/Dependencies.swift index b314bec0f..a72af251b 100644 --- a/SessionUtilitiesKit/Dependency Injection/Dependencies.swift +++ b/SessionUtilitiesKit/Dependency Injection/Dependencies.swift @@ -8,6 +8,9 @@ import Combine public class Dependencies { static let userInfoKey: CodingUserInfoKey = CodingUserInfoKey(rawValue: "session.dependencies.codingOptions")! + /// The `isRTLRetriever` is handled differently from normal dependencies because it's not really treated as such (it's more of + /// a convenience thing than anything) as such it's held outside of the `DependencyStorage` + private static var _isRTLRetriever: Atomic<(Bool, () -> Bool)> = Atomic((false, { false })) private static var _lastCreatedInstance: Atomic = Atomic(nil) private let featureChangeSubject: PassthroughSubject<(String, String?, Any?), Never> = PassthroughSubject() private var storage: Atomic = Atomic(DependencyStorage()) @@ -25,8 +28,8 @@ public class Dependencies { /// for anything accessed via this value) public static var unsafeNonInjected: Dependencies { _lastCreatedInstance.wrappedValue ?? Dependencies() } - public var isRTL: Bool { - let (requiresMainThread, retriever): (Bool, () -> Bool) = storage.wrappedValue.isRTLRetriever + public static var isRTL: Bool { + let (requiresMainThread, retriever): (Bool, () -> Bool) = _isRTLRetriever.wrappedValue /// Determining `isRTL` might require running on the main thread (it may need to accesses UIKit), if it requires the main thread but /// we are on a different thread then just default to `false` to prevent the background thread from potentially lagging and/or crashing @@ -128,8 +131,8 @@ public class Dependencies { } } - public func setIsRTLRetriever(requiresMainThread: Bool, isRTLRetriever: @escaping () -> Bool) { - storage.mutate { $0.isRTLRetriever = (requiresMainThread, isRTLRetriever) } + public static func setIsRTLRetriever(requiresMainThread: Bool, isRTLRetriever: @escaping () -> Bool) { + _isRTLRetriever.mutate { $0 = (requiresMainThread, isRTLRetriever) } } } @@ -280,7 +283,6 @@ private extension Dependencies { struct DependencyStorage { var initializationLocks: [Key: NSLock] = [:] var instances: [Key: Value] = [:] - var isRTLRetriever: (Bool, () -> Bool) = (false, { false }) struct Key: Hashable, CustomStringConvertible { enum Variant: String { diff --git a/SessionUtilitiesKit/General/UIEdgeInsets.swift b/SessionUtilitiesKit/General/UIEdgeInsets.swift index ef5777cda..f904b923e 100644 --- a/SessionUtilitiesKit/General/UIEdgeInsets.swift +++ b/SessionUtilitiesKit/General/UIEdgeInsets.swift @@ -8,9 +8,9 @@ extension UIEdgeInsets { public init(top: CGFloat, leading: CGFloat, bottom: CGFloat, trailing: CGFloat) { self.init( top: top, - left: (Dependencies.unsafeNonInjected.isRTL ? trailing : leading), + left: (Dependencies.isRTL ? trailing : leading), bottom: bottom, - right: (Dependencies.unsafeNonInjected.isRTL ? leading : trailing) + right: (Dependencies.isRTL ? leading : trailing) ) } } diff --git a/SignalUtilitiesKit/Utilities/UIViewController+OWS.swift b/SignalUtilitiesKit/Utilities/UIViewController+OWS.swift index 99c01f854..00b246e35 100644 --- a/SignalUtilitiesKit/Utilities/UIViewController+OWS.swift +++ b/SignalUtilitiesKit/Utilities/UIViewController+OWS.swift @@ -65,12 +65,12 @@ public extension UIViewController { let backButton: UIButton = UIButton(type: .custom) // Nudge closer to the left edge to match default back button item. - let extraLeftPadding: CGFloat = (Dependencies.unsafeNonInjected.isRTL ? 0 : -8) + let extraLeftPadding: CGFloat = (Dependencies.isRTL ? 0 : -8) // Give some extra hit area to the back button. This is a little smaller // than the default back button, but makes sense for our left aligned title // view in the MessagesViewController - let extraRightPadding: CGFloat = (Dependencies.unsafeNonInjected.isRTL ? -0 : 10) + let extraRightPadding: CGFloat = (Dependencies.isRTL ? -0 : 10) // Extra hit area above/below let extraHeightPadding: CGFloat = 8