Skip to content

Commit

Permalink
1.3
Browse files Browse the repository at this point in the history
- added ability to add currently playing songs or podcast via spotify in the befake controller
  - you can also search for songs and add them as "currently playing"
- add BeaTokenManager that holds and manages access tokens throughout the lifecycle of BeReal
- restructured project
- overall improvements to handling self (thanks to @NightwindDev) and removed unneccessary code
- moved the download button adding into another function
- added the ability to download own bereal images from memories
- fix sharing bereals from memories not being saved correctly (images were saved as white images)
- fixed download button duplicating when moving the 2nd photo of a BeReal
- improvements in handling the download button visibility
- move the locate button to the right side of the view in BeaLocationViewController
- fix the apple maps logo and legal not being visible in BeaLocationViewController
- add a context menu and a donation option

- screenshot detection bypass doesnt work anymore
  • Loading branch information
yandevelop committed Jul 16, 2023
1 parent d90dd7d commit 2e7ffc8
Show file tree
Hide file tree
Showing 30 changed files with 1,225 additions and 166 deletions.
20 changes: 11 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
TARGET := iphone:clang:latest:14.0
INSTALL_TARGET_PROCESSES = BeReal
ARCHS = arm64 arm64e
ARCHS = arm64
FINALPACKAGE = 1
PACKAGE_VERSION = 1.2.2
PACKAGE_VERSION = 1.3

THEOS_PACKAGE_SCHEME = rootless

export SYSROOT = $(THEOS)/sdks/iPhoneOS15.5.sdk

include $(THEOS)/makefiles/common.mk

TWEAK_NAME = Bea

Bea_FILES = Tweak/Tweak.x
Bea_CFLAGS = -fobjc-arc
Bea_FRAMEWORKS = UIKit MapKit
$(TWEAK_NAME)_FILES = Tweak/Tweak.x
$(TWEAK_NAME)_CFLAGS = -fobjc-arc
$(TWEAK_NAME)_FRAMEWORKS = UIKit MapKit

ifeq ($(JAILED), 1)
Bea_CFLAGS += -D JAILED=1
ifeq ($(LEGACY_SUPPORT), 1)
$(TWEAK_NAME)_CFLAGS += -D LEGACY_SUPPORT=1
endif

ifeq ($(LEGACY_SUPPORT), 1)
Bea_CFLAGS += -D LEGACY_SUPPORT=1
ifeq ($(JAILED), 1)
Bea_CFLAGS += -D JAILED=1
endif

include $(THEOS_MAKE_PATH)/tweak.mk
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Compatible with all iOS devices running iOS 14 or later.
- Post on time, even if you're posting late
- Set a custom location
- Set a custom retake count
- Add what you're currently playing or add a song
- Download BeReals
- Bypass screenshot detection

