// // FirstViewController.m // LNPopupControllerExample // // Created by Leo Natan on 7/16/15. // Copyright © 2015 Leo Natan. All rights reserved. // #if LNPOPUP @import LNPopupController; #endif #import "FirstViewController.h" #import "DemoPopupContentViewController.h" #import "LoremIpsum.h" #import "RandomColors.h" #import "SettingsTableViewController.h" #import "SplitViewController.h" @import UIKit; extern UIImage* LNSystemImage(NSString* named); @interface TabBar : UITabBar @end @implementation TabBar - (void)setFrame:(CGRect)frame { // NSLog(@"🤦‍♂️ frame: %@ safe area: %@", @(frame), [self valueForKey:@"safeAreaInsets"]); [super setFrame:frame]; } @end @interface Toolbar : UIToolbar @end @implementation Toolbar - (void)setFrame:(CGRect)frame { // NSLog(@"🤦‍♂️ frame: %@ safe area: %@", @(frame), [self valueForKey:@"safeAreaInsets"]); [super setFrame:frame]; } @end @interface FirstView : UIView @end @implementation FirstView - (void)willMoveToWindow:(UIWindow *)newWindow { [super willMoveToWindow:newWindow]; } - (void)didMoveToWindow { [super didMoveToWindow]; } @end @interface FirstViewController () @property (nonatomic, strong) NSString* colorSeedString; @property (nonatomic) NSInteger colorSeedCount; @end @implementation FirstViewController { __weak IBOutlet UIButton *_galleryButton; __weak IBOutlet UIButton *_nextButton; __weak IBOutlet UIBarButtonItem *_barStyleButton; BOOL _alreadyPresentedAutomatically; } - (UITabBarItem *)tabBarItem { if(self.tabBarController != nil) { UIViewController* target = self; if(self.navigationController != nil) { target = self.navigationController; } super.tabBarItem.image = LNSystemImage([NSString stringWithFormat:@"%lu.square.fill", [self.tabBarController.viewControllers indexOfObject:target] + 1]); } return super.tabBarItem; } - (void)viewDidLoad { [super viewDidLoad]; if(self.colorSeedString == nil) { if(self.splitViewController != nil) { self.colorSeedString = [NSString stringWithFormat:@"%@", @(arc4random())]; } else if(self.tabBarController != nil) { NSUInteger tabIdx = [self.tabBarController.viewControllers indexOfObject:self.navigationController ?: self]; self.colorSeedString = [NSString stringWithFormat:@"tab_%@", @(tabIdx)]; } else if(self.navigationController != nil) { self.colorSeedString = [NSString stringWithFormat:@"tab_109"]; } else { self.colorSeedString = @"nil"; } self.colorSeedCount = 0; } NSString* seed = [NSString stringWithFormat:@"%@%@", self.colorSeedString, self.colorSeedCount == 0 ? @"" : [NSString stringWithFormat:@"%@", @(self.colorSeedCount)]]; if (@available(iOS 13.0, *)) { self.view.backgroundColor = LNSeedAdaptiveColor(seed); } else { self.view.backgroundColor = LNSeedLightColor(seed); } self.navigationController.delegate = self; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; //Ugly hack to fix tab bar tint color. self.tabBarController.view.tintColor = self.view.tintColor; //Ugly hack to fix split view controller tint color. self.splitViewController.view.tintColor = self.view.tintColor; //Ugly hack to fix navigation view controller tint color. self.navigationController.view.tintColor = self.view.tintColor; _galleryButton.titleLabel.adjustsFontForContentSizeCategory = YES; _nextButton.titleLabel.adjustsFontForContentSizeCategory = YES; _galleryButton.hidden = [self.parentViewController isKindOfClass:[UINavigationController class]]; _nextButton.hidden = self.navigationController == nil || self.splitViewController != nil; if(self.tabBarController == nil || self.navigationController.topViewController == self.navigationController.viewControllers.firstObject) { [self _presentBar:nil animated:NO]; } } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; } - (void)dealloc { } - (IBAction)_changeBarStyle:(id)sender { if (@available(iOS 13.0, *)) { UIUserInterfaceStyle currentStyle = self.navigationController.traitCollection.userInterfaceStyle; self.navigationController.overrideUserInterfaceStyle = currentStyle == UIUserInterfaceStyleLight ? UIUserInterfaceStyleDark : UIUserInterfaceStyleLight; } else { self.navigationController.toolbar.barStyle = 1 - self.navigationController.toolbar.barStyle; } self.navigationController.toolbar.tintColor = LNRandomSystemColor(); [self.navigationController.toolbar.items enumerateObjectsUsingBlock:^(UIBarButtonItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { obj.tintColor = self.navigationController.toolbar.tintColor; }]; self.navigationController.navigationBar.barStyle = self.navigationController.toolbar.barStyle; self.navigationController.navigationBar.tintColor = self.navigationController.toolbar.tintColor; [self.navigationController setNeedsPopupBarAppearanceUpdate]; } - (UIViewController*)_targetVCForPopup { if([self.splitViewController isKindOfClass:SplitViewControllerPrimaryPopup.class] && self.navigationController != [self.ln_splitViewController viewControllerForColumn:LNSplitViewControllerColumnPrimary]) { return nil; } NSMutableArray* vcs = @[self].mutableCopy; if(self.navigationController) { [vcs addObject:self.navigationController]; } if([self.splitViewController isKindOfClass:SplitViewControllerSecondaryPopup.class] && [vcs containsObject:[self.ln_splitViewController viewControllerForColumn:LNSplitViewControllerColumnPrimary]]) { return nil; } if([self.splitViewController isKindOfClass:SplitViewControllerSecondaryPopup.class] && [vcs containsObject:[self.ln_splitViewController viewControllerForColumn:LNSplitViewControllerColumnSupplementary]]) { return nil; } if([self.splitViewController isKindOfClass:SplitViewControllerGlobalPopup.class]) { return self.splitViewController; } UIViewController* targetVC = self.tabBarController; if(targetVC == nil) { targetVC = self.navigationController; if(targetVC == nil) { targetVC = self; } } return targetVC; } - (IBAction)_presentBar:(id)sender { [self _presentBar:sender animated:YES]; } - (void)_presentBar:(id)sender animated:(BOOL)animated; { #if LNPOPUP if(_alreadyPresentedAutomatically == YES && sender == nil) { return; } if(sender == nil) { _alreadyPresentedAutomatically = YES; } UIViewController* targetVC = [self _targetVCForPopup]; if(targetVC == nil) { return; } if(targetVC.popupContentViewController != nil) { return; } if(targetVC == self.navigationController && self.navigationController.viewControllers.count > 1 && self.splitViewController == nil && sender == nil) { return; } // UIViewController* demoVC = [self.storyboard instantiateViewControllerWithIdentifier:@"SettingsTableViewController"]; UIViewController* demoVC = [DemoPopupContentViewController new]; uint32_t titleLowerLimit = 2; uint32_t titleUpperLimit = 5; uint32_t subtitleLowerLimit = 4; uint32_t subtitleUpperLimit = 16; demoVC.popupItem.title = [[LoremIpsum wordsWithNumber:arc4random_uniform(titleUpperLimit - titleLowerLimit) + titleLowerLimit] capitalizedString]; demoVC.popupItem.subtitle = [[LoremIpsum wordsWithNumber:arc4random_uniform(subtitleUpperLimit - subtitleLowerLimit) + subtitleLowerLimit] valueForKey:@"li_stringByCapitalizingFirstLetter"]; if([NSUserDefaults.standardUserDefaults boolForKey:@"NSForceRightToLeftWritingDirection"]) { demoVC.popupItem.title = [demoVC.popupItem.title stringByApplyingTransform:NSStringTransformLatinToHebrew reverse:NO]; demoVC.popupItem.subtitle = [demoVC.popupItem.subtitle stringByApplyingTransform:NSStringTransformLatinToHebrew reverse:NO]; } demoVC.popupItem.image = [UIImage imageNamed:@"genre7"]; demoVC.popupItem.progress = (float) arc4random() / UINT32_MAX; LNPopupCloseButtonStyle closeButtonStyle = [[[NSUserDefaults standardUserDefaults] objectForKey:PopupSettingsCloseButtonStyle] unsignedIntegerValue]; UILabel* topLabel = [UILabel new]; topLabel.text = NSLocalizedString(@"Top", @""); if (@available(iOS 13.0, *)) { topLabel.textColor = [UIColor systemBackgroundColor]; } else { topLabel.textColor = [UIColor lightTextColor]; } topLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; topLabel.translatesAutoresizingMaskIntoConstraints = NO; [demoVC.view addSubview:topLabel]; CGFloat offset = #if ! TARGET_OS_MACCATALYST closeButtonStyle == LNPopupCloseButtonStyleDefault || #endif closeButtonStyle == LNPopupCloseButtonStyleChevron || closeButtonStyle == LNPopupCloseButtonStyleGrabber ? 40 : 0; [NSLayoutConstraint activateConstraints:@[ [topLabel.topAnchor constraintEqualToAnchor:demoVC.view.safeAreaLayoutGuide.topAnchor], [topLabel.centerXAnchor constraintEqualToAnchor:demoVC.view.safeAreaLayoutGuide.centerXAnchor constant:offset] ]]; UILabel* bottomLabel = [UILabel new]; bottomLabel.text = NSLocalizedString(@"Bottom", @""); if (@available(iOS 13.0, *)) { bottomLabel.textColor = [UIColor systemBackgroundColor]; } else { bottomLabel.textColor = [UIColor lightTextColor]; } bottomLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; bottomLabel.translatesAutoresizingMaskIntoConstraints = NO; [demoVC.view addSubview:bottomLabel]; [NSLayoutConstraint activateConstraints:@[ [bottomLabel.bottomAnchor constraintEqualToAnchor:demoVC.view.safeAreaLayoutGuide.bottomAnchor], [bottomLabel.centerXAnchor constraintEqualToAnchor:demoVC.view.safeAreaLayoutGuide.centerXAnchor] ]]; demoVC.popupItem.accessibilityLabel = NSLocalizedString(@"Custom popup bar accessibility label", @""); demoVC.popupItem.accessibilityHint = NSLocalizedString(@"Custom popup bar accessibility hint", @""); targetVC.popupContentView.popupCloseButton.accessibilityLabel = NSLocalizedString(@"Custom popup button accessibility label", @""); targetVC.popupContentView.popupCloseButton.accessibilityHint = NSLocalizedString(@"Custom popup button accessibility hint", @""); targetVC.popupBar.progressViewStyle = [[[NSUserDefaults standardUserDefaults] objectForKey:PopupSettingsProgressViewStyle] unsignedIntegerValue]; targetVC.popupBar.barStyle = [[[NSUserDefaults standardUserDefaults] objectForKey:PopupSettingsBarStyle] unsignedIntegerValue]; targetVC.popupInteractionStyle = [[[NSUserDefaults standardUserDefaults] objectForKey:PopupSettingsInteractionStyle] unsignedIntegerValue]; targetVC.popupContentView.popupCloseButtonStyle = closeButtonStyle; targetVC.shouldExtendPopupBarUnderSafeArea = [NSUserDefaults.standardUserDefaults boolForKey:PopupSettingsExtendBar]; // if (@available(iOS 13.0, *)) // { // UIContextMenuInteraction* i = [[UIContextMenuInteraction alloc] initWithDelegate:self]; // [targetVC.popupBar addInteraction:i]; // } targetVC.popupPresentationDelegate = self; [targetVC presentPopupBarWithContentViewController:demoVC animated:animated completion:nil]; #endif } - (IBAction)_dismissBar:(id)sender { #if LNPOPUP __kindof UIViewController* targetVC = [self _targetVCForPopup]; [targetVC dismissPopupBarAnimated:YES completion:nil]; #endif } - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { segue.destinationViewController.hidesBottomBarWhenPushed = [NSUserDefaults.standardUserDefaults boolForKey:PopupSettingsHidesBottomBarWhenPushed]; if([segue.destinationViewController isKindOfClass:FirstViewController.class]) { [(FirstViewController*)segue.destinationViewController setColorSeedString:self.colorSeedString]; [(FirstViewController*)segue.destinationViewController setColorSeedCount:self.colorSeedCount + 1]; } } #pragma mark UINavigationControllerDelegate - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated { //Mask Apple's push bug. This uses private API, so don't copy it as is in your app! if(@available(iOS 14.0, *)) { UIViewController* disappearing = [navigationController valueForKey:@"disappearingViewController"]; UIViewController* target = viewController; BOOL isPushing = [[navigationController valueForKey:@"isPushing"] boolValue]; self.tabBarController.view.backgroundColor = (isPushing ? target : disappearing).view.backgroundColor; } } #pragma mark UIContextMenuInteractionDelegate #if LNPOPUP - (nullable UIContextMenuConfiguration *)contextMenuInteraction:(UIContextMenuInteraction *)interaction configurationForMenuAtLocation:(CGPoint)location API_AVAILABLE(ios(13.0)) { return [UIContextMenuConfiguration configurationWithIdentifier:nil previewProvider:nil actionProvider:nil]; } - (void)contextMenuInteraction:(UIContextMenuInteraction *)interaction willEndForConfiguration:(UIContextMenuConfiguration *)configuration animator:(nullable id)animator API_AVAILABLE(ios(13.0)) { [animator addAnimations:^{ UIActivityViewController* avc = [[UIActivityViewController alloc] initWithActivityItems:@[[NSURL URLWithString:@"https://github.com/LeoNatan/LNPopupController"]] applicationActivities:nil]; avc.modalPresentationStyle = UIModalPresentationFormSheet; avc.popoverPresentationController.sourceView = [self _targetVCForPopup].popupBar; [self presentViewController:avc animated:YES completion:nil]; }]; [animator addCompletion:^{ }]; } #endif #pragma mark LNPopupPresentationDelegate - (void)popupPresentationControllerWillPresentPopupBar:(UIViewController*)popupPresentationController animated:(BOOL)animated { } - (void)popupPresentationControllerDidPresentPopupBar:(UIViewController*)popupPresentationController animated:(BOOL)animated { } - (void)popupPresentationControllerWillDismissPopupBar:(UIViewController*)popupPresentationController animated:(BOOL)animated { } - (void)popupPresentationControllerDidDismissPopupBar:(UIViewController*)popupPresentationController animated:(BOOL)animated { } - (void)popupPresentationController:(UIViewController *)popupPresentationController willOpenPopupWithContentController:(UIViewController *)popupContentController animated:(BOOL)animated { } - (void)popupPresentationController:(UIViewController *)popupPresentationController didOpenPopupWithContentController:(UIViewController *)popupContentController animated:(BOOL)animated { } - (void)popupPresentationController:(UIViewController *)popupPresentationController willClosePopupWithContentController:(UIViewController *)popupContentController animated:(BOOL)animated { } - (void)popupPresentationController:(UIViewController *)popupPresentationController didClosePopupWithContentController:(UIViewController *)popupContentController animated:(BOOL)animated { } @end @interface PassthroughNavigationController : UINavigationController @end @implementation PassthroughNavigationController - (UITabBarItem *)tabBarItem { return self.viewControllers.firstObject.tabBarItem; } @end