mirror of https://github.com/opa334/TrollStore.git
1.1
This commit is contained in:
parent
690545931c
commit
b67e3aa9d1
|
@ -1,6 +1,6 @@
|
||||||
Package: com.opa334.trollstoreroothelper
|
Package: com.opa334.trollstoreroothelper
|
||||||
Name: trollstoreroothelper
|
Name: trollstoreroothelper
|
||||||
Version: 1.0.10
|
Version: 1.1
|
||||||
Architecture: iphoneos-arm
|
Architecture: iphoneos-arm
|
||||||
Description: An awesome tool of some sort!!
|
Description: An awesome tool of some sort!!
|
||||||
Maintainer: opa334
|
Maintainer: opa334
|
||||||
|
|
|
@ -730,6 +730,11 @@ int installApp(NSString* appPath, BOOL sign, BOOL force)
|
||||||
// Wipe old version if needed
|
// Wipe old version if needed
|
||||||
if(existed)
|
if(existed)
|
||||||
{
|
{
|
||||||
|
if(![appId isEqualToString:@"com.opa334.TrollStore"])
|
||||||
|
{
|
||||||
|
BKSTerminateApplicationForReasonAndReportWithDescription(appId, 5, false, @"TrollStore - App updated");
|
||||||
|
}
|
||||||
|
|
||||||
NSLog(@"[installApp] found existing TrollStore app, cleaning directory");
|
NSLog(@"[installApp] found existing TrollStore app, cleaning directory");
|
||||||
NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:appContainer.url includingPropertiesForKeys:nil options:0 errorHandler:nil];
|
NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:appContainer.url includingPropertiesForKeys:nil options:0 errorHandler:nil];
|
||||||
NSURL* fileURL;
|
NSURL* fileURL;
|
||||||
|
@ -738,7 +743,7 @@ int installApp(NSString* appPath, BOOL sign, BOOL force)
|
||||||
// do not under any circumstance delete this file as it makes iOS loose the app registration
|
// do not under any circumstance delete this file as it makes iOS loose the app registration
|
||||||
if([fileURL.lastPathComponent isEqualToString:@".com.apple.mobile_container_manager.metadata.plist"] || [fileURL.lastPathComponent isEqualToString:@"_TrollStore"])
|
if([fileURL.lastPathComponent isEqualToString:@".com.apple.mobile_container_manager.metadata.plist"] || [fileURL.lastPathComponent isEqualToString:@"_TrollStore"])
|
||||||
{
|
{
|
||||||
NSLog(@"[installApp] skip removal of %@", fileURL);
|
NSLog(@"[installApp] skipping removal of %@", fileURL);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -767,6 +772,8 @@ int installApp(NSString* appPath, BOOL sign, BOOL force)
|
||||||
|
|
||||||
int uninstallApp(NSString* appPath, NSString* appId)
|
int uninstallApp(NSString* appPath, NSString* appId)
|
||||||
{
|
{
|
||||||
|
BKSTerminateApplicationForReasonAndReportWithDescription(appId, 5, false, @"TrollStore - App uninstalled");
|
||||||
|
|
||||||
LSApplicationProxy* appProxy = [LSApplicationProxy applicationProxyForIdentifier:appId];
|
LSApplicationProxy* appProxy = [LSApplicationProxy applicationProxyForIdentifier:appId];
|
||||||
MCMContainer *appContainer = [objc_getClass("MCMAppDataContainer") containerWithIdentifier:appId createIfNecessary:NO existed:nil error:nil];
|
MCMContainer *appContainer = [objc_getClass("MCMAppDataContainer") containerWithIdentifier:appId createIfNecessary:NO existed:nil error:nil];
|
||||||
NSString *containerPath = [appContainer url].path;
|
NSString *containerPath = [appContainer url].path;
|
||||||
|
@ -1156,6 +1163,14 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||||
} else if([cmd isEqualToString:@"uninstall-persistence-helper"])
|
} else if([cmd isEqualToString:@"uninstall-persistence-helper"])
|
||||||
{
|
{
|
||||||
uninstallPersistenceHelper();
|
uninstallPersistenceHelper();
|
||||||
|
} else if([cmd isEqualToString:@"dash"])
|
||||||
|
{
|
||||||
|
LSApplicationProxy* appProxy = findPersistenceHelperApp();
|
||||||
|
if(appProxy)
|
||||||
|
{
|
||||||
|
NSString* executablePath = appProxy.canonicalExecutablePath;
|
||||||
|
registerPath((char*)executablePath.UTF8String, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NSLog(@"returning %d", ret);
|
NSLog(@"returning %d", ret);
|
||||||
|
|
|
@ -127,7 +127,6 @@ void registerPath(char* cPath, int unregister)
|
||||||
// Misc
|
// Misc
|
||||||
|
|
||||||
dictToRegister[@"ApplicationType"] = @"System";
|
dictToRegister[@"ApplicationType"] = @"System";
|
||||||
dictToRegister[@"BundleNameIsLocalized"] = @1;
|
|
||||||
dictToRegister[@"CFBundleIdentifier"] = appBundleID;
|
dictToRegister[@"CFBundleIdentifier"] = appBundleID;
|
||||||
dictToRegister[@"CodeInfoIdentifier"] = appBundleID;
|
dictToRegister[@"CodeInfoIdentifier"] = appBundleID;
|
||||||
dictToRegister[@"CompatibilityState"] = @0;
|
dictToRegister[@"CompatibilityState"] = @0;
|
||||||
|
@ -144,6 +143,10 @@ void registerPath(char* cPath, int unregister)
|
||||||
dictToRegister[@"SignerIdentity"] = @"Apple iPhone OS Application Signing";
|
dictToRegister[@"SignerIdentity"] = @"Apple iPhone OS Application Signing";
|
||||||
dictToRegister[@"IsAdHocSigned"] = @YES;
|
dictToRegister[@"IsAdHocSigned"] = @YES;
|
||||||
dictToRegister[@"LSInstallType"] = @1;
|
dictToRegister[@"LSInstallType"] = @1;
|
||||||
|
dictToRegister[@"HasMIDBasedSINF"] = @0;
|
||||||
|
dictToRegister[@"MissingSINF"] = @0;
|
||||||
|
dictToRegister[@"FamilyID"] = @0;
|
||||||
|
dictToRegister[@"IsOnDemandInstallCapable"] = @0;
|
||||||
|
|
||||||
NSString* teamIdentifier = constructTeamIdentifierForEntitlements(entitlements);
|
NSString* teamIdentifier = constructTeamIdentifierForEntitlements(entitlements);
|
||||||
if(teamIdentifier) dictToRegister[@"TeamIdentifier"] = teamIdentifier;
|
if(teamIdentifier) dictToRegister[@"TeamIdentifier"] = teamIdentifier;
|
||||||
|
@ -199,7 +202,6 @@ void registerPath(char* cPath, int unregister)
|
||||||
// Misc
|
// Misc
|
||||||
|
|
||||||
pluginDict[@"ApplicationType"] = @"PluginKitPlugin";
|
pluginDict[@"ApplicationType"] = @"PluginKitPlugin";
|
||||||
pluginDict[@"BundleNameIsLocalized"] = @1;
|
|
||||||
pluginDict[@"CFBundleIdentifier"] = pluginBundleID;
|
pluginDict[@"CFBundleIdentifier"] = pluginBundleID;
|
||||||
pluginDict[@"CodeInfoIdentifier"] = pluginBundleID;
|
pluginDict[@"CodeInfoIdentifier"] = pluginBundleID;
|
||||||
pluginDict[@"CompatibilityState"] = @0;
|
pluginDict[@"CompatibilityState"] = @0;
|
||||||
|
|
|
@ -5,7 +5,7 @@ include $(THEOS)/makefiles/common.mk
|
||||||
|
|
||||||
APPLICATION_NAME = TrollStorePersistenceHelper
|
APPLICATION_NAME = TrollStorePersistenceHelper
|
||||||
|
|
||||||
TrollStorePersistenceHelper_FILES = $(wildcard *.m) ../Helper/Shared.m ../Store/TSUtil.m
|
TrollStorePersistenceHelper_FILES = $(wildcard *.m) ../Helper/Shared.m ../Store/TSUtil.m ../Store/TSListControllerShared.m
|
||||||
TrollStorePersistenceHelper_FRAMEWORKS = UIKit CoreGraphics CoreServices
|
TrollStorePersistenceHelper_FRAMEWORKS = UIKit CoreGraphics CoreServices
|
||||||
TrollStorePersistenceHelper_PRIVATE_FRAMEWORKS = Preferences
|
TrollStorePersistenceHelper_PRIVATE_FRAMEWORKS = Preferences
|
||||||
TrollStorePersistenceHelper_CFLAGS = -fobjc-arc
|
TrollStorePersistenceHelper_CFLAGS = -fobjc-arc
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
<string>iPhoneOS</string>
|
<string>iPhoneOS</string>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.0.10</string>
|
<string>1.1</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>UIDeviceFamily</key>
|
<key>UIDeviceFamily</key>
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
#import <UIKit/UIKit.h>
|
#import "../Store/TSListControllerShared.h"
|
||||||
#import <Preferences/PSListController.h>
|
|
||||||
#import <Preferences/PSSpecifier.h>
|
|
||||||
|
|
||||||
@interface TSPHRootViewController : PSListController
|
@interface TSPHRootViewController : TSListControllerShared
|
||||||
{
|
{
|
||||||
UIAlertController* _activityController;
|
NSString* _newerVersion;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -4,38 +4,29 @@
|
||||||
|
|
||||||
@implementation TSPHRootViewController
|
@implementation TSPHRootViewController
|
||||||
|
|
||||||
- (void)loadView
|
- (BOOL)isTrollStore
|
||||||
{
|
{
|
||||||
[super loadView];
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewDidLoad
|
||||||
|
{
|
||||||
|
[super viewDidLoad];
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadSpecifiers) name:UIApplicationWillEnterForegroundNotification object:nil];
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadSpecifiers) name:UIApplicationWillEnterForegroundNotification object:nil];
|
||||||
}
|
|
||||||
|
|
||||||
- (void)startActivity:(NSString*)activity
|
fetchLatestTrollStoreVersion(^(NSString* latestVersion)
|
||||||
{
|
|
||||||
if(_activityController) return;
|
|
||||||
|
|
||||||
_activityController = [UIAlertController alertControllerWithTitle:activity message:@"" preferredStyle:UIAlertControllerStyleAlert];
|
|
||||||
UIActivityIndicatorView* activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(5,5,50,50)];
|
|
||||||
activityIndicator.hidesWhenStopped = YES;
|
|
||||||
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleMedium;
|
|
||||||
[activityIndicator startAnimating];
|
|
||||||
[_activityController.view addSubview:activityIndicator];
|
|
||||||
|
|
||||||
[self presentViewController:_activityController animated:YES completion:nil];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)stopActivityWithCompletion:(void (^)(void))completion
|
|
||||||
{
|
|
||||||
if(!_activityController) return;
|
|
||||||
|
|
||||||
[_activityController dismissViewControllerAnimated:YES completion:^
|
|
||||||
{
|
{
|
||||||
_activityController = nil;
|
NSString* currentVersion = [self getTrollStoreVersion];
|
||||||
if(completion)
|
NSComparisonResult result = [currentVersion compare:latestVersion options:NSNumericSearch];
|
||||||
|
if(result == NSOrderedAscending)
|
||||||
{
|
{
|
||||||
completion();
|
_newerVersion = latestVersion;
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^
|
||||||
|
{
|
||||||
|
[self reloadSpecifiers];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}];
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSMutableArray*)specifiers
|
- (NSMutableArray*)specifiers
|
||||||
|
@ -60,10 +51,28 @@
|
||||||
|
|
||||||
[_specifiers addObject:infoSpecifier];
|
[_specifiers addObject:infoSpecifier];
|
||||||
|
|
||||||
|
BOOL isInstalled = trollStoreAppPath();
|
||||||
|
|
||||||
|
if(_newerVersion && isInstalled)
|
||||||
|
{
|
||||||
|
// Update TrollStore
|
||||||
|
PSSpecifier* updateTrollStoreSpecifier = [PSSpecifier preferenceSpecifierNamed:[NSString stringWithFormat:@"Update TrollStore to %@", _newerVersion]
|
||||||
|
target:self
|
||||||
|
set:nil
|
||||||
|
get:nil
|
||||||
|
detail:nil
|
||||||
|
cell:PSButtonCell
|
||||||
|
edit:nil];
|
||||||
|
updateTrollStoreSpecifier.identifier = @"updateTrollStore";
|
||||||
|
[updateTrollStoreSpecifier setProperty:@YES forKey:@"enabled"];
|
||||||
|
updateTrollStoreSpecifier.buttonAction = @selector(updateTrollStorePressed);
|
||||||
|
[_specifiers addObject:updateTrollStoreSpecifier];
|
||||||
|
}
|
||||||
|
|
||||||
PSSpecifier* utilitiesGroupSpecifier = [PSSpecifier emptyGroupSpecifier];
|
PSSpecifier* utilitiesGroupSpecifier = [PSSpecifier emptyGroupSpecifier];
|
||||||
[_specifiers addObject:utilitiesGroupSpecifier];
|
[_specifiers addObject:utilitiesGroupSpecifier];
|
||||||
|
|
||||||
if(trollStoreAppPath())
|
if(isInstalled)
|
||||||
{
|
{
|
||||||
PSSpecifier* refreshAppRegistrationsSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Refresh App Registrations"
|
PSSpecifier* refreshAppRegistrationsSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Refresh App Registrations"
|
||||||
target:self
|
target:self
|
||||||
|
@ -74,7 +83,7 @@
|
||||||
edit:nil];
|
edit:nil];
|
||||||
refreshAppRegistrationsSpecifier.identifier = @"refreshAppRegistrations";
|
refreshAppRegistrationsSpecifier.identifier = @"refreshAppRegistrations";
|
||||||
[refreshAppRegistrationsSpecifier setProperty:@YES forKey:@"enabled"];
|
[refreshAppRegistrationsSpecifier setProperty:@YES forKey:@"enabled"];
|
||||||
refreshAppRegistrationsSpecifier.buttonAction = @selector(refreshAppRegistrations);
|
refreshAppRegistrationsSpecifier.buttonAction = @selector(refreshAppRegistrationsPressed);
|
||||||
[_specifiers addObject:refreshAppRegistrationsSpecifier];
|
[_specifiers addObject:refreshAppRegistrationsSpecifier];
|
||||||
|
|
||||||
PSSpecifier* uninstallTrollStoreSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Uninstall TrollStore"
|
PSSpecifier* uninstallTrollStoreSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Uninstall TrollStore"
|
||||||
|
@ -130,122 +139,21 @@
|
||||||
|
|
||||||
- (NSString*)getTrollStoreInfoString
|
- (NSString*)getTrollStoreInfoString
|
||||||
{
|
{
|
||||||
NSString* trollStore = trollStoreAppPath();
|
NSString* version = [self getTrollStoreVersion];
|
||||||
if(!trollStore)
|
if(!version)
|
||||||
{
|
{
|
||||||
return @"Not Installed";
|
return @"Not Installed";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSBundle* trollStoreBundle = [NSBundle bundleWithPath:trollStore];
|
|
||||||
NSString* version = [trollStoreBundle objectForInfoDictionaryKey:@"CFBundleVersion"];
|
|
||||||
return [NSString stringWithFormat:@"Installed, %@", version];
|
return [NSString stringWithFormat:@"Installed, %@", version];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)refreshAppRegistrations
|
- (void)handleUninstallation
|
||||||
{
|
{
|
||||||
[self startActivity:@"Refreshing"];
|
_newerVersion = nil;
|
||||||
|
[super handleUninstallation];
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
|
|
||||||
{
|
|
||||||
spawnRoot(helperPath(), @[@"refresh"], nil, nil);
|
|
||||||
respring();
|
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^
|
|
||||||
{
|
|
||||||
[self stopActivityWithCompletion:nil];
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)installTrollStorePressed
|
|
||||||
{
|
|
||||||
NSURL* trollStoreURL = [NSURL URLWithString:@"https://github.com/opa334/TrollStore/releases/latest/download/TrollStore.tar"];
|
|
||||||
NSURLRequest* trollStoreRequest = [NSURLRequest requestWithURL:trollStoreURL];
|
|
||||||
|
|
||||||
[self startActivity:@"Installing TrollStore"];
|
|
||||||
|
|
||||||
NSURLSessionDownloadTask* downloadTask = [NSURLSession.sharedSession downloadTaskWithRequest:trollStoreRequest completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error)
|
|
||||||
{
|
|
||||||
if(error)
|
|
||||||
{
|
|
||||||
UIAlertController* errorAlert = [UIAlertController alertControllerWithTitle:@"Error" message:[NSString stringWithFormat:@"Error downloading TrollStore: %@", error] preferredStyle:UIAlertControllerStyleAlert];
|
|
||||||
UIAlertAction* closeAction = [UIAlertAction actionWithTitle:@"Close" style:UIAlertActionStyleDefault handler:nil];
|
|
||||||
[errorAlert addAction:closeAction];
|
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^
|
|
||||||
{
|
|
||||||
[self stopActivityWithCompletion:^
|
|
||||||
{
|
|
||||||
[self presentViewController:errorAlert animated:YES completion:nil];
|
|
||||||
}];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NSString* tarTmpPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"TrollStore.tar"];
|
|
||||||
[[NSFileManager defaultManager] copyItemAtPath:location.path toPath:tarTmpPath error:nil];
|
|
||||||
|
|
||||||
int ret = spawnRoot(helperPath(), @[@"install-trollstore", tarTmpPath], nil, nil);
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^
|
|
||||||
{
|
|
||||||
[[NSFileManager defaultManager] removeItemAtPath:tarTmpPath error:nil];
|
|
||||||
[self stopActivityWithCompletion:^
|
|
||||||
{
|
|
||||||
[self reloadSpecifiers];
|
|
||||||
|
|
||||||
if(ret == 0)
|
|
||||||
{
|
|
||||||
respring();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UIAlertController* errorAlert = [UIAlertController alertControllerWithTitle:@"Error" message:[NSString stringWithFormat:@"Error installing TrollStore: trollstorehelper returned %d", ret] preferredStyle:UIAlertControllerStyleAlert];
|
|
||||||
UIAlertAction* closeAction = [UIAlertAction actionWithTitle:@"Close" style:UIAlertActionStyleDefault handler:nil];
|
|
||||||
[errorAlert addAction:closeAction];
|
|
||||||
[self presentViewController:errorAlert animated:YES completion:nil];
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
|
|
||||||
[downloadTask resume];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)uninstallTrollStorePressed
|
|
||||||
{
|
|
||||||
UIAlertController* uninstallWarningAlert = [UIAlertController alertControllerWithTitle:@"Warning" message:@"About to uninstall TrollStore and all of the apps installed by it. Continue?" preferredStyle:UIAlertControllerStyleAlert];
|
|
||||||
|
|
||||||
UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
|
|
||||||
[uninstallWarningAlert addAction:cancelAction];
|
|
||||||
|
|
||||||
UIAlertAction* continueAction = [UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action)
|
|
||||||
{
|
|
||||||
spawnRoot(helperPath(), @[@"uninstall-trollstore"], nil, nil);
|
|
||||||
[self reloadSpecifiers];
|
|
||||||
}];
|
|
||||||
[uninstallWarningAlert addAction:continueAction];
|
|
||||||
|
|
||||||
[self presentViewController:uninstallWarningAlert animated:YES completion:nil];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)uninstallPersistenceHelperPressed
|
|
||||||
{
|
|
||||||
UIAlertController* uninstallWarningAlert = [UIAlertController alertControllerWithTitle:@"Warning" message:@"Uninstalling the persistence helper will revert this app back to it's original state, you will however no longer be able to persistently refresh the TrollStore app registrations. Continue?" preferredStyle:UIAlertControllerStyleAlert];
|
|
||||||
|
|
||||||
UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
|
|
||||||
[uninstallWarningAlert addAction:cancelAction];
|
|
||||||
|
|
||||||
UIAlertAction* continueAction = [UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action)
|
|
||||||
{
|
|
||||||
spawnRoot(helperPath(), @[@"uninstall-persistence-helper"], nil, nil);
|
|
||||||
exit(0);
|
|
||||||
}];
|
|
||||||
[uninstallWarningAlert addAction:continueAction];
|
|
||||||
|
|
||||||
[self presentViewController:uninstallWarningAlert animated:YES completion:nil];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
Package: com.opa334.trollstorehelper
|
Package: com.opa334.trollstorehelper
|
||||||
Name: TrollStore Helper
|
Name: TrollStore Helper
|
||||||
Version: 1.0.10
|
Version: 1.1
|
||||||
Architecture: iphoneos-arm
|
Architecture: iphoneos-arm
|
||||||
Description: Helper utility to install and manage TrollStore!
|
Description: Helper utility to install and manage TrollStore!
|
||||||
Maintainer: opa334
|
Maintainer: opa334
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
<string>iPhoneOS</string>
|
<string>iPhoneOS</string>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.0.10</string>
|
<string>1.1</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>UIDeviceFamily</key>
|
<key>UIDeviceFamily</key>
|
||||||
|
|
|
@ -2,6 +2,32 @@
|
||||||
|
|
||||||
#import "TSApplicationsManager.h"
|
#import "TSApplicationsManager.h"
|
||||||
|
|
||||||
|
#define ICON_FORMAT_IPAD 8
|
||||||
|
#define ICON_FORMAT_IPHONE 10
|
||||||
|
|
||||||
|
NSInteger iconFormatToUse(void)
|
||||||
|
{
|
||||||
|
if(UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad)
|
||||||
|
{
|
||||||
|
return ICON_FORMAT_IPAD;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ICON_FORMAT_IPHONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UIImage* imageWithSize(UIImage* image, CGSize size)
|
||||||
|
{
|
||||||
|
if(CGSizeEqualToSize(image.size, size)) return image;
|
||||||
|
UIGraphicsBeginImageContextWithOptions(size, NO, UIScreen.mainScreen.scale);
|
||||||
|
CGRect imageRect = CGRectMake(0.0, 0.0, size.width, size.height);
|
||||||
|
[image drawInRect:imageRect];
|
||||||
|
UIImage* outImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||||
|
UIGraphicsEndImageContext();
|
||||||
|
return outImage;
|
||||||
|
}
|
||||||
|
|
||||||
@interface UIImage ()
|
@interface UIImage ()
|
||||||
+ (UIImage *)_applicationIconImageForBundleIdentifier:(NSString *)id format:(NSInteger)format scale:(double)scale;
|
+ (UIImage *)_applicationIconImageForBundleIdentifier:(NSString *)id format:(NSInteger)format scale:(double)scale;
|
||||||
@end
|
@end
|
||||||
|
@ -10,7 +36,14 @@
|
||||||
|
|
||||||
- (void)loadCachedAppPaths
|
- (void)loadCachedAppPaths
|
||||||
{
|
{
|
||||||
_cachedAppPaths = [[TSApplicationsManager sharedInstance] installedAppPaths];
|
NSArray* appPaths = [[TSApplicationsManager sharedInstance] installedAppPaths];
|
||||||
|
|
||||||
|
_cachedAppPaths = [appPaths sortedArrayUsingComparator:^NSComparisonResult(NSString* appPathA, NSString* appPathB) {
|
||||||
|
NSString* displayNameA = [[TSApplicationsManager sharedInstance] displayNameForAppPath:appPathA];
|
||||||
|
NSString* displayNameB = [[TSApplicationsManager sharedInstance] displayNameForAppPath:appPathB];
|
||||||
|
|
||||||
|
return [displayNameA localizedStandardCompare:displayNameB];
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)init
|
- (instancetype)init
|
||||||
|
@ -19,7 +52,7 @@
|
||||||
if(self)
|
if(self)
|
||||||
{
|
{
|
||||||
[self loadCachedAppPaths];
|
[self loadCachedAppPaths];
|
||||||
_placeholderIcon = [UIImage _applicationIconImageForBundleIdentifier:@"com.apple.WebSheet" format:10 scale:[UIScreen mainScreen].scale];
|
_placeholderIcon = [UIImage _applicationIconImageForBundleIdentifier:@"com.apple.WebSheet" format:iconFormatToUse() scale:[UIScreen mainScreen].scale];
|
||||||
_cachedIcons = [NSMutableDictionary new];
|
_cachedIcons = [NSMutableDictionary new];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
|
@ -120,6 +153,11 @@
|
||||||
return _cachedAppPaths.count;
|
return _cachedAppPaths.count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
|
||||||
|
{
|
||||||
|
[self reloadTable];
|
||||||
|
}
|
||||||
|
|
||||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||||
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ApplicationCell"];
|
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ApplicationCell"];
|
||||||
if (!cell) {
|
if (!cell) {
|
||||||
|
@ -133,9 +171,11 @@
|
||||||
// Configure the cell...
|
// Configure the cell...
|
||||||
cell.textLabel.text = [[TSApplicationsManager sharedInstance] displayNameForAppPath:appPath];
|
cell.textLabel.text = [[TSApplicationsManager sharedInstance] displayNameForAppPath:appPath];
|
||||||
cell.detailTextLabel.text = [NSString stringWithFormat:@"%@ • %@", appVersion, appId];
|
cell.detailTextLabel.text = [NSString stringWithFormat:@"%@ • %@", appVersion, appId];
|
||||||
cell.imageView.layer.borderWidth = 0.34;
|
cell.imageView.layer.borderWidth = 1;
|
||||||
cell.imageView.layer.borderColor = [UIColor separatorColor].CGColor;
|
cell.imageView.layer.borderColor = [UIColor.labelColor colorWithAlphaComponent:0.1].CGColor;
|
||||||
cell.imageView.layer.cornerRadius = 13.8;
|
cell.imageView.layer.cornerRadius = 13.5;
|
||||||
|
cell.imageView.layer.masksToBounds = YES;
|
||||||
|
cell.imageView.layer.cornerCurve = kCACornerCurveContinuous;
|
||||||
|
|
||||||
if(appId)
|
if(appId)
|
||||||
{
|
{
|
||||||
|
@ -150,12 +190,13 @@
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
|
||||||
{
|
{
|
||||||
//usleep(1000 * 5000); // (test delay for debugging)
|
//usleep(1000 * 5000); // (test delay for debugging)
|
||||||
UIImage* iconImage = [UIImage _applicationIconImageForBundleIdentifier:appId format:10 scale:[UIScreen mainScreen].scale];
|
UIImage* iconImage = imageWithSize([UIImage _applicationIconImageForBundleIdentifier:appId format:iconFormatToUse() scale:[UIScreen mainScreen].scale], _placeholderIcon.size);
|
||||||
_cachedIcons[appId] = iconImage;
|
_cachedIcons[appId] = iconImage;
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
if([tableView.indexPathsForVisibleRows containsObject:indexPath])
|
if([tableView.indexPathsForVisibleRows containsObject:indexPath])
|
||||||
{
|
{
|
||||||
cell.imageView.image = iconImage;
|
cell.imageView.image = iconImage;
|
||||||
|
[cell setNeedsLayout];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -207,7 +248,7 @@
|
||||||
[appSelectAlert addAction:detachAction];*/
|
[appSelectAlert addAction:detachAction];*/
|
||||||
|
|
||||||
|
|
||||||
UIAlertAction* openAction = [UIAlertAction actionWithTitle: @"Open" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action)
|
UIAlertAction* openAction = [UIAlertAction actionWithTitle:@"Open" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action)
|
||||||
{
|
{
|
||||||
[self openAppPressedForRowAtIndexPath:indexPath];
|
[self openAppPressedForRowAtIndexPath:indexPath];
|
||||||
[self deselectRow];
|
[self deselectRow];
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
#import <Preferences/PSListController.h>
|
||||||
|
#import <Preferences/PSSpecifier.h>
|
||||||
|
|
||||||
|
@interface TSListControllerShared : PSListController
|
||||||
|
{
|
||||||
|
UIAlertController* _activityController;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isTrollStore;
|
||||||
|
- (NSString*)getTrollStoreVersion;
|
||||||
|
|
||||||
|
- (void)startActivity:(NSString*)activity;
|
||||||
|
- (void)stopActivityWithCompletion:(void (^)(void))completion;
|
||||||
|
|
||||||
|
- (void)installTrollStorePressed;
|
||||||
|
- (void)updateTrollStorePressed;
|
||||||
|
- (void)rebuildIconCachePressed;
|
||||||
|
- (void)refreshAppRegistrationsPressed;
|
||||||
|
- (void)uninstallPersistenceHelperPressed;
|
||||||
|
- (void)handleUninstallation;
|
||||||
|
- (void)uninstallTrollStorePressed;
|
||||||
|
@end
|
|
@ -0,0 +1,227 @@
|
||||||
|
#import "TSListControllerShared.h"
|
||||||
|
#import "TSUtil.h"
|
||||||
|
#import "../Helper/Shared.h"
|
||||||
|
|
||||||
|
@implementation TSListControllerShared
|
||||||
|
|
||||||
|
- (BOOL)isTrollStore
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString*)getTrollStoreVersion
|
||||||
|
{
|
||||||
|
if([self isTrollStore])
|
||||||
|
{
|
||||||
|
return [NSBundle.mainBundle objectForInfoDictionaryKey:@"CFBundleVersion"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSString* trollStorePath = trollStoreAppPath();
|
||||||
|
if(!trollStorePath) return nil;
|
||||||
|
|
||||||
|
NSBundle* trollStoreBundle = [NSBundle bundleWithPath:trollStorePath];
|
||||||
|
return [trollStoreBundle objectForInfoDictionaryKey:@"CFBundleVersion"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)startActivity:(NSString*)activity
|
||||||
|
{
|
||||||
|
if(_activityController) return;
|
||||||
|
|
||||||
|
_activityController = [UIAlertController alertControllerWithTitle:activity message:@"" preferredStyle:UIAlertControllerStyleAlert];
|
||||||
|
UIActivityIndicatorView* activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(5,5,50,50)];
|
||||||
|
activityIndicator.hidesWhenStopped = YES;
|
||||||
|
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleMedium;
|
||||||
|
[activityIndicator startAnimating];
|
||||||
|
[_activityController.view addSubview:activityIndicator];
|
||||||
|
|
||||||
|
[self presentViewController:_activityController animated:YES completion:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)stopActivityWithCompletion:(void (^)(void))completion
|
||||||
|
{
|
||||||
|
if(!_activityController) return;
|
||||||
|
|
||||||
|
[_activityController dismissViewControllerAnimated:YES completion:^
|
||||||
|
{
|
||||||
|
_activityController = nil;
|
||||||
|
if(completion)
|
||||||
|
{
|
||||||
|
completion();
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_updateOrInstallTrollStore:(BOOL)update
|
||||||
|
{
|
||||||
|
NSURL* trollStoreURL = [NSURL URLWithString:@"https://github.com/opa334/TrollStore/releases/latest/download/TrollStore.tar"];
|
||||||
|
NSURLRequest* trollStoreRequest = [NSURLRequest requestWithURL:trollStoreURL];
|
||||||
|
|
||||||
|
if(update)
|
||||||
|
{
|
||||||
|
[self startActivity:@"Updating TrollStore"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[self startActivity:@"Installing TrollStore"];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSURLSessionDownloadTask* downloadTask = [NSURLSession.sharedSession downloadTaskWithRequest:trollStoreRequest completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error)
|
||||||
|
{
|
||||||
|
if(error)
|
||||||
|
{
|
||||||
|
UIAlertController* errorAlert = [UIAlertController alertControllerWithTitle:@"Error" message:[NSString stringWithFormat:@"Error downloading TrollStore: %@", error] preferredStyle:UIAlertControllerStyleAlert];
|
||||||
|
UIAlertAction* closeAction = [UIAlertAction actionWithTitle:@"Close" style:UIAlertActionStyleDefault handler:nil];
|
||||||
|
[errorAlert addAction:closeAction];
|
||||||
|
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^
|
||||||
|
{
|
||||||
|
[self stopActivityWithCompletion:^
|
||||||
|
{
|
||||||
|
[self presentViewController:errorAlert animated:YES completion:nil];
|
||||||
|
}];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSString* tarTmpPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"TrollStore.tar"];
|
||||||
|
[[NSFileManager defaultManager] copyItemAtPath:location.path toPath:tarTmpPath error:nil];
|
||||||
|
|
||||||
|
int ret = spawnRoot(helperPath(), @[@"install-trollstore", tarTmpPath], nil, nil);
|
||||||
|
[[NSFileManager defaultManager] removeItemAtPath:tarTmpPath error:nil];
|
||||||
|
|
||||||
|
if(ret == 0)
|
||||||
|
{
|
||||||
|
respring();
|
||||||
|
|
||||||
|
if([self isTrollStore])
|
||||||
|
{
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^
|
||||||
|
{
|
||||||
|
[self stopActivityWithCompletion:^
|
||||||
|
{
|
||||||
|
[self reloadSpecifiers];
|
||||||
|
}];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^
|
||||||
|
{
|
||||||
|
[self stopActivityWithCompletion:^
|
||||||
|
{
|
||||||
|
UIAlertController* errorAlert = [UIAlertController alertControllerWithTitle:@"Error" message:[NSString stringWithFormat:@"Error installing TrollStore: trollstorehelper returned %d", ret] preferredStyle:UIAlertControllerStyleAlert];
|
||||||
|
UIAlertAction* closeAction = [UIAlertAction actionWithTitle:@"Close" style:UIAlertActionStyleDefault handler:nil];
|
||||||
|
[errorAlert addAction:closeAction];
|
||||||
|
[self presentViewController:errorAlert animated:YES completion:nil];
|
||||||
|
}];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
[downloadTask resume];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)installTrollStorePressed
|
||||||
|
{
|
||||||
|
[self _updateOrInstallTrollStore:NO];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateTrollStorePressed
|
||||||
|
{
|
||||||
|
[self _updateOrInstallTrollStore:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)rebuildIconCachePressed
|
||||||
|
{
|
||||||
|
[self startActivity:@"Rebuilding Icon Cache"];
|
||||||
|
|
||||||
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
|
||||||
|
{
|
||||||
|
spawnRoot(helperPath(), @[@"refresh-all"], nil, nil);
|
||||||
|
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^
|
||||||
|
{
|
||||||
|
[self stopActivityWithCompletion:nil];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)refreshAppRegistrationsPressed
|
||||||
|
{
|
||||||
|
[self startActivity:@"Refreshing"];
|
||||||
|
|
||||||
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
|
||||||
|
{
|
||||||
|
spawnRoot(helperPath(), @[@"refresh"], nil, nil);
|
||||||
|
respring();
|
||||||
|
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^
|
||||||
|
{
|
||||||
|
[self stopActivityWithCompletion:nil];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)uninstallPersistenceHelperPressed
|
||||||
|
{
|
||||||
|
if([self isTrollStore])
|
||||||
|
{
|
||||||
|
spawnRoot(helperPath(), @[@"uninstall-persistence-helper"], nil, nil);
|
||||||
|
[self reloadSpecifiers];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UIAlertController* uninstallWarningAlert = [UIAlertController alertControllerWithTitle:@"Warning" message:@"Uninstalling the persistence helper will revert this app back to it's original state, you will however no longer be able to persistently refresh the TrollStore app registrations. Continue?" preferredStyle:UIAlertControllerStyleAlert];
|
||||||
|
|
||||||
|
UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
|
||||||
|
[uninstallWarningAlert addAction:cancelAction];
|
||||||
|
|
||||||
|
UIAlertAction* continueAction = [UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action)
|
||||||
|
{
|
||||||
|
spawnRoot(helperPath(), @[@"uninstall-persistence-helper"], nil, nil);
|
||||||
|
exit(0);
|
||||||
|
}];
|
||||||
|
[uninstallWarningAlert addAction:continueAction];
|
||||||
|
|
||||||
|
[self presentViewController:uninstallWarningAlert animated:YES completion:nil];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)handleUninstallation
|
||||||
|
{
|
||||||
|
if([self isTrollStore])
|
||||||
|
{
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[self reloadSpecifiers];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)uninstallTrollStorePressed
|
||||||
|
{
|
||||||
|
UIAlertController* uninstallWarningAlert = [UIAlertController alertControllerWithTitle:@"Warning" message:@"About to uninstall TrollStore and all of the apps installed by it. Continue?" preferredStyle:UIAlertControllerStyleAlert];
|
||||||
|
|
||||||
|
UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
|
||||||
|
[uninstallWarningAlert addAction:cancelAction];
|
||||||
|
|
||||||
|
UIAlertAction* continueAction = [UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action)
|
||||||
|
{
|
||||||
|
spawnRoot(helperPath(), @[@"uninstall-trollstore"], nil, nil);
|
||||||
|
[self handleUninstallation];
|
||||||
|
}];
|
||||||
|
[uninstallWarningAlert addAction:continueAction];
|
||||||
|
|
||||||
|
[self presentViewController:uninstallWarningAlert animated:YES completion:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -1,9 +1,8 @@
|
||||||
#import <Preferences/PSListController.h>
|
#import "TSListControllerShared.h"
|
||||||
#import <Preferences/PSSpecifier.h>
|
|
||||||
|
|
||||||
@interface TSSettingsListController : PSListController
|
@interface TSSettingsListController : TSListControllerShared
|
||||||
{
|
{
|
||||||
UIAlertController* _activityController;
|
|
||||||
PSSpecifier* _installPersistenceHelperSpecifier;
|
PSSpecifier* _installPersistenceHelperSpecifier;
|
||||||
|
NSString* _newerVersion;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
|
@ -6,38 +6,24 @@
|
||||||
|
|
||||||
@implementation TSSettingsListController
|
@implementation TSSettingsListController
|
||||||
|
|
||||||
- (void)loadView
|
- (void)viewDidLoad
|
||||||
{
|
{
|
||||||
[super loadView];
|
[super viewDidLoad];
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadSpecifiers) name:UIApplicationWillEnterForegroundNotification object:nil];
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadSpecifiers) name:UIApplicationWillEnterForegroundNotification object:nil];
|
||||||
}
|
|
||||||
|
|
||||||
- (void)startActivity:(NSString*)activity
|
fetchLatestTrollStoreVersion(^(NSString* latestVersion)
|
||||||
{
|
|
||||||
if(_activityController) return;
|
|
||||||
|
|
||||||
_activityController = [UIAlertController alertControllerWithTitle:activity message:@"" preferredStyle:UIAlertControllerStyleAlert];
|
|
||||||
UIActivityIndicatorView* activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(5,5,50,50)];
|
|
||||||
activityIndicator.hidesWhenStopped = YES;
|
|
||||||
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleMedium;
|
|
||||||
[activityIndicator startAnimating];
|
|
||||||
[_activityController.view addSubview:activityIndicator];
|
|
||||||
|
|
||||||
[self presentViewController:_activityController animated:YES completion:nil];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)stopActivityWithCompletion:(void (^)(void))completion
|
|
||||||
{
|
|
||||||
if(!_activityController) return;
|
|
||||||
|
|
||||||
[_activityController dismissViewControllerAnimated:YES completion:^
|
|
||||||
{
|
{
|
||||||
_activityController = nil;
|
NSString* currentVersion = [self getTrollStoreVersion];
|
||||||
if(completion)
|
NSComparisonResult result = [currentVersion compare:latestVersion options:NSNumericSearch];
|
||||||
|
if(result == NSOrderedAscending)
|
||||||
{
|
{
|
||||||
completion();
|
_newerVersion = latestVersion;
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^
|
||||||
|
{
|
||||||
|
[self reloadSpecifiers];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}];
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSMutableArray*)specifiers
|
- (NSMutableArray*)specifiers
|
||||||
|
@ -46,6 +32,25 @@
|
||||||
{
|
{
|
||||||
_specifiers = [NSMutableArray new];
|
_specifiers = [NSMutableArray new];
|
||||||
|
|
||||||
|
if(_newerVersion)
|
||||||
|
{
|
||||||
|
PSSpecifier* updateTrollStoreGroupSpecifier = [PSSpecifier emptyGroupSpecifier];
|
||||||
|
updateTrollStoreGroupSpecifier.name = @"Update Available";
|
||||||
|
[_specifiers addObject:updateTrollStoreGroupSpecifier];
|
||||||
|
|
||||||
|
PSSpecifier* updateTrollStoreSpecifier = [PSSpecifier preferenceSpecifierNamed:[NSString stringWithFormat:@"Update TrollStore to %@", _newerVersion]
|
||||||
|
target:self
|
||||||
|
set:nil
|
||||||
|
get:nil
|
||||||
|
detail:nil
|
||||||
|
cell:PSButtonCell
|
||||||
|
edit:nil];
|
||||||
|
updateTrollStoreSpecifier.identifier = @"updateTrollStore";
|
||||||
|
[updateTrollStoreSpecifier setProperty:@YES forKey:@"enabled"];
|
||||||
|
updateTrollStoreSpecifier.buttonAction = @selector(updateTrollStorePressed);
|
||||||
|
[_specifiers addObject:updateTrollStoreSpecifier];
|
||||||
|
}
|
||||||
|
|
||||||
PSSpecifier* utilitiesGroupSpecifier = [PSSpecifier emptyGroupSpecifier];
|
PSSpecifier* utilitiesGroupSpecifier = [PSSpecifier emptyGroupSpecifier];
|
||||||
utilitiesGroupSpecifier.name = @"Utilities";
|
utilitiesGroupSpecifier.name = @"Utilities";
|
||||||
[utilitiesGroupSpecifier setProperty:@"If an app does not immediately appear after installation, respring here and it should appear afterwards." forKey:@"footerText"];
|
[utilitiesGroupSpecifier setProperty:@"If an app does not immediately appear after installation, respring here and it should appear afterwards." forKey:@"footerText"];
|
||||||
|
@ -192,7 +197,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
PSSpecifier* otherGroupSpecifier = [PSSpecifier emptyGroupSpecifier];
|
PSSpecifier* otherGroupSpecifier = [PSSpecifier emptyGroupSpecifier];
|
||||||
[otherGroupSpecifier setProperty:[NSString stringWithFormat:@"TrollStore %@\n\n© 2022 Lars Fröder (opa334)\n\nCredits:\n@LinusHenze: CoreTrust bug\n@zhuowei: CoreTrust bug writeup and cert\n@lunotech11, @SerenaKit, @tylinux: Various contributions\n@ProcursusTeam: uicache and ldid build\n@cstar_ow: uicache\n@saurik: ldid", getTrollStoreVersion()] forKey:@"footerText"];
|
[otherGroupSpecifier setProperty:[NSString stringWithFormat:@"TrollStore %@\n\n© 2022 Lars Fröder (opa334)\n\nCredits:\n@LinusHenze: CoreTrust bug\n@zhuowei: CoreTrust bug writeup and cert\n@lunotech11, @SerenaKit, @tylinux: Various contributions\n@ProcursusTeam: uicache and ldid build\n@cstar_ow: uicache\n@saurik: ldid", [self getTrollStoreVersion]] forKey:@"footerText"];
|
||||||
[_specifiers addObject:otherGroupSpecifier];
|
[_specifiers addObject:otherGroupSpecifier];
|
||||||
|
|
||||||
// Uninstall TrollStore
|
// Uninstall TrollStore
|
||||||
|
@ -208,6 +213,18 @@
|
||||||
[uninstallTrollStoreSpecifier setProperty:NSClassFromString(@"PSDeleteButtonCell") forKey:@"cellClass"];
|
[uninstallTrollStoreSpecifier setProperty:NSClassFromString(@"PSDeleteButtonCell") forKey:@"cellClass"];
|
||||||
uninstallTrollStoreSpecifier.buttonAction = @selector(uninstallTrollStorePressed);
|
uninstallTrollStoreSpecifier.buttonAction = @selector(uninstallTrollStorePressed);
|
||||||
[_specifiers addObject:uninstallTrollStoreSpecifier];
|
[_specifiers addObject:uninstallTrollStoreSpecifier];
|
||||||
|
|
||||||
|
/*PSSpecifier* doTheDashSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Do the Dash"
|
||||||
|
target:self
|
||||||
|
set:nil
|
||||||
|
get:nil
|
||||||
|
detail:nil
|
||||||
|
cell:PSButtonCell
|
||||||
|
edit:nil];
|
||||||
|
doTheDashSpecifier.identifier = @"doTheDash";
|
||||||
|
[doTheDashSpecifier setProperty:@YES forKey:@"enabled"];
|
||||||
|
uninstallTrollStoreSpecifier.buttonAction = @selector(doTheDashPressed);
|
||||||
|
[_specifiers addObject:doTheDashSpecifier];*/
|
||||||
}
|
}
|
||||||
|
|
||||||
[(UINavigationItem *)self.navigationItem setTitle:@"Settings"];
|
[(UINavigationItem *)self.navigationItem setTitle:@"Settings"];
|
||||||
|
@ -219,21 +236,6 @@
|
||||||
respring();
|
respring();
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)rebuildIconCachePressed
|
|
||||||
{
|
|
||||||
[self startActivity:@"Rebuilding Icon Cache"];
|
|
||||||
|
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
|
|
||||||
{
|
|
||||||
spawnRoot(helperPath(), @[@"refresh-all"], nil, nil);
|
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^
|
|
||||||
{
|
|
||||||
[self stopActivityWithCompletion:nil];
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)installLdidPressed
|
- (void)installLdidPressed
|
||||||
{
|
{
|
||||||
NSURL* ldidURL = [NSURL URLWithString:@"https://github.com/opa334/ldid/releases/download/v2.1.5-procursus5/ldid"];
|
NSURL* ldidURL = [NSURL URLWithString:@"https://github.com/opa334/ldid/releases/download/v2.1.5-procursus5/ldid"];
|
||||||
|
@ -312,27 +314,9 @@
|
||||||
[self presentViewController:selectAppAlert animated:YES completion:nil];
|
[self presentViewController:selectAppAlert animated:YES completion:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)uninstallPersistenceHelperPressed
|
- (void)doTheDashPressed
|
||||||
{
|
{
|
||||||
spawnRoot(helperPath(), @[@"uninstall-persistence-helper"], nil, nil);
|
spawnRoot(helperPath(), @[@"dash"], nil, nil);
|
||||||
[self reloadSpecifiers];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)uninstallTrollStorePressed
|
|
||||||
{
|
|
||||||
UIAlertController* uninstallWarningAlert = [UIAlertController alertControllerWithTitle:@"Warning" message:@"About to uninstall TrollStore and all of the apps installed by it. Continue?" preferredStyle:UIAlertControllerStyleAlert];
|
|
||||||
|
|
||||||
UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
|
|
||||||
[uninstallWarningAlert addAction:cancelAction];
|
|
||||||
|
|
||||||
UIAlertAction* continueAction = [UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action)
|
|
||||||
{
|
|
||||||
spawnRoot(helperPath(), @[@"uninstall-trollstore"], nil, nil);
|
|
||||||
exit(0);
|
|
||||||
}];
|
|
||||||
[uninstallWarningAlert addAction:continueAction];
|
|
||||||
|
|
||||||
[self presentViewController:uninstallWarningAlert animated:YES completion:nil];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
|
@ -4,4 +4,4 @@ extern NSString* helperPath(void);
|
||||||
extern void printMultilineNSString(NSString* stringToPrint);
|
extern void printMultilineNSString(NSString* stringToPrint);
|
||||||
extern int spawnRoot(NSString* path, NSArray* args, NSString** stdOut, NSString** stdErr);
|
extern int spawnRoot(NSString* path, NSArray* args, NSString** stdOut, NSString** stdErr);
|
||||||
extern void respring(void);
|
extern void respring(void);
|
||||||
extern NSString* getTrollStoreVersion(void);
|
extern void fetchLatestTrollStoreVersion(void (^completionHandler)(NSString* latestVersion));
|
|
@ -186,7 +186,26 @@ void respring(void)
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString* getTrollStoreVersion(void)
|
void fetchLatestTrollStoreVersion(void (^completionHandler)(NSString* latestVersion))
|
||||||
{
|
{
|
||||||
return [NSBundle.mainBundle objectForInfoDictionaryKey:@"CFBundleVersion"];
|
NSURL* githubLatestAPIURL = [NSURL URLWithString:@"https://api.github.com/repos/opa334/TrollStore/releases/latest"];
|
||||||
}
|
|
||||||
|
NSURLSessionDataTask* task = [NSURLSession.sharedSession dataTaskWithURL:githubLatestAPIURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
|
||||||
|
{
|
||||||
|
if(!error)
|
||||||
|
{
|
||||||
|
if ([response isKindOfClass:[NSHTTPURLResponse class]])
|
||||||
|
{
|
||||||
|
NSError *jsonError;
|
||||||
|
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
|
||||||
|
|
||||||
|
if (!jsonError)
|
||||||
|
{
|
||||||
|
completionHandler(jsonResponse[@"tag_name"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
[task resume];
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
Package: com.opa334.trollstore
|
Package: com.opa334.trollstore
|
||||||
Name: TrollStore
|
Name: TrollStore
|
||||||
Version: 1.0.10
|
Version: 1.1
|
||||||
Architecture: iphoneos-arm
|
Architecture: iphoneos-arm
|
||||||
Description: An awesome application!
|
Description: An awesome application!
|
||||||
Maintainer: opa334
|
Maintainer: opa334
|
||||||
|
|
|
@ -48,18 +48,20 @@ COPYFILE_DISABLE=1 tar -czvf TrollStore.tar ./TrollStore.app
|
||||||
rm -rf ./TrollStore.app
|
rm -rf ./TrollStore.app
|
||||||
cd -
|
cd -
|
||||||
|
|
||||||
# Step five: compile installer
|
if [[ $1 == "installer" ]]; then
|
||||||
xcodebuild -project ../Installer/TrollInstaller/TrollInstaller.xcodeproj -scheme TrollInstaller -destination generic/platform=iOS -archivePath ./out/Installer.xcarchive archive
|
# Step five: compile installer
|
||||||
|
xcodebuild -project ../Installer/TrollInstaller/TrollInstaller.xcodeproj -scheme TrollInstaller -destination generic/platform=iOS -archivePath ./out/Installer.xcarchive archive
|
||||||
|
|
||||||
if [[ -f "./out/Installer.xcarchive/Products/Applications/TrollInstaller.app/embedded.mobileprovision" ]]; then
|
if [[ -f "./out/Installer.xcarchive/Products/Applications/TrollInstaller.app/embedded.mobileprovision" ]]; then
|
||||||
rm ./out/Installer.xcarchive/Products/Applications/TrollInstaller.app/embedded.mobileprovision
|
rm ./out/Installer.xcarchive/Products/Applications/TrollInstaller.app/embedded.mobileprovision
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ldid -s ./out/Installer.xcarchive/Products/Applications/TrollInstaller.app
|
ldid -s ./out/Installer.xcarchive/Products/Applications/TrollInstaller.app
|
||||||
mkdir ./out/Payload
|
mkdir ./out/Payload
|
||||||
mv ./out/Installer.xcarchive/Products/Applications/TrollInstaller.app ./out/Payload/TrollInstaller.app
|
mv ./out/Installer.xcarchive/Products/Applications/TrollInstaller.app ./out/Payload/TrollInstaller.app
|
||||||
cd out
|
cd out
|
||||||
zip -vr TrollInstaller.ipa Payload
|
zip -vr TrollInstaller.ipa Payload
|
||||||
cd -
|
cd -
|
||||||
rm -rf ./out/Payload
|
rm -rf ./out/Payload
|
||||||
rm -rf ./out/Installer.xcarchive
|
rm -rf ./out/Installer.xcarchive
|
||||||
|
fi
|
Loading…
Reference in New Issue