mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-17 10:43:30 +01:00
[AltStore] Refreshes individual apps
This commit is contained in:
@@ -180,11 +180,48 @@ extension AppManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func refreshAllApps(completionHandler: @escaping (Result<[String: Result<Void, Error>], AppError>) -> Void)
|
func refresh(_ app: InstalledApp, completionHandler: @escaping (Result<InstalledApp, Error>) -> Void)
|
||||||
|
{
|
||||||
|
self.refresh([app]) { (result) in
|
||||||
|
do
|
||||||
|
{
|
||||||
|
guard let (_, result) = try result.get().first else { throw AppError.unknown }
|
||||||
|
completionHandler(result)
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
completionHandler(.failure(error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func refreshAllApps(completionHandler: @escaping (Result<[String: Result<InstalledApp, Error>], AppError>) -> Void)
|
||||||
|
{
|
||||||
|
DatabaseManager.shared.persistentContainer.performBackgroundTask { (context) in
|
||||||
|
do
|
||||||
|
{
|
||||||
|
let fetchRequest = InstalledApp.fetchRequest() as NSFetchRequest<InstalledApp>
|
||||||
|
fetchRequest.relationshipKeyPathsForPrefetching = [#keyPath(InstalledApp.app)]
|
||||||
|
|
||||||
|
let installedApps = try context.fetch(fetchRequest)
|
||||||
|
self.refresh(installedApps) { (result) in
|
||||||
|
context.perform { // keep context alive
|
||||||
|
completionHandler(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
completionHandler(.failure(.prepare(error)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func refresh<T: Collection>(_ installedApps: T, completionHandler: @escaping (Result<[String: Result<InstalledApp, Error>], AppError>) -> Void) where T.Element == InstalledApp
|
||||||
{
|
{
|
||||||
let backgroundTaskID = RSTBeginBackgroundTask("com.rileytestut.AltStore.RefreshApps")
|
let backgroundTaskID = RSTBeginBackgroundTask("com.rileytestut.AltStore.RefreshApps")
|
||||||
|
|
||||||
func finish(_ result: Result<[String: Result<Void, Error>], AppError>)
|
func finish(_ result: Result<[String: Result<InstalledApp, Error>], AppError>)
|
||||||
{
|
{
|
||||||
completionHandler(result)
|
completionHandler(result)
|
||||||
|
|
||||||
@@ -206,40 +243,30 @@ extension AppManager
|
|||||||
case .success(let certificate):
|
case .success(let certificate):
|
||||||
let signer = ALTSigner(team: team, certificate: certificate)
|
let signer = ALTSigner(team: team, certificate: certificate)
|
||||||
|
|
||||||
DatabaseManager.shared.persistentContainer.performBackgroundTask { (context) in
|
let dispatchGroup = DispatchGroup()
|
||||||
do
|
var results = [String: Result<InstalledApp, Error>]()
|
||||||
{
|
|
||||||
let fetchRequest = InstalledApp.fetchRequest() as NSFetchRequest<InstalledApp>
|
|
||||||
fetchRequest.relationshipKeyPathsForPrefetching = [#keyPath(InstalledApp.app)]
|
|
||||||
|
|
||||||
let installedApps = try context.fetch(fetchRequest)
|
let context = DatabaseManager.shared.persistentContainer.newBackgroundContext()
|
||||||
|
|
||||||
let dispatchGroup = DispatchGroup()
|
for app in installedApps
|
||||||
var results = [String: Result<Void, Error>]()
|
{
|
||||||
|
dispatchGroup.enter()
|
||||||
|
|
||||||
for app in installedApps
|
app.managedObjectContext?.perform {
|
||||||
{
|
let bundleIdentifier = app.bundleIdentifier
|
||||||
dispatchGroup.enter()
|
print("Refreshing App:", bundleIdentifier)
|
||||||
|
|
||||||
let bundleIdentifier = app.bundleIdentifier
|
self.refresh(app, signer: signer, context: context) { (result) in
|
||||||
print("Refreshing App:", bundleIdentifier)
|
print("Refreshed App: \(bundleIdentifier).", result)
|
||||||
|
results[bundleIdentifier] = result
|
||||||
self.refresh(app, signer: signer) { (result) in
|
dispatchGroup.leave()
|
||||||
print("Refreshed App: \(bundleIdentifier).", result)
|
|
||||||
results[bundleIdentifier] = result
|
|
||||||
dispatchGroup.leave()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatchGroup.notify(queue: .global()) {
|
|
||||||
context.perform { // Keep context alive
|
|
||||||
finish(.success(results))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
}
|
||||||
{
|
|
||||||
finish(.failure(.prepare(error)))
|
dispatchGroup.notify(queue: .global()) {
|
||||||
|
context.perform {
|
||||||
|
finish(.success(results))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -643,7 +670,7 @@ private extension AppManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func refresh(_ installedApp: InstalledApp, signer: ALTSigner, completionHandler: @escaping (Result<Void, Error>) -> Void)
|
func refresh(_ installedApp: InstalledApp, signer: ALTSigner, context: NSManagedObjectContext, completionHandler: @escaping (Result<InstalledApp, Error>) -> Void)
|
||||||
{
|
{
|
||||||
self.prepareProvisioningProfile(for: installedApp.app, team: signer.team) { (result) in
|
self.prepareProvisioningProfile(for: installedApp.app, team: signer.team) { (result) in
|
||||||
switch result
|
switch result
|
||||||
@@ -660,7 +687,20 @@ private extension AppManager
|
|||||||
|
|
||||||
// Send app to server
|
// Send app to server
|
||||||
installedApp.managedObjectContext?.perform {
|
installedApp.managedObjectContext?.perform {
|
||||||
self.sendAppToServer(fileURL: resignedURL, identifier: installedApp.bundleIdentifier, completionHandler: completionHandler)
|
self.sendAppToServer(fileURL: resignedURL, identifier: installedApp.bundleIdentifier) { (result) in
|
||||||
|
context.perform {
|
||||||
|
switch result
|
||||||
|
{
|
||||||
|
case .success:
|
||||||
|
let installedApp = context.object(with: installedApp.objectID) as! InstalledApp
|
||||||
|
installedApp.expirationDate = profile.expirationDate
|
||||||
|
completionHandler(.success(installedApp))
|
||||||
|
|
||||||
|
case .failure(let error):
|
||||||
|
completionHandler(.failure(error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class MyAppsViewController: UITableViewController
|
|||||||
private lazy var dateFormatter: DateFormatter = {
|
private lazy var dateFormatter: DateFormatter = {
|
||||||
let dateFormatter = DateFormatter()
|
let dateFormatter = DateFormatter()
|
||||||
dateFormatter.dateStyle = .short
|
dateFormatter.dateStyle = .short
|
||||||
dateFormatter.timeStyle = .none
|
dateFormatter.timeStyle = .short
|
||||||
return dateFormatter
|
return dateFormatter
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -73,24 +73,61 @@ private extension MyAppsViewController
|
|||||||
|
|
||||||
extension MyAppsViewController
|
extension MyAppsViewController
|
||||||
{
|
{
|
||||||
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath)
|
override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]?
|
||||||
{
|
{
|
||||||
guard editingStyle == .delete else { return }
|
let deleteAction = UITableViewRowAction(style: .destructive, title: "Delete") { (action, indexPath) in
|
||||||
|
let installedApp = self.dataSource.item(at: indexPath)
|
||||||
|
|
||||||
let installedApp = self.dataSource.item(at: indexPath)
|
DatabaseManager.shared.persistentContainer.performBackgroundTask { (context) in
|
||||||
|
let installedApp = context.object(with: installedApp.objectID) as! InstalledApp
|
||||||
|
context.delete(installedApp)
|
||||||
|
|
||||||
DatabaseManager.shared.persistentContainer.performBackgroundTask { (context) in
|
do
|
||||||
let installedApp = context.object(with: installedApp.objectID) as! InstalledApp
|
{
|
||||||
context.delete(installedApp)
|
try context.save()
|
||||||
|
}
|
||||||
do
|
catch
|
||||||
{
|
{
|
||||||
try context.save()
|
print("Failed to delete installed app.", error)
|
||||||
}
|
}
|
||||||
catch
|
|
||||||
{
|
|
||||||
print("Failed to delete installed app.", error)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let refreshAction = UITableViewRowAction(style: .normal, title: "Refresh") { (action, indexPath) in
|
||||||
|
let installedApp = self.dataSource.item(at: indexPath)
|
||||||
|
|
||||||
|
let toastView = RSTToastView(text: "Refreshing...", detailText: nil)
|
||||||
|
toastView.tintColor = .altPurple
|
||||||
|
toastView.activityIndicatorView.startAnimating()
|
||||||
|
toastView.show(in: self.navigationController?.view ?? self.view)
|
||||||
|
|
||||||
|
AppManager.shared.refresh(installedApp) { (result) in
|
||||||
|
do
|
||||||
|
{
|
||||||
|
let app = try result.get()
|
||||||
|
try app.managedObjectContext?.save()
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
let toastView = RSTToastView(text: "Refreshed \(installedApp.app.name)!", detailText: nil)
|
||||||
|
toastView.tintColor = .altPurple
|
||||||
|
toastView.show(in: self.navigationController?.view ?? self.view, duration: 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
let toastView = RSTToastView(text: "Failed to refresh \(installedApp.app.name)", detailText: error.localizedDescription)
|
||||||
|
toastView.tintColor = .altPurple
|
||||||
|
toastView.show(in: self.navigationController?.view ?? self.view, duration: 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [deleteAction, refreshAction]
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user