├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── bug-report.yml │ ├── config.yml │ └── feature-request.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── LNPCSwiftRefinements └── SwiftRefinements.swift ├── LNPopupController ├── Info.plist ├── LNPopupController.h ├── LNPopupController.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── LNPopupController.xcscheme ├── LNPopupController │ ├── LNPopupBar.h │ ├── LNPopupBarAppearance.h │ ├── LNPopupCloseButton.h │ ├── LNPopupContentView.h │ ├── LNPopupCustomBarViewController.h │ ├── LNPopupDefinitions.h │ ├── LNPopupImageView.h │ ├── LNPopupItem.h │ ├── Private │ │ ├── LNChevronView.h │ │ ├── LNChevronView.m │ │ ├── LNForwardingDelegate.h │ │ ├── LNForwardingDelegate.m │ │ ├── LNMath.h │ │ ├── LNMath.m │ │ ├── LNPopupBar+Private.h │ │ ├── LNPopupBar.mm │ │ ├── LNPopupBarAppearance+Private.h │ │ ├── LNPopupBarAppearance.mm │ │ ├── LNPopupBarAppearanceChainProxy.h │ │ ├── LNPopupBarAppearanceChainProxy.m │ │ ├── LNPopupBarExtras.mm │ │ ├── LNPopupCloseButton+Private.h │ │ ├── LNPopupCloseButton.mm │ │ ├── LNPopupContentView+Private.h │ │ ├── LNPopupContentView.m │ │ ├── LNPopupController.h │ │ ├── LNPopupController.mm │ │ ├── LNPopupCustomBarViewController+Private.h │ │ ├── LNPopupCustomBarViewController.m │ │ ├── LNPopupDebug.h │ │ ├── LNPopupDebug.m │ │ ├── LNPopupImageView+Private.h │ │ ├── LNPopupImageView.mm │ │ ├── LNPopupInteractionPanGestureRecognizer.h │ │ ├── LNPopupInteractionPanGestureRecognizer.m │ │ ├── LNPopupItem+Private.h │ │ ├── LNPopupItem.m │ │ ├── LNPopupLongPressGestureRecognizer.h │ │ ├── LNPopupLongPressGestureRecognizer.m │ │ ├── LNPopupOpenTapGestureRecognizer.h │ │ ├── LNPopupOpenTapGestureRecognizer.m │ │ ├── LNPopupPresentationContainerSupport.h │ │ ├── LNPopupPresentationContainerSupport.m │ │ ├── MarqueeLabel.h │ │ ├── MarqueeLabel.m │ │ ├── NSAttributedString+LNPopupSupport.h │ │ ├── NSAttributedString+LNPopupSupport.m │ │ ├── UIContextMenuInteraction+LNPopupSupportPrivate.h │ │ ├── UIContextMenuInteraction+LNPopupSupportPrivate.mm │ │ ├── UIView+LNPopupSupportPrivate.h │ │ ├── UIView+LNPopupSupportPrivate.mm │ │ ├── UIViewController+LNPopupSupport.mm │ │ ├── UIViewController+LNPopupSupportPrivate.h │ │ ├── UIViewController+LNPopupSupportPrivate.mm │ │ ├── _LNPopupAddressInfo.h │ │ ├── _LNPopupAddressInfo.mm │ │ ├── _LNPopupBackgroundShadowView.h │ │ ├── _LNPopupBackgroundShadowView.m │ │ ├── _LNPopupBarBackgroundMaskView.h │ │ ├── _LNPopupBarBackgroundMaskView.m │ │ ├── _LNPopupBarBackgroundView.h │ │ ├── _LNPopupBarBackgroundView.m │ │ ├── _LNPopupBase64Utils.hh │ │ ├── _LNPopupSwizzlingUtils.h │ │ ├── _LNPopupSwizzlingUtils.m │ │ ├── _LNPopupTransitionAnimator.h │ │ ├── _LNPopupTransitionAnimator.mm │ │ ├── _LNPopupTransitionCloseAnimator.h │ │ ├── _LNPopupTransitionCloseAnimator.m │ │ ├── _LNPopupTransitionGenericCloseAnimator.h │ │ ├── _LNPopupTransitionGenericCloseAnimator.m │ │ ├── _LNPopupTransitionGenericOpenAnimator.h │ │ ├── _LNPopupTransitionGenericOpenAnimator.m │ │ ├── _LNPopupTransitionOpenAnimator.h │ │ ├── _LNPopupTransitionOpenAnimator.m │ │ ├── _LNPopupTransitionPreferredCloseAnimator.h │ │ ├── _LNPopupTransitionPreferredCloseAnimator.mm │ │ ├── _LNPopupTransitionPreferredOpenAnimator.h │ │ ├── _LNPopupTransitionPreferredOpenAnimator.mm │ │ ├── _LNPopupTransitionView.h │ │ ├── _LNPopupTransitionView.mm │ │ ├── _LNPopupUIBarAppearanceProxy.h │ │ ├── _LNPopupUIBarAppearanceProxy.mm │ │ ├── _LNWeakRef.h │ │ └── _LNWeakRef.m │ └── UIViewController+LNPopupSupport.h └── include │ └── LNPopupController │ ├── LNPopupBar.h │ ├── LNPopupBarAppearance.h │ ├── LNPopupCloseButton.h │ ├── LNPopupContentView.h │ ├── LNPopupController.h │ ├── LNPopupCustomBarViewController.h │ ├── LNPopupDefinitions.h │ ├── LNPopupImageView.h │ ├── LNPopupItem.h │ └── UIViewController+LNPopupSupport.h ├── LNPopupControllerExample ├── LNPopupControllerExample.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ ├── LNPopupControllerExample.xcscheme │ │ └── LNPopupControllerExampleNoPopup.xcscheme └── LNPopupControllerExample │ ├── CustomBarScene │ ├── Base.lproj │ │ └── MapScene.storyboard │ ├── CustomMapBarViewController.swift │ ├── LocationsController.swift │ └── MapViewController.swift │ ├── CustomBarScene_ManualLayout │ ├── Base.lproj │ │ └── ManualLayoutScene.storyboard │ └── ManualLayoutCustomBarViewController.swift │ ├── Info.plist │ ├── LNPopupControllerExample.entitlements │ ├── LNPopupControllerExampleNoPopup-Info.plist │ ├── MusicScene │ ├── Base.lproj │ │ └── Music.storyboard │ ├── DemoAlbumTableViewController.swift │ ├── DemoMusicPlayerController.swift │ ├── MusicCell.swift │ └── PortraitTabBarController.swift │ ├── Settings │ └── Base.lproj │ │ └── Settings.storyboard │ ├── Supporting │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-dark.png │ │ │ ├── Icon-tinted.png │ │ │ └── icon_1024.png │ │ ├── AppIconPopupBar.imageset │ │ │ ├── Contents.json │ │ │ ├── Icon-dark.png │ │ │ └── icon_1024.png │ │ ├── Contents.json │ │ ├── demoAlbum.imageset │ │ │ ├── Contents.json │ │ │ └── smackandtoss-blue-orange-abstract-fog-ipad-wallpaper.jpg │ │ ├── gears.imageset │ │ │ ├── Contents.json │ │ │ └── gears.pdf │ │ ├── genre1.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-80s-hits.png │ │ │ ├── genre-image-80s-hits@2x.png │ │ │ └── genre-image-80s-hits@3x.png │ │ ├── genre10.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-country-hits.png │ │ │ ├── genre-image-country-hits@2x.png │ │ │ └── genre-image-country-hits@3x.png │ │ ├── genre11.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-dance.png │ │ │ ├── genre-image-dance@2x.png │ │ │ └── genre-image-dance@3x.png │ │ ├── genre12.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-decades.png │ │ │ ├── genre-image-decades@2x.png │ │ │ └── genre-image-decades@3x.png │ │ ├── genre13.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-electronic.png │ │ │ ├── genre-image-electronic@2x.png │ │ │ └── genre-image-electronic@3x.png │ │ ├── genre14.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-gospel.png │ │ │ ├── genre-image-gospel@2x.png │ │ │ └── genre-image-gospel@3x.png │ │ ├── genre15.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-hip-hop.png │ │ │ ├── genre-image-hip-hop@2x.png │ │ │ └── genre-image-hip-hop@3x.png │ │ ├── genre16.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-indie.png │ │ │ ├── genre-image-indie@2x.png │ │ │ └── genre-image-indie@3x.png │ │ ├── genre17-expanded.imageset │ │ │ ├── Contents.json │ │ │ └── genre-image-jazz-expanded.jpg │ │ ├── genre17.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-jazz.png │ │ │ ├── genre-image-jazz@2x.png │ │ │ └── genre-image-jazz@3x.png │ │ ├── genre18.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-kids-and-family.png │ │ │ ├── genre-image-kids-and-family@2x.png │ │ │ └── genre-image-kids-and-family@3x.png │ │ ├── genre19.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-latin-hits.png │ │ │ ├── genre-image-latin-hits@2x.png │ │ │ └── genre-image-latin-hits@3x.png │ │ ├── genre2.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-alternative.png │ │ │ ├── genre-image-alternative@2x.png │ │ │ └── genre-image-alternative@3x.png │ │ ├── genre20.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-metal.png │ │ │ ├── genre-image-metal@2x.png │ │ │ └── genre-image-metal@3x.png │ │ ├── genre21.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-modern-rock.png │ │ │ ├── genre-image-modern-rock@2x.png │ │ │ └── genre-image-modern-rock@3x.png │ │ ├── genre22.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-pop-gold.png │ │ │ ├── genre-image-pop-gold@2x.png │ │ │ └── genre-image-pop-gold@3x.png │ │ ├── genre23.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-pop-hits.png │ │ │ ├── genre-image-pop-hits@2x.png │ │ │ └── genre-image-pop-hits@3x.png │ │ ├── genre24.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-randb.png │ │ │ ├── genre-image-randb@2x.png │ │ │ └── genre-image-randb@3x.png │ │ ├── genre25.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-reggae.png │ │ │ ├── genre-image-reggae@2x.png │ │ │ └── genre-image-reggae@3x.png │ │ ├── genre26.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-regional-mexican.png │ │ │ ├── genre-image-regional-mexican@2x.png │ │ │ └── genre-image-regional-mexican@3x.png │ │ ├── genre27.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-singer-songwriter.png │ │ │ ├── genre-image-singer-songwriter@2x.png │ │ │ └── genre-image-singer-songwriter@3x.png │ │ ├── genre28.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-smooth-jazz.png │ │ │ ├── genre-image-smooth-jazz@2x.png │ │ │ └── genre-image-smooth-jazz@3x.png │ │ ├── genre29.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-smooth-pop.png │ │ │ ├── genre-image-smooth-pop@2x.png │ │ │ └── genre-image-smooth-pop@3x.png │ │ ├── genre3.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-blues.png │ │ │ ├── genre-image-blues@2x.png │ │ │ └── genre-image-blues@3x.png │ │ ├── genre30.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-world-hits.png │ │ │ ├── genre-image-world-hits@2x.png │ │ │ └── genre-image-world-hits@3x.png │ │ ├── genre4.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-christian.png │ │ │ ├── genre-image-christian@2x.png │ │ │ └── genre-image-christian@3x.png │ │ ├── genre5.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-classic-alt.png │ │ │ ├── genre-image-classic-alt@2x.png │ │ │ └── genre-image-classic-alt@3x.png │ │ ├── genre6.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-classic-country.png │ │ │ ├── genre-image-classic-country@2x.png │ │ │ └── genre-image-classic-country@3x.png │ │ ├── genre7.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-classic-randb.png │ │ │ ├── genre-image-classic-randb@2x.png │ │ │ └── genre-image-classic-randb@3x.png │ │ ├── genre8.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-classic-rock.png │ │ │ ├── genre-image-classic-rock@2x.png │ │ │ └── genre-image-classic-rock@3x.png │ │ ├── genre9.imageset │ │ │ ├── Contents.json │ │ │ ├── genre-image-classical.png │ │ │ ├── genre-image-classical@2x.png │ │ │ └── genre-image-classical@3x.png │ │ ├── genre_white.imageset │ │ │ ├── Contents.json │ │ │ ├── genre_black.png │ │ │ └── genre_white.png │ │ └── statusBarMask.imageset │ │ │ ├── Contents.json │ │ │ └── mask.png │ ├── LNPopupControllerExample-Bridging-Header.h │ ├── LaunchScreen.storyboard │ ├── SceneDelegate.h │ ├── SceneDelegate.m │ └── main.m │ ├── TestingScene │ ├── Base.lproj │ │ └── Main.storyboard │ ├── DemoGallery.h │ ├── DemoGallery.m │ ├── DemoPopupContentViewController.h │ ├── DemoPopupContentViewController.m │ ├── DemoViewController.h │ ├── DemoViewController.m │ ├── IntroWebViewController.h │ ├── IntroWebViewController.m │ ├── LNPopupControllerExampleSupport.h │ ├── LNPopupControllerExampleSupport.m │ ├── LNPopupDemoContextMenuInteraction.h │ ├── LNPopupDemoContextMenuInteraction.m │ ├── LNSplitViewController.h │ ├── LNSplitViewController.m │ ├── PageCardViewController.swift │ ├── ScrollingColorsPageViewController.swift │ ├── ScrollingColorsViewController.swift │ └── ScrollingMapViewController.swift │ └── Utils │ ├── RandomColors.h │ ├── RandomColors.m │ ├── SafeSystemImages.h │ └── SafeSystemImages.m ├── Package.swift ├── README.md ├── Supplements ├── Artwork.png ├── Icon-dark.psd ├── Icon.psd ├── close_button_chevron.png ├── close_button_none.png ├── close_button_round.png ├── compact_custom.png ├── custom_bar.png ├── default_bar_accessibility_label.png ├── floating_bar_style.gif ├── floating_custom.png ├── floating_no_scroll.gif ├── hidesBottomBar_TabBar.gif ├── hidesBottomBar_Toolbar.gif ├── interaction_drag.gif ├── interaction_snap.gif ├── modern_custom.png ├── modern_no_scroll.gif ├── open_floating_popup.gif ├── pointer_interaction.gif ├── popup_bar_context_menu.png ├── popup_transitions.gif ├── progress_view_bottom.png ├── progress_view_none.png ├── progress_view_top.png ├── rtl_english.png ├── rtl_hebrew.png ├── scroll.gif ├── scroll_edge_appearance.gif ├── statusbar_hidden.gif ├── statusbar_style.gif ├── tab_bar_sidebar_floating.gif ├── tab_bar_sidebar_landscape_floating.png └── tab_bar_sidebar_prominent.gif ├── releaseVersion.sh └── update_copyright.sh /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | github: LeoNatan 3 | custom: ['paypal.me/LeoNatan25'] 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.yml: -------------------------------------------------------------------------------- 1 | name: "Bug Report" 2 | description: "Report an issue." 3 | labels: [bug] 4 | body: 5 | - type: textarea 6 | attributes: 7 | label: "Describe the Bug:" 8 | description: "A clear and concise description of what the bug is." 9 | validations: 10 | required: true 11 | - type: textarea 12 | attributes: 13 | label: "Reproduction:" 14 | description: "Steps to reproduce the behavior." 15 | placeholder: | 16 | 1. Go to '...' 17 | 2. Click on '....' 18 | 3. Scroll down to '....' 19 | 4. See error 20 | validations: 21 | required: true 22 | - type: textarea 23 | attributes: 24 | label: "Expected Behavior:" 25 | description: "A clear and concise description of what you expected to happen." 26 | validations: 27 | required: true 28 | - type: textarea 29 | attributes: 30 | label: "Screenshots and/or Videos:" 31 | description: "If applicable, add screenshots and/or videos to help explain your problem." 32 | placeholder: "Drag and drop files here" 33 | validations: 34 | required: false 35 | - type: textarea 36 | attributes: 37 | label: "Additional Context:" 38 | description: "Add any other context about the problem here." 39 | validations: 40 | required: false -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Ask a Question 4 | url: https://github.com/LeoNatan/LNPopupController/discussions/new/choose 5 | about: Please ask questions in Discussions -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | name: "Feature Request" 2 | description: "Suggest an idea for this project." 3 | labels: [enhancement] 4 | body: 5 | - type: textarea 6 | attributes: 7 | label: "Describe the Solution You'd Like:" 8 | description: "A clear and concise description of what you want to happen." 9 | validations: 10 | required: true 11 | - type: textarea 12 | attributes: 13 | label: "Describe Alternatives You've Considered:" 14 | description: "A clear and concise description of any alternative solutions or features you've considered." 15 | validations: 16 | required: false 17 | - type: textarea 18 | attributes: 19 | label: "Additional Context:" 20 | description: "Add any other context or screenshots about the feature request here." 21 | validations: 22 | required: true 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | # CocoaPods 32 | # 33 | # We recommend against adding the Pods directory to your .gitignore. However 34 | # you should judge for yourself, the pros and cons are mentioned at: 35 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 36 | # 37 | # Pods/ 38 | 39 | # Carthage 40 | # 41 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 42 | # Carthage/Checkouts 43 | 44 | Carthage/Build 45 | 46 | # fastlane 47 | # 48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 49 | # screenshots whenever they are needed. 50 | # For more information about the recommended setup visit: 51 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 52 | 53 | fastlane/report.xml 54 | fastlane/Preview.html 55 | fastlane/screenshots 56 | fastlane/test_output 57 | 58 | # Code Injection 59 | # 60 | # After new code Injection tools there's a generated folder /iOSInjectionProject 61 | # https://github.com/johnno1962/injectionforxcode 62 | 63 | iOSInjectionProject/ 64 | .swiftpm 65 | swiftpm 66 | _tmp_release_notes.md -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "LNPopupSettings"] 2 | path = LNPopupSettings 3 | url = https://LeoNatan@github.com/LeoNatan/LNPopupSettings.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2024 Léo Natan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /LNPopupController/Info.plist: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3 | <plist version="1.0"> 4 | <dict> 5 | <key>CFBundleExecutable</key> 6 | <string>$(EXECUTABLE_NAME)</string> 7 | <key>CFBundleIdentifier</key> 8 | <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> 9 | <key>CFBundlePackageType</key> 10 | <string>FMWK</string> 11 | <key>CFBundleShortVersionString</key> 12 | <string>3.0.7</string> 13 | <key>CFBundleVersion</key> 14 | <string>1</string> 15 | <key>LSRequiresIPhoneOS</key> 16 | <true/> 17 | </dict> 18 | </plist> 19 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupController.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2015-08-23. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <LNPopupController/LNPopupDefinitions.h> 10 | #import <LNPopupController/LNPopupContentView.h> 11 | #import <LNPopupController/LNPopupCloseButton.h> 12 | #import <LNPopupController/LNPopupItem.h> 13 | #import <LNPopupController/LNPopupBar.h> 14 | #import <LNPopupController/LNPopupCustomBarViewController.h> 15 | #import <LNPopupController/UIViewController+LNPopupSupport.h> 16 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <Workspace 3 | version = "1.0"> 4 | <FileRef 5 | location = "self:"> 6 | </FileRef> 7 | </Workspace> 8 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3 | <plist version="1.0"> 4 | <dict> 5 | <key>IDEDidComputeMac32BitWarning</key> 6 | <true/> 7 | </dict> 8 | </plist> 9 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController.xcodeproj/xcshareddata/xcschemes/LNPopupController.xcscheme: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <Scheme 3 | LastUpgradeVersion = "9999" 4 | version = "1.3"> 5 | <BuildAction 6 | parallelizeBuildables = "YES" 7 | buildImplicitDependencies = "YES"> 8 | <BuildActionEntries> 9 | <BuildActionEntry 10 | buildForTesting = "YES" 11 | buildForRunning = "YES" 12 | buildForProfiling = "YES" 13 | buildForArchiving = "YES" 14 | buildForAnalyzing = "YES"> 15 | <BuildableReference 16 | BuildableIdentifier = "primary" 17 | BlueprintIdentifier = "39DB52E41B5823330061C589" 18 | BuildableName = "LNPopupController.framework" 19 | BlueprintName = "LNPopupController" 20 | ReferencedContainer = "container:LNPopupController.xcodeproj"> 21 | </BuildableReference> 22 | </BuildActionEntry> 23 | </BuildActionEntries> 24 | </BuildAction> 25 | <TestAction 26 | buildConfiguration = "Debug" 27 | selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" 28 | selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" 29 | shouldUseLaunchSchemeArgsEnv = "YES"> 30 | <Testables> 31 | </Testables> 32 | </TestAction> 33 | <LaunchAction 34 | buildConfiguration = "Debug" 35 | selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" 36 | selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" 37 | launchStyle = "0" 38 | useCustomWorkingDirectory = "NO" 39 | ignoresPersistentStateOnLaunch = "NO" 40 | debugDocumentVersioning = "YES" 41 | debugServiceExtension = "internal" 42 | allowLocationSimulation = "YES"> 43 | <MacroExpansion> 44 | <BuildableReference 45 | BuildableIdentifier = "primary" 46 | BlueprintIdentifier = "39DB52E41B5823330061C589" 47 | BuildableName = "LNPopupController.framework" 48 | BlueprintName = "LNPopupController" 49 | ReferencedContainer = "container:LNPopupController.xcodeproj"> 50 | </BuildableReference> 51 | </MacroExpansion> 52 | </LaunchAction> 53 | <ProfileAction 54 | buildConfiguration = "Release" 55 | shouldUseLaunchSchemeArgsEnv = "YES" 56 | savedToolIdentifier = "" 57 | useCustomWorkingDirectory = "NO" 58 | debugDocumentVersioning = "YES"> 59 | <MacroExpansion> 60 | <BuildableReference 61 | BuildableIdentifier = "primary" 62 | BlueprintIdentifier = "39DB52E41B5823330061C589" 63 | BuildableName = "LNPopupController.framework" 64 | BlueprintName = "LNPopupController" 65 | ReferencedContainer = "container:LNPopupController.xcodeproj"> 66 | </BuildableReference> 67 | </MacroExpansion> 68 | </ProfileAction> 69 | <AnalyzeAction 70 | buildConfiguration = "Debug"> 71 | </AnalyzeAction> 72 | <ArchiveAction 73 | buildConfiguration = "Release" 74 | revealArchiveInOrganizer = "YES"> 75 | </ArchiveAction> 76 | </Scheme> 77 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/LNPopupCloseButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupCloseButton.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2015-08-23. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | #import <LNPopupController/LNPopupDefinitions.h> 11 | 12 | /// Available styles for the popup close button. 13 | typedef NS_ENUM(NSInteger, LNPopupCloseButtonStyle) { 14 | /// The default close button style for the current environment. 15 | LNPopupCloseButtonStyleDefault, 16 | 17 | /// Round close button style. 18 | LNPopupCloseButtonStyleRound, 19 | 20 | /// Chevron close button style. 21 | LNPopupCloseButtonStyleChevron, 22 | 23 | /// Grabber close button style. 24 | LNPopupCloseButtonStyleGrabber, 25 | 26 | /// No close button. 27 | LNPopupCloseButtonStyleNone = 0xFFFF, 28 | 29 | LNPopupCloseButtonStyleFlat LN_DEPRECATED_API("Use LNPopupCloseButtonStyle.grabber instead.") = LNPopupCloseButtonStyleGrabber 30 | } NS_SWIFT_NAME(LNPopupCloseButton.Style); 31 | 32 | NS_ASSUME_NONNULL_BEGIN 33 | 34 | /// The popup content close button. 35 | NS_SWIFT_UI_ACTOR 36 | @interface LNPopupCloseButton : UIButton <UIAppearanceContainer> 37 | 38 | /// Gets or sets the style of the popup close button. Has the same effect as setting the `LNPopupContentView.popupCloseButtonStyle` property of the popup content view. 39 | @property (nonatomic, assign) LNPopupCloseButtonStyle style UI_APPEARANCE_SELECTOR; 40 | 41 | /// The effective popup close button style used by the system. (read-only) 42 | /// 43 | /// Use this property's value to determine, at runtime, what the result of `LNPopupCloseButtonStyleDefault` is. 44 | @property (nonatomic, assign, readonly) LNPopupCloseButtonStyle effectiveStyle; 45 | 46 | /// The button’s background view. (read-only) 47 | /// 48 | /// The value of this property will be `nil` if `style` is set to any value other than `LNPopupCloseButtonStyleRound`. 49 | /// 50 | /// @note Although this property is read-only, its own properties are read/write. Use these properties to configure the appearance and behavior of the button’s background view. 51 | @property (nonatomic, strong, readonly) UIVisualEffectView* backgroundView; 52 | 53 | @end 54 | 55 | NS_ASSUME_NONNULL_END 56 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/LNPopupContentView.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupItem.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2015-09-23. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | #import <LNPopupController/LNPopupDefinitions.h> 11 | #import <LNPopupController/LNPopupCloseButton.h> 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | NS_SWIFT_UI_ACTOR 16 | /// Holds the popup content container view, as well as the popup close button and the popup interaction gesture recognizer. 17 | @interface LNPopupContentView : UIView <UIAppearanceContainer> 18 | 19 | /// The gesture recognizer responsible for interactive opening and closing of the popup. (read-only) 20 | /// 21 | /// The system installs this gesture recognizer on either the popup bar or the popup content view and uses it to open or close the popup. 22 | /// Be careful with modifying this gesture recognizer. It is shared for interactively opening the popup by panning the popup bar (when it is closed), or interactively closing the popup interactively by panning the popup content view (when the popup is open). If you disable the gesture recognizer after opening the popup, you must monitor the state of the popup and reenable the gesture recognizer once closed by the user or through code. 23 | @property (nonatomic, strong, readonly) UIPanGestureRecognizer* popupInteractionGestureRecognizer; 24 | 25 | /// The popup close button style. 26 | /// 27 | /// Defaults to `LNPopupCloseButtonStyleDefault`. 28 | @property (nonatomic, assign) LNPopupCloseButtonStyle popupCloseButtonStyle UI_APPEARANCE_SELECTOR; 29 | 30 | /// The effective popup close button style used by the system. (read-only) 31 | /// 32 | /// Use this property's value to determine, at runtime, what the result of `LNPopupCloseButtonStyleDefault` is. 33 | @property (nonatomic, assign, readonly) LNPopupCloseButtonStyle effectivePopupCloseButtonStyle; 34 | 35 | /// The popup close button. (read-only) 36 | @property (nonatomic, strong, readonly) LNPopupCloseButton* popupCloseButton; 37 | 38 | /// The popup content view background effect, used when the popup content controller's view has transparency. 39 | /// 40 | /// Use `nil` value to inherit the popup bar's background effect if possible, or use a default effect. 41 | /// 42 | /// Defaults to `nil`. 43 | @property (nonatomic, copy, nullable) UIBlurEffect* backgroundEffect UI_APPEARANCE_SELECTOR; 44 | 45 | /// A Boolean value that indicates whether the popup content view is translucent (`true`) or not (`false`). 46 | /// 47 | /// Defaults to `true`. 48 | @property(nonatomic, assign, getter=isTranslucent) BOOL translucent UI_APPEARANCE_SELECTOR; 49 | 50 | @end 51 | 52 | NS_ASSUME_NONNULL_END 53 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/LNPopupCustomBarViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupBarContentViewController.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2016-12-30. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | #import <LNPopupController/LNPopupDefinitions.h> 11 | 12 | @class LNPopupBar; 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | NS_SWIFT_UI_ACTOR 17 | /// An object that manages a custom popup bar view hierarchy. 18 | /// 19 | /// Implement the `UIPointerInteractionDelegate` methods to customize pointer interactions. 20 | @interface LNPopupCustomBarViewController : UIViewController <UIPointerInteractionDelegate> 21 | 22 | /// The containing popup bar. (read-only) 23 | @property (nonatomic, weak, readonly, nullable) LNPopupBar* containingPopupBar; 24 | 25 | /// Indicates whether the default tap gesture recognizer should be added to the popup bar. 26 | /// 27 | /// Defaults to `true`. 28 | @property (nonatomic, assign, readonly) BOOL wantsDefaultTapGestureRecognizer; 29 | 30 | /// Indicates whether the default pan gesture recognizer should be added to the popup bar. 31 | /// 32 | /// Defaults to `true`. 33 | @property (nonatomic, assign, readonly) BOOL wantsDefaultPanGestureRecognizer; 34 | 35 | /// Indicates whether the default highlight gesture recognizer should be added to the popup bar. 36 | /// 37 | /// Defaults to `true`. 38 | @property (nonatomic, assign, readonly) BOOL wantsDefaultHighlightGestureRecognizer; 39 | 40 | /// The content size of the popup bar view. 41 | /// 42 | /// This property's value is used for height calculation of the popup bar. Update this property if you need to resize the popup bar. 43 | @property (nonatomic, assign) CGSize preferredContentSize; 44 | 45 | /// Called after the view has been loaded. For view controllers created in code, this is after `loadView()`. For view controllers unarchived from a nib, this is after the view is set. 46 | - (void)viewDidLoad NS_REQUIRES_SUPER; 47 | 48 | /// Called by the framework to notify the popup bar content view controller that one or more keys of the the popup item have been updated, or the entire popup item has changed. 49 | - (void)popupItemDidUpdate; 50 | 51 | /// Called by the framework no notify the popup bar content view controller that the custom bar is about to move to a popup bar. 52 | /// 53 | /// - Parameter newPopupBar: The new popup bar 54 | - (void)willMoveToPopupBar:(nullable LNPopupBar*)newPopupBar; 55 | 56 | /// Called by the framework no notify the popup bar content view controller that the custom bar has moved to a popup bar. 57 | - (void)didMoveToPopupBar; 58 | 59 | /// Called by the framework to notify the popup bar content view controller that the active appearance has changed. 60 | /// 61 | /// - Parameter activeAppearance: A merged appearance from the popup item, the system appearance and popup bar appearance, as appropriate. 62 | - (void)activeAppearanceDidChange:(LNPopupBarAppearance*)activeAppearance; 63 | 64 | @end 65 | 66 | NS_ASSUME_NONNULL_END 67 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/LNPopupDefinitions.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupDefinitions.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2021-12-16. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #ifndef LNPopupDefinitions_h 10 | #define LNPopupDefinitions_h 11 | 12 | #import <Foundation/Foundation.h> 13 | 14 | #ifndef NS_SWIFT_UI_ACTOR 15 | #define NS_SWIFT_UI_ACTOR 16 | #endif 17 | 18 | #ifndef NS_SWIFT_DISABLE_ASYNC 19 | #define NS_SWIFT_DISABLE_ASYNC 20 | #endif 21 | 22 | #define LN_UNAVAILABLE_API(x) __attribute__((unavailable(x))) 23 | #define LN_DEPRECATED_API(x) __attribute__((deprecated(x))) 24 | 25 | #endif /* LNPopupDefinitions_h */ 26 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/LNPopupImageView.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupImageView.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2025-03-24. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | /// A specialized `UIImageView` subclass, allowing setting a shadow and corner radius. 14 | /// 15 | /// When used inside a popup content view, instances of this class are especially suited as image transition targets. 16 | /// 17 | /// See `UIViewController.viewForPopupTransition(from:to:)`. 18 | @interface LNPopupImageView : UIImageView 19 | 20 | /// The corner radius of the image view. 21 | @property (nonatomic, assign) CGFloat cornerRadius; 22 | /// The shadow displayed underneath the image view. 23 | @property (nonatomic, copy) NSShadow* shadow; 24 | 25 | @end 26 | 27 | NS_ASSUME_NONNULL_END 28 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNChevronView.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNChevronView.h 3 | // 4 | // Created by Léo Natan on 2016-12-02. 5 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 6 | // 7 | 8 | #define LNChevronView __LNChevronView 9 | #define LNChevronViewState __LNChevronViewState 10 | #define LNChevronViewStateUp __LNChevronViewStateUp 11 | #define LNChevronViewStateFlat __LNChevronViewStateFlat 12 | #define LNChevronViewStateDown __LNChevronViewStateDown 13 | 14 | #import <UIKit/UIKit.h> 15 | 16 | NS_ASSUME_NONNULL_BEGIN 17 | 18 | typedef NS_ENUM(NSInteger, LNChevronViewState) { 19 | LNChevronViewStateUp = -1, 20 | LNChevronViewStateFlat = 0, 21 | LNChevronViewStateDown = 1 22 | }; 23 | 24 | @interface LNChevronView : UIView 25 | 26 | @property (nonatomic, assign) LNChevronViewState state; 27 | @property (nonatomic, assign) CGFloat width; 28 | @property (nonatomic, assign) NSTimeInterval animationDuration; 29 | 30 | - (void)setState:(LNChevronViewState)state animated:(BOOL)animated; 31 | 32 | @end 33 | 34 | NS_ASSUME_NONNULL_END 35 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNForwardingDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNForwardingDelegate.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2017-07-15. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <Foundation/Foundation.h> 10 | 11 | @interface LNForwardingDelegate : NSObject 12 | 13 | @property (nonatomic, weak) id forwardedDelegate; 14 | 15 | + (BOOL)isCallerUIKit:(NSArray*)callStackReturnAddresses; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNForwardingDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // LNForwardingDelegate.m 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2017-07-15. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "LNForwardingDelegate.h" 10 | #import "_LNPopupAddressInfo.h" 11 | 12 | @implementation LNForwardingDelegate 13 | 14 | - (BOOL)respondsToSelector:(SEL)aSelector 15 | { 16 | if([super respondsToSelector:aSelector]) 17 | { 18 | return YES; 19 | } 20 | 21 | return [self.forwardedDelegate respondsToSelector:aSelector]; 22 | } 23 | 24 | - (void)forwardInvocation:(NSInvocation *)anInvocation 25 | { 26 | [anInvocation invokeWithTarget:self.forwardedDelegate]; 27 | } 28 | 29 | - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 30 | { 31 | NSMethodSignature* ms = [super methodSignatureForSelector:aSelector]; 32 | 33 | if(ms) 34 | { 35 | return ms; 36 | } 37 | 38 | return [self.forwardedDelegate methodSignatureForSelector:aSelector]; 39 | } 40 | 41 | + (BOOL)isCallerUIKit:(NSArray *)callStackReturnAddresses 42 | { 43 | NSUInteger addr = [callStackReturnAddresses[1] unsignedIntegerValue]; 44 | _LNPopupAddressInfo* addrInfo = [[_LNPopupAddressInfo alloc] initWithAddress:addr]; 45 | 46 | return [addrInfo.image hasPrefix:@"UIKit"]; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNMath.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNMath.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2021-08-06. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #ifndef C__Math_h 10 | #define C__Math_h 11 | 12 | #import <CoreFoundation/CoreFoundation.h> 13 | 14 | CF_EXTERN_C_BEGIN 15 | 16 | extern double _ln_clamp(double v, double lo, double hi); 17 | 18 | CF_EXTERN_C_END 19 | 20 | #endif /* C__Math_h */ 21 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNMath.m: -------------------------------------------------------------------------------- 1 | // 2 | // LNMath. 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2021-08-11. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #include "LNMath.h" 10 | #import <Foundation/Foundation.h> 11 | 12 | double _ln_clamp(double v, double lo, double hi) 13 | { 14 | return MIN(hi, MAX(v, lo)); 15 | } 16 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNPopupBarAppearance+Private.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupBarAppearance+Private.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2021-06-20. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <LNPopupController/LNPopupBarAppearance.h> 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface _LNPopupDominantColorTrait : NSObject <UIObjectTraitDefinition> @end 14 | 15 | @protocol _LNPopupBarAppearanceDelegate <NSObject> 16 | 17 | - (void)popupBarAppearanceDidChange:(LNPopupBarAppearance*)popupBarAppearance; 18 | 19 | @end 20 | 21 | @interface LNPopupBarAppearance () 22 | 23 | @property (nonatomic, weak) id<_LNPopupBarAppearanceDelegate> delegate; 24 | 25 | - (UIBlurEffect *)floatingBackgroundEffectForTraitCollection:(UITraitCollection*)traitCollection; 26 | 27 | @end 28 | 29 | NS_ASSUME_NONNULL_END 30 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNPopupBarAppearanceChainProxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupBarAppearanceChainProxy.h 3 | // LNPopupBarAppearanceChainProxy 4 | // 5 | // Created by Léo Natan on 2021-08-07. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | #import "LNPopupBarAppearance+Private.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface LNPopupBarAppearanceChainProxy : NSObject 15 | 16 | @property (nonatomic, strong) NSArray<UIBarAppearance*>* chain; 17 | 18 | - (instancetype)initWithAppearanceChain:(NSArray<UIBarAppearance*>*)chain; 19 | - (id)objectForKey:(NSString*)key; 20 | - (BOOL)boolForKey:(NSString*)key; 21 | - (NSUInteger)unsignedIntegerForKey:(NSString*)key; 22 | - (double)doubleForKey:(NSString*)key; 23 | 24 | - (void)setChainDelegate:(nullable id<_LNPopupBarAppearanceDelegate>)delegate; 25 | 26 | @end 27 | 28 | 29 | NS_ASSUME_NONNULL_END 30 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNPopupCloseButton+Private.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupCloseButton+Private.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2016-12-02. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <LNPopupController/LNPopupCloseButton.h> 10 | #import <LNPopupController/LNPopupContentView.h> 11 | 12 | @interface LNPopupCloseButton () 13 | 14 | - (instancetype)initWithContainingContentView:(LNPopupContentView*)contentView; 15 | 16 | @property (nonatomic, weak) LNPopupContentView* popupContentView; 17 | 18 | - (void)_setStyle:(LNPopupCloseButtonStyle)style; 19 | - (void)_setButtonContainerStationary; 20 | - (void)_setButtonContainerTransitioning; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNPopupContentView+Private.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupContentView+Private.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2020-08-04. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <LNPopupController/LNPopupContentView.h> 10 | 11 | @interface LNPopupContentView () 12 | 13 | - (instancetype)initWithFrame:(CGRect)frame; 14 | 15 | @property (nonatomic, strong, readwrite) UIPanGestureRecognizer* popupInteractionGestureRecognizer; 16 | @property (nonatomic, strong, readwrite) LNPopupCloseButton* popupCloseButton; 17 | @property (nonatomic, strong) UIVisualEffectView* effectView; 18 | @property (nonatomic, strong, readonly) UIView* contentView; 19 | 20 | @property (nonatomic, weak) UIViewController* currentPopupContentViewController; 21 | 22 | - (void)setControllerOverrideUserInterfaceStyle:(UIUserInterfaceStyle)overrideUserInterfaceStyle; 23 | 24 | - (void)_applyBackgroundEffectWithContentViewController:(UIViewController*)vc barEffect:(UIBlurEffect*)barEffect; 25 | 26 | - (void)_repositionPopupCloseButton; 27 | - (void)_repositionPopupCloseButtonAnimated:(BOOL)animated; 28 | 29 | @end 30 | 31 | @interface _LNPopupTransitionCoordinator : NSObject <UIViewControllerTransitionCoordinator> @end 32 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNPopupController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupController.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2015-08-23. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | #import "LNPopupBar+Private.h" 11 | #import "UIViewController+LNPopupSupportPrivate.h" 12 | #import <LNPopupController/LNPopupCloseButton.h> 13 | #import "LNPopupContentView+Private.h" 14 | #import "LNPopupBar+Private.h" 15 | 16 | CF_EXTERN_C_BEGIN 17 | 18 | #define _LNPopupPresentationStateTransitioning ((LNPopupPresentationState)2) 19 | 20 | @interface LNPopupController : NSObject <_LNPopupBarDelegate> 21 | 22 | - (instancetype)initWithContainerViewController:(__kindof UIViewController*)containerController; 23 | 24 | @property (nonatomic, weak) UIView* bottomBar; 25 | 26 | @property (nonatomic, strong) LNPopupBar* popupBar; 27 | @property (nonatomic, strong, readonly) LNPopupBar* popupBarStorage; 28 | @property (nonatomic, strong, readonly) LNPopupBar* popupBarNoCreate; 29 | @property (nonatomic, strong) LNPopupContentView* popupContentView; 30 | @property (nonatomic, strong) UIScrollView* popupContentContainerView; 31 | 32 | @property (nonatomic) LNPopupPresentationState popupControllerPublicState; 33 | @property (nonatomic) LNPopupPresentationState popupControllerInternalState; 34 | @property (nonatomic) LNPopupPresentationState popupControllerTargetState; 35 | 36 | @property (nonatomic, weak) id<LNPopupPresentationDelegate> userPopupPresentationDelegate; 37 | 38 | @property (nonatomic, strong) __kindof UIViewController* currentContentController; 39 | @property (nonatomic, weak, readonly) __kindof UIViewController* containerController; 40 | 41 | @property (nonatomic) CGPoint lastPopupBarLocation; 42 | @property (nonatomic) CFTimeInterval lastSeenMovement; 43 | 44 | @property (nonatomic, weak) UIViewController* effectiveStatusBarUpdateController; 45 | 46 | @property (assign) BOOL wantsFeedbackGeneration; 47 | 48 | - (CGFloat)_percentFromPopupBar; 49 | 50 | - (void)_setContentToState:(LNPopupPresentationState)state; 51 | - (void)_setContentToState:(LNPopupPresentationState)state animated:(BOOL)animated; 52 | 53 | - (void)_movePopupBarAndContentToBottomBarSuperview; 54 | 55 | - (void)presentPopupBarWithContentViewController:(UIViewController*)contentViewController openPopup:(BOOL)open animated:(BOOL)animated completion:(void(^)(void))completionBlock; 56 | - (void)openPopupAnimated:(BOOL)animated completion:(void(^)(void))completionBlock; 57 | - (void)closePopupAnimated:(BOOL)animated completion:(void(^)(void))completionBlock; 58 | - (void)dismissPopupBarAnimated:(BOOL)animated completion:(void(^)(void))completionBlock; 59 | 60 | - (void)_configurePopupBarFromBottomBar; 61 | - (void)_configurePopupBarFromBottomBarModifyingGroupingIdentifier:(BOOL)modifyingGroupingIdentifier; 62 | - (void)_updateBarExtensionStyleFromPopupBar; 63 | 64 | + (CGFloat)_statusBarHeightForView:(UIView*)view; 65 | 66 | - (void)_fixupGestureRecognizer:(UIGestureRecognizer*)obj; 67 | 68 | @end 69 | 70 | CF_EXTERN_C_END 71 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNPopupCustomBarViewController+Private.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupItem+Private.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2016-12-30. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <LNPopupController/LNPopupItem.h> 10 | #import <LNPopupController/LNPopupCustomBarViewController.h> 11 | #import "LNPopupController.h" 12 | 13 | @interface LNPopupCustomBarViewController () 14 | 15 | @property (nonatomic, weak, readwrite) LNPopupBar* containingPopupBar; 16 | @property (nonatomic, weak) LNPopupController* popupController; 17 | 18 | - (void)_activeAppearanceDidChange:(LNPopupBarAppearance*)activeAppearance; 19 | 20 | - (void)_userFacing_viewWillAppear:(BOOL)animated; 21 | - (void)_userFacing_viewIsAppearing:(BOOL)animated; 22 | - (void)_userFacing_viewDidAppear:(BOOL)animated; 23 | - (void)_userFacing_viewWillDisappear:(BOOL)animated; 24 | - (void)_userFacing_viewDidDisappear:(BOOL)animated; 25 | 26 | @end 27 | 28 | @interface _LNPopupCustomBarViewController_AppearanceControl : LNPopupCustomBarViewController @end 29 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNPopupDebug.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupDebug.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2025-04-04. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <Foundation/Foundation.h> 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | #ifdef DEBUG 14 | CF_EXTERN_C_BEGIN 15 | extern NSUserDefaults* __LNDebugUserDefaults(void); 16 | CF_EXTERN_C_END 17 | #endif 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNPopupDebug.m: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupDebug.m 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2025-04-04. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "LNPopupDebug.h" 10 | 11 | #ifdef DEBUG 12 | NSUserDefaults* __LNDebugUserDefaults(void) 13 | { 14 | static NSUserDefaults* rv = nil; 15 | 16 | static dispatch_once_t onceToken; 17 | dispatch_once(&onceToken, ^{ 18 | SEL sel = NSSelectorFromString(@"settingDefaults"); 19 | if([NSUserDefaults respondsToSelector:sel]) 20 | { 21 | rv = [NSUserDefaults valueForKey:@"settingDefaults"]; 22 | } 23 | else 24 | { 25 | rv = NSUserDefaults.standardUserDefaults; 26 | } 27 | }); 28 | 29 | return rv; 30 | } 31 | #endif 32 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNPopupImageView+Private.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupImageView+Private.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2025-03-24. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <LNPopupController/LNPopupImageView.h> 10 | #import "LNPopupBar+Private.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface LNPopupImageView () 15 | 16 | - (instancetype)initWithContainingPopupBar:(LNPopupBar*)popupBar; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNPopupInteractionPanGestureRecognizer.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupInteractionPanGestureRecognizer.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2017-07-15. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | 11 | @class LNPopupController; 12 | 13 | @interface LNPopupInteractionPanGestureRecognizer : UIPanGestureRecognizer 14 | 15 | - (instancetype)initWithTarget:(id)target action:(SEL)action popupController:(LNPopupController*)popupController; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNPopupItem+Private.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupItem+Private.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2015-08-23. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <LNPopupController/LNPopupItem.h> 10 | #import "LNPopupController.h" 11 | 12 | extern NSArray* __LNPopupItemObservedKeys; 13 | 14 | @class LNPopupItem; 15 | 16 | @protocol _LNPopupItemDelegate <NSObject> 17 | 18 | - (void)_popupItem:(LNPopupItem*)popupItem didChangeToValue:(id)value forKey:(NSString*)key; 19 | 20 | @end 21 | 22 | @interface LNPopupItem () 23 | 24 | @property (nonatomic, strong) UIViewController* swiftuiImageController; 25 | 26 | @property (nonatomic, strong) UIView* swiftuiTitleContentView; 27 | 28 | @property (nonatomic, strong) UIViewController* swiftuiHiddenLeadingController; 29 | @property (nonatomic, strong) UIViewController* swiftuiHiddenTrailingController; 30 | 31 | @property (nonatomic, copy) NSString* accessibilityImageLabel; 32 | @property (nonatomic, copy) NSString* accessibilityProgressLabel; 33 | @property (nonatomic, copy) NSString* accessibilityProgressValue; 34 | 35 | @property (nonatomic, weak, setter=_setItemDelegate:, getter=_itemDelegate) id<_LNPopupItemDelegate> itemDelegate; 36 | @property (nonatomic, weak, setter=_setContainerController:, getter=_containerController) __kindof UIViewController* containerController; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNPopupLongPressGestureRecognizer.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupLongPressGestureRecognizer.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2017-07-15. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | 11 | @interface LNPopupLongPressGestureRecognizer : UILongPressGestureRecognizer 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNPopupLongPressGestureRecognizer.m: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupLongPressGestureRecognizer.m 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2017-07-15. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "LNPopupLongPressGestureRecognizer.h" 10 | #import "LNForwardingDelegate.h" 11 | 12 | @interface LNPopupControllerLongPressGestureDelegate : LNForwardingDelegate <UIGestureRecognizerDelegate> 13 | @end 14 | 15 | @implementation LNPopupControllerLongPressGestureDelegate 16 | 17 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch 18 | { 19 | #if ! TARGET_OS_MACCATALYST 20 | if(@available(iOS 13.4, *)) 21 | { 22 | if(touch.type == UITouchTypeIndirectPointer) 23 | { 24 | return NO; 25 | } 26 | } 27 | #endif 28 | 29 | if([touch.view isKindOfClass:[UIControl class]]) 30 | { 31 | return NO; 32 | } 33 | 34 | if([self.forwardedDelegate respondsToSelector:_cmd]) 35 | { 36 | return [self.forwardedDelegate gestureRecognizer:gestureRecognizer shouldReceiveTouch:touch]; 37 | } 38 | 39 | return YES; 40 | } 41 | 42 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 43 | { 44 | if([NSStringFromClass(otherGestureRecognizer.class) containsString:@"SwiftUI"]) 45 | { 46 | return YES; 47 | } 48 | 49 | if([self.forwardedDelegate respondsToSelector:_cmd]) 50 | { 51 | return [self.forwardedDelegate gestureRecognizer:gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer]; 52 | } 53 | 54 | return NO; 55 | } 56 | 57 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 58 | { 59 | if([self.forwardedDelegate respondsToSelector:_cmd]) 60 | { 61 | return [self.forwardedDelegate gestureRecognizer:gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer]; 62 | } 63 | 64 | return YES; 65 | } 66 | 67 | @end 68 | 69 | 70 | @implementation LNPopupLongPressGestureRecognizer 71 | { 72 | LNPopupControllerLongPressGestureDelegate* _actualDelegate; 73 | } 74 | 75 | - (instancetype)initWithTarget:(id)target action:(SEL)action 76 | { 77 | self = [super initWithTarget:target action:action]; 78 | 79 | if(self) 80 | { 81 | _actualDelegate = [LNPopupControllerLongPressGestureDelegate new]; 82 | [super setDelegate:_actualDelegate]; 83 | } 84 | 85 | return self; 86 | } 87 | 88 | - (id<UIGestureRecognizerDelegate>)delegate 89 | { 90 | return _actualDelegate.forwardedDelegate; 91 | } 92 | 93 | - (void)setDelegate:(id<UIGestureRecognizerDelegate>)delegate 94 | { 95 | _actualDelegate = [LNPopupControllerLongPressGestureDelegate new]; 96 | _actualDelegate.forwardedDelegate = delegate; 97 | [super setDelegate:_actualDelegate]; 98 | } 99 | 100 | @end 101 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNPopupOpenTapGestureRecognizer.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupOpenTapGestureRecognizer.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2017-07-15. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | 11 | @interface LNPopupOpenTapGestureRecognizer : UITapGestureRecognizer 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNPopupOpenTapGestureRecognizer.m: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupOpenTapGestureRecognizer.m 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2017-07-15. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "LNPopupOpenTapGestureRecognizer.h" 10 | #import "LNForwardingDelegate.h" 11 | 12 | @interface LNPopupOpenTapGestureRecognizerForwardingDelegate : LNForwardingDelegate <UIGestureRecognizerDelegate> 13 | 14 | @end 15 | 16 | @implementation LNPopupOpenTapGestureRecognizerForwardingDelegate 17 | 18 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch 19 | { 20 | if([touch.view isKindOfClass:[UIControl class]]) 21 | { 22 | return NO; 23 | } 24 | 25 | if([self.forwardedDelegate respondsToSelector:_cmd]) 26 | { 27 | return [self.forwardedDelegate gestureRecognizer:gestureRecognizer shouldReceiveTouch:touch]; 28 | } 29 | 30 | return YES; 31 | } 32 | 33 | @end 34 | 35 | @implementation LNPopupOpenTapGestureRecognizer 36 | { 37 | LNPopupOpenTapGestureRecognizerForwardingDelegate* _actualDelegate; 38 | } 39 | 40 | - (instancetype)initWithTarget:(id)target action:(SEL)action 41 | { 42 | self = [super initWithTarget:target action:action]; 43 | 44 | if(self) 45 | { 46 | _actualDelegate = [LNPopupOpenTapGestureRecognizerForwardingDelegate new]; 47 | [super setDelegate:_actualDelegate]; 48 | } 49 | 50 | return self; 51 | } 52 | 53 | - (id<UIGestureRecognizerDelegate>)delegate 54 | { 55 | return _actualDelegate.forwardedDelegate; 56 | } 57 | 58 | - (void)setDelegate:(id<UIGestureRecognizerDelegate>)delegate 59 | { 60 | _actualDelegate = [LNPopupOpenTapGestureRecognizerForwardingDelegate new]; 61 | _actualDelegate.forwardedDelegate = delegate; 62 | [super setDelegate:_actualDelegate]; 63 | } 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNPopupPresentationContainerSupport.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupPresentationContainerSupport.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2025-04-13. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface LNPopupPresentationContainerSupport : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/LNPopupPresentationContainerSupport.m: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupPresentationContainerSupport.m 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2025-04-13. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "LNPopupPresentationContainerSupport.h" 10 | #import "UIViewController+LNPopupSupportPrivate.h" 11 | #import "_LNPopupSwizzlingUtils.h" 12 | 13 | #define LN_POPUP_SMART_CHILD_OVERRIDE(name, availability) \ 14 | - (UIViewController*)name API_AVAILABLE(availability) \ 15 | { \ 16 | UIViewController* rv = [self _ln_childViewControllerForStatusBarLogic]; \ 17 | if(rv != nil) \ 18 | { \ 19 | return rv;\ 20 | }\ 21 | \ 22 | Class superclass = LNDynamicSubclassSuper(self, LNPopupPresentationContainerSupport.class);\ 23 | struct objc_super super = {.receiver = self, .super_class = superclass};\ 24 | UIViewController* (*super_class)(struct objc_super*, SEL) = (void*)objc_msgSendSuper;\ 25 | return super_class(&super, _cmd);\ 26 | } 27 | 28 | @implementation LNPopupPresentationContainerSupport 29 | 30 | LN_POPUP_SMART_CHILD_OVERRIDE(childViewControllerForPointerLock, ios(14)) 31 | LN_POPUP_SMART_CHILD_OVERRIDE(childViewControllerForStatusBarStyle, ios(7)) 32 | LN_POPUP_SMART_CHILD_OVERRIDE(childViewControllerForStatusBarHidden, ios(7)) 33 | LN_POPUP_SMART_CHILD_OVERRIDE(childViewControllerForHomeIndicatorAutoHidden, ios(11)) 34 | LN_POPUP_SMART_CHILD_OVERRIDE(childViewControllerForScreenEdgesDeferringSystemGestures, ios(11)) 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/NSAttributedString+LNPopupSupport.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSAttributedString+LNPopupSupport.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2021-09-19. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <Foundation/Foundation.h> 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface NSAttributedString (LNPopupSupport) 14 | 15 | + (instancetype)ln_attributedStringWithAttributedString:(NSAttributedString*)orig defaultAttributes:(nullable NSDictionary<NSAttributedStringKey, id>*)attribs; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/NSAttributedString+LNPopupSupport.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSAttributedString+LNPopupSupport.m 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2021-09-19. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "NSAttributedString+LNPopupSupport.h" 10 | 11 | @implementation NSAttributedString (LNPopupSupport) 12 | 13 | + (instancetype)ln_attributedStringWithAttributedString:(NSAttributedString*)orig defaultAttributes:(nullable NSDictionary<NSAttributedStringKey, id>*)attribs 14 | { 15 | NSMutableAttributedString* rv = [[NSMutableAttributedString alloc] initWithString:orig.string attributes:attribs]; 16 | 17 | [orig enumerateAttributesInRange:NSMakeRange(0, orig.length) options:0 usingBlock:^(NSDictionary<NSAttributedStringKey,id> * _Nonnull attrs, NSRange range, BOOL * _Nonnull stop) { 18 | [rv addAttributes:attrs range:range]; 19 | }]; 20 | 21 | return rv; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/UIContextMenuInteraction+LNPopupSupportPrivate.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIContextMenuInteraction+LNPopupSupportPrivate.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2021-03-28. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | 11 | #ifndef LNPopupControllerEnforceStrictClean 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface UIContextMenuInteraction (LNPopupSupportPrivate) 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/UIView+LNPopupSupportPrivate.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+LNPopupSupportPrivate.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2020-08-01. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | 11 | @class LNPopupBar; 12 | @class LNPopupController; 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | typedef void (^LNInWindowBlock)(dispatch_block_t); 17 | 18 | @interface NSObject (LNPopupSupportPrivate) 19 | 20 | @property (nonatomic, weak, nullable, getter=_ln_attachedPopupController, setter=_ln_setAttachedPopupController:) LNPopupController* attachedPopupController; 21 | 22 | @end 23 | 24 | UIEdgeInsets _LNEdgeInsetsFromDirectionalEdgeInsets(UIView* forView, NSDirectionalEdgeInsets edgeInsets); 25 | 26 | @interface UIView (LNPopupSupportPrivate) 27 | 28 | - (void)_ln_triggerBarAppearanceRefreshIfNeededTriggeringLayout:(BOOL)layout; 29 | - (BOOL)_ln_scrollEdgeAppearanceRequiresFadeForPopupBar:(LNPopupBar*)popupBar; 30 | 31 | - (void)_ln_letMeKnowWhenViewInWindowHierarchy:(LNInWindowBlock)block; 32 | - (void)_ln_forgetAboutIt; 33 | - (nullable NSString*)_ln_effectGroupingIdentifierIfAvailable; 34 | 35 | - (void)_ln_freezeInsets; 36 | 37 | @end 38 | 39 | @interface UIView () 40 | 41 | - (id)_lnpopup_scrollEdgeAppearance; 42 | 43 | @end 44 | 45 | @interface UITabBar () 46 | 47 | @property (nonatomic, getter=_ignoringLayoutDuringTransition, setter=_setIgnoringLayoutDuringTransition:) BOOL ignoringLayoutDuringTransition; 48 | 49 | @end 50 | 51 | @interface UIWindow (LNPopupSupport) 52 | 53 | @property (nonatomic, strong, readonly) UIEvent* _ln_currentEvent; 54 | 55 | @property (nonatomic, assign, nullable, getter=_ln_popupInteractionOnly, setter=_ln_setPopupInteractionOnly:) NSArray* popupInteractionOnly; 56 | 57 | @end 58 | 59 | NS_ASSUME_NONNULL_END 60 | 61 | @interface UIScrollView (LNPopupSupportPrivate) 62 | 63 | - (BOOL)_ln_hasHorizontalContent; 64 | - (BOOL)_ln_hasVerticalContent; 65 | - (BOOL)_ln_scrollingOnlyVertically; 66 | - (BOOL)_ln_isAtTop; 67 | 68 | @end 69 | 70 | @interface _LNPopupBarBackgroundGroupNameOverride: NSObject <UIObjectTraitDefinition> @end 71 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupAddressInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupAddressInfo.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2024-08-09. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <Foundation/Foundation.h> 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface _LNPopupAddressInfo : NSObject 14 | 15 | - (instancetype)initWithAddress:(NSUInteger)address; 16 | 17 | @property (nonatomic, readonly) NSUInteger address; 18 | @property (nonatomic, copy, readonly) NSString* image; 19 | @property (nonatomic, copy, readonly) NSString* symbol; 20 | @property (nonatomic, readonly) NSUInteger offset; 21 | 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupAddressInfo.mm: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupAddressInfo.mm 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2024-08-09. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "_LNPopupAddressInfo.h" 10 | #include <dlfcn.h> 11 | #include <cxxabi.h> 12 | 13 | @implementation _LNPopupAddressInfo 14 | { 15 | Dl_info _info; 16 | } 17 | 18 | @synthesize image, symbol, offset, address; 19 | 20 | - (instancetype)initWithAddress:(NSUInteger)_address 21 | { 22 | self = [super init]; 23 | 24 | if(self) 25 | { 26 | address = _address; 27 | if(dladdr((void*)address, &_info) <= 0) 28 | { 29 | return nil; 30 | } 31 | } 32 | 33 | return self; 34 | } 35 | 36 | - (NSString *)image 37 | { 38 | if(_info.dli_fname != NULL) 39 | { 40 | NSString* potentialImage = [NSString stringWithUTF8String:_info.dli_fname]; 41 | 42 | if([potentialImage containsString:@"/"]) 43 | { 44 | return potentialImage.lastPathComponent; 45 | } 46 | } 47 | 48 | return @"???"; 49 | } 50 | 51 | - (NSString *)symbol 52 | { 53 | if(_info.dli_sname != NULL) 54 | { 55 | return [NSString stringWithUTF8String:_info.dli_sname]; 56 | } 57 | else if(_info.dli_fname != NULL) 58 | { 59 | return self.image; 60 | } 61 | 62 | return [NSString stringWithFormat:@"0x%1lx", (unsigned long)_info.dli_saddr]; 63 | } 64 | 65 | - (NSUInteger)offset 66 | { 67 | NSString* str = nil; 68 | if(_info.dli_sname != NULL && (str = [NSString stringWithUTF8String:_info.dli_sname]) != nil) 69 | { 70 | return address - (NSUInteger)_info.dli_saddr; 71 | } 72 | else if(_info.dli_fname != NULL && (str = [NSString stringWithUTF8String:_info.dli_fname]) != nil) 73 | { 74 | return address - (NSUInteger)_info.dli_fbase; 75 | } 76 | 77 | return address - (NSUInteger)_info.dli_saddr; 78 | } 79 | 80 | - (NSString*)description 81 | { 82 | #if __LP64__ 83 | return [NSString stringWithFormat:@"%-35s 0x%016llx %@ + %ld", self.image.UTF8String, (uint64_t)address, self.symbol, self.offset]; 84 | #else 85 | return [NSString stringWithFormat:@"%-35s 0x%08lx %@ + %d", self.image.UTF8String, (unsigned long)address, self.symbol, self.offset]; 86 | #endif 87 | } 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupBackgroundShadowView.h: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupBackgroundShadowView.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2023-09-25. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface _LNPopupBackgroundShadowView : UIView 14 | 15 | @property (nonatomic, strong) NSShadow* shadow; 16 | @property (nonatomic, assign) CGFloat cornerRadius; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupBackgroundShadowView.m: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupBackgroundShadowView.m 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2023-09-25. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "_LNPopupBackgroundShadowView.h" 10 | 11 | @implementation _LNPopupBackgroundShadowView 12 | { 13 | CAShapeLayer* _maskLayer; 14 | } 15 | 16 | - (instancetype)initWithFrame:(CGRect)frame 17 | { 18 | self = [super initWithFrame:frame]; 19 | 20 | if(self) 21 | { 22 | _maskLayer = [CAShapeLayer layer]; 23 | _maskLayer.fillRule = kCAFillRuleEvenOdd; 24 | self.layer.mask = _maskLayer; 25 | self.layer.shouldRasterize = YES; 26 | } 27 | 28 | return self; 29 | } 30 | 31 | - (void)setShadow:(NSShadow *)shadow 32 | { 33 | _shadow = shadow; 34 | 35 | self.layer.shadowOffset = _shadow.shadowOffset; 36 | self.layer.shadowRadius = _shadow.shadowBlurRadius; 37 | 38 | [self _updateShadowColor]; 39 | [self setNeedsLayout]; 40 | } 41 | 42 | - (void)_updateShadowColor 43 | { 44 | self.layer.shadowColor = [(UIColor*)_shadow.shadowColor colorWithAlphaComponent:1.0].CGColor; 45 | self.layer.shadowOpacity = CGColorGetAlpha([_shadow.shadowColor CGColor]); 46 | } 47 | 48 | - (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection 49 | { 50 | [super traitCollectionDidChange:previousTraitCollection]; 51 | 52 | self.layer.rasterizationScale = self.traitCollection.displayScale; 53 | [self _updateShadowColor]; 54 | } 55 | 56 | - (void)layoutSubviews 57 | { 58 | [super layoutSubviews]; 59 | 60 | CGFloat dx = 2 * _shadow.shadowBlurRadius + fabs(_shadow.shadowOffset.width); 61 | CGFloat dy = 2 * _shadow.shadowBlurRadius + fabs(_shadow.shadowOffset.height); 62 | 63 | self.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:_cornerRadius].CGPath; 64 | _maskLayer.frame = CGRectInset(self.bounds, -dx, -dy); 65 | 66 | UIBezierPath* maskPath = [UIBezierPath bezierPathWithRect:_maskLayer.bounds]; 67 | [maskPath appendPath:[UIBezierPath bezierPathWithRoundedRect:CGRectInset(_maskLayer.bounds, dx, dy) cornerRadius:_cornerRadius]]; 68 | maskPath.usesEvenOddFillRule = YES; 69 | 70 | _maskLayer.path = maskPath.CGPath; 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupBarBackgroundMaskView.h: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupBarBackgroundMaskView.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2023-09-27. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface _LNPopupBarBackgroundMaskView: UIView 14 | 15 | @property (nonatomic, readonly) BOOL wantsCutout; 16 | - (void)setWantsCutout:(BOOL)wantsCutout animated:(BOOL)animated; 17 | 18 | @property (nonatomic) CGRect floatingFrame; 19 | @property (nonatomic) CGFloat floatingCornerRadius; 20 | 21 | @end 22 | 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupBarBackgroundView.h: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupBarBackgroundView.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2021-06-20. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface _LNPopupBarBackgroundView : UIView 14 | 15 | - (instancetype)initWithEffect:(nullable UIVisualEffect *)effect; 16 | 17 | @property (nonatomic, strong, readonly) UIVisualEffectView* effectView; 18 | @property (nonatomic, copy, nullable) UIVisualEffect* effect; 19 | @property (nonatomic, strong, readonly) UIView* contentView; 20 | 21 | @property(nonatomic, copy, nullable) UIColor* foregroundColor; 22 | @property(nonatomic, strong, nullable) UIImage* foregroundImage; 23 | @property(nonatomic) UIViewContentMode foregroundImageContentMode; 24 | - (void)hideOrShowImageViewIfNecessary; 25 | 26 | @property (nonatomic, assign) CGFloat cornerRadius; 27 | 28 | @property (nonatomic, strong, readonly) UIView* transitionShadingView; 29 | 30 | @end 31 | 32 | NS_ASSUME_NONNULL_END 33 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupBase64Utils.hh: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupBase64Utils.hh 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2024-09-01. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <Foundation/Foundation.h> 10 | #include <cstdlib> 11 | #include <array> 12 | 13 | namespace lnpopup { 14 | 15 | template <size_t N> 16 | struct base64_string : std::array<char, N> { 17 | consteval base64_string(const char (&input)[N]) : base64_string(input, std::make_index_sequence<N>{}) {} 18 | template <size_t... Is> 19 | consteval base64_string(const char (&input)[N], std::index_sequence<Is...>) : std::array<char, N>{ input[Is]... } {} 20 | }; 21 | 22 | template <size_t N> 23 | consteval const auto base64_encode(const char(&input)[N]) { 24 | constexpr char encoding_table[] = 25 | { 26 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 27 | 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 28 | 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 29 | 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 30 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' 31 | }; 32 | 33 | constexpr size_t out_len = 4 * (((N - 1) + 2) / 3) + 1; 34 | 35 | size_t in_len = N - 1; 36 | char output[out_len] {0}; 37 | size_t i = 0; 38 | char *p = const_cast<char *>(output); 39 | 40 | for(i = 0; in_len > 2 && i < in_len - 2; i += 3) 41 | { 42 | *p++ = encoding_table[(input[i] >> 2) & 0x3F]; 43 | *p++ = encoding_table[((input[i] & 0x3) << 4) | ((int)(input[i + 1] & 0xF0) >> 4)]; 44 | *p++ = encoding_table[((input[i + 1] & 0xF) << 2) | ((int)(input[i + 2] & 0xC0) >> 6)]; 45 | *p++ = encoding_table[input[i + 2] & 0x3F]; 46 | } 47 | 48 | if(i < in_len) 49 | { 50 | *p++ = encoding_table[(input[i] >> 2) & 0x3F]; 51 | if(i == (in_len - 1)) 52 | { 53 | *p++ = encoding_table[((input[i] & 0x3) << 4)]; 54 | *p++ = '='; 55 | } 56 | else 57 | { 58 | *p++ = encoding_table[((input[i] & 0x3) << 4) | ((int)(input[i + 1] & 0xF0) >> 4)]; 59 | *p++ = encoding_table[((input[i + 1] & 0xF) << 2)]; 60 | } 61 | *p++ = '='; 62 | } 63 | 64 | return base64_string<out_len>(output); 65 | } 66 | 67 | CF_INLINE 68 | auto decode_hidden_string(auto encoded) 69 | { 70 | return [[NSString alloc] initWithData:[[NSData alloc] initWithBase64EncodedString:@(encoded.data()) options:0] encoding:NSUTF8StringEncoding]; 71 | } 72 | 73 | } //namespace lnpopup 74 | 75 | #define LNPopupHiddenString(input) (lnpopup::decode_hidden_string(lnpopup::base64_encode("" input ""))) 76 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupSwizzlingUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupSwizzlingUtils.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2020-07-31. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <Foundation/Foundation.h> 10 | #import <objc/message.h> 11 | #import <objc/runtime.h> 12 | 13 | CF_EXTERN_C_BEGIN 14 | 15 | #define unavailable(...) @available(__VA_ARGS__)) { } else if(YES 16 | 17 | #define LNSwizzleComplain(FORMAT, ...) \ 18 | if(shouldTrapAndPrint) { \ 19 | NSString *errStr = [NSString stringWithFormat:@"%s: " FORMAT,__func__,##__VA_ARGS__]; \ 20 | NSLog(@"LNPopupController: %@", errStr); \ 21 | raise(SIGTRAP); \ 22 | } 23 | 24 | #ifndef LNAlwaysInline 25 | #define LNAlwaysInline CF_INLINE 26 | #endif /* LNAlwaysInline */ 27 | 28 | extern BOOL __LNSwizzleMethod(Class cls, SEL orig, SEL alt); 29 | 30 | #define LNSwizzleMethod __LNSwizzleMethod 31 | 32 | LNAlwaysInline 33 | BOOL __LNSwizzleClassMethod(Class cls, SEL orig, SEL alt) 34 | { 35 | return LNSwizzleMethod(object_getClass((id)cls), orig, alt); 36 | } 37 | 38 | extern BOOL __LNDynamicSubclass(id obj, Class target); 39 | #define LNDynamicSubclass __LNDynamicSubclass 40 | extern Class __LNDynamicSubclassSuper(id obj, Class dynamic); 41 | #define LNDynamicSubclassSuper __LNDynamicSubclassSuper 42 | 43 | NSArray<NSString*>* __LNPopupGetPropertyNames(Class cls, NSArray<NSString*>* excludedProperties); 44 | #define LNPopupGetPropertyNames __LNPopupGetPropertyNames 45 | 46 | CF_EXTERN_C_END 47 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupTransitionAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupTransitionAnimator.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2025-03-24. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | #import <LNPopupController/LNPopupBar.h> 11 | #import <LNPopupController/LNPopupContentView.h> 12 | #import <LNPopupController/UIViewController+LNPopupSupport.h> 13 | #import "_LNPopupTransitionView.h" 14 | 15 | NS_ASSUME_NONNULL_BEGIN 16 | 17 | @interface UIViewPropertyAnimator () 18 | 19 | - (void)addAnimations:(void (^)(void))animation delayFactor:(CGFloat)delayFactor durationFactor:(CGFloat)durationFactor; 20 | 21 | @end 22 | 23 | @interface _LNPopupTransitionAnimator : NSObject 24 | 25 | - (instancetype)initWithTransitionView:(nullable _LNPopupTransitionView*)transitionView userView:(UIView*)view popupBar:(LNPopupBar*)popupBar popupContentView:(LNPopupContentView*)popupContentView; 26 | 27 | @property (nonatomic, strong, readonly) UIView* view; 28 | @property (nonatomic, strong, readonly) LNPopupBar* popupBar; 29 | @property (nonatomic, strong, readonly) LNPopupContentView* popupContentView; 30 | 31 | @property (nonatomic, strong, readonly, nullable) _LNPopupTransitionView* transitionView; 32 | @property (nonatomic, strong, readonly, nullable) UIView<LNPopupTransitionView>* crossfadeView; 33 | @property (nonatomic, readonly) CGRect sourceFrame; 34 | @property (nonatomic, readonly) CGRect targetFrame; 35 | @property (nonatomic, readonly) CGAffineTransform transform; 36 | 37 | @property (nonatomic, readonly) CGFloat scaledBarImageViewCornerRadius; 38 | @property (nonatomic, strong, readonly) NSShadow* scaledBarImageViewShadow; 39 | 40 | - (void)animateWithAnimator:(UIViewPropertyAnimator*)animator otherAnimations:(void(^)(void))otherAnimations NS_REQUIRES_SUPER; 41 | - (void)beforeAnyAnimation NS_REQUIRES_SUPER; 42 | - (void)performBeforeAdditionalAnimations NS_REQUIRES_SUPER; 43 | - (void)performAdditionalAnimations NS_REQUIRES_SUPER; 44 | - (void)performAdditionalDelayed015Animations NS_REQUIRES_SUPER; 45 | - (void)performAdditionalDelayed05Animations NS_REQUIRES_SUPER; 46 | - (void)performAdditional01Animations NS_REQUIRES_SUPER; 47 | - (void)performAdditional075Animations NS_REQUIRES_SUPER; 48 | - (void)performAdditional04Delayed015Animations NS_REQUIRES_SUPER; 49 | - (void)performAdditional075Delayed015Animations NS_REQUIRES_SUPER; 50 | - (void)performAdditionalCompletion NS_REQUIRES_SUPER; 51 | 52 | @property (nonatomic, readonly) LNPopupPresentationState targetState; 53 | 54 | @end 55 | 56 | NS_ASSUME_NONNULL_END 57 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupTransitionCloseAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupTransitionCloseAnimator.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2025-03-24. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "_LNPopupTransitionAnimator.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface _LNPopupTransitionCloseAnimator : _LNPopupTransitionAnimator 14 | 15 | - (instancetype)initWithTransitionView:(nullable _LNPopupTransitionView*)transitionView userView:(UIView*)view popupBar:(LNPopupBar*)popupBar popupContentView:(LNPopupContentView*)popupContentView currentContentController:(UIViewController*)currentContentController containerController:(UIViewController*)containerController; 16 | 17 | @property (nonatomic, strong) UIViewController* currentContentController; 18 | @property (nonatomic, strong) UIViewController* containerController; 19 | 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupTransitionGenericCloseAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupTransitionGenericCloseAnimator.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2025-03-24. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "_LNPopupTransitionCloseAnimator.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface _LNPopupTransitionGenericCloseAnimator : _LNPopupTransitionCloseAnimator 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupTransitionGenericCloseAnimator.m: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupTransitionGenericCloseAnimator.m 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2025-03-24. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "_LNPopupTransitionGenericCloseAnimator.h" 10 | 11 | @implementation _LNPopupTransitionGenericCloseAnimator 12 | { 13 | NSShadow* _targetShadow; 14 | } 15 | 16 | - (void)animateWithAnimator:(UIViewPropertyAnimator *)animator otherAnimations:(void (^)(void))otherAnimations 17 | { 18 | [super animateWithAnimator:animator otherAnimations:otherAnimations]; 19 | 20 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((animator.duration * 0.38) * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 21 | [animator addAnimations:^{ 22 | self.transitionView.cornerRadius = self.popupBar.imageView.cornerRadius; 23 | }]; 24 | }); 25 | } 26 | 27 | - (void)beforeAnyAnimation 28 | { 29 | [super beforeAnyAnimation]; 30 | 31 | _targetShadow = self.popupBar.imageView.shadow.copy; 32 | 33 | NSShadow* hiddenShadow = [_targetShadow copy]; 34 | hiddenShadow.shadowColor = [_targetShadow.shadowColor colorWithAlphaComponent:0.0]; 35 | self.transitionView.shadow = hiddenShadow; 36 | } 37 | 38 | - (void)performAdditionalAnimations 39 | { 40 | [super performAdditionalAnimations]; 41 | 42 | self.transitionView.shadow = _targetShadow; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupTransitionGenericOpenAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupTransitionGenericOpenAnimator.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2025-03-24. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "_LNPopupTransitionOpenAnimator.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface _LNPopupTransitionGenericOpenAnimator : _LNPopupTransitionOpenAnimator 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupTransitionGenericOpenAnimator.m: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupTransitionGenericOpenAnimator.m 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2025-03-24. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "_LNPopupTransitionGenericOpenAnimator.h" 10 | 11 | @implementation _LNPopupTransitionGenericOpenAnimator 12 | { 13 | NSShadow* _targetShadow; 14 | } 15 | 16 | - (void)beforeAnyAnimation 17 | { 18 | [super beforeAnyAnimation]; 19 | 20 | self.transitionView.shadow = self.popupBar.imageView.shadow.copy; 21 | self.transitionView.cornerRadius = self.scaledBarImageViewCornerRadius; 22 | 23 | _targetShadow = [self.transitionView.shadow copy]; 24 | _targetShadow.shadowColor = [_targetShadow.shadowColor colorWithAlphaComponent:0.0]; 25 | } 26 | 27 | - (void)performAdditionalAnimations 28 | { 29 | [super performAdditionalAnimations]; 30 | 31 | self.transitionView.shadow = _targetShadow; 32 | self.transitionView.cornerRadius = 0.0; 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupTransitionOpenAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupTransitionOpenAnimator.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2025-03-24. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | #import "_LNPopupTransitionAnimator.h" 11 | #import <LNPopupController/LNPopupBar.h> 12 | #import <LNPopupController/LNPopupContentView.h> 13 | #import "_LNPopupTransitionView.h" 14 | 15 | NS_ASSUME_NONNULL_BEGIN 16 | 17 | @interface _LNPopupTransitionOpenAnimator : _LNPopupTransitionAnimator 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupTransitionOpenAnimator.m: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupTransitionOpenAnimator.m 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2025-03-24. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "_LNPopupTransitionOpenAnimator.h" 10 | #import <objc/runtime.h> 11 | 12 | @implementation _LNPopupTransitionOpenAnimator 13 | 14 | - (CGRect)sourceFrame 15 | { 16 | return [self.popupBar.imageView.window convertRect:self.popupBar.imageView.bounds fromView:self.popupBar.imageView]; 17 | } 18 | 19 | - (CGRect)targetFrame 20 | { 21 | return [self.popupContentView.window convertRect:self.transitionView.sourceView.bounds fromView:self.transitionView.sourceView];; 22 | } 23 | 24 | - (CGAffineTransform)transform 25 | { 26 | CGFloat ratioX = self.sourceFrame.size.width / self.targetFrame.size.width; 27 | CGFloat ratioY = self.sourceFrame.size.height / self.targetFrame.size.height; 28 | return CGAffineTransformMakeScale(ratioX, ratioY); 29 | } 30 | 31 | - (CGFloat)scaledBarImageViewCornerRadius 32 | { 33 | return self.popupBar.imageView.cornerRadius * self.targetFrame.size.width / self.popupBar.imageView.bounds.size.width; 34 | } 35 | 36 | - (NSShadow *)scaledBarImageViewShadow 37 | { 38 | NSShadow* scaled = self.popupBar.imageView.shadow.copy; 39 | scaled.shadowBlurRadius = scaled.shadowBlurRadius * self.targetFrame.size.width / self.popupBar.imageView.bounds.size.width; 40 | return scaled; 41 | } 42 | 43 | - (LNPopupPresentationState)targetState 44 | { 45 | return LNPopupPresentationStateOpen; 46 | } 47 | 48 | - (void)beforeAnyAnimation 49 | { 50 | [super beforeAnyAnimation]; 51 | 52 | self.crossfadeView.alpha = 1.0; 53 | self.crossfadeView.cornerRadius = self.popupBar.imageView.cornerRadius; 54 | } 55 | 56 | - (void)performBeforeAdditionalAnimations 57 | { 58 | [super performBeforeAdditionalAnimations]; 59 | 60 | self.transitionView.sourceViewTransform = self.transform; 61 | } 62 | 63 | - (void)performAdditionalAnimations 64 | { 65 | [super performAdditionalAnimations]; 66 | 67 | self.transitionView.frame = self.targetFrame; 68 | self.transitionView.sourceViewTransform = CGAffineTransformIdentity; 69 | self.crossfadeView.cornerRadius = self.transitionView.cornerRadius; 70 | } 71 | 72 | - (void)performAdditional01Animations 73 | { 74 | [super performAdditional01Animations]; 75 | 76 | self.crossfadeView.alpha = 0.0; 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupTransitionPreferredCloseAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupTransitionPreferredCloseAnimator.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2025-03-24. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "_LNPopupTransitionCloseAnimator.h" 10 | #import <LNPopupController/UIViewController+LNPopupSupport.h> 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface _LNPopupTransitionPreferredCloseAnimator : _LNPopupTransitionCloseAnimator 15 | 16 | @property (nonatomic, strong, readonly) UIView<LNPopupTransitionView>* view; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupTransitionPreferredCloseAnimator.mm: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupTransitionPreferredCloseAnimator.m 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2025-03-24. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "_LNPopupTransitionPreferredCloseAnimator.h" 10 | 11 | @implementation _LNPopupTransitionPreferredCloseAnimator 12 | { 13 | CGFloat _originalCornerRadius; 14 | NSShadow* _originalShadow; 15 | BOOL _supportsShadow; 16 | } 17 | 18 | @dynamic view; 19 | 20 | - (void)beforeAnyAnimation 21 | { 22 | [super beforeAnyAnimation]; 23 | 24 | if([self.view respondsToSelector:@selector(supportsShadow)]) 25 | { 26 | _supportsShadow = self.view.supportsShadow; 27 | } 28 | else 29 | { 30 | _supportsShadow = YES; 31 | } 32 | 33 | _originalCornerRadius = self.view.cornerRadius; 34 | if(_supportsShadow) 35 | { 36 | _originalShadow = self.view.shadow.copy; 37 | } 38 | else 39 | { 40 | _originalShadow = nil; 41 | } 42 | 43 | self.crossfadeView.cornerRadius = self.view.cornerRadius; 44 | } 45 | 46 | - (void)performAdditionalAnimations 47 | { 48 | [super performAdditionalAnimations]; 49 | 50 | self.view.cornerRadius = self.scaledBarImageViewCornerRadius; 51 | self.crossfadeView.cornerRadius = self.popupBar.imageView.cornerRadius; 52 | if(_supportsShadow) 53 | { 54 | self.view.shadow = self.scaledBarImageViewShadow; 55 | } 56 | else 57 | { 58 | self.transitionView.shadow = self.popupBar.imageView.shadow.copy; 59 | } 60 | } 61 | 62 | - (void)performAdditionalCompletion 63 | { 64 | self.view.cornerRadius = _originalCornerRadius; 65 | if(_supportsShadow) 66 | { 67 | self.view.shadow = _originalShadow; 68 | } 69 | else 70 | { 71 | self.transitionView.shadow = _originalShadow; 72 | } 73 | 74 | [super performAdditionalCompletion]; 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupTransitionPreferredOpenAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupTransitionPreferredOpenAnimator.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2025-03-24. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "_LNPopupTransitionOpenAnimator.h" 10 | #import <LNPopupController/UIViewController+LNPopupSupport.h> 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface _LNPopupTransitionPreferredOpenAnimator : _LNPopupTransitionOpenAnimator 15 | 16 | @property (nonatomic, strong, readonly) UIView<LNPopupTransitionView>* view; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupTransitionPreferredOpenAnimator.mm: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupTransitionPreferredOpenAnimator.m 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2025-03-24. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "_LNPopupTransitionPreferredOpenAnimator.h" 10 | 11 | @implementation _LNPopupTransitionPreferredOpenAnimator 12 | { 13 | CGFloat _originalCornerRadius; 14 | NSShadow* _originalShadow; 15 | BOOL _supportsShadow; 16 | } 17 | 18 | @dynamic view; 19 | 20 | - (void)beforeAnyAnimation 21 | { 22 | [super beforeAnyAnimation]; 23 | 24 | if([self.view respondsToSelector:@selector(supportsShadow)]) 25 | { 26 | _supportsShadow = self.view.supportsShadow; 27 | } 28 | else 29 | { 30 | _supportsShadow = YES; 31 | } 32 | 33 | _originalCornerRadius = self.view.cornerRadius; 34 | if(_supportsShadow) 35 | { 36 | _originalShadow = self.view.shadow.copy; 37 | } 38 | else 39 | { 40 | _originalShadow = nil; 41 | } 42 | 43 | self.view.cornerRadius = self.scaledBarImageViewCornerRadius; 44 | if(_supportsShadow) 45 | { 46 | self.view.shadow = self.scaledBarImageViewShadow; 47 | } 48 | else 49 | { 50 | self.transitionView.shadow = self.popupBar.imageView.shadow.copy; 51 | } 52 | } 53 | 54 | - (void)performAdditionalAnimations 55 | { 56 | [super performAdditionalAnimations]; 57 | 58 | self.view.cornerRadius = _originalCornerRadius; 59 | self.view.shadow = _originalShadow; 60 | 61 | if(_supportsShadow) 62 | { 63 | self.view.shadow = _originalShadow; 64 | } 65 | else 66 | { 67 | self.transitionView.shadow = _originalShadow; 68 | } 69 | 70 | self.crossfadeView.cornerRadius = self.view.cornerRadius; 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupTransitionView.h: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupTransitionView.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2025-03-23. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | #import <LNPopupController/UIViewController+LNPopupSupport.h> 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface _LNPopupTransitionView : UIView <LNPopupTransitionView> 15 | 16 | + (instancetype)transitionViewWithSourceView:(UIView*)sourceView; 17 | 18 | - (instancetype)initWithSourceView:(UIView*)sourceView; 19 | 20 | - (void)setTargetFrameUpdatingTransform:(CGRect)targetFrame; 21 | 22 | @property (nonatomic, strong, readonly) UIView* sourceView; 23 | 24 | @property (nonatomic, copy) NSShadow* shadow; 25 | @property (nonatomic, assign) CGFloat cornerRadius; 26 | @property (nonatomic, assign) BOOL layerAlwaysMasksToBounds; 27 | 28 | @property (nonatomic, assign) CGAffineTransform sourceViewTransform; 29 | 30 | @end 31 | 32 | NS_ASSUME_NONNULL_END 33 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNPopupUIBarAppearanceProxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPopupUIBarAppearanceProxy.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2023-08-30. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <Foundation/Foundation.h> 10 | 11 | #if ! LNPopupControllerEnforceStrictClean 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface _LNPopupUIBarAppearanceProxy : NSObject 16 | 17 | - (instancetype)initWithProxiedObject:(id)obj shadowColorHandler:(BOOL(^)(void))shadowColorHandler; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNWeakRef.h: -------------------------------------------------------------------------------- 1 | // 2 | // _LNWeakRef.h 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2015-08-23. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <Foundation/Foundation.h> 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface _LNWeakRef : NSObject 14 | 15 | @property (nonatomic, weak, readonly) id object; 16 | 17 | + (instancetype)refWithObject:(id)object; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /LNPopupController/LNPopupController/Private/_LNWeakRef.m: -------------------------------------------------------------------------------- 1 | // 2 | // _LNWeakRef.m 3 | // LNPopupController 4 | // 5 | // Created by Léo Natan on 2015-08-23. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "_LNWeakRef.h" 10 | 11 | @implementation _LNWeakRef 12 | 13 | + (instancetype)refWithObject:(id)object 14 | { 15 | if(object == nil) 16 | { 17 | return nil; 18 | } 19 | 20 | _LNWeakRef* rv = [self new]; 21 | rv->_object = object; 22 | 23 | return rv; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /LNPopupController/include/LNPopupController/LNPopupBar.h: -------------------------------------------------------------------------------- 1 | ../../LNPopupController/LNPopupBar.h -------------------------------------------------------------------------------- /LNPopupController/include/LNPopupController/LNPopupBarAppearance.h: -------------------------------------------------------------------------------- 1 | ../../LNPopupController/LNPopupBarAppearance.h -------------------------------------------------------------------------------- /LNPopupController/include/LNPopupController/LNPopupCloseButton.h: -------------------------------------------------------------------------------- 1 | ../../LNPopupController/LNPopupCloseButton.h -------------------------------------------------------------------------------- /LNPopupController/include/LNPopupController/LNPopupContentView.h: -------------------------------------------------------------------------------- 1 | ../../LNPopupController/LNPopupContentView.h -------------------------------------------------------------------------------- /LNPopupController/include/LNPopupController/LNPopupController.h: -------------------------------------------------------------------------------- 1 | ../../LNPopupController.h -------------------------------------------------------------------------------- /LNPopupController/include/LNPopupController/LNPopupCustomBarViewController.h: -------------------------------------------------------------------------------- 1 | ../../LNPopupController/LNPopupCustomBarViewController.h -------------------------------------------------------------------------------- /LNPopupController/include/LNPopupController/LNPopupDefinitions.h: -------------------------------------------------------------------------------- 1 | ../../LNPopupController/LNPopupDefinitions.h -------------------------------------------------------------------------------- /LNPopupController/include/LNPopupController/LNPopupImageView.h: -------------------------------------------------------------------------------- 1 | ../../LNPopupController/LNPopupImageView.h -------------------------------------------------------------------------------- /LNPopupController/include/LNPopupController/LNPopupItem.h: -------------------------------------------------------------------------------- 1 | ../../LNPopupController/LNPopupItem.h -------------------------------------------------------------------------------- /LNPopupController/include/LNPopupController/UIViewController+LNPopupSupport.h: -------------------------------------------------------------------------------- 1 | ../../LNPopupController/UIViewController+LNPopupSupport.h -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <Workspace 3 | version = "1.0"> 4 | <FileRef 5 | location = "self:"> 6 | </FileRef> 7 | </Workspace> 8 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3 | <plist version="1.0"> 4 | <dict> 5 | <key>IDEDidComputeMac32BitWarning</key> 6 | <true/> 7 | </dict> 8 | </plist> 9 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample.xcodeproj/xcshareddata/xcschemes/LNPopupControllerExampleNoPopup.xcscheme: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <Scheme 3 | LastUpgradeVersion = "9999" 4 | version = "2.0"> 5 | <BuildAction 6 | parallelizeBuildables = "YES" 7 | buildImplicitDependencies = "YES"> 8 | <BuildActionEntries> 9 | <BuildActionEntry 10 | buildForTesting = "YES" 11 | buildForRunning = "YES" 12 | buildForProfiling = "YES" 13 | buildForArchiving = "YES" 14 | buildForAnalyzing = "YES"> 15 | <BuildableReference 16 | BuildableIdentifier = "primary" 17 | BlueprintIdentifier = "39FAFC2E24E71A6C008BBC2D" 18 | BuildableName = "LNPopupControllerExampleNoPopup.app" 19 | BlueprintName = "LNPopupControllerExampleNoPopup" 20 | ReferencedContainer = "container:LNPopupControllerExample.xcodeproj"> 21 | </BuildableReference> 22 | </BuildActionEntry> 23 | </BuildActionEntries> 24 | </BuildAction> 25 | <TestAction 26 | buildConfiguration = "Debug" 27 | selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" 28 | selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" 29 | shouldUseLaunchSchemeArgsEnv = "YES"> 30 | <Testables> 31 | </Testables> 32 | </TestAction> 33 | <LaunchAction 34 | buildConfiguration = "Debug" 35 | selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" 36 | selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" 37 | launchStyle = "0" 38 | useCustomWorkingDirectory = "NO" 39 | ignoresPersistentStateOnLaunch = "NO" 40 | debugDocumentVersioning = "NO" 41 | debugXPCServices = "NO" 42 | debugServiceExtension = "internal" 43 | allowLocationSimulation = "YES" 44 | queueDebuggingEnabled = "No"> 45 | <BuildableProductRunnable 46 | runnableDebuggingMode = "0"> 47 | <BuildableReference 48 | BuildableIdentifier = "primary" 49 | BlueprintIdentifier = "39FAFC2E24E71A6C008BBC2D" 50 | BuildableName = "LNPopupControllerExampleNoPopup.app" 51 | BlueprintName = "LNPopupControllerExampleNoPopup" 52 | ReferencedContainer = "container:LNPopupControllerExample.xcodeproj"> 53 | </BuildableReference> 54 | </BuildableProductRunnable> 55 | </LaunchAction> 56 | <ProfileAction 57 | buildConfiguration = "Release" 58 | shouldUseLaunchSchemeArgsEnv = "YES" 59 | savedToolIdentifier = "" 60 | useCustomWorkingDirectory = "NO" 61 | debugDocumentVersioning = "YES"> 62 | <BuildableProductRunnable 63 | runnableDebuggingMode = "0"> 64 | <BuildableReference 65 | BuildableIdentifier = "primary" 66 | BlueprintIdentifier = "39FAFC2E24E71A6C008BBC2D" 67 | BuildableName = "LNPopupControllerExampleNoPopup.app" 68 | BlueprintName = "LNPopupControllerExampleNoPopup" 69 | ReferencedContainer = "container:LNPopupControllerExample.xcodeproj"> 70 | </BuildableReference> 71 | </BuildableProductRunnable> 72 | </ProfileAction> 73 | <AnalyzeAction 74 | buildConfiguration = "Debug"> 75 | </AnalyzeAction> 76 | <ArchiveAction 77 | buildConfiguration = "Release" 78 | revealArchiveInOrganizer = "YES"> 79 | </ArchiveAction> 80 | </Scheme> 81 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/CustomBarScene/CustomMapBarViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CustomMapBarViewController.swift 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2016-12-30. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #if LNPOPUP 10 | import UIKit 11 | 12 | class CustomMapBarView: UIView { 13 | override var frame: CGRect { 14 | didSet { 15 | print("Size: \(self.frame)") 16 | } 17 | } 18 | } 19 | 20 | class CustomMapBarViewController: LNPopupCustomBarViewController { 21 | @IBOutlet weak var searchBar: UISearchBar! 22 | @IBOutlet var heightConstraint: NSLayoutConstraint! 23 | 24 | override var wantsDefaultTapGestureRecognizer: Bool { 25 | return false 26 | } 27 | 28 | override var wantsDefaultHighlightGestureRecognizer: Bool { 29 | return false 30 | } 31 | 32 | fileprivate func updateConstraint() { 33 | heightConstraint.constant = 65 34 | self.preferredContentSize = view.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize) 35 | } 36 | 37 | override func viewDidLoad() { 38 | super.viewDidLoad() 39 | 40 | view.translatesAutoresizingMaskIntoConstraints = false 41 | 42 | updateConstraint() 43 | 44 | guard let bg = (containingPopupBar?.value(forKey: "backgroundView") as? UIView) else { 45 | return 46 | } 47 | 48 | bg.clipsToBounds = true 49 | bg.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner] 50 | bg.layer.cornerRadius = 20 51 | bg.layer.cornerCurve = .continuous 52 | 53 | } 54 | 55 | override func viewWillAppear(_ animated: Bool) { 56 | super.viewWillAppear(animated) 57 | } 58 | 59 | override func viewIsAppearing(_ animated: Bool) { 60 | super.viewIsAppearing(animated) 61 | } 62 | 63 | override func viewDidAppear(_ animated: Bool) { 64 | super.viewDidAppear(animated) 65 | } 66 | 67 | override func viewWillDisappear(_ animated: Bool) { 68 | super.viewWillDisappear(animated) 69 | } 70 | 71 | override func viewDidDisappear(_ animated: Bool) { 72 | super.viewDidDisappear(animated) 73 | } 74 | 75 | override func popupItemDidUpdate() { 76 | searchBar.text = popupItem.title 77 | } 78 | 79 | override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { 80 | super.viewWillTransition(to: size, with: coordinator) 81 | 82 | coordinator.animate(alongsideTransition: { [unowned self] context in 83 | updateConstraint() 84 | }, completion: nil) 85 | } 86 | } 87 | #endif 88 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/CustomBarScene/LocationsController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LocationsController.swift 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2016-12-30. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class LocationsController: UITableViewController, UISearchBarDelegate { 12 | @IBOutlet weak var searchBar: UISearchBar! 13 | 14 | override func viewDidLoad() { 15 | super.viewDidLoad() 16 | 17 | searchBar.delegate = self 18 | } 19 | 20 | override func viewWillAppear(_ animated: Bool) { 21 | super.viewWillAppear(animated) 22 | 23 | #if LNPOPUP 24 | searchBar.text = popupItem.title 25 | #endif 26 | } 27 | 28 | override func scrollViewDidScroll(_ scrollView: UIScrollView) { 29 | searchBar.resignFirstResponder() 30 | } 31 | 32 | override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 33 | tableView.deselectRow(at: indexPath, animated: true) 34 | searchBar.resignFirstResponder() 35 | #if LNPOPUP 36 | popupItem.title = tableView.cellForRow(at: indexPath)?.textLabel?.text 37 | popupPresentationContainer?.closePopup(animated: true, completion: nil) 38 | #endif 39 | } 40 | 41 | func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { 42 | #if LNPOPUP 43 | popupItem.title = searchText 44 | #endif 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/CustomBarScene_ManualLayout/ManualLayoutCustomBarViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ManualLayoutCustomBarViewController.swift 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2020-09-01. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #if LNPOPUP 10 | @objc public 11 | class ManualLayoutCustomBarViewController: LNPopupCustomBarViewController { 12 | let centeredButton = UIButton(type: .system) 13 | let leftButton = UIButton(type: .system) 14 | let backgroundView = UIVisualEffectView(effect: UIBlurEffect(style: .systemChromeMaterial)) 15 | 16 | public 17 | override func viewDidLoad() { 18 | super.viewDidLoad() 19 | 20 | view.autoresizingMask = [] 21 | 22 | backgroundView.layer.masksToBounds = true 23 | backgroundView.layer.cornerCurve = .continuous 24 | backgroundView.layer.cornerRadius = 15 25 | view.addSubview(backgroundView) 26 | 27 | centeredButton.setTitle(NSLocalizedString("Centered", comment: ""), for: .normal) 28 | centeredButton.titleLabel?.font = UIFont.preferredFont(forTextStyle: .headline) 29 | centeredButton.sizeToFit() 30 | view.addSubview(centeredButton) 31 | 32 | leftButton.setTitle("<- \(NSLocalizedString("Leading", comment: ""))", for: .normal) 33 | leftButton.titleLabel?.font = UIFont.preferredFont(forTextStyle: .headline) 34 | leftButton.sizeToFit() 35 | view.addSubview(leftButton) 36 | 37 | self.preferredContentSize = CGSize(width: 0, height: 50) 38 | animateSize() 39 | } 40 | 41 | var idx = 0 42 | func animateSize() { 43 | idx = 1 - idx; 44 | UIView.animate(withDuration: 1.0, delay: 0.0, options: [.curveEaseInOut, .allowUserInteraction]) { 45 | self.preferredContentSize = CGSize(width: 0, height: 50 + self.idx * 50) 46 | } completion: { [weak self] _ in 47 | guard let self else { 48 | return 49 | } 50 | 51 | self.animateSize() 52 | } 53 | } 54 | 55 | public 56 | override func viewDidLayoutSubviews() { 57 | super.viewDidLayoutSubviews() 58 | 59 | let insetLeft = CGFloat.maximum(view.safeAreaInsets.left, 20) 60 | let insetRight = CGFloat.maximum(view.safeAreaInsets.right, 20) 61 | 62 | backgroundView.frame = CGRect(x: insetLeft, y: 2, width: view.bounds.width - insetLeft - insetRight, height: view.bounds.height - 4) 63 | centeredButton.center = backgroundView.center 64 | if UIView.userInterfaceLayoutDirection(for: view.semanticContentAttribute) == .leftToRight { 65 | leftButton.frame = CGRect(x: insetLeft + 20, y: backgroundView.center.y - leftButton.bounds.size.height / 2, width: leftButton.bounds.size.width, height: leftButton.bounds.size.height) 66 | } else { 67 | leftButton.frame = CGRect(x: view.bounds.width - insetRight - leftButton.bounds.width - 20, y: backgroundView.center.y - leftButton.bounds.size.height / 2, width: leftButton.bounds.size.width, height: leftButton.bounds.size.height) 68 | } 69 | } 70 | 71 | public 72 | override var wantsDefaultTapGestureRecognizer: Bool { 73 | return false 74 | } 75 | 76 | public 77 | override var wantsDefaultPanGestureRecognizer: Bool { 78 | return false 79 | } 80 | 81 | public 82 | override var wantsDefaultHighlightGestureRecognizer: Bool { 83 | return false 84 | } 85 | } 86 | #endif 87 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Info.plist: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3 | <plist version="1.0"> 4 | <dict> 5 | <key>CADisableMinimumFrameDurationOnPhone</key> 6 | <true/> 7 | <key>CFBundleDevelopmentRegion</key> 8 | <string>en</string> 9 | <key>CFBundleDisplayName</key> 10 | <string>LNPopup</string> 11 | <key>CFBundleExecutable</key> 12 | <string>$(EXECUTABLE_NAME)</string> 13 | <key>CFBundleIdentifier</key> 14 | <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> 15 | <key>CFBundleInfoDictionaryVersion</key> 16 | <string>6.0</string> 17 | <key>CFBundleName</key> 18 | <string>$(PRODUCT_NAME)</string> 19 | <key>CFBundlePackageType</key> 20 | <string>APPL</string> 21 | <key>CFBundleShortVersionString</key> 22 | <string>3.0.7</string> 23 | <key>CFBundleSignature</key> 24 | <string>????</string> 25 | <key>CFBundleVersion</key> 26 | <string>1</string> 27 | <key>LSApplicationCategoryType</key> 28 | <string>public.app-category.developer-tools</string> 29 | <key>LSRequiresIPhoneOS</key> 30 | <true/> 31 | <key>UIApplicationSceneManifest</key> 32 | <dict> 33 | <key>UIApplicationSupportsMultipleScenes</key> 34 | <true/> 35 | <key>UISceneConfigurations</key> 36 | <dict> 37 | <key>UIWindowSceneSessionRoleApplication</key> 38 | <array> 39 | <dict> 40 | <key>UISceneConfigurationName</key> 41 | <string>LNPopupExample</string> 42 | <key>UISceneDelegateClassName</key> 43 | <string>SceneDelegate</string> 44 | <key>UISceneStoryboardFile</key> 45 | <string>Main</string> 46 | </dict> 47 | </array> 48 | </dict> 49 | </dict> 50 | <key>UIApplicationSupportsIndirectInputEvents</key> 51 | <true/> 52 | <key>UILaunchStoryboardName</key> 53 | <string>LaunchScreen</string> 54 | <key>UIMainStoryboardFile</key> 55 | <string>Main</string> 56 | <key>UIRequiredDeviceCapabilities</key> 57 | <array> 58 | <string>armv7</string> 59 | </array> 60 | <key>UIRequiresFullScreen</key> 61 | <false/> 62 | <key>UIStatusBarTintParameters</key> 63 | <dict> 64 | <key>UINavigationBar</key> 65 | <dict> 66 | <key>Style</key> 67 | <string>UIBarStyleDefault</string> 68 | <key>Translucent</key> 69 | <true/> 70 | </dict> 71 | </dict> 72 | <key>UISupportedInterfaceOrientations</key> 73 | <array> 74 | <string>UIInterfaceOrientationLandscapeLeft</string> 75 | <string>UIInterfaceOrientationLandscapeRight</string> 76 | <string>UIInterfaceOrientationPortrait</string> 77 | </array> 78 | <key>UISupportedInterfaceOrientations~ipad</key> 79 | <array> 80 | <string>UIInterfaceOrientationLandscapeLeft</string> 81 | <string>UIInterfaceOrientationLandscapeRight</string> 82 | <string>UIInterfaceOrientationPortrait</string> 83 | <string>UIInterfaceOrientationPortraitUpsideDown</string> 84 | </array> 85 | </dict> 86 | </plist> 87 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/LNPopupControllerExample.entitlements: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3 | <plist version="1.0"> 4 | <dict> 5 | <key>com.apple.security.application-groups</key> 6 | <array> 7 | <string>group.com.LeoNatan.LNPopupSettings</string> 8 | </array> 9 | </dict> 10 | </plist> 11 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/LNPopupControllerExampleNoPopup-Info.plist: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3 | <plist version="1.0"> 4 | <dict> 5 | <key>CADisableMinimumFrameDurationOnPhone</key> 6 | <true/> 7 | <key>CFBundleDevelopmentRegion</key> 8 | <string>en</string> 9 | <key>CFBundleDisplayName</key> 10 | <string>LNPopup</string> 11 | <key>CFBundleExecutable</key> 12 | <string>$(EXECUTABLE_NAME)</string> 13 | <key>CFBundleIdentifier</key> 14 | <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> 15 | <key>CFBundleInfoDictionaryVersion</key> 16 | <string>6.0</string> 17 | <key>CFBundleName</key> 18 | <string>$(PRODUCT_NAME)</string> 19 | <key>CFBundlePackageType</key> 20 | <string>APPL</string> 21 | <key>CFBundleShortVersionString</key> 22 | <string>1.0</string> 23 | <key>CFBundleSignature</key> 24 | <string>????</string> 25 | <key>CFBundleVersion</key> 26 | <string>1</string> 27 | <key>LSRequiresIPhoneOS</key> 28 | <true/> 29 | <key>UIApplicationSceneManifest</key> 30 | <dict> 31 | <key>UIApplicationSupportsMultipleScenes</key> 32 | <true/> 33 | <key>UISceneConfigurations</key> 34 | <dict> 35 | <key>UIWindowSceneSessionRoleApplication</key> 36 | <array> 37 | <dict> 38 | <key>UISceneConfigurationName</key> 39 | <string>LNPopupExample</string> 40 | <key>UISceneDelegateClassName</key> 41 | <string>SceneDelegate</string> 42 | <key>UISceneStoryboardFile</key> 43 | <string>Main</string> 44 | </dict> 45 | </array> 46 | </dict> 47 | </dict> 48 | <key>UILaunchStoryboardName</key> 49 | <string>LaunchScreen</string> 50 | <key>UIMainStoryboardFile</key> 51 | <string>Main</string> 52 | <key>UIRequiredDeviceCapabilities</key> 53 | <array> 54 | <string>armv7</string> 55 | </array> 56 | <key>UIRequiresFullScreen</key> 57 | <false/> 58 | <key>UIStatusBarTintParameters</key> 59 | <dict> 60 | <key>UINavigationBar</key> 61 | <dict> 62 | <key>Style</key> 63 | <string>UIBarStyleDefault</string> 64 | <key>Translucent</key> 65 | <true/> 66 | </dict> 67 | </dict> 68 | <key>UISupportedInterfaceOrientations</key> 69 | <array> 70 | <string>UIInterfaceOrientationPortrait</string> 71 | <string>UIInterfaceOrientationLandscapeLeft</string> 72 | <string>UIInterfaceOrientationLandscapeRight</string> 73 | <string>UIInterfaceOrientationPortraitUpsideDown</string> 74 | </array> 75 | <key>UISupportedInterfaceOrientations~ipad</key> 76 | <array> 77 | <string>UIInterfaceOrientationPortrait</string> 78 | <string>UIInterfaceOrientationPortraitUpsideDown</string> 79 | <string>UIInterfaceOrientationLandscapeLeft</string> 80 | <string>UIInterfaceOrientationLandscapeRight</string> 81 | </array> 82 | <key>LSApplicationCategoryType</key> 83 | <string>public.app-category.developer-tools</string> 84 | </dict> 85 | </plist> 86 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/MusicScene/MusicCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MusicCell.swift 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2015-08-23. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class MusicCell: UITableViewCell { 12 | let selectionEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterial)) 13 | 14 | required init?(coder: NSCoder) { 15 | super.init(coder: coder) 16 | 17 | selectionEffectView.frame = bounds 18 | selectionEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight] 19 | selectionEffectView.isHidden = true 20 | addSubview(selectionEffectView) 21 | sendSubviewToBack(selectionEffectView) 22 | 23 | selectionStyle = .none 24 | } 25 | 26 | override func layoutSubviews() { 27 | super.layoutSubviews() 28 | 29 | imageView?.layer.cornerRadius = 5 30 | imageView?.layer.cornerCurve = .continuous 31 | 32 | if UIView.userInterfaceLayoutDirection(for: semanticContentAttribute) == .leftToRight { 33 | imageView?.frame = CGRect(x: layoutMargins.left, y: bounds.height / 2 - 24, width: 48, height: 48) 34 | 35 | textLabel?.textAlignment = .left 36 | textLabel?.lineBreakMode = .byTruncatingTail 37 | textLabel?.frame = CGRect(x: imageView!.frame.maxX + 20, y: textLabel!.frame.minY, width: accessoryView!.frame.minX - imageView!.frame.maxX - 40, height: textLabel!.frame.height) 38 | detailTextLabel?.textAlignment = .left 39 | detailTextLabel?.lineBreakMode = .byTruncatingTail 40 | detailTextLabel?.frame = CGRect(x: imageView!.frame.maxX + 20, y: detailTextLabel!.frame.minY, width: accessoryView!.frame.minX - imageView!.frame.maxX - 40, height: detailTextLabel!.frame.height) 41 | 42 | separatorInset = UIEdgeInsets(top: 0, left: textLabel!.frame.origin.x, bottom: 0, right: 0) 43 | } else { 44 | imageView?.frame = CGRect(x: contentView.bounds.width - layoutMargins.right - 48, y: bounds.height / 2 - 24, width: 48, height: 48) 45 | 46 | textLabel?.textAlignment = .right 47 | textLabel?.lineBreakMode = .byTruncatingHead 48 | textLabel?.frame = CGRect(x: 20, y: textLabel!.frame.minY, width: contentView.bounds.width - (2 * layoutMargins.right) - imageView!.bounds.width - 20, height: textLabel!.frame.height) 49 | detailTextLabel?.textAlignment = .right 50 | detailTextLabel?.lineBreakMode = .byTruncatingHead 51 | detailTextLabel?.frame = CGRect(x: 20, y: detailTextLabel!.frame.minY, width: contentView.bounds.width - (2 * layoutMargins.right) - imageView!.bounds.width - 20, height: detailTextLabel!.frame.height) 52 | 53 | separatorInset = UIEdgeInsets(top: 0, left: textLabel!.frame.origin.x, bottom: 0, right: 0) 54 | } 55 | } 56 | 57 | override func setHighlighted(_ highlighted: Bool, animated: Bool) { 58 | guard isHighlighted != highlighted else { 59 | return 60 | } 61 | 62 | super.setHighlighted(highlighted, animated: animated) 63 | 64 | selectionEffectView.alpha = highlighted ? 0.0 : 1.0 65 | selectionEffectView.isHidden = false 66 | UIView.animate(withDuration: highlighted ? 0.0 : 0.35) { 67 | self.selectionEffectView.alpha = highlighted ? 1.0 : 0.0 68 | } completion: { _ in 69 | self.selectionEffectView.isHidden = highlighted == false 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/MusicScene/PortraitTabBarController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PortraitTabBarController.swift 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2015-08-23. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class PortraitTabBarController: UITabBarController { 12 | 13 | override var supportedInterfaceOrientations : UIInterfaceOrientationMask { 14 | return .portrait 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Settings/Base.lproj/Settings.storyboard: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="KD9-4L-yPt"> 3 | <device id="retina6_12" orientation="portrait" appearance="light"/> 4 | <dependencies> 5 | <deployment identifier="iOS"/> 6 | <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22504"/> 7 | <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> 8 | </dependencies> 9 | <scenes> 10 | <!--Settings View Controller--> 11 | <scene sceneID="i41-nV-z2g"> 12 | <objects> 13 | <hostingController storyboardIdentifier="SettingsView" id="27B-rg-hpf" customClass="SettingsViewController" customModule="LNPopupControllerExample" customModuleProvider="target" sceneMemberID="viewController"> 14 | <navigationItem key="navigationItem" leftItemsSupplementBackButton="YES" id="KGL-NH-gfY"/> 15 | </hostingController> 16 | <placeholder placeholderIdentifier="IBFirstResponder" id="HqC-rD-hqG" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/> 17 | </objects> 18 | <point key="canvasLocation" x="1740" y="-2439"/> 19 | </scene> 20 | <!--Navigation Controller--> 21 | <scene sceneID="Y6z-Jl-kP6"> 22 | <objects> 23 | <navigationController storyboardIdentifier="Settings" id="KD9-4L-yPt" sceneMemberID="viewController"> 24 | <navigationBar key="navigationBar" contentMode="scaleToFill" largeTitles="YES" id="ism-MM-egy"> 25 | <rect key="frame" x="0.0" y="59" width="393" height="96"/> 26 | <autoresizingMask key="autoresizingMask"/> 27 | </navigationBar> 28 | <toolbar key="toolbar" opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="Gxc-XC-Tbd"> 29 | <autoresizingMask key="autoresizingMask"/> 30 | </toolbar> 31 | <connections> 32 | <segue destination="27B-rg-hpf" kind="relationship" relationship="rootViewController" id="B7W-Fa-e97"/> 33 | </connections> 34 | </navigationController> 35 | <placeholder placeholderIdentifier="IBFirstResponder" id="11d-Ub-Fi7" userLabel="First Responder" sceneMemberID="firstResponder"/> 36 | </objects> 37 | <point key="canvasLocation" x="904.18604651162786" y="-2439.2703862660946"/> 38 | </scene> 39 | </scenes> 40 | <color key="tintColor" systemColor="systemPinkColor"/> 41 | <resources> 42 | <systemColor name="systemPinkColor"> 43 | <color red="1" green="0.17647058823529413" blue="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> 44 | </systemColor> 45 | </resources> 46 | </document> 47 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2015-08-23. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | 11 | @interface AppDelegate : UIResponder <UIApplicationDelegate> 12 | 13 | @property (strong, nonatomic) UIWindow* window; 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "platform" : "universal", 6 | "reference" : "systemPinkColor" 7 | }, 8 | "idiom" : "universal" 9 | } 10 | ], 11 | "info" : { 12 | "author" : "xcode", 13 | "version" : 1 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icon_1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | }, 9 | { 10 | "appearances" : [ 11 | { 12 | "appearance" : "luminosity", 13 | "value" : "dark" 14 | } 15 | ], 16 | "filename" : "Icon-dark.png", 17 | "idiom" : "universal", 18 | "platform" : "ios", 19 | "size" : "1024x1024" 20 | }, 21 | { 22 | "appearances" : [ 23 | { 24 | "appearance" : "luminosity", 25 | "value" : "tinted" 26 | } 27 | ], 28 | "filename" : "Icon-tinted.png", 29 | "idiom" : "universal", 30 | "platform" : "ios", 31 | "size" : "1024x1024" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/AppIcon.appiconset/Icon-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/AppIcon.appiconset/Icon-dark.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/AppIcon.appiconset/Icon-tinted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/AppIcon.appiconset/Icon-tinted.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/AppIcon.appiconset/icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/AppIcon.appiconset/icon_1024.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/AppIconPopupBar.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icon_1024.png", 5 | "idiom" : "universal" 6 | }, 7 | { 8 | "appearances" : [ 9 | { 10 | "appearance" : "luminosity", 11 | "value" : "dark" 12 | } 13 | ], 14 | "filename" : "Icon-dark.png", 15 | "idiom" : "universal" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/AppIconPopupBar.imageset/Icon-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/AppIconPopupBar.imageset/Icon-dark.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/AppIconPopupBar.imageset/icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/AppIconPopupBar.imageset/icon_1024.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/demoAlbum.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "smackandtoss-blue-orange-abstract-fog-ipad-wallpaper.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/demoAlbum.imageset/smackandtoss-blue-orange-abstract-fog-ipad-wallpaper.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/demoAlbum.imageset/smackandtoss-blue-orange-abstract-fog-ipad-wallpaper.jpg -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/gears.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "gears.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | }, 12 | "properties" : { 13 | "template-rendering-intent" : "template" 14 | } 15 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/gears.imageset/gears.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/gears.imageset/gears.pdf -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-80s-hits.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-80s-hits@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-80s-hits@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre1.imageset/genre-image-80s-hits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre1.imageset/genre-image-80s-hits.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre1.imageset/genre-image-80s-hits@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre1.imageset/genre-image-80s-hits@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre1.imageset/genre-image-80s-hits@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre1.imageset/genre-image-80s-hits@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre10.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-country-hits.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-country-hits@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-country-hits@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre10.imageset/genre-image-country-hits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre10.imageset/genre-image-country-hits.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre10.imageset/genre-image-country-hits@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre10.imageset/genre-image-country-hits@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre10.imageset/genre-image-country-hits@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre10.imageset/genre-image-country-hits@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre11.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-dance.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-dance@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-dance@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre11.imageset/genre-image-dance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre11.imageset/genre-image-dance.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre11.imageset/genre-image-dance@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre11.imageset/genre-image-dance@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre11.imageset/genre-image-dance@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre11.imageset/genre-image-dance@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre12.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-decades.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-decades@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-decades@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre12.imageset/genre-image-decades.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre12.imageset/genre-image-decades.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre12.imageset/genre-image-decades@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre12.imageset/genre-image-decades@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre12.imageset/genre-image-decades@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre12.imageset/genre-image-decades@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre13.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-electronic.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-electronic@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-electronic@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre13.imageset/genre-image-electronic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre13.imageset/genre-image-electronic.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre13.imageset/genre-image-electronic@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre13.imageset/genre-image-electronic@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre13.imageset/genre-image-electronic@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre13.imageset/genre-image-electronic@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre14.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-gospel.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-gospel@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-gospel@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre14.imageset/genre-image-gospel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre14.imageset/genre-image-gospel.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre14.imageset/genre-image-gospel@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre14.imageset/genre-image-gospel@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre14.imageset/genre-image-gospel@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre14.imageset/genre-image-gospel@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre15.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-hip-hop.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-hip-hop@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-hip-hop@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre15.imageset/genre-image-hip-hop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre15.imageset/genre-image-hip-hop.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre15.imageset/genre-image-hip-hop@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre15.imageset/genre-image-hip-hop@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre15.imageset/genre-image-hip-hop@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre15.imageset/genre-image-hip-hop@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre16.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-indie.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-indie@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-indie@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre16.imageset/genre-image-indie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre16.imageset/genre-image-indie.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre16.imageset/genre-image-indie@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre16.imageset/genre-image-indie@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre16.imageset/genre-image-indie@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre16.imageset/genre-image-indie@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre17-expanded.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "genre-image-jazz-expanded.jpg", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre17-expanded.imageset/genre-image-jazz-expanded.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre17-expanded.imageset/genre-image-jazz-expanded.jpg -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre17.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-jazz.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-jazz@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-jazz@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre17.imageset/genre-image-jazz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre17.imageset/genre-image-jazz.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre17.imageset/genre-image-jazz@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre17.imageset/genre-image-jazz@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre17.imageset/genre-image-jazz@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre17.imageset/genre-image-jazz@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre18.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-kids-and-family.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-kids-and-family@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-kids-and-family@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre18.imageset/genre-image-kids-and-family.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre18.imageset/genre-image-kids-and-family.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre18.imageset/genre-image-kids-and-family@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre18.imageset/genre-image-kids-and-family@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre18.imageset/genre-image-kids-and-family@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre18.imageset/genre-image-kids-and-family@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre19.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-latin-hits.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-latin-hits@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-latin-hits@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre19.imageset/genre-image-latin-hits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre19.imageset/genre-image-latin-hits.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre19.imageset/genre-image-latin-hits@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre19.imageset/genre-image-latin-hits@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre19.imageset/genre-image-latin-hits@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre19.imageset/genre-image-latin-hits@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-alternative.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-alternative@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-alternative@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre2.imageset/genre-image-alternative.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre2.imageset/genre-image-alternative.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre2.imageset/genre-image-alternative@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre2.imageset/genre-image-alternative@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre2.imageset/genre-image-alternative@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre2.imageset/genre-image-alternative@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre20.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-metal.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-metal@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-metal@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre20.imageset/genre-image-metal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre20.imageset/genre-image-metal.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre20.imageset/genre-image-metal@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre20.imageset/genre-image-metal@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre20.imageset/genre-image-metal@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre20.imageset/genre-image-metal@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre21.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-modern-rock.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-modern-rock@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-modern-rock@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre21.imageset/genre-image-modern-rock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre21.imageset/genre-image-modern-rock.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre21.imageset/genre-image-modern-rock@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre21.imageset/genre-image-modern-rock@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre21.imageset/genre-image-modern-rock@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre21.imageset/genre-image-modern-rock@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre22.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-pop-gold.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-pop-gold@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-pop-gold@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre22.imageset/genre-image-pop-gold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre22.imageset/genre-image-pop-gold.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre22.imageset/genre-image-pop-gold@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre22.imageset/genre-image-pop-gold@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre22.imageset/genre-image-pop-gold@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre22.imageset/genre-image-pop-gold@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre23.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-pop-hits.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-pop-hits@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-pop-hits@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre23.imageset/genre-image-pop-hits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre23.imageset/genre-image-pop-hits.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre23.imageset/genre-image-pop-hits@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre23.imageset/genre-image-pop-hits@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre23.imageset/genre-image-pop-hits@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre23.imageset/genre-image-pop-hits@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre24.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-randb.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-randb@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-randb@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre24.imageset/genre-image-randb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre24.imageset/genre-image-randb.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre24.imageset/genre-image-randb@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre24.imageset/genre-image-randb@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre24.imageset/genre-image-randb@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre24.imageset/genre-image-randb@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre25.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-reggae.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-reggae@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-reggae@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre25.imageset/genre-image-reggae.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre25.imageset/genre-image-reggae.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre25.imageset/genre-image-reggae@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre25.imageset/genre-image-reggae@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre25.imageset/genre-image-reggae@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre25.imageset/genre-image-reggae@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre26.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-regional-mexican.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-regional-mexican@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-regional-mexican@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre26.imageset/genre-image-regional-mexican.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre26.imageset/genre-image-regional-mexican.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre26.imageset/genre-image-regional-mexican@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre26.imageset/genre-image-regional-mexican@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre26.imageset/genre-image-regional-mexican@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre26.imageset/genre-image-regional-mexican@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre27.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-singer-songwriter.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-singer-songwriter@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-singer-songwriter@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre27.imageset/genre-image-singer-songwriter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre27.imageset/genre-image-singer-songwriter.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre27.imageset/genre-image-singer-songwriter@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre27.imageset/genre-image-singer-songwriter@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre27.imageset/genre-image-singer-songwriter@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre27.imageset/genre-image-singer-songwriter@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre28.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-smooth-jazz.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-smooth-jazz@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-smooth-jazz@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre28.imageset/genre-image-smooth-jazz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre28.imageset/genre-image-smooth-jazz.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre28.imageset/genre-image-smooth-jazz@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre28.imageset/genre-image-smooth-jazz@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre28.imageset/genre-image-smooth-jazz@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre28.imageset/genre-image-smooth-jazz@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre29.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-smooth-pop.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-smooth-pop@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-smooth-pop@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre29.imageset/genre-image-smooth-pop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre29.imageset/genre-image-smooth-pop.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre29.imageset/genre-image-smooth-pop@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre29.imageset/genre-image-smooth-pop@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre29.imageset/genre-image-smooth-pop@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre29.imageset/genre-image-smooth-pop@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-blues.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-blues@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-blues@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre3.imageset/genre-image-blues.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre3.imageset/genre-image-blues.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre3.imageset/genre-image-blues@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre3.imageset/genre-image-blues@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre3.imageset/genre-image-blues@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre3.imageset/genre-image-blues@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre30.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-world-hits.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-world-hits@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-world-hits@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre30.imageset/genre-image-world-hits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre30.imageset/genre-image-world-hits.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre30.imageset/genre-image-world-hits@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre30.imageset/genre-image-world-hits@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre30.imageset/genre-image-world-hits@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre30.imageset/genre-image-world-hits@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-christian.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-christian@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-christian@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre4.imageset/genre-image-christian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre4.imageset/genre-image-christian.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre4.imageset/genre-image-christian@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre4.imageset/genre-image-christian@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre4.imageset/genre-image-christian@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre4.imageset/genre-image-christian@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-classic-alt.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-classic-alt@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-classic-alt@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre5.imageset/genre-image-classic-alt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre5.imageset/genre-image-classic-alt.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre5.imageset/genre-image-classic-alt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre5.imageset/genre-image-classic-alt@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre5.imageset/genre-image-classic-alt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre5.imageset/genre-image-classic-alt@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre6.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-classic-country.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-classic-country@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-classic-country@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre6.imageset/genre-image-classic-country.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre6.imageset/genre-image-classic-country.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre6.imageset/genre-image-classic-country@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre6.imageset/genre-image-classic-country@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre6.imageset/genre-image-classic-country@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre6.imageset/genre-image-classic-country@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre7.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-classic-randb.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-classic-randb@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-classic-randb@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre7.imageset/genre-image-classic-randb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre7.imageset/genre-image-classic-randb.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre7.imageset/genre-image-classic-randb@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre7.imageset/genre-image-classic-randb@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre7.imageset/genre-image-classic-randb@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre7.imageset/genre-image-classic-randb@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre8.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-classic-rock.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-classic-rock@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-classic-rock@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre8.imageset/genre-image-classic-rock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre8.imageset/genre-image-classic-rock.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre8.imageset/genre-image-classic-rock@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre8.imageset/genre-image-classic-rock@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre8.imageset/genre-image-classic-rock@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre8.imageset/genre-image-classic-rock@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre9.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "genre-image-classical.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "genre-image-classical@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "genre-image-classical@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre9.imageset/genre-image-classical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre9.imageset/genre-image-classical.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre9.imageset/genre-image-classical@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre9.imageset/genre-image-classical@2x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre9.imageset/genre-image-classical@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre9.imageset/genre-image-classical@3x.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre_white.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "genre_white.png", 5 | "idiom" : "universal" 6 | }, 7 | { 8 | "appearances" : [ 9 | { 10 | "appearance" : "luminosity", 11 | "value" : "dark" 12 | } 13 | ], 14 | "filename" : "genre_black.png", 15 | "idiom" : "universal" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre_white.imageset/genre_black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre_white.imageset/genre_black.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre_white.imageset/genre_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/genre_white.imageset/genre_white.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/statusBarMask.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "filename" : "mask.png", 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/statusBarMask.imageset/mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/LNPopupControllerExample/LNPopupControllerExample/Supporting/Assets.xcassets/statusBarMask.imageset/mask.png -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/LNPopupControllerExample-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #if LNPOPUP 6 | @import LNPopupController; 7 | #endif 8 | #import "LoremIpsum.h" 9 | #import "RandomColors.h" 10 | #import "SafeSystemImages.h" 11 | #import "SettingKeys.h" 12 | #import "DemoPopupContentViewController.h" 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | @interface UIBlurEffect () 17 | 18 | + (instancetype)_effectWithStyle:(UIBlurEffectStyle)arg1 tintColor:(UIColor*)arg2 invertAutomaticStyle:(BOOL)arg3; 19 | + (instancetype)_effectWithTintColor:(UIColor*)arg1; 20 | + (instancetype)effectWithBlurRadius:(CGFloat)arg1; 21 | + (instancetype)effectWithVariableBlurRadius:(CGFloat)arg1 imageMask:(UIImage*)arg2 API_AVAILABLE(ios(17.0)); 22 | 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22503" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM"> 3 | <device id="retina6_12" orientation="portrait" appearance="light"/> 4 | <dependencies> 5 | <deployment identifier="iOS"/> 6 | <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22503"/> 7 | <capability name="Safe area layout guides" minToolsVersion="9.0"/> 8 | <capability name="System colors in document resources" minToolsVersion="11.0"/> 9 | <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> 10 | </dependencies> 11 | <scenes> 12 | <!--View Controller--> 13 | <scene sceneID="EHf-IW-A2E"> 14 | <objects> 15 | <viewController id="01J-lp-oVM" sceneMemberID="viewController"> 16 | <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3"> 17 | <rect key="frame" x="0.0" y="0.0" width="393" height="852"/> 18 | <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> 19 | <viewLayoutGuide key="safeArea" id="dDD-5z-iaz"/> 20 | <color key="backgroundColor" systemColor="systemGroupedBackgroundColor"/> 21 | </view> 22 | </viewController> 23 | <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/> 24 | </objects> 25 | <point key="canvasLocation" x="34.715000000000003" y="532.5"/> 26 | </scene> 27 | </scenes> 28 | <resources> 29 | <systemColor name="systemGroupedBackgroundColor"> 30 | <color red="0.94901960784313721" green="0.94901960784313721" blue="0.96862745098039216" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> 31 | </systemColor> 32 | </resources> 33 | </document> 34 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/SceneDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.h 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2019-08-21. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | 11 | @interface SceneDelegate : UIResponder <UIWindowSceneDelegate> 12 | 13 | @property (strong, nonatomic) UIWindow* window; 14 | @property (weak, nonatomic) UIWindowScene* windowScene; 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/SceneDelegate.m: -------------------------------------------------------------------------------- 1 | #import "SceneDelegate.h" 2 | 3 | @interface DemoWindow : UIWindow @end 4 | @implementation DemoWindow 5 | 6 | - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 7 | { 8 | id rv = [super hitTest:point withEvent:event]; 9 | 10 | // NSLog(@"DemoWindow hitTest %@", rv); 11 | 12 | return rv; 13 | } 14 | 15 | @end 16 | 17 | @implementation SceneDelegate 18 | 19 | -(instancetype)init 20 | { 21 | self = [super init]; 22 | 23 | if(self) 24 | { 25 | self.window = [DemoWindow new]; 26 | } 27 | 28 | return self; 29 | } 30 | 31 | - (void)scene:(UIWindowScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions 32 | { 33 | self.window.windowScene = scene; 34 | self.windowScene = scene; 35 | 36 | [self.window makeKeyAndVisible]; 37 | 38 | #if TARGET_OS_MACCATALYST 39 | scene.sizeRestrictions.maximumSize = CGSizeMake(DBL_MAX, DBL_MAX); 40 | scene.titlebar.toolbar = nil; 41 | 42 | if([self.window.rootViewController isKindOfClass:UISplitViewController.class]) 43 | { 44 | UISplitViewController* split = (id)self.window.rootViewController; 45 | split.primaryBackgroundStyle = UISplitViewControllerBackgroundStyleSidebar; 46 | } 47 | #endif 48 | } 49 | 50 | - (void)sceneDidDisconnect:(UIScene *)scene 51 | { 52 | // Called as the scene is being released by the system. 53 | // This occurs shortly after the scene enters the background, or when its session is discarded. 54 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 55 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 56 | 57 | self.windowScene = nil; 58 | } 59 | 60 | 61 | - (void)sceneDidBecomeActive:(UIScene *)scene { 62 | // Called when the scene has moved from an inactive state to an active state. 63 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 64 | } 65 | 66 | 67 | - (void)sceneWillResignActive:(UIScene *)scene { 68 | // Called when the scene will move from an active state to an inactive state. 69 | // This may occur due to temporary interruptions (ex. an incoming phone call). 70 | } 71 | 72 | 73 | - (void)sceneWillEnterForeground:(UIScene *)scene { 74 | // Called as the scene transitions from the background to the foreground. 75 | // Use this method to undo the changes made on entering the background. 76 | } 77 | 78 | 79 | - (void)sceneDidEnterBackground:(UIScene *)scene { 80 | // Called as the scene transitions from the foreground to the background. 81 | // Use this method to save data, release shared resources, and store enough scene-specific state information 82 | // to restore the scene back to its current state. 83 | } 84 | 85 | @end 86 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Supporting/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2015-08-23. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | #import "AppDelegate.h" 11 | @import ObjectiveC; 12 | 13 | #if TARGET_OS_MACCATALYST 14 | @interface NSObject (ZZZ) @end 15 | @implementation NSObject (ZZZ) 16 | 17 | + (void)load 18 | { 19 | Class cls = NSClassFromString(@"UIFocusRingManager"); 20 | Method m1 = class_getClassMethod(cls, NSSelectorFromString(@"moveRingToFocusItem:")); 21 | Method m2 = class_getClassMethod(NSObject.class, @selector(__ln_moveRingToFocusItem:)); 22 | method_exchangeImplementations(m1, m2); 23 | } 24 | 25 | + (void)__ln_moveRingToFocusItem:(id)arg1 26 | { 27 | 28 | } 29 | 30 | @end 31 | #endif 32 | 33 | int main(int argc, char * argv[]) { 34 | @autoreleasepool { 35 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/TestingScene/DemoGallery.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoGallery.h 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2020-11-01. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | 14 | NS_ASSUME_NONNULL_END 15 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/TestingScene/DemoGallery.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoGallery.m 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2020-11-01. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "DemoGallery.h" 10 | 11 | #if LNPOPUP 12 | @import LNPopupController; 13 | #import "IntroWebViewController.h" 14 | #import "LNPopupDemoContextMenuInteraction.h" 15 | #endif 16 | 17 | @interface DemoGalleryToolbar : UIToolbar @end 18 | @implementation DemoGalleryToolbar @end 19 | 20 | @interface SizeClassGalleryCell : UITableViewCell 21 | 22 | @property (nonatomic, getter=isEnabled) BOOL enabled; 23 | 24 | @end 25 | 26 | @implementation SizeClassGalleryCell 27 | 28 | -(void)setEnabled:(BOOL)enabled 29 | { 30 | if(enabled) 31 | { 32 | self.textLabel.textColor = UIColor.labelColor; 33 | self.selectionStyle = UITableViewCellSelectionStyleDefault; 34 | } 35 | else 36 | { 37 | self.textLabel.textColor = UIColor.secondaryLabelColor; 38 | self.selectionStyle = UITableViewCellSelectionStyleNone; 39 | } 40 | } 41 | 42 | - (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection 43 | { 44 | [super traitCollectionDidChange:previousTraitCollection]; 45 | 46 | [self setEnabled:self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassRegular]; 47 | } 48 | 49 | @end 50 | 51 | @import SafariServices; 52 | 53 | @interface DemoGalleryController : UITableViewController@end 54 | @implementation DemoGalleryController 55 | { 56 | #if LNPOPUP 57 | IntroWebViewController* _demoVC; 58 | #endif 59 | } 60 | 61 | - (IBAction)unwindToGallery:(UIStoryboardSegue *)unwindSegue { } 62 | 63 | - (void)viewDidLoad 64 | { 65 | [super viewDidLoad]; 66 | 67 | #if LNPOPUP 68 | _demoVC = [IntroWebViewController new]; 69 | 70 | self.navigationController.popupBar.barStyle = LNPopupBarStyleFloating; 71 | self.navigationController.popupBar.standardAppearance.marqueeScrollDelay = 0.0; 72 | self.navigationController.popupBar.standardAppearance.marqueeScrollEnabled = YES; 73 | 74 | self.navigationController.view.tintColor = self.navigationController.navigationBar.tintColor; 75 | [self.navigationController presentPopupBarWithContentViewController:_demoVC animated:NO completion:nil]; 76 | 77 | [self.navigationController.popupBar addInteraction:[LNPopupDemoContextMenuInteraction new]]; 78 | #endif 79 | } 80 | 81 | - (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender 82 | { 83 | if([identifier hasPrefix:@"split"] && self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) 84 | { 85 | [self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow animated:NO]; 86 | 87 | return NO; 88 | } 89 | 90 | return YES; 91 | } 92 | 93 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 94 | { 95 | if(segue.destinationViewController.modalPresentationStyle != UIModalPresentationFullScreen) 96 | { 97 | [self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow animated:YES]; 98 | } 99 | } 100 | 101 | @end 102 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/TestingScene/DemoPopupContentViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoPopupContentViewController.h 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2016-08-06. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | 11 | extern void LNApplyTitleWithSettings(UIViewController* vc) NS_SWIFT_NAME(LNApplyTitleWithSettings(to:)); 12 | 13 | @interface DemoPopupContentViewController : UIViewController 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/TestingScene/DemoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoViewController.h 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2015-08-23. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | 11 | @interface DemoViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/TestingScene/IntroWebViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // IntroWebViewController.h 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2020-10-28. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface IntroWebViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/TestingScene/LNPopupControllerExampleSupport.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupControllerExampleSupport.h 3 | // LNPopupControllerExampleSupport 4 | // 5 | // Created by Léo Natan on 2021-08-31. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | NS_ASSUME_NONNULL_END 14 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/TestingScene/LNPopupDemoContextMenuInteraction.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupDemoContextMenuInteraction.h 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2021-12-17. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface LNPopupDemoContextMenuInteraction : UIContextMenuInteraction 14 | 15 | - (instancetype)init; 16 | - (instancetype)initWithTitle:(BOOL)title; 17 | + (instancetype)new; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/TestingScene/LNPopupDemoContextMenuInteraction.m: -------------------------------------------------------------------------------- 1 | // 2 | // LNPopupDemoContextMenuInteraction.m 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2021-12-17. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "LNPopupDemoContextMenuInteraction.h" 10 | #import "IntroWebViewController.h" 11 | 12 | @interface LNPopupDemoContextMenuInteraction () <UIContextMenuInteractionDelegate> 13 | 14 | @end 15 | 16 | @implementation LNPopupDemoContextMenuInteraction 17 | { 18 | BOOL _includeTitle; 19 | } 20 | 21 | - (instancetype)init 22 | { 23 | return [self initWithTitle:NO]; 24 | } 25 | 26 | - (instancetype)initWithTitle:(BOOL)title 27 | { 28 | self = [super initWithDelegate:self]; 29 | 30 | if(self) 31 | { 32 | _includeTitle = title; 33 | } 34 | 35 | return self; 36 | } 37 | 38 | + (instancetype)new 39 | { 40 | return [[self alloc] init]; 41 | } 42 | 43 | #pragma mark UIContextMenuInteractionDelegate 44 | 45 | - (nullable UIContextMenuConfiguration *)contextMenuInteraction:(UIContextMenuInteraction *)interaction configurationForMenuAtLocation:(CGPoint)location 46 | { 47 | return [UIContextMenuConfiguration configurationWithIdentifier:nil previewProvider:nil actionProvider:^UIMenu * _Nullable(NSArray<UIMenuElement *> * _Nonnull suggestedActions) { 48 | return [UIMenu menuWithTitle: self->_includeTitle ? @"LNPopupController" : @"" children:@[ 49 | [UIMenu menuWithTitle:@"" image:nil identifier:nil options:UIMenuOptionsDisplayInline children:@[ 50 | [UIAction actionWithTitle:NSLocalizedString(@"Visit GitHub Page", @"") image:[UIImage systemImageNamed:@"safari"] identifier:nil handler:^(__kindof UIAction * _Nonnull action) 51 | { 52 | [UIApplication.sharedApplication openURL:[NSURL URLWithString:@"https://github.com/LeoNatan/LNPopupController"] options:@{} completionHandler:nil]; 53 | }], 54 | [UIAction actionWithTitle:NSLocalizedString(@"Report an Issue…", @"") image:[UIImage systemImageNamed:@"ant.fill"] identifier:nil handler:^(__kindof UIAction * _Nonnull action) 55 | { 56 | [UIApplication.sharedApplication openURL:[NSURL URLWithString:@"https://github.com/LeoNatan/LNPopupController/issues/new/choose"] options:@{} completionHandler:nil]; 57 | }] 58 | ]], 59 | [UIAction actionWithTitle:NSLocalizedString(@"Share…", @"") image:[UIImage systemImageNamed:@"square.and.arrow.up"] identifier:nil handler:^(__kindof UIAction * _Nonnull action) 60 | { 61 | UIView* popupBar = [action valueForKeyPath:@"sender.view"]; 62 | UIViewController* presentingController = [popupBar valueForKeyPath:@"viewControllerForAncestor"]; 63 | UIActivityViewController* avc = [[UIActivityViewController alloc] initWithActivityItems:@[[NSURL URLWithString:@"https://github.com/LeoNatan/LNPopupController"]] applicationActivities:nil]; 64 | avc.modalPresentationStyle = UIModalPresentationFormSheet; 65 | avc.popoverPresentationController.sourceView = popupBar; 66 | [presentingController presentViewController:avc animated:YES completion:nil]; 67 | }], 68 | ]]; 69 | }]; 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/TestingScene/LNSplitViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SplitViewController.h 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2023-10-23. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @class LNSplitViewController; 14 | 15 | @interface LNSplitViewController : UISplitViewController @end 16 | 17 | @interface LNSplitViewControllerPrimaryPopup : LNSplitViewController @end 18 | @interface LNSplitViewControllerSecondaryPopup : LNSplitViewController @end 19 | @interface LNSplitViewControllerGlobalPopup : LNSplitViewController @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/TestingScene/LNSplitViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LNSplitViewController.m 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2023-10-23. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | #import "LNSplitViewController.h" 10 | 11 | @implementation LNSplitViewController 12 | 13 | - (void)viewDidLoad 14 | { 15 | [super viewDidLoad]; 16 | 17 | if([self isKindOfClass:LNSplitViewControllerSecondaryPopup.class] == NO) 18 | { 19 | self.minimumPrimaryColumnWidth = 400; 20 | self.maximumPrimaryColumnWidth = 400; 21 | 22 | if(self.style == UISplitViewControllerStyleTripleColumn) 23 | { 24 | self.minimumSupplementaryColumnWidth = 400; 25 | self.maximumSupplementaryColumnWidth = 400; 26 | } 27 | } 28 | } 29 | 30 | - (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator 31 | { 32 | [super willTransitionToTraitCollection:newCollection withTransitionCoordinator:coordinator]; 33 | 34 | if(newCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) 35 | { 36 | [self.presentingViewController dismissViewControllerAnimated:NO completion:nil]; 37 | } 38 | } 39 | 40 | @end 41 | 42 | @implementation LNSplitViewControllerPrimaryPopup @end 43 | @implementation LNSplitViewControllerSecondaryPopup @end 44 | @implementation LNSplitViewControllerGlobalPopup @end 45 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/TestingScene/PageCardViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PageCardViewController.swift 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2024-09-27. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class PageCardViewController: UIViewController { 12 | @IBOutlet var cardView: UIView! 13 | @IBOutlet var indexLabel: UILabel! 14 | public 15 | var prefix: String? = nil { 16 | didSet { 17 | if isViewLoaded { 18 | indexLabel.text = "\(prefix == nil ? "" : prefix!)\(index)" 19 | } 20 | } 21 | } 22 | public 23 | var index: Int = -1 { 24 | didSet { 25 | if isViewLoaded { 26 | indexLabel.text = "\(prefix == nil ? "" : prefix!)\(index)" 27 | } 28 | } 29 | } 30 | 31 | override func viewDidLoad() { 32 | super.viewDidLoad() 33 | 34 | cardView.layer.cornerCurve = .continuous 35 | cardView.layer.cornerRadius = 40 36 | 37 | indexLabel.text = "\(prefix == nil ? "" : prefix!)\(index)" 38 | } 39 | 40 | override func viewSafeAreaInsetsDidChange() { 41 | super.viewSafeAreaInsetsDidChange() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/TestingScene/ScrollingMapViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScrollingMapViewController.swift 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2024-09-27. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ScrollingMapViewController: UIViewController { 12 | override func viewDidLoad() { 13 | super.viewDidLoad() 14 | 15 | #if LNPOPUP 16 | let useCompact = UserDefaults.settings.integer(forKey: .barStyle) == LNPopupBar.Style.compact.rawValue 17 | 18 | let gridBarButtonItem = UIBarButtonItem() 19 | gridBarButtonItem.image = LNSystemImage("map", scale: useCompact ? .compact : .normal) 20 | popupItem.barButtonItems = [gridBarButtonItem] 21 | 22 | LNApplyTitleWithSettings(to: self) 23 | #endif 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Utils/RandomColors.h: -------------------------------------------------------------------------------- 1 | // 2 | // RandomColors.h 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2015-08-23. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | extern UIColor* LNRandomSystemColor(void); 12 | 13 | extern UIColor* LNSeedAdaptiveColor(NSString* seed); 14 | extern UIColor* LNSeedAdaptiveInvertedColor(NSString* seed); 15 | extern UIColor* LNRandomAdaptiveColor(void); 16 | extern UIColor* LNRandomAdaptiveInvertedColor(void); 17 | 18 | extern UIColor* LNSeedDarkColor(NSString* seed); 19 | extern UIColor* LNSeedLightColor(NSString* seed); 20 | extern UIColor* LNRandomDarkColor(void); 21 | extern UIColor* LNRandomLightColor(void); 22 | -------------------------------------------------------------------------------- /LNPopupControllerExample/LNPopupControllerExample/Utils/SafeSystemImages.h: -------------------------------------------------------------------------------- 1 | // 2 | // SafeSystemImages.h 3 | // LNPopupControllerExample 4 | // 5 | // Created by Léo Natan on 2023-09-02. 6 | // Copyright © 2015-2025 Léo Natan. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | typedef NS_ENUM(NSUInteger, LNSystemImageScale) { 14 | LNSystemImageScaleCompact, 15 | LNSystemImageScaleNormal, 16 | LNSystemImageScaleLarge, 17 | LNSystemImageScaleLarger 18 | }; 19 | 20 | extern UIImage* LNSystemImage(NSString* named, LNSystemImageScale scale) NS_SWIFT_NAME(LNSystemImage(_:scale:)); 21 | extern UIBarButtonItem* LNSystemBarButtonItem(NSString* named, LNSystemImageScale scale, __nullable id target, __nullable SEL action) NS_SWIFT_NAME(LNSystemBarButtonItem(_:scale:target:action:)); 22 | extern UIBarButtonItem* LNSystemBarButtonItemAction(NSString* named, LNSystemImageScale scale, UIAction* primaryAction) NS_SWIFT_NAME(LNSystemBarButtonItem(_:scale:primaryAction:)); 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.9 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "LNPopupController", 7 | platforms: [ 8 | .iOS(.v13), 9 | .macCatalyst(.v13) 10 | ], 11 | products: [ 12 | .library( 13 | name: "LNPopupController", 14 | type: .dynamic, 15 | targets: ["LNPopupController", "LNPopupController-ObjC"]), 16 | .library( 17 | name: "LNPopupController-Static", 18 | type: .static, 19 | targets: ["LNPopupController", "LNPopupController-ObjC"]), 20 | ], 21 | dependencies: [], 22 | targets: [ 23 | .target( 24 | name: "LNPopupController-ObjC", 25 | dependencies: [], 26 | path: "LNPopupController", 27 | exclude: ["Info.plist"], 28 | publicHeadersPath: "include", 29 | cSettings: [ 30 | .headerSearchPath("."), 31 | .headerSearchPath("Private") 32 | ]), 33 | .target( 34 | name: "LNPopupController", 35 | dependencies: ["LNPopupController-ObjC"], 36 | path: "LNPCSwiftRefinements") 37 | ], 38 | cxxLanguageStandard: .gnucxx20 39 | ) 40 | -------------------------------------------------------------------------------- /Supplements/Artwork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/Artwork.png -------------------------------------------------------------------------------- /Supplements/Icon-dark.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/Icon-dark.psd -------------------------------------------------------------------------------- /Supplements/Icon.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/Icon.psd -------------------------------------------------------------------------------- /Supplements/close_button_chevron.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/close_button_chevron.png -------------------------------------------------------------------------------- /Supplements/close_button_none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/close_button_none.png -------------------------------------------------------------------------------- /Supplements/close_button_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/close_button_round.png -------------------------------------------------------------------------------- /Supplements/compact_custom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/compact_custom.png -------------------------------------------------------------------------------- /Supplements/custom_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/custom_bar.png -------------------------------------------------------------------------------- /Supplements/default_bar_accessibility_label.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/default_bar_accessibility_label.png -------------------------------------------------------------------------------- /Supplements/floating_bar_style.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/floating_bar_style.gif -------------------------------------------------------------------------------- /Supplements/floating_custom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/floating_custom.png -------------------------------------------------------------------------------- /Supplements/floating_no_scroll.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/floating_no_scroll.gif -------------------------------------------------------------------------------- /Supplements/hidesBottomBar_TabBar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/hidesBottomBar_TabBar.gif -------------------------------------------------------------------------------- /Supplements/hidesBottomBar_Toolbar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/hidesBottomBar_Toolbar.gif -------------------------------------------------------------------------------- /Supplements/interaction_drag.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/interaction_drag.gif -------------------------------------------------------------------------------- /Supplements/interaction_snap.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/interaction_snap.gif -------------------------------------------------------------------------------- /Supplements/modern_custom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/modern_custom.png -------------------------------------------------------------------------------- /Supplements/modern_no_scroll.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/modern_no_scroll.gif -------------------------------------------------------------------------------- /Supplements/open_floating_popup.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/open_floating_popup.gif -------------------------------------------------------------------------------- /Supplements/pointer_interaction.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/pointer_interaction.gif -------------------------------------------------------------------------------- /Supplements/popup_bar_context_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/popup_bar_context_menu.png -------------------------------------------------------------------------------- /Supplements/popup_transitions.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/popup_transitions.gif -------------------------------------------------------------------------------- /Supplements/progress_view_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/progress_view_bottom.png -------------------------------------------------------------------------------- /Supplements/progress_view_none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/progress_view_none.png -------------------------------------------------------------------------------- /Supplements/progress_view_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/progress_view_top.png -------------------------------------------------------------------------------- /Supplements/rtl_english.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/rtl_english.png -------------------------------------------------------------------------------- /Supplements/rtl_hebrew.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/rtl_hebrew.png -------------------------------------------------------------------------------- /Supplements/scroll.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/scroll.gif -------------------------------------------------------------------------------- /Supplements/scroll_edge_appearance.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/scroll_edge_appearance.gif -------------------------------------------------------------------------------- /Supplements/statusbar_hidden.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/statusbar_hidden.gif -------------------------------------------------------------------------------- /Supplements/statusbar_style.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/statusbar_style.gif -------------------------------------------------------------------------------- /Supplements/tab_bar_sidebar_floating.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/tab_bar_sidebar_floating.gif -------------------------------------------------------------------------------- /Supplements/tab_bar_sidebar_landscape_floating.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/tab_bar_sidebar_landscape_floating.png -------------------------------------------------------------------------------- /Supplements/tab_bar_sidebar_prominent.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPopupController/c7ec14fb247c0a5b57fad2c5b2099cbd6c030f91/Supplements/tab_bar_sidebar_prominent.gif -------------------------------------------------------------------------------- /releaseVersion.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if [[ -n $(git status --porcelain) ]]; then 5 | echo -e >&2 "\033[1;31mCannot release version because there are unstaged changes:\033[0m" 6 | git status --short 7 | exit -2 8 | fi 9 | 10 | if [[ -n $(git tag --contains $(git rev-parse --verify HEAD)) ]]; then 11 | echo -e >&2 "\033[1;31mThe latest commit is already contained in the following releases:\033[0m" 12 | git tag --contains $(git rev-parse --verify HEAD) 13 | exit -3 14 | fi 15 | 16 | # if [[ -n $(git log --branches --not --remotes) ]]; then 17 | # echo -e "\033[1;34mPushing pending commits to git\033[0m" 18 | # git push 19 | # fi 20 | 21 | CURRENT_VERSION=$(/usr/libexec/PlistBuddy LNPopupController/Info.plist -c "Print CFBundleShortVersionString") 22 | NEXT_VERSION=$(echo "$CURRENT_VERSION" | perl -pe 's/^((\d+\.)*)(-?\d+)(.*)$/$1.($3+1).$4/e') 23 | 24 | echo -e "\033[1;34mUsing $NEXT_VERSION as release version\033[0m" 25 | 26 | echo -e "\033[1;34mCreating release notes\033[0m" 27 | 28 | RELEASE_NOTES_FILE=_tmp_release_notes.md 29 | 30 | touch "${RELEASE_NOTES_FILE}" 31 | open -Wn "${RELEASE_NOTES_FILE}" 32 | 33 | if ! [ -s "${RELEASE_NOTES_FILE}" ]; then 34 | echo -e >&2 "\033[1;31mNo release notes provided, aborting.\033[0m" 35 | rm -f "${RELEASE_NOTES_FILE}" 36 | exit -1 37 | fi 38 | 39 | echo -e "\033[1;34mUpdating framework version\033[0m" 40 | 41 | /usr/libexec/PlistBuddy LNPopupController/Info.plist -c "Set CFBundleShortVersionString $NEXT_VERSION" -c "Set CFBundleVersion 1" 42 | /usr/libexec/PlistBuddy LNPopupControllerExample/LNPopupControllerExample/Info.plist -c "Set CFBundleShortVersionString $NEXT_VERSION" -c "Set CFBundleVersion 1" 43 | 44 | echo -e "\033[1;34mCommitting all changes to Git for release $NEXT_VERSION\033[0m" 45 | 46 | git add -A 47 | git commit -m "$NEXT_VERSION" 48 | git tag "$NEXT_VERSION" 49 | 50 | git push 51 | git push --tags 52 | 53 | echo -e "\033[1;34mCreating a GitHub release\033[0m" 54 | 55 | gh release create --repo LeoNatan/LNPopupController "$NEXT_VERSION" --title "v$NEXT_VERSION" --notes-file "${RELEASE_NOTES_FILE}" 56 | 57 | rm -f "${RELEASE_NOTES_FILE}" --------------------------------------------------------------------------------