├── .clang-format ├── .gitignore ├── Hyperion ├── HyperionWidgets.h ├── Info.plist ├── LockWidgetsHyperionWidget.h ├── LockWidgetsHyperionWidget.m ├── Makefile └── Preferences.plist ├── Makefile ├── Preferences ├── LWRootListController.h ├── LWRootListController.m ├── LWSelectWidgetController.h ├── LWSelectWidgetController.m ├── Makefile ├── Resources │ ├── Info.plist │ ├── Root.plist │ ├── icon.png │ ├── icon@2x.png │ └── icon@3x.png ├── ctdprefs │ ├── CTDHeaderCell.m │ ├── CTDListController.m │ ├── CTDPreferenceSettings.m │ ├── CTDPrefs.h │ └── CTDTableCell.m └── entry.plist ├── Tweak ├── LockWidgets.plist ├── LockWidgetsManager.h ├── LockWidgetsManager.m ├── Makefile ├── Reachability.h ├── Tweak.h └── Tweak.xm ├── control └── liblockwidgets ├── LockWidgetsConfig.h ├── LockWidgetsConfig.m ├── LockWidgetsUtils.h ├── LockWidgetsView.h ├── LockWidgetsView.mm ├── MRYIPCCenter.h ├── MRYIPCCenter.m └── Makefile /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Chromium 2 | AlignTrailingComments: false 3 | BreakBeforeBraces: Custom 4 | BraceWrapping: 5 | AfterEnum: true 6 | AfterStruct: false 7 | AfterFunction: false 8 | ColumnLimit: 0 9 | IndentWidth: 4 10 | KeepEmptyLinesAtTheStartOfBlocks: false 11 | ObjCSpaceAfterProperty: true 12 | ObjCSpaceBeforeProtocolList: true 13 | PointerBindsToType: false 14 | SpacesBeforeTrailingComments: 1 15 | TabWidth: 4 16 | UseTab: Always 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .theos/ 2 | obj/ 3 | .DS_STORE 4 | packages/ 5 | .vscode/ -------------------------------------------------------------------------------- /Hyperion/HyperionWidgets.h: -------------------------------------------------------------------------------- 1 | // This is the protocol that your HyperionWidget class must conform to 2 | @protocol HyperionWidget 3 | 4 | // These are the required methods 5 | @required 6 | -(void)setup; // The setup method is used to initially layout your contentView 7 | -(UIView*)contentView; // Your contentView must be returned using this method 8 | -(void)layoutForPreview; // This is called when a user accesses the 'HyperionWidget Manager', so make your widget look nice in the manager here. 9 | 10 | // Optional methods 11 | @optional 12 | -(void)updateTime:(NSDate*)time; // This provides the current date as an NSDate when Hyperion updates it 13 | -(void)updateWeather:(NSDictionary*)info; // This provides current weather information when Hyperion updates it 14 | -(void)updateMusic:(NSDictionary*)info; // This provides music information when Hyperion updates it 15 | -(void)updateBattery:(NSDictionary*)info; // This provides battery information when Hyperion updates it 16 | -(void)didAppear; // This method is called when Hyperion will become visible 17 | -(void)didHide; // This method is called when Hyperion is dismissed 18 | 19 | @end -------------------------------------------------------------------------------- /Hyperion/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIdentifier 6 | me.conorthedev.lockwidgets.hyperionwidget 7 | 8 | CFBundleDisplayName 9 | LockWidgets 10 | 11 | HyperionWidgetClass 12 | LockWidgetsHyperionWidget 13 | 14 | HyperionWidgetsVersion 15 | 1 16 | 17 | 18 | -------------------------------------------------------------------------------- /Hyperion/LockWidgetsHyperionWidget.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "HyperionWidgets.h" 3 | 4 | @interface LockWidgetsHyperionWidget : NSObject 5 | 6 | @property (nonatomic, retain) UIView *contentView; 7 | 8 | @end -------------------------------------------------------------------------------- /Hyperion/LockWidgetsHyperionWidget.m: -------------------------------------------------------------------------------- 1 | #import "LockWidgetsHyperionWidget.h" 2 | 3 | @interface LockWidgetsHyperionWidget () { 4 | LockWidgetsView *lockWidgetsView; 5 | } 6 | @end 7 | 8 | @implementation LockWidgetsHyperionWidget 9 | - (void)setup { 10 | self.contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width - 10, 160)]; 11 | self.contentView.backgroundColor = [UIColor clearColor]; 12 | 13 | lockWidgetsView = [[LockWidgetsView alloc] initWithFrame:self.contentView.frame]; 14 | [lockWidgetsView refresh]; 15 | [self.contentView addSubview:lockWidgetsView]; 16 | [lockWidgetsView refresh]; 17 | } 18 | 19 | - (void)layoutForPreview { 20 | [lockWidgetsView setHidden:FALSE]; 21 | [lockWidgetsView refresh]; 22 | } 23 | @end -------------------------------------------------------------------------------- /Hyperion/Makefile: -------------------------------------------------------------------------------- 1 | ARCHS = arm64 arm64e 2 | TARGET = iphone:clang:13.0:12.4 3 | 4 | include $(THEOS)/makefiles/common.mk 5 | 6 | BUNDLE_NAME = LockWidgetsHyperion 7 | $(BUNDLE_NAME)_LIBRARIES = lockwidgets 8 | $(BUNDLE_NAME)_CFLAGS = -fobjc-arc 9 | $(BUNDLE_NAME)_FILES = $(wildcard *.m) $(wildcard *.mm) 10 | $(BUNDLE_NAME)_FRAMEWORKS = UIKit 11 | $(BUNDLE_NAME)_INSTALL_PATH = /Library/Hyperion/Widgets 12 | 13 | include $(THEOS_MAKE_PATH)/bundle.mk 14 | 15 | BUNDLE_PATH = $($(BUNDLE_NAME)_INSTALL_PATH)/$(BUNDLE_NAME).bundle 16 | 17 | internal-stage:: 18 | $(ECHO_NOTHING)mkdir -p $(THEOS_STAGING_DIR)$(BUNDLE_PATH)$(ECHO_END) 19 | $(ECHO_NOTHING)cp Info.plist $(THEOS_STAGING_DIR)$(BUNDLE_PATH)/Info.plist$(ECHO_END) 20 | $(ECHO_NOTHING)cp Preferences.plist $(THEOS_STAGING_DIR)$(BUNDLE_PATH)/Preferences.plist$(ECHO_END) 21 | 22 | after-install:: 23 | install.exec "killall -9 SpringBoard" -------------------------------------------------------------------------------- /Hyperion/Preferences.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | cell 9 | PSGroupCell 10 | label 11 | Settings 12 | 13 | 14 | title 15 | LockWidgets - Hyperion Widget 16 | 17 | 18 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include $(THEOS)/makefiles/common.mk 2 | 3 | SUBPROJECTS += liblockwidgets Tweak Preferences Hyperion 4 | 5 | include $(THEOS_MAKE_PATH)/aggregate.mk 6 | -------------------------------------------------------------------------------- /Preferences/LWRootListController.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "LWSelectWidgetController.h" 4 | #import "ctdprefs/CTDPrefs.h" 5 | 6 | @interface LWRootListController : CTDListController 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /Preferences/LWRootListController.m: -------------------------------------------------------------------------------- 1 | #include "LWRootListController.h" 2 | 3 | @implementation LWRootListController 4 | 5 | - (instancetype)init { 6 | self = [super init]; 7 | 8 | if (self) { 9 | CTDPreferenceSettings *preferenceSettings = 10 | [[CTDPreferenceSettings alloc] init]; 11 | preferenceSettings.customizeNavbar = YES; 12 | preferenceSettings.tintColor = [UIColor colorWithRed:149.0f / 255.0f 13 | green:172.0f / 255.0f 14 | blue:226.0f / 255.0f 15 | alpha:1]; 16 | preferenceSettings.barTintColor = preferenceSettings.tintColor; 17 | preferenceSettings.forceLight = YES; 18 | 19 | self.preferenceSettings = preferenceSettings; 20 | 21 | UIBarButtonItem *respringItem = 22 | [[UIBarButtonItem alloc] initWithTitle:@"Apply" 23 | style:UIBarButtonItemStylePlain 24 | target:self 25 | action:@selector(respring:)]; 26 | self.navigationItem.rightBarButtonItem = respringItem; 27 | } 28 | 29 | return self; 30 | } 31 | 32 | - (void)respring:(id)sender { 33 | pid_t pid; 34 | const char *args[] = {"killall", "backboardd", NULL}; 35 | posix_spawn(&pid, "/usr/bin/killall", NULL, NULL, (char *const *)args, NULL); 36 | } 37 | 38 | - (NSArray *)specifiers { 39 | if (!_specifiers) { 40 | _specifiers = [self loadSpecifiersFromPlistName:@"Root" target:self]; 41 | } 42 | 43 | return _specifiers; 44 | } 45 | 46 | - (void)selectWidgets:(id)sender { 47 | LWSelectWidgetController *controller = [[LWSelectWidgetController alloc] init]; 48 | [self.navigationController pushViewController:controller animated:YES]; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Preferences/LWSelectWidgetController.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | @interface LWSelectWidgetController : UIViewController 6 | @property (strong, nonatomic) UITableView *tableView; 7 | @property (strong, nonatomic) NSMutableArray *availableWidgets; 8 | @property (strong, nonatomic) NSMutableArray *selectedWidgets; 9 | @property (strong, nonatomic) NSArray *allWidgets; 10 | @property (strong, nonatomic) NSMutableDictionary *displayNames; 11 | 12 | @end -------------------------------------------------------------------------------- /Preferences/LWSelectWidgetController.m: -------------------------------------------------------------------------------- 1 | #import "LWSelectWidgetController.h" 2 | 3 | static MRYIPCCenter *center; 4 | 5 | @implementation LWSelectWidgetController 6 | 7 | - (void)viewDidLoad { 8 | [super viewDidLoad]; 9 | 10 | self.navigationItem.title = @"Select Widgets"; 11 | 12 | // Load IPC Center 13 | center = [MRYIPCCenter centerNamed:@"me.conorthedev.lockwidgetsipcserver"]; 14 | 15 | // Load data 16 | NSArray *result = [center callExternalMethod:@selector(getAllIdentifiers:) withArguments:@{}]; 17 | NSMutableArray *mutableResult = [result mutableCopy]; 18 | [mutableResult removeObjectsInArray:[LockWidgetsConfig sharedInstance].selectedWidgets]; 19 | 20 | // Save data to variables 21 | self.availableWidgets = mutableResult; 22 | self.selectedWidgets = [[LockWidgetsConfig sharedInstance].selectedWidgets mutableCopy]; 23 | self.allWidgets = [self.availableWidgets arrayByAddingObjectsFromArray:self.selectedWidgets]; 24 | self.displayNames = [center callExternalMethod:@selector(getWidgetNamesForIdentifiers:) withArguments:@{@"identifiers" : self.allWidgets}]; 25 | 26 | // Setup tableview 27 | self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped]; 28 | self.tableView.delegate = self; 29 | self.tableView.dataSource = self; 30 | 31 | [self.tableView setEditing:YES animated:NO]; 32 | [self.view addSubview:self.tableView]; 33 | } 34 | 35 | - (void)save { 36 | [LockWidgetsConfig sharedInstance].selectedWidgets = self.selectedWidgets; 37 | [[LockWidgetsConfig sharedInstance] writeValue:self.selectedWidgets forKey:@"selectedWidgets"]; 38 | } 39 | 40 | #pragma mark - UITableViewDataSource 41 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)theTableView { 42 | return 2; 43 | } 44 | 45 | - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 46 | if (section == 0) { 47 | return @"Selected Widgets"; 48 | } else { 49 | return @"Available Widgets"; 50 | } 51 | } 52 | 53 | - (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section { 54 | if (section == 0) { 55 | return [self.selectedWidgets count]; 56 | } else { 57 | return [self.availableWidgets count]; 58 | } 59 | } 60 | 61 | // the cell will be returned to the tableView 62 | - (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 63 | if (indexPath.section == 0) { 64 | static NSString *cellIdentifier = @"SelectedWidgetCell"; 65 | 66 | UITableViewCell *cell = (UITableViewCell *)[theTableView dequeueReusableCellWithIdentifier:cellIdentifier]; 67 | if (cell == nil) { 68 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; 69 | } 70 | 71 | cell.textLabel.text = self.displayNames[self.selectedWidgets[indexPath.row]][@"name"]; 72 | if (self.displayNames[self.selectedWidgets[indexPath.row]][@"image"]) { 73 | cell.imageView.image = [self rescaleImage:[UIImage imageWithData:self.displayNames[self.selectedWidgets[indexPath.row]][@"image"]] scaledToSize:CGSizeMake(30, 30)]; 74 | cell.imageView.layer.cornerRadius = 7; 75 | cell.imageView.clipsToBounds = YES; 76 | } else { 77 | cell.imageView.image = [self rescaleImage:[UIImage imageWithContentsOfFile:@"/Library/PreferenceBundles/LockWidgetsPreferences.bundle/icon@3x.png"] scaledToSize:CGSizeMake(30, 30)]; 78 | cell.imageView.layer.cornerRadius = 7; 79 | cell.imageView.clipsToBounds = YES; 80 | } 81 | 82 | return cell; 83 | } else { 84 | static NSString *cellIdentifier = @"WidgetCell"; 85 | 86 | UITableViewCell *cell = (UITableViewCell *)[theTableView dequeueReusableCellWithIdentifier:cellIdentifier]; 87 | if (cell == nil) { 88 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; 89 | } 90 | 91 | cell.textLabel.text = self.displayNames[self.availableWidgets[indexPath.row]][@"name"]; 92 | if (self.displayNames[self.availableWidgets[indexPath.row]][@"image"]) { 93 | cell.imageView.image = [self rescaleImage:[UIImage imageWithData:self.displayNames[self.availableWidgets[indexPath.row]][@"image"]] scaledToSize:CGSizeMake(30, 30)]; 94 | cell.imageView.layer.cornerRadius = 7; 95 | cell.imageView.clipsToBounds = YES; 96 | } else { 97 | cell.imageView.image = [self rescaleImage:[UIImage imageWithContentsOfFile:@"/Library/PreferenceBundles/LockWidgetsPreferences.bundle/icon@3x.png"] scaledToSize:CGSizeMake(30, 30)]; 98 | cell.imageView.layer.cornerRadius = 7; 99 | cell.imageView.clipsToBounds = YES; 100 | } 101 | 102 | return cell; 103 | } 104 | } 105 | 106 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { 107 | return YES; 108 | } 109 | 110 | - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { 111 | return UITableViewCellEditingStyleNone; 112 | } 113 | 114 | - (BOOL)tableView:(UITableView *)tableview shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath { 115 | return NO; 116 | } 117 | 118 | - (BOOL)tableView:(UITableView *)tableview canMoveRowAtIndexPath:(NSIndexPath *)indexPath { 119 | return YES; 120 | } 121 | 122 | - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath 123 | toIndexPath:(NSIndexPath *)toIndexPath { 124 | LogDebug(@"From: %@ | To: %@", fromIndexPath, toIndexPath); 125 | if (fromIndexPath != toIndexPath) { 126 | if (toIndexPath.section == 0) { 127 | if (fromIndexPath.section == toIndexPath.section) { 128 | NSString *identifier = [self.selectedWidgets objectAtIndex:fromIndexPath.row]; 129 | [self.selectedWidgets removeObject:identifier]; 130 | [self.selectedWidgets insertObject:identifier atIndex:toIndexPath.row]; 131 | } else { 132 | NSString *identifier = [self.availableWidgets objectAtIndex:fromIndexPath.row]; 133 | [self.availableWidgets removeObject:identifier]; 134 | [self.selectedWidgets insertObject:identifier atIndex:toIndexPath.row]; 135 | } 136 | } else { 137 | NSString *identifier = [self.selectedWidgets objectAtIndex:fromIndexPath.row]; 138 | [self.selectedWidgets removeObject:identifier]; 139 | [self.availableWidgets insertObject:identifier atIndex:toIndexPath.row]; 140 | } 141 | 142 | [self save]; 143 | [self.tableView reloadData]; 144 | } else { 145 | [self.tableView moveRowAtIndexPath:fromIndexPath toIndexPath:toIndexPath]; 146 | } 147 | } 148 | 149 | - (UIImage *)rescaleImage:(UIImage *)image scaledToSize:(CGSize)newSize { 150 | UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0); 151 | [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; 152 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 153 | UIGraphicsEndImageContext(); 154 | return newImage; 155 | } 156 | 157 | @end 158 | -------------------------------------------------------------------------------- /Preferences/Makefile: -------------------------------------------------------------------------------- 1 | ARCHS = arm64 arm64e 2 | TARGET = iphone:clang:13.0:12.4 3 | 4 | include $(THEOS)/makefiles/common.mk 5 | 6 | BUNDLE_NAME = LockWidgetsPreferences 7 | 8 | $(BUNDLE_NAME)_FILES = LWRootListController.m LWSelectWidgetController.m $(wildcard ctdprefs/*.m) 9 | $(BUNDLE_NAME)_INSTALL_PATH = /Library/PreferenceBundles 10 | $(BUNDLE_NAME)_LIBRARIES = lockwidgets 11 | $(BUNDLE_NAME)_FRAMEWORKS = UIKit 12 | $(BUNDLE_NAME)_PRIVATE_FRAMEWORKS = Preferences 13 | $(BUNDLE_NAME)_CFLAGS = -fobjc-arc 14 | 15 | include $(THEOS_MAKE_PATH)/bundle.mk 16 | 17 | internal-stage:: 18 | $(ECHO_NOTHING)mkdir -p $(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences$(ECHO_END) 19 | $(ECHO_NOTHING)cp entry.plist $(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences/LockWidgetsPreferences.plist$(ECHO_END) 20 | -------------------------------------------------------------------------------- /Preferences/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | LockWidgetsPreferences 9 | CFBundleIdentifier 10 | me.conorthedev.lockwidgets.preferences 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1.0 21 | NSPrincipalClass 22 | LWRootListController 23 | 24 | 25 | -------------------------------------------------------------------------------- /Preferences/Resources/Root.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | cell 9 | PSDefaultCell 10 | cellClass 11 | CTDHeaderCell 12 | title 13 | LockWidgets 14 | subtitle 15 | by ConorTheDev 16 | iconPath 17 | /Library/PreferenceBundles/LockWidgetsPreferences.bundle/icon.png 18 | height 19 | 150 20 | 21 | 22 | cell 23 | PSGroupCell 24 | label 25 | Configuration 26 | footerText 27 | Reachability and Hyperion Integration will only show the first widget in your selected widgets, this may be changed soon. Enabling / disabling requires a respring, nothing else does. 28 | 29 | 30 | cell 31 | PSSwitchCell 32 | default 33 | 34 | defaults 35 | me.conorthedev.lockwidgets.preferences 36 | key 37 | kEnabled 38 | label 39 | Enabled 40 | PostNotification 41 | me.conorthedev.lockwidgets/ReloadPreferences 42 | 43 | 44 | cell 45 | PSSwitchCell 46 | default 47 | 48 | defaults 49 | me.conorthedev.lockwidgets.preferences 50 | key 51 | kHideWhenLocked 52 | label 53 | Hide widgets when device is locked 54 | PostNotification 55 | me.conorthedev.lockwidgets/ReloadPreferences 56 | 57 | 58 | cell 59 | PSSwitchCell 60 | default 61 | 62 | defaults 63 | me.conorthedev.lockwidgets.preferences 64 | key 65 | kReachabilityEnabled 66 | label 67 | Show in Reachability 68 | PostNotification 69 | me.conorthedev.lockwidgets/ReloadPreferences 70 | 71 | 72 | cell 73 | PSGroupCell 74 | 75 | 76 | action 77 | selectWidgets: 78 | cell 79 | PSButtonCell 80 | label 81 | Select Widgets 82 | cellClass 83 | CTDTableCell 84 | 85 | 86 | title 87 | LockWidgets 88 | 89 | 90 | -------------------------------------------------------------------------------- /Preferences/Resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conorthedev/LockWidgets/8980408ce764cce9e6e9e642f5bb960f68a0cf76/Preferences/Resources/icon.png -------------------------------------------------------------------------------- /Preferences/Resources/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conorthedev/LockWidgets/8980408ce764cce9e6e9e642f5bb960f68a0cf76/Preferences/Resources/icon@2x.png -------------------------------------------------------------------------------- /Preferences/Resources/icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conorthedev/LockWidgets/8980408ce764cce9e6e9e642f5bb960f68a0cf76/Preferences/Resources/icon@3x.png -------------------------------------------------------------------------------- /Preferences/ctdprefs/CTDHeaderCell.m: -------------------------------------------------------------------------------- 1 | #import "CTDPrefs.h" 2 | 3 | @implementation CTDHeaderCell 4 | @synthesize titleLabel; 5 | @synthesize backgroundView; 6 | 7 | - (instancetype)initWithStyle:(UITableViewCellStyle)style 8 | reuseIdentifier:(NSString *)reuseIdentifier 9 | specifier:(PSSpecifier *)specifier { 10 | self = [super initWithStyle:style 11 | reuseIdentifier:reuseIdentifier 12 | specifier:specifier]; 13 | 14 | if (self) { 15 | UIView *backgroundColourView = [[UIView alloc] initWithFrame:[self frame]]; 16 | 17 | if ([CTDPreferenceSettings sharedInstance].tintColor) { 18 | backgroundColourView.backgroundColor = 19 | [CTDPreferenceSettings sharedInstance].tintColor; 20 | } else { 21 | if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"13.0")) { 22 | backgroundColourView.backgroundColor = 23 | [UIColor secondarySystemGroupedBackgroundColor]; 24 | } else { 25 | backgroundColourView.backgroundColor = [UIColor whiteColor]; 26 | } 27 | } 28 | 29 | self.iconView = [[UIImageView alloc] 30 | initWithImage:[UIImage imageWithContentsOfFile:specifier.properties 31 | [@"iconPath"]]]; 32 | self.iconView.contentMode = UIViewContentModeScaleAspectFit; 33 | [self.iconView.heightAnchor constraintEqualToConstant:65].active = true; 34 | [self.iconView.widthAnchor constraintEqualToConstant:65].active = true; 35 | 36 | UIStackView *labelStackView = [[UIStackView alloc] init]; 37 | labelStackView.axis = UILayoutConstraintAxisVertical; 38 | labelStackView.alignment = UIStackViewAlignmentLeading; 39 | labelStackView.distribution = UIStackViewDistributionEqualSpacing; 40 | labelStackView.spacing = 5; 41 | 42 | self.titleLabel = [[UILabel alloc] initWithFrame:[self frame]]; 43 | [self.titleLabel setNumberOfLines:1]; 44 | [self.titleLabel setText:specifier.properties[@"title"]]; 45 | [self.titleLabel setBackgroundColor:[UIColor clearColor]]; 46 | [self.titleLabel setShadowColor:[UIColor clearColor]]; 47 | [self.titleLabel setFont:[UIFont boldSystemFontOfSize:30]]; 48 | 49 | self.subtitleLabel = [[UILabel alloc] initWithFrame:[self frame]]; 50 | [self.subtitleLabel setNumberOfLines:1]; 51 | [self.subtitleLabel setText:specifier.properties[@"subtitle"]]; 52 | [self.subtitleLabel setBackgroundColor:[UIColor clearColor]]; 53 | [self.subtitleLabel setShadowColor:[UIColor clearColor]]; 54 | [self.subtitleLabel setFont:[UIFont systemFontOfSize:22]]; 55 | 56 | [self.titleLabel setTextColor:[UIColor whiteColor]]; 57 | [self.subtitleLabel setTextColor:[UIColor whiteColor]]; 58 | 59 | [self.titleLabel.heightAnchor constraintEqualToConstant:33].active = true; 60 | [self.subtitleLabel.heightAnchor constraintEqualToConstant:23].active = 61 | true; 62 | 63 | self.containerStackView = [[UIStackView alloc] init]; 64 | self.containerStackView.axis = UILayoutConstraintAxisHorizontal; 65 | self.containerStackView.alignment = UIStackViewAlignmentCenter; 66 | self.containerStackView.distribution = UIStackViewDistributionEqualSpacing; 67 | self.containerStackView.spacing = 10; 68 | 69 | self.containerStackView.translatesAutoresizingMaskIntoConstraints = NO; 70 | self.iconView.translatesAutoresizingMaskIntoConstraints = NO; 71 | labelStackView.translatesAutoresizingMaskIntoConstraints = NO; 72 | self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO; 73 | backgroundColourView.translatesAutoresizingMaskIntoConstraints = NO; 74 | 75 | [labelStackView addArrangedSubview:self.titleLabel]; 76 | [labelStackView addArrangedSubview:self.subtitleLabel]; 77 | [self.containerStackView addArrangedSubview:self.iconView]; 78 | [self.containerStackView addArrangedSubview:labelStackView]; 79 | [self.contentView addSubview:self.containerStackView]; 80 | [self.contentView insertSubview:backgroundColourView atIndex:0]; 81 | 82 | [backgroundColourView.centerXAnchor 83 | constraintEqualToAnchor:self.centerXAnchor] 84 | .active = true; 85 | [backgroundColourView.centerYAnchor 86 | constraintEqualToAnchor:self.centerYAnchor] 87 | .active = true; 88 | [backgroundColourView.widthAnchor constraintEqualToAnchor:self.widthAnchor] 89 | .active = true; 90 | [backgroundColourView.heightAnchor constraintEqualToConstant:150].active = 91 | true; 92 | 93 | [self.containerStackView.centerXAnchor 94 | constraintEqualToAnchor:self.centerXAnchor] 95 | .active = true; 96 | [self.containerStackView.centerYAnchor 97 | constraintEqualToAnchor:self.centerYAnchor] 98 | .active = true; 99 | [self.heightAnchor constraintEqualToConstant:150].active = true; 100 | } 101 | 102 | return self; 103 | } 104 | 105 | - (instancetype)initWithSpecifier:(PSSpecifier *)specifier { 106 | self = [self initWithStyle:UITableViewCellStyleDefault 107 | reuseIdentifier:nil 108 | specifier:specifier]; 109 | return self; 110 | } 111 | 112 | - (CGFloat)preferredHeightForWidth:(CGFloat)arg1 { 113 | return 150.0f; 114 | } 115 | 116 | @end -------------------------------------------------------------------------------- /Preferences/ctdprefs/CTDListController.m: -------------------------------------------------------------------------------- 1 | #import "CTDPrefs.h" 2 | 3 | @implementation CTDListController 4 | - (instancetype)init { 5 | self = [super init]; 6 | 7 | return self; 8 | } 9 | 10 | - (void)setNavbarThemed:(BOOL)enabled { 11 | UINavigationBar *bar = 12 | self.navigationController.navigationController.navigationBar; 13 | if (enabled && self.preferenceSettings.customizeNavbar) { 14 | bar.barTintColor = self.preferenceSettings.barTintColor; 15 | bar.tintColor = [UIColor whiteColor]; 16 | bar.barStyle = 2; 17 | bar.translucent = NO; 18 | bar.shadowImage = [UIImage new]; 19 | 20 | if (self.preferenceSettings.forceLight) { 21 | bar.barStyle = UIBarStyleBlack; 22 | [bar setTitleTextAttributes: 23 | @{NSForegroundColorAttributeName : [UIColor whiteColor]}]; 24 | } 25 | } else { 26 | bar.barTintColor = [[UINavigationBar appearance] barTintColor]; 27 | bar.tintColor = [[UINavigationBar appearance] tintColor]; 28 | bar.barStyle = [[UINavigationBar appearance] barStyle]; 29 | bar.translucent = YES; 30 | bar.shadowImage = [[UINavigationBar appearance] shadowImage]; 31 | } 32 | } 33 | 34 | - (void)viewDidLoad { 35 | [super viewDidLoad]; 36 | [self setNavbarThemed:YES]; 37 | } 38 | 39 | - (void)reloadSpecifiers { 40 | [super reloadSpecifiers]; 41 | [self setNavbarThemed:YES]; 42 | } 43 | 44 | - (void)viewDidAppear:(BOOL)animated { 45 | [super viewDidAppear:animated]; 46 | [self setNavbarThemed:YES]; 47 | } 48 | 49 | - (void)viewWillDisappear:(BOOL)animated { 50 | [super viewWillDisappear:animated]; 51 | [self setNavbarThemed:NO]; 52 | } 53 | 54 | @end -------------------------------------------------------------------------------- /Preferences/ctdprefs/CTDPreferenceSettings.m: -------------------------------------------------------------------------------- 1 | #import "CTDPrefs.h" 2 | 3 | @implementation CTDPreferenceSettings 4 | + (instancetype)sharedInstance { 5 | static CTDPreferenceSettings *sharedInstance = nil; 6 | 7 | static dispatch_once_t onceToken; 8 | dispatch_once(&onceToken, ^{ 9 | sharedInstance = [CTDPreferenceSettings alloc]; 10 | }); 11 | 12 | return sharedInstance; 13 | } 14 | 15 | - (id)init { 16 | return [CTDPreferenceSettings sharedInstance]; 17 | } 18 | @end -------------------------------------------------------------------------------- /Preferences/ctdprefs/CTDPrefs.h: -------------------------------------------------------------------------------- 1 | // Umbrella header for CTDPrefs. 2 | // Add import lines for each public header, like this: #import 3 | // Don’t forget to also add them to 4 | // CTDPrefs_PUBLIC_HEADERS in your Makefile! 5 | 6 | #import 7 | #import 8 | #import 9 | #import 10 | #import 11 | 12 | @interface UIColor (APIFix) 13 | + (UIColor *)secondarySystemGroupedBackgroundColor; // iOS 13+ 14 | @end 15 | 16 | @interface CTDHeaderCell : PSTableCell 17 | @property (nonatomic, retain) UILabel *titleLabel; 18 | @property (nonatomic, retain) UILabel *subtitleLabel; 19 | @property (nonatomic, retain) UIImageView *iconView; 20 | @property (nonatomic, retain) UIStackView *containerStackView; 21 | @property (nonatomic, retain) UIView *backgroundView; 22 | @end 23 | 24 | @interface CTDPreferenceSettings : NSObject 25 | @property (nonatomic) BOOL customizeNavbar; 26 | @property (nonatomic, strong) UIColor *barTintColor; 27 | @property (nonatomic, strong) UIColor *tintColor; 28 | @property (nonatomic) BOOL forceLight; 29 | 30 | + (instancetype)sharedInstance; 31 | - (id)init; 32 | @end 33 | 34 | @interface CTDListController : PSListController 35 | @property (nonatomic, strong) CTDPreferenceSettings *preferenceSettings; 36 | @end 37 | 38 | @interface CTDTableCell : PSTableCell 39 | @end 40 | 41 | #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) 42 | -------------------------------------------------------------------------------- /Preferences/ctdprefs/CTDTableCell.m: -------------------------------------------------------------------------------- 1 | #import "CTDPrefs.h" 2 | 3 | @implementation CTDTableCell 4 | 5 | - (instancetype)initWithStyle:(UITableViewCellStyle)style 6 | reuseIdentifier:(NSString *)reuseIdentifier 7 | specifier:(PSSpecifier *)specifier { 8 | self = [super initWithStyle:style 9 | reuseIdentifier:reuseIdentifier 10 | specifier:specifier]; 11 | if (self) { 12 | if ([CTDPreferenceSettings sharedInstance].tintColor) { 13 | self.textLabel.textColor = 14 | [CTDPreferenceSettings sharedInstance].tintColor; 15 | } 16 | } 17 | return self; 18 | } 19 | 20 | - (void)tintColorDidChange { 21 | [super tintColorDidChange]; 22 | 23 | if ([CTDPreferenceSettings sharedInstance].tintColor) { 24 | self.textLabel.textColor = [CTDPreferenceSettings sharedInstance].tintColor; 25 | } 26 | } 27 | 28 | - (void)refreshCellContentsWithSpecifier:(PSSpecifier *)specifier { 29 | [super refreshCellContentsWithSpecifier:specifier]; 30 | 31 | if ([CTDPreferenceSettings sharedInstance].tintColor) { 32 | self.textLabel.textColor = [CTDPreferenceSettings sharedInstance].tintColor; 33 | } 34 | } 35 | @end -------------------------------------------------------------------------------- /Preferences/entry.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | entry 6 | 7 | bundle 8 | LockWidgetsPreferences 9 | cell 10 | PSLinkCell 11 | detail 12 | LWRootListController 13 | icon 14 | icon.png 15 | isController 16 | 17 | label 18 | LockWidgets 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Tweak/LockWidgets.plist: -------------------------------------------------------------------------------- 1 | { Filter = { Bundles = ( "com.apple.springboard" ); }; } 2 | -------------------------------------------------------------------------------- /Tweak/LockWidgetsManager.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface UIView (RemoveConstraints) 4 | 5 | - (void)removeAllConstraints; 6 | 7 | @end 8 | 9 | @interface LockWidgetsManager : NSObject 10 | @property (nonatomic, retain) LockWidgetsView *view; 11 | + (instancetype)sharedInstance; 12 | - (id)init; 13 | - (NSArray *)getAllWidgetIdentifiers; 14 | @end 15 | 16 | @interface WGWidgetDiscoveryController : NSObject 17 | - (void)beginDiscovery; 18 | - (id)visibleWidgetIdentifiersForGroup:(id)arg1; 19 | - (id)enabledWidgetIdentifiersForAllGroups; 20 | - (id)disabledWidgetIdentifiers; 21 | @end 22 | 23 | @interface UIImage (UIApplicationIconPrivate) 24 | + (id)_iconForResourceProxy:(id)arg1 format:(int)arg2; 25 | + (id)_iconForResourceProxy:(id)arg1 variant:(int)arg2 variantsScale:(float)arg3; 26 | + (id)_applicationIconImageForBundleIdentifier:(id)arg1 roleIdentifier:(id)arg2 format:(int)arg3 scale:(float)arg4; 27 | + (id)_applicationIconImageForBundleIdentifier:(id)arg1 roleIdentifier:(id)arg2 format:(int)arg3; 28 | + (id)_applicationIconImageForBundleIdentifier:(id)arg1 format:(int)arg2 scale:(float)arg3; 29 | + (id)_applicationIconImageForBundleIdentifier:(id)arg1 format:(int)arg2; 30 | + (int)_iconVariantForUIApplicationIconFormat:(int)arg1 scale:(float *)arg2; 31 | - (id)_applicationIconImageForFormat:(int)arg1 precomposed:(BOOL)arg2 scale:(float)arg3; 32 | - (id)_applicationIconImageForFormat:(int)arg1 precomposed:(BOOL)arg2; 33 | @end 34 | -------------------------------------------------------------------------------- /Tweak/LockWidgetsManager.m: -------------------------------------------------------------------------------- 1 | #import "LockWidgetsManager.h" 2 | 3 | @implementation LockWidgetsManager 4 | 5 | + (instancetype)sharedInstance { 6 | static LockWidgetsManager *sharedInstance = nil; 7 | 8 | static dispatch_once_t onceToken; 9 | dispatch_once(&onceToken, ^{ 10 | sharedInstance = [LockWidgetsManager alloc]; 11 | }); 12 | 13 | return sharedInstance; 14 | } 15 | 16 | - (id)init { 17 | return [LockWidgetsManager sharedInstance]; 18 | } 19 | 20 | - (NSArray *)getAllWidgetIdentifiers { 21 | WGWidgetDiscoveryController *wdc = [[NSClassFromString(@"WGWidgetDiscoveryController") alloc] init]; 22 | [wdc beginDiscovery]; 23 | 24 | return [[wdc disabledWidgetIdentifiers] arrayByAddingObjectsFromArray:[wdc enabledWidgetIdentifiersForAllGroups]]; 25 | } 26 | @end 27 | 28 | @implementation UIView (RemoveConstraints) 29 | 30 | - (void)removeAllConstraints { 31 | UIView *superview = self.superview; 32 | while (superview != nil) { 33 | for (NSLayoutConstraint *c in superview.constraints) { 34 | if (c.firstItem == self || c.secondItem == self) { 35 | [superview removeConstraint:c]; 36 | } 37 | } 38 | superview = superview.superview; 39 | } 40 | 41 | [self removeConstraints:self.constraints]; 42 | self.translatesAutoresizingMaskIntoConstraints = YES; 43 | } 44 | 45 | @end -------------------------------------------------------------------------------- /Tweak/Makefile: -------------------------------------------------------------------------------- 1 | INSTALL_TARGET_PROCESSES = SpringBoard 2 | ARCHS = arm64 arm64e 3 | TARGET = iphone:clang:13.0:12.4 4 | 5 | include $(THEOS)/makefiles/common.mk 6 | 7 | TWEAK_NAME = LockWidgets 8 | 9 | LockWidgets_FILES = Tweak.xm LockWidgetsManager.m 10 | LockWidgets_CFLAGS = -fobjc-arc 11 | LockWidgets_LIBRARIES = lockwidgets 12 | 13 | include $(THEOS_MAKE_PATH)/tweak.mk 14 | -------------------------------------------------------------------------------- /Tweak/Reachability.h: -------------------------------------------------------------------------------- 1 | @interface SBReachabilityWindow : UIWindow 2 | @property (nonatomic, retain) LockWidgetsView *lwReachabilityView; 3 | @end 4 | -------------------------------------------------------------------------------- /Tweak/Tweak.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | #import 5 | #import "LockWidgetsManager.h" 6 | #import "Reachability.h" 7 | 8 | @interface LockWidgetsIPCServer : NSObject 9 | @end 10 | 11 | @interface CSNotificationAdjunctListViewController : UIViewController { 12 | UIStackView *_stackView; 13 | } 14 | 15 | @property (retain, nonatomic) UIStackView *stackView; 16 | 17 | - (void)_didUpdateDisplay; 18 | - (void)_removeItem:(id)arg1 animated:(_Bool)arg2; 19 | - (void)_insertItem:(id)arg1 animated:(_Bool)arg2; 20 | - (void)adjunctListModel:(id)arg1 didRemoveItem:(id)arg2; 21 | - (void)adjunctListModel:(id)arg1 didAddItem:(id)arg2; 22 | - (void)viewWillTransitionToSize:(struct CGSize)arg1 23 | withTransitionCoordinator:(id)arg2; 24 | - (void)viewDidLayoutSubviews; 25 | - (void)viewWillAppear:(_Bool)arg1; 26 | - (void)viewDidLoad; 27 | 28 | @end 29 | 30 | @interface SBDashBoardNotificationAdjunctListViewController : UIViewController { 31 | UIStackView *_stackView; 32 | } 33 | 34 | @property (retain, nonatomic) UIStackView *stackView; 35 | 36 | - (void)_didUpdateDisplay; 37 | - (void)_removeItem:(id)arg1 animated:(_Bool)arg2; 38 | - (void)_insertItem:(id)arg1 animated:(_Bool)arg2; 39 | - (void)adjunctListModel:(id)arg1 didRemoveItem:(id)arg2; 40 | - (void)adjunctListModel:(id)arg1 didAddItem:(id)arg2; 41 | - (void)viewWillTransitionToSize:(struct CGSize)arg1 42 | withTransitionCoordinator:(id)arg2; 43 | - (void)viewDidLayoutSubviews; 44 | - (void)viewWillAppear:(_Bool)arg1; 45 | - (void)viewDidLoad; 46 | 47 | @end 48 | 49 | @interface CSNotificationAdjunctListViewController (LockWidgets) 50 | @property (retain, nonatomic) LockWidgetsView *lockWidgetsView; 51 | - (void)refreshView; 52 | - (void)addLockWidgetsView; 53 | @end 54 | 55 | @interface SBDashBoardNotificationAdjunctListViewController (LockWidgets) 56 | @property (retain, nonatomic) LockWidgetsView *lockWidgetsView; 57 | - (void)refreshView; 58 | - (void)addLockWidgetsView; 59 | @end -------------------------------------------------------------------------------- /Tweak/Tweak.xm: -------------------------------------------------------------------------------- 1 | #import "Tweak.h" 2 | 3 | static LockWidgetsConfig *tweakConfig = nil; 4 | static LockWidgetsIPCServer *ipcServer = nil; 5 | 6 | %group reachability 7 | %hook SBReachabilityWindow 8 | %property (nonatomic, retain) LockWidgetsView *lwReachabilityView; 9 | 10 | -(instancetype)initWithWallpaperVariant:(long long)arg1 { 11 | if((self = %orig)) { 12 | self.lwReachabilityView = [[LockWidgetsView alloc] initWithFrame:CGRectMake(self.frame.origin.x + 5, self.frame.origin.y - (self.frame.size.height / 3.5), self.frame.size.width - 10, 150)]; 13 | } 14 | return self; 15 | } 16 | 17 | -(void)layoutSubviews { 18 | %orig; 19 | if(self.lwReachabilityView && tweakConfig.reachabilityEnabled) { 20 | self.userInteractionEnabled = NO; 21 | self.layer.masksToBounds = NO; 22 | self.clipsToBounds = NO; 23 | 24 | if (self.lwReachabilityView.superview == NULL) { 25 | [self addSubview:self.lwReachabilityView]; 26 | [self bringSubviewToFront:self.lwReachabilityView]; 27 | } 28 | } else { 29 | [self.lwReachabilityView removeFromSuperview]; 30 | } 31 | } 32 | 33 | %end 34 | %end 35 | 36 | /* 37 | IPC SERVER 38 | */ 39 | @implementation LockWidgetsIPCServer { 40 | MRYIPCCenter* _center; 41 | } 42 | 43 | +(void)load { 44 | [self sharedInstance]; 45 | } 46 | 47 | +(instancetype)sharedInstance { 48 | static dispatch_once_t onceToken = 0; 49 | __strong static LockWidgetsIPCServer* sharedInstance = nil; 50 | dispatch_once(&onceToken, ^{ 51 | sharedInstance = [[self alloc] init]; 52 | }); 53 | return sharedInstance; 54 | } 55 | 56 | -(instancetype)init { 57 | if ((self = [super init])) 58 | { 59 | _center = [MRYIPCCenter centerNamed:@"me.conorthedev.lockwidgetsipcserver"]; 60 | [_center addTarget:self action:@selector(getAllIdentifiers:)]; 61 | [_center addTarget:self action:@selector(getWidgetNamesForIdentifiers:)]; 62 | 63 | LogDebug(@"running server in %@", [NSProcessInfo processInfo].processName); 64 | } 65 | return self; 66 | } 67 | 68 | -(NSArray*)getAllIdentifiers:(NSDictionary*)args { 69 | return [[LockWidgetsManager sharedInstance] getAllWidgetIdentifiers]; 70 | } 71 | 72 | -(NSMutableDictionary*)getWidgetNamesForIdentifiers:(NSDictionary*)args { 73 | NSMutableDictionary *allIdentifiers = [NSMutableDictionary new]; 74 | 75 | for(NSString *identifier in args[@"identifiers"]) { 76 | NSError *error; 77 | NSExtension *extension = [NSExtension extensionWithIdentifier:identifier error:&error]; 78 | if(extension && !error) { 79 | WGWidgetInfo *widgetInfo = [[NSClassFromString(@"WGWidgetInfo") alloc] initWithExtension:extension]; 80 | if(widgetInfo) { 81 | WGWidgetHostingViewController *host = [[%c(WGWidgetHostingViewController) alloc] initWithWidgetInfo:widgetInfo delegate:nil host:nil]; 82 | 83 | if(host) { 84 | if(!host.appBundleID) { 85 | [allIdentifiers setValue:@{@"name":[widgetInfo displayName]} forKey:identifier]; 86 | } else { 87 | UIImage *image = [UIImage _applicationIconImageForBundleIdentifier:host.appBundleID format:1]; 88 | NSData *dataImage; 89 | if(image) { 90 | dataImage = UIImagePNGRepresentation(image); 91 | } 92 | 93 | if(dataImage) { 94 | [allIdentifiers setValue:@{@"name":[widgetInfo displayName], @"image": dataImage} forKey:identifier]; 95 | } else { 96 | [allIdentifiers setValue:@{@"name":[widgetInfo displayName]} forKey:identifier]; 97 | } 98 | } 99 | } 100 | } 101 | 102 | } 103 | } 104 | 105 | return allIdentifiers; 106 | } 107 | @end 108 | 109 | %group group 110 | %hook SheetViewController 111 | - (void)setAuthenticated:(BOOL)authenticated { 112 | %orig; 113 | if(authenticated) { 114 | CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), CFSTR("me.conorthedev.lockwidgets/Authenticated"), NULL, NULL, YES); 115 | } else { 116 | CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), CFSTR("me.conorthedev.lockwidgets/NotAuthenticated"), NULL, NULL, YES); 117 | } 118 | } 119 | 120 | - (void)setInScreenOffMode:(BOOL)screenOff { 121 | %orig; 122 | if(screenOff) { 123 | CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), CFSTR("me.conorthedev.lockwidgets/NotAuthenticated"), NULL, NULL, YES); 124 | } 125 | } 126 | %end 127 | %end 128 | 129 | %group ios12 130 | %hook SBDashBoardNotificationAdjunctListViewController 131 | %property (nonatomic, retain) LockWidgetsView *lockWidgetsView; 132 | -(void)viewDidLoad { 133 | %orig; 134 | [self addLockWidgetsView]; 135 | } 136 | 137 | -(void)_insertItem:(id)arg1 animated:(BOOL)arg2 { 138 | %orig; 139 | [self refreshView]; 140 | } 141 | 142 | -(void)viewDidAppear:(BOOL)animated { 143 | %orig; 144 | [self refreshView]; 145 | } 146 | 147 | -(void)_updatePresentingContent { 148 | %orig; 149 | [self refreshView]; 150 | } 151 | 152 | %new 153 | -(void)addLockWidgetsView { 154 | if(!self.lockWidgetsView) { 155 | self.lockWidgetsView = [[LockWidgetsView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 160)]; 156 | } 157 | 158 | UIStackView *stackView = [self valueForKey:@"_stackView"]; 159 | [stackView addArrangedSubview:self.lockWidgetsView]; 160 | 161 | self.lockWidgetsView.translatesAutoresizingMaskIntoConstraints = NO; 162 | [self.lockWidgetsView.centerXAnchor constraintEqualToAnchor:stackView.centerXAnchor].active = true; 163 | [self.lockWidgetsView.leadingAnchor constraintEqualToAnchor:stackView.leadingAnchor constant:5].active = true; 164 | [self.lockWidgetsView.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor constant:-5].active = true; 165 | [self.lockWidgetsView.heightAnchor constraintEqualToConstant:160].active = true; 166 | 167 | [LockWidgetsManager sharedInstance].view = self.lockWidgetsView; 168 | 169 | } 170 | 171 | %new 172 | -(void)refreshView { 173 | if(self.lockWidgetsView) { 174 | [self.lockWidgetsView refresh]; 175 | } 176 | } 177 | %end 178 | %end 179 | 180 | %group ios13 181 | %hook CSNotificationAdjunctListViewController 182 | %property (nonatomic, retain) LockWidgetsView *lockWidgetsView; 183 | -(void)viewDidLoad { 184 | %orig; 185 | [self addLockWidgetsView]; 186 | } 187 | 188 | -(void)_insertItem:(id)arg1 animated:(BOOL)arg2 { 189 | %orig; 190 | [self refreshView]; 191 | } 192 | 193 | -(void)viewDidAppear:(BOOL)animated { 194 | %orig; 195 | [self refreshView]; 196 | } 197 | 198 | -(void)_updatePresentingContent { 199 | %orig; 200 | [self refreshView]; 201 | } 202 | 203 | %new 204 | -(void)addLockWidgetsView { 205 | if(!self.lockWidgetsView) { 206 | self.lockWidgetsView = [[LockWidgetsView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 160)]; 207 | } 208 | 209 | UIStackView *stackView = [self valueForKey:@"_stackView"]; 210 | [stackView addArrangedSubview:self.lockWidgetsView]; 211 | 212 | self.lockWidgetsView.translatesAutoresizingMaskIntoConstraints = NO; 213 | [self.lockWidgetsView.centerXAnchor constraintEqualToAnchor:stackView.centerXAnchor].active = true; 214 | [self.lockWidgetsView.leadingAnchor constraintEqualToAnchor:stackView.leadingAnchor constant:5].active = true; 215 | [self.lockWidgetsView.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor constant:-5].active = true; 216 | [self.lockWidgetsView.heightAnchor constraintEqualToConstant:160].active = true; 217 | 218 | [LockWidgetsManager sharedInstance].view = self.lockWidgetsView; 219 | 220 | } 221 | 222 | %new 223 | -(void)refreshView { 224 | if(self.lockWidgetsView) { 225 | [self.lockWidgetsView refresh]; 226 | } 227 | } 228 | %end 229 | %end 230 | 231 | // Used to reload preferences from Cephei 232 | void reloadPreferences() { 233 | // Log that the preferences are being loaded 234 | LogInfo("Reloading preferences..."); 235 | 236 | // Tell our config class to reload 237 | tweakConfig = [LockWidgetsConfig sharedInstance]; 238 | [tweakConfig reloadPreferences]; 239 | 240 | // Tell our LockWidgetsView to reload 241 | [[LockWidgetsManager sharedInstance].view refresh]; 242 | // Log in the console if LockWidgets is enabled or disabled 243 | LogInfo("%s", tweakConfig.enabled ? "LockWidgets is enabled!" : "LockWidgets is disabled."); 244 | LogInfo("%s", tweakConfig.reachabilityEnabled ? "Reachability is enabled!" : "Reachability is disabled."); 245 | } 246 | 247 | // Called when the tweak is injected into a new process 248 | %ctor { 249 | // Call reloadPreferences and register notification 'me.conorthedev.lockwidgets/ReloadPreferences' to tell the tweak when it should reload it's preferences 250 | reloadPreferences(); 251 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)reloadPreferences, CFSTR("me.conorthedev.lockwidgets/ReloadPreferences"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); 252 | 253 | // If the tweak is enabled, run all code, otherwise ignore everything else 254 | if(tweakConfig.enabled) { 255 | // Start the IPC Server 256 | ipcServer = [[LockWidgetsIPCServer alloc] init]; 257 | 258 | %init(reachability); 259 | 260 | // Easier than having multiple groups, reduces the file length by half basically 261 | NSString *sheetControllerClass = @"SBDashBoardViewController"; 262 | if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"13.0")) { 263 | sheetControllerClass = @"CSCoverSheetViewController"; 264 | LogDebug(@"Current version is iOS 13 or higher, using %@", sheetControllerClass); 265 | %init(ios13); 266 | } else { 267 | LogDebug(@"Current version is iOS 12 or lower, using %@", sheetControllerClass); 268 | %init(ios12); 269 | } 270 | 271 | // Start hooking into reachability classes 272 | // Start hooking into the classes we need to hook 273 | %init(group, SheetViewController = NSClassFromString(sheetControllerClass)); 274 | } 275 | } -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: me.conorthedev.lockwidgets 2 | Name: LockWidgets 3 | Depends: mobilesubstrate, preferenceloader, firmware (= 13.0) 4 | Version: 2.0.2 5 | Architecture: iphoneos-arm 6 | Description: Access your favourite widgets, directly on your lockscreen 7 | Maintainer: ConorTheDev 8 | Author: ConorTheDev 9 | Section: Tweaks 10 | Icon: https://repo-cdn.dynastic.co/249611208846475265.fdd5c6a336e3762bd34a54af1275d1b0-256 -------------------------------------------------------------------------------- /liblockwidgets/LockWidgetsConfig.h: -------------------------------------------------------------------------------- 1 | #import "LockWidgetsUtils.h" 2 | #import "LockWidgetsView.h" 3 | 4 | @interface LockWidgetsConfig : NSObject 5 | @property (nonatomic, retain) NSArray *selectedWidgets; 6 | @property (nonatomic, retain) NSDictionary *preferences; 7 | @property (nonatomic) bool enabled; 8 | @property (nonatomic) bool reachabilityEnabled; 9 | @property (nonatomic) bool hideWhenLocked; 10 | 11 | + (instancetype)sharedInstance; 12 | - (id)init; 13 | 14 | - (void)reloadPreferences; 15 | - (void)saveValues; 16 | - (BOOL)writeValue:(NSObject *)value forKey:(NSString *)key; 17 | @end -------------------------------------------------------------------------------- /liblockwidgets/LockWidgetsConfig.m: -------------------------------------------------------------------------------- 1 | #import "LockWidgetsConfig.h" 2 | 3 | @implementation LockWidgetsConfig 4 | 5 | + (instancetype)sharedInstance { 6 | static LockWidgetsConfig *sharedInstance = nil; 7 | 8 | static dispatch_once_t onceToken; 9 | dispatch_once(&onceToken, ^{ 10 | sharedInstance = [LockWidgetsConfig alloc]; 11 | [sharedInstance reloadPreferences]; 12 | }); 13 | 14 | return sharedInstance; 15 | } 16 | 17 | - (id)init { 18 | return [LockWidgetsConfig sharedInstance]; 19 | } 20 | 21 | - (void)reloadPreferences { 22 | CFStringRef appID = CFSTR("me.conorthedev.lockwidgets.preferences"); 23 | CFArrayRef keyList = CFPreferencesCopyKeyList(appID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); 24 | if (!keyList) { 25 | LogError(@"There's been an error getting the key list! Restoring to default dictionary..."); 26 | self.preferences = @{@"kEnabled" : @YES, @"kHideWhenLocked" : @NO, @"kReachabilityEnabled" : @NO, @"selectedWidgets" : @[ @"com.apple.BatteryCenter.BatteryWidget", @"com.apple.UpNextWidget.extension" ]}; 27 | [self saveValues]; 28 | return; 29 | } 30 | self.preferences = (NSDictionary *)CFBridgingRelease(CFPreferencesCopyMultiple(keyList, appID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost)); 31 | if (!self.preferences) { 32 | LogError(@"There's been an error getting the preferences dictionary! Restoring to default dictionary..."); 33 | self.preferences = @{@"kEnabled" : @YES, @"kHideWhenLocked" : @NO, @"kReachabilityEnabled" : @NO, @"selectedWidgets" : @[ @"com.apple.BatteryCenter.BatteryWidget", @"com.apple.UpNextWidget.extension" ]}; 34 | } 35 | CFRelease(keyList); 36 | 37 | [self saveValues]; 38 | } 39 | 40 | - (void)saveValues { 41 | self.enabled = [self.preferences objectForKey:@"kEnabled"] ? [[self.preferences objectForKey:@"kEnabled"] boolValue] : YES; 42 | self.reachabilityEnabled = [self.preferences objectForKey:@"kReachabilityEnabled"] ? [[self.preferences objectForKey:@"kReachabilityEnabled"] boolValue] : NO; 43 | self.selectedWidgets = [self.preferences objectForKey:@"selectedWidgets"] ? (NSArray *)[self.preferences objectForKey:@"selectedWidgets"] : @[ @"com.apple.BatteryCenter.BatteryWidget", @"com.apple.UpNextWidget.extension" ]; 44 | self.hideWhenLocked = [self.preferences objectForKey:@"kHideWhenLocked"] ? [[self.preferences objectForKey:@"kHideWhenLocked"] boolValue] : NO; 45 | } 46 | 47 | - (BOOL)writeValue:(NSObject *)value forKey:(NSString *)key { 48 | CFPreferencesAppSynchronize((CFStringRef) @"me.conorthedev.lockwidgets.preferences"); 49 | CFPreferencesSetValue((CFStringRef)key, (CFPropertyListRef)value, (CFStringRef) @"me.conorthedev.lockwidgets.preferences", CFSTR("mobile"), kCFPreferencesAnyHost); 50 | CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), CFSTR("me.conorthedev.lockwidgets/ReloadPreferences"), NULL, NULL, YES); 51 | 52 | return YES; 53 | } 54 | @end -------------------------------------------------------------------------------- /liblockwidgets/LockWidgetsUtils.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define LogDebug(message, ...) \ 5 | NSLog((@"[LockWidgets] (DEBUG) " message), ##__VA_ARGS__) 6 | #define LogInfo(message, ...) \ 7 | NSLog((@"[LockWidgets] (INFO) " message), ##__VA_ARGS__) 8 | #define LogError(message, ...) \ 9 | NSLog((@"[LockWidgets] (ERROR) " message), ##__VA_ARGS__) 10 | 11 | #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) 12 | 13 | @interface NSUserDefaults (Private) 14 | - (instancetype)_initWithSuiteName:(NSString *)suiteName 15 | container:(NSURL *)container; 16 | @end 17 | 18 | @interface NSExtension : NSObject 19 | 20 | + (instancetype)extensionWithIdentifier:(NSString *)identifier error:(NSError **)error; 21 | 22 | - (void)beginExtensionRequestWithInputItems:(NSArray *)inputItems completion:(void (^)(NSUUID *requestIdentifier))completion; 23 | 24 | - (int)pidForRequestIdentifier:(NSUUID *)requestIdentifier; 25 | - (void)cancelExtensionRequestWithIdentifier:(NSUUID *)requestIdentifier; 26 | 27 | - (void)setRequestCancellationBlock:(void (^)(NSUUID *uuid, NSError *error))cancellationBlock; 28 | - (void)setRequestCompletionBlock:(void (^)(NSUUID *uuid, NSArray *extensionItems))completionBlock; 29 | - (void)setRequestInterruptionBlock:(void (^)(NSUUID *uuid))interruptionBlock; 30 | 31 | @end -------------------------------------------------------------------------------- /liblockwidgets/LockWidgetsView.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "LockWidgetsConfig.h" 3 | #import "LockWidgetsUtils.h" 4 | #import "substrate.h" 5 | 6 | @interface LockWidgetsView : UIView 7 | @property (strong, nonatomic) UICollectionView *collectionView; 8 | @property (nonatomic, retain) UICollectionViewFlowLayout *collectionViewLayout; 9 | @property (strong, nonatomic) NSMutableArray *widgetIdentifiers; 10 | 11 | - (void)refresh; 12 | void locked(); 13 | void unlocked(); 14 | @end 15 | 16 | @interface MTMaterialView : UIView 17 | @end 18 | 19 | @interface WGWidgetInfo : NSObject { 20 | NSPointerArray *_registeredWidgetHosts; 21 | struct { 22 | unsigned didInitializeWantsVisibleFrame : 1; 23 | } _widgetInfoFlags; 24 | BOOL _wantsVisibleFrame; 25 | NSString *_sdkVersion; 26 | NSExtension *_extension; 27 | long long _initialDisplayMode; 28 | long long _largestAllowedDisplayMode; 29 | UIImage *_icon; 30 | UIImage *_outlineIcon; 31 | NSString *_displayName; 32 | CGSize _preferredContentSize; 33 | } 34 | @property (setter=_setIcon:, getter=_icon, nonatomic, retain) UIImage *icon; //@synthesize icon=_icon - In the implementation block 35 | @property (setter=_setOutlineIcon:, getter=_outlineIcon, nonatomic, retain) UIImage *outlineIcon; //@synthesize outlineIcon=_outlineIcon - In the implementation block 36 | @property (assign, nonatomic) CGSize preferredContentSize; //@synthesize preferredContentSize=_preferredContentSize - In the implementation block 37 | @property (setter=_setDisplayName:, nonatomic, copy) NSString *displayName; //@synthesize displayName=_displayName - In the implementation block 38 | @property (getter=_sdkVersion, nonatomic, copy, readonly) NSString *sdkVersion; //@synthesize sdkVersion=_sdkVersion - In the implementation block 39 | @property (assign, setter=_setLargestAllowedDisplayMode:, nonatomic) long long largestAllowedDisplayMode; //@synthesize largestAllowedDisplayMode=_largestAllowedDisplayMode - In the implementation block 40 | @property (assign, setter=_setWantsVisibleFrame:, nonatomic) BOOL wantsVisibleFrame; //@synthesize wantsVisibleFrame=_wantsVisibleFrame - In the implementation block 41 | @property (nonatomic, readonly) NSExtension *extension; //@synthesize extension=_extension - In the implementation block 42 | @property (nonatomic, copy, readonly) NSString *widgetIdentifier; 43 | @property (nonatomic, readonly) double initialHeight; 44 | @property (nonatomic, readonly) long long initialDisplayMode; //@synthesize initialDisplayMode=_initialDisplayMode - In the implementation block 45 | + (id)_productVersion; 46 | + (double)maximumContentHeightForCompactDisplayMode; 47 | + (id)widgetInfoWithExtension:(id)arg1; 48 | + (void)_updateRowHeightForContentSizeCategory; 49 | - (id)_icon; 50 | - (NSString *)displayName; 51 | - (id)_sdkVersion; 52 | - (CGSize)preferredContentSize; 53 | - (void)setPreferredContentSize:(CGSize)arg1; 54 | - (NSExtension *)extension; 55 | - (id)initWithExtension:(id)arg1; 56 | - (void)_setDisplayName:(NSString *)arg1; 57 | - (NSString *)widgetIdentifier; 58 | - (id)_queue_iconWithSize:(CGSize)arg1 scale:(double)arg2 forWidgetWithIdentifier:(id)arg3 extension:(id)arg4; 59 | - (id)_queue_iconWithOutlineForWidgetWithIdentifier:(id)arg1 extension:(id)arg2; 60 | - (void)_resetIconsImpl; 61 | - (void)_resetIcons; 62 | - (id)widgetInfoWithExtension:(id)arg1; 63 | - (void)_setLargestAllowedDisplayMode:(long long)arg1; 64 | - (BOOL)isLinkedOnOrAfterSystemVersion:(id)arg1; 65 | - (void)requestSettingsIconWithHandler:(/*^block*/ id)arg1; 66 | - (id)_queue_iconFromWidgetBundleForWidgetWithIdentifier:(id)arg1 extension:(id)arg2; 67 | - (void)_setIcon:(UIImage *)arg1; 68 | - (void)_requestIcon:(BOOL)arg1 withHandler:(/*^block*/ id)arg2; 69 | - (id)_outlineIcon; 70 | - (void)_setOutlineIcon:(UIImage *)arg1; 71 | - (void)requestIconWithHandler:(/*^block*/ id)arg1; 72 | - (double)initialHeight; 73 | - (BOOL)wantsVisibleFrame; 74 | - (void)_setWantsVisibleFrame:(BOOL)arg1; 75 | - (void)registerWidgetHost:(id)arg1; 76 | - (void)updatePreferredContentSize:(CGSize)arg1 forWidgetHost:(id)arg2; 77 | - (long long)initialDisplayMode; 78 | - (long long)largestAllowedDisplayMode; 79 | @end 80 | 81 | @interface WGCalendarWidgetInfo : WGWidgetInfo { 82 | NSDate *_date; 83 | } 84 | @property (setter=_setDate:, nonatomic, retain) NSDate *date; //@synthesize date=_date - In the implementation block 85 | + (BOOL)isCalendarExtension:(id)arg1; 86 | - (NSDate *)date; 87 | - (id)initWithExtension:(id)arg1; 88 | - (void)_setDate:(NSDate *)arg1; 89 | - (void)_handleSignificantTimeChange:(id)arg1; 90 | - (id)_queue_iconWithSize:(CGSize)arg1 scale:(double)arg2 forWidgetWithIdentifier:(id)arg3 extension:(id)arg4; 91 | - (id)_queue_iconWithOutlineForWidgetWithIdentifier:(id)arg1 extension:(id)arg2; 92 | - (void)_resetIconsImpl; 93 | @end 94 | 95 | @protocol WGWidgetHostingViewControllerDelegate 96 | 97 | @optional 98 | - (void)remoteViewControllerDidConnectForWidget:(id)arg1; 99 | - (void)remoteViewControllerDidDisconnectForWidget:(id)arg1; 100 | - (void)remoteViewControllerViewDidAppearForWidget:(id)arg1; 101 | - (void)remoteViewControllerViewDidHideForWidget:(id)arg1; 102 | - (void)brokenViewDidAppearForWidget:(id)arg1; 103 | - (/*^block*/ id)widget:(id)arg1 didUpdatePreferredHeight:(double)arg2 completion:(/*^block*/ id)arg3; 104 | - (void)contentAvailabilityDidChangeForWidget:(id)arg1; 105 | - (void)widget:(id)arg1 didChangeLargestSupportedDisplayMode:(long long)arg2; 106 | - (BOOL)shouldRequestWidgetRemoteViewControllers; 107 | - (long long)activeLayoutModeForWidget:(id)arg1; 108 | - (UIEdgeInsets *)marginInsetsForWidget:(id)arg1; 109 | - (UIEdgeInsets *)layoutMarginForWidget:(id)arg1; 110 | - (BOOL)managingContainerIsVisibleForWidget:(id)arg1; 111 | - (CGRect *)visibleFrameForWidget:(id)arg1; 112 | @required 113 | - (CGSize *)maxSizeForWidget:(id)arg1 forDisplayMode:(long long)arg2; 114 | - (void)registerWidgetForRefreshEvents:(id)arg1; 115 | - (void)unregisterWidgetForRefreshEvents:(id)arg1; 116 | @end 117 | 118 | @protocol WGWidgetHostingViewControllerHost 119 | 120 | @optional 121 | - (long long)userSpecifiedDisplayModeForWidget:(id)arg1; 122 | - (void)widget:(id)arg1 didChangeUserSpecifiedDisplayMode:(long long)arg2; 123 | - (long long)largestAvailableDisplayModeForWidget:(id)arg1; 124 | - (void)widget:(id)arg1 didChangeLargestAvailableDisplayMode:(long long)arg2; 125 | - (void)widget:(id)arg1 didEncounterProblematicSnapshotAtURL:(id)arg2; 126 | - (void)widget:(id)arg1 didRemoveSnapshotAtURL:(id)arg2; 127 | - (BOOL)shouldPurgeArchivedSnapshotsForWidget:(id)arg1; 128 | - (BOOL)shouldPurgeNonCAMLSnapshotsForWidget:(id)arg1; 129 | - (BOOL)shouldPurgeNonASTCSnapshotsForWidget:(id)arg1; 130 | - (BOOL)shouldRemoveSnapshotWhenNotVisibleForWidget:(id)arg1; 131 | @end 132 | 133 | @interface WGWidgetLifeCycleSequence : NSObject { 134 | long long _currentState; 135 | NSString *_sequenceIdentifier; 136 | WGWidgetLifeCycleSequence *_previousSequence; 137 | } 138 | @property (assign, setter=_setCurrentState:, nonatomic) long long currentState; //@synthesize currentState=_currentState - In the implementation block 139 | @property (setter=_setPreviousSequence:, getter=_previousSequence, nonatomic, retain) WGWidgetLifeCycleSequence *previousSequence; //@synthesize previousSequence=_previousSequence - In the implementation block 140 | @property (nonatomic, copy, readonly) NSString *sequenceIdentifier; //@synthesize sequenceIdentifier=_sequenceIdentifier - In the implementation block 141 | - (id)description; 142 | - (long long)currentState; 143 | - (id)transitionToState:(long long)arg1; 144 | - (BOOL)isCurrentStateAtLeast:(long long)arg1; 145 | - (id)initWithSequenceIdentifier:(id)arg1; 146 | - (void)_setPreviousSequence:(WGWidgetLifeCycleSequence *)arg1; 147 | - (NSString *)sequenceIdentifier; 148 | - (void)_setCurrentState:(long long)arg1; 149 | - (BOOL)isCurrentState:(long long)arg1; 150 | - (BOOL)_isValidTransitionToState:(long long)arg1; 151 | - (/*^block*/ id)beginTransitionToState:(long long)arg1 error:(id *)arg2; 152 | - (id)sequenceWithIdentifier:(id)arg1; 153 | - (BOOL)isCurrentStateNotYet:(long long)arg1; 154 | - (BOOL)isCurrentStateAtMost:(long long)arg1; 155 | - (id)_previousSequence; 156 | @end 157 | 158 | @class WGWidgetHostingViewController; 159 | 160 | @interface _WGWidgetRemoteViewController : UIViewController { 161 | BOOL _valid; 162 | WGWidgetHostingViewController *_managingHost; 163 | } 164 | @property (assign, setter=_setValid:, getter=_isValid, nonatomic) BOOL valid; //@synthesize valid=_valid - In the implementation block 165 | @property (assign, nonatomic) WGWidgetHostingViewController *managingHost; //@synthesize managingHost=_managingHost - In the implementation block 166 | + (id)exportedInterface; 167 | + (id)serviceViewControllerInterface; 168 | - (void)dealloc; 169 | - (id)disconnect; 170 | - (id)initWithNibName:(id)arg1 bundle:(id)arg2; 171 | - (BOOL)_isValid; 172 | - (BOOL)_canShowWhileLocked; 173 | - (void)viewServiceDidTerminateWithError:(id)arg1; 174 | - (BOOL)__shouldRemoteViewControllerFenceOperations; 175 | - (BOOL)_serviceHasScrollToTopView; 176 | - (void)__viewServiceDidRegisterScrollToTopView; 177 | - (void)__viewServiceDidUnregisterScrollToTopView; 178 | - (void)_setValid:(BOOL)arg1; 179 | - (void)__requestPreferredViewHeight:(double)arg1; 180 | - (void)__closeTransactionForAppearanceCallWithState:(int)arg1 withIdentifier:(id)arg2; 181 | - (void)__setLargestAvailableDisplayMode:(long long)arg1; 182 | - (void)_setActiveDisplayMode:(long long)arg1; 183 | - (void)_setMaximumSize:(CGSize)arg1 forDisplayMode:(long long)arg2; 184 | - (void)_openTransactionForAppearanceCallWithState:(int)arg1 withIdentifier:(id)arg2; 185 | - (void)setManagingHost:(WGWidgetHostingViewController *)arg1; 186 | - (void)_performUpdateWithReplyHandler:(/*^block*/ id)arg1; 187 | - (void)_requestEncodedLayerTreeAtURL:(id)arg1 withReplyHandler:(/*^block*/ id)arg2; 188 | - (void)_updateVisibilityState:(long long)arg1; 189 | - (void)_updateLayoutMargins:(UIEdgeInsets)arg1; 190 | - (void)_updateVisibleFrame:(CGRect)arg1 withReplyHandler:(/*^block*/ id)arg2; 191 | - (WGWidgetHostingViewController *)managingHost; 192 | @end 193 | 194 | @interface WGWidgetHostingViewController : UIViewController { 195 | BOOL _implementsPerformUpdate; 196 | BOOL _lockedOut; 197 | BOOL _disconnectsImmediately; 198 | BOOL _encodingLayerTree; 199 | BOOL _didRequestViewInset; 200 | BOOL _didUpdate; 201 | BOOL _blacklisted; 202 | BOOL _ignoringParentAppearState; 203 | WGWidgetInfo *_widgetInfo; 204 | id _delegate; 205 | id _host; 206 | long long _activeDisplayMode; 207 | double _cornerRadius; 208 | unsigned long long _maskedCorners; 209 | NSString *_appBundleID; 210 | WGWidgetLifeCycleSequence *_activeLifeCycleSequence; 211 | long long _connectionState; 212 | _WGWidgetRemoteViewController *_remoteViewController; 213 | id _extensionRequest; 214 | UIView *_contentProvidingView; 215 | NSTimer *_disconnectionTimer; 216 | /*^block*/ id _remoteViewControllerConnectionHandler; 217 | /*^block*/ id _remoteViewControllerDisconnectionHandler; 218 | NSDate *_lastUnanticipatedDisconnectionDate; 219 | NSMapTable *_openAppearanceTransactions; 220 | NSMutableDictionary *_sequenceIDsToOutstandingWidgetUpdateCompletionHandlers; 221 | CGRect _snapshotViewBounds; 222 | } 223 | @property (nonatomic, copy) NSString *appBundleID; //@synthesize appBundleID=_appBundleID - In the implementation block 224 | @property (getter=_containerIdentifier, nonatomic, copy, readonly) NSString *containerIdentifier; 225 | @property (getter=_activeLifeCycleSequence, nonatomic, readonly) WGWidgetLifeCycleSequence *activeLifeCycleSequence; //@synthesize activeLifeCycleSequence=_activeLifeCycleSequence - In the implementation block 226 | @property (assign, setter=_setConnectionState:, getter=_connectionState, nonatomic) long long connectionState; //@synthesize connectionState=_connectionState - In the implementation block 227 | @property (setter=_setRemoteViewController:, getter=_remoteViewController, nonatomic, retain) _WGWidgetRemoteViewController *remoteViewController; //@synthesize remoteViewController=_remoteViewController - In the implementation block 228 | @property (setter=_setExtensionRequest:, getter=_extensionRequest, nonatomic, copy) id extensionRequest; //@synthesize extensionRequest=_extensionRequest - In the implementation block 229 | @property (setter=_setContentProvidingView:, getter=_contentProvidingView, nonatomic, retain) UIView *contentProvidingView; //@synthesize contentProvidingView=_contentProvidingView - In the implementation block 230 | @property (assign, setter=_setSnapshotBounds:, getter=_snapshotViewBounds, nonatomic) CGRect snapshotViewBounds; //@synthesize snapshotViewBounds=_snapshotViewBounds - In the implementation block 231 | @property (assign, setter=_setEncodingLayerTree:, getter=_isEncodingLayerTree, nonatomic) BOOL encodingLayerTree; //@synthesize encodingLayerTree=_encodingLayerTree - In the implementation block 232 | @property (assign, setter=_setDidRequestViewInset:, getter=_didRequestViewInset, nonatomic) BOOL didRequestViewInset; //@synthesize didRequestViewInset=_didRequestViewInset - In the implementation block 233 | @property (assign, setter=_setDisconnectionTimer:, getter=_disconnectionTimer, nonatomic) NSTimer *disconnectionTimer; //@synthesize disconnectionTimer=_disconnectionTimer - In the implementation block 234 | @property (setter=_setRemoteViewControllerConnectionHandler:, getter=_remoteViewControllerConnectionHandler, nonatomic, copy) id remoteViewControllerConnectionHandler; //@synthesize remoteViewControllerConnectionHandler=_remoteViewControllerConnectionHandler - In the implementation block 235 | @property (setter=_setRemoteViewControllerDisconnectionHandler:, getter=_remoteViewControllerDisconnectionHandler, nonatomic, copy) id remoteViewControllerDisconnectionHandler; //@synthesize remoteViewControllerDisconnectionHandler=_remoteViewControllerDisconnectionHandler - In the implementation block 236 | @property (setter=_setLastUnanticipatedDisconnectionDate:, getter=_lastUnanticipatedDisconnectionDate, nonatomic, retain) NSDate *lastUnanticipatedDisconnectionDate; //@synthesize lastUnanticipatedDisconnectionDate=_lastUnanticipatedDisconnectionDate - In the implementation block 237 | @property (getter=_openAppearanceTransactions, nonatomic, readonly) NSMapTable *openAppearanceTransactions; //@synthesize openAppearanceTransactions=_openAppearanceTransactions - In the implementation block 238 | @property (assign, setter=_setDidUpdate:, getter=_didUpdate, nonatomic) BOOL didUpdate; //@synthesize didUpdate=_didUpdate - In the implementation block 239 | @property (assign, setter=_setImplementsPerformUpdate:, nonatomic) BOOL implementsPerformUpdate; //@synthesize implementsPerformUpdate=_implementsPerformUpdate - In the implementation block 240 | @property (assign, setter=_setBlacklisted:, getter=_isBlacklisted, nonatomic) BOOL blacklisted; //@synthesize blacklisted=_blacklisted - In the implementation block 241 | @property (setter=_setSequenceIDsToOutstandingWidgetUpdateCompletionHandlers:, getter=_sequenceIDsToOutstandingWidgetUpdateCompletionHandlers, nonatomic, retain) NSMutableDictionary *sequenceIDsToOutstandingWidgetUpdateCompletionHandlers; //@synthesize sequenceIDsToOutstandingWidgetUpdateCompletionHandlers=_sequenceIDsToOutstandingWidgetUpdateCompletionHandlers - In the implementation block 242 | @property (assign, setter=_setIgnoringParentAppearState:, getter=_isIgnoringParentAppearState, nonatomic) BOOL ignoringParentAppearState; //@synthesize ignoringParentAppearState=_ignoringParentAppearState - In the implementation block 243 | @property (nonatomic, readonly) WGWidgetInfo *widgetInfo; //@synthesize widgetInfo=_widgetInfo - In the implementation block 244 | @property (nonatomic, copy, readonly) NSString *widgetIdentifier; 245 | @property (nonatomic, copy, readonly) NSString *displayName; 246 | @property (assign, nonatomic) id delegate; //@synthesize delegate=_delegate - In the implementation block 247 | @property (assign, nonatomic) id host; //@synthesize host=_host - In the implementation block 248 | @property (nonatomic, readonly) long long largestAvailableDisplayMode; 249 | @property (nonatomic, readonly) long long activeDisplayMode; //@synthesize activeDisplayMode=_activeDisplayMode - In the implementation block 250 | @property (assign, nonatomic) long long userSpecifiedDisplayMode; 251 | @property (getter=isRemoteViewVisible, nonatomic, readonly) BOOL remoteViewVisible; 252 | @property (getter=isSnapshotLoaded, nonatomic, readonly) BOOL snapshotLoaded; 253 | @property (getter=isBrokenViewVisible, nonatomic, readonly) BOOL brokenViewVisible; 254 | @property (getter=isLockedOut, nonatomic, readonly) BOOL lockedOut; //@synthesize lockedOut=_lockedOut - In the implementation block 255 | @property (assign, nonatomic) double cornerRadius; //@synthesize cornerRadius=_cornerRadius - In the implementation block 256 | @property (assign, nonatomic) unsigned long long maskedCorners; //@synthesize maskedCorners=_maskedCorners - In the implementation block 257 | @property (assign, nonatomic) BOOL disconnectsImmediately; //@synthesize disconnectsImmediately=_disconnectsImmediately - In the implementation block 258 | + (void)setWidgetSnapshotTimestampsEnabled:(BOOL)arg1; 259 | + (BOOL)_canWidgetHostConnectRemoteViewControllerByRequestingForSequence:(id)arg1 disconnectionTimer:(id)arg2 connectionState:(long long)arg3; 260 | + (BOOL)_canWidgetHostConnectRemoteViewControllerByCancellingDisappearanceForSequence:(id)arg1; 261 | + (BOOL)_canWidgetHostRequestRemoteViewControllerForSequence:(id)arg1; 262 | + (BOOL)_canWidgetHostCaptureSnapshotForSequence:(id)arg1; 263 | + (BOOL)_canWidgetHostInsertRemoteViewForSequence:(id)arg1; 264 | + (BOOL)_canWidgetHostEndSequenceByDisconnectingRemoteViewControllerForSequence:(id)arg1; 265 | + (BOOL)_canWidgetHostDisconnectRemoteViewControllerForSequence:(id)arg1 disconnectionTimer:(id)arg2 coalesce:(BOOL)arg3; 266 | - (void)dealloc; 267 | - (id)description; 268 | - (id)delegate; 269 | - (void)setDelegate:(id)arg1; 270 | - (id)host; 271 | - (NSString *)appBundleID; 272 | - (void)setHost:(id)arg1; 273 | - (NSString *)displayName; 274 | - (id)_containerIdentifier; 275 | - (long long)_connectionState; 276 | - (void)setCornerRadius:(double)arg1; 277 | - (void)traitCollectionDidChange:(id)arg1; 278 | - (void)viewWillAppear:(BOOL)arg1; 279 | - (void)viewWillDisappear:(BOOL)arg1; 280 | - (void)setMaskedCorners:(unsigned long long)arg1; 281 | - (void)viewDidLoad; 282 | - (void)setPreferredContentSize:(CGSize)arg1; 283 | - (void)viewDidAppear:(BOOL)arg1; 284 | - (void)viewDidDisappear:(BOOL)arg1; 285 | - (double)cornerRadius; 286 | - (UIEdgeInsets)_layoutMargins; 287 | - (id)_cancelTouches; 288 | - (id)_snapshotView; 289 | - (BOOL)shouldAutomaticallyForwardAppearanceMethods; 290 | - (BOOL)_canShowWhileLocked; 291 | - (id)_remoteViewController; 292 | - (unsigned long long)maskedCorners; 293 | - (void)setAppBundleID:(NSString *)arg1; 294 | - (UIEdgeInsets)_marginInsets; 295 | - (BOOL)isLockedOut; 296 | - (NSString *)widgetIdentifier; 297 | - (void)_setLargestAvailableDisplayMode:(long long)arg1; 298 | - (BOOL)_isBlacklisted; 299 | - (id)_diskWriteQueue; 300 | - (id)initWithWidgetInfo:(id)arg1 delegate:(id)arg2 host:(id)arg3; 301 | - (WGWidgetInfo *)widgetInfo; 302 | - (BOOL)isRemoteViewVisible; 303 | - (BOOL)isSnapshotLoaded; 304 | - (void)setLockedOut:(BOOL)arg1 withExplanation:(id)arg2; 305 | - (void)invalidateCachedSnapshotWithCompletionHandler:(/*^block*/ id)arg1; 306 | - (void)invalidateCachedSnapshotWithURL:(id)arg1 completionHandler:(/*^block*/ id)arg2; 307 | - (void)_updateWidgetWithCompletionHandler:(/*^block*/ id)arg1; 308 | - (BOOL)isLinkedOnOrAfterSystemVersion:(id)arg1; 309 | - (void)requestSettingsIconWithHandler:(/*^block*/ id)arg1; 310 | - (void)requestIconWithHandler:(/*^block*/ id)arg1; 311 | - (void)setUserSpecifiedDisplayMode:(long long)arg1; 312 | - (long long)userSpecifiedDisplayMode; 313 | - (long long)largestAvailableDisplayMode; 314 | - (void)managingContainerWillAppear:(id)arg1; 315 | - (BOOL)isBrokenViewVisible; 316 | - (long long)activeDisplayMode; 317 | - (void)managingContainerDidDisappear:(id)arg1; 318 | - (void)maximumSizeDidChangeForDisplayMode:(long long)arg1; 319 | - (void)_invalidateVisibleFrame; 320 | - (void)setDisconnectsImmediately:(BOOL)arg1; 321 | - (void)_removeItemAsynchronouslyAtURL:(id)arg1; 322 | - (void)_removeAllSnapshotFilesDueToIssue:(BOOL)arg1; 323 | - (void)_updatePreferredContentSizeWithHeight:(double)arg1; 324 | - (void)_purgeLegacySnapshotsIfNecessary; 325 | - (BOOL)_shouldRemoveSnapshotWhenNotVisible; 326 | - (BOOL)_isActiveSequence:(id)arg1; 327 | - (void)_insertSnapshotWithCompletionHandler:(/*^block*/ id)arg1; 328 | - (void)_synchronizeGeometryWithSnapshot; 329 | - (void)_loadSnapshotViewFromDiskIfNecessary:(/*^block*/ id)arg1; 330 | - (CGSize)_maxSizeForDisplayMode:(long long)arg1; 331 | - (void)_rowHeightDidChange:(id)arg1; 332 | - (id)_activeLifeCycleSequence; 333 | - (void)_enqueueRemoteServiceRequest:(/*^block*/ id)arg1 withDescription:(id)arg2; 334 | - (void)setActiveDisplayMode:(long long)arg1; 335 | - (void)_invalidateSnapshotWithForce:(BOOL)arg1 removingSnapshotFilesForActiveDisplayMode:(BOOL)arg2 completionHandler:(/*^block*/ id)arg3; 336 | - (id)_widgetSnapshotURLForSnapshotIdentifier:(id)arg1 ensuringDirectoryExists:(BOOL)arg2; 337 | - (void)_insertLockedOutViewWithExplanation:(id)arg1; 338 | - (void)_endSequence:(id)arg1 withReason:(id)arg2 completion:(/*^block*/ id)arg3; 339 | - (void)_endRemoteViewControllerAppearanceTransitionIfNecessary; 340 | - (id)_lockedOutView; 341 | - (void)_setLockedOutView:(id)arg1; 342 | - (void)_beginSequenceWithReason:(id)arg1 completion:(/*^block*/ id)arg2 updateHandler:(/*^block*/ id)arg3; 343 | - (id)_openAppearanceTransactions; 344 | - (void)_endRemoteViewControllerAppearanceTransitionIfNecessaryWithCompletion:(/*^block*/ id)arg1; 345 | - (void)_validateSnapshotViewForActiveLayoutMode; 346 | - (void)_insertSnapshotViewIfAppropriate; 347 | - (void)_requestVisibilityStateUpdateForPossiblyAppearing:(BOOL)arg1 sequence:(id)arg2; 348 | - (id)_contentProvidingView; 349 | - (void)_insertContentProvidingSubview:(id)arg1 sequence:(id)arg2 completion:(/*^block*/ id)arg3; 350 | - (void)_insertAppropriateContentView; 351 | - (void)_removeAllSnapshotFilesInActiveDisplayModeForContentSizeCategory:(id)arg1; 352 | - (void)_layoutMarginsDidChange; 353 | - (void)_removeAllSnapshotFilesInActiveDisplayModeForAllButActiveUserInterfaceStyle; 354 | - (id)_proxyRequestQueue; 355 | - (void)_enqueueRequest:(/*^block*/ id)arg1 inQueue:(id)arg2 trampolinedToMainQueue:(BOOL)arg3 withDescription:(id)arg4; 356 | - (void)_initiateNewSequenceIfNecessary; 357 | - (void)_noteOutstandingUpdateRequestForSequence:(id)arg1; 358 | - (/*^block*/ id)_updateRequestForSequence:(id)arg1; 359 | - (void)_registerUpdateRequestCompletionHandler:(/*^block*/ id)arg1 forSequence:(id)arg2; 360 | - (void)_performUpdateForSequence:(id)arg1 withCompletionHandler:(/*^block*/ id)arg2; 361 | - (void)_requestInsertionOfRemoteViewAfterViewWillAppearForSequence:(id)arg1 completionHandler:(/*^block*/ id)arg2; 362 | - (void)_abortActiveSequence; 363 | - (void)_connectRemoteViewControllerForReason:(id)arg1 sequence:(id)arg2 completionHandler:(/*^block*/ id)arg3; 364 | - (void)_requestRemoteViewControllerForSequence:(id)arg1 completionHander:(/*^block*/ id)arg2; 365 | - (void)_invalidateDisconnectionTimer; 366 | - (/*^block*/ id)_remoteViewControllerConnectionHandler; 367 | - (void)_setRemoteViewControllerConnectionHandler:(/*^block*/ id)arg1; 368 | - (void)_setConnectionState:(long long)arg1; 369 | - (void)_setExtensionRequest:(id)arg1; 370 | - (void)_finishDisconnectingRemoteViewControllerForSequence:(id)arg1 error:(id)arg2 completion:(/*^block*/ id)arg3; 371 | - (id)_proxyConnectionQueue; 372 | - (id)_extensionRequest; 373 | - (void)_setRemoteViewController:(_WGWidgetRemoteViewController *)arg1; 374 | - (BOOL)implementsPerformUpdate; 375 | - (BOOL)_didUpdate; 376 | - (void)_setDidUpdate:(BOOL)arg1; 377 | - (void)_setImplementsPerformUpdate:(BOOL)arg1; 378 | - (void)_setIgnoringParentAppearState:(BOOL)arg1; 379 | - (id)_viewWillDisappearSemaphore; 380 | - (void)_setViewWillDisappearSemaphore:(id)arg1; 381 | - (void)_removeAllSnapshotFilesForActiveDisplayMode; 382 | - (void)_setSnapshotView:(id)arg1; 383 | - (void)_packageViewFromURL:(id)arg1 reply:(/*^block*/ id)arg2; 384 | - (void)_captureLayerTree:(/*^block*/ id)arg1; 385 | - (void)_beginRemoteViewControllerAppearanceTransitionIfNecessary:(BOOL)arg1 semaphore:(id)arg2 animated:(BOOL)arg3 completion:(/*^block*/ id)arg4; 386 | - (id)_snapshotIdentifierForLayoutMode:(long long)arg1; 387 | - (void)_removeItemAtURL:(id)arg1; 388 | - (void)_removeAllSnapshotFilesMatchingPredicate:(id)arg1 dueToIssue:(BOOL)arg2; 389 | - (BOOL)_isEncodingLayerTree; 390 | - (void)_setEncodingLayerTree:(BOOL)arg1; 391 | - (id)_widgetSnapshotURLForLayoutMode:(long long)arg1 ensuringDirectoryExists:(BOOL)arg2; 392 | - (void)_packageViewWithBlock:(/*^block*/ id)arg1 reply:(/*^block*/ id)arg2; 393 | - (void)_setContentProvidingView:(UIView *)arg1; 394 | - (void)_setViewWillAppearSemaphore:(id)arg1; 395 | - (id)_viewWillAppearSemaphore; 396 | - (BOOL)_canInsertRemoteView:(id *)arg1; 397 | - (CGRect)_snapshotViewBounds; 398 | - (BOOL)_managingContainerIsVisible; 399 | - (BOOL)disconnectsImmediately; 400 | - (void)_disconnectRemoteViewControllerForReason:(id)arg1 sequence:(id)arg2 coalesce:(BOOL)arg3 completionHandler:(/*^block*/ id)arg4; 401 | - (void)_captureSnapshotAndBeginDisappearanceTransitionForSequence:(id)arg1 completionHandler:(/*^block*/ id)arg2; 402 | - (BOOL)_hasOutstandingUpdateRequestForSequence:(id)arg1; 403 | - (void)_scheduleDisconnectionTimerForSequence:(id)arg1 endTransitionBlock:(/*^block*/ id)arg2 completion:(/*^block*/ id)arg3; 404 | - (void)_enqueueDisconnectionRequestForSequence:(id)arg1 endTransitionBlock:(/*^block*/ id)arg2 completion:(/*^block*/ id)arg3; 405 | - (void)_disconnectRemoteViewControllerForSequence:(id)arg1 completion:(/*^block*/ id)arg2; 406 | - (void)_setRemoteViewControllerDisconnectionHandler:(/*^block*/ id)arg1; 407 | - (void)widget:(id)arg1 didTerminateWithError:(id)arg2; 408 | - (void)_attemptReconnectionAfterUnanticipatedDisconnection; 409 | - (void)_disconnectionTimerDidFire:(id)arg1; 410 | - (void)_setBlacklisted:(BOOL)arg1; 411 | - (void)_insertBrokenView; 412 | - (void)_setLastUnanticipatedDisconnectionDate:(NSDate *)arg1; 413 | - (id)_brokenView; 414 | - (void)_setBrokenView:(id)arg1; 415 | - (void)handleReconnectionRequest:(id)arg1; 416 | - (/*^block*/ id)_remoteViewControllerDisconnectionHandler; 417 | - (void)_setupRequestQueue; 418 | - (id)_widgetSnapshotURLForSnapshotIdentifier:(id)arg1; 419 | - (void)_setSnapshotBounds:(CGRect)arg1; 420 | - (BOOL)_didRequestViewInset; 421 | - (void)_setDidRequestViewInset:(BOOL)arg1; 422 | - (id)_disconnectionTimer; 423 | - (void)_setDisconnectionTimer:(NSTimer *)arg1; 424 | - (id)_lastUnanticipatedDisconnectionDate; 425 | - (id)_sequenceIDsToOutstandingWidgetUpdateCompletionHandlers; 426 | - (void)_setSequenceIDsToOutstandingWidgetUpdateCompletionHandlers:(NSMutableDictionary *)arg1; 427 | - (BOOL)_isIgnoringParentAppearState; 428 | @end 429 | 430 | @interface WGWidgetPlatterView : UIView { 431 | MTMaterialView *_backgroundView; 432 | MTMaterialView *_headerBackgroundView; 433 | double _cornerRadius; 434 | BOOL _adjustsFontForContentSizeCategory; 435 | BOOL _contentViewHitTestingDisabled; 436 | BOOL _backgroundHidden; 437 | BOOL _showingMoreContent; 438 | NSString *_materialGroupNameBase; 439 | WGWidgetHostingViewController *_widgetHost; 440 | UIView *_contentView; 441 | unsigned long long _clippingEdge; 442 | double _overrideHeightForLayingOutContentView; 443 | double _topMarginForLayout; 444 | long long _buttonMode; 445 | } 446 | @property (setter=_setContentView:, nonatomic, retain) UIView *contentView; //@synthesize contentView=_contentView - In the implementation block 447 | @property (assign, nonatomic) WGWidgetHostingViewController *widgetHost; //@synthesize widgetHost=_widgetHost - In the implementation block 448 | @property (assign, getter=isContentViewHitTestingDisabled, nonatomic) BOOL contentViewHitTestingDisabled; //@synthesize contentViewHitTestingDisabled=_contentViewHitTestingDisabled - In the implementation block 449 | @property (assign, nonatomic) unsigned long long clippingEdge; //@synthesize clippingEdge=_clippingEdge - In the implementation block 450 | @property (assign, getter=isBackgroundHidden, nonatomic) BOOL backgroundHidden; //@synthesize backgroundHidden=_backgroundHidden - In the implementation block 451 | @property (assign, nonatomic) double overrideHeightForLayingOutContentView; //@synthesize overrideHeightForLayingOutContentView=_overrideHeightForLayingOutContentView - In the implementation block 452 | @property (assign, nonatomic) double topMarginForLayout; //@synthesize topMarginForLayout=_topMarginForLayout - In the implementation block 453 | @property (assign, nonatomic) long long buttonMode; //@synthesize buttonMode=_buttonMode - In the implementation block 454 | @property (nonatomic, readonly) UIButton *showMoreButton; 455 | @property (assign, getter=isShowingMoreContent, nonatomic) BOOL showingMoreContent; //@synthesize showingMoreContent=_showingMoreContent - In the implementation block 456 | @property (assign, getter=isShowMoreButtonVisible, nonatomic) BOOL showMoreButtonVisible; 457 | @property (nonatomic, readonly) UIButton *addWidgetButton; 458 | @property (assign, getter=isAddWidgetButtonVisible, nonatomic) BOOL addWidgetButtonVisible; 459 | @property (readonly) unsigned long long hash; 460 | @property (readonly) Class superclass; 461 | @property (copy, readonly) NSString *description; 462 | @property (copy, readonly) NSString *debugDescription; 463 | @property (assign, nonatomic) BOOL adjustsFontForContentSizeCategory; //@synthesize adjustsFontForContentSizeCategory=_adjustsFontForContentSizeCategory - In the implementation block 464 | @property (nonatomic, copy) NSString *preferredContentSizeCategory; 465 | @property (nonatomic, copy) NSString *materialGroupNameBase; //@synthesize materialGroupNameBase=_materialGroupNameBase - In the implementation block 466 | @property (nonatomic, copy, readonly) NSArray *requiredVisualStyleCategories; 467 | + (double)contentBaselineToBoundsBottomWithWidth:(double)arg1; 468 | - (CGSize)_contentSize; 469 | - (UIView *)contentView; 470 | - (CGSize)intrinsicContentSize; 471 | - (id)initWithFrame:(CGRect)arg1; 472 | - (CGSize)sizeThatFits:(CGSize)arg1; 473 | - (void)layoutSubviews; 474 | - (void)_setContinuousCornerRadius:(double)arg1; 475 | - (double)_continuousCornerRadius; 476 | - (void)willRemoveSubview:(id)arg1; 477 | - (void)setAdjustsFontForContentSizeCategory:(BOOL)arg1; 478 | - (void)_setContentView:(UIView *)arg1; 479 | - (BOOL)adjustsFontForContentSizeCategory; 480 | - (id)visualStylingProviderForCategory:(long long)arg1; 481 | - (long long)buttonMode; 482 | - (void)setButtonMode:(long long)arg1; 483 | - (WGWidgetHostingViewController *)widgetHost; 484 | - (void)setWidgetHost:(WGWidgetHostingViewController *)arg1; 485 | - (void)_layoutContentView; 486 | - (void)setBackgroundHidden:(BOOL)arg1; 487 | - (void)setAddWidgetButtonVisible:(BOOL)arg1; 488 | - (UIButton *)addWidgetButton; 489 | - (NSArray *)requiredVisualStyleCategories; 490 | - (void)setVisualStylingProvider:(id)arg1 forCategory:(long long)arg2; 491 | - (void)setTopMarginForLayout:(double)arg1; 492 | - (double)topMarginForLayout; 493 | - (void)_handleIconButton:(id)arg1; 494 | - (void)_updateUtilityButtonForMode:(long long)arg1; 495 | - (CGSize)sizeThatFitsContentWithSize:(CGSize)arg1; 496 | - (void)_configureHeaderViewsIfNecessary; 497 | - (BOOL)_isUtilityButtonVisible; 498 | - (void)_setUtilityButtonVisible:(BOOL)arg1; 499 | - (void)_updateUtilityButtonForMoreContentState:(BOOL)arg1; 500 | - (void)_configureBackgroundMaterialViewIfNecessary; 501 | - (void)_layoutHeaderViews; 502 | - (UIButton *)showMoreButton; 503 | - (void)_updateShowMoreButtonImage; 504 | - (BOOL)adjustForContentSizeCategoryChange; 505 | - (void)_updateHeaderContentViewVisualStyling; 506 | - (CGRect)_headerFrameForBounds:(CGRect)arg1; 507 | - (void)setShowingMoreContent:(BOOL)arg1; 508 | - (void)_handleAddWidget:(id)arg1; 509 | - (void)_toggleShowMore:(id)arg1; 510 | - (void)setShowMoreButtonVisible:(BOOL)arg1; 511 | - (BOOL)isShowingMoreContent; 512 | - (CGSize)contentSizeForSize:(CGSize)arg1; 513 | - (NSString *)materialGroupNameBase; 514 | - (void)setMaterialGroupNameBase:(NSString *)arg1; 515 | - (CGSize)minimumSizeThatFits:(CGSize)arg1; 516 | - (void)setContentViewHitTestingDisabled:(BOOL)arg1; 517 | - (void)setClippingEdge:(unsigned long long)arg1; 518 | - (BOOL)isShowMoreButtonVisible; 519 | - (BOOL)isAddWidgetButtonVisible; 520 | - (void)setOverrideHeightForLayingOutContentView:(double)arg1; 521 | - (void)iconDidInvalidate:(id)arg1; 522 | - (BOOL)isContentViewHitTestingDisabled; 523 | - (unsigned long long)clippingEdge; 524 | - (BOOL)isBackgroundHidden; 525 | - (double)overrideHeightForLayingOutContentView; 526 | @end -------------------------------------------------------------------------------- /liblockwidgets/LockWidgetsView.mm: -------------------------------------------------------------------------------- 1 | #import "LockWidgetsView.h" 2 | 3 | bool deviceLocked = YES; 4 | LockWidgetsView *globalSelf; 5 | 6 | @implementation LockWidgetsView 7 | @synthesize collectionView; 8 | @synthesize widgetIdentifiers; 9 | 10 | - (id)initWithFrame:(CGRect)frame { 11 | self = [super initWithFrame:frame]; 12 | 13 | if (self) { 14 | globalSelf = self; 15 | // Setup the widgetIdentifiers with some default values if it's not set 16 | if (!widgetIdentifiers) { 17 | widgetIdentifiers = [[LockWidgetsConfig sharedInstance].selectedWidgets mutableCopy]; 18 | } 19 | 20 | self.collectionViewLayout = [[UICollectionViewFlowLayout alloc] init]; 21 | self.collectionViewLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; 22 | self.collectionViewLayout.itemSize = CGSizeMake(frame.size.width - 4, 150); 23 | self.collectionViewLayout.estimatedItemSize = CGSizeMake(frame.size.width - 4, 150); 24 | self.collectionViewLayout.minimumLineSpacing = 5; 25 | 26 | self.collectionView = [[UICollectionView alloc] initWithFrame:frame collectionViewLayout:self.collectionViewLayout]; 27 | self.collectionView.dataSource = self; 28 | self.collectionView.delegate = self; 29 | 30 | self.collectionView.translatesAutoresizingMaskIntoConstraints = NO; 31 | self.collectionView.backgroundColor = [UIColor clearColor]; 32 | self.collectionView.layer.cornerRadius = 13; 33 | self.collectionView.layer.masksToBounds = true; 34 | self.collectionView.pagingEnabled = YES; 35 | self.collectionView.contentSize = CGSizeMake(([widgetIdentifiers count] * frame.size.width - 4) + 100, 150); 36 | 37 | [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"WidgetCell"]; 38 | 39 | [self addSubview:self.collectionView]; 40 | 41 | [NSLayoutConstraint activateConstraints:@[ 42 | [self.collectionView.topAnchor constraintEqualToAnchor:self.topAnchor], 43 | [self.collectionView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor], 44 | [self.collectionView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor], 45 | [self.collectionView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor], 46 | ]]; 47 | 48 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)unlocked, CFSTR("me.conorthedev.lockwidgets/Authenticated"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); 49 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)locked, CFSTR("me.conorthedev.lockwidgets/NotAuthenticated"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); 50 | } 51 | 52 | return self; 53 | } 54 | 55 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 56 | UICollectionViewCell *cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:@"WidgetCell" forIndexPath:indexPath]; 57 | 58 | if ([widgetIdentifiers count] == 0) { 59 | for (UIView *view in cell.contentView.subviews) { 60 | [view removeFromSuperview]; 61 | } 62 | 63 | UILabel *textLabel = [[UILabel alloc] 64 | initWithFrame:CGRectMake(0, 0, self.frame.size.width - 4, 150)]; 65 | textLabel.textAlignment = NSTextAlignmentCenter; 66 | textLabel.textColor = [UIColor whiteColor]; 67 | textLabel.numberOfLines = 0; 68 | [textLabel setText:@"Please select a widget to show"]; 69 | [cell.contentView addSubview:textLabel]; 70 | 71 | UIBlurEffect *blurEffect; 72 | if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"13.0")) { 73 | blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleRegular]; 74 | } else { 75 | blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; 76 | } 77 | 78 | UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; 79 | blurEffectView.frame = CGRectMake(0, 0, self.frame.size.width - 4, 150); 80 | blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 81 | blurEffectView.layer.cornerRadius = 13.0f; 82 | blurEffectView.clipsToBounds = YES; 83 | 84 | [cell.contentView insertSubview:blurEffectView atIndex:0]; 85 | 86 | return cell; 87 | } 88 | 89 | if ((deviceLocked && [LockWidgetsConfig sharedInstance].hideWhenLocked)) { 90 | for (UIView *view in cell.contentView.subviews) { 91 | [view removeFromSuperview]; 92 | } 93 | 94 | UILabel *textLabel = [[UILabel alloc] 95 | initWithFrame:CGRectMake(0, 0, self.frame.size.width - 4, 150)]; 96 | textLabel.textAlignment = NSTextAlignmentCenter; 97 | textLabel.textColor = [UIColor whiteColor]; 98 | textLabel.numberOfLines = 0; 99 | [textLabel setText:@"Unlock device to show widgets view"]; 100 | [cell.contentView addSubview:textLabel]; 101 | 102 | UIBlurEffect *blurEffect; 103 | if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"13.0")) { 104 | blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleRegular]; 105 | } else { 106 | blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; 107 | } 108 | 109 | UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; 110 | blurEffectView.frame = CGRectMake(0, 0, self.frame.size.width - 4, 150); 111 | blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 112 | blurEffectView.layer.cornerRadius = 13.0f; 113 | blurEffectView.clipsToBounds = YES; 114 | 115 | [cell.contentView insertSubview:blurEffectView atIndex:0]; 116 | 117 | return cell; 118 | } 119 | 120 | if (!NSClassFromString(@"WGWidgetPlatterView")) { 121 | for (UIView *view in cell.contentView.subviews) { 122 | [view removeFromSuperview]; 123 | } 124 | 125 | UILabel *textLabel = [[UILabel alloc] 126 | initWithFrame:CGRectMake(0, 0, self.frame.size.width - 4, 150)]; 127 | textLabel.textAlignment = NSTextAlignmentCenter; 128 | textLabel.textColor = [UIColor whiteColor]; 129 | textLabel.numberOfLines = 0; 130 | [textLabel setText:@"Unable to load widgets view"]; 131 | [cell.contentView addSubview:textLabel]; 132 | 133 | UIBlurEffect *blurEffect; 134 | if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"13.0")) { 135 | blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleRegular]; 136 | } else { 137 | blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; 138 | } 139 | 140 | UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; 141 | blurEffectView.frame = CGRectMake(0, 0, self.frame.size.width - 4, 150); 142 | blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 143 | blurEffectView.layer.cornerRadius = 13.0f; 144 | blurEffectView.clipsToBounds = YES; 145 | 146 | [cell.contentView insertSubview:blurEffectView atIndex:0]; 147 | 148 | return cell; 149 | } 150 | 151 | NSError *error; 152 | NSString *identifier = [widgetIdentifiers objectAtIndex:indexPath.row]; 153 | NSExtension *extension = [NSExtension extensionWithIdentifier:identifier error:&error]; 154 | 155 | WGWidgetInfo *widgetInfo = [[NSClassFromString(@"WGWidgetInfo") alloc] initWithExtension:extension]; 156 | WGWidgetHostingViewController *widgetHost = [[NSClassFromString(@"WGWidgetHostingViewController") alloc] initWithWidgetInfo:widgetInfo delegate:nil host:nil]; 157 | 158 | WGWidgetPlatterView *platterView = [[NSClassFromString(@"WGWidgetPlatterView") alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width - 4, 150)]; 159 | 160 | if ([identifier isEqualToString:@"com.apple.UpNextWidget.extension"] || [identifier isEqualToString:@"com.apple.mobilecal.widget"]) { 161 | WGCalendarWidgetInfo *widgetInfoCal = [[NSClassFromString(@"WGCalendarWidgetInfo") alloc] initWithExtension:extension]; 162 | NSDate *now = [NSDate date]; 163 | [widgetInfoCal setValue:now forKey:@"_date"]; 164 | [platterView setWidgetHost:[[NSClassFromString(@"WGWidgetHostingViewController") alloc] initWithWidgetInfo:widgetInfoCal delegate:nil host:nil]]; 165 | } else { 166 | [platterView setWidgetHost:widgetHost]; 167 | } 168 | 169 | for (UIView *view in cell.contentView.subviews) { 170 | [view removeFromSuperview]; 171 | } 172 | 173 | [cell.contentView addSubview:platterView]; 174 | 175 | if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"13.0")) { 176 | // Fix on iOS 13 for the dark header being the old style 177 | MTMaterialView *header = MSHookIvar(platterView, "_headerBackgroundView"); 178 | [header removeFromSuperview]; 179 | } 180 | 181 | if ([identifier isEqualToString:@"com.apple.UpNextWidget.extension"] || [identifier isEqualToString:@"com.apple.mobilecal.widget"]) { 182 | WGCalendarWidgetInfo *widgetInfoCal = [[NSClassFromString(@"WGCalendarWidgetInfo") alloc] initWithExtension:extension]; 183 | NSDate *now = [NSDate date]; 184 | [widgetInfoCal setValue:now forKey:@"_date"]; 185 | [platterView setWidgetHost:[[NSClassFromString(@"WGWidgetHostingViewController") alloc] initWithWidgetInfo:widgetInfoCal delegate:nil host:nil]]; 186 | } else { 187 | [platterView setWidgetHost:[[NSClassFromString(@"WGWidgetHostingViewController") alloc] initWithWidgetInfo:widgetInfo delegate:nil host:nil]]; 188 | } 189 | 190 | return cell; 191 | } 192 | 193 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 194 | if ([widgetIdentifiers count] == 0) { 195 | return 1; 196 | } 197 | return [widgetIdentifiers count]; 198 | } 199 | 200 | - (BOOL)_canShowWhileLocked { 201 | return YES; 202 | } 203 | 204 | - (BOOL)collectionView:(UICollectionView *)collectionView 205 | shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath { 206 | return NO; 207 | } 208 | 209 | - (CGFloat)collectionView:(UICollectionView *)collectionView 210 | layout:(UICollectionViewLayout *)collectionViewLayout 211 | minimumLineSpacingForSectionAtIndex:(NSInteger)section { 212 | return 5; 213 | } 214 | 215 | - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { 216 | return UIEdgeInsetsMake(0, 2, 0, 2); 217 | } 218 | 219 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { 220 | return CGSizeMake(self.frame.size.width - 4, self.frame.size.height + 5); 221 | } 222 | 223 | - (void)refresh { 224 | if (!NSClassFromString(@"WGWidgetPlatterView")) { 225 | return; 226 | } 227 | LogDebug(@"Refreshing..."); 228 | widgetIdentifiers = [[LockWidgetsConfig sharedInstance].selectedWidgets mutableCopy]; 229 | 230 | LogDebug(@"Identififers: %@", widgetIdentifiers); 231 | [self.collectionView reloadData]; 232 | 233 | for (UICollectionViewCell *cell in self.collectionView.visibleCells) { 234 | UIView *contentView = cell.contentView; 235 | WGWidgetPlatterView *platterView = (WGWidgetPlatterView *)contentView; 236 | 237 | if (![platterView isKindOfClass:NSClassFromString(@"WGWidgetPlatterView")]) { 238 | LogError(@"platterView is not WGWidgetPlatterView!! returning before crash..."); 239 | return; 240 | } 241 | 242 | // Parse the widget information from the identifier 243 | NSError *error; 244 | NSString *identifier = widgetIdentifiers[[self.collectionView indexPathForCell:cell].row]; 245 | NSExtension *extension = [NSExtension extensionWithIdentifier:identifier error:&error]; 246 | 247 | WGWidgetInfo *widgetInfo = [[NSClassFromString(@"WGWidgetInfo") alloc] initWithExtension:extension]; 248 | WGWidgetHostingViewController *widgetHost = [[NSClassFromString(@"WGWidgetHostingViewController") alloc] initWithWidgetInfo:widgetInfo delegate:nil host:nil]; 249 | 250 | if ([identifier isEqualToString:@"com.apple.UpNextWidget.extension"] || [identifier isEqualToString:@"com.apple.mobilecal.widget"]) { 251 | WGCalendarWidgetInfo *widgetInfoCal = [[NSClassFromString(@"WGCalendarWidgetInfo") alloc] initWithExtension:extension]; 252 | NSDate *now = [NSDate date]; 253 | [widgetInfoCal setValue:now forKey:@"_date"]; 254 | [platterView setWidgetHost:[[NSClassFromString(@"WGWidgetHostingViewController") alloc] initWithWidgetInfo:widgetInfoCal delegate:nil host:nil]]; 255 | } else { 256 | [platterView setWidgetHost:widgetHost]; 257 | } 258 | } 259 | } 260 | 261 | void locked() { 262 | deviceLocked = YES; 263 | [globalSelf refresh]; 264 | } 265 | 266 | void unlocked() { 267 | deviceLocked = NO; 268 | [globalSelf refresh]; 269 | } 270 | 271 | // FUCK SAFEMODE SHIT YE YE 272 | - (void)setContentHost:(id)arg1 { 273 | } 274 | - (void)setSizeToMimic:(CGSize)arg1 { 275 | } 276 | - (void)_layoutContentHost { 277 | } 278 | - (CGSize)sizeToMimic { 279 | return self.frame.size; 280 | } 281 | - (id)contentHost { 282 | return nil; 283 | } 284 | - (void)_updateSizeToMimic { 285 | } 286 | - (unsigned long long)_optionsForMainOverlay { 287 | return 0; 288 | } 289 | 290 | @end 291 | -------------------------------------------------------------------------------- /liblockwidgets/MRYIPCCenter.h: -------------------------------------------------------------------------------- 1 | @interface MRYIPCCenter : NSObject 2 | @property (nonatomic, readonly) NSString* centerName; 3 | +(instancetype)centerNamed:(NSString*)name; 4 | -(void)addTarget:(id)target action:(SEL)action; 5 | //asynchronously call a void method 6 | -(void)callExternalVoidMethod:(SEL)method withArguments:(NSDictionary*)args; 7 | //synchronously call a method and recieve the return value 8 | -(id)callExternalMethod:(SEL)method withArguments:(NSDictionary*)args; 9 | //asynchronously call a method and receive the return value in the completion handler 10 | -(void)callExternalMethod:(SEL)method withArguments:(NSDictionary*)args completion:(void(^)(id))completionHandler; 11 | 12 | //deprecated 13 | -(void)registerMethod:(SEL)selector withTarget:(id)target; 14 | @end 15 | -------------------------------------------------------------------------------- /liblockwidgets/MRYIPCCenter.m: -------------------------------------------------------------------------------- 1 | @import Foundation; 2 | #import "MRYIPCCenter.h" 3 | 4 | #define THROW(...) [self _throwException:[NSString stringWithFormat:__VA_ARGS__] fromMethod:_cmd] 5 | 6 | @interface NSDistributedNotificationCenter : NSNotificationCenter 7 | + (instancetype)defaultCenter; 8 | @end 9 | 10 | @interface _MRYIPCMethod : NSObject 11 | @property (nonatomic, readonly) id target; 12 | @property (nonatomic, readonly) SEL selector; 13 | - (instancetype)initWithTarget:(id)target selector:(SEL)selector; 14 | @end 15 | 16 | @implementation _MRYIPCMethod 17 | - (instancetype)initWithTarget:(id)target selector:(SEL)selector { 18 | if ((self = [self init])) { 19 | _target = target; 20 | _selector = selector; 21 | } 22 | return self; 23 | } 24 | @end 25 | 26 | @interface MRYIPCCenter () 27 | - (instancetype)initWithName:(NSString *)name; 28 | - (void)_throwException:(NSString *)msg fromMethod:(SEL)method; 29 | - (NSString *)_messageNameForSelector:(SEL)selector; 30 | - (NSString *)_messageReplyNameForSelector:(SEL)selector uuid:(NSString *)uuid; 31 | @end 32 | 33 | @implementation MRYIPCCenter { 34 | NSDistributedNotificationCenter *_notificationCenter; 35 | NSMutableDictionary *_methods; 36 | } 37 | 38 | + (instancetype)centerNamed:(NSString *)name { 39 | return [[self alloc] initWithName:name]; 40 | } 41 | 42 | - (instancetype)initWithName:(NSString *)name { 43 | if ((self = [self init])) { 44 | if (!name.length) 45 | THROW(@"a center name must be supplied"); 46 | _centerName = name; 47 | _notificationCenter = [NSDistributedNotificationCenter defaultCenter]; 48 | _methods = [NSMutableDictionary new]; 49 | } 50 | return self; 51 | } 52 | 53 | - (void)addTarget:(id)target action:(SEL)action { 54 | if (!action || !strlen(sel_getName(action))) 55 | THROW(@"method cannot be null"); 56 | if (!target) 57 | THROW(@"target cannot be null"); 58 | 59 | NSString *messageName = [self _messageNameForSelector:action]; 60 | if (_methods[messageName]) 61 | THROW(@"method already registered: %@", NSStringFromSelector(action)); 62 | 63 | _MRYIPCMethod *method = [[_MRYIPCMethod alloc] initWithTarget:target selector:action]; 64 | _methods[messageName] = method; 65 | 66 | [_notificationCenter addObserver:self selector:@selector(_messageReceived:) name:messageName object:nil]; 67 | } 68 | 69 | //deprecated 70 | - (void)registerMethod:(SEL)selector withTarget:(id)target { 71 | [self addTarget:target action:selector]; 72 | } 73 | 74 | - (void)callExternalVoidMethod:(SEL)method withArguments:(NSDictionary *)args { 75 | NSString *messageName = [self _messageNameForSelector:method]; 76 | NSDictionary *userInfo = args ? @{@"args" : args} : @{}; 77 | [_notificationCenter postNotificationName:messageName object:nil userInfo:userInfo]; 78 | } 79 | 80 | - (id)callExternalMethod:(SEL)method withArguments:(NSDictionary *)args { 81 | __block id returnValue = nil; 82 | dispatch_semaphore_t sema = dispatch_semaphore_create(0); 83 | [self callExternalMethod:method 84 | withArguments:args 85 | completion:^(id ret) { 86 | returnValue = ret; 87 | dispatch_semaphore_signal(sema); 88 | }]; 89 | dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); 90 | return returnValue; 91 | } 92 | 93 | - (void)callExternalMethod:(SEL)method withArguments:(NSDictionary *)args completion:(void (^)(id))completionHandler { 94 | NSString *replyUUID = [NSUUID UUID].UUIDString; 95 | NSString *messageName = [self _messageNameForSelector:method]; 96 | NSString *replyMessageName = [self _messageReplyNameForSelector:method uuid:replyUUID]; 97 | __weak NSDistributedNotificationCenter *weakNotificationCenter = _notificationCenter; 98 | NSOperationQueue *operationQueue = [NSOperationQueue new]; 99 | __block id observer = [_notificationCenter addObserverForName:replyMessageName 100 | object:nil 101 | queue:operationQueue 102 | usingBlock:^(NSNotification *notification) { 103 | completionHandler(notification.userInfo[@"returnValue"]); 104 | [weakNotificationCenter removeObserver:observer]; 105 | observer = nil; 106 | }]; 107 | NSMutableDictionary *userInfo = [NSMutableDictionary new]; 108 | userInfo[@"replyUUID"] = replyUUID; 109 | if (args) 110 | userInfo[@"args"] = args; 111 | [_notificationCenter postNotificationName:messageName object:nil userInfo:userInfo]; 112 | } 113 | 114 | - (NSString *)_messageNameForSelector:(SEL)selector { 115 | return [NSString stringWithFormat:@"MRYIPCCenter-%@-%@", _centerName, NSStringFromSelector(selector)]; 116 | } 117 | 118 | - (NSString *)_messageReplyNameForSelector:(SEL)selector uuid:(NSString *)uuid { 119 | return [NSString stringWithFormat:@"MRYIPCCenter-%@-%@-reply-%@", _centerName, NSStringFromSelector(selector), uuid]; 120 | } 121 | 122 | - (void)_messageReceived:(NSNotification *)notification { 123 | NSString *messageName = notification.name; 124 | _MRYIPCMethod *method = _methods[messageName]; 125 | if (!method) 126 | THROW(@"unrecognised message: %@", messageName); 127 | 128 | //call method: 129 | NSMethodSignature *signature = [method.target methodSignatureForSelector:method.selector]; 130 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; 131 | invocation.target = method.target; 132 | invocation.selector = method.selector; 133 | NSDictionary *args = notification.userInfo[@"args"]; 134 | NSString *replyUUID = notification.userInfo[@"replyUUID"]; 135 | if (args) 136 | [invocation setArgument:&args atIndex:2]; 137 | [invocation invoke]; 138 | 139 | //send reply: 140 | if (replyUUID.length) { 141 | __unsafe_unretained id weakReturnValue = nil; 142 | if (strcmp(signature.methodReturnType, "v") != 0) 143 | [invocation getReturnValue:&weakReturnValue]; 144 | id returnValue = weakReturnValue; 145 | NSDictionary *replyDict = returnValue ? @{@"returnValue" : returnValue} : @{}; 146 | NSString *replyMessageName = [self _messageReplyNameForSelector:method.selector uuid:replyUUID]; 147 | [_notificationCenter postNotificationName:replyMessageName object:nil userInfo:replyDict]; 148 | } 149 | } 150 | 151 | - (void)_throwException:(NSString *)msg fromMethod:(SEL)method { 152 | NSString *reason = [NSString stringWithFormat:@"-[%@ %@] - %@", [self class], NSStringFromSelector(method), msg]; 153 | NSException *myException = [NSException exceptionWithName:@"MRYIPCException" reason:reason userInfo:nil]; 154 | @throw myException; 155 | } 156 | 157 | - (void)dealloc { 158 | [_notificationCenter removeObserver:self]; 159 | } 160 | @end 161 | -------------------------------------------------------------------------------- /liblockwidgets/Makefile: -------------------------------------------------------------------------------- 1 | ARCHS = arm64 arm64e 2 | TARGET = iphone:clang:13.0:12.4 3 | 4 | include $(THEOS)/makefiles/common.mk 5 | 6 | LIBRARY_NAME = liblockwidgets 7 | 8 | liblockwidgets_FILES = LockWidgetsView.mm LockWidgetsConfig.m MRYIPCCenter.m 9 | liblockwidgets_CFLAGS = -fobjc-arc 10 | 11 | include $(THEOS_MAKE_PATH)/library.mk 12 | 13 | after-all:: 14 | mkdir -p $(THEOS)/include/liblockwidgets 15 | cp *.h $(THEOS)/include/liblockwidgets 16 | cp ../.theos/obj/debug/liblockwidgets.dylib $(THEOS)/lib/liblockwidgets.dylib --------------------------------------------------------------------------------