Expand All @@ -34,6 +35,9 @@ Compatible with all iOS devices running iOS 14 or later.
1. Add `https://havoc.app` to your package manager or download the latest `.deb` from the [Releases](https://github.com/yandevelop/Bea/releases) tab.
2. Install Bea using your package manager of choice.

## Donations
If you would like to support the development of this project, you can donate to me [here](https://ko-fi.com/yandevelop)

## License
You may not copy, modify, sublicense or distribute the source code or any packages from it.

20 changes: 18 additions & 2 deletions Tweak/Tweak.h
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "../Utilities/BeaUtilities.m"
#import "../Utilities/UploadViewController/BeaUploadViewController.m"
#import <rootless.h>
#import "../Utilities/Managers/TokenManager/BeaTokenManager.m"
#import "../Utilities/ViewControllers/UploadViewController/BeaUploadViewController.m"

BOOL isUnblurred = NO;
NSString *authorizationKey = nil;
Class photoView;

@interface CAFilter : NSObject
@property (copy) NSString * name;
@end

@interface DoublePhotoView : UIView
@property (nonatomic, strong) BeaButton *downloadButton;
@end

@interface HomeViewController : UIViewController
@property (nonatomic, retain) UIImageView *ibNavBarLogoImageView;
- (void)openDebugMenu;
@end

@interface SettingsViewController : UIViewController
@property (nonatomic, retain) UITableView *tableView;
@end

@interface UIHostingView : UIView
@end
117 changes: 51 additions & 66 deletions Tweak/Tweak.x
Original file line number Diff line number Diff line change
@@ -1,48 +1,51 @@
#import "Tweak.h"

%hook DoublePhotoView
- (void)layoutSubviews {
%property (nonatomic, strong) BeaButton *downloadButton;

- (void)drawRect:(CGRect)rect {
%orig;

UIView *doublePhotoView = (UIView *)self;
UIResponder *responder = self;
while (responder && ![responder isKindOfClass:[UIViewController class]]) {
responder = [responder nextResponder];
}
UIViewController *vc = (UIViewController *)responder;

if ((![vc isKindOfClass:NSClassFromString(@"BeReal.SUIFeedViewController")] && ![vc isKindOfClass:NSClassFromString(@"BeReal.FeedViewController")] && ![vc isKindOfClass:NSClassFromString(@"BeReal.MemoryDetailsViewController")]) || CGRectGetWidth([self frame]) < 180) return;

if ([self downloadButton]) return;

if ([doublePhotoView.subviews.lastObject isKindOfClass:[BeaButton class]] || doublePhotoView.frame.size.width < 180) return;

// make the view accept touches (dragging photos etc)
doublePhotoView.superview.userInteractionEnabled = YES;
doublePhotoView.superview.superview.userInteractionEnabled = YES;
[[self superview] setUserInteractionEnabled:YES];
[[[self superview] superview] setUserInteractionEnabled:YES];

UIResponder *responder = self;
while (responder && ![responder isKindOfClass:[UIViewController class]]) {
responder = [responder nextResponder];
}
UIViewController *vc = (UIViewController *)responder;

if (![vc isKindOfClass:objc_getClass("BeReal.SUIFeedViewController")] && ![vc isKindOfClass:objc_getClass("BeReal.FeedViewController")]) return;
BeaButton *downloadButton = [BeaButton downloadButton];
downloadButton.layer.zPosition = 3;

BeaButton *downloadButton = [BeaButton downloadButton];
[doublePhotoView addSubview:downloadButton];
[self setDownloadButton:downloadButton];
[self addSubview:downloadButton];

[NSLayoutConstraint activateConstraints:@[
[downloadButton.trailingAnchor constraintEqualToAnchor:doublePhotoView.trailingAnchor constant:-11.6],
[downloadButton.bottomAnchor constraintEqualToAnchor:doublePhotoView.topAnchor constant:47.333]
[[[self downloadButton] trailingAnchor] constraintEqualToAnchor:[self trailingAnchor] constant:-11.6],
[[[self downloadButton] bottomAnchor] constraintEqualToAnchor:[self topAnchor] constant:47.333]
]];
}


- (void)onMainImagePressed:(UILongPressGestureRecognizer *)gestureRecognizer {
%orig;
[BeaButton toggleDownloadButtonVisibility:self gestureRecognizer:gestureRecognizer];
[[self downloadButton] toggleVisibilityWithGestureRecognizer:gestureRecognizer];
}


- (void)handleMainPanned:(UIPinchGestureRecognizer *)gestureRecognizer {
%orig;
[BeaButton toggleDownloadButtonVisibility:self gestureRecognizer:gestureRecognizer];
[[self downloadButton] toggleVisibilityWithGestureRecognizer:gestureRecognizer];
}

- (void)handleMainPinched:(UIPinchGestureRecognizer *)gestureRecognizer {
%orig;
[BeaButton toggleDownloadButtonVisibility:self gestureRecognizer:gestureRecognizer];
[[self downloadButton] toggleVisibilityWithGestureRecognizer:gestureRecognizer];
}
%end

Expand All @@ -52,15 +55,16 @@
%orig;
if (isUnblurred) return;

UIAlertController *alertController = (UIAlertController *)self;
if ([alertController.actions[2].title isEqual:@"👀 Unblur"]) {
if ([self.actions[2].title isEqual:@"👀 Unblur"]) {
// Set the whole view to hidden
self.view.superview.hidden = YES;
UIAlertAction *thirdAction = alertController.actions[2];
UIAlertAction *thirdAction = self.actions[2];
id block = [thirdAction valueForKey:@"_handler"];
if (block) {
void (^handler)(UIAlertAction *) = block;
handler(thirdAction);
dispatch_async(dispatch_get_main_queue(), ^{
void (^handler)(UIAlertAction *) = block;
handler(thirdAction);
});
}
isUnblurred = YES;
// Dismiss the UIAlertController automatically
Expand All @@ -69,28 +73,22 @@
}
%end


%hook HomeViewController
- (void)viewDidLoad {
%orig;

UIViewController *homeViewController = (UIViewController *)self;

if (!isUnblurred && [homeViewController respondsToSelector:@selector(openDebugMenu)]) {
if (!isUnblurred && [self respondsToSelector:@selector(openDebugMenu)]) {
//[homeViewController performSelector:@selector(openDebugMenu)];
#ifndef LEGACY_SUPPORT
NSString *version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
NSComparisonResult result = [version compare:@"1.1.2" options:NSNumericSearch];
if (result == NSOrderedAscending) {
BeaAlertView *alertView = [[BeaAlertView alloc] init];
[homeViewController.view addSubview:alertView];
[[self view] addSubview:alertView];
}
#endif
}

UIImageView *beRealLogoView = [self valueForKey:@"ibNavBarLogoImageView"];
beRealLogoView.userInteractionEnabled = YES;

#ifdef JAILED
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"Bea" ofType:@"bundle"];
NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];
Expand All @@ -100,29 +98,28 @@
UIImage *beFakeLogo = [UIImage imageNamed:@"BeFake.png" inBundle:bundle compatibleWithTraitCollection:nil];
#endif

CGSize targetSize = beRealLogoView.image.size;
CGSize targetSize = [[[self ibNavBarLogoImageView] image] size];

UIGraphicsBeginImageContextWithOptions(targetSize, NO, 0);
[beFakeLogo drawInRect:CGRectMake(0, 0, targetSize.width, targetSize.height)];
UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

beRealLogoView.image = resizedImage;

UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
[beRealLogoView addGestureRecognizer:tapGestureRecognizer];

[[self ibNavBarLogoImageView] addGestureRecognizer:tapGestureRecognizer];
[[self ibNavBarLogoImageView] setImage:resizedImage];
[[self ibNavBarLogoImageView] setUserInteractionEnabled:YES];
}

%new
- (void)handleTap:(UITapGestureRecognizer *)gestureRecognizer {

UIViewController *vc = (UIViewController *)self;
// display the error view here
if (!authorizationKey) return;

BeaUploadViewController *beaUploadViewController = [[BeaUploadViewController alloc] initWithAuthorization:authorizationKey];
BeaUploadViewController *beaUploadViewController = [[BeaUploadViewController alloc] init];
beaUploadViewController.modalPresentationStyle = UIModalPresentationFullScreen;
[vc presentViewController:beaUploadViewController animated:YES completion:nil];
[self presentViewController:beaUploadViewController animated:YES completion:nil];
}
%end

Expand All @@ -138,21 +135,18 @@
}
%end


%hook SettingsViewController
- (void)viewDidLoad {
%orig;

UIViewController *vc = (UIViewController *)self;
UITableView *labelView = vc.view.subviews.firstObject;

UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, labelView.frame.size.width, 50)];
UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, [[self tableView] frame].size.width, 50)];
NSString *headerText = [NSString stringWithFormat:@"Bea %@\nmade with ❤️ by yan", TWEAK_VERSION];
headerLabel.text = headerText;
headerLabel.numberOfLines = 0;
headerLabel.font = [UIFont fontWithName:@"Inter" size:10];
headerLabel.textAlignment = NSTextAlignmentCenter;
labelView.tableHeaderView = headerLabel;

