├── .gitignore ├── .swiftpm └── xcode │ └── package.xcworkspace │ └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── LICENSE.md ├── Package.swift ├── PullToRefreshSample ├── PullToRefreshSample.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── swiftpm │ │ │ └── Package.resolved │ └── xcshareddata │ │ └── xcschemes │ │ └── PullToRefreshSample.xcscheme └── PullToRefreshSampleiOS │ ├── PullToRefreshSampleApp.swift │ ├── Resources │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── animation-pulling-shakuro_logo.json │ ├── animation-pulling-shakuro_logo_old.json │ ├── animation-refreshing-shakuro_logo.json │ └── animation-refreshing-shakuro_logo_old.json │ └── UI │ ├── CircleAnimationWithProgressView.swift │ ├── CircleAnimationWithRepeatView.swift │ ├── ContentView.swift │ ├── ContentViewWithSplitView.swift │ ├── ListContentView.swift │ └── ScrollContentView.swift ├── README.md ├── Resources ├── pull_to_refresh_example_1.gif ├── pull_to_refresh_example_2.gif ├── pull_to_refresh_example_main.gif └── title_image.png ├── Shakuro.PullToRefreshSwiftUI.podspec ├── Sources └── PullToRefreshSwiftUI │ ├── GeometryGroupModifier.swift │ ├── PullToRefreshListView.swift │ ├── PullToRefreshListView18IOS.swift │ ├── PullToRefreshListViewOldIOS.swift │ ├── PullToRefreshScrollView.swift │ └── View+readLayoutData.swift └── Tests └── PullToRefreshSwiftUITests └── PullToRefreshSwiftUITests.swift /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | xcuserdata/ 5 | DerivedData/ 6 | .swiftpm/configuration/registries.json 7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 8 | .netrc 9 | -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Shakuro (https://shakuro.com/) 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 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.9 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "PullToRefreshSwiftUI", 8 | platforms: [ 9 | .iOS(.v15) 10 | ], 11 | products: [ 12 | .library( 13 | name: "PullToRefreshSwiftUI", 14 | targets: ["PullToRefreshSwiftUI"]), 15 | ], 16 | dependencies: [ 17 | ], 18 | targets: [ 19 | .target( 20 | name: "PullToRefreshSwiftUI", 21 | dependencies: []), 22 | .testTarget( 23 | name: "PullToRefreshSwiftUITests", 24 | dependencies: ["PullToRefreshSwiftUI"]), 25 | ] 26 | ) 27 | -------------------------------------------------------------------------------- /PullToRefreshSample/PullToRefreshSample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | A51D6A4F2B83DE8000E44E19 /* PullToRefreshSampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51D6A4E2B83DE8000E44E19 /* PullToRefreshSampleApp.swift */; }; 11 | A51D6A612B83E0E800E44E19 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A51D6A5E2B83E0E800E44E19 /* Assets.xcassets */; }; 12 | A51D6A622B83E0E800E44E19 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A51D6A602B83E0E800E44E19 /* Preview Assets.xcassets */; }; 13 | A5288C602BA6B45A0033D0AE /* CircleAnimationWithProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5288C5F2BA6B45A0033D0AE /* CircleAnimationWithProgressView.swift */; }; 14 | A5288C622BA6B4820033D0AE /* CircleAnimationWithRepeatView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5288C612BA6B4820033D0AE /* CircleAnimationWithRepeatView.swift */; }; 15 | A54348322B84672600D1DDB0 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A54348312B84672600D1DDB0 /* ContentView.swift */; }; 16 | A56DF71D2B852C2C00477FBD /* PullToRefreshSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = A56DF71C2B852C2C00477FBD /* PullToRefreshSwiftUI */; }; 17 | A5BA6BAD2B870CEE00DAE39C /* ScrollContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5BA6BAC2B870CEE00DAE39C /* ScrollContentView.swift */; }; 18 | A5BA6BAF2B870D0100DAE39C /* ListContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5BA6BAE2B870D0100DAE39C /* ListContentView.swift */; }; 19 | A5D2E8062B9E31920079FD9B /* Lottie in Frameworks */ = {isa = PBXBuildFile; productRef = A5D2E8052B9E31920079FD9B /* Lottie */; }; 20 | A5DD89652B8867C600EF70A5 /* animation-refreshing-shakuro_logo.json in Resources */ = {isa = PBXBuildFile; fileRef = A5DD89632B8867C600EF70A5 /* animation-refreshing-shakuro_logo.json */; }; 21 | A5DD89662B8867C600EF70A5 /* animation-pulling-shakuro_logo.json in Resources */ = {isa = PBXBuildFile; fileRef = A5DD89642B8867C600EF70A5 /* animation-pulling-shakuro_logo.json */; }; 22 | A5EEB88C2BB0AEB00048B46B /* ContentViewWithSplitView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5EEB88B2BB0AEB00048B46B /* ContentViewWithSplitView.swift */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | A51D6A4B2B83DE8000E44E19 /* PullToRefreshSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PullToRefreshSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | A51D6A4E2B83DE8000E44E19 /* PullToRefreshSampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PullToRefreshSampleApp.swift; sourceTree = ""; }; 28 | A51D6A5C2B83DE9B00E44E19 /* PullToRefreshSwiftUI */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = PullToRefreshSwiftUI; path = ..; sourceTree = ""; }; 29 | A51D6A5E2B83E0E800E44E19 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 30 | A51D6A602B83E0E800E44E19 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 31 | A5288C5F2BA6B45A0033D0AE /* CircleAnimationWithProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleAnimationWithProgressView.swift; sourceTree = ""; }; 32 | A5288C612BA6B4820033D0AE /* CircleAnimationWithRepeatView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleAnimationWithRepeatView.swift; sourceTree = ""; }; 33 | A54348312B84672600D1DDB0 /* ContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 34 | A5BA6BAC2B870CEE00DAE39C /* ScrollContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollContentView.swift; sourceTree = ""; }; 35 | A5BA6BAE2B870D0100DAE39C /* ListContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListContentView.swift; sourceTree = ""; }; 36 | A5DD89632B8867C600EF70A5 /* animation-refreshing-shakuro_logo.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "animation-refreshing-shakuro_logo.json"; sourceTree = ""; }; 37 | A5DD89642B8867C600EF70A5 /* animation-pulling-shakuro_logo.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "animation-pulling-shakuro_logo.json"; sourceTree = ""; }; 38 | A5EEB88B2BB0AEB00048B46B /* ContentViewWithSplitView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentViewWithSplitView.swift; sourceTree = ""; }; 39 | /* End PBXFileReference section */ 40 | 41 | /* Begin PBXFrameworksBuildPhase section */ 42 | A51D6A482B83DE8000E44E19 /* Frameworks */ = { 43 | isa = PBXFrameworksBuildPhase; 44 | buildActionMask = 2147483647; 45 | files = ( 46 | A56DF71D2B852C2C00477FBD /* PullToRefreshSwiftUI in Frameworks */, 47 | A5D2E8062B9E31920079FD9B /* Lottie in Frameworks */, 48 | ); 49 | runOnlyForDeploymentPostprocessing = 0; 50 | }; 51 | /* End PBXFrameworksBuildPhase section */ 52 | 53 | /* Begin PBXGroup section */ 54 | A51D6A422B83DE8000E44E19 = { 55 | isa = PBXGroup; 56 | children = ( 57 | A51D6A5C2B83DE9B00E44E19 /* PullToRefreshSwiftUI */, 58 | A51D6A4D2B83DE8000E44E19 /* PullToRefreshSampleiOS */, 59 | A51D6A4C2B83DE8000E44E19 /* Products */, 60 | A56DF71B2B852C2C00477FBD /* Frameworks */, 61 | ); 62 | sourceTree = ""; 63 | }; 64 | A51D6A4C2B83DE8000E44E19 /* Products */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | A51D6A4B2B83DE8000E44E19 /* PullToRefreshSample.app */, 68 | ); 69 | name = Products; 70 | sourceTree = ""; 71 | }; 72 | A51D6A4D2B83DE8000E44E19 /* PullToRefreshSampleiOS */ = { 73 | isa = PBXGroup; 74 | children = ( 75 | A543482F2B8466B100D1DDB0 /* Application */, 76 | A51D6A5D2B83E0E800E44E19 /* Resources */, 77 | ); 78 | path = PullToRefreshSampleiOS; 79 | sourceTree = ""; 80 | }; 81 | A51D6A5D2B83E0E800E44E19 /* Resources */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | A5DD89642B8867C600EF70A5 /* animation-pulling-shakuro_logo.json */, 85 | A5DD89632B8867C600EF70A5 /* animation-refreshing-shakuro_logo.json */, 86 | A51D6A5E2B83E0E800E44E19 /* Assets.xcassets */, 87 | A51D6A5F2B83E0E800E44E19 /* Preview Content */, 88 | ); 89 | path = Resources; 90 | sourceTree = ""; 91 | }; 92 | A51D6A5F2B83E0E800E44E19 /* Preview Content */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | A51D6A602B83E0E800E44E19 /* Preview Assets.xcassets */, 96 | ); 97 | path = "Preview Content"; 98 | sourceTree = ""; 99 | }; 100 | A543482F2B8466B100D1DDB0 /* Application */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | A51D6A4E2B83DE8000E44E19 /* PullToRefreshSampleApp.swift */, 104 | A54348302B84672600D1DDB0 /* UI */, 105 | ); 106 | name = Application; 107 | sourceTree = ""; 108 | }; 109 | A54348302B84672600D1DDB0 /* UI */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | A54348312B84672600D1DDB0 /* ContentView.swift */, 113 | A5EEB88B2BB0AEB00048B46B /* ContentViewWithSplitView.swift */, 114 | A5BA6BAC2B870CEE00DAE39C /* ScrollContentView.swift */, 115 | A5BA6BAE2B870D0100DAE39C /* ListContentView.swift */, 116 | A5288C5F2BA6B45A0033D0AE /* CircleAnimationWithProgressView.swift */, 117 | A5288C612BA6B4820033D0AE /* CircleAnimationWithRepeatView.swift */, 118 | ); 119 | path = UI; 120 | sourceTree = ""; 121 | }; 122 | A56DF71B2B852C2C00477FBD /* Frameworks */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | ); 126 | name = Frameworks; 127 | sourceTree = ""; 128 | }; 129 | /* End PBXGroup section */ 130 | 131 | /* Begin PBXNativeTarget section */ 132 | A51D6A4A2B83DE8000E44E19 /* PullToRefreshSample */ = { 133 | isa = PBXNativeTarget; 134 | buildConfigurationList = A51D6A592B83DE8200E44E19 /* Build configuration list for PBXNativeTarget "PullToRefreshSample" */; 135 | buildPhases = ( 136 | A51D6A472B83DE8000E44E19 /* Sources */, 137 | A51D6A482B83DE8000E44E19 /* Frameworks */, 138 | A51D6A492B83DE8000E44E19 /* Resources */, 139 | ); 140 | buildRules = ( 141 | ); 142 | dependencies = ( 143 | ); 144 | name = PullToRefreshSample; 145 | packageProductDependencies = ( 146 | A56DF71C2B852C2C00477FBD /* PullToRefreshSwiftUI */, 147 | A5D2E8052B9E31920079FD9B /* Lottie */, 148 | ); 149 | productName = PullToRefreshSample; 150 | productReference = A51D6A4B2B83DE8000E44E19 /* PullToRefreshSample.app */; 151 | productType = "com.apple.product-type.application"; 152 | }; 153 | /* End PBXNativeTarget section */ 154 | 155 | /* Begin PBXProject section */ 156 | A51D6A432B83DE8000E44E19 /* Project object */ = { 157 | isa = PBXProject; 158 | attributes = { 159 | BuildIndependentTargetsInParallel = 1; 160 | LastSwiftUpdateCheck = 1520; 161 | LastUpgradeCheck = 1520; 162 | TargetAttributes = { 163 | A51D6A4A2B83DE8000E44E19 = { 164 | CreatedOnToolsVersion = 15.2; 165 | }; 166 | }; 167 | }; 168 | buildConfigurationList = A51D6A462B83DE8000E44E19 /* Build configuration list for PBXProject "PullToRefreshSample" */; 169 | compatibilityVersion = "Xcode 14.0"; 170 | developmentRegion = en; 171 | hasScannedForEncodings = 0; 172 | knownRegions = ( 173 | en, 174 | Base, 175 | ); 176 | mainGroup = A51D6A422B83DE8000E44E19; 177 | packageReferences = ( 178 | A5D2E8042B9E31920079FD9B /* XCRemoteSwiftPackageReference "lottie-spm" */, 179 | ); 180 | productRefGroup = A51D6A4C2B83DE8000E44E19 /* Products */; 181 | projectDirPath = ""; 182 | projectRoot = ""; 183 | targets = ( 184 | A51D6A4A2B83DE8000E44E19 /* PullToRefreshSample */, 185 | ); 186 | }; 187 | /* End PBXProject section */ 188 | 189 | /* Begin PBXResourcesBuildPhase section */ 190 | A51D6A492B83DE8000E44E19 /* Resources */ = { 191 | isa = PBXResourcesBuildPhase; 192 | buildActionMask = 2147483647; 193 | files = ( 194 | A51D6A622B83E0E800E44E19 /* Preview Assets.xcassets in Resources */, 195 | A5DD89662B8867C600EF70A5 /* animation-pulling-shakuro_logo.json in Resources */, 196 | A5DD89652B8867C600EF70A5 /* animation-refreshing-shakuro_logo.json in Resources */, 197 | A51D6A612B83E0E800E44E19 /* Assets.xcassets in Resources */, 198 | ); 199 | runOnlyForDeploymentPostprocessing = 0; 200 | }; 201 | /* End PBXResourcesBuildPhase section */ 202 | 203 | /* Begin PBXSourcesBuildPhase section */ 204 | A51D6A472B83DE8000E44E19 /* Sources */ = { 205 | isa = PBXSourcesBuildPhase; 206 | buildActionMask = 2147483647; 207 | files = ( 208 | A54348322B84672600D1DDB0 /* ContentView.swift in Sources */, 209 | A5BA6BAD2B870CEE00DAE39C /* ScrollContentView.swift in Sources */, 210 | A5288C622BA6B4820033D0AE /* CircleAnimationWithRepeatView.swift in Sources */, 211 | A5EEB88C2BB0AEB00048B46B /* ContentViewWithSplitView.swift in Sources */, 212 | A5BA6BAF2B870D0100DAE39C /* ListContentView.swift in Sources */, 213 | A51D6A4F2B83DE8000E44E19 /* PullToRefreshSampleApp.swift in Sources */, 214 | A5288C602BA6B45A0033D0AE /* CircleAnimationWithProgressView.swift in Sources */, 215 | ); 216 | runOnlyForDeploymentPostprocessing = 0; 217 | }; 218 | /* End PBXSourcesBuildPhase section */ 219 | 220 | /* Begin XCBuildConfiguration section */ 221 | A51D6A572B83DE8200E44E19 /* Debug */ = { 222 | isa = XCBuildConfiguration; 223 | buildSettings = { 224 | ALWAYS_SEARCH_USER_PATHS = NO; 225 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 226 | CLANG_ANALYZER_NONNULL = YES; 227 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 228 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 229 | CLANG_ENABLE_MODULES = YES; 230 | CLANG_ENABLE_OBJC_ARC = YES; 231 | CLANG_ENABLE_OBJC_WEAK = YES; 232 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 233 | CLANG_WARN_BOOL_CONVERSION = YES; 234 | CLANG_WARN_COMMA = YES; 235 | CLANG_WARN_CONSTANT_CONVERSION = YES; 236 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 237 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 238 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 239 | CLANG_WARN_EMPTY_BODY = YES; 240 | CLANG_WARN_ENUM_CONVERSION = YES; 241 | CLANG_WARN_INFINITE_RECURSION = YES; 242 | CLANG_WARN_INT_CONVERSION = YES; 243 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 244 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 245 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 246 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 247 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 248 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 249 | CLANG_WARN_STRICT_PROTOTYPES = YES; 250 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 251 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 252 | CLANG_WARN_UNREACHABLE_CODE = YES; 253 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 254 | COPY_PHASE_STRIP = NO; 255 | DEBUG_INFORMATION_FORMAT = dwarf; 256 | ENABLE_STRICT_OBJC_MSGSEND = YES; 257 | ENABLE_TESTABILITY = YES; 258 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 259 | GCC_C_LANGUAGE_STANDARD = gnu17; 260 | GCC_DYNAMIC_NO_PIC = NO; 261 | GCC_NO_COMMON_BLOCKS = YES; 262 | GCC_OPTIMIZATION_LEVEL = 0; 263 | GCC_PREPROCESSOR_DEFINITIONS = ( 264 | "DEBUG=1", 265 | "$(inherited)", 266 | ); 267 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 268 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 269 | GCC_WARN_UNDECLARED_SELECTOR = YES; 270 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 271 | GCC_WARN_UNUSED_FUNCTION = YES; 272 | GCC_WARN_UNUSED_VARIABLE = YES; 273 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 274 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 275 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 276 | MTL_FAST_MATH = YES; 277 | ONLY_ACTIVE_ARCH = YES; 278 | SDKROOT = iphoneos; 279 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; 280 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 281 | }; 282 | name = Debug; 283 | }; 284 | A51D6A582B83DE8200E44E19 /* Release */ = { 285 | isa = XCBuildConfiguration; 286 | buildSettings = { 287 | ALWAYS_SEARCH_USER_PATHS = NO; 288 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 289 | CLANG_ANALYZER_NONNULL = YES; 290 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 291 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 292 | CLANG_ENABLE_MODULES = YES; 293 | CLANG_ENABLE_OBJC_ARC = YES; 294 | CLANG_ENABLE_OBJC_WEAK = YES; 295 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 296 | CLANG_WARN_BOOL_CONVERSION = YES; 297 | CLANG_WARN_COMMA = YES; 298 | CLANG_WARN_CONSTANT_CONVERSION = YES; 299 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 300 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 301 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 302 | CLANG_WARN_EMPTY_BODY = YES; 303 | CLANG_WARN_ENUM_CONVERSION = YES; 304 | CLANG_WARN_INFINITE_RECURSION = YES; 305 | CLANG_WARN_INT_CONVERSION = YES; 306 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 307 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 308 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 309 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 310 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 311 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 312 | CLANG_WARN_STRICT_PROTOTYPES = YES; 313 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 314 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 315 | CLANG_WARN_UNREACHABLE_CODE = YES; 316 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 317 | COPY_PHASE_STRIP = NO; 318 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 319 | ENABLE_NS_ASSERTIONS = NO; 320 | ENABLE_STRICT_OBJC_MSGSEND = YES; 321 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 322 | GCC_C_LANGUAGE_STANDARD = gnu17; 323 | GCC_NO_COMMON_BLOCKS = YES; 324 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 325 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 326 | GCC_WARN_UNDECLARED_SELECTOR = YES; 327 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 328 | GCC_WARN_UNUSED_FUNCTION = YES; 329 | GCC_WARN_UNUSED_VARIABLE = YES; 330 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 331 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 332 | MTL_ENABLE_DEBUG_INFO = NO; 333 | MTL_FAST_MATH = YES; 334 | SDKROOT = iphoneos; 335 | SWIFT_COMPILATION_MODE = wholemodule; 336 | VALIDATE_PRODUCT = YES; 337 | }; 338 | name = Release; 339 | }; 340 | A51D6A5A2B83DE8200E44E19 /* Debug */ = { 341 | isa = XCBuildConfiguration; 342 | buildSettings = { 343 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 344 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 345 | CODE_SIGN_STYLE = Automatic; 346 | CURRENT_PROJECT_VERSION = 1; 347 | DEVELOPMENT_ASSET_PATHS = "PullToRefreshSampleiOS/Resources/Preview\\ Content"; 348 | DEVELOPMENT_TEAM = MW2UF479VW; 349 | ENABLE_PREVIEWS = YES; 350 | GENERATE_INFOPLIST_FILE = YES; 351 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 352 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 353 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 354 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 355 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 356 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 357 | LD_RUNPATH_SEARCH_PATHS = ( 358 | "$(inherited)", 359 | "@executable_path/Frameworks", 360 | ); 361 | MARKETING_VERSION = 1.0; 362 | PRODUCT_BUNDLE_IDENTIFIER = Shakuro.PullToRefreshSample; 363 | PRODUCT_NAME = "$(TARGET_NAME)"; 364 | SWIFT_EMIT_LOC_STRINGS = YES; 365 | SWIFT_VERSION = 5.0; 366 | TARGETED_DEVICE_FAMILY = "1,2"; 367 | }; 368 | name = Debug; 369 | }; 370 | A51D6A5B2B83DE8200E44E19 /* Release */ = { 371 | isa = XCBuildConfiguration; 372 | buildSettings = { 373 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 374 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 375 | CODE_SIGN_STYLE = Automatic; 376 | CURRENT_PROJECT_VERSION = 1; 377 | DEVELOPMENT_ASSET_PATHS = "PullToRefreshSampleiOS/Resources/Preview\\ Content"; 378 | DEVELOPMENT_TEAM = MW2UF479VW; 379 | ENABLE_PREVIEWS = YES; 380 | GENERATE_INFOPLIST_FILE = YES; 381 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 382 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 383 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 384 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 385 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 386 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 387 | LD_RUNPATH_SEARCH_PATHS = ( 388 | "$(inherited)", 389 | "@executable_path/Frameworks", 390 | ); 391 | MARKETING_VERSION = 1.0; 392 | PRODUCT_BUNDLE_IDENTIFIER = Shakuro.PullToRefreshSample; 393 | PRODUCT_NAME = "$(TARGET_NAME)"; 394 | SWIFT_EMIT_LOC_STRINGS = YES; 395 | SWIFT_VERSION = 5.0; 396 | TARGETED_DEVICE_FAMILY = "1,2"; 397 | }; 398 | name = Release; 399 | }; 400 | /* End XCBuildConfiguration section */ 401 | 402 | /* Begin XCConfigurationList section */ 403 | A51D6A462B83DE8000E44E19 /* Build configuration list for PBXProject "PullToRefreshSample" */ = { 404 | isa = XCConfigurationList; 405 | buildConfigurations = ( 406 | A51D6A572B83DE8200E44E19 /* Debug */, 407 | A51D6A582B83DE8200E44E19 /* Release */, 408 | ); 409 | defaultConfigurationIsVisible = 0; 410 | defaultConfigurationName = Release; 411 | }; 412 | A51D6A592B83DE8200E44E19 /* Build configuration list for PBXNativeTarget "PullToRefreshSample" */ = { 413 | isa = XCConfigurationList; 414 | buildConfigurations = ( 415 | A51D6A5A2B83DE8200E44E19 /* Debug */, 416 | A51D6A5B2B83DE8200E44E19 /* Release */, 417 | ); 418 | defaultConfigurationIsVisible = 0; 419 | defaultConfigurationName = Release; 420 | }; 421 | /* End XCConfigurationList section */ 422 | 423 | /* Begin XCRemoteSwiftPackageReference section */ 424 | A5D2E8042B9E31920079FD9B /* XCRemoteSwiftPackageReference "lottie-spm" */ = { 425 | isa = XCRemoteSwiftPackageReference; 426 | repositoryURL = "https://github.com/airbnb/lottie-spm.git"; 427 | requirement = { 428 | kind = upToNextMajorVersion; 429 | minimumVersion = 4.4.1; 430 | }; 431 | }; 432 | /* End XCRemoteSwiftPackageReference section */ 433 | 434 | /* Begin XCSwiftPackageProductDependency section */ 435 | A56DF71C2B852C2C00477FBD /* PullToRefreshSwiftUI */ = { 436 | isa = XCSwiftPackageProductDependency; 437 | productName = PullToRefreshSwiftUI; 438 | }; 439 | A5D2E8052B9E31920079FD9B /* Lottie */ = { 440 | isa = XCSwiftPackageProductDependency; 441 | package = A5D2E8042B9E31920079FD9B /* XCRemoteSwiftPackageReference "lottie-spm" */; 442 | productName = Lottie; 443 | }; 444 | /* End XCSwiftPackageProductDependency section */ 445 | }; 446 | rootObject = A51D6A432B83DE8000E44E19 /* Project object */; 447 | } 448 | -------------------------------------------------------------------------------- /PullToRefreshSample/PullToRefreshSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PullToRefreshSample/PullToRefreshSample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /PullToRefreshSample/PullToRefreshSample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "pins" : [ 3 | { 4 | "identity" : "lottie-spm", 5 | "kind" : "remoteSourceControl", 6 | "location" : "https://github.com/airbnb/lottie-spm.git", 7 | "state" : { 8 | "revision" : "3bd43e12d6fb54654366a61f7cfaca787318b8ce", 9 | "version" : "4.4.1" 10 | } 11 | } 12 | ], 13 | "version" : 2 14 | } 15 | -------------------------------------------------------------------------------- /PullToRefreshSample/PullToRefreshSample.xcodeproj/xcshareddata/xcschemes/PullToRefreshSample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 | 16 | 22 | 23 | 24 | 25 | 26 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /PullToRefreshSample/PullToRefreshSampleiOS/PullToRefreshSampleApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Copyright (c) 2024 Shakuro (https://shakuro.com/) 4 | // 5 | // 6 | 7 | import SwiftUI 8 | 9 | @main 10 | struct PullToRefreshSampleApp: App { 11 | 12 | var body: some Scene { 13 | WindowGroup { 14 | if #available(iOS 17.0, *) { 15 | ContentViewWithSplitView() 16 | } else { 17 | ContentView() 18 | } 19 | } 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /PullToRefreshSample/PullToRefreshSampleiOS/Resources/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PullToRefreshSample/PullToRefreshSampleiOS/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /PullToRefreshSample/PullToRefreshSampleiOS/Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PullToRefreshSample/PullToRefreshSampleiOS/Resources/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PullToRefreshSample/PullToRefreshSampleiOS/Resources/animation-pulling-shakuro_logo.json: -------------------------------------------------------------------------------- 1 | {"v":"5.12.1","fr":60,"ip":0,"op":121,"w":2052,"h":570,"nm":"pulldown_pulling","ddd":0,"assets":[{"id":"comp_0","nm":"Logo Light 2","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 8","parent":9,"sr":1,"ks":{"o":{"a":0,"k":50,"ix":11},"r":{"a":0,"k":-2.114,"ix":10},"p":{"a":0,"k":[0.656,-0.024,0],"ix":2,"l":2},"a":{"a":0,"k":[1,0,0],"ix":1,"l":2},"s":{"a":0,"k":[73.465,73.465,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[416.602,416.602],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":0,"k":3,"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.498,0.475,0.475,0.547,0.996,0.333,0.333,0.416],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[1,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":30,"s":[100]},{"t":105,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":41,"s":[100]},{"t":117,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":103,"op":172,"st":15,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 7","parent":9,"sr":1,"ks":{"o":{"a":0,"k":50,"ix":11},"r":{"a":0,"k":-2.114,"ix":10},"p":{"a":0,"k":[0.656,-0.024,0],"ix":2,"l":2},"a":{"a":0,"k":[1,0,0],"ix":1,"l":2},"s":{"a":0,"k":[69.526,69.526,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[416.602,416.602],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":0,"k":3,"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.498,0.475,0.475,0.547,0.996,0.333,0.333,0.416],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[1,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":24,"s":[100]},{"t":99,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":35,"s":[100]},{"t":111,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":103,"op":172,"st":9,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 6","parent":9,"sr":1,"ks":{"o":{"a":0,"k":50,"ix":11},"r":{"a":0,"k":-2.114,"ix":10},"p":{"a":0,"k":[0.656,-0.024,0],"ix":2,"l":2},"a":{"a":0,"k":[1,0,0],"ix":1,"l":2},"s":{"a":0,"k":[65.653,65.653,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[416.602,416.602],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":0,"k":3,"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.498,0.475,0.475,0.547,0.996,0.333,0.333,0.416],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[1,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":15,"s":[100]},{"t":90,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":26,"s":[100]},{"t":102,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":103,"op":172,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Shape Layer 5","sr":1,"ks":{"o":{"a":0,"k":50,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[541,264,0],"ix":2,"l":2},"a":{"a":0,"k":[1,0,0],"ix":1,"l":2},"s":{"a":0,"k":[111.9,111.9,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[416.602,416.602],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":0,"k":3,"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.498,0.475,0.475,0.547,0.996,0.333,0.333,0.416],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[1,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":30,"s":[100]},{"t":105,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":41,"s":[100]},{"t":117,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":103,"st":15,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Shape Layer 4","sr":1,"ks":{"o":{"a":0,"k":50,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[541,264,0],"ix":2,"l":2},"a":{"a":0,"k":[1,0,0],"ix":1,"l":2},"s":{"a":0,"k":[105.9,105.9,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[416.602,416.602],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":0,"k":3,"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.498,0.475,0.475,0.547,0.996,0.333,0.333,0.416],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[1,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":24,"s":[100]},{"t":99,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":35,"s":[100]},{"t":111,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":103,"st":9,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Shape Layer 3","sr":1,"ks":{"o":{"a":0,"k":50,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[541,264,0],"ix":2,"l":2},"a":{"a":0,"k":[1,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[416.602,416.602],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":0,"k":3,"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.498,0.475,0.475,0.547,0.996,0.333,0.333,0.416],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[1,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":15,"s":[100]},{"t":90,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":26,"s":[100]},{"t":102,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":103,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Shape Layer 2","parent":11,"sr":1,"ks":{"o":{"a":0,"k":50,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[189.081,90.25,0],"ix":2,"l":2},"a":{"a":0,"k":[83.183,46.25,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-4.25,-45]],"o":[[0,0],[1.38,14.609]],"v":[[-18.5,-131.75],[-115,-25.75]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":0,"k":3,"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.498,0.475,0.475,0.547,0.996,0.333,0.333,0.416],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 2","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[49.75,105.5]],"o":[[0,0],[-24.918,-52.841]],"v":[[56.25,98.75],[96.5,-46]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":0,"k":3,"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.498,0.475,0.475,0.547,0.996,0.333,0.333,0.416],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.29],"y":[1]},"o":{"x":[0.71],"y":[0]},"t":62,"s":[0]},{"t":96,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.29],"y":[1]},"o":{"x":[0.71],"y":[0]},"t":50,"s":[0]},{"t":86,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":172,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Shape Layer 1","parent":7,"sr":1,"ks":{"o":{"a":0,"k":50,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[36.738,-102.385],[0,0]],"o":[[0,0],[-30.5,85],[0,0]],"v":[[-121,-58.5],[78,29],[-124.5,136.5]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.8],"y":[0]},"t":89,"s":[3]},{"t":108,"s":[0]}],"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.498,0.475,0.475,0.547,0.996,0.333,0.333,0.416],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 2","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-55,-73],[0,0]],"o":[[0,0],[55,73],[0,0]],"v":[[55.5,-131.5],[-76.5,22.5],[152,24]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.8],"y":[0]},"t":89,"s":[3]},{"t":108,"s":[0]}],"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.498,0.475,0.475,0.547,0.996,0.333,0.333,0.416],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.29],"y":[1]},"o":{"x":[0.71],"y":[0]},"t":21,"s":[0]},{"t":127,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.29],"y":[1]},"o":{"x":[0.71],"y":[0]},"t":11,"s":[0]},{"t":117,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":172,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":3,"nm":"Scale","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":32,"s":[270]},{"t":112,"s":[0]}],"ix":10},"p":{"a":0,"k":[540,264,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.79,0.79,0.79],"y":[0,0,0]},"t":10,"s":[126,126,100]},{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.8],"y":[0,0,0]},"t":69,"s":[155.941,155.941,100]},{"t":112,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":302,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Logo 1 Outlines","parent":9,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":94,"s":[100]},{"t":129,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[49.6,-14,0],"ix":2,"l":2},"a":{"a":0,"k":[52,61,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,11.1],[35,9.6],[0,0],[0,0],[0,0],[0,0],[6.2,-22.5],[0.6,-1.6]],"o":[[0,-36.3],[0,0],[0,0],[0,0],[0,0],[22.5,6.2],[-0.5,1.7],[4.2,-10]],"v":[[50.85,28.9],[-8.45,-48.9],[-52.25,-60.9],[-52.25,-15],[-20.05,-6.1],[16.55,4],[46.05,55.9],[43.475,60.775]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[52.25,61.3],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[22.5,6.2],[0,0],[25.87,-27.816],[0,0],[0,0],[0,0],[-5,11.7],[-0.5,1.7]],"o":[[0,0],[28.4,7.9],[0,0],[0,0],[0,0],[10.1,-8.3],[0.7,-1.6],[4.5,-20.4]],"v":[[17.2,-65.7],[-19.425,-76.05],[-6.65,-15.75],[-52.25,21.75],[-52.25,79.05],[21.45,18.55],[44.35,-11.95],[46.15,-16.95]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[52.25,131.35],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.29],"y":[1]},"o":{"x":[0.71],"y":[0]},"t":29,"s":[0]},{"t":103,"s":[100]}],"ix":2},"o":{"a":0,"k":125,"ix":3},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":85,"s":[3]},{"t":141,"s":[0]}],"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.5,0.473,0.473,0.545,1,0.329,0.329,0.412],"ix":8}},"s":{"a":0,"k":[0,-66],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false}],"ip":0,"op":123,"st":-52,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Logo 2 Outlines","parent":9,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":94,"s":[100]},{"t":129,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-52.9,17,0],"ix":2,"l":2},"a":{"a":0,"k":[52,61,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-6.2,22.5],[-0.7,1.7],[0,-11.1],[-35,-9.6],[0,0],[0,0],[0,0]],"o":[[-22.5,-6.2],[0.5,-1.7],[-4.3,10],[0,36.3],[0,0],[0,0],[0,0],[0,0]],"v":[[-16.5,-3.95],[-46,-55.85],[-44.3,-60.85],[-50.9,-28.95],[8.4,48.85],[52.2,60.85],[52.2,14.95],[20,6.05]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[50.9,60.85],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-22.5,-6.2],[0,0],[-22.8,18.8],[0,0],[0,0],[0,0],[5,-11.7],[0.4,-1.8]],"o":[[0,0],[-25.108,-6.8],[0,0],[0,0],[0,0],[-10.1,8.3],[-0.7,1.7],[-4.033,17.45]],"v":[[-17.075,64.725],[17.975,74.425],[6.7,15.75],[52.3,-21.75],[52.3,-79.05],[-21.4,-18.55],[-44.3,11.95],[-46.1,17.05]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[50.158,-8.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":85,"s":[3]},{"t":141,"s":[0]}],"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.5,0.473,0.473,0.545,1,0.329,0.329,0.412],"ix":8}},"s":{"a":0,"k":[80,-2],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.29],"y":[1]},"o":{"x":[0.71],"y":[0]},"t":29,"s":[0]},{"t":103,"s":[100]}],"ix":2},"o":{"a":0,"k":125,"ix":3},"m":1,"ix":4,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":123,"st":-53,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Shape Layer 10","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.21,"y":1},"o":{"x":0.79,"y":0},"t":75,"s":[374.001,-234.909,0],"to":[-47.967,35.386,0],"ti":[47.967,-35.386,0]},{"t":136,"s":[86.2,-22.596,0]}],"ix":2,"l":2},"a":{"a":0,"k":[82.594,-102.985,0],"ix":1,"l":2},"s":{"a":0,"k":[94.766,94.766,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[297.188,298.029],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.074509803922,0.074509803922,0.137254901961,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.5,0.5,0.5,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[34.502,-14.813],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[151.791,151.791],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":302,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Logo 1 Outlines","parent":9,"tt":1,"tp":12,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[49.6,-14,0],"ix":2,"l":2},"a":{"a":0,"k":[52,61,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,11.1],[35,9.6],[0,0],[0,0],[0,0],[0,0],[6.2,-22.5],[0.6,-1.6]],"o":[[0,-36.3],[0,0],[0,0],[0,0],[0,0],[22.5,6.2],[-0.5,1.7],[4.2,-10]],"v":[[50.85,28.9],[-8.45,-48.9],[-52.25,-60.9],[-52.25,-15],[-20.05,-6.1],[16.55,4],[46.05,55.9],[44.35,60.9]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.61568627451,0.61568627451,0.678431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[52.25,60.9],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":302,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Shape Layer 11","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.21,"y":1},"o":{"x":0.79,"y":0},"t":75,"s":[374.001,-234.909,0],"to":[-47.967,35.386,0],"ti":[47.967,-35.386,0]},{"t":136,"s":[86.2,-22.596,0]}],"ix":2,"l":2},"a":{"a":0,"k":[82.594,-102.985,0],"ix":1,"l":2},"s":{"a":0,"k":[94.766,94.766,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[297.188,298.029],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.074509803922,0.074509803922,0.137254901961,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.5,0.5,0.5,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[34.502,-14.813],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[151.791,151.791],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":302,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Logo 2 Outlines","parent":9,"tt":1,"tp":14,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-52.9,17,0],"ix":2,"l":2},"a":{"a":0,"k":[52,61,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-6.2,22.5],[-0.7,1.7],[0,-11.1],[-35,-9.6],[0,0],[0,0],[0,0]],"o":[[-22.5,-6.2],[0.5,-1.7],[-4.3,10],[0,36.3],[0,0],[0,0],[0,0],[0,0]],"v":[[-16.5,-3.95],[-46,-55.85],[-44.3,-60.85],[-50.9,-28.95],[8.4,48.85],[52.2,60.85],[52.2,14.95],[20,6.05]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.61568627451,0.61568627451,0.678431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[50.9,60.85],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":302,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":"Shape Layer 12","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.21,"y":1},"o":{"x":0.79,"y":0},"t":75,"s":[374.001,-234.909,0],"to":[-47.967,35.386,0],"ti":[47.967,-35.386,0]},{"t":136,"s":[86.2,-22.596,0]}],"ix":2,"l":2},"a":{"a":0,"k":[82.594,-102.985,0],"ix":1,"l":2},"s":{"a":0,"k":[94.766,94.766,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[297.188,298.029],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.074509803922,0.074509803922,0.137254901961,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.5,0.5,0.5,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[34.502,-14.813],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[151.791,151.791],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":302,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":"Logo 3 Outlines","parent":15,"tt":1,"tp":16,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[53,-9.5,0],"ix":2,"l":2},"a":{"a":0,"k":[50.5,79.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-22.183,-6.65],[0,0],[-22.8,18.8],[0,0],[0,0],[0,0],[5,-11.7],[0.4,-1.8]],"o":[[0,0],[-28.4,-7.9],[0,0],[0,0],[0,0],[-10.1,8.3],[-0.7,1.7],[-4.658,17.4]],"v":[[-17.825,66.725],[18.6,76.3],[6.7,15.75],[52.3,-21.75],[52.3,-79.05],[-21.4,-18.55],[-44.3,11.95],[-46.1,17.05]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,0.329,0.329,0.412,0.5,0.473,0.473,0.545,1,0.616,0.616,0.678],"ix":9}},"s":{"a":0,"k":[-12.836,68.551],"ix":5},"e":{"a":0,"k":[0.939,-59.545],"ix":6},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[47.758,79.05],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":302,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":"Shape Layer 13","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.21,"y":1},"o":{"x":0.79,"y":0},"t":75,"s":[374.001,-234.909,0],"to":[-47.967,35.386,0],"ti":[47.967,-35.386,0]},{"t":136,"s":[86.2,-22.596,0]}],"ix":2,"l":2},"a":{"a":0,"k":[82.594,-102.985,0],"ix":1,"l":2},"s":{"a":0,"k":[94.766,94.766,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[297.188,298.029],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.074509803922,0.074509803922,0.137254901961,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.5,0.5,0.5,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[34.502,-14.813],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[151.791,151.791],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":302,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":"Logo Outlines","parent":13,"tt":1,"tp":18,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50.5,131,0],"ix":2,"l":2},"a":{"a":0,"k":[50,79.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[19.3,7.275],[0,0],[22.8,-18.8],[0,0],[0,0],[0,0],[-5,11.7],[-0.5,1.7]],"o":[[0,0],[28.4,7.9],[0,0],[0,0],[0,0],[10.1,-8.3],[0.7,-1.6],[6.1,-22.6]],"v":[[17.45,-65.7],[-15.55,-74.3],[-6.65,-15.75],[-52.25,21.75],[-52.25,79.05],[21.45,18.55],[44.35,-11.95],[46.15,-16.95]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,0.329,0.329,0.412,0.5,0.473,0.473,0.545,1,0.616,0.616,0.678],"ix":9}},"s":{"a":0,"k":[23.859,-65.238],"ix":5},"e":{"a":0,"k":[-23.006,43.869],"ix":6},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[52.25,79.05],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":302,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":"Shape Layer 17","parent":21,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.8,"y":0},"t":66,"s":[374.001,-234.909,0],"to":[-47.967,35.386,0],"ti":[47.967,-35.386,0]},{"t":127,"s":[86.2,-22.596,0]}],"ix":2,"l":2},"a":{"a":0,"k":[82.594,-102.985,0],"ix":1,"l":2},"s":{"a":0,"k":[94.766,94.766,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[297.188,298.029],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.074509803922,0.074509803922,0.137254901961,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.5,0.5,0.5,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[34.502,-14.813],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[151.791,151.791],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":194,"st":-9,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":"Logo 1 Outlines 2","parent":9,"tt":1,"tp":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[49.6,-14,0],"ix":2,"l":2},"a":{"a":0,"k":[52,61,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,11.1],[35,9.6],[0,0],[0,0],[0,0],[0,0],[6.2,-22.5],[0.6,-1.6]],"o":[[0,-36.3],[0,0],[0,0],[0,0],[0,0],[22.5,6.2],[-0.5,1.7],[4.2,-10]],"v":[[50.85,28.9],[-8.45,-48.9],[-52.25,-60.9],[-52.25,-15],[-20.05,-6.1],[16.55,4],[46.05,55.9],[44.35,60.9]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.364705882353,0.364705882353,0.443137284821,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[52.25,60.9],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":194,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":"Shape Layer 16","parent":21,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.8,"y":0},"t":66,"s":[374.001,-234.909,0],"to":[-47.967,35.386,0],"ti":[47.967,-35.386,0]},{"t":127,"s":[86.2,-22.596,0]}],"ix":2,"l":2},"a":{"a":0,"k":[82.594,-102.985,0],"ix":1,"l":2},"s":{"a":0,"k":[94.766,94.766,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[297.188,298.029],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.074509803922,0.074509803922,0.137254901961,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.5,0.5,0.5,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[34.502,-14.813],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[151.791,151.791],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":194,"st":-9,"ct":1,"bm":0},{"ddd":0,"ind":23,"ty":4,"nm":"Logo 2 Outlines 2","parent":9,"tt":1,"tp":22,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-52.9,17,0],"ix":2,"l":2},"a":{"a":0,"k":[52,61,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-6.2,22.5],[-0.7,1.7],[0,-11.1],[-35,-9.6],[0,0],[0,0],[0,0]],"o":[[-22.5,-6.2],[0.5,-1.7],[-4.3,10],[0,36.3],[0,0],[0,0],[0,0],[0,0]],"v":[[-16.5,-3.95],[-46,-55.85],[-44.3,-60.85],[-50.9,-28.95],[8.4,48.85],[52.2,60.85],[52.2,14.95],[20,6.05]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.364705882353,0.364705882353,0.443137284821,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[50.9,60.85],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":194,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":24,"ty":4,"nm":"Shape Layer 15","parent":21,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.8,"y":0},"t":66,"s":[374.001,-234.909,0],"to":[-47.967,35.386,0],"ti":[47.967,-35.386,0]},{"t":127,"s":[86.2,-22.596,0]}],"ix":2,"l":2},"a":{"a":0,"k":[82.594,-102.985,0],"ix":1,"l":2},"s":{"a":0,"k":[94.766,94.766,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[297.188,298.029],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.074509803922,0.074509803922,0.137254901961,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.5,0.5,0.5,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[34.502,-14.813],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[151.791,151.791],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":194,"st":-9,"ct":1,"bm":0},{"ddd":0,"ind":25,"ty":4,"nm":"Logo 3 Outlines 2","parent":23,"tt":1,"tp":24,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[53,-9.5,0],"ix":2,"l":2},"a":{"a":0,"k":[50.5,79.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-22.183,-6.65],[0,0],[-22.8,18.8],[0,0],[0,0],[0,0],[5,-11.7],[0.4,-1.8]],"o":[[0,0],[-28.4,-7.9],[0,0],[0,0],[0,0],[-10.1,8.3],[-0.7,1.7],[-4.658,17.4]],"v":[[-17.825,66.725],[18.6,76.3],[6.7,15.75],[52.3,-21.75],[52.3,-79.05],[-21.4,-18.55],[-44.3,11.95],[-46.1,17.05]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.364705882353,0.364705882353,0.443137284821,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[47.758,79.05],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":194,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":26,"ty":4,"nm":"Shape Layer 14","parent":21,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.8,"y":0},"t":66,"s":[374.001,-234.909,0],"to":[-47.967,35.386,0],"ti":[47.967,-35.386,0]},{"t":127,"s":[86.2,-22.596,0]}],"ix":2,"l":2},"a":{"a":0,"k":[82.594,-102.985,0],"ix":1,"l":2},"s":{"a":0,"k":[94.766,94.766,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[297.188,298.029],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.074509803922,0.074509803922,0.137254901961,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.5,0.5,0.5,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[34.502,-14.813],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[151.791,151.791],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":194,"st":-9,"ct":1,"bm":0},{"ddd":0,"ind":27,"ty":4,"nm":"Logo Outlines 2","parent":21,"tt":1,"tp":26,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50.5,131,0],"ix":2,"l":2},"a":{"a":0,"k":[50,79.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[19.3,7.275],[0,0],[22.8,-18.8],[0,0],[0,0],[0,0],[-5,11.7],[-0.5,1.7]],"o":[[0,0],[28.4,7.9],[0,0],[0,0],[0,0],[10.1,-8.3],[0.7,-1.6],[6.1,-22.6]],"v":[[17.45,-65.7],[-15.55,-74.3],[-6.65,-15.75],[-52.25,21.75],[-52.25,79.05],[21.45,18.55],[44.35,-11.95],[46.15,-16.95]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.364705882353,0.364705882353,0.443137284821,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[52.25,79.05],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":194,"st":0,"ct":1,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Logo Light 2","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":120,"s":[0]},{"t":184,"s":[-360]}],"ix":10,"x":"var $bm_rt;\n$bm_rt = loopOut();"},"p":{"a":0,"k":[1026,268,0],"ix":2,"l":2,"x":"var $bm_rt;\n$bm_rt = transform.position;"},"a":{"a":0,"k":[540,264,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"tm":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":297,"s":[4.95]}],"ix":2},"w":1080,"h":562,"ip":0,"op":121,"st":0,"bm":0}],"markers":[],"props":{}} -------------------------------------------------------------------------------- /PullToRefreshSample/PullToRefreshSampleiOS/Resources/animation-pulling-shakuro_logo_old.json: -------------------------------------------------------------------------------- 1 | {"v":"5.1.1","fr":60,"ip":0,"op":70,"w":464,"h":130,"nm":"Slicing Part 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 17","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[232,65.25,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[70,70,100],"ix":6}},"ao":0,"ip":0,"op":70,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Yellow Outlines","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.5],"y":[0]},"n":["0p5_1_0p5_0"],"t":20,"s":[0],"e":[720]},{"t":70}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.5,"y":1},"o":{"x":0.5,"y":0},"n":"0p5_1_0p5_0","t":20,"s":[-310,-60,0],"e":[-25.714,-7.786,0],"to":[20.9523811340332,50.476188659668,0],"ti":[-78.0952377319336,40.9523811340332,0]},{"t":70}],"ix":2},"a":{"a":0,"k":[20.5,33,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,4.72],[-2.52,4],[0,0],[1.28,-1.18],[3.82,-3.56],[1.822,-1.901],[-0.111,-2.921],[-4.04,-3.76],[-5.7,-5.04],[-2.973,0.456],[-0.944,2.856],[2.115,2.138],[3.02,4.18],[0.6,1.18],[1.22,1.7]],"o":[[0,-4.74],[0,0],[-1.28,1.2],[-3.82,3.56],[-2.015,1.696],[-1.898,2.223],[0.2,6],[5.58,5.18],[1.757,2.441],[2.973,-0.456],[0.944,-2.855],[-2.72,-4.38],[-0.78,-1.24],[-1.4,-2],[-2.6,-4.02]],"v":[[-288.345,347.56],[-282.725,335.78],[-282.185,335.02],[-286.005,338.62],[-297.405,349.36],[-303.165,354.76],[-305.945,362.76],[-296.505,376.1],[-279.845,391.78],[-272.138,395.014],[-265.756,389.617],[-267.665,381.48],[-276.385,368.54],[-278.645,365.04],[-282.645,359.34]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.901960784314,0.035294117647,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[305.945,-330],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.12,0.18],[3.02,4.18],[0,2.5],[-1.34,2.12],[-2.72,4.4],[1.134,2.805],[2.657,0.444],[1.945,-2.361],[1.9,-1.78],[3.82,-3.56],[1.822,-1.901],[-0.111,-2.921],[-4.04,-3.76],[-5.7,-5.04],[-2.973,0.456],[-0.944,2.856],[2.115,2.138]],"o":[[-2.72,-4.38],[-1.34,-2.12],[0,-2.5],[3.02,-4.18],[1.899,-2.355],[-1.088,-2.464],[-3.033,-0.395],[-2,1.72],[-3.7,3.56],[-2.015,1.696],[-1.898,2.223],[0.2,6],[5.58,5.18],[1.757,2.441],[2.973,-0.456],[0.944,-2.855],[-0.1,-0.2]],"v":[[-267.665,381.46],[-276.385,368.52],[-279.365,362.3],[-276.385,356.06],[-267.665,343.12],[-266.425,334.76],[-272.425,330.1],[-280.425,333.26],[-286.125,338.62],[-297.405,349.36],[-303.165,354.76],[-305.945,362.76],[-296.505,376.1],[-279.845,391.78],[-272.138,395.014],[-265.756,389.617],[-267.665,381.48]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.866666666667,0.752941176471,0.047058823529,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[305.945,-330],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":70,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Green Outlines","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.5],"y":[0]},"n":["0p5_1_0p5_0"],"t":20,"s":[0],"e":[720]},{"t":70}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.5,"y":1},"o":{"x":0.5,"y":0},"n":"0p5_1_0p5_0","t":20,"s":[311.458,-48.214,0],"e":[27,12.607,0],"to":[-19.1590003967285,77.3095169067383,0],"ti":[67.5363998413086,40.0297584533691,0]},{"t":70}],"ix":2},"a":{"a":0,"k":[20.5,32.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-4.72],[2.52,-4],[0.18,-0.26],[0,0],[-3.82,3.56],[-1.82,1.896],[0.125,2.923],[4.04,3.76],[5.72,5.04],[3.38,-2.85],[-2.85,-3.38],[-3.02,-4.18],[-0.6,-1.18],[0,0]],"o":[[0,4.74],[-0.18,0.24],[0,0],[3.82,-3.56],[2.004,-1.701],[1.911,-2.216],[-0.2,-6],[-5.58,-5.18],[-2.85,-3.38],[-3.38,2.85],[2.72,4.38],[0.8,1.24],[0,0],[2.64,4]],"v":[[-282.835,378.52],[-288.455,390.3],[-288.975,391.06],[-285.175,387.46],[-273.755,376.72],[-268.015,371.32],[-265.235,363.32],[-274.675,349.98],[-291.335,334.3],[-302.615,333.34],[-303.575,344.62],[-294.855,357.56],[-292.575,361.06],[-288.575,366.76]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.619607843137,0.76862745098,0.247058823529,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[305.575,-331],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-0.16],[-3.02,-4.18],[0,-2.5],[1.34,-2],[2.72,-4.4],[-1.134,-2.805],[-2.657,-0.444],[-1.942,2.364],[-1.9,1.78],[-3.82,3.56],[-1.82,1.896],[0.125,2.923],[4.04,3.76],[5.72,5.04],[3.413,-2.855],[-2.855,-3.413]],"o":[[2.72,4.38],[1.34,2.12],[0,2.5],[-3.02,4.18],[-1.899,2.355],[1.088,2.464],[3.033,0.399],[2,-1.72],[3.82,-3.56],[2.004,-1.701],[1.911,-2.216],[-0.2,-6],[-5.58,-5.18],[-2.855,-3.413],[-3.413,2.855],[0.18,0.18]],"v":[[-303.572,344.441],[-294.852,357.381],[-291.872,363.601],[-294.792,369.821],[-303.512,382.761],[-304.752,391.121],[-298.752,395.781],[-290.752,392.621],[-285.052,387.261],[-273.632,376.521],[-267.892,371.121],[-265.112,363.121],[-274.552,349.781],[-291.212,334.101],[-302.562,333.091],[-303.572,344.441]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.450980392157,0.666666666667,0.18431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[305.572,-330.821],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":70,"st":0,"bm":0}],"markers":[]} 2 | -------------------------------------------------------------------------------- /PullToRefreshSample/PullToRefreshSampleiOS/Resources/animation-refreshing-shakuro_logo.json: -------------------------------------------------------------------------------- 1 | {"v":"5.12.1","fr":60,"ip":0,"op":64,"w":2052,"h":570,"nm":"pulldown_procces","ddd":0,"assets":[{"id":"comp_0","nm":"Logo Light 2","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 8","parent":9,"sr":1,"ks":{"o":{"a":0,"k":50,"ix":11},"r":{"a":0,"k":-2.114,"ix":10},"p":{"a":0,"k":[0.656,-0.024,0],"ix":2,"l":2},"a":{"a":0,"k":[1,0,0],"ix":1,"l":2},"s":{"a":0,"k":[73.465,73.465,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[416.602,416.602],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":0,"k":3,"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.498,0.475,0.475,0.547,0.996,0.333,0.333,0.416],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[1,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":30,"s":[100]},{"t":105,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":41,"s":[100]},{"t":117,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":103,"op":172,"st":15,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 7","parent":9,"sr":1,"ks":{"o":{"a":0,"k":50,"ix":11},"r":{"a":0,"k":-2.114,"ix":10},"p":{"a":0,"k":[0.656,-0.024,0],"ix":2,"l":2},"a":{"a":0,"k":[1,0,0],"ix":1,"l":2},"s":{"a":0,"k":[69.526,69.526,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[416.602,416.602],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":0,"k":3,"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.498,0.475,0.475,0.547,0.996,0.333,0.333,0.416],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[1,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":24,"s":[100]},{"t":99,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":35,"s":[100]},{"t":111,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":103,"op":172,"st":9,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 6","parent":9,"sr":1,"ks":{"o":{"a":0,"k":50,"ix":11},"r":{"a":0,"k":-2.114,"ix":10},"p":{"a":0,"k":[0.656,-0.024,0],"ix":2,"l":2},"a":{"a":0,"k":[1,0,0],"ix":1,"l":2},"s":{"a":0,"k":[65.653,65.653,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[416.602,416.602],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":0,"k":3,"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.498,0.475,0.475,0.547,0.996,0.333,0.333,0.416],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[1,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":15,"s":[100]},{"t":90,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":26,"s":[100]},{"t":102,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":103,"op":172,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Shape Layer 5","sr":1,"ks":{"o":{"a":0,"k":50,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[541,264,0],"ix":2,"l":2},"a":{"a":0,"k":[1,0,0],"ix":1,"l":2},"s":{"a":0,"k":[111.9,111.9,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[416.602,416.602],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":0,"k":3,"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.498,0.475,0.475,0.547,0.996,0.333,0.333,0.416],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[1,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":30,"s":[100]},{"t":105,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":41,"s":[100]},{"t":117,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":103,"st":15,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Shape Layer 4","sr":1,"ks":{"o":{"a":0,"k":50,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[541,264,0],"ix":2,"l":2},"a":{"a":0,"k":[1,0,0],"ix":1,"l":2},"s":{"a":0,"k":[105.9,105.9,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[416.602,416.602],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":0,"k":3,"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.498,0.475,0.475,0.547,0.996,0.333,0.333,0.416],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[1,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":24,"s":[100]},{"t":99,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":35,"s":[100]},{"t":111,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":103,"st":9,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Shape Layer 3","sr":1,"ks":{"o":{"a":0,"k":50,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[541,264,0],"ix":2,"l":2},"a":{"a":0,"k":[1,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[416.602,416.602],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":0,"k":3,"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.498,0.475,0.475,0.547,0.996,0.333,0.333,0.416],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[1,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":15,"s":[100]},{"t":90,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":26,"s":[100]},{"t":102,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":103,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Shape Layer 2","parent":11,"sr":1,"ks":{"o":{"a":0,"k":50,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[189.081,90.25,0],"ix":2,"l":2},"a":{"a":0,"k":[83.183,46.25,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-4.25,-45]],"o":[[0,0],[1.38,14.609]],"v":[[-18.5,-131.75],[-115,-25.75]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":0,"k":3,"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.498,0.475,0.475,0.547,0.996,0.333,0.333,0.416],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 2","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[49.75,105.5]],"o":[[0,0],[-24.918,-52.841]],"v":[[56.25,98.75],[96.5,-46]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":0,"k":3,"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.498,0.475,0.475,0.547,0.996,0.333,0.333,0.416],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.29],"y":[1]},"o":{"x":[0.71],"y":[0]},"t":62,"s":[0]},{"t":96,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.29],"y":[1]},"o":{"x":[0.71],"y":[0]},"t":50,"s":[0]},{"t":86,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":172,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Shape Layer 1","parent":7,"sr":1,"ks":{"o":{"a":0,"k":50,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[36.738,-102.385],[0,0]],"o":[[0,0],[-30.5,85],[0,0]],"v":[[-121,-58.5],[78,29],[-124.5,136.5]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.8],"y":[0]},"t":89,"s":[3]},{"t":108,"s":[0]}],"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.498,0.475,0.475,0.547,0.996,0.333,0.333,0.416],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 2","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-55,-73],[0,0]],"o":[[0,0],[55,73],[0,0]],"v":[[55.5,-131.5],[-76.5,22.5],[152,24]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.8],"y":[0]},"t":89,"s":[3]},{"t":108,"s":[0]}],"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.498,0.475,0.475,0.547,0.996,0.333,0.333,0.416],"ix":8}},"s":{"a":0,"k":[0,0],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.29],"y":[1]},"o":{"x":[0.71],"y":[0]},"t":21,"s":[0]},{"t":127,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.29],"y":[1]},"o":{"x":[0.71],"y":[0]},"t":11,"s":[0]},{"t":117,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":172,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":3,"nm":"Scale","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":32,"s":[270]},{"t":112,"s":[0]}],"ix":10},"p":{"a":0,"k":[540,264,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.79,0.79,0.79],"y":[0,0,0]},"t":10,"s":[126,126,100]},{"i":{"x":[0.2,0.2,0.2],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.8],"y":[0,0,0]},"t":69,"s":[155.941,155.941,100]},{"t":112,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":302,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Logo 1 Outlines","parent":9,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":94,"s":[100]},{"t":129,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[49.6,-14,0],"ix":2,"l":2},"a":{"a":0,"k":[52,61,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,11.1],[35,9.6],[0,0],[0,0],[0,0],[0,0],[6.2,-22.5],[0.6,-1.6]],"o":[[0,-36.3],[0,0],[0,0],[0,0],[0,0],[22.5,6.2],[-0.5,1.7],[4.2,-10]],"v":[[50.85,28.9],[-8.45,-48.9],[-52.25,-60.9],[-52.25,-15],[-20.05,-6.1],[16.55,4],[46.05,55.9],[43.475,60.775]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[52.25,61.3],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[22.5,6.2],[0,0],[25.87,-27.816],[0,0],[0,0],[0,0],[-5,11.7],[-0.5,1.7]],"o":[[0,0],[28.4,7.9],[0,0],[0,0],[0,0],[10.1,-8.3],[0.7,-1.6],[4.5,-20.4]],"v":[[17.2,-65.7],[-19.425,-76.05],[-6.65,-15.75],[-52.25,21.75],[-52.25,79.05],[21.45,18.55],[44.35,-11.95],[46.15,-16.95]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[52.25,131.35],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.29],"y":[1]},"o":{"x":[0.71],"y":[0]},"t":29,"s":[0]},{"t":103,"s":[100]}],"ix":2},"o":{"a":0,"k":125,"ix":3},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":85,"s":[3]},{"t":141,"s":[0]}],"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.5,0.473,0.473,0.545,1,0.329,0.329,0.412],"ix":8}},"s":{"a":0,"k":[0,-66],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false}],"ip":0,"op":123,"st":-52,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Logo 2 Outlines","parent":9,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":94,"s":[100]},{"t":129,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-52.9,17,0],"ix":2,"l":2},"a":{"a":0,"k":[52,61,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-6.2,22.5],[-0.7,1.7],[0,-11.1],[-35,-9.6],[0,0],[0,0],[0,0]],"o":[[-22.5,-6.2],[0.5,-1.7],[-4.3,10],[0,36.3],[0,0],[0,0],[0,0],[0,0]],"v":[[-16.5,-3.95],[-46,-55.85],[-44.3,-60.85],[-50.9,-28.95],[8.4,48.85],[52.2,60.85],[52.2,14.95],[20,6.05]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[50.9,60.85],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-22.5,-6.2],[0,0],[-22.8,18.8],[0,0],[0,0],[0,0],[5,-11.7],[0.4,-1.8]],"o":[[0,0],[-25.108,-6.8],[0,0],[0,0],[0,0],[-10.1,8.3],[-0.7,1.7],[-4.033,17.45]],"v":[[-17.075,64.725],[17.975,74.425],[6.7,15.75],[52.3,-21.75],[52.3,-79.05],[-21.4,-18.55],[-44.3,11.95],[-46.1,17.05]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[50.158,-8.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gs","o":{"a":0,"k":100,"ix":9},"w":{"a":1,"k":[{"i":{"x":[0.21],"y":[1]},"o":{"x":[0.79],"y":[0]},"t":85,"s":[3]},{"t":141,"s":[0]}],"ix":10},"g":{"p":3,"k":{"a":0,"k":[0,0.616,0.616,0.678,0.5,0.473,0.473,0.545,1,0.329,0.329,0.412],"ix":8}},"s":{"a":0,"k":[80,-2],"ix":4},"e":{"a":0,"k":[100,0],"ix":5},"t":1,"lc":2,"lj":2,"bm":0,"nm":"Gradient Stroke 1","mn":"ADBE Vector Graphic - G-Stroke","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.29],"y":[1]},"o":{"x":[0.71],"y":[0]},"t":29,"s":[0]},{"t":103,"s":[100]}],"ix":2},"o":{"a":0,"k":125,"ix":3},"m":1,"ix":4,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":123,"st":-53,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Shape Layer 10","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.21,"y":1},"o":{"x":0.79,"y":0},"t":75,"s":[374.001,-234.909,0],"to":[-47.967,35.386,0],"ti":[47.967,-35.386,0]},{"t":136,"s":[86.2,-22.596,0]}],"ix":2,"l":2},"a":{"a":0,"k":[82.594,-102.985,0],"ix":1,"l":2},"s":{"a":0,"k":[94.766,94.766,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[297.188,298.029],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.074509803922,0.074509803922,0.137254901961,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.5,0.5,0.5,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[34.502,-14.813],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[151.791,151.791],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":302,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Logo 1 Outlines","parent":9,"tt":1,"tp":12,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[49.6,-14,0],"ix":2,"l":2},"a":{"a":0,"k":[52,61,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,11.1],[35,9.6],[0,0],[0,0],[0,0],[0,0],[6.2,-22.5],[0.6,-1.6]],"o":[[0,-36.3],[0,0],[0,0],[0,0],[0,0],[22.5,6.2],[-0.5,1.7],[4.2,-10]],"v":[[50.85,28.9],[-8.45,-48.9],[-52.25,-60.9],[-52.25,-15],[-20.05,-6.1],[16.55,4],[46.05,55.9],[44.35,60.9]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.61568627451,0.61568627451,0.678431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[52.25,60.9],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":302,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Shape Layer 11","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.21,"y":1},"o":{"x":0.79,"y":0},"t":75,"s":[374.001,-234.909,0],"to":[-47.967,35.386,0],"ti":[47.967,-35.386,0]},{"t":136,"s":[86.2,-22.596,0]}],"ix":2,"l":2},"a":{"a":0,"k":[82.594,-102.985,0],"ix":1,"l":2},"s":{"a":0,"k":[94.766,94.766,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[297.188,298.029],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.074509803922,0.074509803922,0.137254901961,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.5,0.5,0.5,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[34.502,-14.813],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[151.791,151.791],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":302,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Logo 2 Outlines","parent":9,"tt":1,"tp":14,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-52.9,17,0],"ix":2,"l":2},"a":{"a":0,"k":[52,61,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-6.2,22.5],[-0.7,1.7],[0,-11.1],[-35,-9.6],[0,0],[0,0],[0,0]],"o":[[-22.5,-6.2],[0.5,-1.7],[-4.3,10],[0,36.3],[0,0],[0,0],[0,0],[0,0]],"v":[[-16.5,-3.95],[-46,-55.85],[-44.3,-60.85],[-50.9,-28.95],[8.4,48.85],[52.2,60.85],[52.2,14.95],[20,6.05]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.61568627451,0.61568627451,0.678431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[50.9,60.85],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":302,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":"Shape Layer 12","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.21,"y":1},"o":{"x":0.79,"y":0},"t":75,"s":[374.001,-234.909,0],"to":[-47.967,35.386,0],"ti":[47.967,-35.386,0]},{"t":136,"s":[86.2,-22.596,0]}],"ix":2,"l":2},"a":{"a":0,"k":[82.594,-102.985,0],"ix":1,"l":2},"s":{"a":0,"k":[94.766,94.766,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[297.188,298.029],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.074509803922,0.074509803922,0.137254901961,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.5,0.5,0.5,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[34.502,-14.813],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[151.791,151.791],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":302,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":"Logo 3 Outlines","parent":15,"tt":1,"tp":16,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[53,-9.5,0],"ix":2,"l":2},"a":{"a":0,"k":[50.5,79.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-22.183,-6.65],[0,0],[-22.8,18.8],[0,0],[0,0],[0,0],[5,-11.7],[0.4,-1.8]],"o":[[0,0],[-28.4,-7.9],[0,0],[0,0],[0,0],[-10.1,8.3],[-0.7,1.7],[-4.658,17.4]],"v":[[-17.825,66.725],[18.6,76.3],[6.7,15.75],[52.3,-21.75],[52.3,-79.05],[-21.4,-18.55],[-44.3,11.95],[-46.1,17.05]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,0.329,0.329,0.412,0.5,0.473,0.473,0.545,1,0.616,0.616,0.678],"ix":9}},"s":{"a":0,"k":[-12.836,68.551],"ix":5},"e":{"a":0,"k":[0.939,-59.545],"ix":6},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[47.758,79.05],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":302,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":"Shape Layer 13","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.21,"y":1},"o":{"x":0.79,"y":0},"t":75,"s":[374.001,-234.909,0],"to":[-47.967,35.386,0],"ti":[47.967,-35.386,0]},{"t":136,"s":[86.2,-22.596,0]}],"ix":2,"l":2},"a":{"a":0,"k":[82.594,-102.985,0],"ix":1,"l":2},"s":{"a":0,"k":[94.766,94.766,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[297.188,298.029],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.074509803922,0.074509803922,0.137254901961,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.5,0.5,0.5,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[34.502,-14.813],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[151.791,151.791],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":302,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":"Logo Outlines","parent":13,"tt":1,"tp":18,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50.5,131,0],"ix":2,"l":2},"a":{"a":0,"k":[50,79.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[19.3,7.275],[0,0],[22.8,-18.8],[0,0],[0,0],[0,0],[-5,11.7],[-0.5,1.7]],"o":[[0,0],[28.4,7.9],[0,0],[0,0],[0,0],[10.1,-8.3],[0.7,-1.6],[6.1,-22.6]],"v":[[17.45,-65.7],[-15.55,-74.3],[-6.65,-15.75],[-52.25,21.75],[-52.25,79.05],[21.45,18.55],[44.35,-11.95],[46.15,-16.95]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,0.329,0.329,0.412,0.5,0.473,0.473,0.545,1,0.616,0.616,0.678],"ix":9}},"s":{"a":0,"k":[23.859,-65.238],"ix":5},"e":{"a":0,"k":[-23.006,43.869],"ix":6},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[52.25,79.05],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":302,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":"Shape Layer 17","parent":21,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.8,"y":0},"t":66,"s":[374.001,-234.909,0],"to":[-47.967,35.386,0],"ti":[47.967,-35.386,0]},{"t":127,"s":[86.2,-22.596,0]}],"ix":2,"l":2},"a":{"a":0,"k":[82.594,-102.985,0],"ix":1,"l":2},"s":{"a":0,"k":[94.766,94.766,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[297.188,298.029],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.074509803922,0.074509803922,0.137254901961,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.5,0.5,0.5,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[34.502,-14.813],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[151.791,151.791],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":194,"st":-9,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":"Logo 1 Outlines 2","parent":9,"tt":1,"tp":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[49.6,-14,0],"ix":2,"l":2},"a":{"a":0,"k":[52,61,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,11.1],[35,9.6],[0,0],[0,0],[0,0],[0,0],[6.2,-22.5],[0.6,-1.6]],"o":[[0,-36.3],[0,0],[0,0],[0,0],[0,0],[22.5,6.2],[-0.5,1.7],[4.2,-10]],"v":[[50.85,28.9],[-8.45,-48.9],[-52.25,-60.9],[-52.25,-15],[-20.05,-6.1],[16.55,4],[46.05,55.9],[44.35,60.9]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.364705882353,0.364705882353,0.443137284821,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[52.25,60.9],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":194,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":"Shape Layer 16","parent":21,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.8,"y":0},"t":66,"s":[374.001,-234.909,0],"to":[-47.967,35.386,0],"ti":[47.967,-35.386,0]},{"t":127,"s":[86.2,-22.596,0]}],"ix":2,"l":2},"a":{"a":0,"k":[82.594,-102.985,0],"ix":1,"l":2},"s":{"a":0,"k":[94.766,94.766,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[297.188,298.029],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.074509803922,0.074509803922,0.137254901961,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.5,0.5,0.5,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[34.502,-14.813],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[151.791,151.791],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":194,"st":-9,"ct":1,"bm":0},{"ddd":0,"ind":23,"ty":4,"nm":"Logo 2 Outlines 2","parent":9,"tt":1,"tp":22,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-52.9,17,0],"ix":2,"l":2},"a":{"a":0,"k":[52,61,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-6.2,22.5],[-0.7,1.7],[0,-11.1],[-35,-9.6],[0,0],[0,0],[0,0]],"o":[[-22.5,-6.2],[0.5,-1.7],[-4.3,10],[0,36.3],[0,0],[0,0],[0,0],[0,0]],"v":[[-16.5,-3.95],[-46,-55.85],[-44.3,-60.85],[-50.9,-28.95],[8.4,48.85],[52.2,60.85],[52.2,14.95],[20,6.05]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.364705882353,0.364705882353,0.443137284821,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[50.9,60.85],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":194,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":24,"ty":4,"nm":"Shape Layer 15","parent":21,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.8,"y":0},"t":66,"s":[374.001,-234.909,0],"to":[-47.967,35.386,0],"ti":[47.967,-35.386,0]},{"t":127,"s":[86.2,-22.596,0]}],"ix":2,"l":2},"a":{"a":0,"k":[82.594,-102.985,0],"ix":1,"l":2},"s":{"a":0,"k":[94.766,94.766,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[297.188,298.029],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.074509803922,0.074509803922,0.137254901961,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.5,0.5,0.5,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[34.502,-14.813],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[151.791,151.791],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":194,"st":-9,"ct":1,"bm":0},{"ddd":0,"ind":25,"ty":4,"nm":"Logo 3 Outlines 2","parent":23,"tt":1,"tp":24,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[53,-9.5,0],"ix":2,"l":2},"a":{"a":0,"k":[50.5,79.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-22.183,-6.65],[0,0],[-22.8,18.8],[0,0],[0,0],[0,0],[5,-11.7],[0.4,-1.8]],"o":[[0,0],[-28.4,-7.9],[0,0],[0,0],[0,0],[-10.1,8.3],[-0.7,1.7],[-4.658,17.4]],"v":[[-17.825,66.725],[18.6,76.3],[6.7,15.75],[52.3,-21.75],[52.3,-79.05],[-21.4,-18.55],[-44.3,11.95],[-46.1,17.05]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.364705882353,0.364705882353,0.443137284821,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[47.758,79.05],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":194,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":26,"ty":4,"nm":"Shape Layer 14","parent":21,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.8,"y":0},"t":66,"s":[374.001,-234.909,0],"to":[-47.967,35.386,0],"ti":[47.967,-35.386,0]},{"t":127,"s":[86.2,-22.596,0]}],"ix":2,"l":2},"a":{"a":0,"k":[82.594,-102.985,0],"ix":1,"l":2},"s":{"a":0,"k":[94.766,94.766,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[297.188,298.029],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.074509803922,0.074509803922,0.137254901961,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.5,0.5,0.5,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[34.502,-14.813],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[151.791,151.791],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":194,"st":-9,"ct":1,"bm":0},{"ddd":0,"ind":27,"ty":4,"nm":"Logo Outlines 2","parent":21,"tt":1,"tp":26,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50.5,131,0],"ix":2,"l":2},"a":{"a":0,"k":[50,79.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[19.3,7.275],[0,0],[22.8,-18.8],[0,0],[0,0],[0,0],[-5,11.7],[-0.5,1.7]],"o":[[0,0],[28.4,7.9],[0,0],[0,0],[0,0],[10.1,-8.3],[0.7,-1.6],[6.1,-22.6]],"v":[[17.45,-65.7],[-15.55,-74.3],[-6.65,-15.75],[-52.25,21.75],[-52.25,79.05],[21.45,18.55],[44.35,-11.95],[46.15,-16.95]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.364705882353,0.364705882353,0.443137284821,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[52.25,79.05],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":194,"st":0,"ct":1,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Logo Light 2","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":0,"s":[0]},{"t":64,"s":[-360]}],"ix":10,"x":"var $bm_rt;\n$bm_rt = loopOut();"},"p":{"a":0,"k":[1026,268,0],"ix":2,"l":2,"x":"var $bm_rt;\n$bm_rt = transform.position;"},"a":{"a":0,"k":[540,264,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"tm":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":-120,"s":[0]},{"t":177,"s":[4.95]}],"ix":2},"w":1080,"h":562,"ip":0,"op":64,"st":-120,"bm":0}],"markers":[],"props":{}} -------------------------------------------------------------------------------- /PullToRefreshSample/PullToRefreshSampleiOS/Resources/animation-refreshing-shakuro_logo_old.json: -------------------------------------------------------------------------------- 1 | {"v":"5.1.1","fr":60,"ip":0,"op":80,"w":464,"h":130,"nm":"Slicing Part 2","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 17","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.5],"y":[0]},"n":["0p5_1_0p5_0"],"t":0,"s":[0],"e":[180]},{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.5],"y":[0]},"n":["0p5_1_0p5_0"],"t":30,"s":[180],"e":[180]},{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.5],"y":[0]},"n":["0p5_1_0p5_0"],"t":40,"s":[180],"e":[360]},{"t":70}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[232,65.25,0],"e":[232,68.25,0],"to":[0,0.5,0],"ti":[0,-0.5,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":30,"s":[232,68.25,0],"e":[232,68.25,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":40,"s":[232,68.25,0],"e":[232,65.25,0],"to":[0,-0.5,0],"ti":[0,0.5,0]},{"t":70}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[70,70,100],"ix":6}},"ao":0,"ip":0,"op":80,"st":-70,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Yellow Outlines","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.5],"y":[0]},"n":["0p5_1_0p5_0"],"t":-50,"s":[0],"e":[720]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.5],"y":[0]},"n":["0p833_1_0p5_0"],"t":0,"s":[720],"e":[747]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"n":["0p833_1_0p167_0"],"t":10,"s":[747],"e":[747]},{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.167],"y":[0]},"n":["0p5_1_0p167_0"],"t":20,"s":[747],"e":[720]},{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.5],"y":[0]},"n":["0p5_1_0p5_0"],"t":30,"s":[720],"e":[720]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.5],"y":[0]},"n":["0p833_1_0p5_0"],"t":40,"s":[720],"e":[747]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"n":["0p833_1_0p167_0"],"t":50,"s":[747],"e":[747]},{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.167],"y":[0]},"n":["0p5_1_0p167_0"],"t":60,"s":[747],"e":[720]},{"t":70}],"ix":10},"p":{"a":0,"k":[-25.714,-7.786,0],"ix":2},"a":{"a":0,"k":[20.5,33,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,4.72],[-2.52,4],[0,0],[1.28,-1.18],[3.82,-3.56],[1.822,-1.901],[-0.111,-2.921],[-4.04,-3.76],[-5.7,-5.04],[-2.973,0.456],[-0.944,2.856],[2.115,2.138],[3.02,4.18],[0.6,1.18],[1.22,1.7]],"o":[[0,-4.74],[0,0],[-1.28,1.2],[-3.82,3.56],[-2.015,1.696],[-1.898,2.223],[0.2,6],[5.58,5.18],[1.757,2.441],[2.973,-0.456],[0.944,-2.855],[-2.72,-4.38],[-0.78,-1.24],[-1.4,-2],[-2.6,-4.02]],"v":[[-288.345,347.56],[-282.725,335.78],[-282.185,335.02],[-286.005,338.62],[-297.405,349.36],[-303.165,354.76],[-305.945,362.76],[-296.505,376.1],[-279.845,391.78],[-272.138,395.014],[-265.756,389.617],[-267.665,381.48],[-276.385,368.54],[-278.645,365.04],[-282.645,359.34]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.901960784314,0.035294117647,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[305.945,-330],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.12,0.18],[3.02,4.18],[0,2.5],[-1.34,2.12],[-2.72,4.4],[1.134,2.805],[2.657,0.444],[1.945,-2.361],[1.9,-1.78],[3.82,-3.56],[1.822,-1.901],[-0.111,-2.921],[-4.04,-3.76],[-5.7,-5.04],[-2.973,0.456],[-0.944,2.856],[2.115,2.138]],"o":[[-2.72,-4.38],[-1.34,-2.12],[0,-2.5],[3.02,-4.18],[1.899,-2.355],[-1.088,-2.464],[-3.033,-0.395],[-2,1.72],[-3.7,3.56],[-2.015,1.696],[-1.898,2.223],[0.2,6],[5.58,5.18],[1.757,2.441],[2.973,-0.456],[0.944,-2.855],[-0.1,-0.2]],"v":[[-267.665,381.46],[-276.385,368.52],[-279.365,362.3],[-276.385,356.06],[-267.665,343.12],[-266.425,334.76],[-272.425,330.1],[-280.425,333.26],[-286.125,338.62],[-297.405,349.36],[-303.165,354.76],[-305.945,362.76],[-296.505,376.1],[-279.845,391.78],[-272.138,395.014],[-265.756,389.617],[-267.665,381.48]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.866666666667,0.752941176471,0.047058823529,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[305.945,-330],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":80,"st":-70,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Green Outlines","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.5],"y":[0]},"n":["0p5_1_0p5_0"],"t":-50,"s":[0],"e":[720]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.5],"y":[0]},"n":["0p833_1_0p5_0"],"t":0,"s":[720],"e":[747]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"n":["0p833_1_0p167_0"],"t":10,"s":[747],"e":[747]},{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.167],"y":[0]},"n":["0p5_1_0p167_0"],"t":20,"s":[747],"e":[720]},{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.5],"y":[0]},"n":["0p5_1_0p5_0"],"t":30,"s":[720],"e":[720]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.5],"y":[0]},"n":["0p833_1_0p5_0"],"t":40,"s":[720],"e":[747]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"n":["0p833_1_0p167_0"],"t":50,"s":[747],"e":[747]},{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.167],"y":[0]},"n":["0p5_1_0p167_0"],"t":60,"s":[747],"e":[720]},{"t":70}],"ix":10},"p":{"a":0,"k":[27,12.607,0],"ix":2},"a":{"a":0,"k":[20.5,32.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-4.72],[2.52,-4],[0.18,-0.26],[0,0],[-3.82,3.56],[-1.82,1.896],[0.125,2.923],[4.04,3.76],[5.72,5.04],[3.38,-2.85],[-2.85,-3.38],[-3.02,-4.18],[-0.6,-1.18],[0,0]],"o":[[0,4.74],[-0.18,0.24],[0,0],[3.82,-3.56],[2.004,-1.701],[1.911,-2.216],[-0.2,-6],[-5.58,-5.18],[-2.85,-3.38],[-3.38,2.85],[2.72,4.38],[0.8,1.24],[0,0],[2.64,4]],"v":[[-282.835,378.52],[-288.455,390.3],[-288.975,391.06],[-285.175,387.46],[-273.755,376.72],[-268.015,371.32],[-265.235,363.32],[-274.675,349.98],[-291.335,334.3],[-302.615,333.34],[-303.575,344.62],[-294.855,357.56],[-292.575,361.06],[-288.575,366.76]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.619607843137,0.76862745098,0.247058823529,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[305.575,-331],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-0.16],[-3.02,-4.18],[0,-2.5],[1.34,-2],[2.72,-4.4],[-1.134,-2.805],[-2.657,-0.444],[-1.942,2.364],[-1.9,1.78],[-3.82,3.56],[-1.82,1.896],[0.125,2.923],[4.04,3.76],[5.72,5.04],[3.413,-2.855],[-2.855,-3.413]],"o":[[2.72,4.38],[1.34,2.12],[0,2.5],[-3.02,4.18],[-1.899,2.355],[1.088,2.464],[3.033,0.399],[2,-1.72],[3.82,-3.56],[2.004,-1.701],[1.911,-2.216],[-0.2,-6],[-5.58,-5.18],[-2.855,-3.413],[-3.413,2.855],[0.18,0.18]],"v":[[-303.572,344.441],[-294.852,357.381],[-291.872,363.601],[-294.792,369.821],[-303.512,382.761],[-304.752,391.121],[-298.752,395.781],[-290.752,392.621],[-285.052,387.261],[-273.632,376.521],[-267.892,371.121],[-265.112,363.121],[-274.552,349.781],[-291.212,334.101],[-302.562,333.091],[-303.572,344.441]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.450980392157,0.666666666667,0.18431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[305.572,-330.821],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":80,"st":-70,"bm":0}],"markers":[]} -------------------------------------------------------------------------------- /PullToRefreshSample/PullToRefreshSampleiOS/UI/CircleAnimationWithProgressView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Copyright (c) 2024 Shakuro (https://shakuro.com/) 4 | // 5 | // 6 | 7 | import SwiftUI 8 | 9 | struct CircleAnimationWithProgressView: View { 10 | 11 | private var progress: CGFloat 12 | 13 | init(progress: CGFloat) { 14 | self.progress = progress 15 | } 16 | 17 | var body: some View { 18 | Circle() 19 | .trim(from: 0, to: progress * 0.9) 20 | .stroke(Color.green, lineWidth: 5) 21 | .frame(width: 40, height: 40) 22 | .rotationEffect(Angle(degrees: 270)) 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /PullToRefreshSample/PullToRefreshSampleiOS/UI/CircleAnimationWithRepeatView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Copyright (c) 2024 Shakuro (https://shakuro.com/) 4 | // 5 | // 6 | 7 | import SwiftUI 8 | 9 | struct CircleAnimationWithRepeatView: View { 10 | 11 | @State private var rotationDegrees: CGFloat = 0.0 12 | 13 | var body: some View { 14 | Circle() 15 | .trim(from: 0, to: 0.9) 16 | .stroke(Color.green, lineWidth: 5) 17 | .frame(width: 40, height: 40) 18 | .rotationEffect(Angle(degrees: 270)) 19 | .rotationEffect(Angle(degrees: rotationDegrees)) 20 | .animation(.linear(duration: 1).repeatForever(autoreverses: false), value: rotationDegrees) 21 | .onAppear(perform: { 22 | rotationDegrees = 360 23 | }) 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /PullToRefreshSample/PullToRefreshSampleiOS/UI/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Copyright (c) 2024 Shakuro (https://shakuro.com/) 4 | // 5 | // 6 | 7 | import SwiftUI 8 | 9 | struct ContentView: View { 10 | 11 | private enum Option { 12 | case list 13 | case scroll 14 | } 15 | 16 | @State private var options: [Option] = [.list, .scroll] 17 | 18 | var body: some View { 19 | NavigationView(content: { 20 | List(content: { 21 | ForEach(options, id: \.self, content: { (option) in 22 | NavigationLink(destination: { 23 | switch option { 24 | case .list: 25 | ListContentView() 26 | case .scroll: 27 | ScrollContentView() 28 | } 29 | }, label: { 30 | switch option { 31 | case .list: 32 | Text("List View") 33 | case .scroll: 34 | Text("Scroll View") 35 | } 36 | }) 37 | }) 38 | }) 39 | .navigationTitle("Options") 40 | .navigationBarTitleDisplayMode(.inline) 41 | }) 42 | } 43 | 44 | } 45 | 46 | #Preview { 47 | ContentView() 48 | } 49 | -------------------------------------------------------------------------------- /PullToRefreshSample/PullToRefreshSampleiOS/UI/ContentViewWithSplitView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Copyright (c) 2024 Shakuro (https://shakuro.com/) 4 | // 5 | // 6 | 7 | import SwiftUI 8 | 9 | @available(iOS 17.0, *) 10 | struct ContentViewWithSplitView: View { 11 | 12 | private enum Option { 13 | case list 14 | case scroll 15 | } 16 | 17 | @State private var options: [Option] = [.list, .scroll] 18 | @State private var preferredColumn = NavigationSplitViewColumn.sidebar 19 | @State private var selectedOption: Option? 20 | 21 | var body: some View { 22 | NavigationSplitView(preferredCompactColumn: $preferredColumn) { 23 | List(selection: $selectedOption) { 24 | ForEach(Array(options), id: \.self) { (option) in 25 | NavigationLink(value: option) { 26 | switch option { 27 | case .list: 28 | Text("List View") 29 | case .scroll: 30 | Text("Scroll View") 31 | } 32 | } 33 | } 34 | } 35 | .navigationTitle("Options") 36 | .navigationBarTitleDisplayMode(.inline) 37 | } detail: { 38 | switch selectedOption { 39 | case .list: 40 | ListContentView() 41 | case .scroll: 42 | ScrollContentView() 43 | case .none: 44 | Text("Choose an item from the content") 45 | } 46 | } 47 | } 48 | 49 | } 50 | 51 | @available(iOS 17.0, *) 52 | #Preview(body: { 53 | ContentViewWithSplitView() 54 | }) 55 | -------------------------------------------------------------------------------- /PullToRefreshSample/PullToRefreshSampleiOS/UI/ListContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Copyright (c) 2024 Shakuro (https://shakuro.com/) 4 | // 5 | // 6 | 7 | import Lottie 8 | import PullToRefreshSwiftUI 9 | import SwiftUI 10 | 11 | struct ListItem: Identifiable { 12 | 13 | var title: String 14 | 15 | // MARK: - Identifiable 16 | 17 | var id: String { 18 | return title 19 | } 20 | 21 | } 22 | 23 | struct ListContentView: View { 24 | 25 | private enum AnimationType { 26 | case native 27 | case progressView 28 | case lottie 29 | } 30 | 31 | @State private var isRefreshing: Bool = false 32 | @State private var animationType: AnimationType = .native 33 | 34 | @State private var items: [ListItem] = [ 35 | ListItem(title: "Item 1"), 36 | ListItem(title: "Item 2"), 37 | ListItem(title: "Item 3"), 38 | ListItem(title: "Item 4"), 39 | ListItem(title: "Item 5"), 40 | ListItem(title: "Item 6"), 41 | ListItem(title: "Item 7"), 42 | ListItem(title: "Item 8"), 43 | ListItem(title: "Item 9"), 44 | ListItem(title: "Item 10"), 45 | ListItem(title: "Item 11"), 46 | ListItem(title: "Item 12"), 47 | ListItem(title: "Item 13"), 48 | ListItem(title: "Item 14"), 49 | ListItem(title: "Item 15"), 50 | ListItem(title: "Item 16"), 51 | ListItem(title: "Item 17"), 52 | ListItem(title: "Item 18"), 53 | ListItem(title: "Item 19"), 54 | ListItem(title: "Item 20"), 55 | ListItem(title: "Item 21"), 56 | ] 57 | 58 | var body: some View { 59 | PullToRefreshListView( 60 | pullToRefreshAnimationHeight: 100, 61 | pullToRefreshPullHeight: 100, 62 | showsIndicators: true, 63 | isRefreshing: $isRefreshing, 64 | onRefresh: { 65 | debugPrint("Refreshing") 66 | DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + DispatchTimeInterval.seconds(5), execute: { 67 | isRefreshing = false 68 | items.shuffle() 69 | }) 70 | }, 71 | animationViewBuilder: { (state) in 72 | switch state { 73 | case .idle: 74 | Color.clear 75 | case .pulling(let progress): 76 | switch animationType { 77 | case .native: 78 | CircleAnimationWithProgressView(progress: progress) 79 | case .progressView: 80 | ProgressView(value: max(min(progress, 1), 0), total: 1) 81 | .progressViewStyle(.linear) 82 | case .lottie: 83 | LottieView(animation: .named("animation-pulling-shakuro_logo")) 84 | .playbackMode(.paused(at: .progress(progress))) 85 | } 86 | case .refreshing: 87 | switch animationType { 88 | case .native: 89 | CircleAnimationWithRepeatView() 90 | case .progressView: 91 | ProgressView() 92 | .progressViewStyle(.circular) 93 | case .lottie: 94 | LottieView(animation: .named("animation-refreshing-shakuro_logo")) 95 | .playbackMode(.playing(.fromProgress(0, toProgress: 1, loopMode: .loop))) 96 | } 97 | case .finishing: 98 | switch animationType { 99 | case .native: 100 | CircleAnimationWithRepeatView() 101 | case .progressView: 102 | ProgressView() 103 | .progressViewStyle(.circular) 104 | case .lottie: 105 | LottieView(animation: .named("animation-refreshing-shakuro_logo")) 106 | .playbackMode(.playing(.fromProgress(0, toProgress: 1, loopMode: .loop))) 107 | } 108 | } 109 | }, 110 | contentViewBuilder: { _ in 111 | Picker("Current animation type", selection: $animationType) { 112 | Text("Native").tag(AnimationType.native) 113 | Text("ProgressView").tag(AnimationType.progressView) 114 | Text("Lottie").tag(AnimationType.lottie) 115 | } 116 | .pickerStyle(.segmented) 117 | .listRowSeparator(.hidden, edges: .top) 118 | ForEach(items, content: { (item) in 119 | ListContentItemView(listItem: item) 120 | }) 121 | .onDelete(perform: { (indexSet) in 122 | items.remove(atOffsets: indexSet) 123 | }) 124 | .onMove(perform: { (indices, newOffset) in 125 | items.move(fromOffsets: indices, toOffset: newOffset) 126 | }) 127 | }) 128 | .navigationTitle("Items") 129 | .navigationBarTitleDisplayMode(.inline) 130 | .navigationBarItems(trailing: EditButton()) 131 | } 132 | 133 | } 134 | 135 | struct ListContentItemView: View { 136 | 137 | let listItem: ListItem 138 | 139 | var body: some View { 140 | NavigationLink(destination: ListContentItemDetailView(listItem: listItem)) { 141 | HStack { 142 | Text(listItem.title) 143 | .font(.headline) 144 | .lineLimit(1) 145 | Spacer() 146 | } 147 | .padding(.vertical, 8) 148 | } 149 | } 150 | } 151 | 152 | struct ListContentItemDetailView: View { 153 | 154 | let listItem: ListItem 155 | 156 | var body: some View { 157 | ZStack { 158 | VStack { 159 | Text(listItem.title) 160 | .font(.largeTitle) 161 | .padding(.bottom, 10) 162 | Spacer() 163 | } 164 | } 165 | .navigationTitle(listItem.title) 166 | .edgesIgnoringSafeArea(.bottom) 167 | } 168 | } 169 | 170 | #Preview { 171 | ListContentView() 172 | } 173 | -------------------------------------------------------------------------------- /PullToRefreshSample/PullToRefreshSampleiOS/UI/ScrollContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Copyright (c) 2024 Shakuro (https://shakuro.com/) 4 | // 5 | // 6 | 7 | import Lottie 8 | import PullToRefreshSwiftUI 9 | import SwiftUI 10 | 11 | struct ScrollContentView: View { 12 | 13 | private enum AnimationType { 14 | case native 15 | case progressView 16 | case lottie 17 | } 18 | 19 | @State private var isRefreshing: Bool = false 20 | @State private var animationType: AnimationType = .native 21 | 22 | var body: some View { 23 | PullToRefreshScrollView( 24 | pullToRefreshAnimationHeight: 100, 25 | animationDuration: 0.3, 26 | offsetAboveRefreshingAnimation: 110, 27 | isRefreshing: $isRefreshing, 28 | onRefresh: { 29 | debugPrint("Refreshing") 30 | DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + DispatchTimeInterval.seconds(5), execute: { 31 | isRefreshing = false 32 | }) 33 | }, 34 | animationViewBuilder: { (state) in 35 | switch state { 36 | case .idle: 37 | Color.clear 38 | case .pulling(let progress): 39 | switch animationType { 40 | case .native: 41 | CircleAnimationWithProgressView(progress: progress) 42 | case .progressView: 43 | ProgressView(value: progress, total: 1) 44 | .progressViewStyle(.linear) 45 | case .lottie: 46 | LottieView(animation: .named("animation-pulling-shakuro_logo")) 47 | .playbackMode(.paused(at: .progress(progress))) 48 | } 49 | case .refreshing: 50 | switch animationType { 51 | case .native: 52 | CircleAnimationWithRepeatView() 53 | case .progressView: 54 | ProgressView() 55 | .progressViewStyle(.circular) 56 | case .lottie: 57 | LottieView(animation: .named("animation-refreshing-shakuro_logo")) 58 | .playbackMode(.playing(.fromProgress(0, toProgress: 1, loopMode: .loop))) 59 | } 60 | case .finishing(let progress, let isTriggered): 61 | if isTriggered { 62 | switch animationType { 63 | case .native: 64 | CircleAnimationWithRepeatView() 65 | case .progressView: 66 | ProgressView() 67 | .progressViewStyle(.circular) 68 | case .lottie: 69 | LottieView(animation: .named("animation-refreshing-shakuro_logo")) 70 | .playbackMode(.playing(.fromProgress(0, toProgress: 1, loopMode: .loop))) 71 | .opacity(progress) 72 | .scaleEffect(progress) 73 | } 74 | } else { 75 | switch animationType { 76 | case .native: 77 | CircleAnimationWithProgressView(progress: progress) 78 | case .progressView: 79 | ProgressView(value: progress, total: 1) 80 | .progressViewStyle(.linear) 81 | case .lottie: 82 | LottieView(animation: .named("animation-pulling-shakuro_logo")) 83 | .playbackMode(.paused(at: .progress(progress))) 84 | } 85 | } 86 | } 87 | }, 88 | contentViewBuilder: { _ in 89 | VStack(spacing: 16, content: { 90 | Text(isRefreshing ? "Refreshing" : "Idle") 91 | .font(.largeTitle) 92 | .foregroundStyle(isRefreshing ? .white : .black) 93 | Picker("Current animation type", selection: $animationType) { 94 | Text("Native").tag(AnimationType.native) 95 | Text("ProgressView").tag(AnimationType.progressView) 96 | Text("Lottie").tag(AnimationType.lottie) 97 | } 98 | .pickerStyle(.segmented) 99 | Color.clear 100 | }) 101 | .padding(EdgeInsets(top: 16, leading: 16, bottom: 16, trailing: 16)) 102 | .background(Color(isRefreshing ? .darkGray : .lightGray)) 103 | .animation(.linear(duration: 0.3), value: isRefreshing) 104 | .frame(height: 1000) 105 | }) 106 | .navigationTitle("Scroll View Example") 107 | .navigationBarTitleDisplayMode(.inline) 108 | } 109 | 110 | } 111 | 112 | #Preview { 113 | ScrollContentView() 114 | } 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Shakuro PullToRefreshSwiftUI](Resources/title_image.png) 2 |

3 | # PullToRefreshSwiftUI 4 | ![Version](https://img.shields.io/badge/version-1.6.5-blue.svg) 5 | ![Platform](https://img.shields.io/badge/platform-iOS-lightgrey.svg) 6 | ![License MIT](https://img.shields.io/badge/license-MIT-green.svg) 7 | 8 | - [ScrollView](#scrollview) 9 | - [List](#list) 10 | - [Requirements](#requirements) 11 | - [Installation](#installation) 12 | - [Usage](#usage) 13 | - [License](#license) 14 | 15 | `PullToRefreshSwiftUI` package contains `PullToRefreshScrollView` and `PullToRefreshListView` controls, that allows to add pull to refresh to ScrollView and List SwiftUI containers. 16 | 17 | ![](Resources/pull_to_refresh_example_main.gif) 18 | 19 | ## ScrollView 20 | 21 | A `PullToRefreshScrollView` is a custom control that alows to put some content on scroll view with pull to refresh action. 22 | 23 | `PullToRefreshScrollView` example: 24 | 25 | ```swift 26 | PullToRefreshListView( 27 | pullToRefreshAnimationHeight: 100, 28 | pullToRefreshPullHeight: 100, 29 | isRefreshing: .constant(true), 30 | onRefresh: { 31 | debugPrint("Refreshing") 32 | }, 33 | animationViewBuilder: { (state) in 34 | switch state { 35 | case .idle: 36 | Color.clear 37 | case .pulling(let progress): 38 | ProgressView(value: progress, total: 1) 39 | .progressViewStyle(.linear) 40 | case .refreshing: 41 | ProgressView() 42 | .progressViewStyle(.circular) 43 | case .finishing(let progress, let isTriggered): 44 | if isTriggered { 45 | ProgressView() 46 | .progressViewStyle(.circular) 47 | } else { 48 | ProgressView(value: progress, total: 1) 49 | .progressViewStyle(.linear) 50 | } 51 | } 52 | }, 53 | contentViewBuilder: { _ in 54 | ForEach(0..<5, content: { (item) in 55 | Text("Item \(item)") 56 | }) 57 | }) 58 | ``` 59 | 60 | ![](Resources/pull_to_refresh_example_1.gif) 61 | 62 | ## List 63 | 64 | A `PullToRefreshListView` is a custom control that alows to add some content to list view with pull to refresh action. 65 | 66 | `PullToRefreshListView` example: 67 | 68 | ```swift 69 | PullToRefreshListView( 70 | options: PullToRefreshListViewOptions(pullToRefreshAnimationHeight: 100, 71 | animationDuration: 0.3, 72 | animatePullingViewPresentation: true, 73 | animateRefreshingViewPresentation: true), 74 | isRefreshing: $isRefreshing, 75 | onRefresh: { 76 | debugPrint("Refreshing") 77 | DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + DispatchTimeInterval.seconds(5), execute: { 78 | isRefreshing = false 79 | }) 80 | }, 81 | animationViewBuilder: { (state) in 82 | switch state { 83 | case .idle: 84 | Color.clear 85 | case .pulling(let progress): 86 | ProgressView(value: progress, total: 1) 87 | .progressViewStyle(.linear) 88 | case .refreshing: 89 | ProgressView() 90 | .progressViewStyle(.circular) 91 | case .finishing(let progress, let isTriggered): 92 | if isTriggered { 93 | ProgressView() 94 | .progressViewStyle(.circular) 95 | } else { 96 | ProgressView(value: progress, total: 1) 97 | .progressViewStyle(.linear) 98 | } 99 | } 100 | }, 101 | contentViewBuilder: { _ in 102 | ForEach(0..<5, content: { (item) in 103 | Text("Item \(item)") 104 | }) 105 | }) 106 | ``` 107 | 108 | ![](Resources/pull_to_refresh_example_2.gif) 109 | 110 | ## Requirements 111 | 112 | - iOS 15.0+ 113 | - Xcode 15.0+ 114 | - Swift 5.9+ 115 | 116 | ## Installation 117 | 118 | ### Swift Package Manager 119 | 120 | **App dependency** 121 | 122 | Select File > Add Package Dependencies and enter the repository URL ([Adding Package Dependencies to Your App](https://developer.apple.com/documentation/xcode/adding_package_dependencies_to_your_app)) 123 | 124 | **Package dependency** 125 | 126 | Add `PullToRefreshSwiftUI` as a dependency in your `Package.swift` manifest: 127 | 128 | ```swift 129 | dependencies: [ 130 | .package(url: "https://github.com/shakurocom/PullToRefreshSwiftUI.git", from: "1.6.0") 131 | ] 132 | ``` 133 | 134 | ### CocoaPods 135 | 136 | To integrate PullToRefreshSwiftUI into your Xcode project with CocoaPods, specify it in your `Podfile`: 137 | 138 | ```ruby 139 | pod 'Shakuro.PullToRefreshSwiftUI' 140 | ``` 141 | 142 | Then, run the following command: 143 | 144 | ```bash 145 | $ pod install 146 | ``` 147 | 148 | ### Manually 149 | 150 | If you prefer not to use CocoaPods, you can integrate Shakuro.PullToRefreshSwiftUI simply by copying it to your project. 151 | 152 | ## Usage 153 | 154 | Have a look at the [PullToRefreshSampleiOS](https://github.com/shakurocom/PullToRefreshSwiftUI/tree/main/PullToRefreshSample) 155 | 156 | ## License 157 | 158 | Shakuro.PullToRefreshSwiftUI is released under the MIT license. [See LICENSE](https://github.com/shakurocom/PullToRefreshSwiftUI/blob/main/LICENSE.md) for details. 159 | 160 | ## Give it a try and reach us 161 | 162 | Explore our expertise in Native Mobile Development and iOS Development.

163 | 164 | If you need professional assistance with your mobile or web project, feel free to contact our team 165 | -------------------------------------------------------------------------------- /Resources/pull_to_refresh_example_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakurocom/PullToRefreshSwiftUI/8a75b3693449f9fe062492584575887b76d528bb/Resources/pull_to_refresh_example_1.gif -------------------------------------------------------------------------------- /Resources/pull_to_refresh_example_2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakurocom/PullToRefreshSwiftUI/8a75b3693449f9fe062492584575887b76d528bb/Resources/pull_to_refresh_example_2.gif -------------------------------------------------------------------------------- /Resources/pull_to_refresh_example_main.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakurocom/PullToRefreshSwiftUI/8a75b3693449f9fe062492584575887b76d528bb/Resources/pull_to_refresh_example_main.gif -------------------------------------------------------------------------------- /Resources/title_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shakurocom/PullToRefreshSwiftUI/8a75b3693449f9fe062492584575887b76d528bb/Resources/title_image.png -------------------------------------------------------------------------------- /Shakuro.PullToRefreshSwiftUI.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = 'Shakuro.PullToRefreshSwiftUI' 4 | s.version = '1.6.5' 5 | s.summary = 'PullToRefreshSwiftUI' 6 | s.homepage = 'https://github.com/shakurocom/PullToRefreshSwiftUI' 7 | s.license = { :type => "MIT", :file => "LICENSE.md" } 8 | s.authors = {'wwwpix' => 'spopov@shakuro.com'} 9 | s.source = { :git => 'https://github.com/shakurocom/PullToRefreshSwiftUI.git', :tag => s.version } 10 | s.swift_versions = ['5.9'] 11 | s.source_files = 'Sources/PullToRefreshSwiftUI/*' 12 | s.ios.deployment_target = '15.0' 13 | 14 | end 15 | -------------------------------------------------------------------------------- /Sources/PullToRefreshSwiftUI/GeometryGroupModifier.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Copyright (c) 2024 Shakuro (https://shakuro.com/) 4 | // 5 | // 6 | 7 | import SwiftUI 8 | 9 | public struct GeometryGroupModifier: ViewModifier { 10 | 11 | public init() { } 12 | 13 | public func body(content: Content) -> some View { 14 | if #available(iOS 17.0, *) { 15 | content 16 | // https://medium.com/the-swift-cooperative/swiftui-geometrygroup-guide-from-theory-to-practice-1a7f4b04c4ec 17 | .geometryGroup() 18 | } else { 19 | content 20 | .transformEffect(.identity) 21 | } 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /Sources/PullToRefreshSwiftUI/PullToRefreshListView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Copyright (c) 2024 Shakuro (https://shakuro.com/) 4 | // 5 | // 6 | 7 | import SwiftUI 8 | 9 | public enum PullToRefreshListViewState: Equatable { 10 | case idle 11 | case pulling(progress: CGFloat) 12 | case refreshing 13 | case finishing // state after refreshing - view returning to idle state 14 | } 15 | 16 | public struct PullToRefreshListView: View { 17 | 18 | private let pullToRefreshAnimationHeight: CGFloat 19 | private let pullToRefreshPullHeight: CGFloat 20 | private let offsetAboveRefreshingAnimation: CGFloat 21 | private let showsIndicators: Bool 22 | private let isPullToRefreshEnabled: Bool 23 | private let onScroll: (_ oldOffsetY: CGFloat, _ newOffsetY: CGFloat, _ isInteracting: Bool) -> Void 24 | private let onEndDragging: () -> Void 25 | private let isRefreshing: Binding 26 | private let onRefresh: () -> Void 27 | private let animationViewBuilder: (_ state: PullToRefreshListViewState) -> AnimationViewType 28 | private let contentViewBuilder: (_ scrollViewSize: CGSize) -> ContentViewType 29 | 30 | // MARK: - Initialization 31 | 32 | /// - parameter onScroll: iOS 18+ 33 | /// - parameter onEndDragging: iOS 18+ 34 | public init(pullToRefreshAnimationHeight: CGFloat, 35 | pullToRefreshPullHeight: CGFloat, 36 | showsIndicators: Bool = true, 37 | isPullToRefreshEnabled: Bool = true, 38 | offsetAboveRefreshingAnimation: CGFloat = 0, 39 | onScroll: @escaping (_ oldOffsetY: CGFloat, _ newOffsetY: CGFloat, _ isInteracting: Bool) -> Void = { _, _, _ in }, 40 | onEndDragging: @escaping () -> Void = { }, 41 | isRefreshing: Binding, 42 | onRefresh: @escaping () -> Void, 43 | @ViewBuilder animationViewBuilder: @escaping (_ state: PullToRefreshListViewState) -> AnimationViewType, 44 | @ViewBuilder contentViewBuilder: @escaping (_ scrollViewSize: CGSize) -> ContentViewType) { 45 | self.pullToRefreshAnimationHeight = pullToRefreshAnimationHeight 46 | self.pullToRefreshPullHeight = pullToRefreshPullHeight 47 | self.offsetAboveRefreshingAnimation = offsetAboveRefreshingAnimation 48 | self.showsIndicators = showsIndicators 49 | self.isPullToRefreshEnabled = isPullToRefreshEnabled 50 | self.onScroll = onScroll 51 | self.onEndDragging = onEndDragging 52 | self.isRefreshing = isRefreshing 53 | self.onRefresh = onRefresh 54 | self.animationViewBuilder = animationViewBuilder 55 | self.contentViewBuilder = contentViewBuilder 56 | } 57 | 58 | // MARK: - UI 59 | 60 | public var body: some View { 61 | if #available(iOS 18.0, *) { 62 | PullToRefreshListView18IOS(pullToRefreshAnimationHeight: pullToRefreshAnimationHeight, 63 | pullToRefreshPullHeight: pullToRefreshPullHeight, 64 | showsIndicators: showsIndicators, 65 | isPullToRefreshEnabled: isPullToRefreshEnabled, 66 | offsetAboveRefreshingAnimation: offsetAboveRefreshingAnimation, 67 | onScroll: onScroll, 68 | onEndDragging: onEndDragging, 69 | isRefreshing: isRefreshing, 70 | onRefresh: onRefresh, 71 | animationViewBuilder: animationViewBuilder, 72 | contentViewBuilder: contentViewBuilder) 73 | } else { 74 | PullToRefreshListViewOldIOS(pullToRefreshAnimationHeight: pullToRefreshAnimationHeight, 75 | showsIndicators: showsIndicators, 76 | isPullToRefreshEnabled: isPullToRefreshEnabled, 77 | offsetAboveRefreshingAnimation: offsetAboveRefreshingAnimation, 78 | isRefreshing: isRefreshing, 79 | onRefresh: onRefresh, 80 | animationViewBuilder: animationViewBuilder, 81 | contentViewBuilder: contentViewBuilder) 82 | } 83 | } 84 | 85 | } 86 | 87 | // MARK: - Preview 88 | 89 | #Preview(body: { 90 | PullToRefreshListView( 91 | pullToRefreshAnimationHeight: 100, 92 | pullToRefreshPullHeight: 100, 93 | isRefreshing: .constant(true), 94 | onRefresh: { 95 | debugPrint("Refreshing") 96 | }, 97 | animationViewBuilder: { (state) in 98 | switch state { 99 | case .idle: 100 | Color.clear 101 | case .pulling(let progress): 102 | ProgressView(value: progress, total: 1) 103 | .progressViewStyle(.linear) 104 | case .refreshing: 105 | ProgressView() 106 | .progressViewStyle(.circular) 107 | case .finishing: 108 | ProgressView() 109 | .progressViewStyle(.circular) 110 | } 111 | }, 112 | contentViewBuilder: { _ in 113 | ForEach(0..<5, content: { (item) in 114 | Text("Item \(item)") 115 | }) 116 | }) 117 | }) 118 | -------------------------------------------------------------------------------- /Sources/PullToRefreshSwiftUI/PullToRefreshListView18IOS.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Copyright (c) 2025 Shakuro (https://shakuro.com/) 4 | // 5 | // 6 | 7 | import SwiftUI 8 | 9 | @available(iOS 18.0, *) 10 | public struct PullToRefreshListView18IOS: View { 11 | 12 | private let pullToRefreshAnimationHeight: CGFloat 13 | private let pullToRefreshPullHeight: CGFloat 14 | private let animationDuration: TimeInterval 15 | private let offsetAboveRefreshingAnimation: CGFloat 16 | private let showsIndicators: Bool 17 | private let isPullToRefreshEnabled: Bool 18 | private let onScroll: (_ oldOffsetY: CGFloat, _ newOffsetY: CGFloat, _ isInteracting: Bool) -> Void 19 | private let onEndDragging: () -> Void 20 | private let isRefreshing: Binding 21 | private let onRefresh: () -> Void 22 | private let animationViewBuilder: (_ state: PullToRefreshListViewState) -> AnimationViewType 23 | private let contentViewBuilder: (_ scrollViewSize: CGSize) -> ContentViewType 24 | 25 | @State private var scrollViewSize: CGSize = .zero // needed to build content 26 | @State private var animationOffsetY: CGFloat = 0 // offset to keep refreshing animation in proper place 27 | @State private var pullToRefreshProgressPoints: CGFloat = 0 // progress of pull-to-refresh 28 | @State private var isInteracting: Bool = false // user is actively dragging scroll 29 | @State private var pullToRefreshState: PullToRefreshListViewState = .idle // state of the animation 30 | 31 | // MARK: - Initialization 32 | 33 | public init(pullToRefreshAnimationHeight: CGFloat, 34 | pullToRefreshPullHeight: CGFloat, 35 | animationDuration: TimeInterval = 0.3, 36 | showsIndicators: Bool = true, 37 | isPullToRefreshEnabled: Bool = true, 38 | offsetAboveRefreshingAnimation: CGFloat = 0, 39 | onScroll: @escaping (_ oldOffsetY: CGFloat, _ newOffsetY: CGFloat, _ isInteracting: Bool) -> Void = { _, _, _ in }, 40 | onEndDragging: @escaping () -> Void = { }, 41 | isRefreshing: Binding, 42 | onRefresh: @escaping () -> Void, 43 | @ViewBuilder animationViewBuilder: @escaping (_ state: PullToRefreshListViewState) -> AnimationViewType, 44 | @ViewBuilder contentViewBuilder: @escaping (_ scrollViewSize: CGSize) -> ContentViewType) { 45 | self.pullToRefreshAnimationHeight = pullToRefreshAnimationHeight 46 | self.pullToRefreshPullHeight = pullToRefreshPullHeight 47 | self.animationDuration = animationDuration 48 | self.offsetAboveRefreshingAnimation = offsetAboveRefreshingAnimation 49 | self.showsIndicators = showsIndicators 50 | self.isPullToRefreshEnabled = isPullToRefreshEnabled 51 | self.onScroll = onScroll 52 | self.onEndDragging = onEndDragging 53 | self.isRefreshing = isRefreshing 54 | self.onRefresh = onRefresh 55 | self.animationViewBuilder = animationViewBuilder 56 | self.contentViewBuilder = contentViewBuilder 57 | } 58 | 59 | // MARK: - UI 60 | 61 | public var body: some View { 62 | ZStack(alignment: .top, content: { 63 | pullToRefreshAnimationView() 64 | mainListView() 65 | }) 66 | .clipped() 67 | .onChange(of: isRefreshing.wrappedValue, { (_, newIsRefreshing: Bool) -> Void in 68 | if newIsRefreshing { 69 | showPullToRefreshAnimationIfNeeded() 70 | } else { 71 | endPullToRefreshAnimationIfNeeded() 72 | } 73 | }) 74 | } 75 | 76 | @ViewBuilder 77 | private func mainListView() -> some View { 78 | List(content: { 79 | Color.clear 80 | .frame(height: offsetAboveRefreshingAnimation) 81 | .listRowSeparator(.hidden) 82 | .listRowInsets(EdgeInsets()) 83 | .listRowBackground(Color.clear) 84 | .id("above-offset") 85 | if pullToRefreshState == .refreshing { 86 | Color.clear 87 | .frame(height: pullToRefreshPullHeight) 88 | .listRowSeparator(.hidden) 89 | .listRowInsets(EdgeInsets()) 90 | .listRowBackground(Color.clear) 91 | .id("refreshing-spacer") 92 | } 93 | contentViewBuilder(scrollViewSize) 94 | .modifier(GeometryGroupModifier()) 95 | }) 96 | .environment(\.defaultMinListRowHeight, 0) 97 | .listStyle(PlainListStyle()) 98 | .animation(.easeInOut(duration: animationDuration), value: pullToRefreshState) 99 | .onScrollGeometryChange( 100 | for: ScrollGeometry.self, 101 | of: { return $0 }, 102 | action: { (oldValue: ScrollGeometry, newValue: ScrollGeometry) -> Void in 103 | scrollViewSize = newValue.bounds.size 104 | // top inset is usually added by standard navigation bar 105 | let oldOffsetY = oldValue.contentOffset.y + oldValue.contentInsets.top 106 | let newOffsetY = newValue.contentOffset.y + newValue.contentInsets.top 107 | onScroll(oldOffsetY, newOffsetY, isInteracting) 108 | updateAnimationOffset(contentOffset: newOffsetY) 109 | }) 110 | .onScrollPhaseChange({ (oldPhase: ScrollPhase, newPhase: ScrollPhase) -> Void in 111 | isInteracting = newPhase == .interacting 112 | if oldPhase == .interacting && newPhase != .interacting { 113 | // user released finger 114 | onEndDragging() 115 | triggerPullToRefreshIfNeeded() 116 | } 117 | }) 118 | } 119 | 120 | @ViewBuilder 121 | private func pullToRefreshAnimationView() -> some View { 122 | ZStack(alignment: .top, content: { 123 | animationViewBuilder(pullToRefreshState) 124 | .frame(height: pullToRefreshAnimationHeight) 125 | .modifier(GeometryGroupModifier()) 126 | }) 127 | .opacity(isPullToRefreshEnabled ? 1 : 0) 128 | .frame(height: pullToRefreshAnimationViewHeight(), alignment: .top) 129 | .frame(maxWidth: .infinity) 130 | .clipped() 131 | .offset(x: 0, y: animationOffsetY + offsetAboveRefreshingAnimation) 132 | } 133 | 134 | // MARK: - Private 135 | 136 | private func pullToRefreshAnimationViewHeight() -> CGFloat { 137 | switch pullToRefreshState { 138 | case .idle: return 0 139 | case .pulling: return min(pullToRefreshProgressPoints, pullToRefreshAnimationHeight) 140 | case .refreshing: return pullToRefreshAnimationHeight 141 | case .finishing: return 0 142 | } 143 | } 144 | 145 | private func updateAnimationOffset(contentOffset: CGFloat) { 146 | if contentOffset > 0 { 147 | animationOffsetY = -contentOffset 148 | pullToRefreshProgressPoints = 0 149 | } else { 150 | animationOffsetY = 0 151 | pullToRefreshProgressPoints = -contentOffset 152 | } 153 | updatePullToRefreshPullingState() 154 | } 155 | 156 | private func updatePullToRefreshPullingState() { 157 | switch pullToRefreshState { 158 | case .idle, 159 | .pulling: 160 | if pullToRefreshProgressPoints <= 0.5 { 161 | pullToRefreshState = .idle 162 | } else { 163 | let progress = pullToRefreshProgressPoints / pullToRefreshPullHeight 164 | if progress >= 1.0 { 165 | triggerPullToRefresh() 166 | } else { 167 | pullToRefreshState = .pulling(progress: progress) 168 | } 169 | } 170 | 171 | case .refreshing: 172 | // need to wait for external signal that refreshing has ended 173 | break 174 | 175 | case .finishing: 176 | if pullToRefreshProgressPoints <= 0.5 { 177 | pullToRefreshState = .idle 178 | } else { 179 | pullToRefreshState = .finishing 180 | } 181 | } 182 | } 183 | 184 | private func triggerPullToRefreshIfNeeded() { 185 | guard isPullToRefreshEnabled else { 186 | return 187 | } 188 | switch pullToRefreshState { 189 | case .idle, 190 | .refreshing, 191 | .finishing: 192 | // wrong state 193 | break 194 | 195 | case .pulling(let progress): 196 | if progress >= 1.0 { 197 | triggerPullToRefresh() 198 | } 199 | } 200 | } 201 | 202 | private func triggerPullToRefresh() { 203 | pullToRefreshState = .refreshing 204 | isRefreshing.wrappedValue = true 205 | onRefresh() 206 | UIImpactFeedbackGenerator(style: .medium).impactOccurred() 207 | } 208 | 209 | private func showPullToRefreshAnimationIfNeeded() { 210 | switch pullToRefreshState { 211 | case .idle, 212 | .pulling, 213 | .finishing: 214 | pullToRefreshState = .refreshing 215 | 216 | case .refreshing: 217 | // already refreshing 218 | break 219 | } 220 | } 221 | 222 | private func endPullToRefreshAnimationIfNeeded() { 223 | switch pullToRefreshState { 224 | case .idle: 225 | // should not be here 226 | break 227 | 228 | case .pulling: 229 | // no need to finish - deceleration will do the trick 230 | break 231 | 232 | case .refreshing: 233 | withAnimation(.easeInOut(duration: animationDuration), { 234 | pullToRefreshState = .finishing 235 | }) 236 | 237 | case .finishing: 238 | // already finishing 239 | break 240 | } 241 | } 242 | 243 | } 244 | 245 | // MARK: - Preview 246 | 247 | #Preview(body: { 248 | if #available(iOS 18.0, *) { 249 | PullToRefreshListView18IOS( 250 | pullToRefreshAnimationHeight: 100, 251 | pullToRefreshPullHeight: 100, 252 | isRefreshing: .constant(true), 253 | onRefresh: { 254 | print("Refreshing") 255 | }, 256 | animationViewBuilder: { (state) in 257 | switch state { 258 | case .idle: 259 | Color.clear 260 | case .pulling(let progress): 261 | ProgressView(value: progress, total: 1) 262 | .progressViewStyle(.linear) 263 | case .refreshing: 264 | ProgressView() 265 | .progressViewStyle(.circular) 266 | case .finishing: 267 | ProgressView() 268 | .progressViewStyle(.circular) 269 | } 270 | }, 271 | contentViewBuilder: { _ in 272 | ForEach(0..<5, content: { (item) in 273 | Text("Item \(item)") 274 | }) 275 | }) 276 | } else { 277 | // Fallback on earlier versions 278 | } 279 | }) 280 | -------------------------------------------------------------------------------- /Sources/PullToRefreshSwiftUI/PullToRefreshListViewOldIOS.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Copyright (c) 2024 Shakuro (https://shakuro.com/) 4 | // 5 | // 6 | 7 | import SwiftUI 8 | 9 | public struct PullToRefreshListViewOldIOS: View { 10 | 11 | private let pullToRefreshAnimationHeight: CGFloat 12 | private let animationDuration: TimeInterval 13 | private let offsetAboveRefreshingAnimation: CGFloat 14 | private let showsIndicators: Bool 15 | private let isPullToRefreshEnabled: Bool 16 | private let isRefreshing: Binding 17 | private let onRefresh: () -> Void 18 | private let animationViewBuilder: (_ state: PullToRefreshListViewState) -> AnimationViewType 19 | private let contentViewBuilder: (_ scrollViewSize: CGSize) -> ContentViewType 20 | 21 | @StateObject private var scrollViewState: ScrollViewState2 22 | @State private var topOffset: CGFloat = 0 23 | private let isLogEnabled: Bool = false 24 | 25 | // MARK: - Initialization 26 | 27 | public init(pullToRefreshAnimationHeight: CGFloat, 28 | animationDuration: TimeInterval = 0.3, 29 | showsIndicators: Bool = true, 30 | isPullToRefreshEnabled: Bool = true, 31 | offsetAboveRefreshingAnimation: CGFloat = 0, 32 | isRefreshing: Binding, 33 | onRefresh: @escaping () -> Void, 34 | @ViewBuilder animationViewBuilder: @escaping (_ state: PullToRefreshListViewState) -> AnimationViewType, 35 | @ViewBuilder contentViewBuilder: @escaping (_ scrollViewSize: CGSize) -> ContentViewType) { 36 | self.pullToRefreshAnimationHeight = pullToRefreshAnimationHeight 37 | self.animationDuration = animationDuration 38 | self.offsetAboveRefreshingAnimation = offsetAboveRefreshingAnimation 39 | self.showsIndicators = showsIndicators 40 | self.isPullToRefreshEnabled = isPullToRefreshEnabled 41 | self.isRefreshing = isRefreshing 42 | self.onRefresh = onRefresh 43 | self.animationViewBuilder = animationViewBuilder 44 | self.contentViewBuilder = contentViewBuilder 45 | _scrollViewState = StateObject(wrappedValue: ScrollViewState2(pullToRefreshAnimationHeight: pullToRefreshAnimationHeight)) 46 | } 47 | 48 | // MARK: - UI 49 | 50 | public var body: some View { 51 | let defaultAnimation: Animation = .easeInOut(duration: animationDuration) 52 | ZStack(alignment: .top, content: { 53 | // Animations 54 | VStack(spacing: 0, content: { 55 | Color.clear 56 | .frame(height: offsetAboveRefreshingAnimation) 57 | ZStack(alignment: .center, content: { 58 | animationViewBuilder(scrollViewState.state) 59 | .modifier(GeometryGroupModifier()) 60 | }) 61 | .frame(height: pullToRefreshAnimationHeight) 62 | Color.clear 63 | }) 64 | .opacity(isPullToRefreshEnabled ? 1 : 0) 65 | // List content 66 | GeometryReader(content: { (geometryProxy) in 67 | VStack(spacing: 0, content: { 68 | // view to show pull to refresh animations 69 | // List inset is calculated as safeAreaTopInset + this view height 70 | Color.clear 71 | .frame(height: pullToRefreshAnimationHeight * scrollViewState.progress) 72 | // scrolling direction is not possible to nicely calculate in old ios versions 73 | List(content: { 74 | Color.clear 75 | .frame(height: offsetAboveRefreshingAnimation) 76 | .listRowSeparator(.hidden) 77 | .listRowInsets(EdgeInsets()) 78 | .listRowBackground(Color.clear) 79 | Color.clear 80 | .listRowSeparator(.hidden) 81 | .listRowBackground(Color.clear) 82 | .frame(height: 1) 83 | .listRowInsets(EdgeInsets()) 84 | .readLayoutData(coordinateSpace: .global, onChange: { (data) in 85 | let offsetConclusive = data.frameInCoordinateSpace.minY - topOffset - offsetAboveRefreshingAnimation 86 | if isLogEnabled { 87 | debugPrint("Current offset: \(offsetConclusive) = \(data.frameInCoordinateSpace.minY)" + 88 | " - \(topOffset) - \(offsetAboveRefreshingAnimation)") 89 | } 90 | scrollViewState.contentOffset = offsetConclusive 91 | updateProgressIfNeeded() 92 | stopIfNeeded() 93 | resetReadyTriggeredStateIfNeeded() 94 | startIfNeeded() 95 | }) 96 | contentViewBuilder(geometryProxy.size) 97 | .modifier(GeometryGroupModifier()) 98 | }) 99 | .environment(\.defaultMinListRowHeight, 0) 100 | .listStyle(PlainListStyle()) 101 | }) 102 | .animation(scrollViewState.isDragging ? nil : defaultAnimation, value: scrollViewState.progress) 103 | }) 104 | }) 105 | .readLayoutData(coordinateSpace: .global, onChange: { (data) in 106 | topOffset = data.frameInCoordinateSpace.minY 107 | if isLogEnabled { 108 | debugPrint("Setting topOffset = \(topOffset)") 109 | } 110 | }) 111 | .onAppear(perform: { 112 | scrollViewState.addGestureRecognizer() 113 | }) 114 | .onDisappear(perform: { 115 | scrollViewState.removeGestureRecognizer() 116 | }) 117 | .onChange(of: isRefreshing.wrappedValue, perform: { (isRefreshing) in 118 | if !isRefreshing { 119 | scrollViewState.isRefreshing = false 120 | scrollViewState.isFinishing = true 121 | stopIfNeeded() 122 | resetReadyTriggeredStateIfNeeded() 123 | } 124 | }) 125 | .onChange(of: scrollViewState.isDragging, perform: { (_) in 126 | stopIfNeeded() 127 | resetReadyTriggeredStateIfNeeded() 128 | }) 129 | } 130 | 131 | // MARK: - Private 132 | 133 | private func startIfNeeded() { 134 | if isPullToRefreshEnabled, 135 | scrollViewState.contentOffset > pullToRefreshAnimationHeight, 136 | !scrollViewState.isTriggered && 137 | !scrollViewState.isRefreshing { 138 | 139 | scrollViewState.isTriggered = true 140 | scrollViewState.isRefreshing = true 141 | isRefreshing.wrappedValue = true 142 | onRefresh() 143 | UIImpactFeedbackGenerator(style: .medium).impactOccurred() 144 | } 145 | } 146 | 147 | private func stopIfNeeded() { 148 | if !scrollViewState.isRefreshing && !scrollViewState.isDragging { 149 | scrollViewState.isFinishing = true 150 | Timer.scheduledTimer(withTimeInterval: 0.005, repeats: true, block: { (timer) in 151 | let progressLocal = scrollViewState.progress - 0.03 152 | if progressLocal <= 0 { 153 | scrollViewState.isFinishing = false 154 | scrollViewState.progress = 0 155 | resetReadyTriggeredStateIfNeeded() 156 | timer.invalidate() 157 | } else { 158 | scrollViewState.progress = progressLocal 159 | } 160 | }) 161 | } 162 | } 163 | 164 | private func resetReadyTriggeredStateIfNeeded() { 165 | if scrollViewState.contentOffset <= 1 && 166 | scrollViewState.progress == 0 && 167 | scrollViewState.isTriggered && 168 | !scrollViewState.isRefreshing && 169 | !scrollViewState.isDragging { 170 | 171 | scrollViewState.isTriggered = false 172 | } 173 | } 174 | 175 | private func updateProgressIfNeeded() { 176 | if scrollViewState.isDragging && !scrollViewState.isRefreshing && !scrollViewState.isTriggered && !scrollViewState.isFinishing { 177 | // initial pulling will increase progress to 1; then when drag finished or 178 | // fetch finished stopIfNeeded() will be called where progress will be set to 0. 179 | // isRefreshing check is here because we need to remove conflict between setting progress. 180 | let progress = min(max(scrollViewState.contentOffset / pullToRefreshAnimationHeight, 0), 1) 181 | if progress > scrollViewState.progress { // dragging back to top leads to issues 182 | scrollViewState.progress = progress 183 | } 184 | } 185 | } 186 | 187 | } 188 | 189 | // MARK: - Preview 190 | 191 | #Preview(body: { 192 | PullToRefreshListViewOldIOS( 193 | pullToRefreshAnimationHeight: 100, 194 | isRefreshing: .constant(true), 195 | onRefresh: { 196 | debugPrint("Refreshing") 197 | }, 198 | animationViewBuilder: { (state) in 199 | switch state { 200 | case .idle: 201 | Color.clear 202 | case .pulling(let progress): 203 | ProgressView(value: progress, total: 1) 204 | .progressViewStyle(.linear) 205 | case .refreshing: 206 | ProgressView() 207 | .progressViewStyle(.circular) 208 | case .finishing: 209 | ProgressView() 210 | .progressViewStyle(.circular) 211 | } 212 | }, 213 | contentViewBuilder: { _ in 214 | ForEach(0..<5, content: { (item) in 215 | Text("Item \(item)") 216 | }) 217 | }) 218 | }) 219 | 220 | // MARK: - ScrollViewState 221 | 222 | private class ScrollViewState2: NSObject, ObservableObject, UIGestureRecognizerDelegate { 223 | 224 | @Published var isDragging: Bool = false 225 | var isTriggered: Bool = false 226 | var isRefreshing: Bool = false 227 | var isFinishing: Bool = false 228 | var contentOffset: CGFloat = 0 229 | @Published var progress: CGFloat = 0 230 | 231 | private var panGestureRecognizer: UIPanGestureRecognizer? 232 | 233 | let pullToRefreshAnimationHeight: CGFloat 234 | 235 | var state: PullToRefreshListViewState { 236 | if isRefreshing { 237 | return .refreshing 238 | } else if progress > 0 && !isTriggered && !isFinishing { 239 | return .pulling(progress: progress) 240 | } else if isFinishing { 241 | if isTriggered { 242 | return .pulling(progress: progress) 243 | } else { 244 | return .finishing 245 | } 246 | } else { 247 | return .idle 248 | } 249 | } 250 | 251 | // MARK: - Initialization 252 | 253 | init(pullToRefreshAnimationHeight: CGFloat) { 254 | self.pullToRefreshAnimationHeight = pullToRefreshAnimationHeight 255 | } 256 | 257 | // MARK: - Public 258 | 259 | internal func addGestureRecognizer() { 260 | guard let controller = getRootViewController() else { 261 | return 262 | } 263 | // there is no ability to get isDragging state from SwiftUI ScrollView, 264 | // because ScrollView gesture recognizer intercepts event. 265 | // That's why custom gesture recognizer is added to application window rootViewController view. 266 | let recognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:))) 267 | panGestureRecognizer = recognizer 268 | recognizer.delegate = self 269 | controller.view.addGestureRecognizer(recognizer) 270 | } 271 | 272 | internal func removeGestureRecognizer() { 273 | guard let controller = getRootViewController(), 274 | let recognizer = panGestureRecognizer 275 | else { 276 | return 277 | } 278 | controller.view.removeGestureRecognizer(recognizer) 279 | } 280 | 281 | // MARK: - UIGestureRecognizerDelegate 282 | 283 | internal func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, 284 | shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { 285 | return true 286 | } 287 | 288 | // MARK: - Interface Callbacks 289 | 290 | @objc 291 | private func handlePanGesture(_ recognizer: UIPanGestureRecognizer) { 292 | switch recognizer.state { 293 | 294 | case .possible, 295 | .changed: 296 | break 297 | case .began: 298 | isDragging = true 299 | case .ended, 300 | .cancelled, 301 | .failed: 302 | isDragging = false 303 | @unknown default: 304 | break 305 | } 306 | } 307 | 308 | // MARK: - Private 309 | 310 | private func getRootViewController() -> UIViewController? { 311 | return (UIApplication.shared.connectedScenes.first as? UIWindowScene)?.windows.first?.rootViewController 312 | } 313 | 314 | } 315 | -------------------------------------------------------------------------------- /Sources/PullToRefreshSwiftUI/PullToRefreshScrollView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Copyright (c) 2024 Shakuro (https://shakuro.com/) 4 | // 5 | // 6 | 7 | import SwiftUI 8 | 9 | public enum PullToRefreshScrollViewState { 10 | case idle 11 | case pulling(progress: CGFloat) 12 | case refreshing 13 | case finishing(progress: CGFloat, isTriggered: Bool) 14 | } 15 | 16 | public struct PullToRefreshScrollView: View { 17 | 18 | private let pullToRefreshAnimationHeight: CGFloat 19 | private let animationDuration: TimeInterval 20 | private let showsIndicators: Bool 21 | private let isPullToRefreshEnabled: Bool 22 | private let offsetAboveRefreshingAnimation: CGFloat 23 | private let isRefreshing: Binding 24 | private let onRefresh: () -> Void 25 | private let animationViewBuilder: (_ state: PullToRefreshScrollViewState) -> AnimationViewType 26 | private let contentViewBuilder: (_ scrollViewSize: CGSize) -> ContentViewType 27 | 28 | @StateObject private var scrollViewState: ScrollViewState 29 | 30 | @State private var topOffset: CGFloat = 0 31 | 32 | private let isLogEnabled: Bool = false 33 | 34 | // MARK: - Initialization 35 | 36 | public init(pullToRefreshAnimationHeight: CGFloat, 37 | animationDuration: TimeInterval = 0.3, 38 | showsIndicators: Bool = true, 39 | isPullToRefreshEnabled: Bool = true, 40 | offsetAboveRefreshingAnimation: CGFloat = 0, 41 | isRefreshing: Binding, 42 | onRefresh: @escaping () -> Void, 43 | @ViewBuilder animationViewBuilder: @escaping (_ state: PullToRefreshScrollViewState) -> AnimationViewType, 44 | @ViewBuilder contentViewBuilder: @escaping (_ scrollViewSize: CGSize) -> ContentViewType) { 45 | self.pullToRefreshAnimationHeight = pullToRefreshAnimationHeight 46 | self.animationDuration = animationDuration 47 | self.showsIndicators = showsIndicators 48 | self.isPullToRefreshEnabled = isPullToRefreshEnabled 49 | self.offsetAboveRefreshingAnimation = offsetAboveRefreshingAnimation 50 | self.isRefreshing = isRefreshing 51 | self.onRefresh = onRefresh 52 | self.animationViewBuilder = animationViewBuilder 53 | self.contentViewBuilder = contentViewBuilder 54 | _scrollViewState = StateObject(wrappedValue: ScrollViewState(pullToRefreshAnimationHeight: pullToRefreshAnimationHeight)) 55 | } 56 | 57 | // MARK: - UI 58 | 59 | public var body: some View { 60 | let defaultAnimation: Animation = .easeInOut(duration: animationDuration) 61 | ZStack(alignment: .top, content: { 62 | // Animations 63 | VStack(spacing: 0, content: { 64 | Color.clear 65 | .frame(height: offsetAboveRefreshingAnimation) 66 | ZStack(alignment: .center, content: { 67 | animationViewBuilder(scrollViewState.state) 68 | .modifier(GeometryGroupModifier()) 69 | }) 70 | .frame(height: pullToRefreshAnimationHeight) 71 | Color.clear 72 | }) 73 | .opacity(isPullToRefreshEnabled ? 1 : 0) 74 | // Scroll content 75 | GeometryReader(content: { geometryProxy in 76 | ScrollView(.vertical, showsIndicators: showsIndicators, content: { 77 | VStack(spacing: 0, content: { 78 | Color.clear 79 | .frame(height: offsetAboveRefreshingAnimation) 80 | Color.clear 81 | .frame(height: pullToRefreshAnimationHeight * scrollViewState.progress) 82 | contentViewBuilder(geometryProxy.size) 83 | .modifier(GeometryGroupModifier()) 84 | }) 85 | .animation(scrollViewState.isDragging ? nil : defaultAnimation, value: scrollViewState.progress) 86 | .readLayoutData(coordinateSpace: .global, onChange: { (data) in 87 | let offsetConclusive = data.frameInCoordinateSpace.minY - topOffset 88 | if isLogEnabled { 89 | debugPrint("Current offset: \(offsetConclusive) = \(data.frameInCoordinateSpace.minY) - \(topOffset)") 90 | } 91 | scrollViewState.contentOffset = offsetConclusive 92 | updateProgressIfNeeded() 93 | resetReadyTriggeredStateIfNeeded() 94 | startIfNeeded() 95 | }) 96 | }) 97 | }) 98 | }) 99 | .readLayoutData(coordinateSpace: .global, onChange: { (data) in 100 | topOffset = data.frameInCoordinateSpace.minY 101 | if isLogEnabled { 102 | debugPrint("Setting topOffset = \(topOffset)") 103 | } 104 | }) 105 | .onAppear(perform: { 106 | scrollViewState.addGestureRecognizer() 107 | }) 108 | .onDisappear(perform: { 109 | scrollViewState.removeGestureRecognizer() 110 | }) 111 | .onChange(of: isRefreshing.wrappedValue, perform: { (isRefreshing) in 112 | if !isRefreshing { 113 | scrollViewState.isRefreshing = false 114 | scrollViewState.isFinishing = true 115 | stopIfNeeded() 116 | resetReadyTriggeredStateIfNeeded() 117 | } 118 | }) 119 | .onChange(of: scrollViewState.isDragging, perform: { (_) in 120 | stopIfNeeded() 121 | resetReadyTriggeredStateIfNeeded() 122 | }) 123 | } 124 | 125 | // MARK: - Private 126 | 127 | private func startIfNeeded() { 128 | if isPullToRefreshEnabled, 129 | (scrollViewState.contentOffset * 2) > pullToRefreshAnimationHeight, 130 | !scrollViewState.isTriggered && 131 | !scrollViewState.isRefreshing { 132 | 133 | scrollViewState.isTriggered = true 134 | scrollViewState.isRefreshing = true 135 | isRefreshing.wrappedValue = true 136 | onRefresh() 137 | UIImpactFeedbackGenerator(style: .medium).impactOccurred() 138 | } 139 | } 140 | 141 | private func stopIfNeeded() { 142 | if !scrollViewState.isRefreshing && !scrollViewState.isDragging { 143 | if scrollViewState.progress > 0 { 144 | if scrollViewState.isTriggered { 145 | scrollViewState.isFinishing = true 146 | Timer.scheduledTimer(withTimeInterval: 0.005, repeats: true, block: { (timer) in 147 | let progressLocal = scrollViewState.progress - 0.03 148 | if progressLocal <= 0 { 149 | scrollViewState.isFinishing = false 150 | scrollViewState.progress = 0 151 | resetReadyTriggeredStateIfNeeded() 152 | timer.invalidate() 153 | } else { 154 | scrollViewState.progress = progressLocal 155 | } 156 | }) 157 | } else { 158 | scrollViewState.progress = 0 159 | resetReadyTriggeredStateIfNeeded() 160 | } 161 | } 162 | } 163 | } 164 | 165 | private func resetReadyTriggeredStateIfNeeded() { 166 | if scrollViewState.contentOffset <= 1 && 167 | scrollViewState.progress == 0 && 168 | scrollViewState.isTriggered && 169 | !scrollViewState.isRefreshing && 170 | !scrollViewState.isDragging { 171 | 172 | scrollViewState.isTriggered = false 173 | } 174 | } 175 | 176 | private func updateProgressIfNeeded() { 177 | if !scrollViewState.isRefreshing && !scrollViewState.isTriggered && !scrollViewState.isFinishing { 178 | // initial pulling will increase progress to 1; then when drag finished or 179 | // fetch finished stopIfNeeded() will be called where progress will be set to 0. 180 | // isRefreshing check is here because we need to remove conflict between setting progress. 181 | scrollViewState.progress = min(max((scrollViewState.contentOffset * 2) / pullToRefreshAnimationHeight, 0), 1) 182 | } 183 | } 184 | 185 | } 186 | 187 | // MARK: - Preview 188 | 189 | #Preview(body: { 190 | PullToRefreshScrollView( 191 | pullToRefreshAnimationHeight: 100, 192 | animationDuration: 0.3, 193 | isRefreshing: .constant(true), 194 | onRefresh: { 195 | debugPrint("Refreshing") 196 | }, 197 | animationViewBuilder: { (state) in 198 | switch state { 199 | case .idle: 200 | Color.clear 201 | case .pulling(let progress): 202 | ProgressView(value: progress, total: 1) 203 | .progressViewStyle(.linear) 204 | case .refreshing: 205 | ProgressView() 206 | .progressViewStyle(.circular) 207 | case .finishing(let progress, let isTriggered): 208 | if isTriggered { 209 | ProgressView() 210 | .progressViewStyle(.circular) 211 | } else { 212 | ProgressView(value: progress, total: 1) 213 | .progressViewStyle(.linear) 214 | } 215 | } 216 | }, 217 | contentViewBuilder: { _ in 218 | Color(.lightGray) 219 | .frame(height: 1000) 220 | }) 221 | }) 222 | 223 | // MARK: - ScrollViewState 224 | 225 | private class ScrollViewState: NSObject, ObservableObject, UIGestureRecognizerDelegate { 226 | 227 | @Published var isDragging: Bool = false 228 | var isTriggered: Bool = false 229 | var isRefreshing: Bool = false 230 | var isFinishing: Bool = false 231 | var contentOffset: CGFloat = 0 232 | @Published var progress: CGFloat = 0 233 | 234 | private var panGestureRecognizer: UIPanGestureRecognizer? 235 | 236 | let pullToRefreshAnimationHeight: CGFloat 237 | 238 | var state: PullToRefreshScrollViewState { 239 | if isRefreshing { 240 | return .refreshing 241 | } else if progress > 0 && !isTriggered && !isFinishing { 242 | return .pulling(progress: progress) 243 | } else if isFinishing { 244 | return .finishing(progress: progress, isTriggered: isTriggered) 245 | } else { 246 | return .idle 247 | } 248 | } 249 | 250 | // MARK: - Initialization 251 | 252 | init(pullToRefreshAnimationHeight: CGFloat) { 253 | self.pullToRefreshAnimationHeight = pullToRefreshAnimationHeight 254 | } 255 | 256 | // MARK: - Public 257 | 258 | internal func addGestureRecognizer() { 259 | guard let controller = getRootViewController() else { 260 | return 261 | } 262 | // there is no ability to get isDragging state from SwiftUI ScrollView, 263 | // because ScrollView gesture recognizer intercepts event. 264 | // That's why custom gesture recognizer is added to application window rootViewController view. 265 | let recognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:))) 266 | panGestureRecognizer = recognizer 267 | recognizer.delegate = self 268 | controller.view.addGestureRecognizer(recognizer) 269 | } 270 | 271 | internal func removeGestureRecognizer() { 272 | guard let controller = getRootViewController(), 273 | let recognizer = panGestureRecognizer 274 | else { 275 | return 276 | } 277 | controller.view.removeGestureRecognizer(recognizer) 278 | } 279 | 280 | // MARK: - UIGestureRecognizerDelegate 281 | 282 | internal func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, 283 | shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { 284 | return true 285 | } 286 | 287 | // MARK: - Interface Callbacks 288 | 289 | @objc 290 | private func handlePanGesture(_ recognizer: UIPanGestureRecognizer) { 291 | switch recognizer.state { 292 | 293 | case .possible, 294 | .changed: 295 | break 296 | case .began: 297 | isDragging = true 298 | case .ended, 299 | .cancelled, 300 | .failed: 301 | isDragging = false 302 | @unknown default: 303 | break 304 | } 305 | } 306 | 307 | // MARK: - Private 308 | 309 | private func getRootViewController() -> UIViewController? { 310 | return (UIApplication.shared.connectedScenes.first as? UIWindowScene)?.windows.first?.rootViewController 311 | } 312 | 313 | } 314 | -------------------------------------------------------------------------------- /Sources/PullToRefreshSwiftUI/View+readLayoutData.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Copyright (c) 2024 Shakuro (https://shakuro.com/) 4 | // 5 | // 6 | 7 | import SwiftUI 8 | 9 | struct LayoutData: Equatable { 10 | let size: CGSize 11 | let frameInCoordinateSpace: CGRect 12 | let safeAreaInsets: EdgeInsets 13 | } 14 | 15 | extension View { 16 | 17 | func readLayoutData(coordinateSpace: CoordinateSpace, onChange: @escaping (LayoutData) -> Void) -> some View { 18 | self 19 | .background( 20 | GeometryReader(content: { (geometryProxy) in 21 | Color.clear 22 | .preference(key: SizePreferenceKey.self, 23 | value: LayoutData(size: geometryProxy.size, 24 | frameInCoordinateSpace: geometryProxy.frame(in: coordinateSpace), 25 | safeAreaInsets: geometryProxy.safeAreaInsets)) 26 | }) 27 | ) 28 | .onPreferenceChange(SizePreferenceKey.self, perform: onChange) 29 | } 30 | 31 | } 32 | 33 | private struct SizePreferenceKey: PreferenceKey { 34 | 35 | static var defaultValue: LayoutData = LayoutData(size: .zero, frameInCoordinateSpace: CGRect.zero, safeAreaInsets: EdgeInsets()) 36 | 37 | static func reduce(value: inout LayoutData, nextValue: () -> LayoutData) { } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /Tests/PullToRefreshSwiftUITests/PullToRefreshSwiftUITests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import PullToRefreshSwiftUI 3 | 4 | final class PullToRefreshSwiftUITests: XCTestCase { 5 | func testExample() throws { 6 | // XCTest Documentation 7 | // https://developer.apple.com/documentation/xctest 8 | 9 | // Defining Test Cases and Test Methods 10 | // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods 11 | } 12 | } 13 | --------------------------------------------------------------------------------