mirror of
				https://github.com/SoPat712/YTLitePlus.git
				synced 2025-10-31 12:54:14 -04:00 
			
		
		
		
	added files via upload
This commit is contained in:
		
							
								
								
									
										194
									
								
								Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSView.m
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSView.m
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,194 @@ | ||||
| // | ||||
| //  FHSView.m | ||||
| //  FLEX | ||||
| // | ||||
| //  Created by Tanner Bennett on 1/6/20. | ||||
| // | ||||
|  | ||||
| #import "FHSView.h" | ||||
| #import "FLEXUtility.h" | ||||
| #import "NSArray+FLEX.h" | ||||
|  | ||||
| @interface FHSView (Snapshotting) | ||||
| + (UIImage *)_snapshotView:(UIView *)view; | ||||
| @end | ||||
|  | ||||
| @implementation FHSView | ||||
|  | ||||
| + (instancetype)forView:(UIView *)view isInScrollView:(BOOL)inScrollView { | ||||
|     return [[self alloc] initWithView:view isInScrollView:inScrollView]; | ||||
| } | ||||
|  | ||||
| - (id)initWithView:(UIView *)view isInScrollView:(BOOL)inScrollView { | ||||
|     self = [super init]; | ||||
|     if (self) { | ||||
|         _view = view; | ||||
|         _inScrollView = inScrollView; | ||||
|         _identifier = NSUUID.UUID.UUIDString; | ||||
|  | ||||
|         UIViewController *controller = [FLEXUtility viewControllerForView:view]; | ||||
|         if (controller) { | ||||
|             _important = YES; | ||||
|             _title = [NSString stringWithFormat: | ||||
|                 @"%@ (for %@)", | ||||
|                 NSStringFromClass([controller class]), | ||||
|                 NSStringFromClass([view class]) | ||||
|             ]; | ||||
|         } else { | ||||
|             _title = NSStringFromClass([view class]); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return self; | ||||
| } | ||||
|  | ||||
| - (CGRect)frame { | ||||
|     if (_inScrollView) { | ||||
|         CGPoint offset = [(UIScrollView *)self.view.superview contentOffset]; | ||||
|         return CGRectOffset(self.view.frame, -offset.x, -offset.y); | ||||
|     } else { | ||||
|         return self.view.frame; | ||||
|     } | ||||
| } | ||||
|  | ||||
| - (BOOL)hidden { | ||||
|     return self.view.isHidden; | ||||
| } | ||||
|  | ||||
| - (UIImage *)snapshotImage { | ||||
|     return [FHSView _snapshotView:self.view]; | ||||
| } | ||||
|  | ||||
| - (NSArray<FHSView *> *)children { | ||||
|     BOOL isScrollView = [self.view isKindOfClass:[UIScrollView class]]; | ||||
|     return [self.view.subviews flex_mapped:^id(UIView *subview, NSUInteger idx) { | ||||
|         return [FHSView forView:subview isInScrollView:isScrollView]; | ||||
|     }]; | ||||
| } | ||||
|  | ||||
| - (NSString *)summary { | ||||
|     CGRect f = self.frame; | ||||
|     return [NSString stringWithFormat: | ||||
|         @"%@ (%.1f, %.1f, %.1f, %.1f)", | ||||
|         NSStringFromClass([self.view class]), | ||||
|         f.origin.x, f.origin.y, f.size.width, f.size.height | ||||
|     ]; | ||||
| } | ||||
|  | ||||
| - (NSString *)description{ | ||||
|     return self.view.description; | ||||
| } | ||||
|  | ||||
| - (id)ifImportant:(id)importantAttr ifNormal:(id)normalAttr { | ||||
|     return self.important ? importantAttr : normalAttr; | ||||
| } | ||||
|  | ||||
| @end | ||||
|  | ||||
| @implementation FHSView (Snapshotting) | ||||
|  | ||||
| + (UIImage *)drawView:(UIView *)view { | ||||
|     UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0); | ||||
|     [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES]; | ||||
|     UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); | ||||
|     UIGraphicsEndImageContext(); | ||||
|     return image; | ||||
| } | ||||
|  | ||||
| /// Recursively hides all views that may be obscuring the given view and collects them | ||||
| /// in the given array. You should unhide them all when you are done. | ||||
| + (BOOL)_hideViewsCoveringView:(UIView *)view | ||||
|                           root:(UIView *)rootView | ||||
|                    hiddenViews:(NSMutableArray<UIView *> *)hiddenViews { | ||||
|     // Stop when we reach this view | ||||
|     if (view == rootView) { | ||||
|         return YES; | ||||
|     } | ||||
|  | ||||
|     for (UIView *subview in rootView.subviews.reverseObjectEnumerator.allObjects) { | ||||
|         if ([self _hideViewsCoveringView:view root:subview hiddenViews:hiddenViews]) { | ||||
|             return YES; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (!rootView.isHidden) { | ||||
|         rootView.hidden = YES; | ||||
|         [hiddenViews addObject:rootView]; | ||||
|     } | ||||
|  | ||||
|     return NO; | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Recursively hides all views that may be obscuring the given view and collects them | ||||
| /// in the given array. You should unhide them all when you are done. | ||||
| + (void)hideViewsCoveringView:(UIView *)view doWhileHidden:(void(^)(void))block { | ||||
|     NSMutableArray *viewsToUnhide = [NSMutableArray new]; | ||||
|     if ([self _hideViewsCoveringView:view root:view.window hiddenViews:viewsToUnhide]) { | ||||
|         block(); | ||||
|     } | ||||
|  | ||||
|     for (UIView *v in viewsToUnhide) { | ||||
|         v.hidden = NO; | ||||
|     } | ||||
| } | ||||
|  | ||||
| + (UIImage *)_snapshotVisualEffectBackdropView:(UIView *)view { | ||||
|     NSParameterAssert(view.window); | ||||
|  | ||||
|     // UIVisualEffectView is a special case that cannot be snapshotted | ||||
|     // the same way as any other view. From Apple docs: | ||||
|     // | ||||
|     //   Many effects require support from the window that hosts the | ||||
|     //   UIVisualEffectView. Attempting to take a snapshot of only the | ||||
|     //   UIVisualEffectView will result in a snapshot that does not | ||||
|     //   contain the effect. To take a snapshot of a view hierarchy | ||||
|     //   that contains a UIVisualEffectView, you must take a snapshot | ||||
|     //   of the entire UIWindow or UIScreen that contains it. | ||||
|     // | ||||
|     // To snapshot this view, we traverse the view hierarchy starting | ||||
|     // from the window and hide any views that are on top of the | ||||
|     // _UIVisualEffectBackdropView so that it is visible in a snapshot | ||||
|     // of the window. We then take a snapshot of the window and crop | ||||
|     // it to the part that contains the backdrop view. This appears to | ||||
|     // be the same technique that Xcode's own view debugger uses to | ||||
|     // snapshot visual effect views. | ||||
|     __block UIImage *image = nil; | ||||
|     [self hideViewsCoveringView:view doWhileHidden:^{ | ||||
|         image = [self drawView:view]; | ||||
|         CGRect cropRect = [view.window convertRect:view.bounds fromView:view]; | ||||
|         image = [UIImage imageWithCGImage:CGImageCreateWithImageInRect(image.CGImage, cropRect)]; | ||||
|     }]; | ||||
|  | ||||
|     return image; | ||||
| } | ||||
|  | ||||
| + (UIImage *)_snapshotView:(UIView *)view { | ||||
|     UIView *superview = view.superview; | ||||
|     // Is this view inside a UIVisualEffectView? | ||||
|     if ([superview isKindOfClass:[UIVisualEffectView class]]) { | ||||
|         // Is it (probably) the "backdrop" view of this UIVisualEffectView? | ||||
|         if (superview.subviews.firstObject == view) { | ||||
|             return [self _snapshotVisualEffectBackdropView:view]; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Hide the view's subviews before we snapshot it | ||||
|     NSMutableIndexSet *toUnhide = [NSMutableIndexSet new]; | ||||
|     [view.subviews flex_forEach:^(UIView *v, NSUInteger idx) { | ||||
|         if (!v.isHidden) { | ||||
|             v.hidden = YES; | ||||
|             [toUnhide addIndex:idx]; | ||||
|         } | ||||
|     }]; | ||||
|  | ||||
|     // Snapshot the view, then unhide the previously-unhidden views | ||||
|     UIImage *snapshot = [self drawView:view]; | ||||
|     for (UIView *v in [view.subviews objectsAtIndexes:toUnhide]) { | ||||
|         v.hidden = NO; | ||||
|     } | ||||
|  | ||||
|     return snapshot; | ||||
| } | ||||
|  | ||||
| @end | ||||
		Reference in New Issue
	
	Block a user
	 Balackburn
					Balackburn