[[self tableView] setTableHeaderView:headerLabel];
}
%end

Expand All @@ -163,16 +157,6 @@
}
%end


%hook NSNotificationCenter
- (void)addObserver:(id)arg0 selector:(SEL)arg1 name:(NSNotificationName)arg2 object:(id)arg3 {
if (arg2 == UIApplicationUserDidTakeScreenshotNotification) {
return;
}
%orig;
}
%end

// return a nil string so the BeReal photo view is clear :)
%hook NSBundle
- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName {
Expand All @@ -193,18 +177,18 @@
%orig;
if ([[arg1 allKeys] containsObject:@"Authorization"] && !authorizationKey) {
authorizationKey = arg1[@"Authorization"];
[[BeaTokenManager sharedInstance] setBRAccessToken:authorizationKey];
}
}
%end


%hook UIHostingView
- (void)layoutSubviews {
%orig;
UIView *s = (UIView *)self;
for (UIView *v in s.superview.subviews) {
if ((v.frame.size.width <= 48 && v.frame.size.width > 32) || (([v isKindOfClass:objc_getClass("SwiftUI._UIGraphicsView")] || [v isKindOfClass:[UIView class]]) && v.frame.size.width > 350 && v.subviews.count == 0)) {
v.hidden = YES;
for (UIView *v in [[self superview] subviews]) {
CGFloat width = v.frame.size.width;
if ((width <= 48 && width > 32) || ([v isKindOfClass:[UIView class]] && width > 350 && width < 1400 && v.subviews.count == 0)) {
[v setHidden:YES];
}
}
}
Expand All @@ -215,7 +199,8 @@
- (void)viewWillAppear:(id)arg1 {
%orig;
if ([self.viewControllers.firstObject isKindOfClass:objc_getClass("BeReal.SUIFeedViewController")] && [self.parentViewController isKindOfClass:objc_getClass("BeReal.HomeViewController")] && !isUnblurred) {
[self.parentViewController performSelector:@selector(openDebugMenu)];
HomeViewController *controller = (HomeViewController *)self.parentViewController;
[controller openDebugMenu];
}
}
%end
Expand All @@ -227,8 +212,8 @@
photoView = objc_getClass("RealComponents.DoublePhotoView");
#endif

%init(HomeViewController = objc_getClass("_TtC6BeReal18HomeViewController"),
%init(HomeViewController = objc_getClass("BeReal.HomeViewController"),
DoublePhotoView = photoView,
SettingsViewController = objc_getClass("_TtC6BeReal22SettingsViewController"),
SettingsViewController = objc_getClass("BeReal.SettingsViewController"),
UIHostingView = objc_getClass("_TtC7SwiftUIP33_A34643117F00277B93DEBAB70EC0697116_UIInheritedView"));
}
2 changes: 1 addition & 1 deletion Utilities/BeaUtilities.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@interface BeaButton : UIButton
+ (instancetype)downloadButton;
+ (void)toggleDownloadButtonVisibility:(UIView *)view gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer;
- (void)toggleVisibilityWithGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer;
@end

@interface BeaDownloader : NSObject
Expand Down
13 changes: 5 additions & 8 deletions Utilities/BeaUtilities.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#import "BeaUtilities.h"
#import <Photos/Photos.h>

@implementation BeaDownloader
+ (void)downloadImage:(id)sender {
Expand Down Expand Up @@ -26,7 +27,7 @@ + (void)downloadImage:(id)sender {

+ (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
if (error) {
NSLog(@"Error saving image: %@", error.localizedDescription);
NSLog(@"[Bea]Error saving image: %@", error.localizedDescription);
} else {
UIButton *button = (__bridge UIButton *)contextInfo;
UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:19];
Expand Down Expand Up @@ -72,19 +73,15 @@ + (instancetype)downloadButton {
return downloadButton;
}

+ (void)toggleDownloadButtonVisibility:(UIView *)view gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
if (view.frame.size.width < 180 || ![view.subviews.lastObject isKindOfClass:[BeaButton class]]) return;

BeaButton *downloadButton = view.subviews.lastObject;

- (void)toggleVisibilityWithGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
if ((gestureRecognizer.numberOfTouches < 2 && [gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) || gestureRecognizer.state == 3) {
if (gestureRecognizer.state == 2) return;
[UIView animateWithDuration:0.2 animations:^{
downloadButton.alpha = 1;
self.alpha = 1;
}];
} else if ((gestureRecognizer.state == 1 || gestureRecognizer.state == 2)) {
[UIView animateWithDuration:0.2 animations:^{
downloadButton.alpha = 0;
self.alpha = 0;
}];
}
}
Expand Down
8 changes: 8 additions & 0 deletions Utilities/Managers/TokenManager/BeaTokenManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@interface BeaTokenManager : NSObject
+ (instancetype)sharedInstance;
@property (nonatomic, strong) NSString *BRAccessToken;
@property (nonatomic, strong) NSString *spotifyAccessToken;
@property (nonatomic, strong) NSString *spotifyRefreshToken;
@property (nonatomic, strong) NSNumber *expiryValue;
- (void)writeToKeychainWithDictionary:(NSDictionary *)response;
@end
Loading

0 comments on commit 2e7ffc8

Please sign in to comment.