├── mac.png ├── .DS_Store ├── cover.png ├── navBar.png ├── tabBar.png ├── SwiftUI for iOS 15 ├── .DS_Store ├── Assets.xcassets │ ├── Contents.json │ ├── Avatars │ │ ├── Contents.json │ │ ├── .DS_Store │ │ ├── Avatar 1.imageset │ │ │ ├── Avatar 1.png │ │ │ └── Contents.json │ │ ├── Avatar 2.imageset │ │ │ ├── Avatar 2.png │ │ │ └── Contents.json │ │ ├── Avatar 3.imageset │ │ │ ├── Avatar 3.png │ │ │ └── Contents.json │ │ └── Avatar Default.imageset │ │ │ ├── Avatar Default.jpg │ │ │ └── Contents.json │ ├── Blobs │ │ ├── Contents.json │ │ ├── .DS_Store │ │ └── Blob 1.imageset │ │ │ ├── Contents.json │ │ │ ├── Blob 1 Dark.pdf │ │ │ └── Blob 1.pdf │ ├── Colors │ │ ├── Contents.json │ │ ├── Background.colorset │ │ │ └── Contents.json │ │ └── Shadow.colorset │ │ │ └── Contents.json │ ├── Logos │ │ ├── Contents.json │ │ ├── .DS_Store │ │ ├── Logo 1.imageset │ │ │ ├── Logo 1.jpg │ │ │ └── Contents.json │ │ ├── Logo 2.imageset │ │ │ ├── Logo 2.jpg │ │ │ └── Contents.json │ │ ├── Logo 3.imageset │ │ │ ├── Logo 3.jpg │ │ │ └── Contents.json │ │ └── Logo 4.imageset │ │ │ ├── Logo 4.jpg │ │ │ └── Contents.json │ ├── Waves │ │ ├── Contents.json │ │ ├── .DS_Store │ │ ├── Waves 1.imageset │ │ │ ├── Contents.json │ │ │ ├── Waves 1.pdf │ │ │ └── Waves 1 Dark.pdf │ │ └── Waves 2.imageset │ │ │ ├── Contents.json │ │ │ ├── Waves 2.pdf │ │ │ └── Waves 2 Dark.pdf │ ├── Backgrounds │ │ ├── Contents.json │ │ ├── .DS_Store │ │ ├── Background 1.imageset │ │ │ ├── Background 1.png │ │ │ └── Contents.json │ │ ├── Background 2.imageset │ │ │ ├── Background 2.png │ │ │ └── Contents.json │ │ ├── Background 3.imageset │ │ │ ├── Background 3.png │ │ │ └── Contents.json │ │ ├── Background 4.imageset │ │ │ ├── Background 4.png │ │ │ └── Contents.json │ │ ├── Background 5.imageset │ │ │ ├── Background 5.png │ │ │ └── Contents.json │ │ ├── Background 6.imageset │ │ │ ├── Background 6.png │ │ │ └── Contents.json │ │ ├── Background 7.imageset │ │ │ ├── Background 7.png │ │ │ └── Contents.json │ │ ├── Background 8.imageset │ │ │ ├── Background 8.png │ │ │ └── Contents.json │ │ ├── Background 9.imageset │ │ │ ├── Background 9.png │ │ │ └── Contents.json │ │ └── Background 10.imageset │ │ │ ├── Background 10.png │ │ │ └── Contents.json │ ├── Illustrations │ │ ├── Contents.json │ │ ├── .DS_Store │ │ ├── Illustration 1.imageset │ │ │ ├── Illustration 1.png │ │ │ └── Contents.json │ │ ├── Illustration 2.imageset │ │ │ ├── Illustration 2.png │ │ │ └── Contents.json │ │ ├── Illustration 3.imageset │ │ │ ├── Illustration 3.png │ │ │ └── Contents.json │ │ ├── Illustration 4.imageset │ │ │ ├── Illustration 4.png │ │ │ └── Contents.json │ │ ├── Illustration 5.imageset │ │ │ ├── Illustration 5.png │ │ │ └── Contents.json │ │ ├── Illustration 6.imageset │ │ │ ├── Illustration 6.png │ │ │ └── Contents.json │ │ ├── Illustration 7.imageset │ │ │ ├── Illustration 7.png │ │ │ └── Contents.json │ │ ├── Illustration 8.imageset │ │ │ ├── Illustration 8.png │ │ │ └── Contents.json │ │ ├── Illustration 9.imageset │ │ │ ├── Illustration 9.png │ │ │ └── Contents.json │ │ └── Illustration 10.imageset │ │ │ ├── Illustration 10.png │ │ │ └── Contents.json │ ├── .DS_Store │ ├── AppIcon.appiconset │ │ ├── iPad_20pt.png │ │ ├── iPad_29pt.png │ │ ├── iPad_40pt.png │ │ ├── iPad_76pt.png │ │ ├── App Icon iOS.png │ │ ├── iPad_20pt@2x.png │ │ ├── iPad_29pt@2x.png │ │ ├── iPad_40@2x.png │ │ ├── iPad_76@2x.png │ │ ├── iPhone_20@2x.png │ │ ├── iPhone_29pt.png │ │ ├── iPad_83.5pt@2x.png │ │ ├── iPhone_20pt@3x.png │ │ ├── iPhone_29pt@2x.png │ │ ├── iPhone_29pt@3x.png │ │ ├── iPhone_40pt@2x.png │ │ ├── iPhone_40pt@3x.png │ │ ├── iPhone_60pt@2x.png │ │ ├── iPhone_60pt@3x.png │ │ └── Contents.json │ └── AccentColor.colorset │ │ └── Contents.json ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json ├── Model │ ├── Address.swift │ ├── Model.swift │ ├── Suggestion.swift │ ├── Topic.swift │ ├── PreferenceKeys.swift │ ├── Coin.swift │ ├── Handbook.swift │ ├── Tab.swift │ ├── CourseSection.swift │ └── Course.swift ├── Styles │ ├── Animations.swift │ ├── AnimatableFontModifier.swift │ ├── InputStyle.swift │ ├── Styles.swift │ └── AngularButtonStyle.swift ├── SwiftUI_for_iOS_15App.swift ├── Views │ ├── Modals │ │ ├── MatchedView.swift │ │ ├── ModalView.swift │ │ ├── SignUpView.swift │ │ └── SignInView.swift │ ├── Main │ │ ├── NotificationsView.swift │ │ ├── ExploreView.swift │ │ ├── LibraryView.swift │ │ └── HomeView.swift │ ├── Sheets │ │ ├── SearchView.swift │ │ └── AccountView.swift │ └── Detail │ │ ├── SectionView.swift │ │ └── CourseView.swift ├── Components │ ├── Items │ │ ├── ListRow.swift │ │ ├── SmallCourseItem.swift │ │ ├── SectionRow.swift │ │ ├── CertificateView.swift │ │ ├── HandbookItem.swift │ │ ├── FeaturedItem.swift │ │ └── CourseItem.swift │ ├── Graphics │ │ ├── HexagonView.swift │ │ ├── CircularView.swift │ │ └── BlobView.swift │ └── Buttons │ │ ├── AvatarView.swift │ │ └── PlayView.swift └── Navigation │ ├── ContentView.swift │ ├── NavigationBar.swift │ └── TabBar.swift ├── SwiftUI for iOS 15.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcuserdata │ │ └── joaocarlosmagalhaes.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcuserdata │ └── joaocarlosmagalhaes.xcuserdatad │ ├── xcschemes │ └── xcschememanagement.plist │ └── xcdebugger │ └── Breakpoints_v2.xcbkptlist ├── SwiftUI for iOS 15UITests ├── SwiftUI_for_iOS_15UITestsLaunchTests.swift └── SwiftUI_for_iOS_15UITests.swift ├── SwiftUI for iOS 15Tests └── SwiftUI_for_iOS_15Tests.swift └── README.md /mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/mac.png -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/.DS_Store -------------------------------------------------------------------------------- /cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/cover.png -------------------------------------------------------------------------------- /navBar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/navBar.png -------------------------------------------------------------------------------- /tabBar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/tabBar.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/.DS_Store -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Avatars/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Blobs/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Colors/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Logos/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Waves/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/.DS_Store -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Blobs/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Blobs/.DS_Store -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Logos/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Logos/.DS_Store -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Waves/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Waves/.DS_Store -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Avatars/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Avatars/.DS_Store -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Backgrounds/.DS_Store -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Illustrations/.DS_Store -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPad_20pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPad_20pt.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPad_29pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPad_29pt.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPad_40pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPad_40pt.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPad_76pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPad_76pt.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Logos/Logo 1.imageset/Logo 1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Logos/Logo 1.imageset/Logo 1.jpg -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Logos/Logo 2.imageset/Logo 2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Logos/Logo 2.imageset/Logo 2.jpg -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Logos/Logo 3.imageset/Logo 3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Logos/Logo 3.imageset/Logo 3.jpg -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Logos/Logo 4.imageset/Logo 4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Logos/Logo 4.imageset/Logo 4.jpg -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/App Icon iOS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/App Icon iOS.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPad_20pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPad_20pt@2x.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPad_29pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPad_29pt@2x.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPad_40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPad_40@2x.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPad_76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPad_76@2x.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPhone_20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPhone_20@2x.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPhone_29pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPhone_29pt.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPad_83.5pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPad_83.5pt@2x.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPhone_20pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPhone_20pt@3x.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPhone_29pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPhone_29pt@2x.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPhone_29pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPhone_29pt@3x.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPhone_40pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPhone_40pt@2x.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPhone_40pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPhone_40pt@3x.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPhone_60pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPhone_60pt@2x.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPhone_60pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/iPhone_60pt@3x.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Avatars/Avatar 1.imageset/Avatar 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Avatars/Avatar 1.imageset/Avatar 1.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Avatars/Avatar 2.imageset/Avatar 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Avatars/Avatar 2.imageset/Avatar 2.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Avatars/Avatar 3.imageset/Avatar 3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Avatars/Avatar 3.imageset/Avatar 3.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Avatars/Avatar Default.imageset/Avatar Default.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Avatars/Avatar Default.imageset/Avatar Default.jpg -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 1.imageset/Background 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 1.imageset/Background 1.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 2.imageset/Background 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 2.imageset/Background 2.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 3.imageset/Background 3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 3.imageset/Background 3.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 4.imageset/Background 4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 4.imageset/Background 4.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 5.imageset/Background 5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 5.imageset/Background 5.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 6.imageset/Background 6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 6.imageset/Background 6.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 7.imageset/Background 7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 7.imageset/Background 7.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 8.imageset/Background 8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 8.imageset/Background 8.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 9.imageset/Background 9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 9.imageset/Background 9.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 10.imageset/Background 10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 10.imageset/Background 10.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 1.imageset/Illustration 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 1.imageset/Illustration 1.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 2.imageset/Illustration 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 2.imageset/Illustration 2.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 3.imageset/Illustration 3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 3.imageset/Illustration 3.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 4.imageset/Illustration 4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 4.imageset/Illustration 4.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 5.imageset/Illustration 5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 5.imageset/Illustration 5.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 6.imageset/Illustration 6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 6.imageset/Illustration 6.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 7.imageset/Illustration 7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 7.imageset/Illustration 7.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 8.imageset/Illustration 8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 8.imageset/Illustration 8.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 9.imageset/Illustration 9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 9.imageset/Illustration 9.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 10.imageset/Illustration 10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 10.imageset/Illustration 10.png -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Model/Address.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Address.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 07/06/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct Address: Identifiable, Decodable{ 11 | var id: Int 12 | var country: String 13 | } 14 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15.xcodeproj/project.xcworkspace/xcuserdata/joaocarlosmagalhaes.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncarlosofficial/SwiftUI-for-iOS-15/HEAD/SwiftUI for iOS 15.xcodeproj/project.xcworkspace/xcuserdata/joaocarlosmagalhaes.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /SwiftUI for iOS 15.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Styles/Animations.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Animations.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 31/03/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | extension Animation { 11 | static let openCard = Animation.spring(response: 0.5, dampingFraction: 0.7) 12 | static let closeCard = Animation.spring(response: 0.6, dampingFraction: 0.9) 13 | } 14 | 15 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Model/Model.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Model.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 04/04/22. 6 | // 7 | 8 | import SwiftUI 9 | import Combine 10 | 11 | class Model: ObservableObject { 12 | @Published var showDetail : Bool = false 13 | @Published var selectedModal: Modal = .signIn 14 | } 15 | 16 | enum Modal: String { 17 | case signUp 18 | case signIn 19 | } 20 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Model/Suggestion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Suggestion.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 25/04/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct Suggestion: Identifiable{ 11 | let id = UUID() 12 | var text: String 13 | } 14 | 15 | var suggestions = [ 16 | Suggestion(text: "SwiftUI"), 17 | Suggestion(text: "React"), 18 | Suggestion(text: "Design") 19 | ] 20 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Logos/Logo 1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Logo 1.jpg", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Logos/Logo 2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Logo 2.jpg", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Logos/Logo 3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Logo 3.jpg", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Logos/Logo 4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Logo 4.jpg", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Avatars/Avatar 1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Avatar 1.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Avatars/Avatar 2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Avatar 2.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Avatars/Avatar 3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Avatar 3.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Avatars/Avatar Default.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Avatar Default.jpg", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Background 1.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Background 2.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Background 3.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Background 4.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Background 5.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 6.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Background 6.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 7.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Background 7.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 8.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Background 8.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 9.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Background 9.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/SwiftUI_for_iOS_15App.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftUI_for_iOS_15App.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 27/01/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct SwiftUI_for_iOS_15App: App { 12 | @StateObject var model = Model() 13 | 14 | var body: some Scene { 15 | WindowGroup { 16 | ContentView() 17 | .environmentObject(model) 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Backgrounds/Background 10.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Background 10.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Illustration 1.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 10.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Illustration 10.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Illustration 2.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Illustration 3.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Illustration 4.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Illustration 5.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 6.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Illustration 6.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 7.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Illustration 7.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 8.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Illustration 8.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Illustrations/Illustration 9.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Illustration 9.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Model/Topic.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Topic.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 08/06/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct Topic: Identifiable { 11 | let id = UUID() 12 | var title: String 13 | var icon: String 14 | } 15 | 16 | var topics = [ 17 | Topic(title: "iOS Development", icon: "iphone"), 18 | Topic(title: "UI Design", icon: "eyedropper"), 19 | Topic(title: "Web development", icon: "laptopcomputer") 20 | ] 21 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15.xcodeproj/xcuserdata/joaocarlosmagalhaes.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SwiftUI for iOS 15.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Views/Modals/MatchedView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MatchedView.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 31/03/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct MatchedView: View { 11 | @Namespace var namespace 12 | @State var show = false 13 | 14 | var body: some View { 15 | ZStack { 16 | if !show { 17 | } else { 18 | 19 | } 20 | } 21 | } 22 | } 23 | 24 | struct MatchedView_Previews: PreviewProvider { 25 | static var previews: some View { 26 | MatchedView() 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Model/PreferenceKeys.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PreferenceKeys.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 31/03/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | 11 | struct ScrollPreferenceKey: PreferenceKey { 12 | static var defaultValue: CGFloat = 0 13 | static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { 14 | value = nextValue() 15 | } 16 | } 17 | 18 | struct CirclePreferenceKey: PreferenceKey { 19 | static var defaultValue: CGFloat = 0 20 | static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { 21 | value = nextValue() 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Components/Items/ListRow.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ListRow.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 08/06/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ListRow: View { 11 | var topic: Topic = topics[0] 12 | 13 | var body: some View { 14 | HStack(spacing: 16) { 15 | Image(systemName: topic.icon) 16 | .frame(width: 36, height: 36) 17 | .background(.ultraThinMaterial) 18 | .mask(Circle()) 19 | Text(topic.title) 20 | .fontWeight(.semibold) 21 | Spacer() 22 | } 23 | } 24 | } 25 | 26 | struct ListRow_Previews: PreviewProvider { 27 | static var previews: some View { 28 | ListRow() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Model/Coin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Coin.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 07/06/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct Coin: Identifiable, Decodable { 11 | var id: Int 12 | var coin_name: String 13 | var acronym: String 14 | var logo: String 15 | } 16 | 17 | class CoinModel: ObservableObject { 18 | @Published var coins: [Coin] = [] 19 | 20 | @MainActor 21 | func fetchCoins() async { 22 | do { 23 | let url = URL(string: "https://random-data-api.com/api/crypto_coin/random_crypto_coin?size=10")! 24 | let (data, _) = try await URLSession.shared.data(from: url) 25 | coins = try JSONDecoder().decode([Coin].self, from: data) 26 | } catch { 27 | print("Error") 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.835", 9 | "green" : "0.204", 10 | "red" : "0.384" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "1.000", 27 | "green" : "0.620", 28 | "red" : "0.369" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Colors/Background.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0xFF", 9 | "green" : "0xF6", 10 | "red" : "0xF1" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0.294", 27 | "green" : "0.145", 28 | "red" : "0.145" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Colors/Shadow.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.486", 9 | "green" : "0.165", 10 | "red" : "0.271" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0.000", 27 | "green" : "0.000", 28 | "red" : "0.000" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Styles/AnimatableFontModifier.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnimatableFontModifier.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 31/03/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct AnimatableFontModifier: AnimatableModifier { 11 | var size: Double 12 | var weight: Font.Weight = .regular 13 | var design: Font.Design = .default 14 | 15 | var animatableData: Double { 16 | get { size } 17 | set { size = newValue} 18 | } 19 | 20 | func body(content: Content) -> some View { 21 | content 22 | .font(.system(size: size, weight: weight, design: design)) 23 | } 24 | } 25 | 26 | extension View { 27 | func animatableFont(size: Double, weight: Font.Weight = .regular, design: Font.Design = .default) -> some View{ 28 | self.modifier(AnimatableFontModifier(size: size, weight: weight, design: design)) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Model/Handbook.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Handbook.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 08/06/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct Handbook: Identifiable { 11 | let id = UUID() 12 | var title: String 13 | var subtitle: String 14 | var text: String 15 | var logo: String 16 | var image: String 17 | var color1: Color 18 | var color2: Color 19 | } 20 | 21 | var handbooks = [ 22 | Handbook(title: "SwiftUI Handbook", subtitle: "80 sections - 9 hours", text: "A comprehensive series of tutorials covering Xcode, SwiftUI and all the layout and development techniques", logo: "Logo 1", image: "Illustration 1", color1: .teal, color2: .blue), 23 | Handbook(title: "React Advanced Handbook", subtitle: "30 sections - 3 hours", text: "A comprehensive guide for an overview of the React library and all its basics", logo: "Logo 1", image: "Illustration 2", color1: .purple, color2: .pink) 24 | ] 25 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15.xcodeproj/xcuserdata/joaocarlosmagalhaes.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 9 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15UITests/SwiftUI_for_iOS_15UITestsLaunchTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftUI_for_iOS_15UITestsLaunchTests.swift 3 | // SwiftUI for iOS 15UITests 4 | // 5 | // Created by João Carlos Magalhães on 27/01/22. 6 | // 7 | 8 | import XCTest 9 | 10 | class SwiftUI_for_iOS_15UITestsLaunchTests: XCTestCase { 11 | 12 | override class var runsForEachTargetApplicationUIConfiguration: Bool { 13 | true 14 | } 15 | 16 | override func setUpWithError() throws { 17 | continueAfterFailure = false 18 | } 19 | 20 | func testLaunch() throws { 21 | let app = XCUIApplication() 22 | app.launch() 23 | 24 | // Insert steps here to perform after app launch but before taking a screenshot, 25 | // such as logging into a test account or navigating somewhere in the app 26 | 27 | let attachment = XCTAttachment(screenshot: app.screenshot()) 28 | attachment.name = "Launch Screen" 29 | attachment.lifetime = .keepAlways 30 | add(attachment) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Components/Graphics/HexagonView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HexagonView.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 29/03/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct HexagonView: View { 11 | var body: some View { 12 | Canvas { context, size in 13 | context.draw(Text("DesignCode").font(.largeTitle), at: CGPoint(x: 50, y: 20)) 14 | context.fill(Path(ellipseIn: CGRect(x: 20, y: 30, width: 100, height: 100)), with: .color(.pink)) 15 | context.draw(Image("Blob 1"), in: CGRect(x: 0, y: 0, width: 200, height: 200)) 16 | context.draw(Image(systemName: "hexagon.fill"), in: CGRect(x: 0, y: 0, width: 200, height: 200)) 17 | } 18 | .frame(width: 200, height: 212) 19 | .foregroundStyle(.linearGradient(colors: [.pink, .blue], startPoint: .topLeading, endPoint: .bottomTrailing)) 20 | } 21 | } 22 | 23 | struct HexagonView_Previews: PreviewProvider { 24 | static var previews: some View { 25 | HexagonView() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Model/Tab.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Tab.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 30/03/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct TabItem: Identifiable{ 11 | var id = UUID() 12 | var text: String 13 | var icon: String 14 | var tab: Tab 15 | var color: Color 16 | } 17 | 18 | var tabItems = [ 19 | TabItem(text: "Learn Now", icon: "house", tab: .home, color: .teal), 20 | TabItem(text: "Explore", icon: "magnifyingglass", tab: .explore, color: .blue), 21 | TabItem(text: "Notifications", icon: "bell", tab: .notifications, color: .red), 22 | TabItem(text: "Library", icon: "rectangle.stack", tab: .library, color: .pink) 23 | ] 24 | 25 | enum Tab: String{ 26 | case home 27 | case explore 28 | case notifications 29 | case library 30 | } 31 | 32 | struct TabPreferenceKey: PreferenceKey { 33 | static var defaultValue: CGFloat = 0 34 | static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { 35 | value = nextValue() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Styles/InputStyle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InputStyle.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 01/05/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct InputStyle: ViewModifier { 11 | var icon: String 12 | 13 | func body(content: Content) -> some View { 14 | content 15 | .padding(15) 16 | .padding(.leading, 40) 17 | .background(.thinMaterial) 18 | .mask(RoundedRectangle(cornerRadius: 20)) 19 | .strokeStyle(cornerRadius: 20) 20 | .overlay( 21 | Image(systemName: icon) 22 | .frame(width: 36, height: 36) 23 | .background(.thinMaterial) 24 | .cornerRadius(14) 25 | .frame(maxWidth: .infinity, alignment: .leading) 26 | .padding(8) 27 | ) 28 | } 29 | } 30 | 31 | extension View { 32 | func inputStyle(icon: String = "mail") -> some View { 33 | modifier(InputStyle(icon: icon)) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15Tests/SwiftUI_for_iOS_15Tests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftUI_for_iOS_15Tests.swift 3 | // SwiftUI for iOS 15Tests 4 | // 5 | // Created by João Carlos Magalhães on 27/01/22. 6 | // 7 | 8 | import XCTest 9 | @testable import SwiftUI_for_iOS_15 10 | 11 | class SwiftUI_for_iOS_15Tests: XCTestCase { 12 | 13 | override func setUpWithError() throws { 14 | // Put setup code here. This method is called before the invocation of each test method in the class. 15 | } 16 | 17 | override func tearDownWithError() throws { 18 | // Put teardown code here. This method is called after the invocation of each test method in the class. 19 | } 20 | 21 | func testExample() throws { 22 | // This is an example of a functional test case. 23 | // Use XCTAssert and related functions to verify your tests produce the correct results. 24 | } 25 | 26 | func testPerformanceExample() throws { 27 | // This is an example of a performance test case. 28 | self.measure { 29 | // Put the code you want to measure the time of here. 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Components/Graphics/CircularView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CircularView.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 08/06/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct CircularView: View { 11 | var value: CGFloat = 0.2 12 | var lineWidth: Double = 4 13 | @State var appear = false 14 | 15 | var body: some View { 16 | Circle() 17 | .trim(from: 0, to: appear ? value : 0) 18 | .stroke(style: StrokeStyle(lineWidth: lineWidth, lineCap: .round)) 19 | .fill(.angularGradient(colors: [.purple, .pink, .purple], center: .center, startAngle: .degrees(0), endAngle: .degrees(360))) 20 | .rotationEffect(.degrees(270)) 21 | .onAppear { 22 | withAnimation(.spring().delay(0.5)) { 23 | appear = true 24 | } 25 | } 26 | .onDisappear { 27 | appear = false 28 | } 29 | } 30 | } 31 | 32 | struct CircularView_Previews: PreviewProvider { 33 | static var previews: some View { 34 | CircularView() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Blobs/Blob 1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Blob 1.pdf", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "filename" : "Blob 1 Dark.pdf", 16 | "idiom" : "universal", 17 | "scale" : "1x" 18 | }, 19 | { 20 | "idiom" : "universal", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "appearances" : [ 25 | { 26 | "appearance" : "luminosity", 27 | "value" : "dark" 28 | } 29 | ], 30 | "idiom" : "universal", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "universal", 35 | "scale" : "3x" 36 | }, 37 | { 38 | "appearances" : [ 39 | { 40 | "appearance" : "luminosity", 41 | "value" : "dark" 42 | } 43 | ], 44 | "idiom" : "universal", 45 | "scale" : "3x" 46 | } 47 | ], 48 | "info" : { 49 | "author" : "xcode", 50 | "version" : 1 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Waves/Waves 1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Waves 1.pdf", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "filename" : "Waves 1 Dark.pdf", 16 | "idiom" : "universal", 17 | "scale" : "1x" 18 | }, 19 | { 20 | "idiom" : "universal", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "appearances" : [ 25 | { 26 | "appearance" : "luminosity", 27 | "value" : "dark" 28 | } 29 | ], 30 | "idiom" : "universal", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "universal", 35 | "scale" : "3x" 36 | }, 37 | { 38 | "appearances" : [ 39 | { 40 | "appearance" : "luminosity", 41 | "value" : "dark" 42 | } 43 | ], 44 | "idiom" : "universal", 45 | "scale" : "3x" 46 | } 47 | ], 48 | "info" : { 49 | "author" : "xcode", 50 | "version" : 1 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Waves/Waves 2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Waves 2.pdf", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "filename" : "Waves 2 Dark.pdf", 16 | "idiom" : "universal", 17 | "scale" : "1x" 18 | }, 19 | { 20 | "idiom" : "universal", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "appearances" : [ 25 | { 26 | "appearance" : "luminosity", 27 | "value" : "dark" 28 | } 29 | ], 30 | "idiom" : "universal", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "universal", 35 | "scale" : "3x" 36 | }, 37 | { 38 | "appearances" : [ 39 | { 40 | "appearance" : "luminosity", 41 | "value" : "dark" 42 | } 43 | ], 44 | "idiom" : "universal", 45 | "scale" : "3x" 46 | } 47 | ], 48 | "info" : { 49 | "author" : "xcode", 50 | "version" : 1 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Views/Main/NotificationsView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationsView.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 08/06/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct NotificationsView: View { 11 | var body: some View { 12 | ZStack { 13 | Color("Background").ignoresSafeArea() 14 | 15 | ScrollView { 16 | sectionsSection 17 | } 18 | .safeAreaInset(edge: .top, content: { 19 | Color.clear.frame(height: 70) 20 | }) 21 | .overlay(NavigationBar(title: "Notifications", hasScrolled: .constant(true))) 22 | .background(Image("Blob 1").offset(x: -180, y: 300)) 23 | } 24 | } 25 | 26 | var sectionsSection: some View { 27 | VStack(alignment: .leading) { 28 | ForEach(Array(courseSections.enumerated()), id: \.offset) { index, section in 29 | if index != 0 { Divider() } 30 | SectionRow(section: section) 31 | } 32 | } 33 | .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 30, style: .continuous)) 34 | .strokeStyle(cornerRadius: 30) 35 | .padding(20) 36 | } 37 | } 38 | 39 | struct NotificationsView_Previews: PreviewProvider { 40 | static var previews: some View { 41 | NotificationsView() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Components/Items/SmallCourseItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SmallCourseItem.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 08/06/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct SmallCourseItem: View { 11 | var course: Course = courses[0] 12 | 13 | var body: some View { 14 | VStack(alignment: .leading, spacing: 2) { 15 | RoundedRectangle(cornerRadius: 20, style: .continuous) 16 | .fill(.black.opacity(0.1)) 17 | .overlay( 18 | Image(course.image) 19 | .resizable() 20 | .aspectRatio(contentMode: .fit) 21 | .frame(width: 150, height: 105) 22 | ) 23 | Text(course.subtitle) 24 | .font(.caption) 25 | .foregroundColor(.secondary) 26 | .lineLimit(1) 27 | Text(course.title) 28 | .fontWeight(.semibold) 29 | .frame(maxWidth: .infinity, alignment: .leading) 30 | } 31 | .padding() 32 | .frame(width: 160, height: 200) 33 | .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 30, style: .continuous)) 34 | .strokeStyle(cornerRadius: 30) 35 | } 36 | } 37 | 38 | struct SmallCourseItem_Previews: PreviewProvider { 39 | static var previews: some View { 40 | SmallCourseItem() 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Components/Items/SectionRow.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SectionRow.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 07/06/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct SectionRow: View { 11 | var section: CourseSection = courseSections[0] 12 | var body: some View { 13 | HStack(alignment: .top, spacing: 16) { 14 | Image(section.logo) 15 | .resizable() 16 | .frame(width: 36, height: 36) 17 | .mask(Circle()) 18 | .padding(12) 19 | .background(Color(UIColor.systemBackground).opacity(0.3)) 20 | .mask(Circle()) 21 | .overlay(CircularView(value: section.progress)) 22 | VStack(alignment: .leading, spacing: 8) { 23 | Text(section.subtitle) 24 | .font(.caption.weight(.medium)) 25 | .foregroundColor(.secondary) 26 | Text(section.title) 27 | .fontWeight(.semibold) 28 | Text(section.text) 29 | .font(.caption.weight(.medium)) 30 | .foregroundStyle(.secondary) 31 | ProgressView(value: section.progress) 32 | .accentColor(.white) 33 | .frame(maxWidth: 132) 34 | } 35 | } 36 | .padding(20) 37 | } 38 | } 39 | 40 | struct SectionRow_Previews: PreviewProvider { 41 | static var previews: some View { 42 | SectionRow() 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Components/Buttons/AvatarView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AvatarView.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 06/06/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct AvatarView: View { 11 | @AppStorage("isLogged") var isLogged = true 12 | 13 | var body: some View { 14 | Group { 15 | if isLogged { 16 | AsyncImage(url: URL(string: "https://picsum.photos/200"), transaction: Transaction(animation: .easeOut)) { 17 | phase in 18 | switch phase { 19 | case .success(let image): 20 | image.resizable() 21 | .transition(.scale(scale: 0.5, anchor: .center)) 22 | case .empty: 23 | ProgressView() 24 | case .failure(_): 25 | Color.gray 26 | @unknown default: 27 | EmptyView() 28 | } 29 | } 30 | } else { 31 | Image("Avatar Default") 32 | .resizable() 33 | } 34 | 35 | } 36 | .frame(width: 26, height: 26) 37 | .cornerRadius(10) 38 | .padding(8) 39 | .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 18, style: .continuous)) 40 | .strokeStyle(cornerRadius: 18) 41 | } 42 | } 43 | 44 | struct AvatarView_Previews: PreviewProvider { 45 | static var previews: some View { 46 | AvatarView(isLogged: false) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Styles/Styles.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Styles.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 16/02/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct TitleModifier: ViewModifier { 11 | func body(content: Content) -> some View { 12 | content 13 | .font(.footnote.weight(.semibold)) 14 | .foregroundColor(.secondary) 15 | .frame(maxWidth: .infinity, alignment: .leading) 16 | .padding(20) 17 | .accessibilityAddTraits(.isHeader) 18 | } 19 | } 20 | 21 | extension View { 22 | func titleStyle() -> some View { 23 | modifier(TitleModifier()) 24 | } 25 | } 26 | 27 | struct StrokeModifier: ViewModifier { 28 | var cornerRadius: CGFloat 29 | @Environment(\.colorScheme) var colorScheme 30 | 31 | func body(content: Content) -> some View { 32 | content.overlay( 33 | RoundedRectangle(cornerRadius: cornerRadius, style: .continuous) 34 | .stroke( 35 | .linearGradient( 36 | colors: [ 37 | .white.opacity(colorScheme == .dark ? 0.1 : 0.3), 38 | .black.opacity(colorScheme == .dark ? 0.3 : 0.1) 39 | ], startPoint: .top, endPoint: .bottom 40 | ) 41 | ) 42 | .blendMode(.overlay) 43 | ) 44 | } 45 | } 46 | 47 | extension View { 48 | func strokeStyle(cornerRadius: CGFloat = 30) -> some View { 49 | modifier(StrokeModifier(cornerRadius: cornerRadius)) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Navigation/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 27/01/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | @AppStorage("selectedTab") var selectedTab: Tab = .home 12 | @AppStorage("showModal") var showModal = false 13 | @EnvironmentObject var model: Model 14 | 15 | var body: some View { 16 | ZStack(alignment: .bottom) { 17 | 18 | switch selectedTab { 19 | case .home: 20 | HomeView() 21 | case .explore: 22 | ExploreView() 23 | case .notifications: 24 | NotificationsView() 25 | case .library: 26 | LibraryView() 27 | } 28 | 29 | TabBar() 30 | .offset(y: model.showDetail ? 200 : 0) 31 | 32 | if showModal { 33 | ModalView() 34 | .zIndex(1) 35 | .accessibilityAddTraits(.isModal) 36 | } 37 | } 38 | .safeAreaInset(edge: .bottom, spacing: 0) { 39 | Color.clear.frame(height: 88) 40 | } 41 | .dynamicTypeSize(.large ... .xxLarge) 42 | } 43 | } 44 | 45 | struct ContentView_Previews: PreviewProvider { 46 | static var previews: some View { 47 | Group { 48 | ContentView() 49 | .environment(\.sizeCategory, .accessibilityExtraExtraExtraLarge) 50 | ContentView() 51 | .preferredColorScheme(.dark) 52 | } 53 | .environmentObject(Model()) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15UITests/SwiftUI_for_iOS_15UITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftUI_for_iOS_15UITests.swift 3 | // SwiftUI for iOS 15UITests 4 | // 5 | // Created by João Carlos Magalhães on 27/01/22. 6 | // 7 | 8 | import XCTest 9 | 10 | class SwiftUI_for_iOS_15UITests: XCTestCase { 11 | 12 | override func setUpWithError() throws { 13 | // Put setup code here. This method is called before the invocation of each test method in the class. 14 | 15 | // In UI tests it is usually best to stop immediately when a failure occurs. 16 | continueAfterFailure = false 17 | 18 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 19 | } 20 | 21 | override func tearDownWithError() throws { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | func testExample() throws { 26 | // UI tests must launch the application that they test. 27 | let app = XCUIApplication() 28 | app.launch() 29 | 30 | // Use recording to get started writing UI tests. 31 | // Use XCTAssert and related functions to verify your tests produce the correct results. 32 | } 33 | 34 | func testLaunchPerformance() throws { 35 | if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { 36 | // This measures how long it takes to launch your application. 37 | measure(metrics: [XCTApplicationLaunchMetric()]) { 38 | XCUIApplication().launch() 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Components/Items/CertificateView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CertificateView.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 08/06/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | import SwiftUI 11 | 12 | struct CertificateView: View { 13 | var body: some View { 14 | VStack(alignment: .leading) { 15 | VStack(alignment: .leading, spacing: 8) { 16 | Text("SwiftUI for iOS 15") 17 | .font(.title3.weight(.semibold)) 18 | Text("Certificate") 19 | .font(.subheadline.weight(.medium)) 20 | .foregroundStyle(.secondary) 21 | } 22 | Spacer() 23 | VStack(alignment: .leading, spacing: 8) { 24 | Text("Feb 25, 2022".uppercased()) 25 | .font(.footnote.weight(.semibold)) 26 | Text("DesignCode instructor: Meng To") 27 | .font(.footnote.weight(.medium)) 28 | } 29 | .foregroundStyle(.secondary) 30 | } 31 | .frame(maxWidth: .infinity, alignment: .leading) 32 | .overlay( 33 | Image("Logo 2") 34 | .resizable(resizingMode: .stretch) 35 | .aspectRatio(contentMode: .fit) 36 | .frame(width: 26.0, height: 26.0) 37 | .cornerRadius(10) 38 | .padding(9) 39 | .background(Color(UIColor.systemBackground).opacity(0.1), in: RoundedRectangle(cornerRadius: 16, style: .continuous)) 40 | .strokeStyle(cornerRadius: 16) 41 | .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing) 42 | ) 43 | .padding(20) 44 | .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 30, style: .continuous)) 45 | .strokeStyle(cornerRadius: 30) 46 | } 47 | } 48 | 49 | struct CertificateView_Previews: PreviewProvider { 50 | static var previews: some View { 51 | CertificateView() 52 | } 53 | } 54 | 55 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Components/Items/HandbookItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HandbookItem.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 08/06/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct HandbookItem: View { 11 | var handbook: Handbook = handbooks[0] 12 | 13 | var body: some View { 14 | VStack(alignment: .leading, spacing: 8) { 15 | RoundedRectangle(cornerRadius: 20) 16 | .fill(.black.opacity(0.2)) 17 | .frame(height: 90) 18 | .overlay( 19 | Image(handbook.image) 20 | .resizable() 21 | .aspectRatio(contentMode: .fit) 22 | .frame(width: 150, height: 100) 23 | ) 24 | Text(handbook.title) 25 | .fontWeight(.semibold) 26 | .layoutPriority(1) 27 | Text(handbook.subtitle) 28 | .font(.caption.weight(.medium)) 29 | .foregroundStyle(.secondary) 30 | Text(handbook.text) 31 | .font(.caption) 32 | .foregroundStyle(.secondary) 33 | .lineLimit(3) 34 | Spacer() 35 | } 36 | .padding() 37 | .frame(maxWidth: 200) 38 | .frame(height: 260) 39 | .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 30, style: .continuous)) 40 | .strokeStyle(cornerRadius: 30) 41 | .background( 42 | RoundedRectangle(cornerRadius: 30, style: .continuous) 43 | .fill(.linearGradient(colors: [handbook.color1, handbook.color2], startPoint: .topLeading, endPoint: .bottomTrailing)) 44 | .rotation3DEffect(.degrees(10), axis: (x: 0, y: 1, z: 0), anchor: .bottomTrailing) 45 | .rotationEffect(.degrees(180)) 46 | .padding(.trailing, 40) 47 | ) 48 | } 49 | } 50 | 51 | struct HandbookItem_Previews: PreviewProvider { 52 | static var previews: some View { 53 | HandbookItem(handbook: handbooks[1]) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Styles/AngularButtonStyle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AngularButtonStyle.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 27/04/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct AngularButtonStyle: ButtonStyle { 11 | @Environment(\.controlSize) var controlSize 12 | 13 | var extraPadding: CGFloat { 14 | switch controlSize { 15 | case .mini: 16 | return 0 17 | case .small: 18 | return 0 19 | case .regular: 20 | return 4 21 | case .large: 22 | return 12 23 | @unknown default: 24 | return 0 25 | } 26 | } 27 | 28 | var cornerRadius: CGFloat { 29 | switch controlSize { 30 | case .mini: 31 | return 12 32 | case .small: 33 | return 12 34 | case .regular: 35 | return 16 36 | case .large: 37 | return 20 38 | @unknown default: 39 | return 12 40 | } 41 | } 42 | 43 | func makeBody(configuration: Configuration) -> some View { 44 | configuration.label 45 | .padding(.horizontal, 10 + extraPadding) 46 | .padding(.vertical, 4 + extraPadding) 47 | .background( 48 | RoundedRectangle(cornerRadius: cornerRadius, style: .continuous) 49 | .fill(.linearGradient(colors: [Color(.systemBackground), Color(.systemBackground).opacity(0.6)], startPoint: .top, endPoint: .bottom)) 50 | .blendMode(.softLight) 51 | ) 52 | .background( 53 | RoundedRectangle(cornerRadius: cornerRadius, style: .continuous) 54 | .fill(.angularGradient(colors: [.pink, .purple, .blue, .pink], center: .center, startAngle: .degrees(-90), endAngle: .degrees(270))) 55 | .blur(radius: cornerRadius) 56 | ) 57 | .strokeStyle(cornerRadius: cornerRadius) 58 | } 59 | } 60 | 61 | extension ButtonStyle where Self == AngularButtonStyle { 62 | static var angular: Self { 63 | return .init() 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Views/Main/ExploreView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExploreView.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 08/06/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ExploreView: View { 11 | var body: some View { 12 | ZStack { 13 | Color("Background").ignoresSafeArea() 14 | 15 | 16 | ScrollView { 17 | coursesSection 18 | 19 | Text("Topics".uppercased()) 20 | .titleStyle() 21 | 22 | topicsSection 23 | 24 | Text("Popular".uppercased()) 25 | .titleStyle() 26 | 27 | handbooksSection 28 | } 29 | 30 | .safeAreaInset(edge: .top) { 31 | Color.clear.frame(height: 70) 32 | } 33 | .overlay(NavigationBar(title: "Recent", hasScrolled: .constant(true))) 34 | .background(Image("Blob 1").offset(x: -100, y: -400)) 35 | } 36 | } 37 | 38 | var coursesSection: some View { 39 | ScrollView(.horizontal, showsIndicators: false) { 40 | HStack(spacing: 16) { 41 | ForEach(courses) { course in 42 | SmallCourseItem(course: course) 43 | } 44 | } 45 | .padding(.horizontal, 20) 46 | Spacer() 47 | } 48 | } 49 | 50 | var handbooksSection: some View { 51 | HStack(alignment: .top, spacing: 16) { 52 | ForEach(handbooks) { handbook in 53 | HandbookItem(handbook: handbook) 54 | } 55 | } 56 | .padding(.horizontal, 20) 57 | } 58 | 59 | var topicsSection: some View { 60 | VStack { 61 | ForEach(topics) { topic in 62 | ListRow(topic: topic) 63 | } 64 | } 65 | .padding(20) 66 | .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 30, style: .continuous)) 67 | .strokeStyle(cornerRadius: 30) 68 | .padding(.horizontal, 20) 69 | } 70 | } 71 | 72 | struct ExploreView_Previews: PreviewProvider { 73 | static var previews: some View { 74 | ExploreView() 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Components/Items/FeaturedItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FeaturedItem.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 31/03/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct FeaturedItem: View { 11 | var course : Course = courses[0] 12 | 13 | var body: some View { 14 | VStack(alignment: .leading, spacing: 8.0){ 15 | Spacer() 16 | Image(course.logo) 17 | .resizable(resizingMode: .stretch) 18 | .aspectRatio(contentMode: .fit) 19 | .frame(width: 26.0, height: 26.0) 20 | .cornerRadius(10.0) 21 | .padding(9) 22 | .background(Color(UIColor.systemBackground).opacity(0.1), in: RoundedRectangle(cornerRadius: 20, style: .continuous)) 23 | .strokeStyle(cornerRadius: 16) 24 | Text(course.title) 25 | .font(.largeTitle) 26 | .fontWeight(.bold) 27 | .foregroundStyle(.linearGradient(colors: [.primary, .primary.opacity(0.5)], startPoint: .topLeading, endPoint: .bottomTrailing)) 28 | .lineLimit(1) 29 | Text(course.subtitle.uppercased()) 30 | .font(.footnote) 31 | .fontWeight(.semibold) 32 | .foregroundStyle(.secondary) 33 | Text(course.text) 34 | .font(.footnote) 35 | .multilineTextAlignment(.leading) 36 | .lineLimit(2) 37 | .frame(maxWidth: .infinity, alignment: .leading) 38 | .foregroundColor(.secondary) 39 | 40 | } 41 | .padding(.all, 20.0) 42 | .padding(.vertical, 20.0) 43 | .frame(height: 350.0) 44 | .background(.ultraThinMaterial) 45 | .mask(RoundedRectangle(cornerRadius: 30, style: .continuous)) 46 | // .cornerRadius(30.0) 47 | // .mask(RoundedRectangle(cornerRadius: 30, style: .continuous)) 48 | .strokeStyle() 49 | .padding(.horizontal, 20) 50 | 51 | } 52 | } 53 | 54 | 55 | struct FeaturedItem_Previews: PreviewProvider { 56 | static var previews: some View { 57 | FeaturedItem() 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Components/Items/CourseItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CourseItem.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 31/03/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct CourseItem: View { 11 | var namespace : Namespace.ID 12 | var course : Course = courses[0] 13 | @Binding var show : Bool 14 | 15 | var body: some View { 16 | 17 | VStack { 18 | Spacer() 19 | VStack(alignment: .leading, spacing: 12) { 20 | Text(course.title) 21 | .font(.largeTitle.weight(.bold)) 22 | .matchedGeometryEffect(id: "title\(course.id)", in: namespace) 23 | .frame(maxWidth: .infinity, alignment: .leading) 24 | Text(course.subtitle.uppercased()) 25 | .font(.footnote.weight(.semibold)) 26 | .matchedGeometryEffect(id: "subtitle\(course.id)", in: namespace) 27 | Text(course.text) 28 | .font(.footnote) 29 | .matchedGeometryEffect(id: "text\(course.id)", in: namespace) 30 | 31 | } 32 | .padding(20) 33 | 34 | .background( 35 | Rectangle() 36 | .fill(.ultraThinMaterial) 37 | .mask(RoundedRectangle(cornerRadius: 30, style: .continuous)) 38 | .blur(radius: 30) 39 | .matchedGeometryEffect(id: "blur\(course.id)", in: namespace) 40 | 41 | 42 | ) 43 | 44 | } 45 | .foregroundStyle(.white) 46 | .background( 47 | Image(course.image) 48 | .resizable() 49 | .aspectRatio(contentMode: .fit) 50 | .padding(20) 51 | .matchedGeometryEffect(id: "image\(course.id)", in: namespace) 52 | 53 | ) 54 | .background( 55 | Image(course.background) 56 | .resizable() 57 | .aspectRatio(contentMode: .fill) 58 | .matchedGeometryEffect(id: "background\(course.id)", in: namespace) 59 | 60 | ) 61 | .mask( 62 | RoundedRectangle(cornerRadius: 30, style: .continuous) 63 | .matchedGeometryEffect(id: "mask\(course.id)", in: namespace) 64 | ) 65 | .frame(height: 300) 66 | 67 | } 68 | } 69 | 70 | struct CourseItem_Previews: PreviewProvider { 71 | @Namespace static var namespace 72 | 73 | static var previews: some View { 74 | CourseItem(namespace: namespace, show: .constant(true)) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Views/Main/LibraryView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LibraryView.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 08/06/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct LibraryView: View { 11 | var body: some View { 12 | ZStack { 13 | Color("Background").ignoresSafeArea() 14 | 15 | 16 | ScrollView { 17 | 18 | CertificateView() 19 | .frame(height: 220) 20 | .background( 21 | RoundedRectangle(cornerRadius: 30, style: .continuous) 22 | .fill(.linearGradient(colors: [.purple, .blue], startPoint: .topLeading, endPoint: .bottomTrailing)) 23 | .padding(20) 24 | .offset(y: -30) 25 | ) 26 | .background( 27 | RoundedRectangle(cornerRadius: 30, style: .continuous) 28 | .fill(.linearGradient(colors: [.teal, .blue], startPoint: .topLeading, endPoint: .bottomTrailing)) 29 | .padding(40) 30 | .offset(y: -60) 31 | ) 32 | .padding(20) 33 | 34 | Text("History".uppercased()) 35 | .titleStyle() 36 | 37 | coursesSection 38 | 39 | Text("Topics".uppercased()) 40 | .titleStyle() 41 | 42 | topicsSection 43 | 44 | } 45 | 46 | .safeAreaInset(edge: .top) { 47 | Color.clear.frame(height: 70) 48 | } 49 | .overlay(NavigationBar(title: "Library", hasScrolled: .constant(true))) 50 | .background(Image("Blob 1").offset(x: -100, y: -400)) 51 | } 52 | } 53 | 54 | var coursesSection: some View { 55 | ScrollView(.horizontal, showsIndicators: false) { 56 | HStack(spacing: 16) { 57 | ForEach(courses) { course in 58 | SmallCourseItem(course: course) 59 | } 60 | } 61 | .padding(.horizontal, 20) 62 | Spacer() 63 | } 64 | } 65 | 66 | var topicsSection: some View { 67 | VStack { 68 | ForEach(topics) { topic in 69 | ListRow(topic: topic) 70 | } 71 | } 72 | .padding(20) 73 | .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 30, style: .continuous)) 74 | .strokeStyle(cornerRadius: 30) 75 | .padding(.horizontal, 20) 76 | } 77 | } 78 | 79 | struct LibraryView_Previews: PreviewProvider { 80 | static var previews: some View { 81 | LibraryView() 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Model/CourseSection.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CourseSection.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 07/06/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | import SwiftUI 11 | 12 | struct CourseSection: Identifiable { 13 | let id = UUID() 14 | var title: String 15 | var subtitle: String 16 | var text: String 17 | var image: String 18 | var background: String 19 | var logo: String 20 | var progress: CGFloat 21 | } 22 | 23 | var courseSections = [ 24 | CourseSection(title: "Advanced Custom Layout", subtitle: "SwiftUI for iOS 15", text: "Build an iOS app for iOS 15 with custom layouts...", image: "Illustration 1", background: "Background 5", logo: "Logo 2", progress: 0.5), 25 | CourseSection(title: "Coding the Home View", subtitle: "SwiftUI Concurrency", text: "Learn about the formatted(date:time:) method and AsyncImage", image: "Illustration 2", background: "Background 4", logo: "Logo 2", progress: 0.2), 26 | CourseSection(title: "Styled Components", subtitle: "React Advanced", text: "Reset your CSS, set up your fonts and create your first React component", image: "Illustration 3", background: "Background 3", logo: "Logo 3", progress: 0.8), 27 | CourseSection(title: "Flutter Interactions", subtitle: "Flutter for designers", text: "Use the GestureDetector Widget to create amazing user interactions", image: "Illustration 4", background: "Background 2", logo: "Logo 1", progress: 0.0), 28 | CourseSection(title: "Firebase for Android", subtitle: "Flutter for designers", text: "Create your first Firebase Project and download Firebase plugins for Android", image: "Illustration 5", background: "Background 1", logo: "Logo 1", progress: 0.1), 29 | CourseSection(title: "Advanced Custom Layout", subtitle: "SwiftUI for iOS 15", text: "Build an iOS app for iOS 15 with custom layouts...", image: "Illustration 1", background: "Background 5", logo: "Logo 2", progress: 0.5), 30 | CourseSection(title: "Coding the Home View", subtitle: "SwiftUI Concurrency", text: "Learn about the formatted(date:time:) method and AsyncImage", image: "Illustration 2", background: "Background 4", logo: "Logo 2", progress: 0.2), 31 | CourseSection(title: "Styled Components", subtitle: "React Advanced", text: "Reset your CSS, set up your fonts and create your first React component", image: "Illustration 3", background: "Background 3", logo: "Logo 3", progress: 0.8), 32 | CourseSection(title: "Flutter Interactions", subtitle: "Flutter for designers", text: "Use the GestureDetector Widget to create amazing user interactions", image: "Illustration 4", background: "Background 2", logo: "Logo 1", progress: 0.0), 33 | CourseSection(title: "Firebase for Android", subtitle: "Flutter for designers", text: "Create your first Firebase Project and download Firebase plugins for Android", image: "Illustration 5", background: "Background 1", logo: "Logo 1", progress: 0.1) 34 | ] 35 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Navigation/NavigationBar.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NavigationBar.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 31/03/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct NavigationBar: View { 11 | var title = "" 12 | @Binding var hasScrolled: Bool 13 | @State var showSearch = false 14 | @State var showAccount = false 15 | @AppStorage("showModal") var showModal = false 16 | @AppStorage("isLogged") var isLogged = false 17 | 18 | var body: some View { 19 | ZStack { 20 | Color.clear 21 | .background(.ultraThinMaterial) 22 | .blur(radius: 10) 23 | .opacity(hasScrolled ? 1 : 0) 24 | 25 | Text(title) 26 | .animatableFont(size: hasScrolled ? 22 : 34, weight: .bold) 27 | .frame(maxWidth: .infinity, alignment: .leading) 28 | .padding(.leading, 20) 29 | .padding(.top, 20) 30 | .offset(y: hasScrolled ? -4 : 0) 31 | 32 | HStack(spacing: 16) { 33 | Button { 34 | showSearch = true 35 | } label: { 36 | Image(systemName: "magnifyingglass") 37 | .font(.body.weight(.bold)) 38 | .frame(width: 36, height: 36) 39 | .foregroundColor(.secondary) 40 | .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 14, style: .continuous)) 41 | .strokeStyle(cornerRadius: 14) 42 | } 43 | .sheet(isPresented: $showSearch) { 44 | SearchView() 45 | } 46 | 47 | Button { 48 | if isLogged { 49 | showAccount = true 50 | } else { 51 | withAnimation { 52 | showModal = true 53 | } 54 | } 55 | } label: { 56 | AvatarView() 57 | } 58 | .accessibilityElement() 59 | .accessibilityLabel("Account") 60 | .accessibilityAddTraits(.isButton) 61 | .sheet(isPresented: $showAccount) { 62 | AccountView() 63 | } 64 | } 65 | .frame(maxWidth: .infinity, alignment: .trailing) 66 | .padding(.trailing, 20) 67 | .padding(.top, 20) 68 | .offset(y: hasScrolled ? -4 : 0) 69 | } 70 | .frame(height: hasScrolled ? 44 : 70) 71 | .frame(maxHeight: .infinity, alignment: .top) 72 | } 73 | } 74 | 75 | struct NavigationBar_Previews: PreviewProvider { 76 | static var previews: some View { 77 | NavigationBar(title: "Featured", hasScrolled: .constant(false)) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "iPad_20pt@2x.png", 5 | "idiom" : "iphone", 6 | "scale" : "2x", 7 | "size" : "20x20" 8 | }, 9 | { 10 | "filename" : "iPhone_20pt@3x.png", 11 | "idiom" : "iphone", 12 | "scale" : "3x", 13 | "size" : "20x20" 14 | }, 15 | { 16 | "filename" : "iPad_29pt.png", 17 | "idiom" : "iphone", 18 | "scale" : "1x", 19 | "size" : "29x29" 20 | }, 21 | { 22 | "filename" : "iPad_29pt@2x.png", 23 | "idiom" : "iphone", 24 | "scale" : "2x", 25 | "size" : "29x29" 26 | }, 27 | { 28 | "filename" : "iPhone_29pt@3x.png", 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "29x29" 32 | }, 33 | { 34 | "filename" : "iPad_40@2x.png", 35 | "idiom" : "iphone", 36 | "scale" : "2x", 37 | "size" : "40x40" 38 | }, 39 | { 40 | "filename" : "iPhone_40pt@3x.png", 41 | "idiom" : "iphone", 42 | "scale" : "3x", 43 | "size" : "40x40" 44 | }, 45 | { 46 | "filename" : "iPhone_60pt@2x.png", 47 | "idiom" : "iphone", 48 | "scale" : "2x", 49 | "size" : "60x60" 50 | }, 51 | { 52 | "filename" : "iPhone_60pt@3x.png", 53 | "idiom" : "iphone", 54 | "scale" : "3x", 55 | "size" : "60x60" 56 | }, 57 | { 58 | "filename" : "iPad_20pt.png", 59 | "idiom" : "ipad", 60 | "scale" : "1x", 61 | "size" : "20x20" 62 | }, 63 | { 64 | "filename" : "iPhone_20@2x.png", 65 | "idiom" : "ipad", 66 | "scale" : "2x", 67 | "size" : "20x20" 68 | }, 69 | { 70 | "filename" : "iPhone_29pt.png", 71 | "idiom" : "ipad", 72 | "scale" : "1x", 73 | "size" : "29x29" 74 | }, 75 | { 76 | "filename" : "iPhone_29pt@2x.png", 77 | "idiom" : "ipad", 78 | "scale" : "2x", 79 | "size" : "29x29" 80 | }, 81 | { 82 | "filename" : "iPad_40pt.png", 83 | "idiom" : "ipad", 84 | "scale" : "1x", 85 | "size" : "40x40" 86 | }, 87 | { 88 | "filename" : "iPhone_40pt@2x.png", 89 | "idiom" : "ipad", 90 | "scale" : "2x", 91 | "size" : "40x40" 92 | }, 93 | { 94 | "filename" : "iPad_76pt.png", 95 | "idiom" : "ipad", 96 | "scale" : "1x", 97 | "size" : "76x76" 98 | }, 99 | { 100 | "filename" : "iPad_76@2x.png", 101 | "idiom" : "ipad", 102 | "scale" : "2x", 103 | "size" : "76x76" 104 | }, 105 | { 106 | "filename" : "iPad_83.5pt@2x.png", 107 | "idiom" : "ipad", 108 | "scale" : "2x", 109 | "size" : "83.5x83.5" 110 | }, 111 | { 112 | "filename" : "App Icon iOS.png", 113 | "idiom" : "ios-marketing", 114 | "scale" : "1x", 115 | "size" : "1024x1024" 116 | } 117 | ], 118 | "info" : { 119 | "author" : "xcode", 120 | "version" : 1 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Components/Graphics/BlobView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BlobView.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 29/03/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct BlobView: View { 11 | @State var appear = false 12 | 13 | var body: some View { 14 | TimelineView(.animation) { timeline in 15 | 16 | let now = timeline.date.timeIntervalSinceReferenceDate 17 | let angle = Angle.degrees(now.remainder(dividingBy: 3) * 60) 18 | let x = cos(angle.radians) 19 | let angle2 = Angle.degrees(now.remainder(dividingBy: 6) * 10) 20 | let x2 = cos(angle2.radians) 21 | 22 | Canvas { context, size in 23 | context.fill(path(in: CGRect(x: 0, y: 0, width: size.width, height: size.height), x: x, x2: x2), with: .linearGradient(Gradient(colors: [.pink, .blue]), startPoint: CGPoint(x: 0, y: 0), endPoint: CGPoint(x: 400, y: 400))) 24 | } 25 | .frame(width: 400, height: 414) 26 | .rotationEffect(.degrees(appear ? 360 : 0)) 27 | } 28 | .onAppear{ 29 | withAnimation(.linear(duration: 20).repeatForever(autoreverses: true)){ 30 | appear = true 31 | } 32 | } 33 | 34 | } 35 | func path(in rect: CGRect, x: Double, x2: Double) -> Path{ 36 | var path = Path() 37 | let width = rect.size.width 38 | let height = rect.size.height 39 | path.move(to: CGPoint(x: 0.9923*width, y: 0.42593*height)) 40 | path.addCurve(to: CGPoint(x: 0.6355*width*x2, y: height), control1: CGPoint(x: 0.91864*width*x2, y: 0.77749*height*x2), control2: CGPoint(x: 0.91864*width*x2, y: height)) 41 | path.addCurve(to: CGPoint(x: 0.08995*width, y: 0.60171*height), control1: CGPoint(x: 0.35237*width*x, y: height), control2: CGPoint(x: 0.2695*width, y: 0.77304*height)) 42 | path.addCurve(to: CGPoint(x: 0.34086*width, y: 0.06324*height*x), control1: CGPoint(x: -0.0896*width, y: 0.43038*height), control2: CGPoint(x: 0.002484*width, y: 0.23012*height*x)) 43 | path.addCurve(to: CGPoint(x: 0.9923*width, y: 0.42593*height), control1: CGPoint(x: 0.67924*width, y: -0.10364*height*x), control2: CGPoint(x: 1.05906*width, y: 0.07436*height*x2)) 44 | path.closeSubpath() 45 | return path 46 | } 47 | } 48 | 49 | struct BlobView_Previews: PreviewProvider { 50 | static var previews: some View { 51 | BlobView() 52 | } 53 | } 54 | 55 | struct BlobShape: Shape{ 56 | func path(in rect: CGRect) -> Path{ 57 | var path = Path() 58 | let width = rect.size.width 59 | let height = rect.size.height 60 | path.move(to: CGPoint(x: 0.9923*width, y: 0.42593*height)) 61 | path.addCurve(to: CGPoint(x: 0.6355*width, y: height), control1: CGPoint(x: 0.91864*width, y: 0.77749*height), control2: CGPoint(x: 0.91864*width, y: height)) 62 | path.addCurve(to: CGPoint(x: 0.08995*width, y: 0.60171*height), control1: CGPoint(x: 0.35237*width, y: height), control2: CGPoint(x: 0.2695*width, y: 0.77304*height)) 63 | path.addCurve(to: CGPoint(x: 0.34086*width, y: 0.06324*height), control1: CGPoint(x: -0.0896*width, y: 0.43038*height), control2: CGPoint(x: 0.002484*width, y: 0.23012*height)) 64 | path.addCurve(to: CGPoint(x: 0.9923*width, y: 0.42593*height), control1: CGPoint(x: 0.67924*width, y: -0.10364*height), control2: CGPoint(x: 1.05906*width, y: 0.07436*height)) 65 | path.closeSubpath() 66 | return path 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Views/Sheets/SearchView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SearchView.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 25/04/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct SearchView: View { 11 | @State var text = "" 12 | @State var show = false 13 | @State var selectedIndex = 0 14 | @Namespace var namespace 15 | @Environment(\.presentationMode) var presentationMode 16 | 17 | var body: some View { 18 | NavigationView { 19 | ScrollView { 20 | VStack { 21 | content 22 | } 23 | .padding(20) 24 | .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 30, style: .continuous)) 25 | .strokeStyle(cornerRadius: 30) 26 | .padding(20) 27 | .background( 28 | Rectangle() 29 | .fill(.regularMaterial) 30 | .frame(height: 200) 31 | .frame(maxHeight: .infinity, alignment: .top) 32 | .blur(radius: 20) 33 | .offset(y: -200) 34 | ) 35 | .background( 36 | Image("Blob 1").offset(x: -100, y: -200) 37 | ) 38 | } 39 | .searchable(text: $text, placement: .navigationBarDrawer(displayMode: .always), prompt: Text("SwiftUI, React, UI Design")) { 40 | ForEach(suggestions) { suggestion in 41 | Button { 42 | text = suggestion.text 43 | } label: { 44 | Text(suggestion.text) 45 | .searchCompletion(suggestion.text) 46 | } 47 | } 48 | } 49 | .navigationTitle("Search") 50 | .navigationBarTitleDisplayMode(.inline) 51 | .navigationBarItems(trailing: Button{ presentationMode.wrappedValue.dismiss() } label: { Text("Done").bold() }) 52 | .sheet(isPresented: $show) { 53 | CourseView(namespace: namespace, course: courses[selectedIndex], show: $show) 54 | } 55 | } 56 | } 57 | 58 | var content: some View { 59 | ForEach(Array(courses.enumerated()), id: \.offset) { index, item in 60 | if item.title.contains(text) || text == "" { 61 | if index != 0{ 62 | Divider() 63 | } 64 | Button{ 65 | show = true 66 | selectedIndex = index 67 | } label: { 68 | HStack(alignment: .top, spacing: 12) { 69 | Image(item.image) 70 | .resizable() 71 | .aspectRatio(contentMode: .fill) 72 | .frame(width: 44, height: 44) 73 | .background(Color("Background")) 74 | .mask(Circle()) 75 | VStack(alignment: .leading, spacing: 4){ 76 | Text(item.title).bold() 77 | .foregroundColor(.primary) 78 | Text(item.text) 79 | .font(.footnote) 80 | .foregroundColor(.secondary) 81 | .frame(maxWidth: .infinity, alignment: .leading) 82 | .multilineTextAlignment(.leading) 83 | } 84 | } 85 | .padding(.vertical, 4) 86 | .listRowSeparator(.hidden) 87 | } 88 | } 89 | 90 | } 91 | } 92 | } 93 | 94 | struct SearchView_Previews: PreviewProvider { 95 | static var previews: some View { 96 | SearchView() 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Views/Modals/ModalView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ModalView.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 02/05/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | import SwiftUI 11 | 12 | struct ModalView: View { 13 | @EnvironmentObject var model: Model 14 | @AppStorage("showModal") var showModal = true 15 | @State var viewState: CGSize = .zero 16 | @State var isDismissed = false 17 | @State var appear = [false, false, false] 18 | @AppStorage("isLogged") var isLogged = false 19 | 20 | var body: some View { 21 | ZStack { 22 | Color.clear.background(.regularMaterial) 23 | .onTapGesture { 24 | dismissModal() 25 | } 26 | .ignoresSafeArea() 27 | 28 | Group { 29 | switch model.selectedModal { 30 | case .signUp: SignUpView() 31 | case .signIn: SignInView() 32 | } 33 | } 34 | .mask(RoundedRectangle(cornerRadius: 30, style: .continuous)) 35 | .offset(x: viewState.width, y: viewState.height) 36 | .offset(y: isDismissed ? 1000 : 0) 37 | .rotationEffect(.degrees(viewState.width/40)) 38 | .rotation3DEffect(.degrees(viewState.height/20), axis: (x: 1, y: 0, z: 0)) 39 | .hueRotation(.degrees(viewState.width/5)) 40 | .gesture(drag) 41 | .shadow(color: Color("Shadow").opacity(0.2), radius: 30, x: 0, y: 30) 42 | .opacity(appear[0] ? 1 : 0) 43 | .offset(y: appear[0] ? 0 : 200) 44 | .padding(20) 45 | .background( 46 | Image("Blob 1").offset(x: 200, y: -100) 47 | .opacity(appear[2] ? 1 : 0) 48 | .offset(y: appear[2] ? 0 : 10) 49 | .blur(radius: appear[2] ? 0 : 40) 50 | .allowsHitTesting(false) 51 | .accessibility(hidden: true) 52 | ) 53 | 54 | Button { 55 | dismissModal() 56 | } label: { 57 | Image(systemName: "xmark") 58 | .font(.body.weight(.bold)) 59 | .foregroundColor(.secondary) 60 | .padding(8) 61 | .background(.ultraThinMaterial, in: Circle()) 62 | } 63 | .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing) 64 | .padding(20) 65 | .opacity(appear[1] ? 1 : 0) 66 | .offset(y: appear[1] ? 0 : -200) 67 | } 68 | .onAppear { 69 | withAnimation(.easeOut) { 70 | appear[0] = true 71 | } 72 | withAnimation(.easeOut.delay(0.1)) { 73 | appear[1] = true 74 | } 75 | withAnimation(.easeOut(duration: 1).delay(0.2)) { 76 | appear[2] = true 77 | } 78 | } 79 | .onChange(of: isLogged) { newValue in 80 | if newValue { 81 | dismissModal() 82 | } 83 | } 84 | } 85 | 86 | var drag: some Gesture { 87 | DragGesture() 88 | .onChanged { value in 89 | viewState = value.translation 90 | } 91 | .onEnded { value in 92 | if value.translation.height > 200 { 93 | dismissModal() 94 | } else { 95 | withAnimation(.openCard) { 96 | viewState = .zero 97 | } 98 | } 99 | } 100 | } 101 | 102 | func dismissModal() { 103 | withAnimation { 104 | isDismissed = true 105 | } 106 | withAnimation(.linear.delay(0.3)) { 107 | showModal = false 108 | } 109 | } 110 | } 111 | 112 | struct ModalView_Previews: PreviewProvider { 113 | static var previews: some View { 114 | ModalView() 115 | .environmentObject(Model()) 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Navigation/TabBar.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TabBar.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 30/03/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct TabBar: View { 11 | @AppStorage("selectedTab") var selectedTab: Tab = .home 12 | @State var color: Color = .teal 13 | @State var tabItemWidth: CGFloat = 0 14 | 15 | var body: some View { 16 | GeometryReader { proxy in 17 | let hasHomeIndicator = proxy.safeAreaInsets.bottom - 88 > 20 18 | 19 | HStack { 20 | buttons 21 | } 22 | .padding(.horizontal, 8) 23 | .padding(.top, 14) 24 | .frame(height: hasHomeIndicator ? 88 : 62, alignment: .top) 25 | .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: hasHomeIndicator ? 34 : 0, style: .continuous)) 26 | .background( 27 | background 28 | ) 29 | .overlay( 30 | overlay 31 | ) 32 | .strokeStyle(cornerRadius: hasHomeIndicator ? 34 : 0) 33 | .frame(maxHeight: .infinity, alignment: .bottom) 34 | .ignoresSafeArea() 35 | } 36 | } 37 | 38 | var buttons: some View { 39 | ForEach(tabItems) { item in 40 | Button { 41 | withAnimation(.spring(response: 0.3, dampingFraction: 0.7)) { 42 | selectedTab = item.tab 43 | color = item.color 44 | } 45 | } label: { 46 | VStack(spacing: 0) { 47 | Image(systemName: item.icon) 48 | .symbolVariant(.fill) 49 | .font(.body.bold()) 50 | .frame(width: 44, height: 29) 51 | Text(item.text) 52 | .font(.caption2) 53 | .lineLimit(1) 54 | } 55 | .frame(maxWidth: .infinity) 56 | } 57 | .foregroundStyle(selectedTab == item.tab ? .primary : .secondary) 58 | .blendMode(selectedTab == item.tab ? .overlay : .normal) 59 | .overlay( 60 | GeometryReader { proxy in 61 | // Text("\(proxy.size.width)") 62 | Color.clear.preference(key: TabPreferenceKey.self, value: proxy.size.width) 63 | } 64 | ) 65 | .onPreferenceChange(TabPreferenceKey.self) { value in 66 | tabItemWidth = value 67 | } 68 | } 69 | } 70 | 71 | var background: some View { 72 | HStack { 73 | if selectedTab == .library { Spacer() } 74 | if selectedTab == .explore { Spacer() } // when is explore selected (1 spacer on the left) 75 | if selectedTab == .notifications { 76 | Spacer() 77 | Spacer() 78 | } 79 | Circle().fill(color).frame(width: tabItemWidth) 80 | if selectedTab == .home { Spacer() } // this kicks in when I have learn now selected 81 | if selectedTab == .explore { // when is explore selected (2 spacers on the right) 82 | Spacer() 83 | Spacer() 84 | } 85 | if selectedTab == .notifications { Spacer() } 86 | } 87 | .padding(.horizontal, 8) 88 | } 89 | 90 | var overlay: some View { 91 | HStack { 92 | if selectedTab == .library { Spacer() } 93 | if selectedTab == .explore { Spacer() } 94 | if selectedTab == .notifications { 95 | Spacer() 96 | Spacer() 97 | } 98 | Rectangle() 99 | .fill(color) 100 | .frame(width: 28, height: 5) 101 | .cornerRadius(3) 102 | .frame(width: tabItemWidth) 103 | .frame(maxHeight: .infinity, alignment: .top) 104 | if selectedTab == .home { Spacer() } 105 | if selectedTab == .explore { 106 | Spacer() 107 | Spacer() 108 | } 109 | if selectedTab == .notifications { Spacer() } 110 | } 111 | .padding(.horizontal, 8) 112 | } 113 | } 114 | 115 | struct TabBar_Previews: PreviewProvider { 116 | static var previews: some View { 117 | TabBar() 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Views/Modals/SignUpView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SignUpView.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 26/04/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct SignUpView: View { 11 | enum Field: Hashable { 12 | case email 13 | case password 14 | } 15 | 16 | @State var email = "" 17 | @State var password = "" 18 | @FocusState var focusedField: Field? 19 | @State var circleY: CGFloat = 120 20 | @State var emailY: CGFloat = 0 21 | @State var passwordY: CGFloat = 0 22 | @State var circleColor: Color = .blue 23 | @EnvironmentObject var model: Model 24 | 25 | var body: some View { 26 | VStack(alignment: .leading, spacing: 16) { 27 | Text("Sign up") 28 | .font(.largeTitle).bold() 29 | Text("Access 12+ hours of courses, tutorials and livestreams") 30 | .font(.headline) 31 | TextField("Email", text: $email) 32 | .inputStyle(icon: "mail") 33 | .textContentType(.emailAddress) 34 | .keyboardType(.emailAddress) 35 | .autocapitalization(.none) 36 | .disableAutocorrection(true) 37 | .focused($focusedField, equals: .email) 38 | .shadow(color: focusedField == .email ? .primary.opacity(0.3) : .clear, radius: 10, x: 0, y: 3) 39 | .overlay(geometry) 40 | .onPreferenceChange(CirclePreferenceKey.self) { value in 41 | emailY = value 42 | circleY = value 43 | } 44 | SecureField("Password", text: $password) 45 | .inputStyle(icon: "lock") 46 | .textContentType(.password) 47 | .focused($focusedField, equals: .password) 48 | .shadow(color: focusedField == .password ? .primary.opacity(0.3) : .clear, radius: 10, x: 0, y: 3) 49 | .overlay(geometry) 50 | .onPreferenceChange(CirclePreferenceKey.self) { value in 51 | passwordY = value 52 | } 53 | Button {} label: { 54 | Text("Create an account") 55 | .frame(maxWidth: .infinity) 56 | } 57 | .font(.headline) 58 | .blendMode(.overlay) 59 | .buttonStyle(.angular) 60 | .tint(.accentColor) 61 | .controlSize(.large) 62 | .shadow(color: Color("Shadow").opacity(0.2), radius: 30, x: 0, y: 30) 63 | 64 | Group { 65 | Text("By clicking on ") 66 | + Text("_Create an account_").foregroundColor(.primary.opacity(0.7)) 67 | + Text(", you agree to our **Terms of Service** and **[Privacy Policy](https://designcode.io)**") 68 | 69 | Divider() 70 | 71 | HStack { 72 | Text("Already have an account?") 73 | Button { 74 | model.selectedModal = .signIn 75 | } label: { 76 | Text("**Sign in**") 77 | } 78 | } 79 | } 80 | .font(.footnote) 81 | .foregroundColor(.secondary) 82 | .accentColor(.secondary) 83 | } 84 | .padding(20) 85 | .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 30, style: .continuous)) 86 | .background( 87 | Circle().fill(circleColor) 88 | .frame(width: 68, height: 68) 89 | .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) 90 | .offset(y: circleY) 91 | ) 92 | .coordinateSpace(name: "container") 93 | .strokeStyle(cornerRadius: 30) 94 | .onChange(of: focusedField) { value in 95 | withAnimation { 96 | if value == .email { 97 | circleY = emailY 98 | circleColor = .blue 99 | } else { 100 | circleY = passwordY 101 | circleColor = .red 102 | } 103 | } 104 | } 105 | } 106 | 107 | var geometry: some View { 108 | GeometryReader { proxy in 109 | Color.clear.preference(key: CirclePreferenceKey.self, value: proxy.frame(in: .named("container")).minY) 110 | } 111 | } 112 | } 113 | 114 | struct SignUpView_Previews: PreviewProvider { 115 | static var previews: some View { 116 | ZStack { 117 | SignUpView() 118 | .environmentObject(Model()) 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Views/Modals/SignInView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SignInView.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 02/05/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct SignInView: View { 11 | enum Field: Hashable { 12 | case email 13 | case password 14 | } 15 | 16 | @State var email = "" 17 | @State var password = "" 18 | @FocusState var focusedField: Field? 19 | @State var circleY: CGFloat = 120 20 | @State var emailY: CGFloat = 0 21 | @State var passwordY: CGFloat = 0 22 | @State var circleColor: Color = .blue 23 | @State var appear = [false, false, false] 24 | @EnvironmentObject var model: Model 25 | @AppStorage("isLogged") var isLogged = false 26 | 27 | var body: some View { 28 | VStack(alignment: .leading, spacing: 16) { 29 | Text("Sign in") 30 | .font(.largeTitle).bold() 31 | .opacity(appear[0] ? 1 : 0) 32 | .offset(y: appear[0] ? 0 : 20) 33 | Text("Access 12+ hours of courses, tutorials and livestreams") 34 | .font(.headline) 35 | .opacity(appear[1] ? 1 : 0) 36 | .offset(y: appear[1] ? 0 : 20) 37 | 38 | Group { 39 | TextField("Email", text: $email) 40 | .inputStyle(icon: "mail") 41 | .textContentType(.emailAddress) 42 | .keyboardType(.emailAddress) 43 | .autocapitalization(.none) 44 | .disableAutocorrection(true) 45 | .focused($focusedField, equals: .email) 46 | .shadow(color: focusedField == .email ? .primary.opacity(0.3) : .clear, radius: 10, x: 0, y: 3) 47 | .overlay(geometry) 48 | .onPreferenceChange(CirclePreferenceKey.self) { value in 49 | emailY = value 50 | circleY = value 51 | } 52 | SecureField("Password", text: $password) 53 | .inputStyle(icon: "lock") 54 | .textContentType(.password) 55 | .focused($focusedField, equals: .password) 56 | .shadow(color: focusedField == .password ? .primary.opacity(0.3) : .clear, radius: 10, x: 0, y: 3) 57 | .overlay(geometry) 58 | .onPreferenceChange(CirclePreferenceKey.self) { value in 59 | passwordY = value 60 | } 61 | Button { 62 | isLogged = true 63 | } label: { 64 | Text("Sign in") 65 | .frame(maxWidth: .infinity) 66 | } 67 | .font(.headline) 68 | .blendMode(.overlay) 69 | .buttonStyle(.angular) 70 | .tint(.accentColor) 71 | .controlSize(.large) 72 | .shadow(color: Color("Shadow").opacity(0.2), radius: 30, x: 0, y: 30) 73 | 74 | Divider() 75 | 76 | HStack { 77 | Text("No account yet?") 78 | Button { 79 | model.selectedModal = .signUp 80 | } label: { 81 | Text("**Sign up**") 82 | } 83 | } 84 | .font(.footnote) 85 | .foregroundColor(.secondary) 86 | .accentColor(.secondary) 87 | } 88 | .opacity(appear[2] ? 1 : 0) 89 | .offset(y: appear[2] ? 0 : 20) 90 | } 91 | .padding(20) 92 | .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 30, style: .continuous)) 93 | .background( 94 | Circle().fill(circleColor) 95 | .frame(width: 68, height: 68) 96 | .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) 97 | .offset(y: circleY) 98 | ) 99 | .coordinateSpace(name: "container") 100 | .strokeStyle(cornerRadius: 30) 101 | .onChange(of: focusedField) { value in 102 | withAnimation { 103 | if value == .email { 104 | circleY = emailY 105 | circleColor = .blue 106 | } else { 107 | circleY = passwordY 108 | circleColor = .red 109 | } 110 | } 111 | } 112 | .onAppear { 113 | withAnimation(.spring().delay(0.1)) { 114 | appear[0] = true 115 | } 116 | withAnimation(.spring().delay(0.2)) { 117 | appear[1] = true 118 | } 119 | withAnimation(.spring().delay(0.3)) { 120 | appear[2] = true 121 | } 122 | } 123 | } 124 | 125 | var geometry: some View { 126 | GeometryReader { proxy in 127 | Color.clear.preference(key: CirclePreferenceKey.self, value: proxy.frame(in: .named("container")).minY) 128 | } 129 | } 130 | } 131 | 132 | struct SignInView_Previews: PreviewProvider { 133 | static var previews: some View { 134 | ZStack { 135 | SignInView() 136 | .environmentObject(Model()) 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![cover](cover.png) 2 | 3 | Learn how I built a SwiftUI 3 app with custom layouts, animations and gestures using Xcode 13, SF Symbols 3, Canvas, Concurrency, Searchable and a whole lot more. 4 | 5 | ## What you'll build 6 | 7 | We'll build an iOS 15 app from scratch focusing on custom layout techniques, animations and interactions. We'll build our own custom Tab Bar, Navigation Bar and interactions. While SwiftUI hasn't changed significantly over the past 3 years, the framework is far more comprehensive, with more concise code for state management, animation and now fully supporting effects like blur material. 8 | 9 | 10 | ## Requirements 11 | 12 | This app was built with **Xcode 13**, **iOS 15** and **MacOS Monterey**. It's important that you meet these requirements, as some newly introduced features are only available after iOS 15 and in Xcode 13. 13 | 14 | ![mac](mac.png) 15 | 16 | ## Custom Modifiers 17 | 18 | When you repeat the same modifiers or collection of styles over and over, it is a good idea to start your custom modifiers. A huge advantage with this technique is that you can isolate the styles, just like a component, and apply conditions based on resolutions and devices. Also, when you apply changes, it'll apply everywhere at once. 19 | 20 | ```swift 21 | struct BackgroundStyle: ViewModifier { 22 | var cornerRadius: CGFloat = 20 23 | var opacity: Double = 0.6 24 | @AppStorage("isLiteMode") var isLiteMode = true 25 | 26 | func body(content: Content) -> some View { 27 | content 28 | .backgroundColor(opacity: opacity) 29 | .cornerRadius(cornerRadius) 30 | .shadow(color: Color("Shadow").opacity(isLiteMode ? 0 : 0.3), radius: 20, x: 0, y: 10) 31 | } 32 | } 33 | ``` 34 | 35 | ## Searchable 36 | 37 | It's never been easier to create a search experience with text field focus and suggestions. In this course, we'll learn to customize the looks while building a search experience with data and search completion. 38 | 39 | ```swift 40 | searchable(text: $text) { 41 | ForEach(suggestions) { suggestion in 42 | Button { 43 | text = suggestion.text 44 | } label: { 45 | Text(suggestion.text) 46 | } 47 | .searchCompletion(suggestion.text) 48 | } 49 | } 50 | ``` 51 | 52 | ## Custom Tab Bar 53 | 54 | One of the things I wanted to teach in this course is how to create a fully custom user interface and all the challenges that come with creating a custom tab bar and navigation bar. Understanding this can not only help with building an app that stand out but also a great way to prototyping techniques on a real platform that developers use. 55 | 56 | ![tabBar](tabBar.png) 57 | 58 | ## Custom Navigation Bar 59 | 60 | When you have a custom tab bar, it makes sense to pair it with a custom navigation bar. While it is recommended to use the built-in Navigation View and Tab View for best adaptability across platforms and accessibility, learning how to build and style your own will take your skills to the next level. Popular apps like Instagram, TikTok, Clubhouse actually build their very own bars. For designers, this is fantastic for prototyping since you will have less contraints and are not forced to use the stock user interface for everything. 61 | 62 | ![navBar](navBar.png) 63 | 64 | ## Concurrency 65 | 66 | Working with functions that need to wait for tasks to complete such as an API call is now much easier with async / await. Before, you had to use completion handlers which can make the code difficult to read and debug. With concurrency, your code will be shorter, safer and you will have access to the new AsyncImage and Pull to Refresh features that leverage on the new API. 67 | 68 | ##### ASYNCIMAGE 69 | 70 | [AsyncImage](https://developer.apple.com/documentation/swiftui/asyncimage) allows you to load an image from a URL without relying on a third-party library. It offers great features like placeholder while loading and phases for error handling. On top of that, you can easily apply transitions and animations. 71 | 72 | Let's load an image from [Lorem Picsum](https://picsum.photos) with placeholder that shows a loading indicator. 73 | 74 | ```swift 75 | AsyncImage(url: URL(string: "https://picsum.photos/200"), transaction: .init(animation: .easeOut)) { phase in 76 | switch phase { 77 | case .empty: 78 | Color.white 79 | case .success(let image): 80 | image.resizable().transition(.scale) 81 | case .failure(_): 82 | Color.gray 83 | @unknown default: 84 | Color.gray 85 | } 86 | } 87 | ``` 88 | 89 | ##### ASYNC / AWAIT 90 | 91 | We can create an async function that gets data from an API without using completion handlers. Before decoding the JSON data, we have to wait for the API call to complete. Also, we're using do / catch to handle errors. 92 | 93 | ```swift 94 | func fetchAddress() async { 95 | do { 96 | let url = URL(string: "https://random-data-api.com/api/address/random_address")! 97 | let (data, _) = try await URLSession.shared.data(from: url) 98 | address = try JSONDecoder().decode(Address.self, from: data) 99 | } catch { 100 | print("Error fetching") 101 | } 102 | } 103 | ``` 104 | 105 | We can call the async function using the new task modifier. 106 | 107 | ```swift 108 | .task { 109 | await fetchAddress() 110 | } 111 | ``` 112 | 113 | ##### PULL TO REFRESH 114 | 115 | If you need to refresh the data, you can use the new refreshable modifier, which automatically creates the Pull to Refresh mechanism on a List. 116 | 117 | ```swift 118 | .refreshable { 119 | await fetchAddress() 120 | } 121 | ``` 122 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Views/Detail/SectionView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SectionView.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 07/06/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct SectionView: View { 11 | var section: CourseSection = courseSections[0] 12 | @EnvironmentObject var model: Model 13 | @Environment(\.dismiss) var dismiss 14 | 15 | var body: some View { 16 | ZStack { 17 | ScrollView { 18 | cover 19 | .overlay(PlayView().overlay(CircularView(value: section.progress, lineWidth: 5).padding(24))) 20 | 21 | content 22 | .offset(y: 120) 23 | .padding(.bottom, 200) 24 | } 25 | .background(Color("Background")) 26 | .ignoresSafeArea() 27 | 28 | button 29 | } 30 | } 31 | 32 | var cover: some View { 33 | VStack { 34 | Spacer() 35 | } 36 | .frame(maxWidth: .infinity) 37 | .frame(height: 500) 38 | .foregroundStyle(.black) 39 | .background( 40 | Image(section.image) 41 | .resizable() 42 | .aspectRatio(contentMode: .fit) 43 | .padding(20) 44 | .frame(maxWidth: 500) 45 | ) 46 | .background( 47 | Image(section.background) 48 | .resizable() 49 | .aspectRatio(contentMode: .fill) 50 | ) 51 | .mask( 52 | RoundedRectangle(cornerRadius: 0, style: .continuous) 53 | ) 54 | .overlay( 55 | overlayContent 56 | ) 57 | .frame(height: 500) 58 | } 59 | 60 | var content: some View { 61 | VStack(alignment: .leading, spacing: 30) { 62 | Text("SwiftUI is hands-down the best way for designers to take a first step into code. ") 63 | .font(.title3).fontWeight(.medium) 64 | Text("This course") 65 | .font(.title).bold() 66 | Text("This course is unlike any other. We care about design and want to make sure that you get better at it in the process. It was written for designers and developers who are passionate about collaborating and building real apps for iOS and macOS. While it's not one codebase for all apps, you learn once and can apply the techniques and controls to all platforms with incredible quality, consistency and performance. It's beginner-friendly, but it's also packed with design tricks and efficient workflows for building great user interfaces and interactions.") 67 | Text("This year, SwiftUI got major upgrades from the WWDC 2020. The big news is that thanks to Apple Silicon, Macs will be able to run iOS and iPad apps soon. SwiftUI is the only framework that allows you to build apps for all of Apple's five platforms: iOS, iPadOS, macOS, tvOS and watchOS with the same codebase. New features like the Sidebar, Lazy Grid, Matched Geometry Effect and Xcode 12's visual editing tools will make it easier than ever to build for multiple platforms.") 68 | Text("Multiplatform app") 69 | .font(.title).bold() 70 | Text("For the first time, you can build entire apps using SwiftUI only. In Xcode 12, you can now create multi-platform apps with minimal code changes. SwiftUI will automatically translate the navigation, fonts, forms and controls to its respective platform. For example, a sidebar will look differently on the Mac versus the iPad, while using exactly the same code. Dynamic type will adjust for the appropriate platform language, readability and information density. ") 71 | } 72 | .padding(20) 73 | } 74 | 75 | var button: some View { 76 | Button { 77 | dismiss() 78 | } label: { 79 | Image(systemName: "xmark") 80 | .font(.body.weight(.bold)) 81 | .foregroundColor(.secondary) 82 | .padding(8) 83 | .background(.ultraThinMaterial, in: Circle()) 84 | } 85 | .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing) 86 | .padding(20) 87 | .ignoresSafeArea() 88 | } 89 | 90 | var overlayContent: some View { 91 | VStack(alignment: .leading, spacing: 12) { 92 | Text(section.title) 93 | .font(.largeTitle.weight(.bold)) 94 | .frame(maxWidth: .infinity, alignment: .leading) 95 | 96 | Text(section.subtitle.uppercased()) 97 | .font(.footnote.weight(.semibold)) 98 | Text(section.text) 99 | .font(.footnote) 100 | Divider() 101 | .opacity(0) 102 | HStack { 103 | Image("Avatar Default") 104 | .resizable() 105 | .frame(width: 26, height: 26) 106 | .cornerRadius(10) 107 | .padding(8) 108 | .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 18, style: .continuous)) 109 | .strokeStyle(cornerRadius: 18) 110 | Text("Taught by Meng To") 111 | .font(.footnote) 112 | } 113 | .opacity(0) 114 | } 115 | .padding(20) 116 | .background( 117 | Rectangle() 118 | .fill(.ultraThinMaterial) 119 | .mask(RoundedRectangle(cornerRadius: 30, style: .continuous)) 120 | ) 121 | .offset(y: 250) 122 | .padding(20) 123 | } 124 | } 125 | 126 | struct SectionView_Previews: PreviewProvider { 127 | static var previews: some View { 128 | SectionView() 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Views/Main/HomeView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HomeView.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 31/03/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct HomeView: View { 11 | @State var hasScrolled = false 12 | @Namespace var namespace 13 | @State var show = false 14 | @State var showStatusBar = true 15 | @State var selectedID = UUID() 16 | @State var showCourse = false 17 | @State var selectedIndex = 0 18 | @EnvironmentObject var model: Model 19 | @AppStorage("isLiteMode") var isLiteMode = true 20 | 21 | var body: some View { 22 | ZStack { 23 | Color("Background").ignoresSafeArea() 24 | 25 | ScrollView { 26 | scrollDetection 27 | 28 | featured 29 | 30 | Text("Courses".uppercased()) 31 | .font(.footnote.weight(.semibold)) 32 | .foregroundColor(.secondary) 33 | .frame(maxWidth: .infinity, alignment: .leading) 34 | .padding(.horizontal, 20) 35 | 36 | LazyVGrid(columns: [GridItem(.adaptive(minimum: 300), spacing: 20)], spacing: 20) { 37 | if !show { 38 | cards 39 | } else { 40 | ForEach(courses) { course in 41 | Rectangle() 42 | .fill(.white) 43 | .frame(height: 300) 44 | .cornerRadius(30) 45 | .shadow(color: Color("Shadow"), radius: 20, x: 0, y: 10) 46 | .opacity(0.3) 47 | .padding(.horizontal, 30) 48 | } 49 | } 50 | } 51 | .padding(.horizontal, 20) 52 | } 53 | .coordinateSpace(name: "scroll") 54 | .safeAreaInset(edge: .top, content: { 55 | Color.clear.frame(height: 70) 56 | }) 57 | .overlay( 58 | NavigationBar(title: "Featured", hasScrolled: $hasScrolled) 59 | ) 60 | 61 | if show { 62 | detail 63 | } 64 | } 65 | .statusBar(hidden: !showStatusBar) 66 | .onChange(of: show) { newValue in 67 | withAnimation(.closeCard) { 68 | if newValue { 69 | showStatusBar = false 70 | } else { 71 | showStatusBar = true 72 | } 73 | } 74 | } 75 | } 76 | 77 | var scrollDetection: some View { 78 | GeometryReader { proxy in 79 | // Text("\(proxy.frame(in: .named("scroll")).minY)") 80 | Color.clear.preference(key: ScrollPreferenceKey.self, value: proxy.frame(in: .named("scroll")).minY) 81 | } 82 | .frame(height: 0) 83 | .onPreferenceChange(ScrollPreferenceKey.self, perform: { value in 84 | withAnimation(.easeInOut) { 85 | if value < 0 { 86 | hasScrolled = true 87 | } else { 88 | hasScrolled = false 89 | } 90 | } 91 | }) 92 | } 93 | 94 | var featured: some View { 95 | TabView { 96 | ForEach(Array(featuredCourses.enumerated()), id: \.offset) { index, course in 97 | GeometryReader { proxy in 98 | let minX = proxy.frame(in: .global).minX 99 | 100 | FeaturedItem(course: course) 101 | .frame(maxWidth: 500) 102 | .frame(maxWidth: .infinity) 103 | .padding(.vertical, 40) 104 | .rotation3DEffect(.degrees(minX / -10), axis: (x: 0, y: 1, z: 0)) 105 | .shadow(color: Color("Shadow").opacity(isLiteMode ? 0 : 0.3), radius: 5, x: 0, y: 3) 106 | .blur(radius: abs(minX / 40)) 107 | .overlay( 108 | Image(course.image) 109 | .resizable() 110 | .aspectRatio(contentMode: .fit) 111 | .frame(height: 230) 112 | .offset(x: 32, y: -80) 113 | .offset(x: minX / 2) 114 | ) 115 | .onTapGesture { 116 | showCourse = true 117 | selectedIndex = index 118 | } 119 | .accessibilityElement(children: .combine) 120 | .accessibilityAddTraits(.isButton) 121 | 122 | // Text("\(proxy.frame(in: .global).minX)") 123 | } 124 | } 125 | } 126 | .tabViewStyle(.page(indexDisplayMode: .never)) 127 | .frame(height: 430) 128 | .background( 129 | Image("Blob 1") 130 | .offset(x: 250, y: -100) 131 | .accessibility(hidden: true) 132 | ) 133 | .sheet(isPresented: $showCourse) { 134 | CourseView(namespace: namespace, course: featuredCourses[selectedIndex], show: $showCourse) 135 | } 136 | } 137 | 138 | var cards: some View { 139 | ForEach(courses) { course in 140 | CourseItem(namespace: namespace, course: course, show: $show) 141 | .onTapGesture { 142 | withAnimation(.openCard) { 143 | show.toggle() 144 | model.showDetail.toggle() 145 | showStatusBar = false 146 | selectedID = course.id 147 | } 148 | } 149 | .accessibilityElement(children: .combine) 150 | .accessibilityAddTraits(.isButton) 151 | } 152 | } 153 | 154 | var detail: some View { 155 | ForEach(courses) { course in 156 | if course.id == selectedID { 157 | CourseView(namespace: namespace, course: course, show: $show) 158 | .zIndex(1) 159 | .transition(.asymmetric( 160 | insertion: .opacity.animation(.easeInOut(duration: 0.1)), 161 | removal: .opacity.animation(.easeInOut(duration: 0.3).delay(0.2)))) 162 | } 163 | } 164 | } 165 | } 166 | 167 | struct HomeView_Previews: PreviewProvider { 168 | static var previews: some View { 169 | HomeView() 170 | .preferredColorScheme(.dark) 171 | .environmentObject(Model()) 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Blobs/Blob 1.imageset/Blob 1 Dark.pdf: -------------------------------------------------------------------------------- 1 | %PDF-1.7 2 | 3 | 1 0 obj 4 | << /Length 2 0 R 5 | /FunctionType 4 6 | /Domain [ 0.000000 1.000000 ] 7 | /Range [ 0.000000 1.000000 0.000000 1.000000 0.000000 1.000000 ] 8 | >> 9 | stream 10 | { 0.680000 exch 0.000000 exch 1.000000 exch dup 0.000000 gt { exch pop exch pop exch pop dup 0.000000 sub -0.617441 mul 0.680000 add exch dup 0.000000 sub 0.346745 mul 0.000000 add exch dup 0.000000 sub -0.117162 mul 1.000000 add exch } if dup 0.497884 gt { exch pop exch pop exch pop dup 0.497884 sub 1.249540 mul 0.372586 add exch dup 0.497884 sub 0.270245 mul 0.172639 add exch dup 0.497884 sub -0.104225 mul 0.941667 add exch } if dup 1.000000 gt { exch pop exch pop exch pop 1.000000 exch 0.308333 exch 0.889333 exch } if pop } 11 | endstream 12 | endobj 13 | 14 | 2 0 obj 15 | 533 16 | endobj 17 | 18 | 3 0 obj 19 | << /Length 4 0 R 20 | /FunctionType 4 21 | /Domain [ 0.000000 1.000000 ] 22 | /Range [ 0.000000 1.000000 0.000000 1.000000 0.000000 1.000000 ] 23 | >> 24 | stream 25 | { 0.354046 exch 0.111250 exch 0.741667 exch dup 0.000000 gt { exch pop exch pop exch pop dup 0.000000 sub -0.185418 mul 0.354046 add exch dup 0.000000 sub -0.032819 mul 0.111250 add exch dup 0.000000 sub -0.200490 mul 0.741667 add exch } if dup 1.000000 gt { exch pop exch pop exch pop 0.168627 exch 0.078431 exch 0.541176 exch } if pop } 26 | endstream 27 | endobj 28 | 29 | 4 0 obj 30 | 339 31 | endobj 32 | 33 | 5 0 obj 34 | << /BBox [ 0.000000 0.000000 738.000000 504.000000 ] 35 | /Resources << /ExtGState << /E1 << /ca 0.800000 >> >> 36 | /Pattern << /P2 << /Matrix [ -89.297676 541.385132 541.385132 89.297676 -481.977722 -133.584229 ] 37 | /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] 38 | /Extend [ true true ] 39 | /Domain [ 0.000000 1.000000 ] 40 | /ShadingType 2 41 | /ColorSpace /DeviceRGB 42 | /Function 1 0 R 43 | >> 44 | /PatternType 2 45 | /Type /Pattern 46 | >> 47 | /P1 << /Matrix [ 298.970886 -350.692474 350.692474 298.970886 -285.305023 71.329773 ] 48 | /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] 49 | /Extend [ true true ] 50 | /Domain [ 0.000000 1.000000 ] 51 | /ShadingType 2 52 | /ColorSpace /DeviceRGB 53 | /Function 3 0 R 54 | >> 55 | /PatternType 2 56 | /Type /Pattern 57 | >> 58 | >> 59 | >> 60 | /Subtype /Form 61 | /Length 6 0 R 62 | /Group << /Type /Group 63 | /S /Transparency 64 | >> 65 | /Type /XObject 66 | >> 67 | stream 68 | /DeviceRGB CS 69 | /DeviceRGB cs 70 | q 71 | 1.000000 0.000000 -0.000000 1.000000 0.000061 -44.392426 cm 72 | /Pattern cs 73 | /P1 scn 74 | 269.428467 138.087189 m 75 | 59.709106 37.050446 -66.856354 274.893402 37.016521 409.180908 c 76 | 81.218369 466.325256 141.662384 528.442871 233.870117 464.037445 c 77 | 309.190613 411.427429 347.637177 484.222870 411.657196 472.823273 c 78 | 466.548828 463.049133 518.117920 484.894348 580.558960 451.957031 c 79 | 643.000000 419.019714 735.000000 367.392426 707.000000 273.392426 c 80 | 679.000000 179.392426 680.257019 126.020905 587.459961 102.115662 c 81 | 476.617310 73.561737 422.856384 221.272125 269.428467 138.087189 c 82 | h 83 | f 84 | n 85 | Q 86 | q 87 | /E1 gs 88 | 1.000000 0.000000 -0.000000 -1.000000 52.000000 663.580322 cm 89 | /Pattern cs 90 | /P2 scn 91 | 419.097107 207.780243 m 92 | 126.230804 38.736938 -94.074966 361.207092 40.412846 546.306396 c 93 | 128.815689 667.977661 229.274109 701.694885 348.658661 612.919678 c 94 | 446.178711 540.403015 464.187622 638.877441 563.593811 630.728882 c 95 | 663.000000 622.580261 743.000000 382.580261 630.000000 330.580261 c 96 | 517.000000 278.580261 574.000000 297.190674 419.097107 207.780243 c 97 | h 98 | f 99 | n 100 | Q 101 | 102 | endstream 103 | endobj 104 | 105 | 6 0 obj 106 | 1074 107 | endobj 108 | 109 | 7 0 obj 110 | << /BBox [ 0.000000 0.000000 738.000000 504.000000 ] 111 | /Resources << >> 112 | /Subtype /Form 113 | /Length 8 0 R 114 | /Group << /Type /Group 115 | /S /Transparency 116 | >> 117 | /Type /XObject 118 | >> 119 | stream 120 | /DeviceRGB CS 121 | /DeviceRGB cs 122 | q 123 | 1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm 124 | 0.000000 0.000000 0.000000 scn 125 | 0.000000 504.000000 m 126 | 738.000000 504.000000 l 127 | 738.000000 0.000000 l 128 | 0.000000 0.000000 l 129 | 0.000000 504.000000 l 130 | h 131 | f 132 | n 133 | Q 134 | 135 | endstream 136 | endobj 137 | 138 | 8 0 obj 139 | 237 140 | endobj 141 | 142 | 9 0 obj 143 | << /XObject << /X1 5 0 R >> 144 | /ExtGState << /E1 << /SMask << /Type /Mask 145 | /G 7 0 R 146 | /S /Alpha 147 | >> 148 | /Type /ExtGState 149 | >> >> 150 | >> 151 | endobj 152 | 153 | 10 0 obj 154 | << /Length 11 0 R >> 155 | stream 156 | /DeviceRGB CS 157 | /DeviceRGB cs 158 | q 159 | /E1 gs 160 | /X1 Do 161 | Q 162 | 163 | endstream 164 | endobj 165 | 166 | 11 0 obj 167 | 46 168 | endobj 169 | 170 | 12 0 obj 171 | << /Annots [] 172 | /Type /Page 173 | /MediaBox [ 0.000000 0.000000 738.000000 504.000000 ] 174 | /Resources 9 0 R 175 | /Contents 10 0 R 176 | /Parent 13 0 R 177 | >> 178 | endobj 179 | 180 | 13 0 obj 181 | << /Kids [ 12 0 R ] 182 | /Count 1 183 | /Type /Pages 184 | >> 185 | endobj 186 | 187 | 14 0 obj 188 | << /Type /Catalog 189 | /Pages 13 0 R 190 | >> 191 | endobj 192 | 193 | xref 194 | 0 15 195 | 0000000000 65535 f 196 | 0000000010 00000 n 197 | 0000000727 00000 n 198 | 0000000749 00000 n 199 | 0000001272 00000 n 200 | 0000001294 00000 n 201 | 0000004235 00000 n 202 | 0000004258 00000 n 203 | 0000004745 00000 n 204 | 0000004767 00000 n 205 | 0000005065 00000 n 206 | 0000005169 00000 n 207 | 0000005191 00000 n 208 | 0000005369 00000 n 209 | 0000005445 00000 n 210 | trailer 211 | << /ID [ (some) (id) ] 212 | /Root 14 0 R 213 | /Size 15 214 | >> 215 | startxref 216 | 5506 217 | %%EOF -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Blobs/Blob 1.imageset/Blob 1.pdf: -------------------------------------------------------------------------------- 1 | %PDF-1.7 2 | 3 | 1 0 obj 4 | << /Length 2 0 R 5 | /FunctionType 4 6 | /Domain [ 0.000000 1.000000 ] 7 | /Range [ 0.000000 1.000000 0.000000 1.000000 0.000000 1.000000 ] 8 | >> 9 | stream 10 | { 0.294118 exch 0.721569 exch 0.976471 exch dup 0.000000 gt { exch pop exch pop exch pop dup 0.000000 sub 1.192122 mul 0.294118 add exch dup 0.000000 sub -0.409564 mul 0.721569 add exch dup 0.000000 sub -0.285232 mul 0.976471 add exch } if dup 0.536200 gt { exch pop exch pop exch pop dup 0.536200 sub 0.067642 mul 0.933333 add exch dup 0.536200 sub 0.591871 mul 0.501961 add exch dup 0.536200 sub 0.219838 mul 0.823529 add exch } if dup 1.000000 gt { exch pop exch pop exch pop 0.964706 exch 0.776471 exch 0.925490 exch } if pop } 11 | endstream 12 | endobj 13 | 14 | 2 0 obj 15 | 532 16 | endobj 17 | 18 | 3 0 obj 19 | << /Length 4 0 R 20 | /FunctionType 4 21 | /Domain [ 0.000000 1.000000 ] 22 | /Range [ 0.000000 1.000000 0.000000 1.000000 0.000000 1.000000 ] 23 | >> 24 | stream 25 | { 1.000000 exch 0.000000 exch 0.622857 exch dup 0.000000 gt { exch pop exch pop exch pop dup 0.000000 sub -0.020047 mul 1.000000 add exch dup 0.000000 sub 0.938222 mul 0.000000 add exch dup 0.000000 sub 0.024744 mul 0.622857 add exch } if dup 0.978070 gt { exch pop exch pop exch pop 0.980392 exch 0.917647 exch 0.647059 exch } if pop } 26 | endstream 27 | endobj 28 | 29 | 4 0 obj 30 | 337 31 | endobj 32 | 33 | 5 0 obj 34 | << /BBox [ 0.000000 0.000000 738.000000 504.000000 ] 35 | /Resources << /ExtGState << /E1 << /ca 0.500000 >> >> 36 | /Pattern << /P2 << /Matrix [ -89.297676 541.385132 541.385132 89.297676 -481.977722 -133.584259 ] 37 | /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] 38 | /Extend [ true true ] 39 | /Domain [ 0.000000 1.000000 ] 40 | /ShadingType 2 41 | /ColorSpace /DeviceRGB 42 | /Function 1 0 R 43 | >> 44 | /PatternType 2 45 | /Type /Pattern 46 | >> 47 | /P1 << /Matrix [ 229.685791 -453.308228 809.726501 128.584808 -295.864685 436.983002 ] 48 | /Shading << /Coords [ 0.500000 0.500000 0.000000 0.500000 0.500000 0.500000 ] 49 | /Extend [ true true ] 50 | /Domain [ 0.000000 1.000000 ] 51 | /ShadingType 3 52 | /ColorSpace /DeviceRGB 53 | /Function 3 0 R 54 | >> 55 | /PatternType 2 56 | /Type /Pattern 57 | >> 58 | >> 59 | >> 60 | /Subtype /Form 61 | /Length 6 0 R 62 | /Group << /Type /Group 63 | /S /Transparency 64 | >> 65 | /Type /XObject 66 | >> 67 | stream 68 | /DeviceRGB CS 69 | /DeviceRGB cs 70 | q 71 | 1.000000 0.000000 -0.000000 1.000000 0.000061 -44.392426 cm 72 | /Pattern cs 73 | /P1 scn 74 | 269.428467 138.087189 m 75 | 59.709106 37.050446 -66.856354 274.893402 37.016521 409.180908 c 76 | 81.218369 466.325256 141.662384 528.442871 233.870117 464.037445 c 77 | 309.190613 411.427429 347.637177 484.222870 411.657196 472.823273 c 78 | 466.548828 463.049133 518.117920 484.894348 580.558960 451.957031 c 79 | 643.000000 419.019714 735.000000 367.392426 707.000000 273.392426 c 80 | 679.000000 179.392426 680.257019 126.020905 587.459961 102.115662 c 81 | 476.617310 73.561737 422.856384 221.272125 269.428467 138.087189 c 82 | h 83 | f 84 | n 85 | Q 86 | q 87 | /E1 gs 88 | 1.000000 0.000000 -0.000000 -1.000000 52.000000 663.580322 cm 89 | /Pattern cs 90 | /P2 scn 91 | 419.097107 207.780243 m 92 | 126.230804 38.736938 -94.074966 361.207092 40.412846 546.306396 c 93 | 128.815689 667.977661 229.274109 701.694885 348.658661 612.919678 c 94 | 446.178711 540.403015 464.187622 638.877441 563.593811 630.728882 c 95 | 663.000000 622.580261 743.000000 382.580261 630.000000 330.580261 c 96 | 517.000000 278.580261 574.000000 297.190674 419.097107 207.780243 c 97 | h 98 | f 99 | n 100 | Q 101 | 102 | endstream 103 | endobj 104 | 105 | 6 0 obj 106 | 1074 107 | endobj 108 | 109 | 7 0 obj 110 | << /BBox [ 0.000000 0.000000 738.000000 504.000000 ] 111 | /Resources << >> 112 | /Subtype /Form 113 | /Length 8 0 R 114 | /Group << /Type /Group 115 | /S /Transparency 116 | >> 117 | /Type /XObject 118 | >> 119 | stream 120 | /DeviceRGB CS 121 | /DeviceRGB cs 122 | q 123 | 1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm 124 | 0.000000 0.000000 0.000000 scn 125 | 0.000000 504.000000 m 126 | 738.000000 504.000000 l 127 | 738.000000 0.000000 l 128 | 0.000000 0.000000 l 129 | 0.000000 504.000000 l 130 | h 131 | f 132 | n 133 | Q 134 | 135 | endstream 136 | endobj 137 | 138 | 8 0 obj 139 | 237 140 | endobj 141 | 142 | 9 0 obj 143 | << /XObject << /X1 5 0 R >> 144 | /ExtGState << /E1 << /SMask << /Type /Mask 145 | /G 7 0 R 146 | /S /Alpha 147 | >> 148 | /Type /ExtGState 149 | >> >> 150 | >> 151 | endobj 152 | 153 | 10 0 obj 154 | << /Length 11 0 R >> 155 | stream 156 | /DeviceRGB CS 157 | /DeviceRGB cs 158 | q 159 | /E1 gs 160 | /X1 Do 161 | Q 162 | 163 | endstream 164 | endobj 165 | 166 | 11 0 obj 167 | 46 168 | endobj 169 | 170 | 12 0 obj 171 | << /Annots [] 172 | /Type /Page 173 | /MediaBox [ 0.000000 0.000000 738.000000 504.000000 ] 174 | /Resources 9 0 R 175 | /Contents 10 0 R 176 | /Parent 13 0 R 177 | >> 178 | endobj 179 | 180 | 13 0 obj 181 | << /Kids [ 12 0 R ] 182 | /Count 1 183 | /Type /Pages 184 | >> 185 | endobj 186 | 187 | 14 0 obj 188 | << /Type /Catalog 189 | /Pages 13 0 R 190 | >> 191 | endobj 192 | 193 | xref 194 | 0 15 195 | 0000000000 65535 f 196 | 0000000010 00000 n 197 | 0000000726 00000 n 198 | 0000000748 00000 n 199 | 0000001269 00000 n 200 | 0000001291 00000 n 201 | 0000004251 00000 n 202 | 0000004274 00000 n 203 | 0000004761 00000 n 204 | 0000004783 00000 n 205 | 0000005081 00000 n 206 | 0000005185 00000 n 207 | 0000005207 00000 n 208 | 0000005385 00000 n 209 | 0000005461 00000 n 210 | trailer 211 | << /ID [ (some) (id) ] 212 | /Root 14 0 R 213 | /Size 15 214 | >> 215 | startxref 216 | 5522 217 | %%EOF -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Views/Sheets/AccountView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AccountView.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 16/02/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct AccountView: View { 11 | 12 | @State var isDeleated = false 13 | @State var isPineed = false 14 | @State var address: Address = Address(id: 1, country: "Canada") 15 | @Environment(\.dismiss) var dismiss 16 | @AppStorage("isLogged") var isLoegged = false 17 | @AppStorage("isLiteMode") var isLiteMode = true 18 | @ObservedObject var coinModel = CoinModel() 19 | 20 | func fetchAddress() async { 21 | do { 22 | let url = URL(string: "https://random-data-api.com/api/address/random_address")! 23 | let (data, _) = try await URLSession.shared.data(from: url) 24 | address = try JSONDecoder().decode(Address.self, from: data) 25 | } catch { 26 | address = Address(id: 1, country: "Error Fatching") 27 | } 28 | 29 | } 30 | 31 | var body: some View { 32 | NavigationView { 33 | List { 34 | 35 | profile 36 | 37 | menu 38 | 39 | Section{ 40 | Toggle(isOn: $isLiteMode){ 41 | Label("Lite Mode", systemImage: isLiteMode ? "tortoise" : "hare") 42 | } 43 | } 44 | .accentColor(.primary) 45 | 46 | links 47 | 48 | coins 49 | 50 | Button{ 51 | isLoegged = false 52 | dismiss() 53 | } label: { 54 | Text("Sign out") 55 | } 56 | .tint(.red) 57 | 58 | } 59 | .task { 60 | await fetchAddress() 61 | await coinModel.fetchCoins() 62 | } 63 | .refreshable { 64 | await fetchAddress() 65 | await coinModel.fetchCoins() 66 | } 67 | .listStyle(.insetGrouped) 68 | .navigationTitle("Account") 69 | .navigationBarItems(trailing: Button { dismiss() } label: { Text("Done").bold() }) 70 | } 71 | } 72 | 73 | var profile: some View { 74 | VStack(spacing: 8){ 75 | Image(systemName: 76 | "person.crop.circle.fill.badge.checkmark") 77 | .symbolVariant(.circle.fill) 78 | .font(.system(size: 32)) 79 | .symbolRenderingMode(.palette) 80 | .foregroundStyle(.blue, .blue.opacity(0.3)) 81 | .padding() 82 | .background(Circle().fill(.ultraThinMaterial)) 83 | .background( 84 | HexagonView() 85 | // Image(systemName: "hexagon") 86 | // .symbolVariant(.fill) 87 | // .foregroundColor(.blue) 88 | // .font(.system(size: 200)) 89 | .offset(x: -50, y: -100) 90 | ) 91 | .background( 92 | BlobView() 93 | .offset(x: 200, y: 0) 94 | .scaleEffect(0.6) 95 | ) 96 | Text("João Carlos Magalhães") 97 | .font(.title.weight(.semibold)) 98 | HStack{ 99 | Image(systemName: "location") 100 | .imageScale(.large) 101 | Text(address.country) 102 | .foregroundColor(.secondary) 103 | } 104 | } 105 | .frame(maxWidth: .infinity) 106 | .padding() 107 | } 108 | 109 | var menu: some View{ 110 | Section { 111 | NavigationLink(destination: HomeView()){ 112 | Label("Settings", systemImage: "gear") 113 | } 114 | NavigationLink { Text("Billing") } label: { 115 | Label("Billing", systemImage: "creditcard") 116 | } 117 | NavigationLink { HomeView() } label: { 118 | Label("Help", systemImage: "questionmark") 119 | } 120 | } 121 | .accentColor(.primary) 122 | .listRowSeparatorTint(.blue) 123 | .listRowSeparator(.hidden) 124 | } 125 | 126 | var links: some View { 127 | Section{ 128 | if !isDeleated { 129 | Link(destination: URL(string: "https://apple.com")!){ 130 | HStack{ 131 | Label("Website", systemImage: "house") 132 | Spacer() 133 | Image(systemName: "link") 134 | .foregroundColor(.secondary) 135 | } 136 | } 137 | .swipeActions(edge: .leading, allowsFullSwipe: true) { 138 | Button(action: { isDeleated = true }) { 139 | Label("Delete", systemImage: "trash") 140 | } 141 | .tint(.red) 142 | 143 | pinButton 144 | 145 | } 146 | } 147 | Link(destination: URL(string: "https://youtube.com")!){ 148 | HStack{ 149 | Label("YouTube", systemImage: "tv") 150 | Spacer() 151 | Image(systemName: "link") 152 | .foregroundColor(.secondary) 153 | } 154 | } 155 | .swipeActions{ 156 | pinButton 157 | } 158 | } 159 | .accentColor(.primary) 160 | .listRowSeparator(.hidden) 161 | } 162 | 163 | var coins: some View{ 164 | Section(header: Text("Coins")){ 165 | ForEach(coinModel.coins){ coin in 166 | HStack { 167 | AsyncImage(url: URL(string: coin.logo)){ image in 168 | image.resizable() 169 | .aspectRatio(contentMode: .fit) 170 | } placeholder: { 171 | ProgressView() 172 | } 173 | .frame(width: 32, height: 32) 174 | VStack(alignment: .leading, spacing: 2) { 175 | Text(coin.coin_name) 176 | Text(coin.acronym) 177 | .font(.caption) 178 | .foregroundColor(.secondary) 179 | } 180 | } 181 | } 182 | } 183 | } 184 | 185 | var pinButton: some View{ 186 | Button { isPineed.toggle() } label: { 187 | if isPineed{ 188 | Label("Unpin", systemImage: "pin.slash") 189 | } else{ 190 | Label("Pin", systemImage: "pin") 191 | } 192 | 193 | } 194 | .tint(isPineed ? .gray : .yellow) 195 | } 196 | } 197 | 198 | struct AccountView_Previews: PreviewProvider { 199 | static var previews: some View { 200 | AccountView() 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Model/Course.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Course.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 31/03/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct Course: Identifiable { 11 | let id = UUID() 12 | var title : String 13 | var subtitle : String 14 | var text : String 15 | var image : String 16 | var background : String 17 | var logo : String 18 | 19 | var contentDescription: String 20 | var contentTitle : String 21 | var contentText1 : String 22 | var contentText2 : String 23 | var avatar : String 24 | var avatarDescription : String 25 | } 26 | 27 | var featuredCourses = [ 28 | Course(title: "SwiftUI for iOS 15", subtitle: "20 sections - 3 hours", text: "Learn how I buit an iOS App for iOS 15 with custum layouts, animations and...", image: "Illustration 5", background: "Background 5", logo: "Logo 2", contentDescription: "SwiftUI is handson the best way for designers to take a first step into code", contentTitle: "The SwuifUI course", contentText1: "This course is unlike any other. We care about design and want to make sure you get better at it in the process. It was written for designers and developers who are passionate about collaborating and building real apps for iOS and macOS.", contentText2: "While it's not one codebase for all apps, you learn once and can apply the techniques and controls to all platforms with incredible quality, consistency and performance.", avatar: "Avatar Default", avatarDescription: "Taught by John Carlos"), 29 | Course(title: "UI design for iOS 15", subtitle: "20 sections - 3 hours", text: "Learn how I buit an iOS App for iOS 15 with custum layouts, animations and...", image: "Illustration 3", background: "Background 4", logo: "Logo 4", contentDescription: "SwiftUI is handson the best way for designers to take a first step into code", contentTitle: "The SwuifUI course", contentText1: "This course is unlike any other. We care about design and want to make sure you get better at it in the process. It was written for designers and developers who are passionate about collaborating and building real apps for iOS and macOS.", contentText2: "While it's not one codebase for all apps, you learn once and can apply the techniques and controls to all platforms with incredible quality, consistency and performance.", avatar: "Avatar Default", avatarDescription: "Taught by John Carlos"), 30 | Course(title: "Flutter for Designers", subtitle: "20 sections - 3 hours", text: "Learn how I buit an iOS App for iOS 15 with custum layouts, animations and...", image: "Illustration 1", background: "Background 1", logo: "Logo 1", contentDescription: "SwiftUI is handson the best way for designers to take a first step into code", contentTitle: "The SwuifUI course", contentText1: "This course is unlike any other. We care about design and want to make sure you get better at it in the process. It was written for designers and developers who are passionate about collaborating and building real apps for iOS and macOS.", contentText2: "While it's not one codebase for all apps, you learn once and can apply the techniques and controls to all platforms with incredible quality, consistency and performance.", avatar: "Avatar Default", avatarDescription: "Taught by John Carlos"), 31 | Course(title: "Advanced React Hooks", subtitle: "20 sections - 3 hours", text: "Learn how I buit an iOS App for iOS 15 with custum layouts, animations and...", image: "Illustration 2", background: "Background 2", logo: "Logo 3", contentDescription: "SwiftUI is handson the best way for designers to take a first step into code", contentTitle: "The SwuifUI course", contentText1: "This course is unlike any other. We care about design and want to make sure you get better at it in the process. It was written for designers and developers who are passionate about collaborating and building real apps for iOS and macOS.", contentText2: "While it's not one codebase for all apps, you learn once and can apply the techniques and controls to all platforms with incredible quality, consistency and performance.", avatar: "Avatar Default", avatarDescription: "Taught by John Carlos"), 32 | ] 33 | 34 | var courses = [ 35 | Course(title: "SwiftUI for iOS 15", subtitle: "20 sections - 3 hours", text: "Learn how I buit an iOS App for iOS 15 with custum layouts, animations and...", image: "Illustration 5", background: "Background 5", logo: "Logo 2", contentDescription: "SwiftUI is handson the best way for designers to take a first step into code", contentTitle: "The SwuifUI course", contentText1: "This course is unlike any other. We care about design and want to make sure you get better at it in the process. It was written for designers and developers who are passionate about collaborating and building real apps for iOS and macOS.", contentText2: "While it's not one codebase for all apps, you learn once and can apply the techniques and controls to all platforms with incredible quality, consistency and performance.", avatar: "Avatar Default", avatarDescription: "Taught by John Carlos"), 36 | Course(title: "UI design for iOS 15", subtitle: "20 sections - 3 hours", text: "Learn how I buit an iOS App for iOS 15 with custum layouts, animations and...", image: "Illustration 3", background: "Background 4", logo: "Logo 4", contentDescription: "SwiftUI is handson the best way for designers to take a first step into code", contentTitle: "The SwuifUI course", contentText1: "This course is unlike any other. We care about design and want to make sure you get better at it in the process. It was written for designers and developers who are passionate about collaborating and building real apps for iOS and macOS.", contentText2: "While it's not one codebase for all apps, you learn once and can apply the techniques and controls to all platforms with incredible quality, consistency and performance.", avatar: "Avatar Default", avatarDescription: "Taught by John Carlos"), 37 | Course(title: "Flutter for Designers", subtitle: "20 sections - 3 hours", text: "Learn how I buit an iOS App for iOS 15 with custum layouts, animations and...", image: "Illustration 1", background: "Background 1", logo: "Logo 1", contentDescription: "SwiftUI is handson the best way for designers to take a first step into code", contentTitle: "The SwuifUI course", contentText1: "This course is unlike any other. We care about design and want to make sure you get better at it in the process. It was written for designers and developers who are passionate about collaborating and building real apps for iOS and macOS.", contentText2: "While it's not one codebase for all apps, you learn once and can apply the techniques and controls to all platforms with incredible quality, consistency and performance.", avatar: "Avatar Default", avatarDescription: "Taught by John Carlos"), 38 | Course(title: "Advanced React Hooks", subtitle: "20 sections - 3 hours", text: "Learn how I buit an iOS App for iOS 15 with custum layouts, animations and...", image: "Illustration 2", background: "Background 2", logo: "Logo 3", contentDescription: "SwiftUI is handson the best way for designers to take a first step into code", contentTitle: "The SwuifUI course", contentText1: "This course is unlike any other. We care about design and want to make sure you get better at it in the process. It was written for designers and developers who are passionate about collaborating and building real apps for iOS and macOS.", contentText2: "While it's not one codebase for all apps, you learn once and can apply the techniques and controls to all platforms with incredible quality, consistency and performance.", avatar: "Avatar Default", avatarDescription: "Taught by John Carlos"), 39 | ] 40 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Components/Buttons/PlayView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PlayView.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 08/06/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | import SwiftUI 11 | 12 | struct PlayView: View { 13 | var body: some View { 14 | PlayShape() 15 | .fill(Color("Shadow").opacity(0.8)) 16 | .frame(width: 52, height: 52) 17 | .overlay(PlayShape().stroke(.white)) 18 | .background( 19 | PlayShape() 20 | .fill(.angularGradient(colors: [.blue, .red, .blue], center: .center, startAngle: .degrees(0), endAngle: .degrees(360))) 21 | .blur(radius: 12) 22 | ) 23 | .offset(x: 2) 24 | .frame(width: 120, height: 120) 25 | .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 46, style: .continuous)) 26 | .strokeStyle(cornerRadius: 46) 27 | .shadow(color: Color("Shadow").opacity(0.2), radius: 30, x: 0, y: 30) 28 | .overlay( 29 | Text("12:08") 30 | .font(.footnote.weight(.semibold)) 31 | .padding(.vertical, 2) 32 | .padding(.horizontal, 4) 33 | .background(Color(UIColor.systemBackground).opacity(0.3)) 34 | .cornerRadius(4) 35 | .offset(y: 44) 36 | ) 37 | } 38 | } 39 | 40 | struct PlayView_Previews: PreviewProvider { 41 | static var previews: some View { 42 | PlayView() 43 | } 44 | } 45 | 46 | struct PlayShape: Shape { 47 | func path(in rect: CGRect) -> Path { 48 | var path = Path() 49 | let width = rect.size.width 50 | let height = rect.size.height 51 | path.move(to: CGPoint(x: 0.04718*width, y: 0.08831*height)) 52 | path.addCurve(to: CGPoint(x: 0.01539*width, y: 0.18464*height), control1: CGPoint(x: 0.0284*width, y: 0.11157*height), control2: CGPoint(x: 0.01969*width, y: 0.14249*height)) 53 | path.addCurve(to: CGPoint(x: 0.0111*width, y: 0.35395*height), control1: CGPoint(x: 0.0111*width, y: 0.22673*height), control2: CGPoint(x: 0.0111*width, y: 0.28167*height)) 54 | path.addLine(to: CGPoint(x: 0.0111*width, y: 0.35451*height)) 55 | path.addLine(to: CGPoint(x: 0.0111*width, y: 0.64549*height)) 56 | path.addLine(to: CGPoint(x: 0.0111*width, y: 0.64605*height)) 57 | path.addCurve(to: CGPoint(x: 0.01539*width, y: 0.81536*height), control1: CGPoint(x: 0.0111*width, y: 0.71834*height), control2: CGPoint(x: 0.0111*width, y: 0.77327*height)) 58 | path.addCurve(to: CGPoint(x: 0.04718*width, y: 0.91169*height), control1: CGPoint(x: 0.01969*width, y: 0.85751*height), control2: CGPoint(x: 0.0284*width, y: 0.88844*height)) 59 | path.addCurve(to: CGPoint(x: 0.18025*width, y: 0.98084*height), control1: CGPoint(x: 0.07864*width, y: 0.95067*height), control2: CGPoint(x: 0.12701*width, y: 0.9758*height)) 60 | path.addCurve(to: CGPoint(x: 0.28883*width, y: 0.95745*height), control1: CGPoint(x: 0.21201*width, y: 0.98384*height), control2: CGPoint(x: 0.24613*width, y: 0.97517*height)) 61 | path.addCurve(to: CGPoint(x: 0.45389*width, y: 0.87614*height), control1: CGPoint(x: 0.33148*width, y: 0.93975*height), control2: CGPoint(x: 0.38434*width, y: 0.91228*height)) 62 | path.addLine(to: CGPoint(x: 0.45443*width, y: 0.87586*height)) 63 | path.addLine(to: CGPoint(x: 0.73443*width, y: 0.73036*height)) 64 | path.addLine(to: CGPoint(x: 0.73498*width, y: 0.73008*height)) 65 | path.addCurve(to: CGPoint(x: 0.89575*width, y: 0.64208*height), control1: CGPoint(x: 0.80453*width, y: 0.69394*height), control2: CGPoint(x: 0.85739*width, y: 0.66647*height)) 66 | path.addCurve(to: CGPoint(x: 0.97255*width, y: 0.56915*height), control1: CGPoint(x: 0.93415*width, y: 0.61766*height), control2: CGPoint(x: 0.95956*width, y: 0.59541*height)) 67 | path.addCurve(to: CGPoint(x: 0.97255*width, y: 0.43086*height), control1: CGPoint(x: 0.99432*width, y: 0.52513*height), control2: CGPoint(x: 0.99432*width, y: 0.47487*height)) 68 | path.addCurve(to: CGPoint(x: 0.89575*width, y: 0.35792*height), control1: CGPoint(x: 0.95956*width, y: 0.40459*height), control2: CGPoint(x: 0.93416*width, y: 0.38234*height)) 69 | path.addCurve(to: CGPoint(x: 0.73498*width, y: 0.26992*height), control1: CGPoint(x: 0.85739*width, y: 0.33353*height), control2: CGPoint(x: 0.80453*width, y: 0.30606*height)) 70 | path.addLine(to: CGPoint(x: 0.73444*width, y: 0.26964*height)) 71 | path.addLine(to: CGPoint(x: 0.45444*width, y: 0.12415*height)) 72 | path.addLine(to: CGPoint(x: 0.4539*width, y: 0.12387*height)) 73 | path.addCurve(to: CGPoint(x: 0.28883*width, y: 0.04256*height), control1: CGPoint(x: 0.38434*width, y: 0.08773*height), control2: CGPoint(x: 0.33148*width, y: 0.06026*height)) 74 | path.addCurve(to: CGPoint(x: 0.18025*width, y: 0.01916*height), control1: CGPoint(x: 0.24613*width, y: 0.02483*height), control2: CGPoint(x: 0.21201*width, y: 0.01616*height)) 75 | path.addCurve(to: CGPoint(x: 0.04718*width, y: 0.08831*height), control1: CGPoint(x: 0.12701*width, y: 0.0242*height), control2: CGPoint(x: 0.07864*width, y: 0.04933*height)) 76 | path.closeSubpath() 77 | path.move(to: CGPoint(x: 0.04718*width, y: 0.08831*height)) 78 | path.addCurve(to: CGPoint(x: 0.01539*width, y: 0.18464*height), control1: CGPoint(x: 0.0284*width, y: 0.11157*height), control2: CGPoint(x: 0.01969*width, y: 0.14249*height)) 79 | path.addCurve(to: CGPoint(x: 0.0111*width, y: 0.35395*height), control1: CGPoint(x: 0.0111*width, y: 0.22673*height), control2: CGPoint(x: 0.0111*width, y: 0.28167*height)) 80 | path.addLine(to: CGPoint(x: 0.0111*width, y: 0.35451*height)) 81 | path.addLine(to: CGPoint(x: 0.0111*width, y: 0.64549*height)) 82 | path.addLine(to: CGPoint(x: 0.0111*width, y: 0.64605*height)) 83 | path.addCurve(to: CGPoint(x: 0.01539*width, y: 0.81536*height), control1: CGPoint(x: 0.0111*width, y: 0.71834*height), control2: CGPoint(x: 0.0111*width, y: 0.77327*height)) 84 | path.addCurve(to: CGPoint(x: 0.04718*width, y: 0.91169*height), control1: CGPoint(x: 0.01969*width, y: 0.85751*height), control2: CGPoint(x: 0.0284*width, y: 0.88844*height)) 85 | path.addCurve(to: CGPoint(x: 0.18025*width, y: 0.98084*height), control1: CGPoint(x: 0.07864*width, y: 0.95067*height), control2: CGPoint(x: 0.12701*width, y: 0.9758*height)) 86 | path.addCurve(to: CGPoint(x: 0.28883*width, y: 0.95745*height), control1: CGPoint(x: 0.21201*width, y: 0.98384*height), control2: CGPoint(x: 0.24613*width, y: 0.97517*height)) 87 | path.addCurve(to: CGPoint(x: 0.45389*width, y: 0.87614*height), control1: CGPoint(x: 0.33148*width, y: 0.93975*height), control2: CGPoint(x: 0.38434*width, y: 0.91228*height)) 88 | path.addLine(to: CGPoint(x: 0.45443*width, y: 0.87586*height)) 89 | path.addLine(to: CGPoint(x: 0.73443*width, y: 0.73036*height)) 90 | path.addLine(to: CGPoint(x: 0.73498*width, y: 0.73008*height)) 91 | path.addCurve(to: CGPoint(x: 0.89575*width, y: 0.64208*height), control1: CGPoint(x: 0.80453*width, y: 0.69394*height), control2: CGPoint(x: 0.85739*width, y: 0.66647*height)) 92 | path.addCurve(to: CGPoint(x: 0.97255*width, y: 0.56915*height), control1: CGPoint(x: 0.93415*width, y: 0.61766*height), control2: CGPoint(x: 0.95956*width, y: 0.59541*height)) 93 | path.addCurve(to: CGPoint(x: 0.97255*width, y: 0.43086*height), control1: CGPoint(x: 0.99432*width, y: 0.52513*height), control2: CGPoint(x: 0.99432*width, y: 0.47487*height)) 94 | path.addCurve(to: CGPoint(x: 0.89575*width, y: 0.35792*height), control1: CGPoint(x: 0.95956*width, y: 0.40459*height), control2: CGPoint(x: 0.93416*width, y: 0.38234*height)) 95 | path.addCurve(to: CGPoint(x: 0.73498*width, y: 0.26992*height), control1: CGPoint(x: 0.85739*width, y: 0.33353*height), control2: CGPoint(x: 0.80453*width, y: 0.30606*height)) 96 | path.addLine(to: CGPoint(x: 0.73444*width, y: 0.26964*height)) 97 | path.addLine(to: CGPoint(x: 0.45444*width, y: 0.12415*height)) 98 | path.addLine(to: CGPoint(x: 0.4539*width, y: 0.12387*height)) 99 | path.addCurve(to: CGPoint(x: 0.28883*width, y: 0.04256*height), control1: CGPoint(x: 0.38434*width, y: 0.08773*height), control2: CGPoint(x: 0.33148*width, y: 0.06026*height)) 100 | path.addCurve(to: CGPoint(x: 0.18025*width, y: 0.01916*height), control1: CGPoint(x: 0.24613*width, y: 0.02483*height), control2: CGPoint(x: 0.21201*width, y: 0.01616*height)) 101 | path.addCurve(to: CGPoint(x: 0.04718*width, y: 0.08831*height), control1: CGPoint(x: 0.12701*width, y: 0.0242*height), control2: CGPoint(x: 0.07864*width, y: 0.04933*height)) 102 | path.closeSubpath() 103 | return path 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Views/Detail/CourseView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CourseView.swift 3 | // SwiftUI for iOS 15 4 | // 5 | // Created by João Carlos Magalhães on 31/03/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct CourseView: View { 11 | var namespace: Namespace.ID 12 | var course: Course = courses[0] 13 | @Binding var show: Bool 14 | @State var appear = [false, false, false] 15 | @EnvironmentObject var model: Model 16 | @State var viewState: CGSize = .zero 17 | @State var isDraggable = true 18 | @State var showSection = false 19 | @State var selectedIndex = 0 20 | 21 | var body: some View { 22 | ZStack { 23 | ScrollView { 24 | cover 25 | 26 | content 27 | .offset(y: 120) 28 | .padding(.bottom, 200) 29 | .opacity(appear[2] ? 1 : 0) 30 | } 31 | .coordinateSpace(name: "scroll") 32 | .onAppear { model.showDetail = true } 33 | .onDisappear { model.showDetail = false } 34 | .background(Color("Background")) 35 | .mask(RoundedRectangle(cornerRadius: viewState.width / 3, style: .continuous)) 36 | .shadow(color: .black.opacity(0.3), radius: 30, x: 0, y: 10) 37 | .scaleEffect(viewState.width / -500 + 1) 38 | .background(.black.opacity(viewState.width / 500)) 39 | .background(.ultraThinMaterial) 40 | .gesture(isDraggable ? drag : nil) 41 | .ignoresSafeArea() 42 | 43 | button 44 | } 45 | .onAppear { 46 | fadeIn() 47 | } 48 | .onChange(of: show) { newValue in 49 | fadeOut() 50 | } 51 | } 52 | 53 | var cover: some View { 54 | GeometryReader { proxy in 55 | let scrollY = proxy.frame(in: .named("scroll")).minY 56 | 57 | VStack { 58 | Spacer() 59 | } 60 | .frame(maxWidth: .infinity) 61 | .frame(height: scrollY > 0 ? 500 + scrollY : 500) 62 | .foregroundStyle(.black) 63 | .background( 64 | Image(course.image) 65 | .resizable() 66 | .aspectRatio(contentMode: .fit) 67 | .padding(20) 68 | .frame(maxWidth: 500) 69 | .matchedGeometryEffect(id: "image\(course.id)", in: namespace) 70 | .offset(y: scrollY > 0 ? scrollY * -0.8 : 0) 71 | .accessibilityLabel("Cover Image") 72 | ) 73 | .background( 74 | Image(course.background) 75 | .resizable() 76 | .aspectRatio(contentMode: .fill) 77 | .matchedGeometryEffect(id: "background\(course.id)", in: namespace) 78 | .offset(y: scrollY > 0 ? -scrollY : 0) 79 | .scaleEffect(scrollY > 0 ? scrollY / 1000 + 1 : 1) 80 | .blur(radius: scrollY / 10) 81 | ) 82 | .mask( 83 | RoundedRectangle(cornerRadius: appear[0] ? 0 : 30, style: .continuous) 84 | .matchedGeometryEffect(id: "mask\(course.id)", in: namespace) 85 | .offset(y: scrollY > 0 ? -scrollY : 0) 86 | ) 87 | .overlay( 88 | overlayContent 89 | .offset(y: scrollY > 0 ? scrollY * -0.6 : 0) 90 | ) 91 | } 92 | .frame(height: 500) 93 | } 94 | 95 | var content: some View { 96 | VStack(alignment: .leading) { 97 | ForEach(Array(courseSections.enumerated()), id: \.offset) { index, section in 98 | if index != 0 { Divider() } 99 | SectionRow(section: section) 100 | .onTapGesture { 101 | selectedIndex = index 102 | showSection = true 103 | } 104 | } 105 | } 106 | .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 30, style: .continuous)) 107 | .strokeStyle(cornerRadius: 30) 108 | .padding(20) 109 | .sheet(isPresented: $showSection) { 110 | SectionView(section: courseSections[selectedIndex]) 111 | } 112 | } 113 | 114 | var button: some View { 115 | Button { 116 | withAnimation(.closeCard) { 117 | show.toggle() 118 | model.showDetail.toggle() 119 | } 120 | } label: { 121 | Image(systemName: "xmark") 122 | .font(.body.weight(.bold)) 123 | .foregroundColor(.secondary) 124 | .padding(8) 125 | .background(.ultraThinMaterial, in: Circle()) 126 | } 127 | .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing) 128 | .padding(20) 129 | .ignoresSafeArea() 130 | } 131 | 132 | var overlayContent: some View { 133 | VStack(alignment: .leading, spacing: 12) { 134 | Text(course.title) 135 | .font(.largeTitle.weight(.bold)) 136 | .matchedGeometryEffect(id: "title\(course.id)", in: namespace) 137 | .frame(maxWidth: .infinity, alignment: .leading) 138 | Text(course.subtitle.uppercased()) 139 | .font(.footnote.weight(.semibold)) 140 | .matchedGeometryEffect(id: "subtitle\(course.id)", in: namespace) 141 | Text(course.text) 142 | .font(.footnote) 143 | .matchedGeometryEffect(id: "text\(course.id)", in: namespace) 144 | Divider() 145 | .opacity(appear[0] ? 1 : 0) 146 | HStack { 147 | Image("Avatar Default") 148 | .resizable() 149 | .frame(width: 26, height: 26) 150 | .cornerRadius(10) 151 | .padding(8) 152 | .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 18, style: .continuous)) 153 | .strokeStyle(cornerRadius: 18) 154 | Text("Taught by iOSNick") 155 | .font(.footnote) 156 | } 157 | .opacity(appear[1] ? 1 : 0) 158 | } 159 | .padding(20) 160 | .background( 161 | Rectangle() 162 | .fill(.ultraThinMaterial) 163 | .mask(RoundedRectangle(cornerRadius: 30, style: .continuous)) 164 | .matchedGeometryEffect(id: "blur\(course.id)", in: namespace) 165 | ) 166 | .offset(y: 250) 167 | .padding(20) 168 | } 169 | 170 | var drag: some Gesture { 171 | DragGesture(minimumDistance: 30, coordinateSpace: .local) 172 | .onChanged { value in 173 | guard value.translation.width > 0 else { return } // we want to make sure the value is also above 0. This is the condition to go to the next line. This stops us from being able to drag left. 174 | 175 | if value.startLocation.x < 100 { 176 | withAnimation(.closeCard) { 177 | viewState = value.translation 178 | } 179 | } 180 | 181 | if viewState.width > 120 { 182 | close() 183 | } 184 | } 185 | .onEnded { value in 186 | if viewState.width > 80 { 187 | close() 188 | } else { 189 | withAnimation(.closeCard) { 190 | viewState = .zero 191 | } 192 | } 193 | } 194 | } 195 | 196 | func fadeIn() { 197 | withAnimation(.easeOut.delay(0.3)) { 198 | appear[0] = true 199 | } 200 | withAnimation(.easeOut.delay(0.4)) { 201 | appear[1] = true 202 | } 203 | withAnimation(.easeOut.delay(0.5)) { 204 | appear[2] = true 205 | } 206 | } 207 | 208 | func fadeOut() { 209 | appear[0] = false 210 | appear[1] = false 211 | appear[2] = false 212 | } 213 | 214 | func close() { 215 | withAnimation(.closeCard.delay(0.3)) { 216 | show.toggle() 217 | model.showDetail.toggle() 218 | } 219 | 220 | withAnimation(.closeCard) { 221 | viewState = .zero 222 | } 223 | 224 | isDraggable = false 225 | } 226 | } 227 | 228 | struct CourseView_Previews: PreviewProvider { 229 | @Namespace static var namespace 230 | 231 | static var previews: some View { 232 | CourseView(namespace: namespace, show: .constant(true)) 233 | .environmentObject(Model()) 234 | } 235 | } 236 | -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Waves/Waves 1.imageset/Waves 1.pdf: -------------------------------------------------------------------------------- 1 | %PDF-1.7 2 | 3 | 1 0 obj 4 | << /Length 2 0 R 5 | /FunctionType 4 6 | /Domain [ 0.000000 1.000000 ] 7 | /Range [ 0.000000 1.000000 0.000000 1.000000 0.000000 1.000000 ] 8 | >> 9 | stream 10 | { 0.902222 exch 0.902222 exch 0.933333 exch dup 0.035511 gt { exch pop exch pop exch pop dup 0.035511 sub -0.111548 mul 0.902222 add exch dup 0.035511 sub -0.111548 mul 0.902222 add exch dup 0.035511 sub -0.021600 mul 0.933333 add exch } if dup 1.000000 gt { exch pop exch pop exch pop 0.794635 exch 0.794635 exch 0.912500 exch } if pop } 11 | endstream 12 | endobj 13 | 14 | 2 0 obj 15 | 339 16 | endobj 17 | 18 | 3 0 obj 19 | << /Length 4 0 R 20 | /FunctionType 4 21 | /Domain [ 0.000000 1.000000 ] 22 | /Range [ 0.000000 1.000000 0.000000 1.000000 0.000000 1.000000 ] 23 | >> 24 | stream 25 | { 0.949020 exch 0.964706 exch 1.000000 exch dup 0.000000 gt { exch pop exch pop exch pop dup 0.000000 sub 0.000000 mul 0.949020 add exch dup 0.000000 sub 0.000000 mul 0.964706 add exch dup 0.000000 sub 0.000000 mul 1.000000 add exch } if dup 1.000000 gt { exch pop exch pop exch pop 0.949020 exch 0.964706 exch 1.000000 exch } if pop } 26 | endstream 27 | endobj 28 | 29 | 4 0 obj 30 | 336 31 | endobj 32 | 33 | 5 0 obj 34 | << /Length 6 0 R 35 | /FunctionType 4 36 | /Domain [ 0.000000 1.000000 ] 37 | /Range [ 0.000000 1.000000 ] 38 | >> 39 | stream 40 | { 0.500000 exch dup 0.035511 gt { exch pop dup 0.035511 sub 0.518409 mul 0.500000 add exch } if dup 1.000000 gt { exch pop 1.000000 exch } if pop } 41 | endstream 42 | endobj 43 | 44 | 6 0 obj 45 | 148 46 | endobj 47 | 48 | 7 0 obj 49 | << /Type /XObject 50 | /Length 8 0 R 51 | /Group << /Type /Group 52 | /S /Transparency 53 | /CS /DeviceGray 54 | >> 55 | /Subtype /Form 56 | /Resources << /Pattern << /P1 << /Matrix [ 233.942795 -165.856781 165.856781 233.942795 -86.802643 -204.442978 ] 57 | /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] 58 | /Extend [ true true ] 59 | /Domain [ 0.000000 1.000000 ] 60 | /ShadingType 2 61 | /ColorSpace /DeviceGray 62 | /Function 5 0 R 63 | >> 64 | /PatternType 2 65 | /Type /Pattern 66 | >> >> >> 67 | /BBox [ 0.000000 0.000000 428.000000 100.000000 ] 68 | >> 69 | stream 70 | /DeviceGray CS 71 | /DeviceGray cs 72 | 1.000000 0.000000 -0.000000 1.000000 0.000000 -17.827332 cm 73 | 0.000000 99.453758 m 74 | 150.897446 61.327290 246.374374 125.827332 428.000031 94.453758 c 75 | 428.000031 22.453735 l 76 | 253.174408 82.309814 171.096115 50.516239 0.000000 22.453735 c 77 | 0.000000 99.453758 l 78 | h 79 | /Pattern cs 80 | /P1 scn 81 | f 82 | n 83 | 84 | endstream 85 | endobj 86 | 87 | 8 0 obj 88 | 310 89 | endobj 90 | 91 | 9 0 obj 92 | << /Length 10 0 R 93 | /FunctionType 4 94 | /Domain [ 0.000000 1.000000 ] 95 | /Range [ 0.000000 1.000000 ] 96 | >> 97 | stream 98 | { 0.400000 exch dup 0.000000 gt { exch pop dup 0.000000 sub 0.600000 mul 0.400000 add exch } if dup 1.000000 gt { exch pop 1.000000 exch } if pop } 99 | endstream 100 | endobj 101 | 102 | 10 0 obj 103 | 148 104 | endobj 105 | 106 | 11 0 obj 107 | << /Type /XObject 108 | /Length 12 0 R 109 | /Group << /Type /Group 110 | /S /Transparency 111 | /CS /DeviceGray 112 | >> 113 | /Subtype /Form 114 | /Resources << /Pattern << /P1 << /Matrix [ -0.000000 -45.000004 45.000004 -0.000000 -45.000004 100.000000 ] 115 | /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] 116 | /Extend [ true true ] 117 | /Domain [ 0.000000 1.000000 ] 118 | /ShadingType 2 119 | /ColorSpace /DeviceGray 120 | /Function 9 0 R 121 | >> 122 | /PatternType 2 123 | /Type /Pattern 124 | >> >> >> 125 | /BBox [ 0.000000 0.000000 428.000000 100.000000 ] 126 | >> 127 | stream 128 | /DeviceGray CS 129 | /DeviceGray cs 130 | 1.000000 0.000000 -0.000000 1.000000 0.000000 -18.187927 cm 131 | 0.000000 114.814453 m 132 | 162.434509 44.782616 230.025238 136.375824 428.000031 114.814453 c 133 | 428.000031 18.187927 l 134 | 0.000000 18.187927 l 135 | 0.000000 114.814453 l 136 | h 137 | /Pattern cs 138 | /P1 scn 139 | f 140 | n 141 | 142 | endstream 143 | endobj 144 | 145 | 12 0 obj 146 | 271 147 | endobj 148 | 149 | 13 0 obj 150 | << /Pattern << /P2 << /Matrix [ 233.942795 -165.856781 165.856781 233.942795 -86.802643 -204.442978 ] 151 | /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] 152 | /Extend [ true true ] 153 | /Domain [ 0.000000 1.000000 ] 154 | /ShadingType 2 155 | /ColorSpace /DeviceRGB 156 | /Function 1 0 R 157 | >> 158 | /PatternType 2 159 | /Type /Pattern 160 | >> 161 | /P1 << /Matrix [ -0.000000 -45.000004 45.000004 -0.000000 -45.000004 100.000000 ] 162 | /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] 163 | /Extend [ true true ] 164 | /Domain [ 0.000000 1.000000 ] 165 | /ShadingType 2 166 | /ColorSpace /DeviceRGB 167 | /Function 3 0 R 168 | >> 169 | /PatternType 2 170 | /Type /Pattern 171 | >> 172 | >> 173 | /ExtGState << /E2 << /SMask << /Type /Mask 174 | /G 7 0 R 175 | /S /Luminosity 176 | >> 177 | /Type /ExtGState 178 | >> 179 | /E1 << /SMask << /Type /Mask 180 | /G 11 0 R 181 | /S /Luminosity 182 | >> 183 | /Type /ExtGState 184 | >> 185 | >> 186 | >> 187 | endobj 188 | 189 | 14 0 obj 190 | << /Length 15 0 R >> 191 | stream 192 | /DeviceRGB CS 193 | /DeviceRGB cs 194 | q 195 | /E1 gs 196 | 1.000000 0.000000 -0.000000 1.000000 0.000000 -18.187927 cm 197 | /Pattern cs 198 | /P1 scn 199 | 0.000000 114.814453 m 200 | 162.434509 44.782616 230.025238 136.375824 428.000031 114.814453 c 201 | 428.000031 18.187927 l 202 | 0.000000 18.187927 l 203 | 0.000000 114.814453 l 204 | h 205 | f 206 | n 207 | Q 208 | q 209 | /E2 gs 210 | 1.000000 0.000000 -0.000000 1.000000 0.000000 -17.827332 cm 211 | /Pattern cs 212 | /P2 scn 213 | 0.000000 99.453758 m 214 | 150.897446 61.327290 246.374374 125.827332 428.000031 94.453758 c 215 | 428.000031 22.453735 l 216 | 253.174408 82.309814 171.096115 50.516239 0.000000 22.453735 c 217 | 0.000000 99.453758 l 218 | h 219 | f 220 | n 221 | Q 222 | 223 | endstream 224 | endobj 225 | 226 | 15 0 obj 227 | 571 228 | endobj 229 | 230 | 16 0 obj 231 | << /Annots [] 232 | /Type /Page 233 | /MediaBox [ 0.000000 0.000000 428.000000 100.000000 ] 234 | /Resources 13 0 R 235 | /Contents 14 0 R 236 | /Parent 17 0 R 237 | >> 238 | endobj 239 | 240 | 17 0 obj 241 | << /Kids [ 16 0 R ] 242 | /Count 1 243 | /Type /Pages 244 | >> 245 | endobj 246 | 247 | 18 0 obj 248 | << /Type /Catalog 249 | /Pages 17 0 R 250 | >> 251 | endobj 252 | 253 | xref 254 | 0 19 255 | 0000000000 65535 f 256 | 0000000010 00000 n 257 | 0000000533 00000 n 258 | 0000000555 00000 n 259 | 0000001075 00000 n 260 | 0000001097 00000 n 261 | 0000001393 00000 n 262 | 0000001415 00000 n 263 | 0000002757 00000 n 264 | 0000002779 00000 n 265 | 0000003076 00000 n 266 | 0000003099 00000 n 267 | 0000004399 00000 n 268 | 0000004422 00000 n 269 | 0000006198 00000 n 270 | 0000006827 00000 n 271 | 0000006850 00000 n 272 | 0000007029 00000 n 273 | 0000007105 00000 n 274 | trailer 275 | << /ID [ (some) (id) ] 276 | /Root 18 0 R 277 | /Size 19 278 | >> 279 | startxref 280 | 7166 281 | %%EOF -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Waves/Waves 1.imageset/Waves 1 Dark.pdf: -------------------------------------------------------------------------------- 1 | %PDF-1.7 2 | 3 | 1 0 obj 4 | << /Length 2 0 R 5 | /FunctionType 4 6 | /Domain [ 0.000000 1.000000 ] 7 | /Range [ 0.000000 1.000000 0.000000 1.000000 0.000000 1.000000 ] 8 | >> 9 | stream 10 | { 0.109080 exch 0.109080 exch 0.254167 exch dup 0.035511 gt { exch pop exch pop exch pop dup 0.035511 sub -0.037171 mul 0.109080 add exch dup 0.035511 sub -0.037171 mul 0.109080 add exch dup 0.035511 sub -0.017280 mul 0.254167 add exch } if dup 1.000000 gt { exch pop exch pop exch pop 0.073229 exch 0.073229 exch 0.237500 exch } if pop } 11 | endstream 12 | endobj 13 | 14 | 2 0 obj 15 | 339 16 | endobj 17 | 18 | 3 0 obj 19 | << /Length 4 0 R 20 | /FunctionType 4 21 | /Domain [ 0.000000 1.000000 ] 22 | /Range [ 0.000000 1.000000 0.000000 1.000000 0.000000 1.000000 ] 23 | >> 24 | stream 25 | { 0.145098 exch 0.145098 exch 0.294118 exch dup 0.000000 gt { exch pop exch pop exch pop dup 0.000000 sub 0.000000 mul 0.145098 add exch dup 0.000000 sub 0.000000 mul 0.145098 add exch dup 0.000000 sub 0.000000 mul 0.294118 add exch } if dup 1.000000 gt { exch pop exch pop exch pop 0.145098 exch 0.145098 exch 0.294118 exch } if pop } 26 | endstream 27 | endobj 28 | 29 | 4 0 obj 30 | 336 31 | endobj 32 | 33 | 5 0 obj 34 | << /Length 6 0 R 35 | /FunctionType 4 36 | /Domain [ 0.000000 1.000000 ] 37 | /Range [ 0.000000 1.000000 ] 38 | >> 39 | stream 40 | { 0.500000 exch dup 0.035511 gt { exch pop dup 0.035511 sub 0.518409 mul 0.500000 add exch } if dup 1.000000 gt { exch pop 1.000000 exch } if pop } 41 | endstream 42 | endobj 43 | 44 | 6 0 obj 45 | 148 46 | endobj 47 | 48 | 7 0 obj 49 | << /Type /XObject 50 | /Length 8 0 R 51 | /Group << /Type /Group 52 | /S /Transparency 53 | /CS /DeviceGray 54 | >> 55 | /Subtype /Form 56 | /Resources << /Pattern << /P1 << /Matrix [ 233.942795 -165.856781 165.856781 233.942795 -86.802643 -204.442978 ] 57 | /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] 58 | /Extend [ true true ] 59 | /Domain [ 0.000000 1.000000 ] 60 | /ShadingType 2 61 | /ColorSpace /DeviceGray 62 | /Function 5 0 R 63 | >> 64 | /PatternType 2 65 | /Type /Pattern 66 | >> >> >> 67 | /BBox [ 0.000000 0.000000 428.000000 100.000000 ] 68 | >> 69 | stream 70 | /DeviceGray CS 71 | /DeviceGray cs 72 | 1.000000 0.000000 -0.000000 1.000000 0.000000 -17.827332 cm 73 | 0.000000 99.453758 m 74 | 150.897446 61.327290 246.374374 125.827332 428.000031 94.453758 c 75 | 428.000031 22.453735 l 76 | 253.174408 82.309814 171.096115 50.516239 0.000000 22.453735 c 77 | 0.000000 99.453758 l 78 | h 79 | /Pattern cs 80 | /P1 scn 81 | f 82 | n 83 | 84 | endstream 85 | endobj 86 | 87 | 8 0 obj 88 | 310 89 | endobj 90 | 91 | 9 0 obj 92 | << /Length 10 0 R 93 | /FunctionType 4 94 | /Domain [ 0.000000 1.000000 ] 95 | /Range [ 0.000000 1.000000 ] 96 | >> 97 | stream 98 | { 0.400000 exch dup 0.000000 gt { exch pop dup 0.000000 sub 0.600000 mul 0.400000 add exch } if dup 1.000000 gt { exch pop 1.000000 exch } if pop } 99 | endstream 100 | endobj 101 | 102 | 10 0 obj 103 | 148 104 | endobj 105 | 106 | 11 0 obj 107 | << /Type /XObject 108 | /Length 12 0 R 109 | /Group << /Type /Group 110 | /S /Transparency 111 | /CS /DeviceGray 112 | >> 113 | /Subtype /Form 114 | /Resources << /Pattern << /P1 << /Matrix [ -0.000000 -59.702690 59.702690 -0.000000 -59.702690 100.000000 ] 115 | /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] 116 | /Extend [ true true ] 117 | /Domain [ 0.000000 1.000000 ] 118 | /ShadingType 2 119 | /ColorSpace /DeviceGray 120 | /Function 9 0 R 121 | >> 122 | /PatternType 2 123 | /Type /Pattern 124 | >> >> >> 125 | /BBox [ 0.000000 0.000000 428.000000 100.000000 ] 126 | >> 127 | stream 128 | /DeviceGray CS 129 | /DeviceGray cs 130 | 1.000000 0.000000 -0.000000 1.000000 0.000000 -18.187927 cm 131 | 0.000000 114.814453 m 132 | 162.434509 44.782616 230.025238 136.375824 428.000031 114.814453 c 133 | 428.000031 18.187927 l 134 | 0.000000 18.187927 l 135 | 0.000000 114.814453 l 136 | h 137 | /Pattern cs 138 | /P1 scn 139 | f 140 | n 141 | 142 | endstream 143 | endobj 144 | 145 | 12 0 obj 146 | 271 147 | endobj 148 | 149 | 13 0 obj 150 | << /Pattern << /P2 << /Matrix [ 233.942795 -165.856781 165.856781 233.942795 -86.802643 -204.442978 ] 151 | /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] 152 | /Extend [ true true ] 153 | /Domain [ 0.000000 1.000000 ] 154 | /ShadingType 2 155 | /ColorSpace /DeviceRGB 156 | /Function 1 0 R 157 | >> 158 | /PatternType 2 159 | /Type /Pattern 160 | >> 161 | /P1 << /Matrix [ -0.000000 -59.702690 59.702690 -0.000000 -59.702690 100.000000 ] 162 | /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] 163 | /Extend [ true true ] 164 | /Domain [ 0.000000 1.000000 ] 165 | /ShadingType 2 166 | /ColorSpace /DeviceRGB 167 | /Function 3 0 R 168 | >> 169 | /PatternType 2 170 | /Type /Pattern 171 | >> 172 | >> 173 | /ExtGState << /E2 << /SMask << /Type /Mask 174 | /G 7 0 R 175 | /S /Luminosity 176 | >> 177 | /Type /ExtGState 178 | >> 179 | /E1 << /SMask << /Type /Mask 180 | /G 11 0 R 181 | /S /Luminosity 182 | >> 183 | /Type /ExtGState 184 | >> 185 | >> 186 | >> 187 | endobj 188 | 189 | 14 0 obj 190 | << /Length 15 0 R >> 191 | stream 192 | /DeviceRGB CS 193 | /DeviceRGB cs 194 | q 195 | /E1 gs 196 | 1.000000 0.000000 -0.000000 1.000000 0.000000 -18.187927 cm 197 | /Pattern cs 198 | /P1 scn 199 | 0.000000 114.814453 m 200 | 162.434509 44.782616 230.025238 136.375824 428.000031 114.814453 c 201 | 428.000031 18.187927 l 202 | 0.000000 18.187927 l 203 | 0.000000 114.814453 l 204 | h 205 | f 206 | n 207 | Q 208 | q 209 | /E2 gs 210 | 1.000000 0.000000 -0.000000 1.000000 0.000000 -17.827332 cm 211 | /Pattern cs 212 | /P2 scn 213 | 0.000000 99.453758 m 214 | 150.897446 61.327290 246.374374 125.827332 428.000031 94.453758 c 215 | 428.000031 22.453735 l 216 | 253.174408 82.309814 171.096115 50.516239 0.000000 22.453735 c 217 | 0.000000 99.453758 l 218 | h 219 | f 220 | n 221 | Q 222 | 223 | endstream 224 | endobj 225 | 226 | 15 0 obj 227 | 571 228 | endobj 229 | 230 | 16 0 obj 231 | << /Annots [] 232 | /Type /Page 233 | /MediaBox [ 0.000000 0.000000 428.000000 100.000000 ] 234 | /Resources 13 0 R 235 | /Contents 14 0 R 236 | /Parent 17 0 R 237 | >> 238 | endobj 239 | 240 | 17 0 obj 241 | << /Kids [ 16 0 R ] 242 | /Count 1 243 | /Type /Pages 244 | >> 245 | endobj 246 | 247 | 18 0 obj 248 | << /Type /Catalog 249 | /Pages 17 0 R 250 | >> 251 | endobj 252 | 253 | xref 254 | 0 19 255 | 0000000000 65535 f 256 | 0000000010 00000 n 257 | 0000000533 00000 n 258 | 0000000555 00000 n 259 | 0000001075 00000 n 260 | 0000001097 00000 n 261 | 0000001393 00000 n 262 | 0000001415 00000 n 263 | 0000002757 00000 n 264 | 0000002779 00000 n 265 | 0000003076 00000 n 266 | 0000003099 00000 n 267 | 0000004399 00000 n 268 | 0000004422 00000 n 269 | 0000006198 00000 n 270 | 0000006827 00000 n 271 | 0000006850 00000 n 272 | 0000007029 00000 n 273 | 0000007105 00000 n 274 | trailer 275 | << /ID [ (some) (id) ] 276 | /Root 18 0 R 277 | /Size 19 278 | >> 279 | startxref 280 | 7166 281 | %%EOF -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Waves/Waves 2.imageset/Waves 2.pdf: -------------------------------------------------------------------------------- 1 | %PDF-1.7 2 | 3 | 1 0 obj 4 | << /Length 2 0 R 5 | /FunctionType 4 6 | /Domain [ 0.000000 1.000000 ] 7 | /Range [ 0.000000 1.000000 0.000000 1.000000 0.000000 1.000000 ] 8 | >> 9 | stream 10 | { 0.902222 exch 0.902222 exch 0.933333 exch dup 0.035511 gt { exch pop exch pop exch pop dup 0.035511 sub -0.111548 mul 0.902222 add exch dup 0.035511 sub -0.111548 mul 0.902222 add exch dup 0.035511 sub -0.021600 mul 0.933333 add exch } if dup 1.000000 gt { exch pop exch pop exch pop 0.794635 exch 0.794635 exch 0.912500 exch } if pop } 11 | endstream 12 | endobj 13 | 14 | 2 0 obj 15 | 339 16 | endobj 17 | 18 | 3 0 obj 19 | << /Length 4 0 R 20 | /FunctionType 4 21 | /Domain [ 0.000000 1.000000 ] 22 | /Range [ 0.000000 1.000000 0.000000 1.000000 0.000000 1.000000 ] 23 | >> 24 | stream 25 | { 0.949020 exch 0.964706 exch 1.000000 exch dup 0.000000 gt { exch pop exch pop exch pop dup 0.000000 sub 0.000000 mul 0.949020 add exch dup 0.000000 sub 0.000000 mul 0.964706 add exch dup 0.000000 sub 0.000000 mul 1.000000 add exch } if dup 1.000000 gt { exch pop exch pop exch pop 0.949020 exch 0.964706 exch 1.000000 exch } if pop } 26 | endstream 27 | endobj 28 | 29 | 4 0 obj 30 | 336 31 | endobj 32 | 33 | 5 0 obj 34 | << /Length 6 0 R 35 | /FunctionType 4 36 | /Domain [ 0.000000 1.000000 ] 37 | /Range [ 0.000000 1.000000 ] 38 | >> 39 | stream 40 | { 0.500000 exch dup 0.035511 gt { exch pop dup 0.035511 sub 0.518409 mul 0.500000 add exch } if dup 1.000000 gt { exch pop 1.000000 exch } if pop } 41 | endstream 42 | endobj 43 | 44 | 6 0 obj 45 | 148 46 | endobj 47 | 48 | 7 0 obj 49 | << /Type /XObject 50 | /Length 8 0 R 51 | /Group << /Type /Group 52 | /S /Transparency 53 | /CS /DeviceGray 54 | >> 55 | /Subtype /Form 56 | /Resources << /Pattern << /P1 << /Matrix [ 191.301773 -405.610107 405.610107 191.301773 -340.965271 -242.819534 ] 57 | /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] 58 | /Extend [ true true ] 59 | /Domain [ 0.000000 1.000000 ] 60 | /ShadingType 2 61 | /ColorSpace /DeviceGray 62 | /Function 5 0 R 63 | >> 64 | /PatternType 2 65 | /Type /Pattern 66 | >> >> >> 67 | /BBox [ 0.000000 0.000000 1280.000000 100.000000 ] 68 | >> 69 | stream 70 | /DeviceGray CS 71 | /DeviceGray cs 72 | 1.000000 0.000000 -0.000000 1.000000 0.000000 -17.827332 cm 73 | 0.000000 99.453758 m 74 | 451.282043 61.327290 736.820496 125.827332 1280.000000 94.453758 c 75 | 1280.000000 22.453735 l 76 | 757.157043 82.309814 511.689301 50.516239 0.000000 22.453735 c 77 | 0.000000 99.453758 l 78 | h 79 | /Pattern cs 80 | /P1 scn 81 | f 82 | n 83 | 84 | endstream 85 | endobj 86 | 87 | 8 0 obj 88 | 312 89 | endobj 90 | 91 | 9 0 obj 92 | << /Length 10 0 R 93 | /FunctionType 4 94 | /Domain [ 0.000000 1.000000 ] 95 | /Range [ 0.000000 1.000000 ] 96 | >> 97 | stream 98 | { 0.400000 exch dup 0.000000 gt { exch pop dup 0.000000 sub 0.600000 mul 0.400000 add exch } if dup 1.000000 gt { exch pop 1.000000 exch } if pop } 99 | endstream 100 | endobj 101 | 102 | 10 0 obj 103 | 148 104 | endobj 105 | 106 | 11 0 obj 107 | << /Type /XObject 108 | /Length 12 0 R 109 | /Group << /Type /Group 110 | /S /Transparency 111 | /CS /DeviceGray 112 | >> 113 | /Subtype /Form 114 | /Resources << /Pattern << /P1 << /Matrix [ -0.000000 -45.000004 45.000004 -0.000000 -45.000004 100.000000 ] 115 | /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] 116 | /Extend [ true true ] 117 | /Domain [ 0.000000 1.000000 ] 118 | /ShadingType 2 119 | /ColorSpace /DeviceGray 120 | /Function 9 0 R 121 | >> 122 | /PatternType 2 123 | /Type /Pattern 124 | >> >> >> 125 | /BBox [ 0.000000 0.000000 1280.000000 100.000000 ] 126 | >> 127 | stream 128 | /DeviceGray CS 129 | /DeviceGray cs 130 | 1.000000 0.000000 -0.000000 1.000000 0.000000 -18.187927 cm 131 | 0.000000 114.814453 m 132 | 485.785400 44.782616 687.925964 136.375824 1280.000000 114.814453 c 133 | 1280.000000 18.187927 l 134 | 0.000000 18.187927 l 135 | 0.000000 114.814453 l 136 | h 137 | /Pattern cs 138 | /P1 scn 139 | f 140 | n 141 | 142 | endstream 143 | endobj 144 | 145 | 12 0 obj 146 | 273 147 | endobj 148 | 149 | 13 0 obj 150 | << /Pattern << /P2 << /Matrix [ 191.301773 -405.610107 405.610107 191.301773 -340.965271 -242.819534 ] 151 | /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] 152 | /Extend [ true true ] 153 | /Domain [ 0.000000 1.000000 ] 154 | /ShadingType 2 155 | /ColorSpace /DeviceRGB 156 | /Function 1 0 R 157 | >> 158 | /PatternType 2 159 | /Type /Pattern 160 | >> 161 | /P1 << /Matrix [ -0.000000 -45.000004 45.000004 -0.000000 -45.000004 100.000000 ] 162 | /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] 163 | /Extend [ true true ] 164 | /Domain [ 0.000000 1.000000 ] 165 | /ShadingType 2 166 | /ColorSpace /DeviceRGB 167 | /Function 3 0 R 168 | >> 169 | /PatternType 2 170 | /Type /Pattern 171 | >> 172 | >> 173 | /ExtGState << /E2 << /SMask << /Type /Mask 174 | /G 7 0 R 175 | /S /Luminosity 176 | >> 177 | /Type /ExtGState 178 | >> 179 | /E1 << /SMask << /Type /Mask 180 | /G 11 0 R 181 | /S /Luminosity 182 | >> 183 | /Type /ExtGState 184 | >> 185 | >> 186 | >> 187 | endobj 188 | 189 | 14 0 obj 190 | << /Length 15 0 R >> 191 | stream 192 | /DeviceRGB CS 193 | /DeviceRGB cs 194 | q 195 | /E1 gs 196 | 1.000000 0.000000 -0.000000 1.000000 0.000000 -18.187927 cm 197 | /Pattern cs 198 | /P1 scn 199 | 0.000000 114.814453 m 200 | 485.785400 44.782616 687.925964 136.375824 1280.000000 114.814453 c 201 | 1280.000000 18.187927 l 202 | 0.000000 18.187927 l 203 | 0.000000 114.814453 l 204 | h 205 | f 206 | n 207 | Q 208 | q 209 | /E2 gs 210 | 1.000000 0.000000 -0.000000 1.000000 0.000000 -17.827332 cm 211 | /Pattern cs 212 | /P2 scn 213 | 0.000000 99.453758 m 214 | 451.282043 61.327290 736.820496 125.827332 1280.000000 94.453758 c 215 | 1280.000000 22.453735 l 216 | 757.157043 82.309814 511.689301 50.516239 0.000000 22.453735 c 217 | 0.000000 99.453758 l 218 | h 219 | f 220 | n 221 | Q 222 | 223 | endstream 224 | endobj 225 | 226 | 15 0 obj 227 | 575 228 | endobj 229 | 230 | 16 0 obj 231 | << /Annots [] 232 | /Type /Page 233 | /MediaBox [ 0.000000 0.000000 1280.000000 100.000000 ] 234 | /Resources 13 0 R 235 | /Contents 14 0 R 236 | /Parent 17 0 R 237 | >> 238 | endobj 239 | 240 | 17 0 obj 241 | << /Kids [ 16 0 R ] 242 | /Count 1 243 | /Type /Pages 244 | >> 245 | endobj 246 | 247 | 18 0 obj 248 | << /Type /Catalog 249 | /Pages 17 0 R 250 | >> 251 | endobj 252 | 253 | xref 254 | 0 19 255 | 0000000000 65535 f 256 | 0000000010 00000 n 257 | 0000000533 00000 n 258 | 0000000555 00000 n 259 | 0000001075 00000 n 260 | 0000001097 00000 n 261 | 0000001393 00000 n 262 | 0000001415 00000 n 263 | 0000002761 00000 n 264 | 0000002783 00000 n 265 | 0000003080 00000 n 266 | 0000003103 00000 n 267 | 0000004406 00000 n 268 | 0000004429 00000 n 269 | 0000006206 00000 n 270 | 0000006839 00000 n 271 | 0000006862 00000 n 272 | 0000007042 00000 n 273 | 0000007118 00000 n 274 | trailer 275 | << /ID [ (some) (id) ] 276 | /Root 18 0 R 277 | /Size 19 278 | >> 279 | startxref 280 | 7179 281 | %%EOF -------------------------------------------------------------------------------- /SwiftUI for iOS 15/Assets.xcassets/Waves/Waves 2.imageset/Waves 2 Dark.pdf: -------------------------------------------------------------------------------- 1 | %PDF-1.7 2 | 3 | 1 0 obj 4 | << /Length 2 0 R 5 | /FunctionType 4 6 | /Domain [ 0.000000 1.000000 ] 7 | /Range [ 0.000000 1.000000 0.000000 1.000000 0.000000 1.000000 ] 8 | >> 9 | stream 10 | { 0.109080 exch 0.109080 exch 0.254167 exch dup 0.035511 gt { exch pop exch pop exch pop dup 0.035511 sub -0.037171 mul 0.109080 add exch dup 0.035511 sub -0.037171 mul 0.109080 add exch dup 0.035511 sub -0.017280 mul 0.254167 add exch } if dup 1.000000 gt { exch pop exch pop exch pop 0.073229 exch 0.073229 exch 0.237500 exch } if pop } 11 | endstream 12 | endobj 13 | 14 | 2 0 obj 15 | 339 16 | endobj 17 | 18 | 3 0 obj 19 | << /Length 4 0 R 20 | /FunctionType 4 21 | /Domain [ 0.000000 1.000000 ] 22 | /Range [ 0.000000 1.000000 0.000000 1.000000 0.000000 1.000000 ] 23 | >> 24 | stream 25 | { 0.145098 exch 0.145098 exch 0.294118 exch dup 0.000000 gt { exch pop exch pop exch pop dup 0.000000 sub 0.000000 mul 0.145098 add exch dup 0.000000 sub 0.000000 mul 0.145098 add exch dup 0.000000 sub 0.000000 mul 0.294118 add exch } if dup 1.000000 gt { exch pop exch pop exch pop 0.145098 exch 0.145098 exch 0.294118 exch } if pop } 26 | endstream 27 | endobj 28 | 29 | 4 0 obj 30 | 336 31 | endobj 32 | 33 | 5 0 obj 34 | << /Length 6 0 R 35 | /FunctionType 4 36 | /Domain [ 0.000000 1.000000 ] 37 | /Range [ 0.000000 1.000000 ] 38 | >> 39 | stream 40 | { 0.500000 exch dup 0.035511 gt { exch pop dup 0.035511 sub 0.518409 mul 0.500000 add exch } if dup 1.000000 gt { exch pop 1.000000 exch } if pop } 41 | endstream 42 | endobj 43 | 44 | 6 0 obj 45 | 148 46 | endobj 47 | 48 | 7 0 obj 49 | << /Type /XObject 50 | /Length 8 0 R 51 | /Group << /Type /Group 52 | /S /Transparency 53 | /CS /DeviceGray 54 | >> 55 | /Subtype /Form 56 | /Resources << /Pattern << /P1 << /Matrix [ 191.301773 -405.610107 405.610107 191.301773 -340.965271 -242.819595 ] 57 | /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] 58 | /Extend [ true true ] 59 | /Domain [ 0.000000 1.000000 ] 60 | /ShadingType 2 61 | /ColorSpace /DeviceGray 62 | /Function 5 0 R 63 | >> 64 | /PatternType 2 65 | /Type /Pattern 66 | >> >> >> 67 | /BBox [ 0.000000 0.000000 1280.000000 100.000000 ] 68 | >> 69 | stream 70 | /DeviceGray CS 71 | /DeviceGray cs 72 | 1.000000 0.000000 -0.000000 1.000000 0.000000 -17.827332 cm 73 | 0.000000 99.453758 m 74 | 451.282043 61.327290 736.820496 125.827332 1280.000000 94.453758 c 75 | 1280.000000 22.453735 l 76 | 757.157043 82.309814 511.689301 50.516239 0.000000 22.453735 c 77 | 0.000000 99.453758 l 78 | h 79 | /Pattern cs 80 | /P1 scn 81 | f 82 | n 83 | 84 | endstream 85 | endobj 86 | 87 | 8 0 obj 88 | 312 89 | endobj 90 | 91 | 9 0 obj 92 | << /Length 10 0 R 93 | /FunctionType 4 94 | /Domain [ 0.000000 1.000000 ] 95 | /Range [ 0.000000 1.000000 ] 96 | >> 97 | stream 98 | { 0.400000 exch dup 0.000000 gt { exch pop dup 0.000000 sub 0.600000 mul 0.400000 add exch } if dup 1.000000 gt { exch pop 1.000000 exch } if pop } 99 | endstream 100 | endobj 101 | 102 | 10 0 obj 103 | 148 104 | endobj 105 | 106 | 11 0 obj 107 | << /Type /XObject 108 | /Length 12 0 R 109 | /Group << /Type /Group 110 | /S /Transparency 111 | /CS /DeviceGray 112 | >> 113 | /Subtype /Form 114 | /Resources << /Pattern << /P1 << /Matrix [ -0.000000 -59.702690 59.702690 -0.000000 -59.702690 100.000000 ] 115 | /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] 116 | /Extend [ true true ] 117 | /Domain [ 0.000000 1.000000 ] 118 | /ShadingType 2 119 | /ColorSpace /DeviceGray 120 | /Function 9 0 R 121 | >> 122 | /PatternType 2 123 | /Type /Pattern 124 | >> >> >> 125 | /BBox [ 0.000000 0.000000 1280.000000 100.000000 ] 126 | >> 127 | stream 128 | /DeviceGray CS 129 | /DeviceGray cs 130 | 1.000000 0.000000 -0.000000 1.000000 0.000000 -18.187927 cm 131 | 0.000000 114.814453 m 132 | 485.785400 44.782616 687.925964 136.375824 1280.000000 114.814453 c 133 | 1280.000000 18.187927 l 134 | 0.000000 18.187927 l 135 | 0.000000 114.814453 l 136 | h 137 | /Pattern cs 138 | /P1 scn 139 | f 140 | n 141 | 142 | endstream 143 | endobj 144 | 145 | 12 0 obj 146 | 273 147 | endobj 148 | 149 | 13 0 obj 150 | << /Pattern << /P2 << /Matrix [ 191.301773 -405.610107 405.610107 191.301773 -340.965271 -242.819595 ] 151 | /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] 152 | /Extend [ true true ] 153 | /Domain [ 0.000000 1.000000 ] 154 | /ShadingType 2 155 | /ColorSpace /DeviceRGB 156 | /Function 1 0 R 157 | >> 158 | /PatternType 2 159 | /Type /Pattern 160 | >> 161 | /P1 << /Matrix [ -0.000000 -59.702690 59.702690 -0.000000 -59.702690 100.000000 ] 162 | /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] 163 | /Extend [ true true ] 164 | /Domain [ 0.000000 1.000000 ] 165 | /ShadingType 2 166 | /ColorSpace /DeviceRGB 167 | /Function 3 0 R 168 | >> 169 | /PatternType 2 170 | /Type /Pattern 171 | >> 172 | >> 173 | /ExtGState << /E2 << /SMask << /Type /Mask 174 | /G 7 0 R 175 | /S /Luminosity 176 | >> 177 | /Type /ExtGState 178 | >> 179 | /E1 << /SMask << /Type /Mask 180 | /G 11 0 R 181 | /S /Luminosity 182 | >> 183 | /Type /ExtGState 184 | >> 185 | >> 186 | >> 187 | endobj 188 | 189 | 14 0 obj 190 | << /Length 15 0 R >> 191 | stream 192 | /DeviceRGB CS 193 | /DeviceRGB cs 194 | q 195 | /E1 gs 196 | 1.000000 0.000000 -0.000000 1.000000 0.000000 -18.187927 cm 197 | /Pattern cs 198 | /P1 scn 199 | 0.000000 114.814453 m 200 | 485.785400 44.782616 687.925964 136.375824 1280.000000 114.814453 c 201 | 1280.000000 18.187927 l 202 | 0.000000 18.187927 l 203 | 0.000000 114.814453 l 204 | h 205 | f 206 | n 207 | Q 208 | q 209 | /E2 gs 210 | 1.000000 0.000000 -0.000000 1.000000 0.000000 -17.827332 cm 211 | /Pattern cs 212 | /P2 scn 213 | 0.000000 99.453758 m 214 | 451.282043 61.327290 736.820496 125.827332 1280.000000 94.453758 c 215 | 1280.000000 22.453735 l 216 | 757.157043 82.309814 511.689301 50.516239 0.000000 22.453735 c 217 | 0.000000 99.453758 l 218 | h 219 | f 220 | n 221 | Q 222 | 223 | endstream 224 | endobj 225 | 226 | 15 0 obj 227 | 575 228 | endobj 229 | 230 | 16 0 obj 231 | << /Annots [] 232 | /Type /Page 233 | /MediaBox [ 0.000000 0.000000 1280.000000 100.000000 ] 234 | /Resources 13 0 R 235 | /Contents 14 0 R 236 | /Parent 17 0 R 237 | >> 238 | endobj 239 | 240 | 17 0 obj 241 | << /Kids [ 16 0 R ] 242 | /Count 1 243 | /Type /Pages 244 | >> 245 | endobj 246 | 247 | 18 0 obj 248 | << /Type /Catalog 249 | /Pages 17 0 R 250 | >> 251 | endobj 252 | 253 | xref 254 | 0 19 255 | 0000000000 65535 f 256 | 0000000010 00000 n 257 | 0000000533 00000 n 258 | 0000000555 00000 n 259 | 0000001075 00000 n 260 | 0000001097 00000 n 261 | 0000001393 00000 n 262 | 0000001415 00000 n 263 | 0000002761 00000 n 264 | 0000002783 00000 n 265 | 0000003080 00000 n 266 | 0000003103 00000 n 267 | 0000004406 00000 n 268 | 0000004429 00000 n 269 | 0000006206 00000 n 270 | 0000006839 00000 n 271 | 0000006862 00000 n 272 | 0000007042 00000 n 273 | 0000007118 00000 n 274 | trailer 275 | << /ID [ (some) (id) ] 276 | /Root 18 0 R 277 | /Size 19 278 | >> 279 | startxref 280 | 7179 281 | %%EOF --------------------------------------------------------------------------------