Skip to content

Commit

Permalink
fix [Feature Suggestion] Load apps in Landscape mode #11
Browse files Browse the repository at this point in the history
  • Loading branch information
hugeBlack committed Dec 13, 2024
1 parent 386ae51 commit 0385e3d
Show file tree
Hide file tree
Showing 11 changed files with 235 additions and 24 deletions.
10 changes: 6 additions & 4 deletions LiveContainerSwiftUI/LCAppBanner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,17 @@ struct LCAppBanner : View {
HStack {
Text(appInfo.displayName()).font(.system(size: 16)).bold()
if model.uiIsShared {
Text("lc.appBanner.shared".loc).font(.system(size: 8)).bold().padding(2)
.frame(width: 50, height:16)
Image(systemName: "arrowshape.turn.up.left.fill")
.font(.system(size: 8))
.frame(width: 16, height:16)
.background(
Capsule().fill(Color("BadgeColor"))
)
}
if model.uiIsJITNeeded {
Text("JIT").font(.system(size: 8)).bold().padding(2)
.frame(width: 30, height:16)
Image(systemName: "bolt.fill")
.font(.system(size: 8))
.frame(width: 16, height:16)
.background(
Capsule().fill(Color("JITBadgeColor"))
)
Expand Down
8 changes: 8 additions & 0 deletions LiveContainerSwiftUI/LCAppInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
#import <UIKit/UIKit.h>
#import "LCUtils.h"

typedef NS_ENUM(NSInteger, LCOrientationLock){
Disabled = 0,
Landscape = 1,
Portrait = 2
};

@interface LCAppInfo : NSObject {
NSMutableDictionary* _info;
NSString* _bundlePath;
Expand All @@ -15,10 +21,12 @@
@property bool bypassAssertBarrierOnQueue;
@property UIColor* cachedColor;
@property Signer signer;
@property LCOrientationLock orientationLock;
@property bool doUseLCBundleId;
@property NSString* selectedLanguage;
@property NSString* dataUUID;
@property NSArray<NSDictionary*>* containerInfo;
@property bool autoSaveDisabled;

- (void)setBundlePath:(NSString*)newBundlePath;
- (NSMutableDictionary*)info;
Expand Down
18 changes: 15 additions & 3 deletions LiveContainerSwiftUI/LCAppInfo.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ - (instancetype)initWithBundlePath:(NSString*)bundlePath {
if(self) {
_bundlePath = bundlePath;
_info = [NSMutableDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", bundlePath]];

_autoSaveDisabled = false;
}
return self;
}
Expand Down Expand Up @@ -187,7 +187,10 @@ - (NSDictionary *)generateWebClipConfigWithContainerId:(NSString*)containerId {
}

- (void)save {
[_info writeToFile:[NSString stringWithFormat:@"%@/Info.plist", _bundlePath] atomically:YES];
if(!_autoSaveDisabled) {
[_info writeToFile:[NSString stringWithFormat:@"%@/Info.plist", _bundlePath] atomically:YES];
}

}

- (void)preprocessBundleBeforeSiging:(NSURL *)bundleURL completion:(dispatch_block_t)completion {
Expand Down Expand Up @@ -422,7 +425,16 @@ - (Signer)signer {
}
- (void)setSigner:(Signer)newSigner {
_info[@"signer"] = [NSNumber numberWithInt:(int) newSigner];
NSLog(@"[LC] new signer = %d", (int) newSigner);
[self save];

}

- (LCOrientationLock)orientationLock {
return (LCOrientationLock) [((NSNumber*) _info[@"LCOrientationLock"]) intValue];

}
- (void)setOrientationLock:(LCOrientationLock)orientationLock {
_info[@"LCOrientationLock"] = [NSNumber numberWithInt:(int) orientationLock];
[self save];

}
Expand Down
4 changes: 4 additions & 0 deletions LiveContainerSwiftUI/LCAppListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ struct LCAppListView : View, LCAppBannerDelegate, LCAppModelDelegate {

if let appToReplace {
// copy previous configration to new app
finalNewApp.autoSaveDisabled = true
finalNewApp.isLocked = appToReplace.appInfo.isLocked
finalNewApp.isHidden = appToReplace.appInfo.isHidden
finalNewApp.isJITNeeded = appToReplace.appInfo.isJITNeeded
Expand All @@ -471,6 +472,9 @@ struct LCAppListView : View, LCAppBannerDelegate, LCAppModelDelegate {
finalNewApp.signer = appToReplace.appInfo.signer
finalNewApp.selectedLanguage = appToReplace.appInfo.selectedLanguage
finalNewApp.dataUUID = appToReplace.appInfo.dataUUID
finalNewApp.orientationLock = appToReplace.appInfo.orientationLock
finalNewApp.autoSaveDisabled = false
finalNewApp.save()
}
DispatchQueue.main.async {
if let appToReplace {
Expand Down
2 changes: 2 additions & 0 deletions LiveContainerSwiftUI/LCAppModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class LCAppModel: ObservableObject, Hashable {
@Published var uiUseLCBundleId : Bool
@Published var uiBypassAssertBarrierOnQueue : Bool
@Published var uiSigner : Signer
@Published var uiOrientationLock : LCOrientationLock
@Published var uiSelectedLanguage : String
@Published var supportedLanaguages : [String]?

Expand All @@ -52,6 +53,7 @@ class LCAppModel: ObservableObject, Hashable {
self.uiDoSymlinkInbox = appInfo.doSymlinkInbox
self.uiBypassAssertBarrierOnQueue = appInfo.bypassAssertBarrierOnQueue
self.uiSigner = appInfo.signer
self.uiOrientationLock = appInfo.orientationLock
self.uiUseLCBundleId = appInfo.doUseLCBundleId

for container in uiContainers {
Expand Down
20 changes: 20 additions & 0 deletions LiveContainerSwiftUI/LCAppSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,21 @@ struct LCAppSettingsView : View{
} footer: {
Text("lc.appSettings.useLCBundleIdDesc".loc)
}
if sharedModel.isPhone {
Section {
Picker(selection: $model.uiOrientationLock) {
Text("lc.common.disabled".loc).tag(LCOrientationLock.Disabled)
Text("lc.apppSettings.orientationLock.landscape".loc).tag(LCOrientationLock.Landscape)
Text("lc.apppSettings.orientationLock.portrait".loc).tag(LCOrientationLock.Portrait)
} label: {
Text("lc.apppSettings.orientationLock".loc)
}
.onChange(of: model.uiOrientationLock, perform: { newValue in
Task { await setOrientationLock(newValue) }
})
}
}


Section {
Toggle(isOn: $model.uiDoSymlinkInbox) {
Expand Down Expand Up @@ -477,6 +492,11 @@ struct LCAppSettingsView : View{
model.uiUseLCBundleId = doUseLCBundleId
}

func setOrientationLock(_ lock : LCOrientationLock) async {
appInfo.orientationLock = lock
model.uiOrientationLock = lock
}

func loadSupportedLanguages() {
do {
try model.loadSupportedLanguages()
Expand Down
85 changes: 68 additions & 17 deletions LiveContainerSwiftUI/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -222,23 +222,6 @@
}
}
},
"lc.appBanner.shared" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "SHARED"
}
},
"zh_CN" : {
"stringUnit" : {
"state" : "translated",
"value" : "共享"
}
}
}
},
"lc.appBanner.uninstall" : {
"extractionState" : "manual",
"localizations" : {
Expand Down Expand Up @@ -637,6 +620,57 @@
}
}
},
"lc.apppSettings.orientationLock" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Orientation Lock"
}
},
"zh_CN" : {
"stringUnit" : {
"state" : "translated",
"value" : "旋转锁定"
}
}
}
},
"lc.apppSettings.orientationLock.landscape" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Landscape"
}
},
"zh_CN" : {
"stringUnit" : {
"state" : "translated",
"value" : "横屏"
}
}
}
},
"lc.apppSettings.orientationLock.portrait" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Portrait"
}
},
"zh_CN" : {
"stringUnit" : {
"state" : "translated",
"value" : "竖屏"
}
}
}
},
"lc.appSettings.appOpenInOtherLc %@ %@" : {
"extractionState" : "manual",
"localizations" : {
Expand Down Expand Up @@ -1198,6 +1232,23 @@
}
}
},
"lc.common.disabled" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Disabled"
}
},
"zh_CN" : {
"stringUnit" : {
"state" : "translated",
"value" : "禁用"
}
}
}
},
"lc.common.done" : {
"extractionState" : "manual",
"localizations" : {
Expand Down
3 changes: 3 additions & 0 deletions LiveContainerSwiftUI/Shared.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ class SharedModel: ObservableObject {

@Published var apps : [LCAppModel] = []
@Published var hiddenApps : [LCAppModel] = []
let isPhone: Bool = {
UIDevice.current.userInterfaceIdiom == .phone
}()

func updateMultiLCStatus() {
if LCUtils.appUrlScheme()?.lowercased() != "livecontainer" {
Expand Down
1 change: 1 addition & 0 deletions TweakLoader/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ LIBRARY_NAME = TweakLoader
TweakLoader_FILES = SecItem.m TweakLoader.m NSBundle+FixCydiaSubstrate.m NSFileManager+GuestHooks.m UIKit+GuestHooks.m utils.m DocumentPicker.m FBSSerialQueue.m ../Localization.m ../fishhook/fishhook.c
TweakLoader_CFLAGS = -objc-arc
TweakLoader_INSTALL_PATH = /Applications/LiveContainer.app/Frameworks
TweakLoader_PRIVATE_FRAMEWORKS = CoreServices FrontBoard RunningBoardServices

include $(THEOS_MAKE_PATH)/library.mk
67 changes: 67 additions & 0 deletions TweakLoader/UIKit+GuestHooks.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,35 @@
#import <LocalAuthentication/LocalAuthentication.h>
#import "Localization.h"

UIInterfaceOrientation orientationLock = UIInterfaceOrientationUnknown;

__attribute__((constructor))
static void UIKitGuestHooksInit() {
swizzle(UIApplication.class, @selector(_applicationOpenURLAction:payload:origin:), @selector(hook__applicationOpenURLAction:payload:origin:));
swizzle(UIApplication.class, @selector(_connectUISceneFromFBSScene:transitionContext:), @selector(hook__connectUISceneFromFBSScene:transitionContext:));
swizzle(UIScene.class, @selector(scene:didReceiveActions:fromTransitionContext:), @selector(hook_scene:didReceiveActions:fromTransitionContext:));

NSInteger orientationLockDirection = [NSBundle.mainBundle.infoDictionary[@"LCOrientationLock"] integerValue];
if([UIDevice.currentDevice userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
switch (orientationLockDirection) {
case 1:
orientationLock = UIInterfaceOrientationLandscapeRight;
break;
case 2:
orientationLock = UIInterfaceOrientationPortrait;
break;
default:
break;
}
if(orientationLock != UIInterfaceOrientationUnknown) {
swizzle(FBSSceneParameters.class, @selector(initWithXPCDictionary:), @selector(hook_initWithXPCDictionary:));
swizzle(UIViewController.class, @selector(__supportedInterfaceOrientations), @selector(hook___supportedInterfaceOrientations));
swizzle(UIViewController.class, @selector(shouldAutorotateToInterfaceOrientation:), @selector(hook_shouldAutorotateToInterfaceOrientation:));
swizzle(UIWindow.class, @selector(setAutorotates:forceUpdateInterfaceOrientation:), @selector(hook_setAutorotates:forceUpdateInterfaceOrientation:));
}

}

}

NSString* findDefaultContainerWithBundleId(NSString* bundleId) {
Expand Down Expand Up @@ -281,6 +305,15 @@ - (void)hook__connectUISceneFromFBSScene:(id)scene transitionContext:(UIApplicat
context.payload = nil;
context.actions = nil;
[self hook__connectUISceneFromFBSScene:scene transitionContext:context];
if(orientationLock != UIInterfaceOrientationUnknown) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[LSApplicationWorkspace defaultWorkspace] openApplicationWithBundleID:@"com.apple.springboard"];
});

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[LSApplicationWorkspace defaultWorkspace] openApplicationWithBundleID:NSUserDefaults.lcMainBundle.bundleIdentifier];
});
}
}
@end

