Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
ff4dccb
Add GitHub Actions build workflow
ChrisGleich1AufsMaul Jun 22, 2026
02dabcc
Expose file browser header for framework module
ChrisGleich1AufsMaul Jun 22, 2026
23544d3
Upload FLEX framework artifact from CI
ChrisGleich1AufsMaul Jun 22, 2026
1687092
Add Theos tweak package workflow
ChrisGleich1AufsMaul Jun 22, 2026
8dad04c
Allow FLEX deprecation warnings in tweak build
ChrisGleich1AufsMaul Jun 22, 2026
3bc15d8
Relax warnings for Theos tweak build
ChrisGleich1AufsMaul Jun 22, 2026
7e69ec4
Make CI independent of simulator devices
ChrisGleich1AufsMaul Jun 22, 2026
652a233
Upload injectable FLEX loader dylib
ChrisGleich1AufsMaul Jun 22, 2026
d40f46b
Use Node 24 compatible GitHub Actions
ChrisGleich1AufsMaul Jun 22, 2026
2bea8b2
Guard heap object class names
ChrisGleich1AufsMaul Jun 22, 2026
e017688
Improve toolbar contrast over app content
ChrisGleich1AufsMaul Jun 22, 2026
59b2e85
AI-based recommendation engine for FLEX, providing suggestions and in…
ChrisGleich1AufsMaul Jun 25, 2026
bc16fa3
workflow updated
ChrisGleich1AufsMaul Jun 25, 2026
69c1e3f
workflow: file renamed
ChrisGleich1AufsMaul Jun 25, 2026
fc655c5
Falscher Import-Pfad korrigiert
ChrisGleich1AufsMaul Jun 25, 2026
4a2aa4b
Update FLEX.yml
ChrisGleich1AufsMaul Jun 25, 2026
6a8e301
fix: Build error in GitHub Actions workflow for FLEXRecommendation an…
ChrisGleich1AufsMaul Jun 25, 2026
3c4fad0
fix: error: missing context for method declaration
ChrisGleich1AufsMaul Jun 25, 2026
d182ce6
changes
ChrisGleich1AufsMaul Jun 26, 2026
8740652
fix FLEX build errors
ChrisGleich1AufsMaul Jun 26, 2026
57d772a
Fix FLEXRecommendationEngine.m build errors in GitHub Actions.
ChrisGleich1AufsMaul Jun 27, 2026
e075f96
fixing build with github actions
ChrisGleich1AufsMaul Jul 3, 2026
c576b69
updated FLEXRecommendationEngine.m
ChrisGleich1AufsMaul Jul 3, 2026
e20afd3
Add: Shortcut volume up+down for open FLEX
ChrisGleich1AufsMaul Jul 3, 2026
d0267ef
Build target iOS 15.0
ChrisGleich1AufsMaul Jul 3, 2026
8ef98d6
Revert "updated FLEXRecommendationEngine.m"
ChrisGleich1AufsMaul Jul 3, 2026
88786cf
Revert "fixing build with github actions"
ChrisGleich1AufsMaul Jul 3, 2026
bb4bb49
Revert "updated FLEXRecommendationEngine.m"
ChrisGleich1AufsMaul Jul 3, 2026
5cf21cb
Revert "updated FLEXRecommendationEngine.m"
ChrisGleich1AufsMaul Jul 3, 2026
db1cc9b
Revert "fixing build with github actions"
ChrisGleich1AufsMaul Jul 3, 2026
9985dcb
Revert "updated FLEXRecommendationEngine.m"
ChrisGleich1AufsMaul Jul 3, 2026
d11ef6e
removed FLEXRecommendationEngine.m from the project
ChrisGleich1AufsMaul Jul 3, 2026
e8b5293
modified: Classes/Manager/FLEXManager+Extensibility.m
ChrisGleich1AufsMaul Jul 3, 2026
f333102
UIView Github link
ChrisGleich1AufsMaul Jul 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions .github/workflows/FLEX.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: Build

on:
push:
branches:
- main
- master
- codex/flex-mit-github-actions-kompilieren
pull_request:
workflow_dispatch:

jobs:
xcode:
name: Xcode build and tests
runs-on: macos-15

env:
DERIVED_DATA_PATH: build/DerivedData

steps:
- name: Check out repository
uses: actions/checkout@v5

- name: Show build environment
run: |
xcodebuild -version
xcodebuild -showsdks
- name: Build FLEX framework
run: |
xcodebuild build \
-project FLEX.xcodeproj \
-scheme FLEX \
-configuration Debug \
-sdk iphonesimulator \
-destination 'generic/platform=iOS Simulator' \
-derivedDataPath "$DERIVED_DATA_PATH" \
CODE_SIGNING_ALLOWED=NO
- name: Upload FLEX framework
uses: actions/upload-artifact@v6
with:
name: FLEX-framework-debug-iphonesimulator
path: ${{ env.DERIVED_DATA_PATH }}/Build/Products/Debug-iphonesimulator/FLEX.framework
if-no-files-found: error

- name: Build FLEX tests
run: |
xcodebuild build-for-testing \
-project FLEX.xcodeproj \
-scheme FLEXTests \
-configuration Debug \
-sdk iphonesimulator \
-destination 'generic/platform=iOS Simulator' \
-derivedDataPath "$DERIVED_DATA_PATH" \
CODE_SIGNING_ALLOWED=NO
tweak:
name: Theos tweak package
runs-on: macos-15

