[AltStoreCore] Refactors core AltStore logic into AltStoreCore framework

AltStoreCore will contain all shared AltStore code between AltStore and any app extensions. Initially, it includes all AltStore model logic.
This commit is contained in:
Riley Testut
2020-09-03 16:39:08 -07:00
parent de925e7fea
commit f1a39e1a1f
149 changed files with 3266 additions and 1792 deletions

View File

@@ -0,0 +1,64 @@
//
// JSONDecoder+Properties.swift
// Harmony
//
// Created by Riley Testut on 10/3/18.
// Copyright © 2018 Riley Testut. All rights reserved.
//
import Foundation
import CoreData
public extension CodingUserInfoKey
{
static let managedObjectContext = CodingUserInfoKey(rawValue: "managedObjectContext")!
static let sourceURL = CodingUserInfoKey(rawValue: "sourceURL")!
}
public final class JSONDecoder: Foundation.JSONDecoder
{
@DecoderItem(key: .managedObjectContext)
public var managedObjectContext: NSManagedObjectContext?
@DecoderItem(key: .sourceURL)
public var sourceURL: URL?
}
public extension Decoder
{
var managedObjectContext: NSManagedObjectContext? { self.userInfo[.managedObjectContext] as? NSManagedObjectContext }
var sourceURL: URL? { self.userInfo[.sourceURL] as? URL }
}
@propertyWrapper
public struct DecoderItem<Value>
{
public let key: CodingUserInfoKey
public var wrappedValue: Value? {
get { fatalError("only works on instance properties of classes") }
set { fatalError("only works on instance properties of classes") }
}
public init(key: CodingUserInfoKey)
{
self.key = key
}
public static subscript<OuterSelf: JSONDecoder>(
_enclosingInstance decoder: OuterSelf,
wrapped wrappedKeyPath: ReferenceWritableKeyPath<OuterSelf, Value?>,
storage storageKeyPath: ReferenceWritableKeyPath<OuterSelf, Self>
) -> Value? {
get {
let wrapper = decoder[keyPath: storageKeyPath]
let value = decoder.userInfo[wrapper.key] as? Value
return value
}
set {
let wrapper = decoder[keyPath: storageKeyPath]
decoder.userInfo[wrapper.key] = newValue
}
}
}

View File

@@ -0,0 +1,17 @@
//
// UIApplication+AppExtension.swift
// DeltaCore
//
// Created by Riley Testut on 6/14/18.
// Copyright © 2018 Riley Testut. All rights reserved.
//
import UIKit
public extension UIApplication
{
// Cannot normally use UIApplication.shared from extensions, so we get around this by calling value(forKey:).
class var alt_shared: UIApplication? {
return UIApplication.value(forKey: "sharedApplication") as? UIApplication
}
}

View File

@@ -0,0 +1,43 @@
//
// UIColor+Hex.swift
// AltStore
//
// Created by Riley Testut on 7/15/19.
// Copyright © 2019 Riley Testut. All rights reserved.
//
import UIKit
public extension UIColor
{
// Borrowed from https://stackoverflow.com/a/26341062
var hexString: String {
let components = self.cgColor.components
let r: CGFloat = components?[0] ?? 0.0
let g: CGFloat = components?[1] ?? 0.0
let b: CGFloat = components?[2] ?? 0.0
let hexString = String.init(format: "%02lX%02lX%02lX", lroundf(Float(r * 255)), lroundf(Float(g * 255)), lroundf(Float(b * 255)))
return hexString
}
// Borrowed from https://stackoverflow.com/a/33397427
convenience init?(hexString: String)
{
let hex = hexString.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
var int = UInt32()
Scanner(string: hex).scanHexInt32(&int)
let a, r, g, b: UInt32
switch hex.count {
case 3: // RGB (12-bit)
(a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
case 6: // RGB (24-bit)
(a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
case 8: // ARGB (32-bit)
(a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
default:
return nil
}
self.init(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: CGFloat(a) / 255)
}
}

View File

@@ -0,0 +1,57 @@
//
// UserDefaults+AltStore.swift
// AltStore
//
// Created by Riley Testut on 6/4/19.
// Copyright © 2019 Riley Testut. All rights reserved.
//
import Foundation
import Roxas
public extension UserDefaults
{
@NSManaged var firstLaunch: Date?
@NSManaged var preferredServerID: String?
@NSManaged var isBackgroundRefreshEnabled: Bool
@NSManaged var isDebugModeEnabled: Bool
@NSManaged var presentedLaunchReminderNotification: Bool
@NSManaged var legacySideloadedApps: [String]?
@NSManaged var isLegacyDeactivationSupported: Bool
@NSManaged var activeAppLimitIncludesExtensions: Bool
var activeAppsLimit: Int? {
get {
return self._activeAppsLimit?.intValue
}
set {
if let value = newValue
{
self._activeAppsLimit = NSNumber(value: value)
}
else
{
self._activeAppsLimit = nil
}
}
}
@NSManaged @objc(activeAppsLimit) private var _activeAppsLimit: NSNumber?
func registerDefaults()
{
let ios13_5 = OperatingSystemVersion(majorVersion: 13, minorVersion: 5, patchVersion: 0)
let isLegacyDeactivationSupported = !ProcessInfo.processInfo.isOperatingSystemAtLeast(ios13_5)
let activeAppLimitIncludesExtensions = !ProcessInfo.processInfo.isOperatingSystemAtLeast(ios13_5)
self.register(defaults: [
#keyPath(UserDefaults.isBackgroundRefreshEnabled): true,
#keyPath(UserDefaults.isLegacyDeactivationSupported): isLegacyDeactivationSupported,
#keyPath(UserDefaults.activeAppLimitIncludesExtensions): activeAppLimitIncludesExtensions
])
}
}