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
|
||||
Name: trollstoreroothelper
|
||||
Version: 1.0.10
|
||||
Version: 1.1
|
||||
Architecture: iphoneos-arm
|
||||
Description: An awesome tool of some sort!!
|
||||
Maintainer: opa334
|
||||
|
|
|
@ -730,6 +730,11 @@ int installApp(NSString* appPath, BOOL sign, BOOL force)
|
|||
// Wipe old version if needed
|
||||
if(existed)
|
||||
{
|
||||
if(![appId isEqualToString:@"com.opa334.TrollStore"])
|
||||
{
|
||||
BKSTerminateApplicationForReasonAndReportWithDescription(appId, 5, false, @"TrollStore - App updated");
|
||||
}
|
||||
|
||||
NSLog(@"[installApp] found existing TrollStore app, cleaning directory");
|
||||
NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:appContainer.url includingPropertiesForKeys:nil options:0 errorHandler:nil];
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -767,6 +772,8 @@ int installApp(NSString* appPath, BOOL sign, BOOL force)
|
|||
|
||||
int uninstallApp(NSString* appPath, NSString* appId)
|
||||
{
|
||||
BKSTerminateApplicationForReasonAndReportWithDescription(appId, 5, false, @"TrollStore - App uninstalled");
|
||||
|
||||
LSApplicationProxy* appProxy = [LSApplicationProxy applicationProxyForIdentifier:appId];
|
||||
MCMContainer *appContainer = [objc_getClass("MCMAppDataContainer") containerWithIdentifier:appId createIfNecessary:NO existed:nil error:nil];
|
||||
NSString *containerPath = [appContainer url].path;
|
||||
|
@ -1156,6 +1163,14 @@ int main(int argc, char *argv[], char *envp[]) {
|
|||
} else if([cmd isEqualToString:@"uninstall-persistence-helper"])
|
||||
{
|
||||
uninstallPersistenceHelper();
|
||||
} else if([cmd isEqualToString:@"dash"])
|
||||
{
|
||||
LSApplicationProxy* appProxy = findPersistenceHelperApp();
|
||||
if(appProxy)
|
||||
{
|
||||
NSString* executablePath = appProxy.canonicalExecutablePath;
|
||||
registerPath((char*)executablePath.UTF8String, 1);
|
||||
}
|
||||
}
|
||||
|
||||
NSLog(@"returning %d", ret);
|
||||
|
|
|
@ -127,7 +127,6 @@ void registerPath(char* cPath, int unregister)
|
|||
// Misc
|
||||
|
||||
dictToRegister[@"ApplicationType"] = @"System";
|
||||
dictToRegister[@"BundleNameIsLocalized"] = @1;
|
||||
dictToRegister[@"CFBundleIdentifier"] = appBundleID;
|
||||
dictToRegister[@"CodeInfoIdentifier"] = appBundleID;
|
||||
dictToRegister[@"CompatibilityState"] = @0;
|
||||
|
@ -144,6 +143,10 @@ void registerPath(char* cPath, int unregister)
|
|||
dictToRegister[@"SignerIdentity"] = @"Apple iPhone OS Application Signing";
|
||||
dictToRegister[@"IsAdHocSigned"] = @YES;
|
||||
dictToRegister[@"LSInstallType"] = @1;
|
||||
dictToRegister[@"HasMIDBasedSINF"] = @0;
|
||||
dictToRegister[@"MissingSINF"] = @0;
|
||||
dictToRegister[@"FamilyID"] = @0;
|
||||
dictToRegister[@"IsOnDemandInstallCapable"] = @0;
|
||||
|
||||
NSString* teamIdentifier = constructTeamIdentifierForEntitlements(entitlements);
|
||||
if(teamIdentifier) dictToRegister[@"TeamIdentifier"] = teamIdentifier;
|
||||
|
@ -199,7 +202,6 @@ void registerPath(char* cPath, int unregister)
|
|||
// Misc
|
||||
|
||||
pluginDict[@"ApplicationType"] = @"PluginKitPlugin";
|
||||
pluginDict[@"BundleNameIsLocalized"] = @1;
|
||||
pluginDict[@"CFBundleIdentifier"] = pluginBundleID;
|
||||
pluginDict[@"CodeInfoIdentifier"] = pluginBundleID;
|
||||
pluginDict[@"CompatibilityState"] = @0;
|
||||
|
|
|
@ -5,7 +5,7 @@ include $(THEOS)/makefiles/common.mk
|
|||
|
||||
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_PRIVATE_FRAMEWORKS = Preferences
|
||||
TrollStorePersistenceHelper_CFLAGS = -fobjc-arc
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
<string>iPhoneOS</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0.10</string>
|
||||
<string>1.1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIDeviceFamily</key>
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#import <UIKit/UIKit.h>
|
||||
#import <Preferences/PSListController.h>
|
||||
#import <Preferences/PSSpecifier.h>
|
||||
#import "../Store/TSListControllerShared.h"
|
||||
|
||||
@interface TSPHRootViewController : PSListController
|
||||
@interface TSPHRootViewController : TSListControllerShared
|
||||
{
|
||||
UIAlertController* _activityController;
|
||||
NSString* _newerVersion;
|
||||
}
|
||||
@end
|
||||
|
|
|
@ -4,38 +4,29 @@
|
|||
|
||||
@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];
|
||||
}
|
||||
|
||||
- (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:^
|
||||
fetchLatestTrollStoreVersion(^(NSString* latestVersion)
|
||||
{
|
||||
_activityController = nil;
|
||||
if(completion)
|
||||
NSString* currentVersion = [self getTrollStoreVersion];
|
||||
NSComparisonResult result = [currentVersion compare:latestVersion options:NSNumericSearch];
|
||||
if(result == NSOrderedAscending)
|
||||
{
|
||||
completion();
|
||||
_newerVersion = latestVersion;
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
{
|
||||
[self reloadSpecifiers];
|
||||
});
|
||||
}
|
||||
}];
|
||||
});
|
||||
}
|
||||
|
||||
- (NSMutableArray*)specifiers
|
||||
|
@ -60,10 +51,28 @@
|
|||
|
||||
[_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];
|
||||
[_specifiers addObject:utilitiesGroupSpecifier];
|
||||
|
||||
if(trollStoreAppPath())
|
||||
if(isInstalled)
|
||||
{
|
||||
PSSpecifier* refreshAppRegistrationsSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Refresh App Registrations"
|
||||
target:self
|
||||
|
@ -74,7 +83,7 @@
|
|||
edit:nil];
|
||||
refreshAppRegistrationsSpecifier.identifier = @"refreshAppRegistrations";
|
||||
[refreshAppRegistrationsSpecifier setProperty:@YES forKey:@"enabled"];
|
||||
refreshAppRegistrationsSpecifier.buttonAction = @selector(refreshAppRegistrations);
|
||||
refreshAppRegistrationsSpecifier.buttonAction = @selector(refreshAppRegistrationsPressed);
|
||||
[_specifiers addObject:refreshAppRegistrationsSpecifier];
|
||||
|
||||
PSSpecifier* uninstallTrollStoreSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Uninstall TrollStore"
|
||||
|
@ -130,122 +139,21 @@
|
|||
|
||||
- (NSString*)getTrollStoreInfoString
|
||||
{
|
||||
NSString* trollStore = trollStoreAppPath();
|
||||
if(!trollStore)
|
||||
NSString* version = [self getTrollStoreVersion];
|
||||
if(!version)
|
||||
{
|
||||
return @"Not Installed";
|
||||
}
|
||||
else
|
||||
{
|
||||
NSBundle* trollStoreBundle = [NSBundle bundleWithPath:trollStore];
|
||||
NSString* version = [trollStoreBundle objectForInfoDictionaryKey:@"CFBundleVersion"];
|
||||
return [NSString stringWithFormat:@"Installed, %@", version];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)refreshAppRegistrations
|
||||
- (void)handleUninstallation
|
||||
{
|
||||
[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)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];
|
||||
_newerVersion = nil;
|
||||
[super handleUninstallation];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Package: com.opa334.trollstorehelper
|
||||
Name: TrollStore Helper
|
||||
Version: 1.0.10
|
||||
Version: 1.1
|
||||
Architecture: iphoneos-arm
|
||||
Description: Helper utility to install and manage TrollStore!
|
||||
Maintainer: opa334
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
<string>iPhoneOS</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0.10</string>
|
||||
<string>1.1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIDeviceFamily</key>
|
||||
|
|
|
@ -2,6 +2,32 @@
|
|||
|
||||
#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 ()
|
||||
+ (UIImage *)_applicationIconImageForBundleIdentifier:(NSString *)id format:(NSInteger)format scale:(double)scale;
|
||||
@end
|
||||
|
@ -10,7 +36,14 @@
|
|||
|
||||
- (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
|
||||
|
@ -19,7 +52,7 @@
|
|||
if(self)
|
||||
{
|
||||
[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];
|
||||
}
|
||||
return self;
|
||||
|
@ -120,6 +153,11 @@
|
|||
return _cachedAppPaths.count;
|
||||
}
|
||||
|
||||
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
|
||||
{
|
||||
[self reloadTable];
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ApplicationCell"];
|
||||
if (!cell) {
|
||||
|
@ -133,9 +171,11 @@
|
|||
// Configure the cell...
|
||||
cell.textLabel.text = [[TSApplicationsManager sharedInstance] displayNameForAppPath:appPath];
|
||||
cell.detailTextLabel.text = [NSString stringWithFormat:@"%@ • %@", appVersion, appId];
|
||||
cell.imageView.layer.borderWidth = 0.34;
|
||||
cell.imageView.layer.borderColor = [UIColor separatorColor].CGColor;
|
||||
cell.imageView.layer.cornerRadius = 13.8;
|
||||
cell.imageView.layer.borderWidth = 1;
|
||||
cell.imageView.layer.borderColor = [UIColor.labelColor colorWithAlphaComponent:0.1].CGColor;
|
||||
cell.imageView.layer.cornerRadius = 13.5;
|
||||
cell.imageView.layer.masksToBounds = YES;
|
||||
cell.imageView.layer.cornerCurve = kCACornerCurveContinuous;
|
||||
|
||||
if(appId)
|
||||
{
|
||||
|
@ -150,12 +190,13 @@
|
|||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
|
||||
{
|
||||
//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;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if([tableView.indexPathsForVisibleRows containsObject:indexPath])
|
||||
{
|
||||
cell.imageView.image = iconImage;
|
||||
[cell setNeedsLayout];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -207,7 +248,7 @@
|
|||
[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 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 <Preferences/PSSpecifier.h>
|
||||
#import "TSListControllerShared.h"
|
||||
|
||||
@interface TSSettingsListController : PSListController
|
||||
@interface TSSettingsListController : TSListControllerShared
|
||||
{
|
||||
UIAlertController* _activityController;
|
||||
PSSpecifier* _installPersistenceHelperSpecifier;
|
||||
NSString* _newerVersion;
|
||||
}
|
||||
@end
|
|
@ -6,38 +6,24 @@
|
|||
|
||||
@implementation TSSettingsListController
|
||||
|
||||
- (void)loadView
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super loadView];
|
||||
[super viewDidLoad];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadSpecifiers) name:UIApplicationWillEnterForegroundNotification object:nil];
|
||||
}
|
||||
|
||||
- (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:^
|
||||
fetchLatestTrollStoreVersion(^(NSString* latestVersion)
|
||||
{
|
||||
_activityController = nil;
|
||||
if(completion)
|
||||
NSString* currentVersion = [self getTrollStoreVersion];
|
||||
NSComparisonResult result = [currentVersion compare:latestVersion options:NSNumericSearch];
|
||||
if(result == NSOrderedAscending)
|
||||
{
|
||||
completion();
|
||||
_newerVersion = latestVersion;
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
{
|
||||
[self reloadSpecifiers];
|
||||
});
|
||||
}
|
||||
}];
|
||||
});
|
||||
}
|
||||
|
||||
- (NSMutableArray*)specifiers
|
||||
|
@ -46,6 +32,25 @@
|
|||
{
|
||||
_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];
|
||||
utilitiesGroupSpecifier.name = @"Utilities";
|
||||
[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];
|
||||
[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];
|
||||
|
||||
// Uninstall TrollStore
|
||||
|
@ -208,6 +213,18 @@
|
|||
[uninstallTrollStoreSpecifier setProperty:NSClassFromString(@"PSDeleteButtonCell") forKey:@"cellClass"];
|
||||
uninstallTrollStoreSpecifier.buttonAction = @selector(uninstallTrollStorePressed);
|
||||
[_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"];
|
||||
|
@ -219,21 +236,6 @@
|
|||
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
|
||||
{
|
||||
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];
|
||||
}
|
||||
|
||||
- (void)uninstallPersistenceHelperPressed
|
||||
- (void)doTheDashPressed
|
||||
{
|
||||
spawnRoot(helperPath(), @[@"uninstall-persistence-helper"], 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];
|
||||
spawnRoot(helperPath(), @[@"dash"], nil, nil);
|
||||
}
|
||||
|
||||
@end
|
|
@ -4,4 +4,4 @@ extern NSString* helperPath(void);
|
|||
extern void printMultilineNSString(NSString* stringToPrint);
|
||||
extern int spawnRoot(NSString* path, NSArray* args, NSString** stdOut, NSString** stdErr);
|
||||
extern void respring(void);
|
||||
extern NSString* getTrollStoreVersion(void);
|
||||
extern void fetchLatestTrollStoreVersion(void (^completionHandler)(NSString* latestVersion));
|
|
@ -186,7 +186,26 @@ void respring(void)
|
|||
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
|
||||
Name: TrollStore
|
||||
Version: 1.0.10
|
||||
Version: 1.1
|
||||
Architecture: iphoneos-arm
|
||||
Description: An awesome application!
|
||||
Maintainer: opa334
|
||||
|
|
|
@ -48,18 +48,20 @@ COPYFILE_DISABLE=1 tar -czvf TrollStore.tar ./TrollStore.app
|
|||
rm -rf ./TrollStore.app
|
||||
cd -
|
||||
|
||||
# Step five: compile installer
|
||||
xcodebuild -project ../Installer/TrollInstaller/TrollInstaller.xcodeproj -scheme TrollInstaller -destination generic/platform=iOS -archivePath ./out/Installer.xcarchive archive
|
||||
if [[ $1 == "installer" ]]; then
|
||||
# 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
|
||||
rm ./out/Installer.xcarchive/Products/Applications/TrollInstaller.app/embedded.mobileprovision
|
||||
fi
|
||||
if [[ -f "./out/Installer.xcarchive/Products/Applications/TrollInstaller.app/embedded.mobileprovision" ]]; then
|
||||
rm ./out/Installer.xcarchive/Products/Applications/TrollInstaller.app/embedded.mobileprovision
|
||||
fi
|
||||
|
||||
ldid -s ./out/Installer.xcarchive/Products/Applications/TrollInstaller.app
|
||||
mkdir ./out/Payload
|
||||
mv ./out/Installer.xcarchive/Products/Applications/TrollInstaller.app ./out/Payload/TrollInstaller.app
|
||||
cd out
|
||||
zip -vr TrollInstaller.ipa Payload
|
||||
cd -
|
||||
rm -rf ./out/Payload
|
||||
rm -rf ./out/Installer.xcarchive
|
||||
ldid -s ./out/Installer.xcarchive/Products/Applications/TrollInstaller.app
|
||||
mkdir ./out/Payload
|
||||
mv ./out/Installer.xcarchive/Products/Applications/TrollInstaller.app ./out/Payload/TrollInstaller.app
|
||||
cd out
|
||||
zip -vr TrollInstaller.ipa Payload
|
||||
cd -
|
||||
rm -rf ./out/Payload
|
||||
rm -rf ./out/Installer.xcarchive
|
||||
fi
|
Loading…
Reference in New Issue