├── 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 | 
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 | 
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 | 
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 | 
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
--------------------------------------------------------------------------------