Skip to content

Commit

Permalink
support new installation options in API v1.5
Browse files Browse the repository at this point in the history
  • Loading branch information
n3d1117 committed Mar 24, 2022
1 parent 62998e5 commit 81dd1f6
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 60 deletions.
2 changes: 0 additions & 2 deletions appdb/API/API+Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,8 @@ extension API {

Preferences.set(.deviceName, to: data["name"].stringValue)
Preferences.set(.deviceVersion, to: data["ios_version"].stringValue)
Preferences.set(.enableIapPatch, to: data["enable_inapp_patch"].stringValue == "yes")
Preferences.set(.disableRevocationChecks, to: data["disable_protection_checks"].stringValue == "yes")
Preferences.set(.forceDisablePRO, to: data["is_pro_disabled"].stringValue == "yes")
Preferences.set(.enableTrainer, to: data["enable_trainer"].stringValue == "yes")
Preferences.set(.signingIdentityType, to: data["signing_identity_type"].stringValue)
Preferences.set(.optedOutFromEmails, to: data["is_opted_out_from_emails"].stringValue == "yes")

Expand Down
7 changes: 5 additions & 2 deletions appdb/API/API+Install.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ import SwiftyJSON

extension API {

static func install(id: String, type: ItemType, alongsideId: String = "", displayName: String = "", completion:@escaping (_ error: String?) -> Void) {
AF.request(endpoint, parameters: ["action": Actions.install.rawValue, "type": type.rawValue, "id": id, "is_alongside": alongsideId.lowercased(), "display_name": displayName, "lang": languageCode], headers: headersWithCookie)
static func install(id: String, type: ItemType, additionalOptions: [AdditionalInstallationParameters: Any] = [:], completion:@escaping (_ error: String?) -> Void) {
var parameters: [String: Any] = ["action": Actions.install.rawValue, "type": type.rawValue, "id": id, "lang": languageCode]
for (key, value) in additionalOptions { parameters[key.rawValue] = value }

AF.request(endpoint, parameters: parameters, headers: headersWithCookie)
.responseJSON { response in
switch response.result {
case .success(let value):
Expand Down
11 changes: 9 additions & 2 deletions appdb/API/API.swift
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,16 @@ enum ConfigurationParameters: String {
case askForOptions = "params[ask_for_installation_options]"
case clearDevEntity = "params[clear_developer_entity]"
case disableProtectionChecks = "params[disable_protection_checks]"
case enableIapPatch = "params[enable_inapp_patch]"
case forceDisablePRO = "params[is_pro_disabled]"
case enableTrainer = "params[enable_trainer]"
case signingIdentityType = "params[signing_identity_type]"
case optedOutFromEmails = "params[is_opted_out_from_emails]"
}

enum AdditionalInstallationParameters: String {
case alongside = "enable_features[alongside]"
case name = "enable_features[name]"
case inApp = "enable_features[inapp]"
case trainer = "enable_features[trainer]"
case removePlugins = "enable_features[remove_plugins]"
case pushNotifications = "enable_features[push]"
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ class AdditionalInstallOptionsNavController: UINavigationController, AdditionalI

func updateHeight() {
setupConstraints()
UIView.animate(withDuration: 0.2, animations: view.superview!.layoutIfNeeded)
if let sv = view.superview {
UIView.animate(withDuration: 0.2, animations: sv.layoutIfNeeded)
}
}

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
Expand All @@ -59,58 +61,54 @@ class AdditionalInstallOptionsNavController: UINavigationController, AdditionalI
}

class AdditionalInstallOptionsViewController: TableViewController {

weak var heightDelegate: AdditionalInstallOptionsHeightDelegate?

var onCompletion: ((Bool, String, String) -> Void)?
var onCompletion: ((_ patchIap: Bool, _ enableGameTrainer: Bool, _ removePlugins: Bool, _ enablePushNotifications: Bool,
_ duplicateApp: Bool, _ newId: String, _ newName: String) -> Void)?

private var duplicateApp = true
private var newId: String = ""
private var newName: String = ""

var cancelled = true

private let placeholder: String = Global.randomString(length: 4).lowercased()
private let placeholder: String = Global.randomString(length: 5).lowercased()

private let rowHeight: CGFloat = 50
var height: CGFloat {
let navbarHeight: CGFloat = navigationController?.navigationBar.frame.height ?? 0
return navbarHeight + rowHeight * CGFloat(duplicateApp ? 3 : 2)
let navbarHeight: CGFloat = navigationController?.navigationBar.frame.height ?? 44
return navbarHeight + rowHeight * CGFloat(sections.first!.rows.count)
}

lazy var sections: [Static.Section] = [
Section(rows: [
Row(text: "Duplicate app".localized(), accessory: .switchToggle(value: duplicateApp) { [unowned self] newValue in
self.duplicateApp = newValue
self.setInstallButtonEnabled()
self.switchMode()
}, cellClass: SimpleStaticCell.self),
Row(text: "New display name".localized(), cellClass: StaticTextFieldCell.self, context:
["placeholder": "Use Original".localized(), "callback": { [unowned self] (newName: String) in
self.newName = newName
self.setInstallButtonEnabled()
}]
),
Row(text: "Patch in-app Purchases".localized(), cellClass: SwitchCell.self, context: ["valueChange": { new in
Preferences.set(.enableIapPatch, to: new)
}, "value": Preferences.enableIapPatch]),
Row(text: "Enable Game Trainer".localized(), cellClass: SwitchCell.self, context: ["valueChange": { new in
Preferences.set(.enableTrainer, to: new)
}, "value": Preferences.enableTrainer]),
Row(text: "Remove Plugins".localized(), cellClass: SwitchCell.self, context: ["valueChange": { new in
Preferences.set(.removePlugins, to: new)
}, "value": Preferences.removePlugins]),
Row(text: "Enable Push Notifications".localized(), cellClass: SwitchCell.self, context: ["valueChange": { new in
Preferences.set(.enablePushNotifications, to: new)
}, "value": Preferences.enablePushNotifications]),
Row(text: "Duplicate app".localized(), cellClass: SwitchCell.self, context: ["valueChange": { (new: Bool) in
Preferences.set(.duplicateApp, to: new)
self.setInstallButtonEnabled()
}, "value": Preferences.duplicateApp]),
Row(text: "New ID".localized(), cellClass: StaticTextFieldCell.self, context:
["placeholder": placeholder, "callback": { [unowned self] (newId: String) in
self.newId = newId.isEmpty ? self.placeholder : newId
self.setInstallButtonEnabled()
}]
)
])
]

lazy var compactSections: [Static.Section] = [
Section(rows: [
Row(text: "Duplicate app".localized(), accessory: .switchToggle(value: duplicateApp) { [unowned self] newValue in
self.duplicateApp = newValue
self.setInstallButtonEnabled()
self.switchMode()
}, cellClass: SimpleStaticCell.self),
Row(text: "New display name".localized(), cellClass: StaticTextFieldCell.self, context:
["placeholder": "Use Original".localized(), "callback": { [unowned self] (newName: String) in
self.newName = newName
self.setInstallButtonEnabled()
}]
}, "forceLowercase": true, "characterLimit": 5]
)
])
]
Expand All @@ -126,6 +124,9 @@ class AdditionalInstallOptionsViewController: TableViewController {

// Hide last separator
tableView.tableFooterView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 1))
if #available(iOS 15.0, *) {
tableView.sectionHeaderTopPadding = 0
}

tableView.rowHeight = rowHeight
tableView.isScrollEnabled = false
Expand All @@ -138,23 +139,18 @@ class AdditionalInstallOptionsViewController: TableViewController {
dataSource.sections = sections
}

private func switchMode() {
heightDelegate?.updateHeight()
dataSource.sections = duplicateApp ? sections : compactSections
}

@objc private func dismissAnimated() {
cancelled = true
dismiss(animated: true)
}

@objc private func proceedWithInstall() {
onCompletion?(self.duplicateApp, self.newId, self.newName)
onCompletion?(Preferences.enableIapPatch, Preferences.enableTrainer, Preferences.removePlugins, Preferences.enablePushNotifications, Preferences.duplicateApp, self.newId.lowercased(), self.newName)
cancelled = false
dismiss(animated: true)
}

private func setInstallButtonEnabled() {
navigationItem.rightBarButtonItem?.isEnabled = !newId.contains(" ")
navigationItem.rightBarButtonItem?.isEnabled = newId.count == 5 && !newId.contains(" ")
}
}
18 changes: 18 additions & 0 deletions appdb/Startup/Preferences.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ extension Defaults.Keys {
static let enableTrainer = Key<Bool>("enableTrainer", default: false)
static let signingIdentityType = Key<String>("signingIdentityType", default: "auto")
static let optedOutFromEmails = Key<Bool>("optedOutFromEmails", default: false)
static let removePlugins = Key<Bool>("removePlugins", default: false)
static let enablePushNotifications = Key<Bool>("enablePush", default: false)
static let duplicateApp = Key<Bool>("duplicateApp", default: true)
}

// Sensitive data is stored in Keychain
Expand Down Expand Up @@ -160,6 +163,18 @@ enum Preferences {
static var optedOutFromEmails: Bool {
defaults[.optedOutFromEmails]
}

static var removePlugins: Bool {
defaults[.removePlugins]
}

static var enablePushNotifications: Bool {
defaults[.enablePushNotifications]
}

static var duplicateApp: Bool {
defaults[.duplicateApp]
}
}

extension Preferences {
Expand Down Expand Up @@ -209,6 +224,9 @@ extension Preferences {
UserDefaults.standard.removeObject(forKey: Defaults.Keys.enableTrainer.name)
UserDefaults.standard.removeObject(forKey: Defaults.Keys.signingIdentityType.name)
UserDefaults.standard.removeObject(forKey: Defaults.Keys.optedOutFromEmails.name)
UserDefaults.standard.removeObject(forKey: Defaults.Keys.removePlugins.name)
UserDefaults.standard.removeObject(forKey: Defaults.Keys.enablePushNotifications.name)
UserDefaults.standard.removeObject(forKey: Defaults.Keys.duplicateApp.name)
}

// Remove secure keys
Expand Down
19 changes: 11 additions & 8 deletions appdb/Tabs/Downloads/Library/Library+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,8 @@ extension Library {
if Preferences.deviceIsLinked {
setButtonTitle("Requesting...")

func install(alongsideId: String = "", displayName: String = "") {
API.install(id: sender.linkId, type: .myAppstore, alongsideId: alongsideId, displayName: displayName) { [weak self] error in
func install(_ additionalOptions: [AdditionalInstallationParameters: Any] = [:]) {
API.install(id: sender.linkId, type: .myAppstore, additionalOptions: additionalOptions) { [weak self] error in
guard let self = self else { return }

if let error = error {
Expand Down Expand Up @@ -308,12 +308,15 @@ extension Library {
}
}

vc.onCompletion = { (duplicate: Bool, newId: String, newName: String) in
if duplicate {
install(alongsideId: newId, displayName: newName)
} else {
install(displayName: newName)
}
vc.onCompletion = { (patchIap: Bool, enableGameTrainer: Bool, removePlugins: Bool, enablePushNotifications: Bool, duplicateApp: Bool, newId: String, newName: String) in
var additionalOptions: [AdditionalInstallationParameters: Any] = [:]
if patchIap { additionalOptions[.inApp] = 1 }
if enableGameTrainer { additionalOptions[.trainer] = 1 }
if removePlugins { additionalOptions[.removePlugins] = 1 }
if enablePushNotifications { additionalOptions[.pushNotifications] = 1 }
if duplicateApp && !newId.isEmpty { additionalOptions[.alongside] = newId }
if !newName.isEmpty { additionalOptions[.name] = newName }
install(additionalOptions)
}
} else {
install()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ class DetailsDownload: DetailsCell {

host.bottom ~== cracker.top ~- 3
host.leading ~== host.superview!.leading ~+ Global.Size.margin.value
host.width ~<= host.superview!.width * 0.6
host.width ~<= host.superview!.width * 0.65

uploader.leading ~== cracker.leading
uploader.trailing ~== cracker.trailing
Expand Down Expand Up @@ -177,7 +177,7 @@ class DetailsDownloadUnified: DetailsCell {

host.centerY ~== button.centerY ~- 9
host.leading ~== host.superview!.leading ~+ Global.Size.margin.value
host.width ~<= host.superview!.width * 0.6
host.width ~<= host.superview!.width * 0.65

cracker.leading ~== host.leading
cracker.trailing ~== host.trailing
Expand Down
19 changes: 11 additions & 8 deletions appdb/Tabs/Featured/Details/Details.swift
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,8 @@ class Details: LoadingTableView {
if Preferences.deviceIsLinked {
setButtonTitle("Requesting...")

func install(alongsideId: String = "", displayName: String = "") {
API.install(id: sender.linkId, type: self.contentType, alongsideId: alongsideId, displayName: displayName) { [weak self] error in
func install(_ additionalOptions: [AdditionalInstallationParameters: Any] = [:]) {
API.install(id: sender.linkId, type: self.contentType, additionalOptions: additionalOptions) { [weak self] error in
guard let self = self else { return }

if let error = error {
Expand Down Expand Up @@ -333,12 +333,15 @@ class Details: LoadingTableView {
}
}

vc.onCompletion = { (duplicate: Bool, newId: String, newName: String) in
if duplicate {
install(alongsideId: newId, displayName: newName)
} else {
install(displayName: newName)
}
vc.onCompletion = { (patchIap: Bool, enableGameTrainer: Bool, removePlugins: Bool, enablePushNotifications: Bool, duplicateApp: Bool, newId: String, newName: String) in
var additionalOptions: [AdditionalInstallationParameters: Any] = [:]
if patchIap { additionalOptions[.inApp] = 1 }
if enableGameTrainer { additionalOptions[.trainer] = 1 }
if removePlugins { additionalOptions[.removePlugins] = 1 }
if enablePushNotifications { additionalOptions[.pushNotifications] = 1 }
if duplicateApp && !newId.isEmpty { additionalOptions[.alongside] = newId }
if !newName.isEmpty { additionalOptions[.name] = newName }
install(additionalOptions)
}
} else {
install()
Expand Down
20 changes: 19 additions & 1 deletion appdb/Tabs/Settings/Settings+StaticCells.swift
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,8 @@ class StaticTextFieldCell: SimpleStaticCell, UITextFieldDelegate {
var textfieldDidEndEditing: ((String) -> Void)?

var textField: UITextField!
var characterLimit: Int?
var forceLowercase = false

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
Expand Down Expand Up @@ -309,11 +311,27 @@ class StaticTextFieldCell: SimpleStaticCell, UITextFieldDelegate {
if let callback = row.context?["callback"] as? (String) -> Void {
self.textfieldDidEndEditing = callback
}
if let limit = row.context?["characterLimit"] as? Int {
characterLimit = limit
}
if let lower = row.context?["forceLowercase"] as? Bool {
forceLowercase = lower
}
}

@objc func textFieldDidChange(_ textField: UITextField) {
guard let text = textField.text else { return }
textfieldDidEndEditing?(text)
var adjustedText = text

if forceLowercase {
adjustedText = adjustedText.lowercased()
}
if let limit = characterLimit {
adjustedText = String(adjustedText.prefix(limit))
}

textField.text = adjustedText
textfieldDidEndEditing?(adjustedText)
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
Expand Down

0 comments on commit 81dd1f6

Please sign in to comment.