Expand Down Expand Up @@ -342,3 +375,37 @@ - (void)hook_scene:(id)scene didReceiveActions:(NSSet *)actions fromTransitionCo
[self hook_scene:scene didReceiveActions:newActions fromTransitionContext:context];
}
@end

@implementation FBSSceneParameters(LiveContainerHook)
- (instancetype)hook_initWithXPCDictionary:(NSDictionary*)dict {

FBSSceneParameters* ans = [self hook_initWithXPCDictionary:dict];
UIMutableApplicationSceneSettings* settings = [ans.settings mutableCopy];
UIMutableApplicationSceneClientSettings* clientSettings = [ans.clientSettings mutableCopy];
[settings setInterfaceOrientation:orientationLock];
[clientSettings setInterfaceOrientation:orientationLock];
ans.settings = settings;
ans.clientSettings = clientSettings;
return ans;
}
@end



@implementation UIViewController(LiveContainerHook)

- (UIInterfaceOrientationMask)hook___supportedInterfaceOrientations {
return (UIInterfaceOrientationMask)(1 << orientationLock);
}

- (BOOL)hook_shouldAutorotateToInterfaceOrientation:(NSInteger)orientation {
return YES;
}

@end

@implementation UIWindow(hook)
- (void)hook_setAutorotates:(BOOL)autorotates forceUpdateInterfaceOrientation:(BOOL)force {
[self hook_setAutorotates:YES forceUpdateInterfaceOrientation:YES];
}
@end
Loading

0 comments on commit 0385e3d

Please sign in to comment.