├── Demo
├── vince.jpg
├── Assets.xcassets
│ ├── Contents.json
│ ├── AppIcon.appiconset
│ │ ├── ipad76.png
│ │ ├── mac128.png
│ │ ├── mac16.png
│ │ ├── mac256.png
│ │ ├── mac32.png
│ │ ├── mac512.png
│ │ ├── mac64.png
│ │ ├── ipad152.png
│ │ ├── iphone120.png
│ │ ├── iphone180.png
│ │ ├── mac1024.png
│ │ ├── ipadPro167.png
│ │ ├── settings58.png
│ │ ├── settings87.png
│ │ ├── spotlight80.png
│ │ ├── appstore1024.png
│ │ ├── ipadSettings29.png
│ │ ├── ipadSettings58.png
│ │ ├── notification40.png
│ │ ├── notification60.png
│ │ ├── spotlight120.png
│ │ ├── ipadSpotlight40.png
│ │ ├── ipadSpotlight80.png
│ │ ├── ipadNotification20.png
│ │ └── ipadNotification40.png
│ ├── AppIcon.solidimagestack
│ │ ├── Back.solidimagestacklayer
│ │ │ ├── Contents.json
│ │ │ └── Content.imageset
│ │ │ │ ├── or.jpg
│ │ │ │ └── Contents.json
│ │ ├── Front.solidimagestacklayer
│ │ │ ├── Contents.json
│ │ │ └── Content.imageset
│ │ │ │ ├── galss.png
│ │ │ │ └── Contents.json
│ │ ├── Middle.solidimagestacklayer
│ │ │ ├── Contents.json
│ │ │ └── Content.imageset
│ │ │ │ ├── dash circle.png
│ │ │ │ └── Contents.json
│ │ └── Contents.json
│ ├── Brand Assets.brandassets
│ │ ├── App Icon.imagestack
│ │ │ ├── Back.imagestacklayer
│ │ │ │ ├── Contents.json
│ │ │ │ └── Content.imageset
│ │ │ │ │ └── Contents.json
│ │ │ ├── Front.imagestacklayer
│ │ │ │ ├── Contents.json
│ │ │ │ └── Content.imageset
│ │ │ │ │ └── Contents.json
│ │ │ ├── Middle.imagestacklayer
│ │ │ │ ├── Contents.json
│ │ │ │ └── Content.imageset
│ │ │ │ │ └── Contents.json
│ │ │ └── Contents.json
│ │ ├── App Icon - App Store.imagestack
│ │ │ ├── Back.imagestacklayer
│ │ │ │ ├── Contents.json
│ │ │ │ └── Content.imageset
│ │ │ │ │ └── Contents.json
│ │ │ ├── Front.imagestacklayer
│ │ │ │ ├── Contents.json
│ │ │ │ └── Content.imageset
│ │ │ │ │ └── Contents.json
│ │ │ ├── Middle.imagestacklayer
│ │ │ │ ├── Contents.json
│ │ │ │ └── Content.imageset
│ │ │ │ │ └── Contents.json
│ │ │ └── Contents.json
│ │ ├── Top Shelf Image.imageset
│ │ │ └── Contents.json
│ │ ├── Top Shelf Image Wide.imageset
│ │ │ └── Contents.json
│ │ └── Contents.json
│ └── AccentColor.colorset
│ │ └── Contents.json
├── Preview Content
│ └── Preview Assets.xcassets
│ │ └── Contents.json
├── Localizable.xcstrings
├── TestView.swift
├── TestAPNS
│ ├── video.apns
│ ├── images.apns
│ ├── rating.apns
│ ├── watchVideo.apns
│ └── watchVideo copy.apns
├── Demo.entitlements
├── Info.plist
└── DemoApp.swift
├── Action
├── Media.xcassets
│ ├── Contents.json
│ └── TouchBarBezel.colorset
│ │ └── Contents.json
└── Info.plist
├── AppClips
├── Assets.xcassets
│ ├── Contents.json
│ ├── AppIcon.appiconset
│ │ ├── mac16.png
│ │ ├── mac32.png
│ │ ├── mac64.png
│ │ ├── ipad152.png
│ │ ├── ipad76.png
│ │ ├── mac1024.png
│ │ ├── mac128.png
│ │ ├── mac256.png
│ │ ├── mac512.png
│ │ ├── ipadPro167.png
│ │ ├── iphone120.png
│ │ ├── iphone180.png
│ │ ├── settings58.png
│ │ ├── settings87.png
│ │ ├── appstore1024.png
│ │ ├── spotlight120.png
│ │ ├── spotlight80.png
│ │ ├── ipadSettings29.png
│ │ ├── ipadSettings58.png
│ │ ├── ipadSpotlight40.png
│ │ ├── ipadSpotlight80.png
│ │ ├── notification40.png
│ │ ├── notification60.png
│ │ ├── ipadNotification20.png
│ │ └── ipadNotification40.png
│ └── AccentColor.colorset
│ │ └── Contents.json
├── Preview Content
│ └── Preview Assets.xcassets
│ │ └── Contents.json
├── AppClips.entitlements
├── Info.plist
└── AppClipsApp.swift
├── iMessage
├── Assets.xcassets
│ ├── Contents.json
│ ├── vince.imageset
│ │ ├── vince.jpg
│ │ └── Contents.json
│ └── iMessage App Icon.stickersiconset
│ │ ├── icon-messages-app-27x20@2x.png
│ │ ├── icon-messages-app-27x20@3x.png
│ │ ├── icon-messages-app-store-1024x768.png
│ │ ├── icon-messages-settings-29x29@2x.png
│ │ ├── icon-messages-settings-29x29@3x.png
│ │ ├── icon-messages-app-iPadAir-67x50@2x.png
│ │ ├── icon-messages-app-iPadAir-74x55@2x.png
│ │ ├── icon-messages-app-iPhone-60x45@2x.png
│ │ ├── icon-messages-app-iPhone-60x45@3x.png
│ │ ├── icon-messages-app-store-1024x1024.png
│ │ ├── icon-messages-settings-29x29@2x 1.png
│ │ ├── icon-messages-transcript-32x24@2x.png
│ │ ├── icon-messages-transcript-32x24@3x.png
│ │ └── Contents.json
└── Info.plist
├── Notification
├── Resources
│ ├── heroes-1.jpg
│ ├── heroes-2.jpg
│ ├── heroes-3.jpg
│ └── highlights.mp4
├── Info.plist
├── NotificationViewController.swift
└── NotificationViewController+UserNotifications.swift
├── HeroesWatch Watch App
├── Assets.xcassets
│ ├── Contents.json
│ ├── AppIcon.appiconset
│ │ ├── ItunesArtwork@2x.png
│ │ └── Contents.json
│ └── AccentColor.colorset
│ │ └── Contents.json
├── highlights.mp4
├── Preview Content
│ └── Preview Assets.xcassets
│ │ └── Contents.json
├── HeroesWatch Watch App.entitlements
├── ContentView.swift
└── HeroesWatchApp.swift
├── Heroes
├── Sources
│ ├── HeroShared
│ │ ├── Resources
│ │ │ ├── Assets.xcassets
│ │ │ │ ├── Contents.json
│ │ │ │ ├── pol.imageset
│ │ │ │ │ ├── pol.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── alex.imageset
│ │ │ │ │ ├── alex.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── brad.imageset
│ │ │ │ │ ├── brad.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── jane.imageset
│ │ │ │ │ ├── jane.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── mete.imageset
│ │ │ │ │ ├── mete.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── sara.imageset
│ │ │ │ │ ├── sara.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── shai.imageset
│ │ │ │ │ ├── shai.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── zach.imageset
│ │ │ │ │ ├── zach.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── andrea.imageset
│ │ │ │ │ ├── andrea.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── andrei.imageset
│ │ │ │ │ ├── andrei.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── beyza.imageset
│ │ │ │ │ ├── beyza.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── davide.imageset
│ │ │ │ │ ├── davide.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── emilio.imageset
│ │ │ │ │ ├── emilio.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── flora.imageset
│ │ │ │ │ ├── flora.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── gyuree.imageset
│ │ │ │ │ ├── gyuree.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── ios4.imageset
│ │ │ │ │ ├── images.jpeg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── josip.imageset
│ │ │ │ │ ├── josip.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── lukasz.imageset
│ │ │ │ │ ├── lukasz.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── marcin.imageset
│ │ │ │ │ ├── marcin.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── marco.imageset
│ │ │ │ │ ├── marco.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── natan.imageset
│ │ │ │ │ ├── natan.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── pedro.imageset
│ │ │ │ │ ├── pedro.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── peter.imageset
│ │ │ │ │ ├── peter.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── pietro.imageset
│ │ │ │ │ ├── pietro.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── vince 1.imageset
│ │ │ │ │ ├── vince.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── vince.imageset
│ │ │ │ │ ├── vince.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── alberto.imageset
│ │ │ │ │ ├── alberto.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── batuhan.imageset
│ │ │ │ │ ├── batuhan.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── borbala.imageset
│ │ │ │ │ ├── borbala.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── davide2.imageset
│ │ │ │ │ ├── davide2.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── ios8.imageset
│ │ │ │ │ ├── IOS_8_logo.png
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── ios9.imageset
│ │ │ │ │ ├── IOS_9_Logo.png
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── michael.imageset
│ │ │ │ │ ├── michael.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── pradnya.imageset
│ │ │ │ │ ├── pradnya.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── stefano.imageset
│ │ │ │ │ ├── stefano.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── Krysztof.imageset
│ │ │ │ │ ├── Krysztof.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── ios14.imageset
│ │ │ │ │ ├── IOS_14_Logo.png
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── vincenzo.imageset
│ │ │ │ │ ├── vincenzo.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── libranner.imageset
│ │ │ │ │ ├── libranner.jpg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── ios3.imageset
│ │ │ │ │ ├── IPhone_OS_3_logo.png
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── logo.imageset
│ │ │ │ │ ├── swift_heroes_logo.jpeg
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── ios10.imageset
│ │ │ │ │ ├── 240px-IOS_10_logo.svg.png
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── wordLogo.imageset
│ │ │ │ │ ├── logo_swiftheroes_ufficiale_SH-blu.png
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── heroBlue.colorset
│ │ │ │ │ └── Contents.json
│ │ │ │ └── heroOrange.colorset
│ │ │ │ │ └── Contents.json
│ │ │ └── Localizable.xcstrings
│ │ ├── Heroes.swift
│ │ ├── Enums
│ │ │ ├── ListType.swift
│ │ │ └── OperatingSystem.swift
│ │ ├── Extensions
│ │ │ ├── Color+Extensions.swift
│ │ │ ├── String+Extensions.swift
│ │ │ └── Image+Extensions.swift
│ │ ├── Protocols
│ │ │ └── Listable.swift
│ │ ├── Data
│ │ │ ├── ListItem.swift
│ │ │ └── ExtensionItem.swift
│ │ ├── Spotlight
│ │ │ └── Spotlight.swift
│ │ └── Notifications
│ │ │ └── NotificationHelper.swift
│ ├── MacroClient
│ │ └── main.swift
│ ├── MacroMacros
│ │ ├── CompilerPlugin.swift
│ │ ├── DebugListMacro.swift
│ │ ├── LogPropertyMacro.swift
│ │ ├── NavigationTitleMacro.swift
│ │ └── DebugPrintMacro.swift
│ ├── HeroiOS
│ │ ├── Extensions
│ │ │ ├── List+Extensions.swift
│ │ │ ├── UIViewController+Extensions.swift
│ │ │ └── View+Extensions.swift
│ │ ├── SceneDelegate.swift
│ │ ├── Modifiers
│ │ │ ├── ExternalScreenToolBarModifier.swift
│ │ │ ├── ForegroundViewModifier.swift
│ │ │ └── ExternalScreenViewModifier.swift
│ │ ├── ExternalScreens
│ │ │ ├── ScreenManager.swift
│ │ │ ├── ExternalScreenToolBar.swift
│ │ │ ├── ExternalScreenView.swift
│ │ │ └── ExternalScreenControlView.swift
│ │ ├── Views
│ │ │ ├── BackgroundView.swift
│ │ │ ├── PreviewItemView.swift
│ │ │ ├── MessageView.swift
│ │ │ ├── ShareView.swift
│ │ │ ├── SpeakerListView.swift
│ │ │ └── ExtensionListView.swift
│ │ ├── Resources
│ │ │ └── Localizable.xcstrings
│ │ ├── AppDelegate+QuickActions.swift
│ │ ├── QuickActions
│ │ │ └── QuickActionsManager.swift
│ │ ├── AppDelegate+Notifications.swift
│ │ └── AppDelegate.swift
│ └── Macros
│ │ └── Macros.swift
├── .gitignore
├── test.apns
├── Tests
│ ├── HeroiOSTests
│ │ └── HeroiOSTests.swift
│ ├── HeroSharedTests
│ │ └── HeroSharedTests.swift
│ └── MacroTests
│ │ └── MacroTests.swift
└── Package.swift
├── SwiftHeroesFaq
├── en
│ └── SwiftHeroesFaq.json
└── it
│ └── SwiftHeroesFaq.json
├── Demo.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ │ └── vince.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── swiftpm
│ │ └── Package.resolved
├── xcuserdata
│ ├── u380112.xcuserdatad
│ │ ├── xcdebugger
│ │ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ │ └── xcschememanagement.plist
│ └── vince.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
└── xcshareddata
│ └── xcschemes
│ ├── Demo.xcscheme
│ ├── Action.xcscheme
│ ├── iMessage.xcscheme
│ ├── Spotlight.xcscheme
│ ├── Notification.xcscheme
│ ├── NotificationService.xcscheme
│ └── Share.xcscheme
├── Spotlight
├── ImportExtension.swift
└── Info.plist
├── NotificationService
└── Info.plist
├── Preview
├── Info.plist
└── PreviewViewController.swift
├── Share
├── Info.plist
└── ShareViewController.swift
└── README.md
/Demo/vince.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/vince.jpg
--------------------------------------------------------------------------------
/Action/Media.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/iMessage/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Notification/Resources/heroes-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Notification/Resources/heroes-1.jpg
--------------------------------------------------------------------------------
/Notification/Resources/heroes-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Notification/Resources/heroes-2.jpg
--------------------------------------------------------------------------------
/Notification/Resources/heroes-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Notification/Resources/heroes-3.jpg
--------------------------------------------------------------------------------
/HeroesWatch Watch App/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/HeroesWatch Watch App/highlights.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/HeroesWatch Watch App/highlights.mp4
--------------------------------------------------------------------------------
/Notification/Resources/highlights.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Notification/Resources/highlights.mp4
--------------------------------------------------------------------------------
/Demo/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/AppClips/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Localizable.xcstrings:
--------------------------------------------------------------------------------
1 | {
2 | "sourceLanguage" : "en",
3 | "strings" : {
4 |
5 | },
6 | "version" : "1.0"
7 | }
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/ipad76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/ipad76.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/mac128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/mac128.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/mac16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/mac16.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/mac256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/mac256.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/mac32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/mac32.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/mac512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/mac512.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/mac64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/mac64.png
--------------------------------------------------------------------------------
/HeroesWatch Watch App/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/iMessage/Assets.xcassets/vince.imageset/vince.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/iMessage/Assets.xcassets/vince.imageset/vince.jpg
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/mac16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/mac16.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/mac32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/mac32.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/mac64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/mac64.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/ipad152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/ipad152.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/iphone120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/iphone120.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/iphone180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/iphone180.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/mac1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/mac1024.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/ipad152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/ipad152.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/ipad76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/ipad76.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/mac1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/mac1024.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/mac128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/mac128.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/mac256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/mac256.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/mac512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/mac512.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/ipadPro167.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/ipadPro167.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/settings58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/settings58.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/settings87.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/settings87.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/spotlight80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/spotlight80.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.solidimagestack/Back.solidimagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.solidimagestack/Front.solidimagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.solidimagestack/Middle.solidimagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/ipadPro167.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/ipadPro167.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/iphone120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/iphone120.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/iphone180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/iphone180.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/settings58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/settings58.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/settings87.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/settings87.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/appstore1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/appstore1024.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/ipadSettings29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/ipadSettings29.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/ipadSettings58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/ipadSettings58.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/notification40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/notification40.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/notification60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/notification60.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/spotlight120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/spotlight120.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/appstore1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/appstore1024.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/spotlight120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/spotlight120.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/spotlight80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/spotlight80.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/ipadSpotlight40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/ipadSpotlight40.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/ipadSpotlight80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/ipadSpotlight80.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/ipadSettings29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/ipadSettings29.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/ipadSettings58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/ipadSettings58.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/ipadSpotlight40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/ipadSpotlight40.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/ipadSpotlight80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/ipadSpotlight80.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/notification40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/notification40.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/notification60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/notification60.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/ipadNotification20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/ipadNotification20.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/ipadNotification40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.appiconset/ipadNotification40.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Heroes.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import SwiftUI
3 |
4 | public class Heroes {
5 | public init() {}
6 | public var test: String = "Testing"
7 | }
8 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/ipadNotification20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/ipadNotification20.png
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AppIcon.appiconset/ipadNotification40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/AppClips/Assets.xcassets/AppIcon.appiconset/ipadNotification40.png
--------------------------------------------------------------------------------
/Demo/Localizable.xcstrings:
--------------------------------------------------------------------------------
1 | {
2 | "sourceLanguage" : "en",
3 | "strings" : {
4 | "Cool" : {
5 |
6 | },
7 | "Name" : {
8 |
9 | }
10 | },
11 | "version" : "1.0"
12 | }
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Heroes/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /.build
3 | /Packages
4 | xcuserdata/
5 | DerivedData/
6 | .swiftpm/configuration/registries.json
7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
8 | .netrc
9 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/pol.imageset/pol.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/pol.imageset/pol.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/MacroClient/main.swift:
--------------------------------------------------------------------------------
1 | //
2 | // main.swift
3 | // Heroes
4 | //
5 | // Created by Vince Davis on 9/5/24.
6 | //
7 |
8 | import Macros
9 |
10 | let a = 17
11 | let b = 25
12 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/alex.imageset/alex.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/alex.imageset/alex.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/brad.imageset/brad.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/brad.imageset/brad.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/jane.imageset/jane.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/jane.imageset/jane.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/mete.imageset/mete.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/mete.imageset/mete.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/sara.imageset/sara.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/sara.imageset/sara.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/shai.imageset/shai.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/shai.imageset/shai.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/zach.imageset/zach.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/zach.imageset/zach.jpg
--------------------------------------------------------------------------------
/SwiftHeroesFaq/en/SwiftHeroesFaq.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "answer" : "wow this is cool",
4 | "level" : 1,
5 | "sortOrder" : 1,
6 | "question" : "Testing Out",
7 | "linkType" : "none"
8 | }
9 | ]
--------------------------------------------------------------------------------
/SwiftHeroesFaq/it/SwiftHeroesFaq.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "answer" : "wow this is cool",
4 | "level" : 1,
5 | "sortOrder" : 1,
6 | "question" : "Testing Out",
7 | "linkType" : "none"
8 | }
9 | ]
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/andrea.imageset/andrea.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/andrea.imageset/andrea.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/andrei.imageset/andrei.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/andrei.imageset/andrei.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/beyza.imageset/beyza.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/beyza.imageset/beyza.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/davide.imageset/davide.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/davide.imageset/davide.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/emilio.imageset/emilio.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/emilio.imageset/emilio.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/flora.imageset/flora.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/flora.imageset/flora.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/gyuree.imageset/gyuree.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/gyuree.imageset/gyuree.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/ios4.imageset/images.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/ios4.imageset/images.jpeg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/josip.imageset/josip.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/josip.imageset/josip.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/lukasz.imageset/lukasz.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/lukasz.imageset/lukasz.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/marcin.imageset/marcin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/marcin.imageset/marcin.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/marco.imageset/marco.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/marco.imageset/marco.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/natan.imageset/natan.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/natan.imageset/natan.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/pedro.imageset/pedro.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/pedro.imageset/pedro.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/peter.imageset/peter.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/peter.imageset/peter.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/pietro.imageset/pietro.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/pietro.imageset/pietro.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/vince 1.imageset/vince.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/vince 1.imageset/vince.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/vince.imageset/vince.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/vince.imageset/vince.jpg
--------------------------------------------------------------------------------
/HeroesWatch Watch App/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/HeroesWatch Watch App/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png
--------------------------------------------------------------------------------
/Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/alberto.imageset/alberto.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/alberto.imageset/alberto.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/batuhan.imageset/batuhan.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/batuhan.imageset/batuhan.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/borbala.imageset/borbala.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/borbala.imageset/borbala.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/davide2.imageset/davide2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/davide2.imageset/davide2.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/ios8.imageset/IOS_8_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/ios8.imageset/IOS_8_logo.png
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/ios9.imageset/IOS_9_Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/ios9.imageset/IOS_9_Logo.png
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/michael.imageset/michael.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/michael.imageset/michael.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/pradnya.imageset/pradnya.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/pradnya.imageset/pradnya.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/stefano.imageset/stefano.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/stefano.imageset/stefano.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/Krysztof.imageset/Krysztof.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/Krysztof.imageset/Krysztof.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/ios14.imageset/IOS_14_Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/ios14.imageset/IOS_14_Logo.png
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/vincenzo.imageset/vincenzo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/vincenzo.imageset/vincenzo.jpg
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/libranner.imageset/libranner.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/libranner.imageset/libranner.jpg
--------------------------------------------------------------------------------
/AppClips/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/ios3.imageset/IPhone_OS_3_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/ios3.imageset/IPhone_OS_3_logo.png
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/logo.imageset/swift_heroes_logo.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/logo.imageset/swift_heroes_logo.jpeg
--------------------------------------------------------------------------------
/Heroes/Sources/MacroMacros/CompilerPlugin.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CompilerPlugin.swift
3 | // Heroes
4 | //
5 | // Created by Vince Davis on 9/5/24.
6 | //
7 |
8 | import SwiftCompilerPlugin
9 | import SwiftSyntaxMacros
10 |
11 |
12 |
--------------------------------------------------------------------------------
/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-app-27x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-app-27x20@2x.png
--------------------------------------------------------------------------------
/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-app-27x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-app-27x20@3x.png
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/ios10.imageset/240px-IOS_10_logo.svg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/ios10.imageset/240px-IOS_10_logo.svg.png
--------------------------------------------------------------------------------
/Demo.xcodeproj/project.xcworkspace/xcuserdata/vince.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo.xcodeproj/project.xcworkspace/xcuserdata/vince.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.solidimagestack/Back.solidimagestacklayer/Content.imageset/or.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.solidimagestack/Back.solidimagestacklayer/Content.imageset/or.jpg
--------------------------------------------------------------------------------
/HeroesWatch Watch App/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-app-store-1024x768.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-app-store-1024x768.png
--------------------------------------------------------------------------------
/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-settings-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-settings-29x29@2x.png
--------------------------------------------------------------------------------
/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-settings-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-settings-29x29@3x.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.solidimagestack/Front.solidimagestacklayer/Content.imageset/galss.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.solidimagestack/Front.solidimagestacklayer/Content.imageset/galss.png
--------------------------------------------------------------------------------
/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-app-iPadAir-67x50@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-app-iPadAir-67x50@2x.png
--------------------------------------------------------------------------------
/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-app-iPadAir-74x55@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-app-iPadAir-74x55@2x.png
--------------------------------------------------------------------------------
/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-app-iPhone-60x45@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-app-iPhone-60x45@2x.png
--------------------------------------------------------------------------------
/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-app-iPhone-60x45@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-app-iPhone-60x45@3x.png
--------------------------------------------------------------------------------
/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-app-store-1024x1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-app-store-1024x1024.png
--------------------------------------------------------------------------------
/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-settings-29x29@2x 1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-settings-29x29@2x 1.png
--------------------------------------------------------------------------------
/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-transcript-32x24@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-transcript-32x24@2x.png
--------------------------------------------------------------------------------
/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-transcript-32x24@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/icon-messages-transcript-32x24@3x.png
--------------------------------------------------------------------------------
/Demo/TestView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TestView.swift
3 | // Demo
4 | //
5 | // Created by Vince Davis on 9/5/24.
6 | //
7 |
8 | import SwiftUI
9 | import Macros
10 |
11 |
12 | @NavigationTitle("Cool")
13 | struct UserProfileView: View {
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.solidimagestack/Middle.solidimagestacklayer/Content.imageset/dash circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Demo/Assets.xcassets/AppIcon.solidimagestack/Middle.solidimagestacklayer/Content.imageset/dash circle.png
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/wordLogo.imageset/logo_swiftheroes_ufficiale_SH-blu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vinced45/Swift-Heroes-Demo/HEAD/Heroes/Sources/HeroShared/Resources/Assets.xcassets/wordLogo.imageset/logo_swiftheroes_ufficiale_SH-blu.png
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "tv"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "tv"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "tv"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Demo/TestAPNS/video.apns:
--------------------------------------------------------------------------------
1 | {
2 | "aps": {
3 | "category" : "video",
4 | "alert": {
5 | "title": "Swift Heroes Push",
6 | "body": "Open this to see our cool video"
7 | }
8 | },
9 | "Simulator Target Bundle": "com.swiftheroes.Demo"
10 | }
11 |
--------------------------------------------------------------------------------
/Action/Media.xcassets/TouchBarBezel.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | },
6 | "colors" : [
7 | {
8 | "idiom" : "mac",
9 | "color" : {
10 | "reference" : "systemPurpleColor"
11 | }
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/Demo/TestAPNS/images.apns:
--------------------------------------------------------------------------------
1 | {
2 | "aps": {
3 | "category" : "images",
4 | "alert": {
5 | "title": "Swift Heroes Slideshow",
6 | "body": "This is an example of a slideshow"
7 | }
8 | },
9 | "Simulator Target Bundle": "com.swiftheroes.Demo"
10 | }
11 |
--------------------------------------------------------------------------------
/Demo/TestAPNS/rating.apns:
--------------------------------------------------------------------------------
1 | {
2 | "aps": {
3 | "category" : "default",
4 | "alert": {
5 | "title": "Swift Heroes Ratings",
6 | "body": "Please rate us to tell us how we did."
7 | }
8 | },
9 | "Simulator Target Bundle": "com.swiftheroes.Demo"
10 | }
11 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Enums/ListType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/14/24.
6 | //
7 |
8 | import Foundation
9 |
10 | public enum ListType: String {
11 | case sectionHeader
12 | case speaker
13 | case extensionItem
14 | case faq
15 | }
16 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.solidimagestack/Back.solidimagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "or.jpg",
5 | "idiom" : "vision",
6 | "scale" : "2x"
7 | }
8 | ],
9 | "info" : {
10 | "author" : "xcode",
11 | "version" : 1
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/HeroesWatch Watch App/HeroesWatch Watch App.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | aps-environment
6 | development
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Demo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.solidimagestack/Front.solidimagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "galss.png",
5 | "idiom" : "vision",
6 | "scale" : "2x"
7 | }
8 | ],
9 | "info" : {
10 | "author" : "xcode",
11 | "version" : 1
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Heroes/test.apns:
--------------------------------------------------------------------------------
1 | {
2 | "aps": {
3 | "alert": {
4 | "title": "Cool Video",
5 | "body": "You can do video on Apple Watch!"
6 | },
7 | "category": "video",
8 | "thread-id": "5280"
9 | },
10 | "Simulator Target Bundle": "com.swiftheroes.Demo.watchkitapp"
11 | }
12 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.solidimagestack/Middle.solidimagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "dash circle.png",
5 | "idiom" : "vision",
6 | "scale" : "2x"
7 | }
8 | ],
9 | "info" : {
10 | "author" : "xcode",
11 | "version" : 1
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "tv",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "tv",
9 | "scale" : "2x"
10 | }
11 | ],
12 | "info" : {
13 | "author" : "xcode",
14 | "version" : 1
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Extensions/Color+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Color.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/8/24.
6 | //
7 |
8 | import SwiftUI
9 |
10 | public extension Color {
11 | static let heroOrange = Color("heroOrange", bundle: .module)
12 | static let heroBlue = Color("heroBlue", bundle: .module)
13 | }
14 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/Brand Assets.brandassets/Top Shelf Image Wide.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "tv",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "tv",
9 | "scale" : "2x"
10 | }
11 | ],
12 | "info" : {
13 | "author" : "xcode",
14 | "version" : 1
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/HeroesWatch Watch App/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "ItunesArtwork@2x.png",
5 | "idiom" : "universal",
6 | "platform" : "watchos",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "tv",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "tv",
9 | "scale" : "2x"
10 | }
11 | ],
12 | "info" : {
13 | "author" : "xcode",
14 | "version" : 1
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "tv",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "tv",
9 | "scale" : "2x"
10 | }
11 | ],
12 | "info" : {
13 | "author" : "xcode",
14 | "version" : 1
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "tv",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "tv",
9 | "scale" : "2x"
10 | }
11 | ],
12 | "info" : {
13 | "author" : "xcode",
14 | "version" : 1
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.solidimagestack/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | },
6 | "layers" : [
7 | {
8 | "filename" : "Front.solidimagestacklayer"
9 | },
10 | {
11 | "filename" : "Middle.solidimagestacklayer"
12 | },
13 | {
14 | "filename" : "Back.solidimagestacklayer"
15 | }
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/Brand Assets.brandassets/App Icon.imagestack/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | },
6 | "layers" : [
7 | {
8 | "filename" : "Front.imagestacklayer"
9 | },
10 | {
11 | "filename" : "Middle.imagestacklayer"
12 | },
13 | {
14 | "filename" : "Back.imagestacklayer"
15 | }
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/Demo/TestAPNS/watchVideo.apns:
--------------------------------------------------------------------------------
1 | {
2 | "aps": {
3 | "alert": {
4 | "title": "Silver Salmon Creek",
5 | "body": "You are within 5 miles of Silver Salmon Creek."
6 | },
7 | "category": "LandmarkNear",
8 | "thread-id": "5280"
9 | },
10 | "landmarkIndex": 1,
11 | "Simulator Target Bundle": "com.swiftheroes.Demo.watchkitapp"
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/AppClips/AppClips.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.developer.parent-application-identifiers
6 |
7 | $(AppIdentifierPrefix)com.swiftheroes.Demo
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | },
6 | "layers" : [
7 | {
8 | "filename" : "Front.imagestacklayer"
9 | },
10 | {
11 | "filename" : "Middle.imagestacklayer"
12 | },
13 | {
14 | "filename" : "Back.imagestacklayer"
15 | }
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/AppClips/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSAppClip
6 |
7 | NSAppClipRequestEphemeralUserNotification
8 |
9 | NSAppClipRequestLocationConfirmation
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroiOS/Extensions/List+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/14/24.
6 | //
7 |
8 | import SwiftUI
9 |
10 | public extension List {
11 | func customListStyle() -> some View {
12 | self
13 | #if os(iOS)
14 | .listStyle(.grouped)
15 | #elseif os(macOS)
16 | .listStyle(.sidebar)
17 | #endif
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Extensions/String+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // String.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/14/24.
6 | //
7 |
8 | import Foundation
9 |
10 | public extension String {
11 | static let iphone = "iphone"
12 | static let watch = "applewatch"
13 | static let ipad = "ipad"
14 | static let mac = "macbook"
15 | static let tv = "appletv"
16 | static let xr = "visionpro"
17 | }
18 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Protocols/Listable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Listable.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/14/24.
6 | //
7 |
8 | import Foundation
9 | import SwiftUI
10 |
11 | public protocol Listable {
12 | var id: String { get }
13 | var title: String { get }
14 | var subtitle: String { get }
15 | var image: Image { get }
16 | var badges: [String] { get }
17 | var type: ListType { get }
18 | }
19 |
--------------------------------------------------------------------------------
/iMessage/Assets.xcassets/vince.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "vince.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 |
--------------------------------------------------------------------------------
/Demo/TestAPNS/watchVideo copy.apns:
--------------------------------------------------------------------------------
1 | {
2 | "aps": {
3 | "category" : "default",
4 | "alert": {
5 | "title": "Beautiful View",
6 | "subtitle": "",
7 | "body" : "Denali, Alaska",
8 | },
9 | "mutable-content": 1
10 | },
11 | "attachment-url": "https://www.nps.gov/dena/learn/nature/images/wildlife-landing.jpg",
12 | "Simulator Target Bundle": "com.swiftheroes.Demo"
13 | }
14 |
--------------------------------------------------------------------------------
/Heroes/Tests/HeroiOSTests/HeroiOSTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import HeroiOS
3 |
4 | final class HeroiOSTests: XCTestCase {
5 | func testExample() throws {
6 | // XCTest Documentation
7 | // https://developer.apple.com/documentation/xctest
8 |
9 | // Defining Test Cases and Test Methods
10 | // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods
11 | }
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/Heroes/Tests/HeroSharedTests/HeroSharedTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import HeroShared
3 |
4 | final class HeroSharedTests: XCTestCase {
5 | func testExample() throws {
6 | // XCTest Documentation
7 | // https://developer.apple.com/documentation/xctest
8 |
9 | // Defining Test Cases and Test Methods
10 | // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/alex.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "alex.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/brad.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "brad.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/jane.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "jane.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/mete.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "mete.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/pol.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "pol.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/sara.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "sara.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/shai.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "shai.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/zach.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "zach.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/alberto.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "alberto.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/andrea.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "andrea.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/andrei.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "andrei.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/batuhan.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "batuhan.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/beyza.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "beyza.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/borbala.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "borbala.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/davide.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "davide.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/davide2.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "davide2.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/emilio.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "emilio.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/flora.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "flora.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/gyuree.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "gyuree.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/ios4.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "images.jpeg",
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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/ios8.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "IOS_8_logo.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/ios9.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "IOS_9_Logo.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/josip.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "josip.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/lukasz.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "lukasz.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/marcin.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "marcin.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/marco.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "marco.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/michael.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "michael.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/natan.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "natan.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/pedro.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "pedro.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/peter.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "peter.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/pietro.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "pietro.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/pradnya.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "pradnya.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/stefano.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "stefano.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/vince 1.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "vince.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/vince.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "vince.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/Krysztof.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "Krysztof.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/ios14.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "IOS_14_Logo.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/libranner.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "libranner.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/vincenzo.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "vincenzo.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 |
--------------------------------------------------------------------------------
/Spotlight/ImportExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ImportExtension.swift
3 | // Spotlight
4 | //
5 | // Created by Vince Davis on 4/7/24.
6 | //
7 |
8 | import CoreSpotlight
9 |
10 | class ImportExtension: CSImportExtension {
11 |
12 | override func update(_ attributes: CSSearchableItemAttributeSet, forFileAt: URL) throws {
13 | // Add attributes that describe the file at contentURL.
14 | // Throw an error with details on failure.
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/ios3.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "IPhone_OS_3_logo.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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/logo.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "swift_heroes_logo.jpeg",
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 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/ios10.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "240px-IOS_10_logo.svg.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 |
--------------------------------------------------------------------------------
/iMessage/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSExtension
6 |
7 | NSExtensionPointIdentifier
8 | com.apple.message-payload-provider
9 | NSExtensionPrincipalClass
10 | $(PRODUCT_MODULE_NAME).MessagesViewController
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/AppClips/AppClipsApp.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppClipsApp.swift
3 | // AppClips
4 | //
5 | // Created by Vince Davis on 4/8/24.
6 | //
7 |
8 | import SwiftUI
9 | import Observation
10 | import HeroiOS
11 | import HeroShared
12 |
13 | @main
14 | struct AppClipsApp: App {
15 | @State var screenManager = ScreenManager()
16 |
17 | var body: some Scene {
18 | WindowGroup {
19 | SpeakerListView()
20 | .environment(screenManager)
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/wordLogo.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "logo_swiftheroes_ufficiale_SH-blu.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 |
--------------------------------------------------------------------------------
/NotificationService/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSExtension
6 |
7 | NSExtensionPointIdentifier
8 | com.apple.usernotifications.service
9 | NSExtensionPrincipalClass
10 | $(PRODUCT_MODULE_NAME).NotificationService
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Demo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "originHash" : "17764b17a716c53bb44bc8b2eb5cca990ca86802f763a445d883f1bbc6ad8c0d",
3 | "pins" : [
4 | {
5 | "identity" : "swift-syntax",
6 | "kind" : "remoteSourceControl",
7 | "location" : "https://github.com/swiftlang/swift-syntax.git",
8 | "state" : {
9 | "revision" : "64889f0c732f210a935a0ad7cda38f77f876262d",
10 | "version" : "509.1.1"
11 | }
12 | }
13 | ],
14 | "version" : 3
15 | }
16 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroiOS/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // Demo
4 | //
5 | // Created by Vince Davis on 4/10/24.
6 | //
7 |
8 | #if os(iOS)
9 | import UIKit
10 | public class SceneDelegate: UIResponder, UIWindowSceneDelegate {
11 | public func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
12 | QuickActionsManager.shared.handleQaItem(type: shortcutItem.type)
13 | print("scene delegate with item \(shortcutItem.type)")
14 | }
15 | }
16 | #endif
17 |
--------------------------------------------------------------------------------
/Heroes/Sources/MacroMacros/DebugListMacro.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DebugListMacro.swift
3 | // Heroes
4 | //
5 | // Created by Vince Davis on 9/5/24.
6 | //
7 |
8 | import SwiftCompilerPlugin
9 | import SwiftSyntax
10 | import SwiftSyntaxBuilder
11 | import SwiftSyntaxMacros
12 |
13 | //public struct DebugListMacro: MemberMacro {
14 | // public static func expansion(
15 | // of node: AttributeSyntax,
16 | // providingMembersOf declaration: some DeclGroupSyntax,
17 | // in context: some MacroExpansionContext
18 | // ) throws -> [DeclSyntax] {
19 | // // Implementation as before
20 | // }
21 | //}
22 |
--------------------------------------------------------------------------------
/Demo/Demo.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | aps-environment
6 | development
7 | com.apple.developer.aps-environment
8 | development
9 | com.apple.security.app-sandbox
10 |
11 | com.apple.security.application-groups
12 |
13 | group.com.swiftheroes.demo
14 |
15 | com.apple.security.files.user-selected.read-only
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroiOS/Modifiers/ExternalScreenToolBarModifier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/13/24.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct ExternalScreenToolBarModifier: ViewModifier {
11 | var screenManager: ScreenManager
12 | @Binding var showingSheet: Bool
13 |
14 | func body(content: Content) -> some View {
15 | #if os(iOS)
16 | return content
17 | .toolbar {
18 | ExternalScreenToolBar(screenManager: screenManager, showingSheet: $showingSheet)
19 | }
20 | #else
21 | return content
22 | #endif
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Heroes/Sources/MacroMacros/LogPropertyMacro.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LogPropertyMacro.swift
3 | // Heroes
4 | //
5 | // Created by Vince Davis on 9/5/24.
6 | //
7 |
8 | import SwiftCompilerPlugin
9 | import SwiftSyntax
10 | import SwiftSyntaxBuilder
11 | import SwiftSyntaxMacros
12 |
13 | //public struct LogPropertyMacro: AccessorMacro {
14 | // public static func expansion(
15 | // of node: AttributeSyntax,
16 | // providingAccessorsOf declaration: some DeclSyntaxProtocol,
17 | // in context: some MacroExpansionContext
18 | // ) throws -> [AccessorDeclSyntax] {
19 | // // Implementation for logging property access
20 | // }
21 | //}
22 |
--------------------------------------------------------------------------------
/Preview/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSExtension
6 |
7 | NSExtensionAttributes
8 |
9 | QLIsDataBasedPreview
10 |
11 | QLSupportedContentTypes
12 |
13 | QLSupportsSearchableItems
14 |
15 |
16 | NSExtensionPrincipalClass
17 | $(PRODUCT_MODULE_NAME).PreviewViewController
18 | NSExtensionPointIdentifier
19 | com.apple.quicklook.preview
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Enums/OperatingSystem.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/13/24.
6 | //
7 |
8 | import Foundation
9 |
10 | public enum OperatingSystem {
11 | case macOS
12 | case iOS
13 | case tvOS
14 | case watchOS
15 | case visionOS
16 |
17 | #if os(macOS)
18 | public static let current = macOS
19 | #elseif os(iOS)
20 | public static let current = iOS
21 | #elseif os(tvOS)
22 | public static let current = tvOS
23 | #elseif os(watchOS)
24 | public static let current = watchOS
25 | #elseif os(visionOS)
26 | public static let current = visionOS
27 | #else
28 | #error("Unsupported platform")
29 | #endif
30 | }
31 |
--------------------------------------------------------------------------------
/Spotlight/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CSExtensionLabel
6 | SpotlightImporter
7 | NSExtension
8 |
9 | NSExtensionAttributes
10 |
11 | CSSupportedContentTypes
12 |
13 | com.example.plain-text
14 |
15 |
16 | NSExtensionPointIdentifier
17 | com.apple.spotlight.import
18 | NSExtensionPrincipalClass
19 | $(PRODUCT_MODULE_NAME).ImportExtension
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroiOS/ExternalScreens/ScreenManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/8/24.
6 | //
7 |
8 | import Foundation
9 | import SwiftUI
10 | import Observation
11 | import HeroShared
12 |
13 | @Observable
14 | public class ScreenManager {
15 | public init() {}
16 |
17 | public var showScreen = false
18 | public var speaker: Speaker = .alex
19 | public var selection: Int = 0
20 | public var speakers: [Speaker] = Speaker.all
21 |
22 | public func add() {
23 | selection += 1
24 | speaker = speakers[selection]
25 | }
26 |
27 | public func minus() {
28 | selection -= 1
29 | speaker = speakers[selection]
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Heroes/Sources/Macros/Macros.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Macros.swift
3 | // Heroes
4 | //
5 | // Created by Vince Davis on 9/5/24.
6 | //
7 |
8 | //@attached(member, names: named(debugList))
9 | //public macro DebugList() = #externalMacro(module: "MacroMacros", type: "DebugListMacro")
10 | //
11 | //@attached(accessor)
12 | //public macro LogProperty() = #externalMacro(module: "MacroMacros", type: "LogPropertyMacro")
13 |
14 | //@attached(member, names: named(debugPrintModifier))
15 | //public macro DebugPrint(_ properties: String...) = #externalMacro(module: "MacroMacros", type: "DebugPrintMacro")
16 |
17 | @attached(member, names: named(body))
18 | public macro NavigationTitle(_ title: String) = #externalMacro(module: "MacroMacros", type: "NavigationTitleMacro")
19 |
--------------------------------------------------------------------------------
/Demo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CoreSpotlightActions
6 |
7 |
8 | CoreSpotlightActionIdentifier
9 | CS_ACTION_1
10 | CoreSpotlightActionSymbolImage
11 | pencil
12 | CoreSpotlightActionTitle
13 | Test Me
14 |
15 |
16 | ITSAppUsesNonExemptEncryption
17 |
18 | NSUserActivityTypes
19 |
20 | com.swiftheroes.speakers
21 |
22 | com.apple.security.app-sandbox
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/Brand Assets.brandassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "assets" : [
3 | {
4 | "filename" : "App Icon - App Store.imagestack",
5 | "idiom" : "tv",
6 | "role" : "primary-app-icon",
7 | "size" : "1280x768"
8 | },
9 | {
10 | "filename" : "App Icon.imagestack",
11 | "idiom" : "tv",
12 | "role" : "primary-app-icon",
13 | "size" : "400x240"
14 | },
15 | {
16 | "filename" : "Top Shelf Image Wide.imageset",
17 | "idiom" : "tv",
18 | "role" : "top-shelf-image-wide",
19 | "size" : "2320x720"
20 | },
21 | {
22 | "filename" : "Top Shelf Image.imageset",
23 | "idiom" : "tv",
24 | "role" : "top-shelf-image",
25 | "size" : "1920x720"
26 | }
27 | ],
28 | "info" : {
29 | "author" : "xcode",
30 | "version" : 1
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroiOS/Views/BackgroundView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BackgroundView 2.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/14/24.
6 | //
7 |
8 | import SwiftUI
9 | import HeroShared
10 |
11 | public struct BackgroundView: View {
12 | public init() {}
13 | public var body: some View {
14 | ZStack {
15 | LinearGradient(gradient: Gradient(colors: [.heroOrange,.heroBlue ]), startPoint: .top, endPoint: .bottom)
16 |
17 | VStack {
18 | Image.logo
19 | .cornerRadius(15.0)
20 |
21 | Image.wordLogo
22 | .resizable()
23 | .frame(width: 300, height: 150)
24 | }
25 | }
26 | .ignoresSafeArea()
27 | }
28 | }
29 |
30 | #Preview {
31 | BackgroundView()
32 | }
33 |
--------------------------------------------------------------------------------
/Share/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSExtension
6 |
7 | NSExtensionAttributes
8 |
9 | NSExtensionActivationRule
10 |
11 | NSExtensionActivationDictionaryVersion
12 | 2
13 | NSExtensionActivationSupportsAttachmentsWithMaxCount
14 | 1
15 | NSExtensionActivationSupportsImageWithMaxCount
16 |
17 | 1
18 |
19 |
20 | NSExtensionPointIdentifier
21 | com.apple.share-services
22 | NSExtensionPrincipalClass
23 | $(PRODUCT_MODULE_NAME).ShareViewController
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroiOS/Resources/Localizable.xcstrings:
--------------------------------------------------------------------------------
1 | {
2 | "sourceLanguage" : "en",
3 | "strings" : {
4 | "" : {
5 |
6 | },
7 | "👓" : {
8 |
9 | },
10 | "Bad Image" : {
11 |
12 | },
13 | "Extensions" : {
14 |
15 | },
16 | "Found Image" : {
17 |
18 | },
19 | "Half screen content here" : {
20 |
21 | },
22 | "Nothing selected" : {
23 |
24 | },
25 | "Post as Image" : {
26 |
27 | },
28 | "Speakers" : {
29 |
30 | },
31 | "Swift Heroes" : {
32 | "localizations" : {
33 | "en" : {
34 | "stringUnit" : {
35 | "state" : "translated",
36 | "value" : "Swift Heroes"
37 | }
38 | },
39 | "it" : {
40 | "stringUnit" : {
41 | "state" : "translated",
42 | "value" : "Eroi rapidi"
43 | }
44 | }
45 | }
46 | }
47 | },
48 | "version" : "1.0"
49 | }
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/heroBlue.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "display-p3",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.400",
9 | "green" : "0.215",
10 | "red" : "0.080"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "display-p3",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0.400",
27 | "green" : "0.215",
28 | "red" : "0.080"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Resources/Assets.xcassets/heroOrange.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "display-p3",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.306",
9 | "green" : "0.428",
10 | "red" : "0.929"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "display-p3",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0.306",
27 | "green" : "0.427",
28 | "red" : "0.925"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroiOS/AppDelegate+QuickActions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate+QuickActions.swift
3 | // Demo
4 | //
5 | // Created by Vince Davis on 4/10/24.
6 | //
7 |
8 | import Foundation
9 |
10 | #if os(iOS)
11 | import UIKit
12 |
13 | public extension AppDelegate {
14 | public func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
15 |
16 | if let shortcutItem = options.shortcutItem {
17 | print("App delegate quick action")
18 |
19 | QuickActionsManager.shared.handleQaItem(type: shortcutItem.type)
20 |
21 | }
22 |
23 |
24 | let sceneConfiguration = UISceneConfiguration(name: "Custom Configuration", sessionRole: connectingSceneSession.role)
25 | sceneConfiguration.delegateClass = SceneDelegate.self
26 |
27 | return sceneConfiguration
28 | }
29 | }
30 | #endif
31 |
--------------------------------------------------------------------------------
/Demo.xcodeproj/xcuserdata/u380112.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
9 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Notification/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSExtension
6 |
7 | NSExtensionAttributes
8 |
9 | UNNotificationExtensionCategory
10 |
11 | images
12 | flightStatus
13 | video
14 | default
15 |
16 | UNNotificationExtensionDefaultContentHidden
17 |
18 | UNNotificationExtensionInitialContentSizeRatio
19 | 0.25
20 | UNNotificationExtensionUserInteractionEnabled
21 |
22 |
23 | NSExtensionPointIdentifier
24 | com.apple.usernotifications.content-extension
25 | NSExtensionPrincipalClass
26 | $(PRODUCT_MODULE_NAME).NotificationViewController
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Notification/NotificationViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotificationViewController.swift
3 | // Notification
4 | //
5 | // Created by Vince Davis on 4/7/24.
6 | //
7 |
8 | import HeroiOS
9 | import HeroShared
10 | import SwiftUI
11 |
12 | #if os(macOS)
13 | import AppKit
14 |
15 | class NotificationViewController: NSViewController {
16 |
17 | var viewModel: NotificationModel = .init()
18 |
19 | override func viewDidLoad() {
20 | super.viewDidLoad()
21 | preferredContentSize = CGSize(width: 320, height: 300)
22 | self.add(swiftUIView: AnyView(NotificationView(viewModel: viewModel)))
23 | }
24 | }
25 | #endif
26 |
27 | #if os(iOS) || os(visionOS)
28 | import UIKit
29 |
30 | class NotificationViewController: UIViewController {
31 | var viewModel: NotificationModel = .init()
32 |
33 | override func viewDidLoad() {
34 | super.viewDidLoad()
35 | preferredContentSize = CGSize(width: 320, height: 300)
36 | self.add(swiftUIView: AnyView(NotificationView(viewModel: viewModel)))
37 | }
38 | }
39 | #endif
40 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Swift Heroes Demo App
2 |
3 | This is from my talk "Don't forget about me!" at Swift Heroes '24
4 |
5 |
6 | Share & Action Extensions
7 | https://medium.com/@henribredtprivat/create-an-ios-share-extension-with-custom-ui-in-swift-and-swiftui-2023-6cf069dc1209
8 | https://medium.com/@cmoulinet/ios-share-extension-custom-rules-to-limit-type-or-numbers-of-medias-selected-91ab596d505
9 |
10 | Spotlight & Handoff
11 | https://www.hackingwithswift.com/quick-start/swiftui/how-to-continue-an-nsuseractivity-in-swiftui
12 | https://swiftui-lab.com/nsuseractivity-with-swiftui/
13 | https://betterprogramming.pub/implement-core-spotlight-in-a-swiftui-app-859cb703f55d
14 |
15 | AppClips
16 | https://developer.apple.com/documentation/app_clips/creating_an_app_clip_with_xcode
17 |
18 | Quick Actions
19 | https://medium.com/appcent/add-quick-actions-to-swiftui-app-4498df911b93
20 |
21 | Message * Outdated for Views but other content is good.
22 | https://www.oreilly.com/library/view/ios-10-swift/9781491966426/ch01.html
23 |
24 | External Screen
25 | https://useyourloaf.com/blog/swiftui-supporting-external-screens/
26 |
27 | Notifications
28 | https://www.avanderlee.com/swift/rich-notifications/
29 |
30 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroiOS/ExternalScreens/ExternalScreenToolBar.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/13/24.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct ExternalScreenToolBar: ToolbarContent {
11 | var screenManager: ScreenManager
12 | @Binding var showingSheet: Bool
13 |
14 | var body: some ToolbarContent {
15 | #if os(iOS)
16 | ToolbarItem(placement: .topBarLeading) {
17 | Text("👓")
18 | .font(.largeTitle)
19 | }
20 | ToolbarItem(placement: .topBarTrailing) {
21 | if screenManager.showScreen {
22 | Button(action: {
23 | showingSheet = true
24 | }, label: {
25 | Image(systemName: "airplayvideo")
26 | .font(.title3)
27 | .symbolRenderingMode(.palette)
28 | .foregroundStyle(.black, .blue)
29 | .symbolEffect(.pulse.byLayer, isActive: true)
30 | })
31 | }
32 | }
33 | #else
34 | ToolbarItem(placement: .automatic) {
35 | Text("")
36 | .font(.largeTitle)
37 | }
38 | #endif
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Action/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSExtension
6 |
7 | NSExtensionAttributes
8 |
9 | NSExtensionActivationRule
10 |
11 | NSExtensionActivationDictionaryVersion
12 | 2
13 | NSExtensionActivationSupportsAttachmentsWithMaxCount
14 | 1
15 | NSExtensionActivationSupportsImageWithMaxCount
16 |
17 | 1
18 |
19 | NSExtensionServiceAllowsFinderPreviewItem
20 |
21 | NSExtensionServiceAllowsTouchBarItem
22 |
23 | NSExtensionServiceFinderPreviewIconName
24 | NSActionTemplate
25 | NSExtensionServiceTouchBarBezelColorName
26 | TouchBarBezel
27 | NSExtensionServiceTouchBarIconName
28 | NSActionTemplate
29 |
30 | NSExtensionPointIdentifier
31 | com.apple.ui-services
32 | NSExtensionPrincipalClass
33 | $(PRODUCT_MODULE_NAME).ActionViewController
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroiOS/Modifiers/ForegroundViewModifier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/8/24.
6 | //
7 |
8 | import SwiftUI
9 | import Combine
10 |
11 | #if os(iOS)
12 | import UIKit
13 | #endif
14 |
15 | struct ForegroundViewModifier: ViewModifier where ScreenContent: View {
16 | @Binding var inBackground: Bool
17 | let screenContent: () -> ScreenContent
18 |
19 | #if os(iOS)
20 | @Environment(\.scenePhase) var scenePhase
21 |
22 | func body(content: Content) -> some View {
23 | content
24 | .onChange(of: scenePhase) { _, newPhase in
25 | if newPhase == .inactive {
26 | print("Inactive")
27 | inBackground = true
28 | } else if newPhase == .active {
29 | print("Active")
30 | inBackground = false
31 | } else if newPhase == .background {
32 | print("Background")
33 | inBackground = true
34 | }
35 | }
36 | .fullScreenCover(isPresented: $inBackground, content: {
37 | screenContent()
38 | })
39 | .transaction({ transaction in
40 | transaction.disablesAnimations = true
41 | })
42 | }
43 | #else
44 | func body(content: Content) -> some View {
45 | content
46 | }
47 | #endif
48 | }
49 |
--------------------------------------------------------------------------------
/Heroes/Tests/MacroTests/MacroTests.swift:
--------------------------------------------------------------------------------
1 | import SwiftSyntax
2 | import SwiftSyntaxBuilder
3 | import SwiftSyntaxMacros
4 | import SwiftSyntaxMacrosTestSupport
5 | import XCTest
6 |
7 | // Macro implementations build for the host, so the corresponding module is not available when cross-compiling. Cross-compiled tests may still make use of the macro itself in end-to-end tests.
8 | #if canImport(MacroMacros)
9 | import MacroMacros
10 |
11 |
12 | #endif
13 |
14 | final class MacroTests: XCTestCase {
15 | // func testMacro() throws {
16 | // #if canImport(MyMacroMacros)
17 | // assertMacroExpansion(
18 | // """
19 | // #stringify(a + b)
20 | // """,
21 | // expandedSource: """
22 | // (a + b, "a + b")
23 | // """,
24 | // macros: testMacros
25 | // )
26 | // #else
27 | // throw XCTSkip("macros are only supported when running tests for the host platform")
28 | // #endif
29 | // }
30 | //
31 | // func testMacroWithStringLiteral() throws {
32 | // #if canImport(MyMacroMacros)
33 | // assertMacroExpansion(
34 | // #"""
35 | // #stringify("Hello, \(name)")
36 | // """#,
37 | // expandedSource: #"""
38 | // ("Hello, \(name)", #""Hello, \(name)""#)
39 | // """#,
40 | // macros: testMacros
41 | // )
42 | // #else
43 | // throw XCTSkip("macros are only supported when running tests for the host platform")
44 | // #endif
45 | // }
46 | }
47 |
--------------------------------------------------------------------------------
/Preview/PreviewViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PreviewViewController.swift
3 | // Preview
4 | //
5 | // Created by Vince Davis on 4/15/24.
6 | //
7 |
8 | import UIKit
9 | import QuickLook
10 | import HeroiOS
11 | import SwiftUI
12 |
13 | class PreviewViewController: UIViewController, QLPreviewingController {
14 |
15 | override func viewDidLoad() {
16 | super.viewDidLoad()
17 | // Do any additional setup after loading the view.
18 | }
19 |
20 | func preparePreviewOfSearchableItem(identifier: String, queryString: String?, completionHandler handler: @escaping (Error?) -> Void) {
21 | // Perform any setup necessary in order to prepare the view.
22 |
23 | // Call the completion handler so Quick Look knows that the preview is fully loaded.
24 | // Quick Look will display a loading spinner while the completion handler is not called.
25 | self.add(swiftUIView: AnyView(PreviewItemView(identifier: identifier)))
26 | handler(nil)
27 | }
28 |
29 |
30 | func preparePreviewOfFile(at url: URL, completionHandler handler: @escaping (Error?) -> Void) {
31 | // Add the supported content types to the QLSupportedContentTypes array in the Info.plist of the extension.
32 |
33 | // Perform any setup necessary in order to prepare the view.
34 |
35 | // Call the completion handler so Quick Look knows that the preview is fully loaded.
36 | // Quick Look will display a loading spinner while the completion handler is not called.
37 | handler(nil)
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroiOS/QuickActions/QuickActionsManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/10/24.
6 | //
7 |
8 | import Foundation
9 | import Observation
10 |
11 | #if os(iOS)
12 | import UIKit
13 | #endif
14 |
15 | @Observable
16 | public class QuickActionsManager {
17 | public static let shared = QuickActionsManager()
18 | public init() {}
19 |
20 | public var quickAction: QuickAction? = nil
21 |
22 | public func handleQaItem(type: String) {
23 | if type == "share" {
24 | quickAction = .share
25 | } else if type == "alberto" {
26 | quickAction = .alberto
27 | }
28 | }
29 |
30 | public func addQuickActions() {
31 | #if os(iOS)
32 | UIApplication.shared.shortcutItems = [
33 | UIApplicationShortcutItem(type: "share",
34 | localizedTitle: "Show Share",
35 | localizedSubtitle: "Show Share for Extensions",
36 | icon: UIApplicationShortcutIcon.init(systemImageName: "square.and.arrow.up")),
37 | UIApplicationShortcutItem(type: "alberto",
38 | localizedTitle: "Show Alberto",
39 | localizedSubtitle: "Show Speaker Profile for Alberto",
40 | icon: UIApplicationShortcutIcon.init(systemImageName: "music.mic")),
41 | ]
42 | #endif
43 | }
44 | }
45 |
46 | public enum QuickAction: String, Hashable {
47 | case share
48 | case alberto
49 | }
50 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroiOS/ExternalScreens/ExternalScreenView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/8/24.
6 | //
7 |
8 | import Foundation
9 | import SwiftUI
10 | import HeroShared
11 |
12 | public struct ExternalScreenView: View {
13 | public init() {}
14 |
15 | @Environment(ScreenManager.self)
16 | public var screenManager: ScreenManager
17 |
18 | @State var speaker: Speaker = .alex
19 |
20 | public var body: some View {
21 | ZStack {
22 | LinearGradient(gradient: Gradient(colors: [.heroOrange, .heroBlue]), startPoint: .top, endPoint: .bottom)
23 |
24 | VStack {
25 | HStack {
26 | Image.logo
27 | .resizable()
28 | .frame(width: 75, height: 75)
29 | .cornerRadius(10.0)
30 |
31 | Image.wordLogo
32 | .resizable()
33 | .frame(width: 300, height: 100)
34 | }
35 | .padding()
36 |
37 | speaker.image
38 | .resizable()
39 | .frame(width: 290, height: 290)
40 | .cornerRadius(15.0)
41 |
42 | Text(speaker.name)
43 | .font(.largeTitle)
44 | .bold()
45 |
46 | Spacer()
47 | }
48 | }
49 | .ignoresSafeArea()
50 | .onChange(of: screenManager.speaker) { _, newValue in
51 | speaker = newValue
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroiOS/Extensions/UIViewController+Extensions.swift:
--------------------------------------------------------------------------------
1 |
2 | import SwiftUI
3 |
4 | #if os(iOS) || os(visionOS)
5 | import UIKit
6 | public extension UIViewController {
7 | func add(swiftUIView: AnyView) {
8 | let childView = UIHostingController(rootView: AnyView(swiftUIView))
9 | addChild(childView)
10 | view.addSubview(childView.view)
11 | childView.didMove(toParent: self)
12 |
13 | childView.view.translatesAutoresizingMaskIntoConstraints = false
14 | childView.view.heightAnchor.constraint(equalTo: self.view.heightAnchor).isActive = true
15 | childView.view.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
16 | childView.view.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
17 | childView.view.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
18 | }
19 | }
20 | #elseif os(macOS)
21 | import AppKit
22 | public extension NSViewController {
23 | func add(swiftUIView: AnyView) {
24 | let childView = NSHostingController(rootView: AnyView(swiftUIView))
25 | addChild(childView)
26 | view.addSubview(childView.view)
27 |
28 | childView.view.translatesAutoresizingMaskIntoConstraints = false
29 | childView.view.heightAnchor.constraint(equalTo: self.view.heightAnchor).isActive = true
30 | childView.view.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
31 | childView.view.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
32 | childView.view.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
33 | }
34 | }
35 | #endif
36 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroiOS/Views/PreviewItemView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PreviewItemView.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/15/24.
6 | //
7 |
8 | import SwiftUI
9 | import HeroShared
10 |
11 | public struct PreviewItemView: View {
12 | public var identifier: String
13 | public init(identifier: String) {
14 | self.identifier = identifier
15 | }
16 |
17 | public var body: some View {
18 | if let speaker = Speaker.all.filter({ $0.id == identifier }).first {
19 | ZStack {
20 | LinearGradient(gradient: Gradient(colors: [.heroOrange, .heroBlue]), startPoint: .top, endPoint: .bottom)
21 |
22 | VStack {
23 | HStack {
24 | Image.logo
25 | .resizable()
26 | .frame(width: 100, height: 100)
27 | .cornerRadius(15.0)
28 |
29 | Image.wordLogo
30 | .resizable()
31 | .frame(height: 150)
32 | }
33 | .padding()
34 |
35 | speaker.image
36 | .resizable()
37 | .frame(width: 300, height: 300)
38 | .cornerRadius(15.0)
39 |
40 | Text(speaker.name)
41 | .font(.largeTitle)
42 | .bold()
43 | }
44 | }
45 | .ignoresSafeArea()
46 | }
47 | }
48 | }
49 |
50 | #Preview {
51 | PreviewItemView(identifier: "1")
52 | }
53 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroiOS/Extensions/View+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/8/24.
6 | //
7 |
8 | import Foundation
9 | import SwiftUI
10 | import HeroShared
11 |
12 | public extension View {
13 | func externalScreen(_ showingExternalScreen: Binding, screenContent: @escaping () -> ScreenContent) -> some View where ScreenContent: View {
14 | modifier(ExternalScreenViewModifier(showingExternalScreen: showingExternalScreen, screenContent: screenContent))
15 | }
16 |
17 | func backgroundScreen(_ inBackground: Binding, screenContent: @escaping () -> ScreenContent) -> some View where ScreenContent: View {
18 | modifier(ForegroundViewModifier(inBackground: inBackground, screenContent: screenContent))
19 | }
20 |
21 | func externalScreenToolbar(screenManager: ScreenManager, showingSheet: Binding) -> some View {
22 | return self.modifier(ExternalScreenToolBarModifier(screenManager: screenManager, showingSheet: showingSheet))
23 | }
24 |
25 | @ViewBuilder
26 | func ifOS(_ operatingSystems: OperatingSystem...,modifier: (Self) -> Content) -> some View {
27 | if operatingSystems.contains(OperatingSystem.current) {
28 | modifier(self)
29 | } else {
30 | self
31 | }
32 | }
33 |
34 | func modify(@ViewBuilder modifier: (Self) -> T) -> T {
35 | modifier(self)
36 | }
37 |
38 | func customToolBarStyle() -> some View {
39 | self
40 | #if os(iOS)
41 | .toolbarBackground(Color.heroOrange.gradient, for: .navigationBar)
42 | .toolbarBackground(.visible, for: .navigationBar)
43 | #endif
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Heroes/Sources/MacroMacros/NavigationTitleMacro.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NavigationTitleMacro.swift
3 | // Heroes
4 | //
5 | // Created by Vince Davis on 9/5/24.
6 | //
7 |
8 | import SwiftCompilerPlugin
9 | import SwiftSyntax
10 | import SwiftSyntaxBuilder
11 | import SwiftSyntaxMacros
12 |
13 | public struct NavigationTitleMacro: MemberMacro {
14 | public static func expansion(
15 | of node: AttributeSyntax,
16 | providingMembersOf declaration: some DeclGroupSyntax,
17 | in context: some MacroExpansionContext
18 | ) throws -> [DeclSyntax] {
19 | guard let argument = node.arguments?.as(LabeledExprListSyntax.self)?.first?.expression,
20 | let stringLiteral = argument.as(StringLiteralExprSyntax.self)?.segments.first?.as(StringSegmentSyntax.self)?.content else {
21 | throw MacroError.invalidArgument
22 | }
23 |
24 | let titleValue = stringLiteral.text
25 |
26 | let newBodyCode = """
27 | var body: some View {
28 | NavigationView {
29 | VStack {
30 | Text("Name")
31 | }
32 | .navigationTitle("\(titleValue)")
33 | }
34 | }
35 | """
36 |
37 | return [DeclSyntax(stringLiteral: newBodyCode)]
38 | }
39 | }
40 |
41 | public enum MacroError: Error, CustomStringConvertible {
42 | case invalidArgument
43 |
44 | public var description: String {
45 | switch self {
46 | case .invalidArgument:
47 | return "The NavigationTitle macro requires a string literal argument."
48 | }
49 | }
50 | }
51 |
52 | @main
53 | struct MacrosPlugin: CompilerPlugin {
54 | let providingMacros: [Macro.Type] = [
55 | NavigationTitleMacro.self
56 | // Add more macros here
57 | ]
58 | }
59 |
--------------------------------------------------------------------------------
/Demo.xcodeproj/xcuserdata/vince.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Action.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 | AppClips.xcscheme_^#shared#^_
13 |
14 | orderHint
15 | 7
16 |
17 | Demo.xcscheme_^#shared#^_
18 |
19 | orderHint
20 | 1
21 |
22 | HeroesWatch Watch App.xcscheme_^#shared#^_
23 |
24 | orderHint
25 | 8
26 |
27 | My Cool Extension.xcscheme_^#shared#^_
28 |
29 | orderHint
30 | 12
31 |
32 | NewExtension.xcscheme_^#shared#^_
33 |
34 | orderHint
35 | 13
36 |
37 | Notification.xcscheme_^#shared#^_
38 |
39 | orderHint
40 | 3
41 |
42 | NotificationService.xcscheme_^#shared#^_
43 |
44 | orderHint
45 | 4
46 |
47 | Preview.xcscheme_^#shared#^_
48 |
49 | orderHint
50 | 10
51 |
52 | Share.xcscheme_^#shared#^_
53 |
54 | orderHint
55 | 5
56 |
57 | Spotlight.xcscheme_^#shared#^_
58 |
59 | orderHint
60 | 6
61 |
62 | iMessage.xcscheme_^#shared#^_
63 |
64 | orderHint
65 | 2
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/Demo/DemoApp.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DemoApp.swift
3 | // Demo
4 | //
5 | // Created by Vince Davis on 4/7/24.
6 | //
7 |
8 | import SwiftUI
9 | import UserNotifications
10 | import CoreSpotlight
11 | import Observation
12 | import HeroiOS
13 | import HeroShared
14 | import Macros
15 |
16 | @main
17 | struct DemoApp: App {
18 | #if !os(tvOS) && !os(macOS)
19 | @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
20 | #endif
21 | @Environment(\.scenePhase) var scenePhase
22 |
23 | @State var inBackground: Bool = false
24 |
25 | init() {
26 | print("Main first")
27 | }
28 |
29 | var body: some Scene {
30 | WindowGroup {
31 | if #available(iOS 17.0, *) {
32 | if inBackground {
33 | BackgroundView()
34 | } else {
35 | //MainView()
36 | UserProfileView()
37 | }
38 | } else if #available(macOS 14.0, *) {
39 | MainView()
40 | } else if #available(tvOS 17.0, *) {
41 | if inBackground {
42 | BackgroundView()
43 | } else {
44 | MainView()
45 | }
46 | } else if #available(visionOS 1.0, *){
47 | MainView()
48 | } else {
49 | MainView()
50 | }
51 | }
52 | .onChange(of: scenePhase) { _, newPhase in
53 | switch newPhase {
54 | case .background:
55 | inBackground = true
56 | if #available(iOS 17.0, *) {
57 | QuickActionsManager.shared.addQuickActions()
58 | }
59 | case .inactive:
60 | inBackground = true
61 | case .active:
62 | inBackground = false
63 | @unknown default:
64 | inBackground = false
65 | }
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/Heroes/Sources/MacroMacros/DebugPrintMacro.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DebugPrintMacro.swift
3 | // Heroes
4 | //
5 | // Created by Vince Davis on 9/5/24.
6 | //
7 |
8 | //import SwiftCompilerPlugin
9 | //import SwiftSyntax
10 | //import SwiftSyntaxBuilder
11 | //import SwiftSyntaxMacros
12 | //
13 | //public struct DebugPrintMacro: MemberMacro {
14 | // public static func expansion(
15 | // of node: AttributeSyntax,
16 | // providingMembersOf declaration: some DeclGroupSyntax,
17 | // in context: some MacroExpansionContext
18 | // ) throws -> [DeclSyntax] {
19 | // guard let structDecl = declaration.as(StructDeclSyntax.self) else {
20 | // throw MacroError.notAStruct
21 | // }
22 | //
23 | // let properties = node.arguments?.as(LabeledExprListSyntax.self)?.map { $0.expression.description } ?? []
24 | //
25 | // let propertyChecks = properties.map { property in
26 | // """
27 | // if !properties.contains("\(property)") {
28 | // fatalError("Property '\(property)' is not defined in the view.")
29 | // }
30 | // """
31 | // }.joined(separator: "\n")
32 | //
33 | // let propertyPrints = properties.map { property in
34 | // "print(\"\\($0): \\(String(describing: self.\(property)))\")"
35 | // }.joined(separator: "\n ")
36 | //
37 | // let modifierCode = """
38 | // func debugPrintModifier() -> some View {
39 | // let properties = Set(Mirror(reflecting: self).children.compactMap { $0.label })
40 | // \(propertyChecks)
41 | // return self.modifier(DebugPrintModifier(action: {
42 | // print("Debug Print for \\(String(describing: Self.self)):")
43 | // \(propertyPrints)
44 | // }))
45 | // }
46 | // """
47 | //
48 | // return [DeclSyntax(stringLiteral: modifierCode)]
49 | // }
50 | //}
51 | //
52 | //public enum MacroError: Error {
53 | // case notAStruct
54 | //}
55 |
--------------------------------------------------------------------------------
/Notification/NotificationViewController+UserNotifications.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotificationViewController+UserNotifications.swift
3 | // Notification
4 | //
5 | // Created by Vince Davis on 4/13/24.
6 | //
7 |
8 | #if canImport(UserNotifications)
9 | import UserNotifications
10 | import UserNotificationsUI
11 |
12 | extension NotificationViewController: UNNotificationContentExtension {
13 | func didReceive(_ notification: UNNotification) {
14 | let cat = notification.request.content.categoryIdentifier
15 |
16 | viewModel.catergory = cat
17 | }
18 |
19 | func didReceive(_ response: UNNotificationResponse, completionHandler completion: @escaping (UNNotificationContentExtensionResponseOption) -> Void) {
20 | if response.actionIdentifier == "testNotification.changeAction" {
21 | //self.scrollNextItem()
22 | viewModel.changeRating()
23 | completion(UNNotificationContentExtensionResponseOption.doNotDismiss)
24 | } else if response.actionIdentifier == "testNotification.playAction" {
25 | //self.scrollPreviousItem()
26 | viewModel.play()
27 | completion(UNNotificationContentExtensionResponseOption.doNotDismiss)
28 | } else if response.actionIdentifier == "testNotification.slideAction" {
29 | //self.scrollPreviousItem()
30 | viewModel.slide()
31 | completion(UNNotificationContentExtensionResponseOption.doNotDismiss)
32 | } else if response.actionIdentifier == "testNotification.pauseAction" {
33 | //self.scrollPreviousItem()
34 | viewModel.pause()
35 | completion(UNNotificationContentExtensionResponseOption.doNotDismiss)
36 | } else if response.actionIdentifier == "testNotification.submitAction" {
37 | //self.scrollPreviousItem()
38 | completion(UNNotificationContentExtensionResponseOption.dismiss)
39 | } else {
40 | //completion(UNNotificationContentExtensionResponseOption.dismissAndForwardAction)
41 | completion(UNNotificationContentExtensionResponseOption.doNotDismiss)
42 | }
43 | }
44 | }
45 | #endif
46 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroiOS/AppDelegate+Notifications.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate+Notifications.swift
3 | // Demo
4 | //
5 | // Created by Vince Davis on 4/10/24.
6 | //
7 |
8 | import Foundation
9 |
10 | #if os(iOS) || os(visionOS) || os(macOS)
11 | import UserNotifications
12 |
13 | public extension AppDelegate {
14 | public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
15 | let userInfo = notification.request.content.userInfo
16 | print("Receive notification in the foreground \(userInfo)")
17 | let pref = UserDefaults.init(suiteName: "group.id.gits.notifserviceextension")
18 | pref?.set(userInfo, forKey: "NOTIF_DATA")
19 | //guard let vc = UIApplication.shared.windows.first?.rootViewController as? ViewController else { return }
20 | //vc.handleNotifData()
21 | completionHandler([.alert, .badge, .sound])
22 | }
23 |
24 | public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
25 | let userInfo = response.notification.request.content.userInfo
26 | //if let customData = userInfo["customData"] as? String {
27 | //print("Custom data received: \(customData)")
28 |
29 | switch response.actionIdentifier {
30 | case UNNotificationDefaultActionIdentifier:
31 | // the user swiped to unlock
32 | print("Default identifier")
33 | case "testNotification.doneAction":
34 | // the user tapped our "show more info…" button
35 | print("Done more information…")
36 | case "testNotification.openAction":
37 | // the user tapped our "show more info…" button
38 | print("Open more information…")
39 | default:
40 | break
41 | }
42 | // }
43 | completionHandler()
44 | }
45 | }
46 | #endif
47 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Data/ListItem.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListItem.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/14/24.
6 | //
7 |
8 | import Foundation
9 | import SwiftUI
10 |
11 | public struct ListItem: Identifiable, Hashable, Listable {
12 | public init(id: String, title: String, subtitle: String, image: Image, badges: [String], type: ListType, items: [ListItem]? = nil) {
13 | self.id = id
14 | self.title = title
15 | self.subtitle = subtitle
16 | self.image = image
17 | self.badges = badges
18 | self.type = type
19 | self.items = items
20 | }
21 |
22 | public var id: String
23 | public var title: String
24 | public var subtitle: String
25 | public var image: Image
26 | public var badges: [String]
27 | public var type: ListType
28 | public var items: [ListItem]?
29 |
30 | public func hash(into hasher: inout Hasher) {
31 | return hasher.combine(id)
32 | }
33 |
34 | public static func == (lhs: ListItem, rhs: ListItem) -> Bool {
35 | return lhs.id == rhs.id
36 | }
37 | }
38 |
39 | public extension ListItem {
40 | static let speakers = ListItem(id: "1000",
41 | title: "Speakers",
42 | subtitle: "Swift Hero Speakers",
43 | image: Image(systemName: "person.3.fill"),
44 | badges: [],
45 | type: .sectionHeader,
46 | items: Speaker.all.map({ ListItem(id : $0.id, title: $0.title, subtitle: $0.subtitle, image: $0.image, badges: [], type: .speaker) }))
47 |
48 | static let extensions = ListItem(id: "2000",
49 | title: "Extensions",
50 | subtitle: "Extensions covered in Talk",
51 | image: Image(systemName: "puzzlepiece.extension.fill"),
52 | badges: [],
53 | type: .sectionHeader,
54 | items: ExtensionItem.all.map({ ListItem(id : $0.id, title: $0.title, subtitle: $0.subtitle, image: $0.image, badges: $0.platforms, type: .extensionItem) }))
55 | }
56 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroiOS/Modifiers/ExternalScreenViewModifier.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 | import Combine
3 | #if os(iOS)
4 | import UIKit
5 | #endif
6 |
7 | public struct ExternalScreenViewModifier: ViewModifier where ScreenContent: View {
8 | @Binding var showingExternalScreen: Bool
9 | let screenContent: () -> ScreenContent
10 |
11 | #if os(iOS)
12 | @State var additionalWindows: [UIWindow] = []
13 |
14 | public func body(content: Content) -> some View {
15 | content
16 | .onReceive(
17 | screenDidConnectPublisher,
18 | perform: screenDidConnect
19 | )
20 | .onReceive(
21 | screenDidDisconnectPublisher,
22 | perform: screenDidDisconnect
23 | )
24 | }
25 |
26 | private var screenDidConnectPublisher: AnyPublisher {
27 | NotificationCenter.default
28 | .publisher(for: UIScreen.didConnectNotification)
29 | .compactMap { $0.object as? UIScreen }
30 | .receive(on: RunLoop.main)
31 | .eraseToAnyPublisher()
32 | }
33 |
34 | private var screenDidDisconnectPublisher: AnyPublisher {
35 | NotificationCenter.default
36 | .publisher(for: UIScreen.didDisconnectNotification)
37 | .compactMap { $0.object as? UIScreen }
38 | .receive(on: RunLoop.main)
39 | .eraseToAnyPublisher()
40 | }
41 |
42 | private func screenDidConnect(_ screen: UIScreen) {
43 | let window = UIWindow(frame: screen.bounds)
44 |
45 | window.windowScene = UIApplication.shared.connectedScenes
46 | .first { ($0 as? UIWindowScene)?.screen == screen }
47 | as? UIWindowScene
48 |
49 | let controller = UIHostingController(rootView: screenContent())
50 | window.rootViewController = controller
51 | window.isHidden = false
52 | additionalWindows.append(window)
53 | showingExternalScreen = true
54 | }
55 |
56 | private func screenDidDisconnect(_ screen: UIScreen) {
57 | additionalWindows.removeAll { $0.screen == screen }
58 | showingExternalScreen = false
59 | }
60 | #else
61 | public func body(content: Content) -> some View {
62 | content
63 | }
64 | #endif
65 | }
66 |
--------------------------------------------------------------------------------
/Heroes/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version: 5.10
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 | import CompilerPluginSupport
6 |
7 | let package = Package(
8 | name: "Heroes",
9 | defaultLocalization: "en",
10 | platforms: [.macOS(.v12), .iOS(.v17), .watchOS(.v10), .visionOS(.v1)],
11 | products: [
12 | // Products define the executables and libraries a package produces, making them visible to other packages.
13 | .library(
14 | name: "HeroShared",
15 | targets: ["HeroShared"]),
16 | .library(
17 | name: "HeroiOS",
18 | targets: ["HeroiOS"]),
19 | .library(
20 | name: "Macros",
21 | targets: ["Macros"]
22 | ),
23 | .executable(
24 | name: "MacroClient",
25 | targets: ["MacroClient"]
26 | ),
27 | ],
28 | dependencies: [
29 | .package(url: "https://github.com/swiftlang/swift-syntax.git", from: "509.0.0"),
30 | ],
31 | targets: [
32 | // Targets are the basic building blocks of a package, defining a module or a test suite.
33 | // Targets can depend on other targets in this package and products from dependencies.
34 | .target(
35 | name: "HeroShared"),
36 | .testTarget(
37 | name: "HeroSharedTests",
38 | dependencies: ["HeroShared"]),
39 | .target(
40 | name: "HeroiOS",
41 | dependencies: ["HeroShared"]),
42 | .testTarget(
43 | name: "HeroiOSTests",
44 | dependencies: ["HeroiOS", "HeroShared"]),
45 | .macro(
46 | name: "MacroMacros",
47 | dependencies: [
48 | .product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
49 | .product(name: "SwiftCompilerPlugin", package: "swift-syntax")
50 | ]
51 | ),
52 | .target(name: "Macros", dependencies: ["MacroMacros"]),
53 | .executableTarget(name: "MacroClient", dependencies: ["Macros"]),
54 | .testTarget(
55 | name: "MacroTests",
56 | dependencies: [
57 | "MacroMacros",
58 | .product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"),
59 | ]
60 | ),
61 | ]
62 | )
63 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroiOS/Views/MessageView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MessageView.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/14/24.
6 | //
7 |
8 | import Foundation
9 | import SwiftUI
10 | import HeroShared
11 |
12 | struct MessageItem: Hashable {
13 | let id: UUID = .init()
14 | let image: Image
15 |
16 | public func hash(into hasher: inout Hasher) {
17 | return hasher.combine(id)
18 | }
19 | }
20 |
21 | public struct MessageView: View {
22 | public init(action: @escaping ((Image, Bool) -> Void)) {
23 | self.action = action
24 | }
25 |
26 | @State var postAsImage: Bool = true
27 |
28 | let items: [MessageItem] = [
29 | .init(image: .logo),
30 | .init(image: .wordLogo),
31 | .init(image: .alex),
32 | .init(image: .alberto),
33 | .init(image: .ios3),
34 | .init(image: .ios4),
35 | .init(image: .ios8),
36 | .init(image: .ios9),
37 | .init(image: .ios10),
38 | .init(image: .ios14)
39 | ]
40 |
41 | public var action: ((Image, Bool) -> Void)
42 | let columns = [
43 | GridItem(.flexible()),
44 | GridItem(.flexible()),
45 | ]
46 |
47 | public var body: some View {
48 | ZStack {
49 | LinearGradient(gradient: Gradient(colors: [.heroOrange,.heroBlue ]), startPoint: .top, endPoint: .bottom)
50 | VStack {
51 | Toggle("Post as Image", isOn: $postAsImage)
52 | .bold()
53 |
54 | ScrollView {
55 | LazyVGrid(columns: columns, spacing: 20) {
56 | ForEach(items, id: \.self) { item in
57 | Button(action: {
58 | action(item.image, postAsImage)
59 | }, label: {
60 | item.image
61 | .resizable()
62 | .frame(width: 150, height: 150)
63 | .aspectRatio(contentMode: .fit)
64 | .cornerRadius(10.0)
65 | })
66 | }
67 | }
68 | }
69 | }
70 | .padding()
71 | }
72 | .ignoresSafeArea()
73 | }
74 | }
75 |
76 | #Preview {
77 | MessageView(action: { _,_ in })
78 | }
79 |
--------------------------------------------------------------------------------
/HeroesWatch Watch App/ContentView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ContentView.swift
3 | // HeroesWatch Watch App
4 | //
5 | // Created by Vince Davis on 4/11/24.
6 | //
7 |
8 | import SwiftUI
9 | import UserNotifications
10 | import HeroShared
11 |
12 | let activityType = "com.swiftheroes.speakers"
13 |
14 | struct ContentView: View {
15 | @State var selectedItem: ListItem? = nil
16 |
17 | @State var items: [ListItem] = Speaker.all.map({ ListItem(id: $0.id, title: $0.title, subtitle: $0.subtitle, image: $0.image, badges: [], type: .speaker, items: nil)})
18 | var body: some View {
19 | NavigationSplitView(sidebar: {
20 | List(items, selection: $selectedItem) { item in
21 | NavigationLink(value: item, label: {
22 | HStack {
23 | item.image.resizable().frame(width: 20, height: 20)
24 | Text(item.title)
25 | }
26 | .containerBackground(Color.heroOrange.gradient, for: .navigation)
27 | })
28 | }
29 | }, detail: {
30 | if let item = selectedItem {
31 | VStack {
32 | item.image.resizable()
33 |
34 | Text(item.title)
35 | }
36 | .containerBackground(Color.heroOrange.gradient, for: .navigation)
37 | .userActivity(activityType, element: item, { element, activity in
38 | let bundleid = Bundle.main.bundleIdentifier ?? ""
39 | activity.addUserInfoEntries(from: ["id": item.id,
40 | "name": item.title,
41 | "setby": bundleid])
42 | //activity.el
43 | logUserActivity(activity, label: "Item")
44 | })
45 | }
46 | })
47 | .task {
48 | let center = UNUserNotificationCenter.current()
49 | _ = try? await center.requestAuthorization(
50 | options: [.alert, .sound, .badge]
51 | )
52 | }
53 |
54 | }
55 |
56 | func logUserActivity(_ activity: NSUserActivity, label: String = "") {
57 | print("\(label) TYPE = \(activity.activityType)")
58 | print("\(label) INFO = \(activity.userInfo ?? [:])")
59 | }
60 | }
61 |
62 | #Preview {
63 | ContentView()
64 | }
65 |
--------------------------------------------------------------------------------
/Demo.xcodeproj/xcuserdata/u380112.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Action.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 2
11 |
12 | AppClips.xcscheme_^#shared#^_
13 |
14 | orderHint
15 | 8
16 |
17 | Demo.xcscheme_^#shared#^_
18 |
19 | orderHint
20 | 6
21 |
22 | HeroesWatch Watch App.xcscheme_^#shared#^_
23 |
24 | orderHint
25 | 9
26 |
27 | Notification.xcscheme_^#shared#^_
28 |
29 | orderHint
30 | 0
31 |
32 | NotificationService.xcscheme_^#shared#^_
33 |
34 | orderHint
35 | 5
36 |
37 | Preview.xcscheme_^#shared#^_
38 |
39 | orderHint
40 | 7
41 |
42 | Share.xcscheme_^#shared#^_
43 |
44 | orderHint
45 | 1
46 |
47 | Spotlight.xcscheme_^#shared#^_
48 |
49 | orderHint
50 | 3
51 |
52 | iMessage.xcscheme_^#shared#^_
53 |
54 | orderHint
55 | 4
56 |
57 |
58 | SuppressBuildableAutocreation
59 |
60 | 4E5F30612BC35E9000356231
61 |
62 | primary
63 |
64 |
65 | 4E5F30772BC35F3000356231
66 |
67 | primary
68 |
69 |
70 | 4E5F308F2BC35FAD00356231
71 |
72 | primary
73 |
74 |
75 | 4E5F30A12BC35FFF00356231
76 |
77 | primary
78 |
79 |
80 | 4E5F30B72BC3602400356231
81 |
82 | primary
83 |
84 |
85 | 4E5F30CD2BC3606300356231
86 |
87 | primary
88 |
89 |
90 | 4E5F30E42BC3659600356231
91 |
92 | primary
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/iMessage/Assets.xcassets/iMessage App Icon.stickersiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "icon-messages-settings-29x29@2x.png",
5 | "idiom" : "iphone",
6 | "scale" : "2x",
7 | "size" : "29x29"
8 | },
9 | {
10 | "filename" : "icon-messages-settings-29x29@3x.png",
11 | "idiom" : "iphone",
12 | "scale" : "3x",
13 | "size" : "29x29"
14 | },
15 | {
16 | "filename" : "icon-messages-app-iPhone-60x45@2x.png",
17 | "idiom" : "iphone",
18 | "scale" : "2x",
19 | "size" : "60x45"
20 | },
21 | {
22 | "filename" : "icon-messages-app-iPhone-60x45@3x.png",
23 | "idiom" : "iphone",
24 | "scale" : "3x",
25 | "size" : "60x45"
26 | },
27 | {
28 | "filename" : "icon-messages-settings-29x29@2x 1.png",
29 | "idiom" : "ipad",
30 | "scale" : "2x",
31 | "size" : "29x29"
32 | },
33 | {
34 | "filename" : "icon-messages-app-iPadAir-67x50@2x.png",
35 | "idiom" : "ipad",
36 | "scale" : "2x",
37 | "size" : "67x50"
38 | },
39 | {
40 | "filename" : "icon-messages-app-iPadAir-74x55@2x.png",
41 | "idiom" : "ipad",
42 | "scale" : "2x",
43 | "size" : "74x55"
44 | },
45 | {
46 | "filename" : "icon-messages-app-store-1024x1024.png",
47 | "idiom" : "ios-marketing",
48 | "scale" : "1x",
49 | "size" : "1024x1024"
50 | },
51 | {
52 | "filename" : "icon-messages-app-27x20@2x.png",
53 | "idiom" : "universal",
54 | "platform" : "ios",
55 | "scale" : "2x",
56 | "size" : "27x20"
57 | },
58 | {
59 | "filename" : "icon-messages-app-27x20@3x.png",
60 | "idiom" : "universal",
61 | "platform" : "ios",
62 | "scale" : "3x",
63 | "size" : "27x20"
64 | },
65 | {
66 | "filename" : "icon-messages-transcript-32x24@2x.png",
67 | "idiom" : "universal",
68 | "platform" : "ios",
69 | "scale" : "2x",
70 | "size" : "32x24"
71 | },
72 | {
73 | "filename" : "icon-messages-transcript-32x24@3x.png",
74 | "idiom" : "universal",
75 | "platform" : "ios",
76 | "scale" : "3x",
77 | "size" : "32x24"
78 | },
79 | {
80 | "filename" : "icon-messages-app-store-1024x768.png",
81 | "idiom" : "ios-marketing",
82 | "platform" : "ios",
83 | "scale" : "1x",
84 | "size" : "1024x768"
85 | }
86 | ],
87 | "info" : {
88 | "author" : "xcode",
89 | "version" : 1
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/Share/ShareViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ShareViewController.swift
3 | // Share
4 | //
5 | // Created by Vince Davis on 4/7/24.
6 | //
7 |
8 | import Social
9 | import SwiftUI
10 | import HeroiOS
11 | import HeroShared
12 |
13 | #if os(iOS)
14 | import UIKit
15 | import MobileCoreServices
16 | import UniformTypeIdentifiers
17 |
18 | class ShareViewController: UIViewController {
19 | override func viewDidLoad() {
20 | super.viewDidLoad()
21 |
22 | var imageFound = false
23 | print("share started")
24 | for item in self.extensionContext!.inputItems as! [NSExtensionItem] {
25 | for provider in item.attachments! {
26 | print("share looping")
27 | if provider.hasItemConformingToTypeIdentifier(UTType.image.identifier) {
28 | // This is an image. We'll load it, then place it in our image view.
29 | provider.loadItem(forTypeIdentifier: UTType.image.identifier, options: nil, completionHandler: { (imageURL, error) in
30 | OperationQueue.main.addOperation {
31 | if let imageURL = imageURL as? URL {
32 | print("share found")
33 | let image = UIImage(data: try! Data(contentsOf: imageURL))
34 | let shareView = ShareView(image: image, action: self.done)
35 | self.add(swiftUIView: AnyView(shareView))
36 | }
37 | }
38 | })
39 |
40 | imageFound = true
41 | break
42 | }
43 | }
44 |
45 | if (imageFound) {
46 | // We only handle one image, so stop looking for more.
47 | print("share donw")
48 | break
49 | }
50 | }
51 | }
52 |
53 | /// Close the Share Extension
54 | func done() {
55 | self.extensionContext?.completeRequest(returningItems: [], completionHandler: nil)
56 | }
57 | }
58 | #endif
59 |
60 | #if os(macOS)
61 | import AppKit
62 |
63 | class ShareViewController: NSViewController {
64 | override func viewDidLoad() {
65 | super.viewDidLoad()
66 |
67 | self.add(swiftUIView: AnyView(SwiftUIView(action: close)))
68 | }
69 |
70 | /// Close the Share Extension
71 | func close() {
72 | self.extensionContext?.completeRequest(returningItems: [], completionHandler: nil)
73 | }
74 | }
75 | #endif
76 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroiOS/ExternalScreens/ExternalScreenControlView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExternalScreenControlView.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/15/24.
6 | //
7 |
8 | import SwiftUI
9 | import Observation
10 |
11 | struct ExternalScreenControlView: View {
12 | @Bindable var viewModel: ScreenManager
13 |
14 | var body: some View {
15 | ZStack {
16 | LinearGradient(gradient: Gradient(colors: [.heroOrange,.heroBlue]), startPoint: .top, endPoint: .bottom)
17 |
18 | HStack {
19 | Button(action: {
20 | viewModel.minus()
21 | }, label: {
22 | Image(systemName: "chevron.left")
23 | .font(.largeTitle)
24 | .foregroundStyle(viewModel.selection == 0 ? .gray : .white)
25 | .bold()
26 | }).disabled(viewModel.selection == 0)
27 |
28 | Spacer()
29 |
30 | speakerTabView
31 |
32 | Spacer()
33 |
34 | Button(action: {
35 | viewModel.add()
36 | }, label: {
37 | Image(systemName: "chevron.right")
38 | .font(.largeTitle)
39 | .foregroundStyle(viewModel.selection == (viewModel.speakers.count - 1) ? .gray : .white)
40 | .bold()
41 | }).disabled(viewModel.selection == (viewModel.speakers.count - 1))
42 | }
43 | .padding()
44 | }
45 | .ignoresSafeArea()
46 | }
47 |
48 | @ViewBuilder
49 | var speakerTabView: some View {
50 | TabView(selection: $viewModel.selection) {
51 | ForEach(0.. Bool {
17 |
18 | print("AppDelegate first")
19 | UNUserNotificationCenter.current().delegate = self
20 | NotificationHelper().setup()
21 | application.registerForRemoteNotifications()
22 |
23 | return true
24 | }
25 |
26 | public func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
27 | let tokenChars = (deviceToken as NSData).bytes.bindMemory(to: CChar.self, capacity: deviceToken.count)
28 | var tokenString = ""
29 | for i in 0.. Void)
16 | public init(image: UIImage? = nil, action: @escaping (() -> Void)) {
17 | self.image = image
18 | self.action = action
19 | }
20 | #elseif os(macOS)
21 | public var image: NSImage?
22 | public var action: (() -> Void)
23 | public init(image: NSImage? = nil, action: @escaping (() -> Void)) {
24 | self.image = image
25 | self.action = action
26 | }
27 | #else
28 | public var image: Image?
29 | public var action: (() -> Void)
30 | public init(image: Image? = nil, action: @escaping (() -> Void)) {
31 | self.image = image
32 | self.action = action
33 | }
34 | #endif
35 |
36 | public var body: some View {
37 | NavigationStack {
38 | ZStack {
39 | LinearGradient(gradient: Gradient(colors: [.heroOrange,.heroBlue ]), startPoint: .top, endPoint: .bottom)
40 |
41 | if let foundImage = image {
42 | #if os(iOS)
43 | let newImage = Image(uiImage: foundImage)
44 | #elseif os(macOS)
45 | let newImage = Image(nsImage: foundImage)
46 | #else
47 | let newImage = foundImage
48 | #endif
49 | VStack {
50 | HStack {
51 | Image.logo
52 | .resizable()
53 | .frame(width: 100, height: 100)
54 | .cornerRadius(15.0)
55 |
56 | Image.wordLogo
57 | .resizable()
58 | .frame(height: 150)
59 | }
60 | .padding()
61 |
62 | newImage.resizable().frame(width: 300, height: 300)
63 | Text("Found Image")
64 | }
65 | } else {
66 | VStack {
67 | Text("Bad Image")
68 | }
69 | }
70 | }
71 | .ignoresSafeArea()
72 | #if os(iOS)
73 | .toolbar {
74 | ToolbarItem(placement: .topBarTrailing, content: {
75 | Button(action: {
76 | action()
77 | }, label: {
78 | Image(systemName: "x.circle.fill")
79 | })
80 | })
81 | }
82 | #endif
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Spotlight/Spotlight.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/13/24.
6 | //
7 |
8 | #if os(iOS) || os(macOS) || os(visionOS)
9 | import UniformTypeIdentifiers
10 | import CoreSpotlight
11 | #endif
12 | #if os(iOS)
13 | import UIKit
14 | #endif
15 |
16 | public struct Spotlight {
17 | @MainActor
18 | static public func indexSpeakers() async -> Bool {
19 | await withCheckedContinuation { continuation in
20 | Spotlight.indexSpeakers(){ success in
21 | continuation.resume(returning: success)
22 | }
23 | }
24 | }
25 |
26 | static public func deIndexSpeakers() async -> Bool {
27 | await withCheckedContinuation { continuation in
28 | Spotlight.deIndexSpeakers(){ success in
29 | continuation.resume(returning: success)
30 | }
31 | }
32 | }
33 |
34 | // static public func handleUserActivity(_ userActivity: NSUserActivity) {
35 | //
36 | // }
37 | }
38 |
39 | private extension Spotlight {
40 | @MainActor
41 | static private func indexSpeakers(completion: @escaping (Bool) -> Void) {
42 | #if os(iOS) || os(macOS) || os(visionOS)
43 |
44 | let items = Speaker.all.map({
45 | let attributeSet = CSSearchableItemAttributeSet(contentType: UTType.text)
46 | attributeSet.title = $0.name
47 | attributeSet.contentDescription = $0.subtitle
48 | #if os(iOS)
49 | if let image = $0.image.getUIImage(newSize: .init(width: 30, height: 30)),
50 | let data = image.jpegData(compressionQuality: 1.0) {
51 | attributeSet.thumbnailData = data
52 | }
53 | attributeSet.actionIdentifiers = ["CS_ACTION_1"]
54 | #endif
55 |
56 | return CSSearchableItem(uniqueIdentifier: $0.id, domainIdentifier: "com.swiftheroes", attributeSet: attributeSet)
57 | })
58 |
59 | CSSearchableIndex.default().indexSearchableItems(items) { error in
60 | if let error = error {
61 | print("Indexing error: \(error.localizedDescription)")
62 | completion(false)
63 | } else {
64 | print("Search item successfully indexed!")
65 | completion(true)
66 | }
67 | }
68 | #endif
69 | }
70 |
71 | static private func deIndexSpeakers(completion: @escaping (Bool) -> Void) {
72 | #if os(iOS) || os(macOS) || os(visionOS)
73 | let identifiers = Speaker.all.map({ $0.id })
74 | CSSearchableIndex.default().deleteSearchableItems(withIdentifiers: identifiers) { error in
75 | if let error = error {
76 | print("Deindexing error: \(error.localizedDescription)")
77 | completion(false)
78 | } else {
79 | print("Search item successfully removed!")
80 | completion(true)
81 | }
82 | }
83 | #endif
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/Demo.xcodeproj/xcshareddata/xcschemes/Demo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
9 |
10 |
16 |
22 |
23 |
24 |
25 |
26 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
62 |
68 |
69 |
70 |
71 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/HeroesWatch Watch App/HeroesWatchApp.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HeroesWatchApp.swift
3 | // HeroesWatch Watch App
4 | //
5 | // Created by Vince Davis on 4/11/24.
6 | //
7 |
8 | import SwiftUI
9 | import HeroShared
10 | import UserNotifications
11 |
12 | import AVKit
13 | import Foundation
14 |
15 | @main
16 | struct HeroesWatch_Watch_AppApp: App {
17 | //@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
18 |
19 | var body: some Scene {
20 | WindowGroup {
21 | ContentView()
22 | }
23 |
24 | WKNotificationScene(controller: NotificationController.self, category: "video")
25 | }
26 | }
27 |
28 | import AVFoundation
29 | struct NotificationView: View {
30 | var speaker: Speaker = .alex
31 | @State var isSwitched: Bool = false
32 | public var player: AVPlayer = AVPlayer(url: Bundle.main.url(forResource: "highlights", withExtension: "mp4")!)
33 |
34 | var body: some View {
35 | VStack {
36 | // speaker.image
37 | // .resizable()
38 | // .scaledToFit()
39 | // .cornerRadius(5.0)
40 | VideoPlayer(player: player).scaledToFit()
41 |
42 | Text(speaker.name)
43 | .font(.headline)
44 |
45 | //Toggle("Test Me", isOn: $isSwitched)
46 | Button("Play", action: { player.play() })
47 |
48 | Divider()
49 |
50 | if isSwitched {
51 | Text("You are within 5 miles of one of your favorite landmarks.")
52 | .font(.caption)
53 | }
54 | }
55 | }
56 | }
57 |
58 |
59 | #Preview {
60 | NotificationView()
61 | }
62 |
63 | class NotificationController: WKUserNotificationHostingController {
64 |
65 | let landmarkIndexKey = "landmarkIndex"
66 |
67 | override var body: NotificationView {
68 | NotificationView(speaker: .alberto)
69 |
70 | }
71 |
72 | override class var isInteractive: Bool {
73 | return true
74 | }
75 |
76 | override class var sashColor: Color? {
77 | return Color.heroBlue
78 | }
79 |
80 | override class var wantsSashBlur: Bool {
81 | return true
82 | }
83 |
84 | override class var titleColor: Color? {
85 | return .heroOrange
86 | }
87 |
88 | override class var subtitleColor: Color? {
89 | return .secondary
90 | }
91 |
92 | override func didReceive(_ notification: UNNotification) {
93 | //let modelData = ModelData()
94 | self.notificationActions = [.init(identifier: "action_identifier", title: "Dynamic action title")]
95 | let notificationData =
96 | notification.request.content.userInfo as? [String: Any]
97 |
98 | // let aps = notificationData?["aps"] as? [String: Any]
99 | // let alert = aps?["alert"] as? [String: Any]
100 | //
101 | //
102 | // title = alert?["title"] as? String
103 | // message = alert?["body"] as? String
104 | //
105 | //
106 | // if let index = notificationData?[landmarkIndexKey] as? Int {
107 | // landmark = modelData.landmarks[index]
108 | // }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Extensions/Image+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Image.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/8/24.
6 | //
7 |
8 | import SwiftUI
9 |
10 | public extension Image {
11 | static let alberto = Image("alberto", bundle: .module)
12 | static let alex = Image("alex", bundle: .module)
13 | static let andrea = Image("andrea", bundle: .module)
14 | static let andrei = Image("andrei", bundle: .module)
15 | static let batuhan = Image("batuhan", bundle: .module)
16 | static let beyza = Image("beyza", bundle: .module)
17 | static let borbala = Image("borbala", bundle: .module)
18 | static let brad = Image("brad", bundle: .module)
19 | static let davide = Image("davide", bundle: .module)
20 | static let davide2 = Image("davide2", bundle: .module)
21 | static let emilio = Image("emilio", bundle: .module)
22 | static let flora = Image("flora", bundle: .module)
23 | static let gyuree = Image("gyuree", bundle: .module)
24 | static let jane = Image("jane", bundle: .module)
25 | static let josip = Image("josip", bundle: .module)
26 | static let krysztof = Image("krysztof", bundle: .module)
27 | static let libranner = Image("libranner", bundle: .module)
28 | static let lukasz = Image("lukasz", bundle: .module)
29 | static let marcin = Image("marcin", bundle: .module)
30 | static let marco = Image("marco", bundle: .module)
31 | static let mete = Image("mete", bundle: .module)
32 | static let michael = Image("michael", bundle: .module)
33 | static let natan = Image("natan", bundle: .module)
34 | static let pedro = Image("pedro", bundle: .module)
35 | static let peter = Image("peter", bundle: .module)
36 | static let pietro = Image("pietro", bundle: .module)
37 | static let pol = Image("pol", bundle: .module)
38 | static let pradnya = Image("pradnya", bundle: .module)
39 | static let sara = Image("sara", bundle: .module)
40 | static let shai = Image("shai", bundle: .module)
41 | static let stefano = Image("stefano", bundle: .module)
42 | static let vince = Image("vince", bundle: .module)
43 | static let vincenzo = Image("vincenzo", bundle: .module)
44 | static let zach = Image("zach", bundle: .module)
45 |
46 | static let logo = Image("logo", bundle: .module)
47 | static let wordLogo = Image("wordLogo", bundle: .module)
48 |
49 | static let ios3 = Image("ios3", bundle: .module)
50 | static let ios4 = Image("ios4", bundle: .module)
51 | static let ios8 = Image("ios8", bundle: .module)
52 | static let ios9 = Image("ios9", bundle: .module)
53 | static let ios10 = Image("ios10", bundle: .module)
54 | static let ios14 = Image("ios14", bundle: .module)
55 | }
56 |
57 | public extension Image {
58 | func styled() -> some View {
59 | self
60 | .font(.title2)
61 | .symbolRenderingMode(.palette)
62 | .foregroundStyle(Color.heroOrange, Color.heroBlue)
63 | }
64 | #if os(iOS)
65 | @MainActor
66 | func getUIImage(newSize: CGSize) -> UIImage? {
67 | let image = resizable()
68 | .scaledToFill()
69 | .frame(width: newSize.width, height: newSize.height)
70 | .clipped()
71 | return ImageRenderer(content: image).uiImage
72 | }
73 | #endif
74 | }
75 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroiOS/Views/SpeakerListView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SpeakerListView.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/9/24.
6 | //
7 |
8 | import SwiftUI
9 | import Observation
10 | import HeroShared
11 |
12 | let activityType = "com.swiftheroes.speakers"
13 |
14 | public struct SpeakerListView: View {
15 | @Environment(ScreenManager.self) var screenManager: ScreenManager
16 |
17 | @State var quickActionsManager = QuickActionsManager.shared
18 | @State private var isSheetPresented = false
19 |
20 | public init() {}
21 |
22 | let columns = [
23 | GridItem(.flexible()),
24 | GridItem(.flexible()),
25 | ]
26 |
27 | public var body: some View {
28 | NavigationStack {
29 | ScrollView {
30 | LazyVGrid(columns: columns, spacing: 20) {
31 | ForEach(Speaker.all, id: \.id) { speaker in
32 | VStack {
33 | speaker.image
34 | .resizable()
35 | .frame(width: 150, height: 150)
36 | .cornerRadius(15.0)
37 |
38 | Text(speaker.title)
39 | .font(.title3)
40 | .bold()
41 | }
42 | }
43 | }
44 | .padding(.horizontal)
45 | }
46 | .padding()
47 | .navigationTitle("Speakers")
48 | .customToolBarStyle()
49 | .externalScreenToolbar(screenManager: screenManager, showingSheet: $isSheetPresented)
50 | }
51 | .sheet(isPresented: $isSheetPresented) {
52 | Text("Half screen content here")
53 | .presentationDetents([.fraction(0.33), .medium])
54 | //.interactiveDismissDisabled(true)
55 | }
56 | .userActivity(activityType, element: "1", { element, activity in
57 | let bundleid = Bundle.main.bundleIdentifier ?? ""
58 |
59 | activity.addUserInfoEntries(from: ["id": "1",
60 | "name": "Alex",
61 | "setby": bundleid])
62 | //activity.el
63 | logUserActivity(activity, label: "Activity")
64 | })
65 | .onContinueUserActivity(activityType, perform: { userActivity in
66 | if let _ = userActivity.userInfo?["id"] as? String {
67 | // Load handoff page
68 |
69 | }
70 |
71 | logUserActivity(userActivity, label: "on activity")
72 | })
73 | .onChange(of: quickActionsManager.quickAction) { _, _ in
74 | print("Change current action is \(String(describing: quickActionsManager.quickAction?.rawValue))")
75 | }
76 | .onChange(of: screenManager.showScreen) { _, newValue in
77 | isSheetPresented = newValue
78 | }
79 | .onAppear {
80 | print("current action is \(String(describing: quickActionsManager.quickAction?.rawValue))")
81 | }
82 | }
83 |
84 | func logUserActivity(_ activity: NSUserActivity, label: String = "") {
85 | print("\(label) TYPE = \(activity.activityType)")
86 | print("\(label) INFO = \(activity.userInfo ?? [:])")
87 | }
88 | }
89 |
90 | #Preview {
91 | SpeakerListView()
92 | #if os(iOS)
93 | .environment(ScreenManager())
94 | #endif
95 | }
96 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroiOS/Views/ExtensionListView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExtensionListView 2.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/10/24.
6 | //
7 |
8 | import SwiftUI
9 | import HeroShared
10 |
11 | public struct ExtensionListView: View {
12 | @Environment(ScreenManager.self) var screenManager: ScreenManager
13 | @State var quickActionsManager = QuickActionsManager.shared
14 | @State private var isSheetPresented = false
15 |
16 | public init() {}
17 |
18 | public var body: some View {
19 | NavigationStack {
20 | List(ExtensionItem.all) { item in
21 | HStack {
22 | Label(title: {
23 | Text(item.name)
24 | }, icon: {
25 | item.image.styled()
26 | })
27 | Spacer()
28 |
29 | ZStack {
30 | Rectangle()
31 | .foregroundColor(Color.heroOrange.opacity(0.3))
32 | .cornerRadius(10)
33 |
34 |
35 | HStack(spacing: 2) {
36 | Image(systemName: "iphone")
37 | Image(systemName: "applewatch")
38 | Image(systemName: "ipad")
39 | Image(systemName: "macbook")
40 | Image(systemName: "appletv")
41 | Image(systemName: "visionpro")
42 | }
43 | }
44 | .frame(width: 150, height: 30)
45 | }
46 | }
47 | .customListStyle()
48 | .navigationTitle("Extensions")
49 | .customToolBarStyle()
50 | .externalScreenToolbar(screenManager: screenManager, showingSheet: $isSheetPresented)
51 | }
52 | .sheet(isPresented: $isSheetPresented) {
53 | Text("Half screen content here")
54 | .presentationDetents([.fraction(0.33), .medium])
55 | }
56 | .userActivity(activityType, element: "1", { element, activity in
57 | let bundleid = Bundle.main.bundleIdentifier ?? ""
58 |
59 | activity.addUserInfoEntries(from: ["id": "1",
60 | "name": "Alex",
61 | "setby": bundleid])
62 | //activity.el
63 | logUserActivity(activity, label: "Activity")
64 | })
65 | .onContinueUserActivity(activityType, perform: { userActivity in
66 | if let _ = userActivity.userInfo?["id"] as? String {
67 | // Load handoff page
68 |
69 | }
70 |
71 | logUserActivity(userActivity, label: "on activity")
72 | })
73 | .onChange(of: quickActionsManager.quickAction) { _, _ in
74 | print("Change current action is \(String(describing: quickActionsManager.quickAction?.rawValue))")
75 | }
76 | .onChange(of: screenManager.showScreen) { _, newValue in
77 | isSheetPresented = newValue
78 | }
79 | .onAppear {
80 | print("current action is \(String(describing: quickActionsManager.quickAction?.rawValue))")
81 | }
82 | }
83 |
84 | func logUserActivity(_ activity: NSUserActivity, label: String = "") {
85 | print("\(label) TYPE = \(activity.activityType)")
86 | print("\(label) INFO = \(activity.userInfo ?? [:])")
87 | }
88 | }
89 |
90 | #Preview {
91 | ExtensionListView()
92 | .environment(ScreenManager())
93 | }
94 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Data/ExtensionItem.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExtensionItem.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/10/24.
6 | //
7 |
8 | import Foundation
9 | import SwiftUI
10 |
11 | public struct ExtensionItem: Identifiable, Equatable {
12 | public init(id: String, name: String, desc: String, image: Image, platforms: [String]) {
13 | self.id = id
14 | self.name = name
15 | self.desc = desc
16 | self.image = image
17 | self.platforms = platforms
18 | }
19 |
20 | public var id: String
21 | public var name: String
22 | public var desc: String
23 | public var image: Image
24 | public var platforms: [String]
25 | }
26 |
27 | public extension ExtensionItem {
28 | static var all: [ExtensionItem] {
29 | return [
30 | .init(id: "100",
31 | name: "Action",
32 | desc: "",
33 | image: Image(systemName: "bolt.fill"),
34 | platforms: [.iphone, .ipad, .mac]
35 | ),
36 | .init(id: "200",
37 | name: "Share",
38 | desc: "",
39 | image: Image(systemName: "square.and.arrow.up"),
40 | platforms: [.iphone, .ipad, .mac]
41 | ),
42 | .init(id: "300",
43 | name: "Notification",
44 | desc: "",
45 | image: Image(systemName: "bell.badge.fill"),
46 | platforms: [.iphone, .watch, .ipad, .mac, .xr]
47 | ),
48 | .init(id: "400",
49 | name: "iMessage",
50 | desc: "",
51 | image: Image(systemName: "message.fill"),
52 | platforms: [.iphone, .ipad]
53 | ),
54 | .init(id: "500",
55 | name: "Spotlight",
56 | desc: "",
57 | image: Image(systemName: "magnifyingglass"),
58 | platforms: [.iphone, .ipad, .mac]
59 | ),
60 | .init(id: "600",
61 | name: "AppClips",
62 | desc: "",
63 | image: Image(systemName: "appclip"),
64 | platforms: [.iphone, .ipad]
65 | ),
66 | .init(id: "700",
67 | name: "Quick Actions",
68 | desc: "",
69 | image: Image(systemName: "list.bullet"),
70 | platforms: [.iphone, .ipad]
71 | ),
72 | .init(id: "800",
73 | name: "Handoff",
74 | desc: "",
75 | image: Image(systemName: "macbook.and.iphone"),
76 | platforms: [.iphone, .watch, .ipad, .mac, .tv, .xr]
77 | ),
78 | .init(id: "900",
79 | name: "External Screen",
80 | desc: "",
81 | image: Image(systemName: "tv"),
82 | platforms: [.iphone, .ipad]
83 | ),
84 | .init(id: "950",
85 | name: "Quick Look Preview",
86 | desc: "",
87 | image: Image(systemName: "eye.fill"),
88 | platforms: [.iphone, .ipad]
89 | ),
90 | ]
91 | }
92 | }
93 |
94 | extension ExtensionItem: Listable {
95 | public var type: ListType {
96 | return .extensionItem
97 | }
98 |
99 | public var title: String {
100 | self.name
101 | }
102 |
103 | public var subtitle: String {
104 | self.desc
105 | }
106 |
107 | public var badges: [String] {
108 | self.platforms
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/Demo.xcodeproj/xcshareddata/xcschemes/Action.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
9 |
10 |
16 |
22 |
23 |
24 |
30 |
36 |
37 |
38 |
39 |
40 |
46 |
47 |
59 |
61 |
67 |
68 |
69 |
70 |
78 |
80 |
86 |
87 |
88 |
89 |
91 |
92 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/Demo.xcodeproj/xcshareddata/xcschemes/iMessage.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
9 |
10 |
16 |
22 |
23 |
24 |
30 |
36 |
37 |
38 |
39 |
40 |
46 |
47 |
59 |
61 |
67 |
68 |
69 |
70 |
78 |
80 |
86 |
87 |
88 |
89 |
91 |
92 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/Demo.xcodeproj/xcshareddata/xcschemes/Spotlight.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
9 |
10 |
16 |
22 |
23 |
24 |
30 |
36 |
37 |
38 |
39 |
40 |
46 |
47 |
59 |
61 |
67 |
68 |
69 |
70 |
78 |
80 |
86 |
87 |
88 |
89 |
91 |
92 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/Demo.xcodeproj/xcshareddata/xcschemes/Notification.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
9 |
10 |
16 |
22 |
23 |
24 |
30 |
36 |
37 |
38 |
39 |
40 |
46 |
47 |
59 |
61 |
67 |
68 |
69 |
70 |
78 |
80 |
86 |
87 |
88 |
89 |
91 |
92 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/Demo.xcodeproj/xcshareddata/xcschemes/NotificationService.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
9 |
10 |
16 |
22 |
23 |
24 |
30 |
36 |
37 |
38 |
39 |
40 |
46 |
47 |
59 |
61 |
67 |
68 |
69 |
70 |
78 |
80 |
86 |
87 |
88 |
89 |
91 |
92 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/Demo.xcodeproj/xcshareddata/xcschemes/Share.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
6 |
10 |
11 |
17 |
23 |
24 |
25 |
31 |
37 |
38 |
39 |
40 |
41 |
47 |
48 |
60 |
62 |
68 |
69 |
70 |
71 |
79 |
81 |
87 |
88 |
89 |
90 |
92 |
93 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/Heroes/Sources/HeroShared/Notifications/NotificationHelper.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotificationHelper.swift
3 | //
4 | //
5 | // Created by Vince Davis on 4/10/24.
6 | //
7 |
8 | import Foundation
9 | #if !os(tvOS)
10 | import UserNotifications
11 |
12 | public struct NotificationHelper {
13 | public init() {}
14 | public func setup() {
15 | let changeAction = UNNotificationAction(identifier: "testNotification.changeAction",
16 | title: "Change Rating",
17 | options: [],
18 | icon: .init(systemImageName: "star.fill"))
19 | let submitAction = UNNotificationAction(identifier: "testNotification.submitAction",
20 | title: "Submit",
21 | options: [.destructive],
22 | icon: .init(systemImageName: "paperplane.fill"))
23 | let testNotifCategory = UNNotificationCategory(identifier: "default",
24 | actions: [changeAction, submitAction],
25 | intentIdentifiers: [],
26 | options: [])
27 |
28 | let playAction = UNNotificationAction(identifier: "testNotification.playAction",
29 | title: "Play",
30 | options: [],
31 | icon: .init(systemImageName: "play.fill"))
32 | let pauseAction = UNNotificationAction(identifier: "testNotification.pauseAction",
33 | title: "Pause",
34 | options: [],
35 | icon: .init(systemImageName: "pause.fill"))
36 | let videoNotifCategory = UNNotificationCategory(identifier: "video",
37 | actions: [playAction, pauseAction],
38 | intentIdentifiers: [],
39 | options: [])
40 |
41 | let action = UNNotificationAction(identifier: "testNotification.slideAction",
42 | title: "Slide",
43 | options: [],
44 | icon: .init(systemImageName: "photo.artframe"))
45 |
46 | let imageNotifCategory = UNNotificationCategory(identifier: "images",
47 | actions: [action],
48 | intentIdentifiers: [],
49 | options: [])
50 |
51 | let statusAction = UNNotificationAction(identifier: "testNotification.showFlight",
52 | title: "Show Flight Status",
53 | options: [],
54 | icon: .init(systemImageName: "airplane"))
55 |
56 | let statusNotifCategory = UNNotificationCategory(identifier: "flightStatus",
57 | actions: [statusAction],
58 | intentIdentifiers: [],
59 | options: [])
60 |
61 | UNUserNotificationCenter.current().setNotificationCategories([testNotifCategory,imageNotifCategory,videoNotifCategory, statusNotifCategory])
62 |
63 |
64 | let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
65 | UNUserNotificationCenter.current().requestAuthorization(
66 | options: authOptions,
67 | completionHandler: {_, _ in })
68 | }
69 | }
70 | #endif
71 |
--------------------------------------------------------------------------------