[Themes] Rough but working code
This commit is contained in:
parent
318e393f61
commit
1178b53a27
2 changed files with 113 additions and 4 deletions
|
|
@ -23,9 +23,50 @@ struct Theme: Codable {
|
|||
let data: ThemeData
|
||||
}
|
||||
|
||||
func swizzleDCDThemeColor() {
|
||||
func hexToUIColor(_ hex: String) -> UIColor? {
|
||||
let r: CGFloat
|
||||
let g: CGFloat
|
||||
let b: CGFloat
|
||||
let a: CGFloat
|
||||
|
||||
if hex.hasPrefix("#") {
|
||||
let start = hex.index(hex.startIndex, offsetBy: 1)
|
||||
var hexColor = String(hex[start...])
|
||||
|
||||
if hexColor.count == 6 {
|
||||
hexColor.append("ff")
|
||||
}
|
||||
|
||||
if hexColor.count == 8 {
|
||||
let scanner = Scanner(string: hexColor)
|
||||
var hexNumber: UInt64 = 0
|
||||
|
||||
if scanner.scanHexInt64(&hexNumber) {
|
||||
r = CGFloat((hexNumber & 0xff00_0000) >> 24) / 255
|
||||
g = CGFloat((hexNumber & 0x00ff_0000) >> 16) / 255
|
||||
b = CGFloat((hexNumber & 0x0000_ff00) >> 8) / 255
|
||||
a = CGFloat(hexNumber & 0x0000_00ff) / 255
|
||||
|
||||
return UIColor(red: r, green: g, blue: b, alpha: a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func swizzleDCDThemeColor(_ semanticColors: [String: [String]]) {
|
||||
os_log("Swizzling DCDThemeColor", log: vendettaLog, type: .info)
|
||||
|
||||
let DCDTheme = NSClassFromString("DCDTheme")!
|
||||
let dcdThemeTarget: AnyClass = object_getClass(DCDTheme)!
|
||||
|
||||
let themeIndexSelector = NSSelectorFromString("themeIndex")
|
||||
let themeIndexMethod = class_getClassMethod(dcdThemeTarget, themeIndexSelector)!
|
||||
let themeIndexImpl = method_getImplementation(themeIndexMethod)
|
||||
typealias ThemeIndexType = @convention(c) (AnyObject, Selector) -> Int
|
||||
let themeIndex: ThemeIndexType = unsafeBitCast(themeIndexImpl, to: ThemeIndexType.self)
|
||||
|
||||
let DCDThemeColor: AnyClass = NSClassFromString("DCDThemeColor")!
|
||||
os_log("Found instance of DCDThemeColor", log: vendettaLog, type: .debug)
|
||||
let target: AnyClass = object_getClass(DCDThemeColor)!
|
||||
|
|
@ -38,9 +79,74 @@ func swizzleDCDThemeColor() {
|
|||
os_log("DCDThemeColor has %{public}d methods", log: vendettaLog, type: .debug, methodCount)
|
||||
|
||||
for i in 0..<Int(methodCount) {
|
||||
let unwrapped = methods![i]
|
||||
let methodName = NSStringFromSelector(method_getName(unwrapped))
|
||||
let method = methods![i]
|
||||
let selector = method_getName(method)
|
||||
let methodName = NSStringFromSelector(selector)
|
||||
os_log(
|
||||
"Found method %{public}@", log: vendettaLog, type: .debug, methodName)
|
||||
if let semanticColor = semanticColors[methodName] {
|
||||
os_log(
|
||||
"Swizzling %{public}@", log: vendettaLog, type: .debug, methodName)
|
||||
|
||||
let originalImpl = method_getImplementation(method)
|
||||
typealias OriginalType = @convention(c) (AnyObject, Selector) -> UIColor
|
||||
let original = unsafeBitCast(originalImpl, to: OriginalType.self)
|
||||
let semanticColorBlock: @convention(block) (AnyObject) -> UIColor = {
|
||||
(self: AnyObject) -> UIColor in
|
||||
let themeIndexVal = themeIndex(dcdThemeTarget, themeIndexSelector)
|
||||
if semanticColor.count - 1 >= themeIndexVal {
|
||||
if let semanticUIColor = hexToUIColor(
|
||||
semanticColor[themeIndexVal])
|
||||
{
|
||||
return semanticUIColor
|
||||
}
|
||||
}
|
||||
|
||||
return original(target, selector)
|
||||
}
|
||||
let semanticColorImplementation = imp_implementationWithBlock(
|
||||
unsafeBitCast(semanticColorBlock, to: AnyObject.self))
|
||||
method_setImplementation(
|
||||
method, semanticColorImplementation)
|
||||
|
||||
}
|
||||
}
|
||||
free(methods)
|
||||
}
|
||||
|
||||
func swizzleUIColor(_ rawColors: [String: String]) {
|
||||
os_log("Swizzling UIColor", log: vendettaLog, type: .info)
|
||||
|
||||
let UIColor: AnyClass = NSClassFromString("UIColor")!
|
||||
os_log("Found instance of UIColor", log: vendettaLog, type: .debug)
|
||||
let target: AnyClass = object_getClass(UIColor)!
|
||||
|
||||
os_log("Found UIColor", log: vendettaLog, type: .debug)
|
||||
|
||||
var methodCount: UInt32 = 0
|
||||
let methods = class_copyMethodList(target, &methodCount)
|
||||
|
||||
os_log("UIColor has %{public}d methods", log: vendettaLog, type: .debug, methodCount)
|
||||
|
||||
for i in 0..<Int(methodCount) {
|
||||
let method = methods![i]
|
||||
let selector = method_getName(method)
|
||||
let methodName = NSStringFromSelector(selector)
|
||||
os_log(
|
||||
"Found method %{public}@", log: vendettaLog, type: .debug, methodName)
|
||||
if let rawColor = rawColors[methodName] {
|
||||
os_log(
|
||||
"Swizzling %{public}@", log: vendettaLog, type: .debug, methodName)
|
||||
let rawColorBlock: @convention(block) (AnyObject) -> UIColor = {
|
||||
(self: AnyObject) -> UIColor in
|
||||
return hexToUIColor(rawColor)!
|
||||
}
|
||||
let rawColorImplementation = imp_implementationWithBlock(
|
||||
unsafeBitCast(rawColorBlock, to: AnyObject.self))
|
||||
method_setImplementation(
|
||||
method, rawColorImplementation)
|
||||
|
||||
}
|
||||
}
|
||||
free(methods)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,10 @@ class LoadHook: ClassHook<RCTCxxBridge> {
|
|||
{
|
||||
orig.executeApplicationScript(
|
||||
"this.__vendetta_theme=\(themeString)".data(using: .utf8)!, url: source, async: false)
|
||||
swizzleDCDThemeColor()
|
||||
let theme = try? JSONDecoder().decode(Theme.self, from: themeString.data(using: .utf8)!)
|
||||
if let semanticColors = theme?.data.semanticColors { swizzleDCDThemeColor(semanticColors) }
|
||||
if let rawColors = theme?.data.rawColors { swizzleUIColor(rawColors) }
|
||||
|
||||
}
|
||||
|
||||
if vendetta != nil {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue