[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
|
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)
|
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")!
|
let DCDThemeColor: AnyClass = NSClassFromString("DCDThemeColor")!
|
||||||
os_log("Found instance of DCDThemeColor", log: vendettaLog, type: .debug)
|
os_log("Found instance of DCDThemeColor", log: vendettaLog, type: .debug)
|
||||||
let target: AnyClass = object_getClass(DCDThemeColor)!
|
let target: AnyClass = object_getClass(DCDThemeColor)!
|
||||||
|
|
@ -38,9 +79,74 @@ func swizzleDCDThemeColor() {
|
||||||
os_log("DCDThemeColor has %{public}d methods", log: vendettaLog, type: .debug, methodCount)
|
os_log("DCDThemeColor has %{public}d methods", log: vendettaLog, type: .debug, methodCount)
|
||||||
|
|
||||||
for i in 0..<Int(methodCount) {
|
for i in 0..<Int(methodCount) {
|
||||||
let unwrapped = methods![i]
|
let method = methods![i]
|
||||||
let methodName = NSStringFromSelector(method_getName(unwrapped))
|
let selector = method_getName(method)
|
||||||
|
let methodName = NSStringFromSelector(selector)
|
||||||
os_log(
|
os_log(
|
||||||
"Found method %{public}@", log: vendettaLog, type: .debug, methodName)
|
"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(
|
orig.executeApplicationScript(
|
||||||
"this.__vendetta_theme=\(themeString)".data(using: .utf8)!, url: source, async: false)
|
"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 {
|
if vendetta != nil {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue