Skip to content

Commit

Permalink
Allow adding app shortcuts to home screen (rewrite #62)
Browse files Browse the repository at this point in the history
Thanks @Vishram1123 for the idea
  • Loading branch information
khanhduytran0 committed Aug 5, 2024
1 parent aa7261c commit 499cae4
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 17 deletions.
1 change: 1 addition & 0 deletions AppInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
- (void)setDataUUID:(NSString *)uuid;
- (void)setTweakFolder:(NSString *)tweakFolder;
- (instancetype)initWithBundlePath:(NSString*)bundlePath;
- (NSDictionary *)generateWebClipConfig;
- (void)save;
@end
47 changes: 47 additions & 0 deletions AppInfo.m
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,53 @@ - (UIImage*)icon {
return icon;
}

- (UIImage *)generateLiveContainerWrappedIcon {
UIImage *lcIcon = [UIImage imageNamed:@"AppIcon76x76"];
UIImage *icon = self.icon;
CGFloat iconXY = (lcIcon.size.width - 40) / 2;
UIGraphicsBeginImageContextWithOptions(lcIcon.size, NO, 0.0);
[lcIcon drawInRect:CGRectMake(0, 0, lcIcon.size.width, lcIcon.size.height)];
CGRect rect = CGRectMake(iconXY, iconXY, 40, 40);
[[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:7] addClip];
[icon drawInRect:rect];
UIImage *newIcon = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newIcon;
}

- (NSDictionary *)generateWebClipConfig {
NSDictionary *payload = @{
@"FullScreen": @YES,
@"Icon": UIImagePNGRepresentation(self.generateLiveContainerWrappedIcon),
@"IgnoreManifestScope": @YES,
@"IsRemovable": @YES,
@"Label": self.displayName,
@"PayloadDescription": [NSString stringWithFormat:@"Web Clip for launching %@ (%@) in LiveContainer", self.displayName, self.bundlePath.lastPathComponent],
@"PayloadDisplayName": self.displayName,
@"PayloadIdentifier": self.bundleIdentifier,
@"PayloadType": @"com.apple.webClip.managed",
@"PayloadUUID": self.dataUUID,
@"PayloadVersion": @(1),
@"Precomposed": @NO,
@"toPayloadOrganization": @"LiveContainer",
@"URL": [NSString stringWithFormat:@"livecontainer://livecontainer-launch?bundle-name=%@", self.bundlePath.lastPathComponent]
};
return @{
@"ConsentText": @{
@"default": [NSString stringWithFormat:@"This profile installs a web clip which opens %@ (%@) in LiveContainer", self.displayName, self.bundlePath.lastPathComponent]
},
@"PayloadContent": @[payload],
@"PayloadDescription": payload[@"PayloadDescription"],
@"PayloadDisplayName": self.displayName,
@"PayloadIdentifier": self.bundleIdentifier,
@"PayloadOrganization": @"LiveContainer",
@"PayloadRemovalDisallowed": @(NO),
@"PayloadType": @"Configuration",
@"PayloadUUID": @"345097fb-d4f7-4a34-ab90-2e3f1ad62eed",
@"PayloadVersion": @(1),
};
}

- (void)save {
[_info writeToFile:[NSString stringWithFormat:@"%@/Info.plist", _bundlePath] atomically:YES];
}
Expand Down
17 changes: 17 additions & 0 deletions LCAppDelegate.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import "LCAppDelegate.h"
#import "LCJITLessSetupViewController.h"
#import "LCTabBarController.h"
#import "LCUtils.h"

@implementation LCAppDelegate

Expand All @@ -18,4 +19,20 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
return YES;
}

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
NSURLComponents* components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO];
if(![components.host isEqualToString:@"livecontainer-launch"]) return false;

for (NSURLQueryItem* queryItem in components.queryItems) {
if ([queryItem.name isEqualToString:@"bundle-name"]) {
[NSUserDefaults.standardUserDefaults setObject:queryItem.value forKey:@"selected"];

// Attempt to restart LiveContainer with the selected guest app
[LCUtils launchToGuestApp];
break;
}
}
return true;
}

@end
36 changes: 19 additions & 17 deletions LCRootViewController.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#import <CommonCrypto/CommonDigest.h>
#import <SafariServices/SafariServices.h>
#import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
#import "LCRootViewController.h"
#import "LCUtils.h"
Expand All @@ -8,7 +9,6 @@
#import "unarchive.h"
#import "AppInfo.h"


#include <libgen.h>
#include <mach-o/fat.h>
#include <mach-o/loader.h>
Expand Down Expand Up @@ -78,6 +78,13 @@ static void patchExecSlice(const char *path, struct mach_header_64 *header) {
}
}

@implementation NSURL(hack)
- (BOOL)safari_isHTTPFamilyURL {
// Screw it, Apple
return YES;
}
@end

@interface LCRootViewController ()
@property(atomic) NSMutableArray<NSString *> *objects;
@property(nonatomic) NSString *bundlePath, *docPath, *tweakPath;
Expand Down Expand Up @@ -164,22 +171,7 @@ - (void)launchButtonTapped {
return;
}

NSString *urlScheme;
NSString *tsPath = [NSString stringWithFormat:@"%@/../_TrollStore", NSBundle.mainBundle.bundlePath];
if (!access(tsPath.UTF8String, F_OK)) {
urlScheme = @"apple-magnifier://enable-jit?bundle-id=%@";
} else if (LCUtils.certificatePassword) {
urlScheme = @"livecontainer://open?un_used=%@";
} else {
urlScheme = @"sidestore://sidejit-enable?bid=%@";
}
NSURL *sidejitURL = [NSURL URLWithString:[NSString stringWithFormat:urlScheme, NSBundle.mainBundle.bundleIdentifier]];
if ([UIApplication.sharedApplication canOpenURL:sidejitURL]) {
[UIApplication.sharedApplication openURL:sidejitURL options:@{} completionHandler:^(BOOL b) {
exit(0);
}];
return;
}
if ([LCUtils launchToGuestApp]) return;

[self showDialogTitle:@"Instruction" message:@"To use this button, you need a build of SideStore that supports enabling JIT through URL scheme. Otherwise, you need to manually enable it."
handler:^(UIAlertAction * action) {
Expand Down Expand Up @@ -619,6 +611,16 @@ - (UIContextMenuConfiguration *)tableView:(UITableView *)tableView contextMenuCo
}

NSArray *menuItems = @[
[UIAction
actionWithTitle:@"Add to Home Screen"
image:[UIImage systemImageNamed:@"plus.app"]
identifier:nil
handler:^(UIAction *action) {
NSData *data = [NSPropertyListSerialization dataWithPropertyList:appInfo.generateWebClipConfig format:NSPropertyListXMLFormat_v1_0 options:0 error:0];
NSString *url = [NSString stringWithFormat:@"data:application/x-apple-aspen-config;base64,%@", [data base64EncodedStringWithOptions:0]];
SFSafariViewController *svc = [[SFSafariViewController alloc] initWithURL:[NSURL URLWithString:url]];
[self presentViewController:svc animated:YES completion:nil];
}],
[UIMenu
menuWithTitle:@"Change tweak folder"
image:[UIImage systemImageNamed:@"gearshape.2"]
Expand Down
2 changes: 2 additions & 0 deletions LCUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
+ (NSProgress *)signAppBundle:(NSURL *)path completionHandler:(void (^)(BOOL success, NSError *error))completionHandler;

+ (BOOL)isAppGroupSideStore;
+ (BOOL)launchToGuestApp;

+ (NSURL *)archiveIPAWithSetupMode:(BOOL)setup error:(NSError **)error;


@end
21 changes: 21 additions & 0 deletions LCUtils.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@import Darwin;
@import MachO;
@import UIKit;

#import "AltStoreCore/ALTSigner.h"
#import "LCUtils.h"
Expand Down Expand Up @@ -247,4 +248,24 @@ + (NSURL *)archiveIPAWithSetupMode:(BOOL)setup error:(NSError **)error {
return tmpIPAPath;
}

+ (BOOL)launchToGuestApp {
NSString *urlScheme;
NSString *tsPath = [NSString stringWithFormat:@"%@/../_TrollStore", NSBundle.mainBundle.bundlePath];
if (!access(tsPath.UTF8String, F_OK)) {
urlScheme = @"apple-magnifier://enable-jit?bundle-id=%@";
} else if (LCUtils.certificatePassword) {
urlScheme = @"livecontainer://livecontainer-launch?unused=%@";
} else {
urlScheme = @"sidestore://sidejit-enable?bid=%@";
}
NSURL *launchURL = [NSURL URLWithString:[NSString stringWithFormat:urlScheme, NSBundle.mainBundle.bundleIdentifier]];
if ([UIApplication.sharedApplication canOpenURL:launchURL]) {
[UIApplication.sharedApplication openURL:launchURL options:@{} completionHandler:^(BOOL b) {
exit(0);
}];
return true;
}
return false;
}

@end

0 comments on commit 499cae4

Please sign in to comment.