├── .gitignore ├── GcUniversal ├── GcColorPickerUtils.h ├── GcColorUtils.h ├── GcImagePickerUtils.h ├── GcImageUtils.h ├── HelperFunctions.h ├── libgcuniversal.tbd ├── libgcuniversalrootless.tbd └── module.modulemap ├── Preview.jpg ├── README.md └── install.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /GcUniversal/GcColorPickerUtils.h: -------------------------------------------------------------------------------- 1 | // By: @MrGcGamer 2 | #import 3 | #import 4 | 5 | @interface GcColorPickerUtils : NSObject 6 | + (NSString *)hexStringFromColor:(UIColor *)color ; 7 | + (UIColor *)colorWithHex:(NSString *)hexStr ; 8 | + (UIColor *)colorFromDefaults:(NSString *)defaults withKey:(NSString *)key ; 9 | + (UIColor *)colorFromDefaults:(NSString *)defaults withKey:(NSString *)key fallback:(NSString *)fallback ; 10 | @end -------------------------------------------------------------------------------- /GcUniversal/GcColorUtils.h: -------------------------------------------------------------------------------- 1 | // By: @MrGcGamer 2 | #import 3 | 4 | typedef NS_ENUM(NSUInteger, ColorComponent) { 5 | kColorRed, 6 | kColorGreen, 7 | kColorBlue, 8 | kColorHue, 9 | kColorSaturation, 10 | kColorBrightness, 11 | kColorAlpha 12 | }; 13 | 14 | @interface UIColor (colorUtils) 15 | + (UIColor *)closestColorFromArray:(NSArray *)colors toColor:(UIColor *)color ; 16 | - (CGFloat)getColorComponent:(ColorComponent)component ; 17 | - (CGFloat)rgbValue; 18 | - (BOOL)isGrayscale; 19 | - (BOOL)isNearGrayscale; 20 | - (BOOL)isDarkColor; 21 | - (BOOL)isLightColor; 22 | @end -------------------------------------------------------------------------------- /GcUniversal/GcImagePickerUtils.h: -------------------------------------------------------------------------------- 1 | // By: @MrGcGamer 2 | #import 3 | #import 4 | 5 | typedef NS_CLOSED_ENUM(NSUInteger, ImageSizingMode) { 6 | kSizingModeMin, 7 | kSizingModeMax 8 | }; 9 | 10 | typedef struct { 11 | ImageSizingMode sizingMode; 12 | CGFloat size; 13 | CGFloat scale; 14 | } ImageSizingConfig; 15 | 16 | @interface GcImagePickerUtils : NSObject 17 | + (UIImage *)imageFromDefaults:(NSString *)defaults withKey:(NSString *)key ; 18 | + (UIImage *)imageFromDefaults:(NSString *)defaults withKey:(NSString *)key error:(NSError **)error ; 19 | + (UIImage *)thumbnailFromDefaults:(NSString *)defaults withKey:(NSString *)key forSizingMode:(ImageSizingMode)sizingMode ; 20 | + (UIImage *)thumbnailFromDefaults:(NSString *)defaults withKey:(NSString *)key forConfig:(ImageSizingConfig)sizingConfig ; 21 | + (UIImage *)thumbnailFromDefaults:(NSString *)defaults withKey:(NSString *)key maxSize:(CGFloat)maxSize scale:(CGFloat)scale ; 22 | + (UIImage *)thumbnailFromDefaults:(NSString *)defaults withKey:(NSString *)key minSize:(CGFloat)minSize scale:(CGFloat)scale ; 23 | + (UIImage *)thumbnailForURL:(NSURL *)url withConfig:(ImageSizingConfig)config ; 24 | + (UIImage *)thumbnailForURL:(NSURL *)url maxSize:(CGFloat)maxSize scale:(CGFloat)scale ; 25 | + (UIImage *)thumbnailForURL:(NSURL *)url minSize:(CGFloat)minSize scale:(CGFloat)scale ; 26 | + (NSData *)dataFromDefaults:(NSString *)defaults withKey:(NSString *)key ; 27 | + (NSData *)dataFromDefaults:(NSString *)defaults withKey:(NSString *)key error:(NSError **)error ; 28 | + (NSURL *)videoURLFromDefaults:(NSString *)defaults withKey:(NSString *)key ; 29 | + (BOOL)isVideoInDefaults:(NSString *)defaults withKey:(NSString *)key ; 30 | + (BOOL)isImageInDefaults:(NSString *)defaults withKey:(NSString *)key ; 31 | + (BOOL)setImage:(UIImage *)image forDefaults:(NSString *)defaults withKey:(NSString *)key png:(BOOL)png ; 32 | @end -------------------------------------------------------------------------------- /GcUniversal/GcImageUtils.h: -------------------------------------------------------------------------------- 1 | // By: @MrGcGamer 2 | #import 3 | 4 | FOUNDATION_EXPORT BOOL isHEICSupported(void); 5 | #if __IPHONE_OS_VERSION_MAX_ALLOWED < 170000 6 | FOUNDATION_EXPORT NSData *UIImageHEICRepresentation(UIImage *image, CGFloat compressionQuality); 7 | #endif 8 | 9 | @interface UIImage (imageUtils) 10 | + (UIImage *)stockImgForBundleID:(NSString *)arg1 ; 11 | + (UIImage *)thumbnailForImage:(UIImage *)image withMaxSize:(CGFloat)maxSize scale:(CGFloat)scale ; 12 | - (UIColor *)averageColor; 13 | - (NSArray *)dominantColors; 14 | @end 15 | -------------------------------------------------------------------------------- /GcUniversal/HelperFunctions.h: -------------------------------------------------------------------------------- 1 | // By: @MrGcGamer 2 | #import 3 | NS_ASSUME_NONNULL_BEGIN 4 | @interface UIView (fconstraints) 5 | -(void)anchorTop:(nullable NSLayoutAnchor *)top 6 | leading:(nullable NSLayoutAnchor *)leading 7 | bottom:(nullable NSLayoutAnchor *)bottom 8 | trailing:(nullable NSLayoutAnchor *)trailing 9 | padding:(UIEdgeInsets)insets 10 | size:(CGSize)size ; 11 | 12 | -(void)anchorTop:(nullable NSLayoutAnchor *)top 13 | leading:(nullable NSLayoutAnchor *)leading 14 | bottom:(nullable NSLayoutAnchor *)bottom 15 | trailing:(nullable NSLayoutAnchor *)trailing 16 | padding:(UIEdgeInsets)insets ; 17 | 18 | -(void)anchorTop:(nullable NSLayoutAnchor *)top 19 | leading:(nullable NSLayoutAnchor *)leading 20 | bottom:(nullable NSLayoutAnchor *)bottom 21 | trailing:(nullable NSLayoutAnchor *)trailing 22 | size:(CGSize)size ; 23 | 24 | -(void)anchorTop:(nullable NSLayoutAnchor *)top 25 | leading:(nullable NSLayoutAnchor *)leading 26 | bottom:(nullable NSLayoutAnchor *)bottom 27 | trailing:(nullable NSLayoutAnchor *)trailing ; 28 | 29 | -(void)anchorCenterX:(nullable NSLayoutAnchor *)centerX 30 | centerY:(nullable NSLayoutAnchor *)centerY 31 | size:(CGSize)size ; 32 | 33 | -(void)anchorCenterX:(nullable NSLayoutAnchor *)centerX 34 | centerY:(nullable NSLayoutAnchor *)centerY ; 35 | 36 | -(void)anchorEqualsToView:(UIView *)view padding:(UIEdgeInsets)insets ; 37 | -(void)anchorEqualsToView:(UIView *)view ; 38 | @end 39 | 40 | FOUNDATION_EXPORT void logToFile(NSString *path, NSString *log); 41 | 42 | NS_ASSUME_NONNULL_END -------------------------------------------------------------------------------- /GcUniversal/libgcuniversal.tbd: -------------------------------------------------------------------------------- 1 | --- !tapi-tbd 2 | tbd-version: 4 3 | targets: [ arm64-ios, arm64e-ios ] 4 | flags: [ not_app_extension_safe ] 5 | install-name: '/usr/lib/libgcuniversal.dylib' 6 | current-version: 0 7 | compatibility-version: 0 8 | exports: 9 | - targets: [ arm64-ios, arm64e-ios ] 10 | symbols: [ _UIImageHEICRepresentation, _isHEICSupported, _logToFile ] 11 | objc-classes: [ GcColorPickerCell, GcColorPickerUtils, GcDuoTwitterCell, GcImagePickerCell, 12 | GcImagePickerUtils, GcSocialCell, GcSymbolPickerCell, GcTwitterCell ] 13 | ... 14 | -------------------------------------------------------------------------------- /GcUniversal/libgcuniversalrootless.tbd: -------------------------------------------------------------------------------- 1 | --- !tapi-tbd 2 | tbd-version: 4 3 | targets: [ arm64-ios, arm64e-ios ] 4 | flags: [ not_app_extension_safe ] 5 | install-name: '@rpath/libgcuniversal.dylib' 6 | current-version: 0 7 | compatibility-version: 0 8 | exports: 9 | - targets: [ arm64-ios, arm64e-ios ] 10 | symbols: [ _UIImageHEICRepresentation, _isHEICSupported, _logToFile ] 11 | objc-classes: [ GcColorPickerCell, GcColorPickerUtils, GcDuoTwitterCell, GcImagePickerCell, 12 | GcImagePickerUtils, GcSocialCell, GcSymbolPickerCell, GcTwitterCell ] 13 | ... 14 | -------------------------------------------------------------------------------- /GcUniversal/module.modulemap: -------------------------------------------------------------------------------- 1 | module GcUniversal { 2 | module ColorPickerUtils { 3 | header "GcColorPickerUtils.h" 4 | export * 5 | } 6 | module ColorUtils { 7 | header "GcColorUtils.h" 8 | export * 9 | } 10 | module ImagePickerUtils { 11 | header "GcImagePickerUtils.h" 12 | export * 13 | } 14 | module ImageUtils { 15 | header "GcImageUtils.h" 16 | export * 17 | } 18 | module HelperFunctions { 19 | header "HelperFunctions.h" 20 | export * 21 | } 22 | } -------------------------------------------------------------------------------- /Preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrGcGamer/LibGcUniversalDocumentation/ca0a2521f6b0da427cee284bd09925da8a0bf295/Preview.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LibGcUniversal 2 | LibGcUniversal is a universal library for tweak development I made because I think it's annoying to add a new library for every little thing. 3 | 4 | ## Contents of LibGcUniversal 5 | - [GcColorPickerCell](#implementation-of-a-color-picker) 6 | - [GcImagePickerCell](#implementation-of-an-image-picker) 7 | - [GcSymbolPickerCell](#implementation-of-a-symbol-picker) 8 | - [Getting picker results from Sandboxed processes](#getting-picker-results-from-sandboxed-processes) 9 | - [GcTwitterCell](#implementation-of-a-twitter-cell) 10 | - [GcDuoTwitterCell](#implementation-of-a-duo-twitter-cell) 11 | - [GcSocialCell](#implementation-of-a-social-cell) 12 | - [Little helper methods](#using-the-helper-functions) 13 | - [Color utils](#using-the-color-utils) 14 | - [Image utils](#using-the-image-utils) 15 | - [Other](#other) 16 | 17 | # Usage 18 | 19 | ## Installation in Theos 20 | 21 | ### Automatic installation (Recommended) 22 | 23 | Run the `install.sh` script in this repository to automatically copy the necessary files. 24 | 25 | ### Manual installation 26 | 27 | 1. Download this repository 28 | 2. Copy the `libgcuniversal.tbd` into your `theos/lib` folder. 29 | 3. Copy the `libgcuniversalrootless.tbd` to `theos/lib/iphone/rootless` and rename it to `libgcuniversal.tbd`. 30 | 3. Put the `GcUniversal` folder into your `theos/include` folder. 31 | 4. Done! 32 | 33 | ## Project configuration 34 | 1. Add `TWEAKNAME_LIBRARIES = gcuniversal` to your makefiles (not needed if you only use one of the social cells for example) 35 | 2. Add `com.mrgcgamer.libgcuniversal` to the `Depends` in your `control` file 36 | 3. Done! 37 | 38 | ## Implementation of a color picker 39 | PreferenceBundle plist (Root.plist e.g.) 40 | ```xml 41 | 42 | cell 43 | PSLinkCell 44 | cellClass 45 | GcColorPickerCell 46 | label 47 | Your Color Label 48 | defaults 49 | com.your.identifier 50 | key 51 | YourColor 52 | supportsAlpha 53 | 54 | safeOnDismiss 55 | 56 | fallback 57 | ffffffff 58 | style 59 | 1 60 | 61 | ``` 62 | ### supportsAlpha 63 | The `supportsAlpha` property is optional and will default to `true` if nothing else has been specified. 64 | 65 | ### safeOnDismiss 66 | The `safeOnDismiss` property is optional and will default to `true` if nothing else has been specified. 67 | When `safeOnDismiss` is turned off, the user will have to press the `X` Button in the top right for the color to be saved, when this option is on, the color will be saved even if the color picker was dismissed via the swipe down gesture. 68 | 69 | ### fallback 70 | The `fallback` property is optional and will default to a clear color if the fallback color hasn’t been set. 71 | 72 | You may use any color hex code which conforms to one of the following color hex code notations: 73 | - `rgb` (`#FAE`) 74 | - `rgba` (`#BEEF` / `#FAE:0.69`) 75 | - `rrggbb` (`#DEADBE`) 76 | - `rrggbbaa` (`#DEADBEEF` / `#DEADBE:0.42`) 77 | 78 | ### style 79 | The `style` property is optional and will default to `0`, which is the same style used by the imagepicker (rounded corners).
80 | The `style` property can also be set to `1` which will result in the "stock" iOS style introduced in iOS 14 (the rainbow circle). NOTE: This option also works on iOS versions below iOS 14 81 | 82 | ![Preview of the styles](Preview.jpg) 83 | 84 | ### Retrieving a color (example) 85 | Once this is implemented you can then get the chosen color from within your tweak. So an example of how to retrieve the color could look something like this: 86 | 87 | ```objc 88 | #import 89 | 90 | UIColor *color = [GcColorPickerUtils colorFromDefaults:@"DEFAULTS" withKey:@"KEY"]; 91 | UIColor *colorWithFallback = [GcColorPickerUtils colorFromDefaults:@"DEFAULTS" withKey:@"KEY" fallback:@"ffffffff"]; 92 | ``` 93 | Fallback values have to condone to one of the above-mentioned notations.
94 | For other helpful methods (color - HEX conversion), take a look at [GcColorPickerUtils.h](GcUniversal/GcColorPickerUtils.h) 95 | 96 | ## Implementation of an image picker 97 | PreferenceBundle plist (Root.plist e.g.) 98 | ```xml 99 | 100 | cell 101 | PSLinkCell 102 | cellClass 103 | GcImagePickerCell 104 | label 105 | Your Image Label 106 | defaults 107 | com.your.identifier 108 | key 109 | YourImage 110 | usesPhotos 111 | 112 | usesVideos 113 | 114 | videoQuality 115 | 1 116 | 117 | ``` 118 | ### usesPhotos 119 | The `usesPhotos` property is optional and will default to `true`. 120 | ### usesVideos 121 | The `usesVideo` property is optional and will default to `false`. 122 | ### videoQuality 123 | The `videoQuality` property is optional. It impacts both media quality and storage space usage.
124 | The default value of `videoQuality` is `1`.
125 | Possible `videoQuality` values are as follows: 126 | - `0` = high quality 127 | - `1` = medium quality 128 | - `2` = low quality 129 | 130 | ### Retrieving an image (example) 131 | ```objc 132 | #import 133 | 134 | UIImage *scaledThumbnail = [GcImagePickerUtils thumbnailFromDefaults:@"DEFAULTS" withKey:@"KEY" maxSize:400 scale:2]; // scaled to maxSize, lower memory usage 135 | UIImage *thumbnail = [GcImagePickerUtils thumbnailFromDefaults:@"DEFAULTS" withKey:@"KEY"]; // lower res, lower memory usage 136 | UIImage *img = [GcImagePickerUtils imageFromDefaults:@"DEFAULTS" withKey:@"KEY"]; // full size, high memory usage 137 | ``` 138 | NOTE:
139 | It is recommended that you make yourself familiar with the [GcImagePickerUtils.h](GcUniversal/GcImagePickerUtils.h) header, to see the available methods.
140 | The `thumbnailFromDefaults:` methods should be used in most cases as the resulting images are scaled to a max size, based on the decives `scale` and `screenSize`. 141 | ```objc 142 | + (UIImage *)thumbnailFromDefaults:(NSString *)defaults withKey:(NSString *)key ; 143 | ``` 144 |
If you want to get the images data instead of the image you can use: 145 | ```objc 146 | NSData *data = [GcImagePickerUtils dataFromDefaults:@"DEFAULTS" withKey:@"KEY"]; 147 | ``` 148 | 149 | ### Retrieving a video (example) 150 | If you decided to let the user pick a video, you can retrieve an `NSURL` leading to it something like this: 151 | ```objc 152 | #import 153 | 154 | NSURL *videoURL = [GcImagePickerUtils videoURLFromDefaults:@"DEFAULTS" withKey:@"KEY"]; 155 | 156 | if (videoURL) { // this check is to prevent a crash in case the user didn't select any media 157 | // do something with the videoURL 158 | } 159 | ``` 160 | ### Getting the media type 161 | In case you give the user the ability to choose a video or an image, you can easily check which one they went for, by doing something like this: 162 | ```objc 163 | #import 164 | 165 | BOOL isVideo = [GcImagePickerUtils isVideoInDefaults:@"DEFAULTS" withKey:@"KEY"]; 166 | 167 | if (isVideo) { 168 | // do video stuff 169 | } else { 170 | // do photo stuff 171 | } 172 | ``` 173 | It is also possible to check if the user selected an image like this: 174 | ```objc 175 | BOOL isPhoto = [GcImagePickerUtils isImageInDefaults:@"DEFAULTS" withKey:@"KEY"]; 176 | ``` 177 | If you prefer that (though it doesn't make any difference which method you use). 178 | 179 | ### Programmatically setting the image selection 180 | In case you want to store some image for later reuse, you can do so using: 181 | ```objc 182 | + (BOOL)setImage:(UIImage *)image forDefaults:(NSString *)defaults withKey:(NSString *)key png:(BOOL)png ; 183 | ``` 184 | Example: 185 | ```objc 186 | #import 187 | 188 | BOOL success = [GcImagePickerUtils setImage:img forDefaults:@"com.mrgcgamer.test" withKey:@"SomeKey"]; 189 | 190 | if (success) 191 | NSLog(@"Image saved successfully"); 192 | ``` 193 | ## Implementation of a symbol picker 194 | PreferenceBundle plist (Root.plist e.g.) 195 | ```xml 196 | 197 | cell 198 | PSLinkCell 199 | cellClass 200 | GcSymbolPickerCell 201 | label 202 | Your Symbol Label 203 | defaults 204 | com.your.identifier 205 | key 206 | YourSymbol 207 | tintColor 208 | 6B10E6FF 209 | 210 | ``` 211 | The symbol picker is only supported on iOS 13+, as SFSymbols didn't exist before.
212 | If you include one in your tweak and it run on a lower iOS version, a pop up will appear, telling the user, that symbols are not supported on their iOS version.
213 | ### tintColor 214 | This is optional and allows you to specify a color, which will be used as the `tintColor` of the selected symbol in the preview. 215 | 216 | ## Stylisation of the pickers 217 | LibGcUniversal allows you to specify SFSymbols as the icon image for the cell. This functions identical to `iconImageSystem` from [Cepheis HBListController](https://hbang.github.io/libcephei/Classes/HBListController.html).
218 | (This feature requires iOS 13+ and will display nothing on lower iOS versions) 219 | ```xml 220 | 221 | cell 222 | PSLinkCell 223 | cellClass 224 | GcSOMETHINGPickerCell 225 | iconImageSystem 226 | 227 | name 228 | heart 229 | backgroundColor 230 | #ff3b30 231 | 232 | 233 | ``` 234 | ### name 235 | Required. The symbol name to use. 236 | ### weight 237 | Optional. The weight to render the symbol at. The supported values are: `ultraLight`, `thin`, `light`, `regular`, `medium`, `semibold`, `bold`, `heavy`, `black`. The default is `regular`. 238 | ### scale 239 | Optional. The scale to render the symbol at. The supported values are: `small`, `medium`, `large`. The default is `medium`. 240 | ### pointSize 241 | Optional. The equivalent font size to render the symbol at. The default is `20.0`. 242 | ### tintColor 243 | Optional. The color to render the icon in. The default is no value. If the value is not set, the default iOS blue tint color is used. When backgroundColor is set, no value means white (#ffffff) will be used. 244 | ### backgroundColor 245 | Optional. The background color to use for the symbol. When specified, the symbol will be rendered inside an icon shape of the specified background color. The symbol will be scaled down by 20% to appropriately fit the icon shape. The default is no value, which means no icon shape will be rendered. 246 | 247 | ## Getting picker results from Sandboxed processes 248 | I would suggest using Cephei if you are working in a sandboxed app, as it makes preferences mush easier and handles XPC stuff for the prefs.
249 | For images, you would probably need to set up some form of IPC, and for a video, I am not quite sure if that is possible at all, without moving it to the apps documents directory due to the fact, that videos are most likely used in an AVPlayer which uses a URL, but the AVPlayer is also going to be restricted by the sandbox and therefore not able to access the directory, where the video will be copied to, by the library, but for colors you can just use Cephei like this: 250 | ```objc 251 | HBPreferences *prefs = [[HBPreferences alloc] initWithIdentifier:@"DEFAULTS"]; 252 | 253 | NSString *colorHEX = [prefs objectForKey:@"KEY"]; 254 | UIColor *yourColor = [GcColorPickerUtils colorWithHex:colorHEX]; 255 | ``` 256 | ## Implementation of a Twitter cell 257 | PreferenceBundle plist (Root.plist e.g.) 258 | ```xml 259 | 260 | cell 261 | PSButtonCell 262 | cellClass 263 | GcTwitterCell 264 | accountLabel 265 | LabelForTheAccount 266 | account 267 | TwitterTagOfAccount 268 | URL 269 | URLToAnotherFancyImage 270 | 271 | ``` 272 | It is recommended to use a picture with a resolution of around `200x200`. 273 | ### URL 274 | `URL` is an optional value, for the link to an image to display. 275 | ### Local profile picture 276 | If don't want to use the URL, you will also need to include the profile picture of the account in the `Resources` folder of your preferences. 277 | The picture will have to have the same name as the Twitter tag of the provided account and be stored as a `.png` file. 278 | 279 | ## Implementation of a duo Twitter cell 280 | PreferenceBundle plist (Root.plist e.g.) 281 | ```xml 282 | 283 | cellClass 284 | GcDuoTwitterCell 285 | firstLabel 286 | LabelForTheFirstAccount 287 | firstAccount 288 | TwitterTagOfFirstAccount 289 | firstURL 290 | URLToSomeFancyImage 291 | secondLabel 292 | LabelForTheSecondAccount 293 | secondAccount 294 | TwitterTagOfSecondAccount 295 | secondURL 296 | URLToAnotherFancyImage 297 | 298 | ``` 299 | It is recommended to use a picture with a resolution of around `200x200`. 300 | ### URLs 301 | `firstURL` and `secondURL` are optional values, which can be set, to specify a URL to the images for each account somewhere online. 302 | If you use the URLs, make sure they link to the images directly. It is also possible to have only one image loaded using the URL and the other one using local files. 303 | ### Local profile pictures 304 | If don't want to use the URLs, you will also need to include the profile pictures of the two accounts in the `Resources` folder of your preferences. 305 | The pictures will have to have the same name as the Twitter tag of the corresponding account and be stored as `.png` files. 306 | 307 | ## Implementation of a Social Cell 308 | PreferenceBundle plist (Root.plist e.g.) 309 | ```xml 310 | 311 | cell 312 | PSButtonCell 313 | cellClass 314 | GcSocialCell 315 | userName 316 | AccountLabel 317 | subtitle 318 | someFancySubtitle 319 | accessoryType 320 | 0 321 | accessoryURL 322 | URLToAnAccessoryImage 323 | pfpURL 324 | URLToSomePFP 325 | URL 326 | URLToSomewhere 327 | 328 | ``` 329 | ### userName 330 | `userName` is a required value and will be the username displayed on the cell. 331 | ### subtitle 332 | `subtitle` is an optional value and will be displayed below the `userName` if specified. 333 | If it hasn't been specified the `userName` will be horizontally centred on the cell. In case you don't want the username to be centred but also don't want to specify a subtitle, you can specify a subtitle only containing whitespace characters. 334 | ### accessoryType 335 | `accessoryType` is an optional value, which can be specified in order to display an accessory image (the little image on the right-hand side). 336 | The default value of `accessoryType` is `0`. 337 | Possible `accessoryType` values are as follows: 338 | - `0` = none 339 | - `1` = Github 340 | - `2` = Reddit 341 | - `3` = Custom 342 | ### accessoryURL 343 | This property is optional and only applies if you chose to set the `accessoryType` to `3` / custom. 344 | Here you can specify the URL to an image will which be displayed as the accessory image 345 | ### Local accessory image 346 | If you want to use a local image as the accessory icon, you will have to put it in the 'Resources' folder of your preference bundle and it will have to have the name:`userName.png` where `userName` is the same you specified earlier for display. 347 | ### Custom accessory image note 348 | It is recommended to provide an image with no clear border on any side, to avoid an unexpectedly small or shifted icon. 349 | ### pfpURL 350 | This property holds the URL to the profile picture you want to display. 351 | ### Local profile picture 352 | If don't want to use the URLs, you will also need to include the profile pictures of the two accounts in the `Resources` folder of your preferences. 353 | The pictures will have to have the same name as the Twitter tag of the corresponding account and be stored as `.png` files. 354 | ### URL 355 | `URL` is required and is the URL the user will be lead to, once they tapped the cell. 356 | 357 | ## Using the helper functions 358 | First of all, you will need to import HelperFunction.h as follows: 359 | ```objc 360 | #import 361 | ``` 362 | The [HelperFunctions.h](GcUniversal/HelperFunctions.h) file includes this interface (more stuff in the file): 363 | ```objc 364 | @interface UIView (extension) 365 | -(void)anchorTop:(nullable NSLayoutAnchor *)top 366 | leading:(nullable NSLayoutAnchor *)leading 367 | bottom:(nullable NSLayoutAnchor *)bottom 368 | trailing:(nullable NSLayoutAnchor *)trailing 369 | padding:(UIEdgeInsets)insets 370 | size:(CGSize)size ; 371 | 372 | -(void)anchorCenterX:(nullable NSLayoutAnchor *)centerX 373 | centerY:(nullable NSLayoutAnchor *)centerY 374 | size:(CGSize)size ; 375 | 376 | -(void)anchorEqualsToView:(UIView *)view padding:(UIEdgeInsets)insets ; 377 | @end 378 | 379 | void logToFile(NSString *path, NSString *log); 380 | ``` 381 | ### Constraint helpers usage 382 | Therefor you can use the HelperFunctions like this: 383 | ```objc 384 | UIView *view = [UIView new]; 385 | [someOtherView addSubview:view]; 386 | 387 | [view anchorTop:someOtherView.topAnchor leading:someOtherView.leadingAnchor bottom:nil trailing:nil padding:UIEdgeInsetsMake(32,15,0,0) size:CGSizeMake(64,64)]; 388 | ``` 389 | Now, this would constrain the `topAnchor` of `view` to the `topAnchor` of `someOtherView` with padding of `32`, 390 | also, this would constrain the `leadingAnchor` of `view` to the `leadingAnchor` of `someOtherView` with padding of `15`, 391 | furthermore, this would constrain the `widthAnchor` and `heightAnchor` of `view` to `64` each. 392 | 393 | If you are looking for a better explanation of this function, I recommend watching [this](https://www.youtube.com/watch?v=iqpAP7s3b-8&t=840s) video, as it's also where I got the function from, which I tried to convert to Obj-C. 394 | 395 | ### logToFile 396 | ```objc 397 | void logToFile(NSString *path, NSString *log); 398 | ``` 399 | This is a simple convenience function, which writes the given log to the end of the of the file at the provided path. (If the file doesn't exist, it will be created) 400 | 401 | ## Using the color utils 402 | Don't forget to import the `GcColorUtils.h`. 403 | ```objc 404 | #import 405 | ``` 406 | The interface in `GcColorUtils.h` looks as follows: 407 | ```objc 408 | typedef NS_ENUM(NSUInteger, ColorComponent) { 409 | kColorRed, 410 | kColorGreen, 411 | kColorBlue, 412 | kColorHue, 413 | kColorSaturation, 414 | kColorBrightness, 415 | kColorAlpha 416 | }; 417 | 418 | @interface UIColor (colorUtils) 419 | + (UIColor *)closestColorFromArray:(NSArray *)colors toColor:(UIColor *)color ; 420 | - (CGFloat)getColorComponent:(ColorComponent)component ; 421 | - (CGFloat)rgbValue; 422 | - (BOOL)isGrayscale; 423 | - (BOOL)isNearGrayscale; 424 | - (BOOL)isDarkColor; 425 | - (BOOL)isLightColor; 426 | @end 427 | ``` 428 | All the functions should be relatively self-explanatory I think, but I will explain a few of them anyways. 429 | The `closestColorFromArray: toColor: ;` function returns the color from the input array, which is the closest to the input color. 430 | The `rgbValue` function returns a float between 0 and 3. This float is calculated by adding the `r`, `g` and `b` values of the color together. 431 | 432 | ## Using the image utils 433 | Don't forget to import the `GcImageUtils.h`. 434 | ```objc 435 | #import 436 | ``` 437 | The interface in `GcImageUtils.h` looks something like this: 438 | ```objc 439 | BOOL isHEICSupported(void); 440 | NSData *UIImageHEICRepresentation(UIImage *image, CGFloat compressionQuality); 441 | 442 | @interface UIImage (imageUtils) 443 | + (UIImage *)stockImgForBundleID:(NSString *)arg1 ; 444 | + (UIImage *)thumbnailForImage:(UIImage *)image withMaxSize:(CGFloat)size scale:(CGFloat)scale ; 445 | - (UIColor *)averageColor; 446 | - (NSArray *)dominantColors; 447 | @end 448 | ``` 449 | ### isHEICSupported 450 | Return a `BOOL` indicating wether the device/iOS combination support the HEIC image format. 451 | 452 | ### UIImageHEICRepresentation (Deprecated/Obsoleted with iOS 17) 453 | Same thing as [UIImageJPEGRepresentation](https://developer.apple.com/documentation/uikit/1624115-uiimagejpegrepresentation?language=objc) or [UIImagePNGRepresentation](https://developer.apple.com/documentation/uikit/1624096-uiimagepngrepresentation?language=objc) but for `HEIC`. 454 | 455 | ### stockImgForBundleID 456 | This method will give you the stock (unthemed) icon for an app / service. 457 | 458 | ### thumbnailForMaxSize 459 | This method returns a downscaled version of the provided image. 460 | It downscaled to the `size` provided eg: with `size = 400` and an image of `1920x1080` it will be resized to `400x225`.
461 | Why is that useful?
462 | Downsampling the image manually instead of letting UIKit handle this at display time drastically reduces the memory footprint of the image in memory, thus it is recommended to use this method whenever you use "global" images of a substantial size for extended periods of time.
463 | 464 | (If the `size` provided is negativ, it will implicitely function as `thumbnailForImage:withMinSize:scale:`, thus the short side of the resulting image will be at least `size` long) 465 | 466 | ### averageColor 467 | Returns the average / mean color of an image. 468 | 469 | ### dominantColors 470 | Do note that this function will return an array of colors with an unspecified count, so you will have to check for the array count manually and you might have to specify different behaviour within your project depending on the number of colors returned. 471 | 472 | The rest of these functions should be self-explanatory though, but if you do have a question, just ask me on Twitter or something. 473 | 474 | ## Other 475 | If you want to ask me anything about my library or if you happen to find a typo feel free to contact me on [Twitter](https://twitter.com/messages/compose?recipient_id=860938938910986244) or ping me on a discord server, if you find me (no friend-requests or message-requests). 476 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Make sure the THEOS environment variable is set 4 | if [ -z "${THEOS}" ]; then 5 | echo "THEOS environment variable is missing." 6 | exit 1 7 | fi 8 | 9 | # Exit on error 10 | set -e 11 | 12 | # Be verbose 13 | set -v 14 | 15 | # Copy the dynamic libraries 16 | rm -f "$THEOS/lib/libgcuniversal.dylib" 17 | mkdir -p "${THEOS}/lib/iphone/rootless" 18 | cp GcUniversal/libgcuniversal.tbd "${THEOS}/lib/" 19 | cp GcUniversal/libgcuniversalrootless.tbd "${THEOS}/lib/iphone/rootless/libgcuniversal.tbd" 20 | 21 | # Copy the header files 22 | mkdir -p "${THEOS}/include/GcUniversal" 23 | cp GcUniversal/*.h "${THEOS}/include/GcUniversal/" 24 | 25 | # Copy the module map 26 | cp GcUniversal/module.modulemap "${THEOS}/include/GcUniversal/" 27 | 28 | # We're done 29 | set +v 30 | 31 | echo 32 | echo "Installation successful!" 33 | echo --------------------------------------------------------------------------------