├── FirstLook.plist ├── Headers ├── CCSModuleMetadata.h ├── CCUIModuleInstance.h ├── CCUIModuleInstanceManager.h ├── CCUIToggleModule.h ├── LLTouchManager.h ├── LastLookManager.h ├── SBBacklightController.h └── SBLockScreenManager.h ├── Makefile ├── Models ├── FirstLookManager.h └── FirstLookManager.m ├── README.md ├── Tweak.x └── control /FirstLook.plist: -------------------------------------------------------------------------------- 1 | { 2 | Filter = { 3 | Bundles = ("com.apple.springboard"); 4 | }; 5 | } 6 | -------------------------------------------------------------------------------- /Headers/CCSModuleMetadata.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface CCSModuleMetadata : NSObject 4 | @property (nonatomic, copy, readonly) NSString *moduleIdentifier; 5 | @end -------------------------------------------------------------------------------- /Headers/CCUIModuleInstance.h: -------------------------------------------------------------------------------- 1 | #import "CCSModuleMetadata.h" 2 | #import "CCUIToggleModule.h" 3 | 4 | @interface CCUIModuleInstance : NSObject 5 | @property (nonatomic, assign, readonly) CCSModuleMetadata *metadata; 6 | @property (nonatomic, assign, readonly) CCUIToggleModule *module; 7 | @end -------------------------------------------------------------------------------- /Headers/CCUIModuleInstanceManager.h: -------------------------------------------------------------------------------- 1 | #import "CCUIModuleInstance.h" 2 | 3 | @interface CCUIModuleInstanceManager : NSObject 4 | @property (nonatomic, assign, readonly) NSArray *moduleInstances; 5 | 6 | + (instancetype)sharedInstance; 7 | @end -------------------------------------------------------------------------------- /Headers/CCUIToggleModule.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface CCUIToggleModule : NSObject 4 | @property (nonatomic, assign, readwrite, getter=isSelected) BOOL selected; 5 | @end -------------------------------------------------------------------------------- /Headers/LLTouchManager.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface LLTouchManager : NSObject 4 | @property (nonatomic, assign, readwrite) BOOL isListening; 5 | 6 | + (instancetype)sharedInstance; 7 | 8 | - (void)startListeningTouchEvents; 9 | - (void)stopListeningTouchEvents; 10 | @end -------------------------------------------------------------------------------- /Headers/LastLookManager.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface LastLookManager : NSObject 4 | @property (nonatomic, assign, readwrite) BOOL isActive; 5 | 6 | + (instancetype)sharedInstance; 7 | @end -------------------------------------------------------------------------------- /Headers/SBBacklightController.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface SBBacklightController : NSObject 4 | @property (nonatomic, assign, readonly) BOOL screenIsOn; 5 | 6 | + (instancetype)sharedInstance; 7 | + (instancetype)sharedInstanceIfExists; 8 | 9 | - (void)_startFadeOutAnimationFromLockSource:(int)source; 10 | - (void)setBacklightState:(NSInteger)state source:(NSInteger)source; 11 | @end -------------------------------------------------------------------------------- /Headers/SBLockScreenManager.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface SBLockScreenManager : NSObject 4 | @property (atomic, assign, readonly) BOOL isLockScreenActive; 5 | @property (atomic, assign, readonly) BOOL isLockScreenVisible; 6 | 7 | + (instancetype)sharedInstance; 8 | + (instancetype)sharedInstanceIfExists; 9 | @end -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ifeq ($(ROOTLESS),1) 2 | THEOS_DEVICE_IP = 192.168.1.8 3 | THEOS_DEVICE_PORT = 22 4 | THEOS_PACKAGE_SCHEME = rootless 5 | else ifeq ($(ROOTHIDE),1) 6 | THEOS_PACKAGE_SCHEME = roothide 7 | else 8 | THEOS_DEVICE_IP = 192.168.1.9 9 | THEOS_DEVICE_PORT = 22 10 | endif 11 | 12 | DEBUG = 0 13 | FINALPACKAGE = 1 14 | TARGET := iphone:clang:16.5:12.0 15 | INSTALL_TARGET_PROCESSES = SpringBoard 16 | 17 | include $(THEOS)/makefiles/common.mk 18 | 19 | TWEAK_NAME = FirstLook 20 | $(TWEAK_NAME)_FILES = Tweak.x Models/FirstLookManager.m 21 | $(TWEAK_NAME)_CFLAGS = -fobjc-arc 22 | 23 | include $(THEOS_MAKE_PATH)/tweak.mk 24 | -------------------------------------------------------------------------------- /Models/FirstLookManager.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "../Headers/CCUIModuleInstanceManager.h" 4 | #import "../Headers/SBBacklightController.h" 5 | #import "../Headers/SBLockScreenManager.h" 6 | #import "../Headers/LastLookManager.h" 7 | #import "../Headers/LLTouchManager.h" 8 | 9 | @interface FirstLookManager : NSObject 10 | + (instancetype)sharedInstance; 11 | 12 | - (void)scheduleLastLook; 13 | - (void)cancelLastLook; 14 | - (void)scheduleScreenDim; 15 | - (void)cancelScreenDim; 16 | 17 | - (CGFloat)stayOnDuration; 18 | - (BOOL)isLastLookEnabled; 19 | - (BOOL)isAODEnabled; 20 | @end -------------------------------------------------------------------------------- /Models/FirstLookManager.m: -------------------------------------------------------------------------------- 1 | #import "FirstLookManager.h" 2 | 3 | @implementation FirstLookManager { 4 | NSTimer *_lastLookTimer; 5 | NSTimer *_screenDimTimer; 6 | } 7 | 8 | + (instancetype)sharedInstance { 9 | static FirstLookManager *instance = nil; 10 | static dispatch_once_t onceToken; 11 | 12 | dispatch_once(&onceToken, ^{ 13 | instance = [FirstLookManager new]; 14 | }); 15 | 16 | return instance; 17 | } 18 | 19 | - (void)scheduleLastLook { 20 | [self cancelLastLook]; 21 | 22 | _lastLookTimer = [NSTimer scheduledTimerWithTimeInterval:self.stayOnDuration * 0.9 repeats:NO block:^(NSTimer * _Nonnull timer) { 23 | SBLockScreenManager *sblsm = [NSClassFromString(@"SBLockScreenManager") sharedInstance]; 24 | if (self.isAODEnabled && sblsm.isLockScreenActive) { 25 | [[NSClassFromString(@"LLTouchManager") sharedInstance] startListeningTouchEvents]; 26 | 27 | SBBacklightController *sbbc = [NSClassFromString(@"SBBacklightController") sharedInstanceIfExists]; 28 | [sbbc _startFadeOutAnimationFromLockSource:3]; 29 | } 30 | }]; 31 | } 32 | 33 | - (void)cancelLastLook { 34 | [_lastLookTimer invalidate]; 35 | _lastLookTimer = nil; 36 | } 37 | 38 | - (void)scheduleScreenDim { 39 | [self cancelScreenDim]; 40 | 41 | _screenDimTimer = [NSTimer scheduledTimerWithTimeInterval:self.stayOnDuration repeats:NO block:^(NSTimer * _Nonnull timer) { 42 | if (self.isLastLookActive) { 43 | SBBacklightController *sbbc = [NSClassFromString(@"SBBacklightController") sharedInstanceIfExists]; 44 | [sbbc setBacklightState:1 source:667]; 45 | [sbbc setBacklightState:3 source:667]; 46 | } 47 | }]; 48 | } 49 | 50 | - (void)cancelScreenDim { 51 | [_screenDimTimer invalidate]; 52 | _screenDimTimer = nil; 53 | } 54 | 55 | - (BOOL)isLastLookActive { 56 | return [[NSClassFromString(@"LastLookManager") sharedInstance] isActive]; 57 | } 58 | 59 | - (CGFloat)stayOnDuration { 60 | LastLookManager *llman = [NSClassFromString(@"LastLookManager") sharedInstance]; 61 | if (class_getInstanceVariable([llman class], "normal_stayOnDuration") == NULL) { 62 | return 10; 63 | } 64 | 65 | return [[llman valueForKey:@"normal_stayOnDuration"] floatValue]; 66 | } 67 | 68 | - (BOOL)isLastLookEnabled { 69 | LastLookManager *llman = [NSClassFromString(@"LastLookManager") sharedInstance]; 70 | if (class_getInstanceVariable([llman class], "enabled") == NULL) { 71 | return NO; 72 | } 73 | 74 | if (![[llman valueForKey:@"enabled"] boolValue]) { 75 | return NO; 76 | } 77 | 78 | NSArray *modules = [[NSClassFromString(@"CCUIModuleInstanceManager") sharedInstance] moduleInstances]; 79 | for (CCUIModuleInstance *instance in modules) { 80 | if ([instance.metadata.moduleIdentifier isEqualToString:@"com.anthopak.lastlookmainmodule"]) { 81 | if (!instance.module.selected) { 82 | return NO; 83 | } 84 | } 85 | } 86 | 87 | return YES; 88 | } 89 | 90 | - (BOOL)isAODEnabled { 91 | LastLookManager *llman = [NSClassFromString(@"LastLookManager") sharedInstance]; 92 | if (class_getInstanceVariable([llman class], "enabled") == NULL) { 93 | return NO; 94 | } 95 | 96 | if (![[llman valueForKey:@"enabled"] boolValue]) { 97 | return NO; 98 | } 99 | 100 | if (class_getInstanceVariable([llman class], "AOD_enabled") == NULL) { 101 | return NO; 102 | } 103 | 104 | return [[llman valueForKey:@"AOD_enabled"] boolValue]; 105 | } 106 | 107 | @end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FirstLook 2 |
  • Automatically shows ShortLook when the display is turned on. REQUIRES LastLook tweak
  • 3 |
    4 |
  • Tested on iOS 16.4 (rootless), no options to configure
  • 5 |
    6 |
  • Developed for u/METE0RiteZ as part of the TweakBounty
  • 7 | -------------------------------------------------------------------------------- /Tweak.x: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import "Models/FirstLookManager.h" 5 | 6 | void notifyBlankedScreen(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { 7 | SBBacklightController *sbbc = [%c(SBBacklightController) sharedInstanceIfExists]; 8 | 9 | if (sbbc.screenIsOn) { 10 | if (![FirstLookManager sharedInstance].isLastLookEnabled) { 11 | return; 12 | } 13 | 14 | [[%c(LLTouchManager) sharedInstance] startListeningTouchEvents]; 15 | 16 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 17 | [sbbc _startFadeOutAnimationFromLockSource:3]; 18 | }); 19 | } 20 | } 21 | 22 | %hook SBBacklightController 23 | - (void)_notifyObserversWillTransitionToBacklightState:(NSInteger)state source:(NSInteger)source { 24 | %orig; 25 | 26 | FirstLookManager *flman = [FirstLookManager sharedInstance]; 27 | 28 | // Source 12 is a notification... 29 | if (state == 1 && source == 12 && flman.isLastLookEnabled) { 30 | [flman scheduleScreenDim]; 31 | } 32 | 33 | else { 34 | [flman cancelScreenDim]; 35 | } 36 | } 37 | %end 38 | 39 | %hook UNNotificationRequest 40 | + (instancetype)requestWithIdentifier:(id)arg1 pushPayload:(id)arg2 bundleIdentifier:(id)arg3 { 41 | if ([[%c(SBLockScreenManager) sharedInstanceIfExists] isLockScreenActive]) { 42 | [[FirstLookManager sharedInstance] scheduleScreenDim]; 43 | } 44 | 45 | return %orig; 46 | } 47 | %end 48 | 49 | %ctor { 50 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, notifyBlankedScreen, CFSTR("com.apple.springboard.hasBlankedScreen"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); 51 | } -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: com.dvntm.firstlook 2 | Name: FirstLook 3 | Version: 0.0.3 4 | Architecture: iphoneos-arm 5 | Description: First look for the LastLook tweak 6 | Maintainer: dvntm 7 | Author: dvntm 8 | Section: Tweaks 9 | Depends: mobilesubstrate (>= 0.9.5000), com.anthopak.lastlook 10 | --------------------------------------------------------------------------------