2023-03-17 15:48:57 -04:00
|
|
|
import Orion
|
|
|
|
|
import UIKit
|
2024-03-15 08:10:25 +08:00
|
|
|
import PyoncordTweakC
|
2023-03-17 15:48:57 -04:00
|
|
|
import os
|
|
|
|
|
|
|
|
|
|
struct Author: Codable {
|
|
|
|
|
let name: String
|
|
|
|
|
let id: String?
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ThemeData: Codable {
|
|
|
|
|
let name: String
|
|
|
|
|
let description: String?
|
|
|
|
|
let authors: [Author]?
|
|
|
|
|
let spec: Int
|
|
|
|
|
let semanticColors: [String: [String]]?
|
|
|
|
|
let rawColors: [String: String]?
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct Theme: Codable {
|
|
|
|
|
let id: String
|
|
|
|
|
let selected: Bool
|
|
|
|
|
let data: ThemeData
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-19 04:45:46 -04:00
|
|
|
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]]) {
|
2024-03-15 08:10:25 +08:00
|
|
|
os_log("Swizzling DCDThemeColor", log: pyoncordLog, type: .info)
|
2023-03-17 15:48:57 -04:00
|
|
|
|
2023-03-19 13:57:58 -04:00
|
|
|
let DCDTheme: AnyClass = NSClassFromString("DCDTheme")!
|
2023-03-19 04:45:46 -04:00
|
|
|
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)
|
|
|
|
|
|
2023-03-17 15:48:57 -04:00
|
|
|
let DCDThemeColor: AnyClass = NSClassFromString("DCDThemeColor")!
|
2024-03-15 08:10:25 +08:00
|
|
|
os_log("Found instance of DCDThemeColor", log: pyoncordLog, type: .debug)
|
2023-03-17 15:48:57 -04:00
|
|
|
let target: AnyClass = object_getClass(DCDThemeColor)!
|
|
|
|
|
|
2024-03-15 08:10:25 +08:00
|
|
|
os_log("Found DCDThemeColor", log: pyoncordLog, type: .debug)
|
2023-03-17 15:48:57 -04:00
|
|
|
|
|
|
|
|
var methodCount: UInt32 = 0
|
2023-03-19 13:57:58 -04:00
|
|
|
let methods = class_copyMethodList(target, &methodCount)!
|
2023-03-17 15:48:57 -04:00
|
|
|
|
2024-03-15 08:10:25 +08:00
|
|
|
os_log("DCDThemeColor has %{public}d methods", log: pyoncordLog, type: .debug, methodCount)
|
2023-03-17 15:48:57 -04:00
|
|
|
|
|
|
|
|
for i in 0..<Int(methodCount) {
|
2023-03-19 13:57:58 -04:00
|
|
|
let method = methods[i]
|
2023-03-19 04:45:46 -04:00
|
|
|
let selector = method_getName(method)
|
|
|
|
|
let methodName = NSStringFromSelector(selector)
|
|
|
|
|
os_log(
|
2024-03-15 08:10:25 +08:00
|
|
|
"Found method %{public}@", log: pyoncordLog, type: .debug, methodName)
|
2023-03-19 04:45:46 -04:00
|
|
|
if let semanticColor = semanticColors[methodName] {
|
|
|
|
|
os_log(
|
2024-03-15 08:10:25 +08:00
|
|
|
"Swizzling %{public}@", log: pyoncordLog, type: .debug, methodName)
|
2023-03-19 04:45:46 -04:00
|
|
|
|
|
|
|
|
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]) {
|
2024-03-15 08:10:25 +08:00
|
|
|
os_log("Swizzling UIColor", log: pyoncordLog, type: .info)
|
2023-03-19 04:45:46 -04:00
|
|
|
|
|
|
|
|
let UIColor: AnyClass = NSClassFromString("UIColor")!
|
2024-03-15 08:10:25 +08:00
|
|
|
os_log("Found instance of UIColor", log: pyoncordLog, type: .debug)
|
2023-03-19 04:45:46 -04:00
|
|
|
let target: AnyClass = object_getClass(UIColor)!
|
|
|
|
|
|
2024-03-15 08:10:25 +08:00
|
|
|
os_log("Found UIColor", log: pyoncordLog, type: .debug)
|
2023-03-19 04:45:46 -04:00
|
|
|
|
|
|
|
|
var methodCount: UInt32 = 0
|
2023-03-19 13:57:58 -04:00
|
|
|
let methods = class_copyMethodList(target, &methodCount)!
|
2023-03-19 04:45:46 -04:00
|
|
|
|
2024-03-15 08:10:25 +08:00
|
|
|
os_log("UIColor has %{public}d methods", log: pyoncordLog, type: .debug, methodCount)
|
2023-03-19 04:45:46 -04:00
|
|
|
|
|
|
|
|
for i in 0..<Int(methodCount) {
|
2023-03-19 13:57:58 -04:00
|
|
|
let method = methods[i]
|
2023-03-19 04:45:46 -04:00
|
|
|
let selector = method_getName(method)
|
|
|
|
|
let methodName = NSStringFromSelector(selector)
|
2023-03-17 15:48:57 -04:00
|
|
|
os_log(
|
2024-03-15 08:10:25 +08:00
|
|
|
"Found method %{public}@", log: pyoncordLog, type: .debug, methodName)
|
2023-03-19 04:45:46 -04:00
|
|
|
if let rawColor = rawColors[methodName] {
|
|
|
|
|
os_log(
|
2024-03-15 08:10:25 +08:00
|
|
|
"Swizzling %{public}@", log: pyoncordLog, type: .debug, methodName)
|
2023-03-19 04:45:46 -04:00
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
}
|
2023-03-17 15:48:57 -04:00
|
|
|
}
|
2023-03-19 04:45:46 -04:00
|
|
|
free(methods)
|
2023-03-17 15:48:57 -04:00
|
|
|
}
|