Skip to content

Commit

Permalink
support ipa cache
Browse files Browse the repository at this point in the history
  • Loading branch information
n3d1117 committed Jan 5, 2022
1 parent 104acc6 commit e4f2f29
Show file tree
Hide file tree
Showing 6 changed files with 247 additions and 0 deletions.
20 changes: 20 additions & 0 deletions appdb.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@
817610F621515A3200602FF2 /* API+DeviceStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 817610EC21515A3200602FF2 /* API+DeviceStatus.swift */; };
817610F721515A3200602FF2 /* API+Links.swift in Sources */ = {isa = PBXBuildFile; fileRef = 817610ED21515A3200602FF2 /* API+Links.swift */; };
817610F821515A3200602FF2 /* API+News.swift in Sources */ = {isa = PBXBuildFile; fileRef = 817610EE21515A3200602FF2 /* API+News.swift */; };
8176EFA92785E5B5004545DA /* IPACache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8176EFA82785E5B5004545DA /* IPACache.swift */; };
8176EFAB2785E5F3004545DA /* API+IPACache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8176EFAA2785E5F3004545DA /* API+IPACache.swift */; };
8176EFAD2785E61F004545DA /* IPACacheStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8176EFAC2785E61F004545DA /* IPACacheStatus.swift */; };
8177B60C1F81992F0014A944 /* Details+FullScreenshots.swift in Sources */ = {isa = PBXBuildFile; fileRef = 818CB5D41E787AB400A69213 /* Details+FullScreenshots.swift */; };
817A40E11E5E27EB003FD6F1 /* Details+Screenshots.swift in Sources */ = {isa = PBXBuildFile; fileRef = 817A40E01E5E27EB003FD6F1 /* Details+Screenshots.swift */; };
817A40E41E5E2FB2003FD6F1 /* SnappableFlowLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 817A40E31E5E2FB2003FD6F1 /* SnappableFlowLayout.swift */; };
Expand Down Expand Up @@ -443,6 +446,9 @@
817610EC21515A3200602FF2 /* API+DeviceStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "API+DeviceStatus.swift"; sourceTree = "<group>"; };
817610ED21515A3200602FF2 /* API+Links.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "API+Links.swift"; sourceTree = "<group>"; };
817610EE21515A3200602FF2 /* API+News.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "API+News.swift"; sourceTree = "<group>"; };
8176EFA82785E5B5004545DA /* IPACache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPACache.swift; sourceTree = "<group>"; };
8176EFAA2785E5F3004545DA /* API+IPACache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "API+IPACache.swift"; sourceTree = "<group>"; };
8176EFAC2785E61F004545DA /* IPACacheStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPACacheStatus.swift; sourceTree = "<group>"; };
817962D722A43F65005BB1F0 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
817A40E01E5E27EB003FD6F1 /* Details+Screenshots.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = "Details+Screenshots.swift"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
817A40E31E5E2FB2003FD6F1 /* SnappableFlowLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SnappableFlowLayout.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -969,6 +975,14 @@
path = Bulletins;
sourceTree = "<group>";
};
8176EFA72785E5A9004545DA /* IPA Cache */ = {
isa = PBXGroup;
children = (
8176EFA82785E5B5004545DA /* IPACache.swift */,
);
path = "IPA Cache";
sourceTree = "<group>";
};
81795CD61E60885600805B3A /* • ElasticLabel */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -1127,6 +1141,7 @@
818763BD2676299800049F58 /* Device Chooser */,
814FF02C207B9B5F0049DF9A /* Device Link */,
810C71FC20ACDA9800D6310E /* Device Status */,
8176EFA72785E5A9004545DA /* IPA Cache */,
819EC27C20A76EB6007138CF /* Theme Chooser */,
81DD29D52288CD1A00412BE6 /* Language Chooser */,
81F0C0A723535B4000604A10 /* Advanced Options */,
Expand Down Expand Up @@ -1339,6 +1354,7 @@
817610EC21515A3200602FF2 /* API+DeviceStatus.swift */,
817610E721515A3100602FF2 /* API+Genres.swift */,
81207DB0215EC6AC00296D20 /* API+Install.swift */,
8176EFAA2785E5F3004545DA /* API+IPACache.swift */,
817610ED21515A3200602FF2 /* API+Links.swift */,
81FC8B4022735E5E003788F3 /* API+MyAppstore.swift */,
817610EE21515A3200602FF2 /* API+News.swift */,
Expand Down Expand Up @@ -1439,6 +1455,7 @@
811BEE262151538600F1F56A /* SingleNews.swift */,
814F4FBA2196FA35005A8111 /* UpdateableApp.swift */,
818763C026762B1F00049F58 /* LinkedDevice.swift */,
8176EFAC2785E61F004545DA /* IPACacheStatus.swift */,
);
path = Models;
sourceTree = "<group>";
Expand Down Expand Up @@ -1819,6 +1836,7 @@
buildActionMask = 2147483647;
files = (
81190B43216A2FC800C81BEB /* TwoPortraitScreenshotsSearchCell+Stars.swift in Sources */,
8176EFAD2785E61F004545DA /* IPACacheStatus.swift in Sources */,
819E69941F8FCD1000C4608F /* LandscapeScreenshotSearchCell.swift in Sources */,
81EC00651DAD7514009EEFFA /* Featured.swift in Sources */,
817610F421515A3200602FF2 /* API+DeviceLink.swift in Sources */,
Expand Down Expand Up @@ -1969,6 +1987,7 @@
81AF3532215115B200A798D7 /* RoundedButton.swift in Sources */,
815016A32312DAFE00E06E1E /* NewWishes.swift in Sources */,
818763BF267629B800049F58 /* DeviceChooser.swift in Sources */,
8176EFA92785E5B5004545DA /* IPACache.swift in Sources */,
81EC00681DAD76EC009EEFFA /* Extensions.swift in Sources */,
819E69891F8E8C2700C4608F /* SearchCell.swift in Sources */,
818979412284853A00EC87B2 /* DownloadingCell.swift in Sources */,
Expand Down Expand Up @@ -1998,6 +2017,7 @@
817610F321515A3200602FF2 /* API+Search.swift in Sources */,
81004A12209E2545002414F1 /* SystemStatus.swift in Sources */,
816CEEDB1DBD00E5002CFF6E /* CategoryCell.swift in Sources */,
8176EFAB2785E5F3004545DA /* API+IPACache.swift in Sources */,
816CEED91DBCE8A2002CFF6E /* Categories.swift in Sources */,
818A55A920584D9100162E51 /* LNZSnapToCenterCollectionViewLayout.swift in Sources */,
81897943228485AA00EC87B2 /* LocalIPADownloadUtil.swift in Sources */,
Expand Down
57 changes: 57 additions & 0 deletions appdb/API/API+IPACache.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//
// API+IPACache.swift
// appdb
//
// Created by ned on 05/01/22.
// Copyright © 2022 ned. All rights reserved.
//

import Alamofire
import SwiftyJSON

extension API {

static func getIPACacheStatus(success:@escaping (_ status: IPACacheStatus) -> Void, fail:@escaping (_ error: NSError) -> Void) {

AF.request(endpoint, parameters: ["action": Actions.getIpaCacheStatus.rawValue], headers: headersWithCookie)
.responseObject(keyPath: "data") { (response: AFDataResponse<IPACacheStatus>) in
switch response.result {
case .success(let result):
success(result)
case .failure(let error):
fail(error as NSError)
}
}
}

static func reinstallEverything(success:@escaping () -> Void, fail:@escaping (_ error: String) -> Void) {
AF.request(endpoint, parameters: ["action": Actions.installFromCache.rawValue], headers: headersWithCookie)
.responseJSON { response in
switch response.result {
case .success(let value):
let json = JSON(value)
if !json["success"].boolValue {
fail(json["errors"][0].stringValue)
} else {
success()
}
case .failure(let error):
fail(error.localizedDescription)
}
}
}

static func clearIpaCache(success:@escaping () -> Void) {
AF.request(endpoint, parameters: ["action": Actions.clearIpaCache.rawValue], headers: headersWithCookie)
.response { _ in
success()
}
}

static func revalidateIpaCache(success:@escaping () -> Void) {
AF.request(endpoint, parameters: ["action": Actions.revalidateIpaCache.rawValue], headers: headersWithCookie)
.response { _ in
success()
}
}
}
5 changes: 5 additions & 0 deletions appdb/API/API.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ enum Actions: String {
case getAppdbAppsBundleIds = "get_appdb_apps_bundle_ids"
case processRedirect = "process_redirect"
case getAllDevices = "get_all_devices"
case getIpaCacheStatus = "get_ipa_cache_status"
case installFromCache = "install_from_cache"
case clearIpaCache = "clear_ipa_cache"
case revalidateIpaCache = "ensure_ipa_cache"
case transferIpaCache = "transfer_ipa_cache"
}

enum ConfigurationParameters: String {
Expand Down
24 changes: 24 additions & 0 deletions appdb/Models/IPACacheStatus.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// IPACacheStatus.swift
// appdb
//
// Created by ned on 05/01/22.
// Copyright © 2022 ned. All rights reserved.
//

import ObjectMapper

struct IPACacheStatus: Mappable {

init?(map: Map) { }

var sizeHr: String = ""
var inUpdate = false
var updatedAt: String = ""

mutating func mapping(map: Map) {
sizeHr <- map["size_hr"]
inUpdate <- map["in_update"]
updatedAt <- map["updated_at"]
}
}
137 changes: 137 additions & 0 deletions appdb/Tabs/Settings/IPA Cache/IPACache.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
//
// IPACache.swift
// appdb
//
// Created by ned on 05/01/22.
// Copyright © 2022 ned. All rights reserved.
//

import UIKit

class IPACache: LoadingTableView {

var status: IPACacheStatus? {
didSet {
self.tableView.spr_endRefreshing()
self.state = .done
}
}

convenience init() {
if #available(iOS 13.0, *) {
self.init(style: .insetGrouped)
} else {
self.init(style: .grouped)
}
}

override func viewDidLoad() {
super.viewDidLoad()

title = "IPA Cache".localized()

tableView.register(SimpleStaticCell.self, forCellReuseIdentifier: "cell")
tableView.estimatedRowHeight = 50

tableView.theme_separatorColor = Color.borderColor
tableView.theme_backgroundColor = Color.tableViewBackgroundColor
view.theme_backgroundColor = Color.tableViewBackgroundColor

animated = false
showsErrorButton = false
showsSpinner = false

// Hide last separator
tableView.tableFooterView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 1))

if Global.isIpad {
// Add 'Dismiss' button for iPad
let dismissButton = UIBarButtonItem(title: "Dismiss".localized(), style: .done, target: self, action: #selector(self.dismissAnimated))
self.navigationItem.rightBarButtonItems = [dismissButton]
}

// Refresh action
tableView.spr_setIndicatorHeader { [weak self] in
self?.fetchStatus()
}

tableView.spr_beginRefreshing()
}

private func fetchStatus() {
API.getIPACacheStatus { [weak self] status in
guard let self = self else { return }
self.status = status
} fail: { [weak self] error in
guard let self = self else { return }
self.status = nil
self.showErrorMessage(text: "Cannot connect".localized(), secondaryText: error.localizedDescription, animated: false)
}
}

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

override func numberOfSections(in tableView: UITableView) -> Int {
status == nil ? 0 : 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
status == nil ? 0 : 5
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? SimpleStaticCell, let status = status {
switch indexPath.row {
case 0:
cell.textLabel?.text = "Size".localized()
cell.detailTextLabel?.text = status.sizeHr
cell.selectionStyle = .none
case 1:
cell.textLabel?.text = "In Update".localized()
cell.detailTextLabel?.text = status.inUpdate ? "Yes".localized() : "No".localized()
cell.selectionStyle = .none
case 2:
cell.textLabel?.text = "Reinstall everything".localized()
cell.textLabel?.theme_textColor = Color.mainTint
cell.selectionStyle = .default
case 3:
cell.textLabel?.text = "Clear IPA cache".localized()
cell.textLabel?.theme_textColor = Color.mainTint
cell.selectionStyle = .default
case 4:
cell.textLabel?.text = "Re-validate IPA cache".localized()
cell.textLabel?.theme_textColor = Color.mainTint
cell.selectionStyle = .default
default: break
}
return cell
}
return UITableViewCell()
}

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
status == nil ? nil : status?.updatedAt
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
switch indexPath.row {
case 2:
API.reinstallEverything(success: {
Messages.shared.showSuccess(message: "Success".localized(), context: .viewController(self))
}, fail: { error in
Messages.shared.showError(message: error.prettified, context: .viewController(self))
})
case 3:
API.clearIpaCache {
Messages.shared.showSuccess(message: "Success".localized(), context: .viewController(self))
}
case 4:
API.revalidateIpaCache {
Messages.shared.showSuccess(message: "Success".localized(), context: .viewController(self))
}
default:
break
}
}
}
4 changes: 4 additions & 0 deletions appdb/Tabs/Settings/Settings+Sections.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ extension Settings {
API.setConfiguration(params: [.askForOptions: newValue ? "yes" : "no"], success: {}, fail: { _ in })
}, cellClass: SimpleStaticCell.self),

Row(text: "IPA Cache".localized(), selection: { [unowned self] _ in
self.push(IPACache())
}, accessory: .disclosureIndicator, cellClass: SimpleStaticCell.self),

Row(text: "Advanced Options".localized(), selection: { [unowned self] _ in
self.push(AdvancedOptions())
}, accessory: .disclosureIndicator, cellClass: SimpleStaticCell.self)
Expand Down

0 comments on commit e4f2f29

Please sign in to comment.