├── .gitignore ├── Telescope.plist ├── packages └── com.mtac.telescope_1.2_iphoneos-arm.deb ├── README.md ├── control ├── Makefile └── Tweak.xm /.gitignore: -------------------------------------------------------------------------------- 1 | .theos 2 | .DS_Store 3 | .vscode -------------------------------------------------------------------------------- /Telescope.plist: -------------------------------------------------------------------------------- 1 | { 2 | Filter = { 3 | Bundles = ( 4 | "com.apple.mobileslideshow" 5 | ); 6 | }; 7 | } -------------------------------------------------------------------------------- /packages/com.mtac.telescope_1.2_iphoneos-arm.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MTACS/Telescope/HEAD/packages/com.mtac.telescope_1.2_iphoneos-arm.deb -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Telescope 2 | iOS 15 Photo information for iOS 14 3 | 4 | ![IMG_0042](https://user-images.githubusercontent.com/13209789/121762339-3d606500-cb03-11eb-9dec-3e8be1eb66ad.jpg) 5 | 6 | -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: com.mtac.telescope 2 | Name: Telescope 3 | Version: 1.2 4 | Architecture: iphoneos-arm 5 | Description: iOS 15 Photo information for iOS 14 6 | Maintainer: MTAC 7 | Author: MTAC 8 | Section: Tweaks 9 | Depends: mobilesubstrate (>= 0.9.5000) 10 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TARGET := iphone:clang:latest:13.0 2 | THEOS_DEVICE_IP = 192.168.1.71 3 | INSTALL_TARGET_PROCESSES = MobileSlideShow Camera Preferences 4 | ARCHS = arm64 arm64e 5 | SYSROOT = $(THEOS)/sdks/iPhoneOS14.2.sdk 6 | DEBUG = 1 7 | FINALPACKAGE = 0 8 | 9 | include $(THEOS)/makefiles/common.mk 10 | 11 | TWEAK_NAME = Telescope 12 | 13 | Telescope_FILES = Tweak.xm 14 | Telescope_CFLAGS = -fobjc-arc -Wdeprecated-declarations -Wno-deprecated-declarations 15 | 16 | include $(THEOS_MAKE_PATH)/tweak.mk 17 | 18 | -------------------------------------------------------------------------------- /Tweak.xm: -------------------------------------------------------------------------------- 1 | #import 2 | #import "spawn.h" 3 | #define WIDTH [UIScreen mainScreen].bounds.size.width 4 | #define HEIGHT [UIScreen mainScreen].bounds.size.height 5 | 6 | @import MapKit; 7 | UIViewController *infoPopoverController; 8 | 9 | @interface PXNavigationTitleView: UIView 10 | @property (strong, nonatomic) UITapGestureRecognizer *info; 11 | @end 12 | 13 | @interface PUOneUpViewController: UIViewController 14 | - (id)pu_debugCurrentAsset; 15 | @end 16 | 17 | @interface PUNavigationController: UINavigationController 18 | - (UIViewController*)_currentToolbarViewController; 19 | @end 20 | 21 | @interface PHAsset: NSObject 22 | @property (nonatomic, readonly) NSString *originalFilename; 23 | @property (nonatomic, readonly) NSData *locationData; 24 | @property (nonatomic, readonly) NSDate *creationDate; 25 | @property (nonatomic, readonly) CLLocation *location; 26 | - (CGSize)imageSize; 27 | - (id)mainFileURL; 28 | - (id)originalMetadataProperties; 29 | - (id)originalImageProperties; 30 | @end 31 | 32 | @interface TelescopeInfoViewController : UIViewController 33 | @end 34 | 35 | @implementation TelescopeInfoViewController 36 | - (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection { 37 | return UIModalPresentationNone; 38 | } 39 | @end 40 | 41 | @interface UILabel (Telescope) 42 | - (void)setMarqueeRunning:(BOOL)arg1; 43 | - (void)setMarqueeEnabled:(BOOL)arg1; 44 | - (BOOL)marqueeEnabled; 45 | - (BOOL)marqueeRunning; 46 | @end 47 | 48 | @interface UIView (Telescope) 49 | - (id)_viewControllerForAncestor; 50 | @end 51 | 52 | @interface SBIconController: UIViewController 53 | + (id)sharedInstance; 54 | @end 55 | 56 | %group Tweak 57 | %hook PXNavigationTitleView 58 | %property (strong, nonatomic) UITapGestureRecognizer *info; 59 | - (void)layoutSubviews { // Not ideal, but no other usual method seemed to work 60 | %orig; 61 | if (!self.info) { 62 | self.info = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(loadInfo)]; 63 | self.info.numberOfTapsRequired = 1; 64 | [self addGestureRecognizer:self.info]; 65 | } 66 | } 67 | - (void)viewWillDisappear:(BOOL)animated { 68 | %orig; 69 | [[%c(SBIconController) sharedInstance] dismissViewControllerAnimated:infoPopoverController completion:nil]; 70 | } 71 | %new 72 | - (void)loadInfo { 73 | PHAsset *asset = [(PUOneUpViewController *)[(PUNavigationController *)[self performSelector:@selector(_viewControllerForAncestor)] _currentToolbarViewController] pu_debugCurrentAsset]; 74 | if (asset) { 75 | TelescopeInfoViewController *controller = [[TelescopeInfoViewController alloc] init]; 76 | 77 | NSDictionary *properties = [asset originalImageProperties]; 78 | 79 | infoPopoverController = [[UIViewController alloc] init]; 80 | infoPopoverController.modalPresentationStyle = UIModalPresentationPopover; 81 | infoPopoverController.preferredContentSize = CGSizeMake(340, 400); 82 | 83 | UILabel *infoLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 10, 150, 60)]; 84 | infoLabel.font = [UIFont boldSystemFontOfSize:30]; 85 | infoLabel.text = @"Info"; 86 | [infoPopoverController.view addSubview:infoLabel]; 87 | 88 | UIButton *closeButton = [[UIButton alloc] initWithFrame:CGRectMake(275, 0, 80, 80)]; 89 | [closeButton setImage:[UIImage systemImageNamed:@"xmark.circle.fill"] forState:UIControlStateNormal]; 90 | [closeButton setTintColor:[UIColor secondaryLabelColor]]; 91 | [closeButton addTarget:self action:@selector(closeView) forControlEvents:UIControlEventTouchUpInside]; 92 | [infoPopoverController.view addSubview:closeButton]; 93 | 94 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 95 | [formatter setDateFormat:@"EEEE • MMM dd, YYYY • h:mm a"]; 96 | UILabel *dateLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 60, 310, 40)]; 97 | dateLabel.font = [UIFont systemFontOfSize:18]; 98 | dateLabel.text = [formatter stringFromDate:asset.creationDate]; 99 | [infoPopoverController.view addSubview:dateLabel]; 100 | 101 | CGSize imageSize = [asset imageSize]; 102 | NSDictionary *attributes; 103 | NSString *assetPath = [[[asset mainFileURL] absoluteString] stringByReplacingOccurrencesOfString:@"file://" withString:@""]; 104 | float byteRepresentation; 105 | BOOL isDirectory; 106 | if ([[NSFileManager defaultManager] fileExistsAtPath:assetPath isDirectory:&isDirectory]) { 107 | attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:assetPath error:nil]; 108 | byteRepresentation = (float)[[attributes objectForKey:NSFileSize] longLongValue] / (1024 * 1024); 109 | } else { 110 | byteRepresentation = 0; 111 | } 112 | 113 | UILabel *fileName = [[UILabel alloc] initWithFrame:CGRectMake(15, 90, 310, 40)]; 114 | fileName.font = [UIFont systemFontOfSize:18]; 115 | fileName.textColor = [UIColor secondaryLabelColor]; 116 | fileName.text = [NSString stringWithFormat:@"%@ • %ix%i • %.02f MB", [[[[asset mainFileURL] absoluteString] stringByReplacingOccurrencesOfString:@"file://" withString:@""] lastPathComponent], (int)imageSize.width, (int)imageSize.height, byteRepresentation]; 117 | [fileName setMarqueeEnabled:YES]; 118 | [fileName setMarqueeRunning:YES]; 119 | [infoPopoverController.view addSubview:fileName]; 120 | 121 | UILabel *modelLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 120, 310, 40)]; 122 | modelLabel.font = [UIFont systemFontOfSize:18]; 123 | NSString *make = [[properties objectForKey:@"{TIFF}"] objectForKey:@"Make"]; 124 | NSString *model = [[properties objectForKey:@"{TIFF}"] objectForKey:@"Model"]; 125 | if (make != NULL && model != NULL) { 126 | modelLabel.text = [NSString stringWithFormat:@"%@ %@", make, model]; 127 | } else { 128 | modelLabel.text = @"Camera model unknown"; 129 | } 130 | [infoPopoverController.view addSubview:modelLabel]; 131 | 132 | UILabel *lensInfo = [[UILabel alloc] initWithFrame:CGRectMake(15, 150, 310, 40)]; 133 | lensInfo.textColor = [UIColor secondaryLabelColor]; 134 | [lensInfo setMarqueeEnabled:YES]; 135 | [lensInfo setMarqueeRunning:YES]; 136 | NSString *lensInfoText = [[properties objectForKey:@"{Exif}"] objectForKey:@"LensModel"]; 137 | if (lensInfoText != NULL) { 138 | lensInfo.text = lensInfoText; 139 | } else { 140 | lensInfo.text = @"Lens info unknown"; 141 | } 142 | [infoPopoverController.view addSubview:lensInfo]; 143 | 144 | MKMapView *mapView = [[MKMapView alloc] initWithFrame:CGRectMake(15, 190, 310, 190)]; 145 | mapView.showsUserLocation = YES; 146 | mapView.mapType = MKMapTypeStandard; 147 | mapView.delegate = self; 148 | mapView.layer.cornerRadius = 10; 149 | [infoPopoverController.view addSubview:mapView]; 150 | 151 | UIButton *addressButton = [[UIButton alloc] initWithFrame:CGRectMake(15, 375, 310, 40)]; 152 | [addressButton setTitleColor:[UIColor linkColor] forState:UIControlStateNormal]; 153 | [addressButton addTarget:self action:@selector(openLink) forControlEvents:UIControlEventTouchUpInside]; 154 | [infoPopoverController.view addSubview:addressButton]; 155 | 156 | CLGeocoder *geocoder = [[CLGeocoder alloc]init]; 157 | [geocoder reverseGeocodeLocation:asset.location completionHandler:^(NSArray *placemarks, NSError *error) { 158 | CLPlacemark *placemark = [placemarks lastObject]; 159 | NSString *address = [NSString stringWithFormat:@"%@, %@, %@, %@", placemark.thoroughfare, placemark.locality, placemark.administrativeArea, placemark.postalCode]; 160 | if (placemark.thoroughfare != NULL) { 161 | [addressButton setTitle:address forState:UIControlStateNormal]; 162 | } else { 163 | [addressButton setTitle:@"" forState:UIControlStateNormal]; 164 | } 165 | }]; 166 | 167 | UIPopoverPresentationController *popover = infoPopoverController.popoverPresentationController; 168 | 169 | popover.delegate = controller; 170 | popover.permittedArrowDirections = UIPopoverArrowDirectionUp; 171 | popover.sourceView = self; 172 | popover.sourceRect = self.bounds; 173 | 174 | [(UIViewController *)[self _viewControllerForAncestor] presentViewController:infoPopoverController animated:YES completion:nil]; 175 | } 176 | } 177 | %new 178 | - (void)mapView:(MKMapView *)aMapView didUpdateUserLocation:(MKUserLocation *)aUserLocation { 179 | 180 | MKCoordinateRegion region; 181 | region.span.latitudeDelta = 0.001; 182 | region.span.longitudeDelta = 0.001; 183 | 184 | PHAsset *asset = [(PUOneUpViewController *)[(PUNavigationController *)[self performSelector:@selector(_viewControllerForAncestor)] _currentToolbarViewController] pu_debugCurrentAsset]; 185 | if (asset) { 186 | region.center.latitude = asset.location.coordinate.latitude; 187 | region.center.longitude = asset.location.coordinate.longitude; 188 | } 189 | 190 | [aMapView setRegion:region animated:YES]; 191 | 192 | MKPlacemark *marker = [[MKPlacemark alloc] initWithCoordinate:asset.location.coordinate addressDictionary:nil]; 193 | [aMapView addAnnotation:marker]; 194 | } 195 | %new 196 | - (void)openLink { 197 | PHAsset *asset = [(PUOneUpViewController *)[(PUNavigationController *)[self performSelector:@selector(_viewControllerForAncestor)] _currentToolbarViewController] pu_debugCurrentAsset]; 198 | if (asset) { 199 | NSString *address = [NSString stringWithFormat:@"http://maps.apple.com/?sll=%f,%f", asset.location.coordinate.latitude, asset.location.coordinate.longitude]; 200 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:address] options:@{} completionHandler:nil]; 201 | } 202 | } 203 | %new 204 | - (void)closeView { 205 | [(UIViewController *)[self _viewControllerForAncestor] dismissViewControllerAnimated:infoPopoverController completion:nil]; 206 | } 207 | %end 208 | %end 209 | 210 | %ctor { 211 | %init(Tweak); 212 | } 213 | 214 | --------------------------------------------------------------------------------