steps:
- name: Check out repository
uses: actions/checkout@v5

- name: Install Theos
run: |
git clone --recursive https://github.com/theos/theos.git "$HOME/theos"
echo "THEOS=$HOME/theos" >> "$GITHUB_ENV"
- name: Install tweak signing tools
run: |
brew install ldid
- name: Build FLEX Loader tweak package
working-directory: Tweak
run: |
make package FINALPACKAGE=1 THEOS_PACKAGE_SCHEME=rootless
- name: Collect injectable FLEX Loader dylib
run: |
mkdir -p Tweak/artifacts
cp Tweak/.theos/obj/FLEXLoader.dylib Tweak/artifacts/FLEXLoader.dylib
- name: Upload injectable FLEX Loader dylib
uses: actions/upload-artifact@v6
with:
name: FLEXLoader-dylib
path: Tweak/artifacts/FLEXLoader.dylib
if-no-files-found: error

- name: Upload FLEX Loader tweak
uses: actions/upload-artifact@v6
with:
name: FLEXLoader-tweak
path: Tweak/packages/*.deb
if-no-files-found: error
43 changes: 22 additions & 21 deletions Classes/GlobalStateExplorers/FLEXLiveObjectsController.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ - (void)viewDidLoad {
self.searchBarDebounceInterval = kFLEXDebounceInstant;
self.showsCarousel = YES;
self.carousel.items = @[@"A→Z", @"Count", @"Size"];

self.refreshControl = [UIRefreshControl new];
[self.refreshControl addTarget:self action:@selector(refreshControlDidRefresh:) forControlEvents:UIControlEventValueChanged];

[self reloadTableData];
}

Expand All @@ -63,31 +63,40 @@ - (void)reloadTableData {
for (unsigned int i = 0; i < classCount; i++) {
CFDictionarySetValue(mutableCountsForClasses, (__bridge const void *)classes[i], (const void *)0);
}

// Enumerate all objects on the heap to build the counts of instances for each class.
[FLEXHeapEnumerator enumerateLiveObjectsUsingBlock:^(__unsafe_unretained id object, __unsafe_unretained Class actualClass) {
if (!actualClass) {
return;
}

NSUInteger instanceCount = (NSUInteger)CFDictionaryGetValue(mutableCountsForClasses, (__bridge const void *)actualClass);
instanceCount++;
CFDictionarySetValue(mutableCountsForClasses, (__bridge const void *)actualClass, (const void *)instanceCount);
}];

// Convert our CF primitive dictionary into a nicer mapping of class name strings to counts that we will use as the table's model.
NSMutableDictionary<NSString *, NSNumber *> *mutableCountsForClassNames = [NSMutableDictionary new];
NSMutableDictionary<NSString *, NSNumber *> *mutableSizesForClassNames = [NSMutableDictionary new];
for (unsigned int i = 0; i < classCount; i++) {
Class class = classes[i];
const char *classNameCString = class_getName(class);
if (!classNameCString) {
continue;
}

NSUInteger instanceCount = (NSUInteger)CFDictionaryGetValue(mutableCountsForClasses, (__bridge const void *)(class));
NSString *className = @(class_getName(class));
NSString *className = @(classNameCString);
if (instanceCount > 0) {
[mutableCountsForClassNames setObject:@(instanceCount) forKey:className];
}
[mutableSizesForClassNames setObject:@(class_getInstanceSize(class)) forKey:className];
}
free(classes);

self.instanceCountsForClassNames = mutableCountsForClassNames;
self.instanceSizesForClassNames = mutableSizesForClassNames;

[self updateSearchResults:nil];
}

Expand All @@ -112,7 +121,7 @@ - (void)updateHeaderTitle {
filteredCount += count;
filteredSize += count * self.instanceSizesForClassNames[className].unsignedIntegerValue;
}

if (filteredCount == totalCount) {
// Unfiltered
self.headerTitle = [NSString
Expand All @@ -132,8 +141,6 @@ - (void)updateHeaderTitle {
];
}
}


#pragma mark - FLEXGlobalsEntry

+ (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row {
Expand All @@ -146,20 +153,18 @@ + (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row {

return liveObjectsViewController;
}


#pragma mark - Search bar

- (void)updateSearchResults:(NSString *)filter {
NSInteger selectedScope = self.selectedScope;

if (filter.length) {
NSPredicate *searchPredicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@", filter];
self.filteredClassNames = [self.allClassNames filteredArrayUsingPredicate:searchPredicate];
} else {
self.filteredClassNames = self.allClassNames;
}

if (selectedScope == kFLEXLiveObjectsSortAlphabeticallyIndex) {
self.filteredClassNames = [self.filteredClassNames sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
} else if (selectedScope == kFLEXLiveObjectsSortByCountIndex) {
Expand All @@ -179,12 +184,10 @@ - (void)updateSearchResults:(NSString *)filter {
return [@(count2.integerValue * size2.integerValue) compare:@(count1.integerValue * size1.integerValue)];
}];
}

[self updateHeaderTitle];
[self.tableView reloadData];
}


#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
Expand Down Expand Up @@ -213,15 +216,13 @@ - (UITableViewCell *)tableView:(__kindof UITableView *)tableView cellForRowAtInd
countStyle:NSByteCountFormatterCountStyleFile
]
];

return cell;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return self.headerTitle;
}


#pragma mark - Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
Expand All @@ -233,4 +234,4 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
[self.navigationController pushViewController:instances animated:YES];
}

@end
@end
Loading