diff --git a/Challenge2/Challenge2.xcodeproj/project.pbxproj b/Challenge2/Challenge2.xcodeproj/project.pbxproj new file mode 100644 index 0000000..1467c43 --- /dev/null +++ b/Challenge2/Challenge2.xcodeproj/project.pbxproj @@ -0,0 +1,392 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 55; + objects = { + +/* Begin PBXBuildFile section */ + 4F1204792894741D007C8DA9 /* PersonProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F1204782894741D007C8DA9 /* PersonProgressView.swift */; }; + 4F12047B28948236007C8DA9 /* Gradient+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F12047A28948236007C8DA9 /* Gradient+Extensions.swift */; }; + 4F12047D28948249007C8DA9 /* SendState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F12047C28948249007C8DA9 /* SendState.swift */; }; + 4F1204812894828C007C8DA9 /* AirdropView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F1204802894828C007C8DA9 /* AirdropView.swift */; }; + 4F1204832894829E007C8DA9 /* AirdropTargetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F1204822894829E007C8DA9 /* AirdropTargetView.swift */; }; + 4F1204872894832B007C8DA9 /* AirdropTargetViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F1204862894832B007C8DA9 /* AirdropTargetViewModel.swift */; }; + 4F52C8F8289447FF002500A9 /* Challenge2App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F52C8F7289447FF002500A9 /* Challenge2App.swift */; }; + 4F52C8FA289447FF002500A9 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F52C8F9289447FF002500A9 /* ContentView.swift */; }; + 4F52C8FC28944800002500A9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4F52C8FB28944800002500A9 /* Assets.xcassets */; }; + 4F52C8FF28944800002500A9 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4F52C8FE28944800002500A9 /* Preview Assets.xcassets */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 4F1204782894741D007C8DA9 /* PersonProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersonProgressView.swift; sourceTree = ""; }; + 4F12047A28948236007C8DA9 /* Gradient+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Gradient+Extensions.swift"; sourceTree = ""; }; + 4F12047C28948249007C8DA9 /* SendState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendState.swift; sourceTree = ""; }; + 4F1204802894828C007C8DA9 /* AirdropView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AirdropView.swift; sourceTree = ""; }; + 4F1204822894829E007C8DA9 /* AirdropTargetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AirdropTargetView.swift; sourceTree = ""; }; + 4F1204862894832B007C8DA9 /* AirdropTargetViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AirdropTargetViewModel.swift; sourceTree = ""; }; + 4F52C8F4289447FF002500A9 /* Challenge2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Challenge2.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4F52C8F7289447FF002500A9 /* Challenge2App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Challenge2App.swift; sourceTree = ""; }; + 4F52C8F9289447FF002500A9 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 4F52C8FB28944800002500A9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 4F52C8FE28944800002500A9 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4F52C8F1289447FF002500A9 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 4F120484289482DA007C8DA9 /* Extensions */ = { + isa = PBXGroup; + children = ( + 4F12047A28948236007C8DA9 /* Gradient+Extensions.swift */, + ); + path = Extensions; + sourceTree = ""; + }; + 4F1204882894833A007C8DA9 /* AirdropTargetView */ = { + isa = PBXGroup; + children = ( + 4F1204822894829E007C8DA9 /* AirdropTargetView.swift */, + 4F1204862894832B007C8DA9 /* AirdropTargetViewModel.swift */, + 4F1204782894741D007C8DA9 /* PersonProgressView.swift */, + 4F12047C28948249007C8DA9 /* SendState.swift */, + ); + path = AirdropTargetView; + sourceTree = ""; + }; + 4F12048928948350007C8DA9 /* Views */ = { + isa = PBXGroup; + children = ( + 4F1204802894828C007C8DA9 /* AirdropView.swift */, + 4F1204882894833A007C8DA9 /* AirdropTargetView */, + ); + path = Views; + sourceTree = ""; + }; + 4F52C8EB289447FF002500A9 = { + isa = PBXGroup; + children = ( + 4F52C8F6289447FF002500A9 /* Challenge2 */, + 4F52C8F5289447FF002500A9 /* Products */, + ); + sourceTree = ""; + }; + 4F52C8F5289447FF002500A9 /* Products */ = { + isa = PBXGroup; + children = ( + 4F52C8F4289447FF002500A9 /* Challenge2.app */, + ); + name = Products; + sourceTree = ""; + }; + 4F52C8F6289447FF002500A9 /* Challenge2 */ = { + isa = PBXGroup; + children = ( + 4F52C8F7289447FF002500A9 /* Challenge2App.swift */, + 4F52C8F9289447FF002500A9 /* ContentView.swift */, + 4F12048928948350007C8DA9 /* Views */, + 4F120484289482DA007C8DA9 /* Extensions */, + 4F52C8FB28944800002500A9 /* Assets.xcassets */, + 4F52C8FD28944800002500A9 /* Preview Content */, + ); + path = Challenge2; + sourceTree = ""; + }; + 4F52C8FD28944800002500A9 /* Preview Content */ = { + isa = PBXGroup; + children = ( + 4F52C8FE28944800002500A9 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 4F52C8F3289447FF002500A9 /* Challenge2 */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4F52C90228944800002500A9 /* Build configuration list for PBXNativeTarget "Challenge2" */; + buildPhases = ( + 4F52C8F0289447FF002500A9 /* Sources */, + 4F52C8F1289447FF002500A9 /* Frameworks */, + 4F52C8F2289447FF002500A9 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Challenge2; + productName = Challenge2; + productReference = 4F52C8F4289447FF002500A9 /* Challenge2.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4F52C8EC289447FF002500A9 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1340; + LastUpgradeCheck = 1340; + TargetAttributes = { + 4F52C8F3289447FF002500A9 = { + CreatedOnToolsVersion = 13.4.1; + }; + }; + }; + buildConfigurationList = 4F52C8EF289447FF002500A9 /* Build configuration list for PBXProject "Challenge2" */; + compatibilityVersion = "Xcode 13.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 4F52C8EB289447FF002500A9; + productRefGroup = 4F52C8F5289447FF002500A9 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4F52C8F3289447FF002500A9 /* Challenge2 */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 4F52C8F2289447FF002500A9 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4F52C8FF28944800002500A9 /* Preview Assets.xcassets in Resources */, + 4F52C8FC28944800002500A9 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 4F52C8F0289447FF002500A9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4F52C8FA289447FF002500A9 /* ContentView.swift in Sources */, + 4F12047B28948236007C8DA9 /* Gradient+Extensions.swift in Sources */, + 4F1204792894741D007C8DA9 /* PersonProgressView.swift in Sources */, + 4F12047D28948249007C8DA9 /* SendState.swift in Sources */, + 4F1204872894832B007C8DA9 /* AirdropTargetViewModel.swift in Sources */, + 4F1204812894828C007C8DA9 /* AirdropView.swift in Sources */, + 4F1204832894829E007C8DA9 /* AirdropTargetView.swift in Sources */, + 4F52C8F8289447FF002500A9 /* Challenge2App.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 4F52C90028944800002500A9 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.5; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 4F52C90128944800002500A9 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.5; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 4F52C90328944800002500A9 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"Challenge2/Preview Content\""; + DEVELOPMENT_TEAM = L2FL95P32D; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = me.MattPfeiffer.SwiftUIChallenge2; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 4F52C90428944800002500A9 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"Challenge2/Preview Content\""; + DEVELOPMENT_TEAM = L2FL95P32D; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = me.MattPfeiffer.SwiftUIChallenge2; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4F52C8EF289447FF002500A9 /* Build configuration list for PBXProject "Challenge2" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4F52C90028944800002500A9 /* Debug */, + 4F52C90128944800002500A9 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4F52C90228944800002500A9 /* Build configuration list for PBXNativeTarget "Challenge2" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4F52C90328944800002500A9 /* Debug */, + 4F52C90428944800002500A9 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4F52C8EC289447FF002500A9 /* Project object */; +} diff --git a/Challenge2/Challenge2.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Challenge2/Challenge2.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/Challenge2/Challenge2.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Challenge2/Challenge2.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Challenge2/Challenge2.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Challenge2/Challenge2.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Challenge2/Challenge2/Assets.xcassets/AccentColor.colorset/Contents.json b/Challenge2/Challenge2/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/Challenge2/Challenge2/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Challenge2/Challenge2/Assets.xcassets/AppIcon.appiconset/Contents.json b/Challenge2/Challenge2/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..9221b9b --- /dev/null +++ b/Challenge2/Challenge2/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Challenge2/Challenge2/Assets.xcassets/Contents.json b/Challenge2/Challenge2/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Challenge2/Challenge2/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Challenge2/Challenge2/Assets.xcassets/Katniss.imageset/Contents.json b/Challenge2/Challenge2/Assets.xcassets/Katniss.imageset/Contents.json new file mode 100644 index 0000000..0558bcf --- /dev/null +++ b/Challenge2/Challenge2/Assets.xcassets/Katniss.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "IMG_3167.jpg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Challenge2/Challenge2/Assets.xcassets/Katniss.imageset/IMG_3167.jpg b/Challenge2/Challenge2/Assets.xcassets/Katniss.imageset/IMG_3167.jpg new file mode 100644 index 0000000..677975c Binary files /dev/null and b/Challenge2/Challenge2/Assets.xcassets/Katniss.imageset/IMG_3167.jpg differ diff --git a/Challenge2/Challenge2/Assets.xcassets/Lynyrd.imageset/Contents.json b/Challenge2/Challenge2/Assets.xcassets/Lynyrd.imageset/Contents.json new file mode 100644 index 0000000..bf8f064 --- /dev/null +++ b/Challenge2/Challenge2/Assets.xcassets/Lynyrd.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "IMG_5122.jpg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Challenge2/Challenge2/Assets.xcassets/Lynyrd.imageset/IMG_5122.jpg b/Challenge2/Challenge2/Assets.xcassets/Lynyrd.imageset/IMG_5122.jpg new file mode 100644 index 0000000..74cb0f9 Binary files /dev/null and b/Challenge2/Challenge2/Assets.xcassets/Lynyrd.imageset/IMG_5122.jpg differ diff --git a/Challenge2/Challenge2/Challenge2App.swift b/Challenge2/Challenge2/Challenge2App.swift new file mode 100644 index 0000000..fad334e --- /dev/null +++ b/Challenge2/Challenge2/Challenge2App.swift @@ -0,0 +1,17 @@ +// +// Challenge2App.swift +// Challenge2 +// +// Created by Matt Pfeiffer on 7/29/22. +// + +import SwiftUI + +@main +struct Challenge2App: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} diff --git a/Challenge2/Challenge2/ContentView.swift b/Challenge2/Challenge2/ContentView.swift new file mode 100644 index 0000000..544f862 --- /dev/null +++ b/Challenge2/Challenge2/ContentView.swift @@ -0,0 +1,22 @@ +// +// ContentView.swift +// Challenge2 +// +// Created by Matt Pfeiffer on 7/29/22. +// + +import SwiftUI + +let charcoal = Color.init(white: 0.15) + +struct ContentView: View { + var body: some View { + AirdropView() + } +} + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + ContentView() + } +} diff --git a/Challenge2/Challenge2/Extensions/Gradient+Extensions.swift b/Challenge2/Challenge2/Extensions/Gradient+Extensions.swift new file mode 100644 index 0000000..a99f265 --- /dev/null +++ b/Challenge2/Challenge2/Extensions/Gradient+Extensions.swift @@ -0,0 +1,32 @@ +// +// Gradient+Extensions.swift +// Challenge2 +// +// Created by Matt Pfeiffer on 7/29/22. +// + +import SwiftUI + +public extension Gradient { + static var shiny: Gradient { + Gradient(colors: [ + Color.white.opacity(0.0125), + Color.white.opacity(0.025), + Color.white.opacity(0.05), + Color.white.opacity(0.1), + Color.white.opacity(0.2), + Color.white.opacity(0.25), + Color.white.opacity(0.375), + Color.white.opacity(0.5), + Color.white.opacity(0.75), + Color.white.opacity(0.5), + Color.white.opacity(0.375), + Color.white.opacity(0.25), + Color.white.opacity(0.175), + Color.white.opacity(0.1), + Color.white.opacity(0.05), + Color.white.opacity(0.025), + Color.white.opacity(0.0125), + ]) + } +} diff --git a/Challenge2/Challenge2/Preview Content/Preview Assets.xcassets/Contents.json b/Challenge2/Challenge2/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Challenge2/Challenge2/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Challenge2/Challenge2/Views/AirdropTargetView/AirdropTargetView.swift b/Challenge2/Challenge2/Views/AirdropTargetView/AirdropTargetView.swift new file mode 100644 index 0000000..a56ddba --- /dev/null +++ b/Challenge2/Challenge2/Views/AirdropTargetView/AirdropTargetView.swift @@ -0,0 +1,50 @@ +// +// AirdropTargetView.swift +// Challenge2 +// +// Created by Matt Pfeiffer on 7/29/22. +// + +import SwiftUI + +struct AirdropTargetView: View { + @ObservedObject var viewModel: AirdropTargetViewModel + + init(name: String, image: Image? = nil) { + viewModel = AirdropTargetViewModel(name: name, image: image) + } + + var body: some View { + ZStack { + + VStack(spacing: 2) { + PersonProgressView(image: viewModel.image, + progress: viewModel.progress, + sendState: viewModel.sendState) + .frame(width: 150, height: 150) + .padding(.bottom, 10) + + Text("\(viewModel.name)'s iPhone") + .foregroundColor(.white) + .font(.system(size: 14)) + + Text(viewModel.stateText) + .opacity(viewModel.opacity) + .foregroundColor(viewModel.sendState.color) + .font(.system(size: 14)) + } + .contentShape(Rectangle()) + .onTapGesture { + viewModel.simulateInitiate() + } + } + .onDisappear { + viewModel.timer?.invalidate() + } + } +} +struct AirdropTargetView_Previews: PreviewProvider { + static var previews: some View { + AirdropTargetView(name: "Mock Name") + } +} diff --git a/Challenge2/Challenge2/Views/AirdropTargetView/AirdropTargetViewModel.swift b/Challenge2/Challenge2/Views/AirdropTargetView/AirdropTargetViewModel.swift new file mode 100644 index 0000000..0b1cf91 --- /dev/null +++ b/Challenge2/Challenge2/Views/AirdropTargetView/AirdropTargetViewModel.swift @@ -0,0 +1,85 @@ +// +// AirdropTargetViewModel.swift +// Challenge2 +// +// Created by Matt Pfeiffer on 7/29/22. +// + +import SwiftUI + +class AirdropTargetViewModel: ObservableObject { + @Published var sendState: AirdropSendState = .preSend + @Published var progress: CGFloat = 0.0 + @Published var opacity: Double = 1.0 + + var name: String + var image: Image? + + var timer: Timer? + + var stateText: String { + switch sendState { + case .preSend: + return "from Matt" + case .connecting: + return "Waiting..." + case .inProgress: + return "Sending..." + case .done: + return "Sent" + } + } + + init(name: String, image: Image? = nil) { + self.name = name + self.image = image + } + + func simulateInitiate() { + progress = 0.0 + sendState = .connecting + withAnimation(.easeInOut(duration: 1.0).repeatForever(autoreverses: true)) { + opacity = 0.0 + } + + let waitTime: TimeInterval = 2.0 + DispatchQueue.main.asyncAfter(deadline: .now() + waitTime) { + self.simulateConnected() + } + } + + func simulateConnected() { + sendState = .inProgress + withAnimation(.easeInOut(duration: 0.1)) { + self.opacity = 1.0 + } + + timer = Timer.scheduledTimer(timeInterval: 0.01, + target: self, + selector: #selector(stepProgress), + userInfo: nil, + repeats: true) + } + + @objc func stepProgress() { + DispatchQueue.main.async { + self.progress += 0.005 + + + + if self.progress > 1.0 { + self.simulateCompleted() + } + } + } + + func simulateCompleted() { + timer?.invalidate() + + // slight delay so that the progress finishes before fadeout + let waitTime: TimeInterval = 0.1 + DispatchQueue.main.asyncAfter(deadline: .now() + waitTime) { + self.sendState = .done + } + } +} diff --git a/Challenge2/Challenge2/Views/AirdropTargetView/PersonProgressView.swift b/Challenge2/Challenge2/Views/AirdropTargetView/PersonProgressView.swift new file mode 100644 index 0000000..8015e0a --- /dev/null +++ b/Challenge2/Challenge2/Views/AirdropTargetView/PersonProgressView.swift @@ -0,0 +1,83 @@ +// +// PersonProgressView.swift +// Challenge2 +// +// Created by Matt Pfeiffer on 7/29/22. +// + +import SwiftUI + +struct PersonProgressView: View { + var image: Image? = Image("Lynyrd") + var progress: CGFloat = 0.5 + var sendState: AirdropSendState = .inProgress + + @State private var isAnimating: Bool = false + + var body: some View { + GeometryReader { geo in + let lineWidth = geo.size.width * 0.03 + let personWidth = geo.size.width * 0.5 + + Circle() + .fill(.gray) + .padding(lineWidth) + .overlay( + ZStack { + + if sendState != .done { + Circle() + .stroke(Color.gray, lineWidth: lineWidth) + + Circle() + .trim(from: 1.0 - progress, to: 1.0) + .rotation(.degrees(90)) + .stroke(Color.blue, lineWidth: lineWidth) + .rotation3DEffect(Angle(degrees: 180), axis: (x: 1.0, y: 0.0, z: 0.0)) + } + + if let image = image { + image + .resizable() + .frame(width: geo.size.width * 0.95, + height: geo.size.width * 0.95) + .clipShape(Circle()) + } else { + Image(systemName: "person.fill") + .resizable() + .frame(width: personWidth, height: personWidth * 1.1) + .aspectRatio(contentMode: .fill) + .foregroundColor(charcoal) + .offset(y: personWidth * 0.2) + .padding(personWidth * 0.2) + .clipShape(Circle()) + } + + if sendState == .done { + LinearGradient(gradient: .shiny, + startPoint: .leading, + endPoint: .trailing) + .offset(x: isAnimating ? geo.size.width : -geo.size.width) + .rotationEffect(Angle(degrees: -45)) + .clipShape(Circle()) + .padding(lineWidth) + .onAppear() { + withAnimation(.linear(duration: 1.0)){ + isAnimating.toggle() + } + } + } + } + .animation(.easeIn(duration: 1.0), value: sendState) + ) + } + } +} + +struct PersonProgressView_Previews: PreviewProvider { + static var previews: some View { + PersonProgressView() + .padding() + .background(charcoal) + } +} diff --git a/Challenge2/Challenge2/Views/AirdropTargetView/SendState.swift b/Challenge2/Challenge2/Views/AirdropTargetView/SendState.swift new file mode 100644 index 0000000..74c9627 --- /dev/null +++ b/Challenge2/Challenge2/Views/AirdropTargetView/SendState.swift @@ -0,0 +1,39 @@ +// +// SendState.swift +// Challenge2 +// +// Created by Matt Pfeiffer on 7/29/22. +// + +import SwiftUI + +enum AirdropSendState { + case preSend, connecting, inProgress, done + + var color: Color { + switch self { + case .preSend: + return .white + case .connecting: + return .gray + case .inProgress: + return .gray + case .done: + return .blue + } + } + + var opacity: Double { + if self == .connecting { + return 0.0 + } + return 1.0 + } + + var animation: Animation? { + if self == .connecting { + return .easeInOut(duration: 1.0).repeatForever(autoreverses: true) + } + return nil + } +} diff --git a/Challenge2/Challenge2/Views/AirdropView.swift b/Challenge2/Challenge2/Views/AirdropView.swift new file mode 100644 index 0000000..fe51c76 --- /dev/null +++ b/Challenge2/Challenge2/Views/AirdropView.swift @@ -0,0 +1,41 @@ +// +// AirdropView.swift +// Challenge2 +// +// Created by Matt Pfeiffer on 7/29/22. +// + +import SwiftUI + +struct AirdropView: View { + let targets = [AirdropTarget(image: Image("Lynyrd"), name: "Lynyrd"), + AirdropTarget(image: Image("Katniss"), name: "Katniss"), + AirdropTarget(name: "Random Guy")] + + var body: some View { + ZStack { + charcoal + ScrollView(.horizontal) { + HStack(spacing: 20) { + ForEach(targets, id: \.id) { target in + AirdropTargetView(name: target.name, image: target.image) + .padding() + } + } + } + } + .ignoresSafeArea() + } + + struct AirdropTarget { + var id = UUID() + var image: Image? + var name: String + } +} + +struct AirdropView_Previews: PreviewProvider { + static var previews: some View { + AirdropView() + } +}