diff --git a/FireworkVideoUI.podspec b/FireworkVideoUI.podspec index 0e20e2f..e4ea145 100644 --- a/FireworkVideoUI.podspec +++ b/FireworkVideoUI.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FireworkVideoUI' - s.version = '0.1.0' + s.version = '0.1.2' s.summary = 'An extension library meant to provide easier interfaces for the FireworkVideoSDK.' s.homepage = 'https://github.com/loopsocial/firework_ios_sdk_ui_extensions' s.license = 'Apache License, Version 2.0' diff --git a/Sources/FireworkVideoUI/AppLanguage/AppLanguageManager.swift b/Sources/FireworkVideoUI/AppLanguage/AppLanguageManager.swift index 89cac35..b227c8a 100644 --- a/Sources/FireworkVideoUI/AppLanguage/AppLanguageManager.swift +++ b/Sources/FireworkVideoUI/AppLanguage/AppLanguageManager.swift @@ -103,13 +103,13 @@ public class AppLanguageManager { UIViewController.swizzleViewControllerMethodsForAppLanguage() Bundle.swizzleBundleMethodsForAppLanguage() URLSession.swizzleURLSessionMethodsForAppLanguage() - NumberFormatter.swizzleNumberFormatterMethodsForAppLanguage() UIImageView.swizzleImageViewMethodsForAppLanguage() UILabel.swizzleLabelMethodsForAppLanguage() UITextField.swizzleTextFieldMethodsForAppLanguage() UITextView.swizzleTextViewMethodsForAppLanguage() UIWindow.swizzleWindowMethodsForAppLanguage() UIView.swizzleViewMethodsForAppLanguage() + NSLocale.swizzleNSLocaleMethodsForAppLanguage() } LayoutFlipManager.swizzelMethods() diff --git a/Sources/FireworkVideoUI/AppLanguage/Extensions/Foundation/NSLocale+AppLanguage.swift b/Sources/FireworkVideoUI/AppLanguage/Extensions/Foundation/NSLocale+AppLanguage.swift new file mode 100644 index 0000000..748b97b --- /dev/null +++ b/Sources/FireworkVideoUI/AppLanguage/Extensions/Foundation/NSLocale+AppLanguage.swift @@ -0,0 +1,49 @@ +// +// Locale+AppLanguage.swift +// +// Created by linjie jiang on 5/7/24. +// + +import Foundation + +extension NSLocale { + static func swizzleNSLocaleMethodsForAppLanguage() { + Swizzle.swizzleClassSelector( + cls: self, + originalSelector: #selector(getter: NSLocale.current), + customSelector: #selector(NSLocale.fw_current)) + Swizzle.swizzleClassSelector( + cls: self, + originalSelector: #selector(getter: NSLocale.autoupdatingCurrent), + customSelector: #selector(NSLocale.fw_autoupdatingCurrent)) + Swizzle.swizzleClassSelector( + cls: self, + originalSelector: #selector(getter: NSLocale.preferredLanguages), + customSelector: #selector(NSLocale.fw_preferredLanguages)) + } + + @objc class func fw_current() -> Locale { + if let language = AppLanguageManager.shared.appLanguage { + return Locale(identifier: language) + } + + return fw_current() + } + + @objc class func fw_autoupdatingCurrent() -> Locale { + if let language = AppLanguageManager.shared.appLanguage { + return Locale(identifier: language) + } + + return fw_autoupdatingCurrent() + } + + @objc class func fw_preferredLanguages() -> [String] { + let languages = fw_preferredLanguages() + if let language = AppLanguageManager.shared.appLanguage { + return [language] + languages + } + + return languages + } +} diff --git a/Sources/FireworkVideoUI/AppLanguage/Extensions/Foundation/NumberFormatter+AppLanguage.swift b/Sources/FireworkVideoUI/AppLanguage/Extensions/Foundation/NumberFormatter+AppLanguage.swift deleted file mode 100644 index 8a0735e..0000000 --- a/Sources/FireworkVideoUI/AppLanguage/Extensions/Foundation/NumberFormatter+AppLanguage.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// NumberFormatter+AppLanguage.swift -// -// Created by linjie jiang on 2023/2/20. -// - -import Foundation - -extension NumberFormatter { - static func swizzleNumberFormatterMethodsForAppLanguage() { - Swizzle.swizzleSelector( - cls: self, - originalSelector: #selector(NumberFormatter.string(from:)), - customSelector: #selector(NumberFormatter.fw_string(from:))) - } - - @objc func fw_string(from number: NSNumber) -> String? { - if let language = AppLanguageManager.shared.appLanguage, - self.numberStyle == .currency { - self.locale = Locale(identifier: language) - } - - return fw_string(from: number) - } -} diff --git a/Sources/FireworkVideoUI/AppLanguage/Extensions/UIKit/UILabel+AppLanguage.swift b/Sources/FireworkVideoUI/AppLanguage/Extensions/UIKit/UILabel+AppLanguage.swift index 97dc013..4059e7a 100644 --- a/Sources/FireworkVideoUI/AppLanguage/Extensions/UIKit/UILabel+AppLanguage.swift +++ b/Sources/FireworkVideoUI/AppLanguage/Extensions/UIKit/UILabel+AppLanguage.swift @@ -8,7 +8,7 @@ import UIKit extension UILabel { private struct AssociatedKeys { - static var hasCalculatedTextAlignment = "hasCalculatedTextAlignmentKey" + static var hasCalculatedTextAlignment: UInt8 = 0 } private var hasCalculatedTextAlignment: Bool { diff --git a/Sources/FireworkVideoUI/AppLanguage/Extensions/UIKit/UITextField+AppLanguage.swift b/Sources/FireworkVideoUI/AppLanguage/Extensions/UIKit/UITextField+AppLanguage.swift index f5f0b78..9acd08c 100644 --- a/Sources/FireworkVideoUI/AppLanguage/Extensions/UIKit/UITextField+AppLanguage.swift +++ b/Sources/FireworkVideoUI/AppLanguage/Extensions/UIKit/UITextField+AppLanguage.swift @@ -8,7 +8,7 @@ import UIKit extension UITextField { private struct AssociatedKeys { - static var hasCalculatedTextAlignment = "hasCalculatedTextAlignmentKey" + static var hasCalculatedTextAlignment: UInt8 = 0 } private var hasCalculatedTextAlignment: Bool { diff --git a/Sources/FireworkVideoUI/AppLanguage/Extensions/UIKit/UITextView+AppLanguage.swift b/Sources/FireworkVideoUI/AppLanguage/Extensions/UIKit/UITextView+AppLanguage.swift index d9d2f95..a1c02ee 100644 --- a/Sources/FireworkVideoUI/AppLanguage/Extensions/UIKit/UITextView+AppLanguage.swift +++ b/Sources/FireworkVideoUI/AppLanguage/Extensions/UIKit/UITextView+AppLanguage.swift @@ -8,7 +8,7 @@ import UIKit extension UITextView { private struct AssociatedKeys { - static var hasCalculatedTextAlignment = "hasCalculatedTextAlignmentKey" + static var hasCalculatedTextAlignment: UInt8 = 0 } private var hasCalculatedTextAlignment: Bool { diff --git a/Sources/FireworkVideoUI/AppLanguage/Extensions/UIKit/UIView+AppLanguage.swift b/Sources/FireworkVideoUI/AppLanguage/Extensions/UIKit/UIView+AppLanguage.swift index 8893eca..7f733ba 100644 --- a/Sources/FireworkVideoUI/AppLanguage/Extensions/UIKit/UIView+AppLanguage.swift +++ b/Sources/FireworkVideoUI/AppLanguage/Extensions/UIKit/UIView+AppLanguage.swift @@ -8,6 +8,10 @@ import UIKit import FireworkVideo import AVFoundation +private let gNamesOfImagesWithDirection: [String] = [ + "c3RyZWFtLWdhdGUtYmFjaw==".decodeBase64String(), +] + extension UIView { static func swizzleViewMethodsForAppLanguage() { Swizzle.swizzleSelector( @@ -60,7 +64,35 @@ extension UIView { view.viewType = .normal } + let swiftUIImageLayerClassName = "SW1hZ2VMYXllcg==".decodeBase64String() + let swiftUITextLayerClassName = "Q0dEcmF3aW5nTGF5ZXI=".decodeBase64String() + let layerClassName = String(describing: type(of: self.layer)) + + if AppLanguageManager.shared.shouldHorizontalFlip, + layerClassName == swiftUITextLayerClassName || + layerClassName == swiftUIImageLayerClassName { + view.viewType = .normal + } + DispatchQueue.main.async { + if AppLanguageManager.shared.shouldHorizontalFlip, + layerClassName == swiftUIImageLayerClassName, + let contents = self.layer.contents as? CFTypeRef, + CFGetTypeID(contents) == CGImage.typeID { + let image = self.layer.contents as! CGImage + for imageName in gNamesOfImagesWithDirection { + let imageWithDirection = UIImage( + named: imageName, + in: Bundle(for: FireworkVideoSDK.self), + compatibleWith: nil + )?.cgImage + if image == imageWithDirection { + view.viewType = .flip + break + } + } + } + if view.layer.sublayers?.first(where: { layer in layer is AVPlayerLayer }) != nil, AppLanguageManager.shared.shouldHorizontalFlip { diff --git a/Sources/FireworkVideoUI/Extensions/ObjCRuntime/Swizzle.swift b/Sources/FireworkVideoUI/Extensions/ObjCRuntime/Swizzle.swift index 401326a..a886f93 100644 --- a/Sources/FireworkVideoUI/Extensions/ObjCRuntime/Swizzle.swift +++ b/Sources/FireworkVideoUI/Extensions/ObjCRuntime/Swizzle.swift @@ -32,6 +32,21 @@ public class Swizzle { guard let originalMethod = class_getClassMethod(cls, originalSelector) else { return } guard let customMethod = class_getClassMethod(cls, customSelector) else { return } - method_exchangeImplementations(originalMethod, customMethod) + let clsType: AnyClass? = object_getClass(cls) + if class_addMethod( + clsType, + originalSelector, + method_getImplementation(customMethod), + method_getTypeEncoding(customMethod) + ) { + class_replaceMethod( + clsType, + customSelector, + method_getImplementation(originalMethod), + method_getTypeEncoding(originalMethod) + ) + } else { + method_exchangeImplementations(originalMethod, customMethod) + } } } diff --git a/Sources/FireworkVideoUI/LayoutFlip/Extensions/Foundation/NSObject+LayoutFlip.swift b/Sources/FireworkVideoUI/LayoutFlip/Extensions/Foundation/NSObject+LayoutFlip.swift index 42091eb..d39257d 100644 --- a/Sources/FireworkVideoUI/LayoutFlip/Extensions/Foundation/NSObject+LayoutFlip.swift +++ b/Sources/FireworkVideoUI/LayoutFlip/Extensions/Foundation/NSObject+LayoutFlip.swift @@ -10,7 +10,7 @@ typealias ReloadClosure = () -> Void extension NSObject { private struct AssociatedKeys { - static var reloadClosures = "reloadBlocks" + static var reloadClosures: UInt8 = 0 } private var reloadClosures: [String: ReloadClosure] { diff --git a/Sources/FireworkVideoUI/LayoutFlip/Extensions/UIKit/CALayer+LayoutFlip.swift b/Sources/FireworkVideoUI/LayoutFlip/Extensions/UIKit/CALayer+LayoutFlip.swift index 5d4ffe4..34be76b 100644 --- a/Sources/FireworkVideoUI/LayoutFlip/Extensions/UIKit/CALayer+LayoutFlip.swift +++ b/Sources/FireworkVideoUI/LayoutFlip/Extensions/UIKit/CALayer+LayoutFlip.swift @@ -8,9 +8,9 @@ import UIKit extension CALayer { private struct AssociatedKeys { - static var basicTransform = "basicTransform" - static var isRenderStartLayer = "isRenderStartLayer" - static var affineTransform = "affineTransform" + static var basicTransform: UInt8 = 0 + static var isRenderStartLayer: UInt8 = 0 + static var affineTransform: UInt8 = 0 } static func swizzleLayerMethodsForLayoutFlip() { diff --git a/Sources/FireworkVideoUI/LayoutFlip/Extensions/UIKit/UIView+LayoutFlip.swift b/Sources/FireworkVideoUI/LayoutFlip/Extensions/UIKit/UIView+LayoutFlip.swift index c23bb00..a7fb95f 100644 --- a/Sources/FireworkVideoUI/LayoutFlip/Extensions/UIKit/UIView+LayoutFlip.swift +++ b/Sources/FireworkVideoUI/LayoutFlip/Extensions/UIKit/UIView+LayoutFlip.swift @@ -17,8 +17,8 @@ private let gNoFlipClasses: [Any] = [ "PUPhotosSectionHeaderContentView", "UITableViewIndex", "UIWebView", - "X1VJUmVtb3RlVmlldw==".decodeBase64String(), // _UIRemoteView - "VUlBdXRvY29ycmVjdFRleHRWaWV3".decodeBase64String() // UIAutocorrectTextView + "X1VJUmVtb3RlVmlldw==".decodeBase64String(), + "VUlBdXRvY29ycmVjdFRleHRWaWV3".decodeBase64String(), ] enum LayoutFlipViewType: Int { @@ -32,9 +32,9 @@ enum LayoutFlipViewType: Int { extension UIView { private struct AssociatedKeys { - static var viewType = "viewType" - static var calculatedViewType = "calculatedViewType" - static var lastType = "lastType" + static var viewType: UInt8 = 0 + static var calculatedViewType: UInt8 = 0 + static var lastType: UInt8 = 0 } static func swizzleViewMethodsForLayoutFlip() { @@ -50,6 +50,10 @@ extension UIView { cls: self, originalSelector: #selector(UIView.snapshotView(afterScreenUpdates:)), customSelector: #selector(UIView.fw_snapshotView(afterScreenUpdates:))) + Swizzle.swizzleSelector( + cls: self, + originalSelector: #selector(UIView.layoutSubviews), + customSelector: #selector(UIView.fw_layoutSubviews)) } var viewType: LayoutFlipViewType { @@ -137,6 +141,11 @@ extension UIView { return view } + @objc func fw_layoutSubviews() { + fw_layoutSubviews() + renewLayerTransformForceRecursively(false) + } + func renewLayerTransformForceRecursively(_ forceRecursively: Bool) { if !isIOSSDKView { return @@ -151,7 +160,11 @@ extension UIView { let shouldSetFlipTransform = shouldFlipSuperview != shouldFlipCurrentView if shouldSetFlipTransform && LayoutFlipManager.shared.enableHorizontalFlip { - layer.basicTransform = CGAffineTransformMakeScale(-1, 1) + if layer.anchorPoint == CGPointZero { + layer.basicTransform = CGAffineTransformConcat(CGAffineTransformMakeScale(-1, 1), CGAffineTransform(translationX: layer.bounds.width, y: 0)) + } else { + layer.basicTransform = CGAffineTransformMakeScale(-1, 1) + } } else { layer.basicTransform = CGAffineTransformIdentity }