diff --git a/LiveActivity/LiveActivityLiveActivity.swift b/LiveActivity/FIFALiveActivity.swift similarity index 87% rename from LiveActivity/LiveActivityLiveActivity.swift rename to LiveActivity/FIFALiveActivity.swift index 58aaa4e..d280ad5 100644 --- a/LiveActivity/LiveActivityLiveActivity.swift +++ b/LiveActivity/FIFALiveActivity.swift @@ -8,13 +8,13 @@ import ActivityKit import WidgetKit import SwiftUI +import OneSignalLiveActivities -struct LiveActivityAttributes: ActivityAttributes { +struct FIFALiveActivityAttributes: ActivityAttributes { public struct ContentState: Codable, Hashable { // Dynamic stateful properties about your activity go here! var homeScore: Int var awayScore: Int - } // Fixed non-changing properties about your activity go here! @@ -23,12 +23,11 @@ struct LiveActivityAttributes: ActivityAttributes { var awayTeam: String var fifaLogo: String var sponsorLogo: String - } -struct LiveActivityLiveActivity: Widget { +struct FIFALiveActivity: Widget { var body: some WidgetConfiguration { - ActivityConfiguration(for: LiveActivityAttributes.self) { context in + ActivityConfiguration(for: FIFALiveActivityAttributes.self) { context in // Lock screen/banner UI goes here ZStack { VStack { @@ -158,22 +157,22 @@ extension Color { } } -extension LiveActivityAttributes { - fileprivate static var preview: LiveActivityAttributes { - LiveActivityAttributes(name: "Switzerland vs. Germany", homeTeam: "Switzerland", awayTeam: "Germany", fifaLogo: "fifa_logo", sponsorLogo: "cocacola_logo") +extension FIFALiveActivityAttributes { + fileprivate static var preview: FIFALiveActivityAttributes { + FIFALiveActivityAttributes(name: "Switzerland vs. Germany", homeTeam: "Switzerland", awayTeam: "Germany", fifaLogo: "fifa_logo", sponsorLogo: "cocacola_logo") } } -extension LiveActivityAttributes.ContentState { - fileprivate static var smiley: LiveActivityAttributes.ContentState { - LiveActivityAttributes.ContentState(homeScore: 6, awayScore: 1) +extension FIFALiveActivityAttributes.ContentState { + fileprivate static var smiley: FIFALiveActivityAttributes.ContentState { + FIFALiveActivityAttributes.ContentState(homeScore: 6, awayScore: 1) } } -#Preview("Expanded Dynamic Island", as: ActivityPreviewViewKind.dynamicIsland(.expanded) , using: LiveActivityAttributes.preview) { - LiveActivityLiveActivity() +#Preview("Expanded Dynamic Island", as: ActivityPreviewViewKind.dynamicIsland(.expanded) , using: FIFALiveActivityAttributes.preview) { + FIFALiveActivity() } contentStates: { - LiveActivityAttributes.ContentState.smiley + FIFALiveActivityAttributes.ContentState.smiley } diff --git a/LiveActivity/LiveActivityBundle.swift b/LiveActivity/LiveActivityBundle.swift index a35a980..6122712 100644 --- a/LiveActivity/LiveActivityBundle.swift +++ b/LiveActivity/LiveActivityBundle.swift @@ -10,7 +10,9 @@ import SwiftUI @main struct LiveActivityBundle: WidgetBundle { + var body: some Widget { - LiveActivityLiveActivity() + FIFALiveActivity() + SimpleLiveActivity() } } diff --git a/LiveActivity/SimpleLiveActivity.swift b/LiveActivity/SimpleLiveActivity.swift new file mode 100644 index 0000000..8e7c745 --- /dev/null +++ b/LiveActivity/SimpleLiveActivity.swift @@ -0,0 +1,71 @@ +// +// LiveActivityLiveActivity.swift +// LiveActivity +// +// Created by William Shepherd on 1/22/24. +// + +import ActivityKit +import WidgetKit +import SwiftUI +import OneSignalLiveActivities + +struct SimpleLiveActivityAttributes: ActivityAttributes { + public struct ContentState: Codable, Hashable { + // Dynamic stateful properties about your activity go here! + // Update using the API by setting the `event_updates` parameter + var message: String + } + + // Fixed non-changing properties about your activity go here! + var name: String +} + +struct SimpleLiveActivity: Widget { + var body: some WidgetConfiguration { + ActivityConfiguration(for: FIFALiveActivityAttributes.self) { context in + // Lock screen/banner UI goes here + } dynamicIsland: { context in + DynamicIsland { + DynamicIslandExpandedRegion(.leading) { + Text("Leading") + } + DynamicIslandExpandedRegion(.trailing) { + Text("Trailing") + } + DynamicIslandExpandedRegion(.center) { + Text("C") + } + } compactLeading: { + Text("L") + } compactTrailing: { + Text("T") + } minimal: { + Text("M") + } + .widgetURL(URL(string: "http://www.onesignal.com")) + .keylineTint(Color.red) + + + } + } +} + +extension SimpleLiveActivityAttributes { + fileprivate static var preview: SimpleLiveActivityAttributes { + SimpleLiveActivityAttributes(name: "Joe") + } +} + +extension SimpleLiveActivityAttributes.ContentState { + fileprivate static var smiley: SimpleLiveActivityAttributes.ContentState { + SimpleLiveActivityAttributes.ContentState(message: "👋🏽") + } + +} + +#Preview("Expanded Dynamic Island", as: ActivityPreviewViewKind.dynamicIsland(.expanded) , using: SimpleLiveActivityAttributes.preview) { + SimpleLiveActivity() +} contentStates: { + SimpleLiveActivityAttributes.ContentState.smiley +} diff --git a/OneSignal iOS Sample.xcodeproj/project.pbxproj b/OneSignal iOS Sample.xcodeproj/project.pbxproj index 9f5f55f..8168c50 100644 --- a/OneSignal iOS Sample.xcodeproj/project.pbxproj +++ b/OneSignal iOS Sample.xcodeproj/project.pbxproj @@ -12,6 +12,12 @@ 670113BD29E9A70800D01DE9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 670113BC29E9A70800D01DE9 /* Assets.xcassets */; }; 670113C029E9A70800D01DE9 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 670113BF29E9A70800D01DE9 /* Preview Assets.xcassets */; }; 670113CD29E9AA8400D01DE9 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 670113CC29E9AA8400D01DE9 /* NotificationService.swift */; }; + 6708E9722C93464B00022A29 /* OneSignalExtension in Frameworks */ = {isa = PBXBuildFile; productRef = 6708E9712C93464B00022A29 /* OneSignalExtension */; }; + 6708E9742C93464B00022A29 /* OneSignalFramework in Frameworks */ = {isa = PBXBuildFile; productRef = 6708E9732C93464B00022A29 /* OneSignalFramework */; }; + 6708E9762C93464B00022A29 /* OneSignalInAppMessages in Frameworks */ = {isa = PBXBuildFile; productRef = 6708E9752C93464B00022A29 /* OneSignalInAppMessages */; }; + 6708E9782C93464B00022A29 /* OneSignalLocation in Frameworks */ = {isa = PBXBuildFile; productRef = 6708E9772C93464B00022A29 /* OneSignalLocation */; }; + 6708E97A2C94AE5C00022A29 /* SimpleLiveActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6708E9792C94AE5C00022A29 /* SimpleLiveActivity.swift */; }; + 6708E97B2C94AE5C00022A29 /* SimpleLiveActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6708E9792C94AE5C00022A29 /* SimpleLiveActivity.swift */; }; 673A9B662A1C06F9000243D0 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 67324DF429F5F81700886064 /* WidgetKit.framework */; }; 673A9B672A1C06F9000243D0 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 67324DF629F5F81700886064 /* SwiftUI.framework */; }; 673A9B6A2A1C06F9000243D0 /* SampleWidgetExtensionBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 673A9B692A1C06F9000243D0 /* SampleWidgetExtensionBundle.swift */; }; @@ -21,15 +27,13 @@ 673A9B742A1C06FA000243D0 /* SampleWidgetExtension.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 673A9B6F2A1C06F9000243D0 /* SampleWidgetExtension.intentdefinition */; }; 675089842A2697E600579634 /* SportsScoreLiveActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 675089832A2697E600579634 /* SportsScoreLiveActivity.swift */; }; 675089852A26986C00579634 /* SportsScoreLiveActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 675089832A2697E600579634 /* SportsScoreLiveActivity.swift */; }; - 675CA1C42C1CE00700EA9907 /* OneSignalExtension in Frameworks */ = {isa = PBXBuildFile; productRef = 675CA1C32C1CE00700EA9907 /* OneSignalExtension */; }; - 675CA1C62C1CE00700EA9907 /* OneSignalFramework in Frameworks */ = {isa = PBXBuildFile; productRef = 675CA1C52C1CE00700EA9907 /* OneSignalFramework */; }; - 675CA1C82C1CE00700EA9907 /* OneSignalInAppMessages in Frameworks */ = {isa = PBXBuildFile; productRef = 675CA1C72C1CE00700EA9907 /* OneSignalInAppMessages */; }; - 6779EB1A2B5F5EFE0061F28B /* LiveActivityLiveActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67DA2FD52B5E509900821C94 /* LiveActivityLiveActivity.swift */; }; + 6779EB1A2B5F5EFE0061F28B /* FIFALiveActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67DA2FD52B5E509900821C94 /* FIFALiveActivity.swift */; }; + 678D862B2C269A2B005F1CB0 /* OSControlBoardViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 678D862A2C269A2B005F1CB0 /* OSControlBoardViewModel.swift */; }; 679958692A1C0DAC0006091F /* SampleWidgetExtensionExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 673A9B652A1C06F9000243D0 /* SampleWidgetExtensionExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 67DA2FD02B5E509900821C94 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 67324DF429F5F81700886064 /* WidgetKit.framework */; }; 67DA2FD12B5E509900821C94 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 67324DF629F5F81700886064 /* SwiftUI.framework */; }; 67DA2FD42B5E509900821C94 /* LiveActivityBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67DA2FD32B5E509900821C94 /* LiveActivityBundle.swift */; }; - 67DA2FD62B5E509900821C94 /* LiveActivityLiveActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67DA2FD52B5E509900821C94 /* LiveActivityLiveActivity.swift */; }; + 67DA2FD62B5E509900821C94 /* FIFALiveActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67DA2FD52B5E509900821C94 /* FIFALiveActivity.swift */; }; 67DA2FDA2B5E509900821C94 /* AppIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67DA2FD92B5E509900821C94 /* AppIntent.swift */; }; 67DA2FDC2B5E509A00821C94 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 67DA2FDB2B5E509A00821C94 /* Assets.xcassets */; }; 67DA2FE02B5E509A00821C94 /* LiveActivityExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 67DA2FCF2B5E509900821C94 /* LiveActivityExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; @@ -83,6 +87,7 @@ 670113CA29E9AA8400D01DE9 /* OneSignalNotificationServiceExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = OneSignalNotificationServiceExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 670113CC29E9AA8400D01DE9 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; }; 670113CE29E9AA8400D01DE9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6708E9792C94AE5C00022A29 /* SimpleLiveActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleLiveActivity.swift; sourceTree = ""; }; 67324DF429F5F81700886064 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; }; 67324DF629F5F81700886064 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; }; 673A9B652A1C06F9000243D0 /* SampleWidgetExtensionExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SampleWidgetExtensionExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -92,9 +97,10 @@ 673A9B702A1C06FA000243D0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 673A9B722A1C06FA000243D0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 675089832A2697E600579634 /* SportsScoreLiveActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SportsScoreLiveActivity.swift; sourceTree = ""; }; + 678D862A2C269A2B005F1CB0 /* OSControlBoardViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OSControlBoardViewModel.swift; sourceTree = ""; }; 67DA2FCF2B5E509900821C94 /* LiveActivityExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = LiveActivityExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 67DA2FD32B5E509900821C94 /* LiveActivityBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveActivityBundle.swift; sourceTree = ""; }; - 67DA2FD52B5E509900821C94 /* LiveActivityLiveActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveActivityLiveActivity.swift; sourceTree = ""; }; + 67DA2FD52B5E509900821C94 /* FIFALiveActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FIFALiveActivity.swift; sourceTree = ""; }; 67DA2FD92B5E509900821C94 /* AppIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppIntent.swift; sourceTree = ""; }; 67DA2FDB2B5E509A00821C94 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 67DA2FDD2B5E509A00821C94 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -107,8 +113,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 675CA1C82C1CE00700EA9907 /* OneSignalInAppMessages in Frameworks */, - 675CA1C62C1CE00700EA9907 /* OneSignalFramework in Frameworks */, + 6708E9762C93464B00022A29 /* OneSignalInAppMessages in Frameworks */, + 6708E9782C93464B00022A29 /* OneSignalLocation in Frameworks */, + 6708E9742C93464B00022A29 /* OneSignalFramework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -116,7 +123,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 675CA1C42C1CE00700EA9907 /* OneSignalExtension in Frameworks */, + 6708E9722C93464B00022A29 /* OneSignalExtension in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -171,6 +178,7 @@ 67E3788E29EDD99200320FC3 /* OneSignal iOS Sample.entitlements */, 670113B829E9A70700D01DE9 /* OneSignal_iOS_SampleApp.swift */, 670113BA29E9A70700D01DE9 /* OSControlBoardView.swift */, + 678D862A2C269A2B005F1CB0 /* OSControlBoardViewModel.swift */, 670113BC29E9A70800D01DE9 /* Assets.xcassets */, 670113BE29E9A70800D01DE9 /* Preview Content */, ); @@ -220,10 +228,11 @@ isa = PBXGroup; children = ( 67DA2FD32B5E509900821C94 /* LiveActivityBundle.swift */, - 67DA2FD52B5E509900821C94 /* LiveActivityLiveActivity.swift */, + 67DA2FD52B5E509900821C94 /* FIFALiveActivity.swift */, 67DA2FD92B5E509900821C94 /* AppIntent.swift */, 67DA2FDB2B5E509A00821C94 /* Assets.xcassets */, 67DA2FDD2B5E509A00821C94 /* Info.plist */, + 6708E9792C94AE5C00022A29 /* SimpleLiveActivity.swift */, ); path = LiveActivity; sourceTree = ""; @@ -249,8 +258,9 @@ ); name = "OneSignal iOS Sample"; packageProductDependencies = ( - 675CA1C52C1CE00700EA9907 /* OneSignalFramework */, - 675CA1C72C1CE00700EA9907 /* OneSignalInAppMessages */, + 6708E9732C93464B00022A29 /* OneSignalFramework */, + 6708E9752C93464B00022A29 /* OneSignalInAppMessages */, + 6708E9772C93464B00022A29 /* OneSignalLocation */, ); productName = "OneSignal iOS Sample"; productReference = 670113B529E9A70700D01DE9 /* OneSignal iOS Sample.app */; @@ -270,7 +280,7 @@ ); name = OneSignalNotificationServiceExtension; packageProductDependencies = ( - 675CA1C32C1CE00700EA9907 /* OneSignalExtension */, + 6708E9712C93464B00022A29 /* OneSignalExtension */, ); productName = OneSignalNotificationServiceExtension; productReference = 670113CA29E9AA8400D01DE9 /* OneSignalNotificationServiceExtension.appex */; @@ -318,7 +328,7 @@ attributes = { BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 1520; - LastUpgradeCheck = 1520; + LastUpgradeCheck = 1540; TargetAttributes = { 670113B429E9A70700D01DE9 = { CreatedOnToolsVersion = 14.3; @@ -344,7 +354,7 @@ ); mainGroup = 670113AC29E9A70700D01DE9; packageReferences = ( - 675CA1C22C1CE00700EA9907 /* XCRemoteSwiftPackageReference "onesignal-ios-sdk" */, + 6708E9702C93464B00022A29 /* XCRemoteSwiftPackageReference "onesignal-ios-sdk" */, ); productRefGroup = 670113B629E9A70700D01DE9 /* Products */; projectDirPath = ""; @@ -401,8 +411,10 @@ 670113BB29E9A70700D01DE9 /* OSControlBoardView.swift in Sources */, 673A9B742A1C06FA000243D0 /* SampleWidgetExtension.intentdefinition in Sources */, 670113B929E9A70700D01DE9 /* OneSignal_iOS_SampleApp.swift in Sources */, - 6779EB1A2B5F5EFE0061F28B /* LiveActivityLiveActivity.swift in Sources */, + 678D862B2C269A2B005F1CB0 /* OSControlBoardViewModel.swift in Sources */, + 6779EB1A2B5F5EFE0061F28B /* FIFALiveActivity.swift in Sources */, 675089842A2697E600579634 /* SportsScoreLiveActivity.swift in Sources */, + 6708E97A2C94AE5C00022A29 /* SimpleLiveActivity.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -431,7 +443,8 @@ files = ( 67DA2FD42B5E509900821C94 /* LiveActivityBundle.swift in Sources */, 67DA2FDA2B5E509900821C94 /* AppIntent.swift in Sources */, - 67DA2FD62B5E509900821C94 /* LiveActivityLiveActivity.swift in Sources */, + 6708E97B2C94AE5C00022A29 /* SimpleLiveActivity.swift in Sources */, + 67DA2FD62B5E509900821C94 /* FIFALiveActivity.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -460,6 +473,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -521,6 +535,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -860,32 +875,37 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ - 675CA1C22C1CE00700EA9907 /* XCRemoteSwiftPackageReference "onesignal-ios-sdk" */ = { + 6708E9702C93464B00022A29 /* XCRemoteSwiftPackageReference "onesignal-ios-sdk" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/onesignal/onesignal-ios-sdk"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 5.2.1; + minimumVersion = 5.2.4; }; }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - 675CA1C32C1CE00700EA9907 /* OneSignalExtension */ = { + 6708E9712C93464B00022A29 /* OneSignalExtension */ = { isa = XCSwiftPackageProductDependency; - package = 675CA1C22C1CE00700EA9907 /* XCRemoteSwiftPackageReference "onesignal-ios-sdk" */; + package = 6708E9702C93464B00022A29 /* XCRemoteSwiftPackageReference "onesignal-ios-sdk" */; productName = OneSignalExtension; }; - 675CA1C52C1CE00700EA9907 /* OneSignalFramework */ = { + 6708E9732C93464B00022A29 /* OneSignalFramework */ = { isa = XCSwiftPackageProductDependency; - package = 675CA1C22C1CE00700EA9907 /* XCRemoteSwiftPackageReference "onesignal-ios-sdk" */; + package = 6708E9702C93464B00022A29 /* XCRemoteSwiftPackageReference "onesignal-ios-sdk" */; productName = OneSignalFramework; }; - 675CA1C72C1CE00700EA9907 /* OneSignalInAppMessages */ = { + 6708E9752C93464B00022A29 /* OneSignalInAppMessages */ = { isa = XCSwiftPackageProductDependency; - package = 675CA1C22C1CE00700EA9907 /* XCRemoteSwiftPackageReference "onesignal-ios-sdk" */; + package = 6708E9702C93464B00022A29 /* XCRemoteSwiftPackageReference "onesignal-ios-sdk" */; productName = OneSignalInAppMessages; }; + 6708E9772C93464B00022A29 /* OneSignalLocation */ = { + isa = XCSwiftPackageProductDependency; + package = 6708E9702C93464B00022A29 /* XCRemoteSwiftPackageReference "onesignal-ios-sdk" */; + productName = OneSignalLocation; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 670113AD29E9A70700D01DE9 /* Project object */; diff --git a/OneSignal iOS Sample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/OneSignal iOS Sample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 8c8f1fb..a3022b0 100644 --- a/OneSignal iOS Sample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/OneSignal iOS Sample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -6,8 +6,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/onesignal/onesignal-ios-sdk", "state" : { - "revision" : "f0552ddf17c6881eaa8c14ed187144485da6c8a9", - "version" : "5.2.1" + "revision" : "a197d9de8992ba2f0b43c75ea52a507e18f95681", + "version" : "5.2.4" } } ], diff --git a/OneSignal iOS Sample.xcodeproj/xcshareddata/xcschemes/OneSignal iOS Sample.xcscheme b/OneSignal iOS Sample.xcodeproj/xcshareddata/xcschemes/OneSignal iOS Sample.xcscheme index 2b71135..358d6cd 100644 --- a/OneSignal iOS Sample.xcodeproj/xcshareddata/xcschemes/OneSignal iOS Sample.xcscheme +++ b/OneSignal iOS Sample.xcodeproj/xcshareddata/xcschemes/OneSignal iOS Sample.xcscheme @@ -1,6 +1,6 @@ ? = nil - - let activityId = "live_activity_id" + @EnvironmentObject var vm: OSControlBoardViewModel var body: some View { - VStack { - Image(systemName: "globe") - .imageScale(.large) - .foregroundColor(.accentColor) - - Text("OneSignal iOS Sample") - .padding([.bottom], 40) - - Button(action: { - OneSignal.login("iamwillshepherd@kronos.local") - }) { - Text("Login") - .padding() - .background(Color.blue) - .foregroundColor(.white) - .cornerRadius(10) - } - - - Button(action: { - OneSignal.logout() - }) { - Text("Logout") - .padding() - .background(Color.blue) - .foregroundColor(.white) - .cornerRadius(10) - } - - Button(action: { - OneSignal.User.pushSubscription.optIn() - }) { - Text("Enable Push") - .padding() - .background(Color.blue) - .foregroundColor(.white) - .cornerRadius(10) - } - - Button(action: { - OneSignal.User.pushSubscription.optOut() - }) { - Text("Disable Push") - .padding() - .background(Color.blue) - .foregroundColor(.white) - .cornerRadius(10) - } - - Button(action: { - OneSignal.InAppMessages.addTrigger("show_push_permission_prompt", withValue: "1") - }) { - Text("Prompt Push Permission") - .padding() - .background(Color.blue) - .foregroundColor(.white) - .cornerRadius(10) - } - - Button(action: { - OneSignal.InAppMessages.addTrigger("TESTITY_TEST_TEST", withValue: "test") - }) { - Text("Present In-app Message") - .padding() - .background(Color.blue) - .foregroundColor(.white) - .cornerRadius(10) - } - - Button(action: { - startActivity() - }) { - Text("Start Live Activity") - .padding() - .background(Color.blue) - .foregroundColor(.white) - .cornerRadius(10) - } - - Button(action: { - stopActivity() - }) { - Text("End Live Activity") - .padding() - .background(Color.blue) - .foregroundColor(.white) - .cornerRadius(10) - } - } - .padding() - } - - func startActivity() { - let attributes = LiveActivityAttributes(name: "Switzerland vs. Germany", homeTeam: "Switzerland", awayTeam: "Germany", fifaLogo: "fifa_logo", sponsorLogo: "cocacola_logo") - let contentState = LiveActivityAttributes.ContentState(homeScore: 6, awayScore: 1) - let activityContent = ActivityContent(state: contentState, staleDate: Calendar.current.date(byAdding: .minute, value: 30, to: Date())!) + NavigationView { + VStack(spacing: 20) { + Image(systemName: "bell.circle.fill") + .imageScale(.large) + .foregroundColor(.accentColor) + .padding(.top, 40) - do { - activity = try Activity.request( - attributes: attributes, - content: activityContent, - pushType: .token) + Text("OneSignal iOS Sample") + .font(.title) + .fontWeight(.bold) + .padding(.bottom, 20) + + VStack(spacing: 15) { + Group { + Text(vm.onesignalId) + Text(vm.externalId) + } + + ActionButton(title: vm.LoginAction.text, action: vm.LoginAction.action) - Task { - for await data in activity!.pushTokenUpdates { - let token = data.map {String(format: "%02x", $0)}.joined() - print("Live Activity Push Token: ", token) - OneSignal.LiveActivities.enter(activityId, withToken: token) + ActionButton(title: vm.RequestPushPermissionAction.text, action: vm.RequestPushPermissionAction.action) + .disabled(!vm.canRequestPushPermission) + + ActionButton(title: "Soft Prompt Push Permission", action: { + vm.presentPushPermissionSoftPrompt() + }).disabled(vm.isPushEnabled) + + ActionButton(title: vm.subscribeToPushAction.text, action: vm.subscribeToPushAction.action) + + + ActionButton(title: "Present In-app Message", action: { + vm.presentIAM() + }) + +// ActionButton(title: vm.FIFALiveActivityAction.text, action: vm.FIFALiveActivityAction.action) + ActionButton(title: vm.SimpleLiveActivityAction.text, action: vm.SimpleLiveActivityAction.action) + + ActionButton(title: "Show Preference Center", action: { + vm.presentPreferenceCenter() + }, buttonColor: .orange) } + + Spacer() } - } catch (let error) { - print(error.localizedDescription) - } - } - - func stopActivity() { - OneSignal.LiveActivities.exit(activityId) + .navigationTitle("Control Board") + .navigationBarTitleDisplayMode(.inline) + .padding() + } } +} + +struct ActionButton: View { + let title: String + let action: () -> Void + var buttonColor: Color = .blue + var body: some View { + Button(action: action) { + Text(title) + .font(.body) + .frame(maxWidth: .infinity) + .padding() + .background(buttonColor) + .foregroundColor(.white) + .cornerRadius(8) + } + .padding(.horizontal) + .buttonStyle(PlainButtonStyle()) + } } + struct ContentView_Previews: PreviewProvider { + static let previewVm = OSControlBoardViewModel() static var previews: some View { - OSControlBoardView() + OSControlBoardView().environmentObject(previewVm) } } diff --git a/OneSignal iOS Sample/OSControlBoardViewModel.swift b/OneSignal iOS Sample/OSControlBoardViewModel.swift new file mode 100644 index 0000000..4416980 --- /dev/null +++ b/OneSignal iOS Sample/OSControlBoardViewModel.swift @@ -0,0 +1,221 @@ +// +// OSControlBoardViewModel.swift +// OneSignal iOS Sample +// +// Created by William Shepherd on 6/22/24. +// + +import Foundation +import ActivityKit +import OneSignalFramework +import OneSignalLiveActivities + +struct ButtonAction { + let text: String + let action: () -> Void + + init(text: String, action: @escaping () -> Void) { + self.text = text + self.action = action // Store the closure, don't call it + } +} + +class OSControlBoardViewModel: ObservableObject { + @Published var isPushEnabled: Bool + @Published var isSubscribed: Bool + @Published var isLoggedIn: Bool + + // The Activity must be bound to a unique ActivityId + // This is how OneSignal knows about your activity + private var simpleLiveActivityId = "unique_simple_id" + // Note that OneSignal does not know anything about + // you ActivityAttributes structure; Use the Activity ID + // to help keep track of each Activities' ActivityAttributes + private var simpleLiveActivity: Activity? = nil + + private var FIFALiveActivityId = "sui_vs_ger_2024_06_23" + private var FIFALiveActivity: Activity? = nil + + init() { + isLoggedIn = OneSignal.User.externalId != nil + isPushEnabled = OneSignal.Notifications.permission + isSubscribed = OneSignal.User.pushSubscription.optedIn + } + + var LoginAction: ButtonAction { + if isLoggedIn { + return ButtonAction(text: "Logout", action: { [weak self] in + OneSignal.logout() + DispatchQueue.main.async { + self?.isLoggedIn = false + } + }) + } else { + return ButtonAction(text: "Login", action: { [weak self] in + OneSignal.login("him@kronos.local") + DispatchQueue.main.async { + self?.isLoggedIn = true + } + }) + } + } + + var RequestPushPermissionAction: ButtonAction { + if isPushEnabled { + return ButtonAction( + text: "Push Permission Granted", + action: { } + ) + } else { + return ButtonAction( + text: "Request Push Permission", + action: { OneSignal.Notifications.requestPermission() } + ) + } + } + + var subscribeToPushAction: ButtonAction { + if isSubscribed { + return ButtonAction( + text: "Unsubscribe from Push Notifications", + action: { [weak self] in + OneSignal.User.pushSubscription.optOut() + self?.isSubscribed = false + }) + } else { + return ButtonAction( + text: "Subscribe to Push Notifications", + action: { [weak self] in + OneSignal.User.pushSubscription.optIn() + self?.isSubscribed = true + }) + } + } + + var externalId: String { + OneSignal.User.externalId ?? "Anonymous User" + } + + var onesignalId: String { + OneSignal.User.onesignalId ?? "N/A" + } + + var canRequestPushPermission: Bool { + OneSignal.Notifications.canRequestPermission + } + + var SimpleLiveActivityAction: ButtonAction { + if simpleLiveActivity != nil { + return ButtonAction(text: "End Simple Live Activity", action: { [weak self] in + self?.stopSimpleLiveActivity() + }) + } else { + return ButtonAction(text: "Start Simple Live Activity", action: { [weak self] in + self?.startSimpleLiveActivity() + }) + } + } + + var FIFALiveActivityAction: ButtonAction { + if FIFALiveActivity != nil { + return ButtonAction(text: "End FIFA Live Activity", action: { [weak self] in + self?.stopFIFALiveActivity() + }) + } else { + return ButtonAction(text: "Start FIFA Live Activity", action: { [weak self] in + self?.startFIFALiveActivity() + }) + } + } + + func presentIAM() { + OneSignal.InAppMessages.addTrigger("TESTITY_TEST_TEST", withValue: "test") + } + + func presentPushPermissionSoftPrompt() { + OneSignal.InAppMessages.addTrigger("show_push_permission_prompt", withValue: "1") + } + + func presentPreferenceCenter() { + OneSignal.InAppMessages.addTrigger("preferences", withValue: "show") + } + + func startSimpleLiveActivity() { + let attributes = SimpleLiveActivityAttributes(name: "him") + let contentState = SimpleLiveActivityAttributes.ContentState(message: "👋🏽") + let activityContent = ActivityContent(state: contentState, staleDate: Calendar.current.date(byAdding: .minute, value: 30, to: Date())!) + + do { + simpleLiveActivity = try Activity.request( + attributes: attributes, + content: activityContent, + pushType: .token) + + Task { + for await data in simpleLiveActivity!.pushTokenUpdates { + let token = data.map {String(format: "%02x", $0)}.joined() + print("Simple Live Activity Push Token::", token) + OneSignal.LiveActivities.enter(simpleLiveActivityId, withToken: token) + print("Simple Live Activity Started") + } + } + } catch (let error) { + print(error.localizedDescription) + } + } + + func stopSimpleLiveActivity() { + if simpleLiveActivity == nil { + return + } + + simpleLiveActivity = nil + OneSignal.LiveActivities.exit(simpleLiveActivityId) + print("Simple Live Activity Stopped") + } + + func startFIFALiveActivity() { + let attributes = FIFALiveActivityAttributes(name: "Switzerland vs. Germany", homeTeam: "Switzerland", awayTeam: "Germany", fifaLogo: "fifa_logo", sponsorLogo: "cocacola_logo") + let contentState = FIFALiveActivityAttributes.ContentState(homeScore: 0, awayScore: 0) + let activityContent = ActivityContent(state: contentState, staleDate: Calendar.current.date(byAdding: .minute, value: 30, to: Date())!) + + do { + FIFALiveActivity = try Activity.request( + attributes: attributes, + content: activityContent, + pushType: .token) + + Task { + for await data in FIFALiveActivity!.pushTokenUpdates { + let token = data.map {String(format: "%02x", $0)}.joined() + print("FIFA Live Activity Push Token::", token) + OneSignal.LiveActivities.enter(FIFALiveActivityId, withToken: token) + print("FIFA Live Activity Started") + } + } + } catch (let error) { + print(error.localizedDescription) + } + } + + func stopFIFALiveActivity() { + if FIFALiveActivity == nil { + return + } + + FIFALiveActivity = nil + OneSignal.LiveActivities.exit(FIFALiveActivityId) + print("FIFA Live Activity Stopped") + } + + @available(iOS 17.2, *) + func setupFIFALiveActivityPushToStart() { + Task { + for try await data in Activity.pushToStartTokenUpdates { + let token = data.map { String(format: "%02x", $0) }.joined() + OneSignal.LiveActivities.setPushToStartToken(FIFALiveActivityAttributes.self, withToken: token) + print("FIFA Live Activity pushToStart Token:: \(token)") + } + } + } +} diff --git a/OneSignal iOS Sample/OneSignal_iOS_SampleApp.swift b/OneSignal iOS Sample/OneSignal_iOS_SampleApp.swift index 2c02239..6e4eb9c 100644 --- a/OneSignal iOS Sample/OneSignal_iOS_SampleApp.swift +++ b/OneSignal iOS Sample/OneSignal_iOS_SampleApp.swift @@ -17,24 +17,58 @@ struct OneSignal_iOS_SampleApp: App { var body: some Scene { WindowGroup { OSControlBoardView() + .environmentObject(appDelegate.vm!) } } } -class AppDelegate: UIResponder, UIApplicationDelegate, OSInAppMessageLifecycleListener { +class AppDelegate: UIResponder, UIApplicationDelegate, OSInAppMessageLifecycleListener, OSNotificationPermissionObserver, OSUserStateObserver, OSPushSubscriptionObserver { + var vm: OSControlBoardViewModel? + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool { - OneSignal.Debug.setLogLevel(.LL_VERBOSE) +// OneSignal.Debug.setLogLevel(.LL_VERBOSE) OneSignal.initialize("202d4f61-1ca9-42df-9d36-bb17d8613abf", withLaunchOptions: launchOptions) - + + vm = OSControlBoardViewModel() +// Setup pushToStartToken if iOS version supports it if #available(iOS 17.2, *) { - Task { - for try await data in Activity.pushToStartTokenUpdates { - let token = data.map {String(format: "%02x", $0)}.joined() - OneSignal.LiveActivities.setPushToStartToken(LiveActivityAttributes.self, withToken: token) - } - } + vm?.setupFIFALiveActivityPushToStart() } + + OneSignal.Notifications.addPermissionObserver(self) + OneSignal.User.addObserver(self) + OneSignal.User.pushSubscription.addObserver(self) return true } + + func onNotificationPermissionDidChange(_ permission: Bool) { + print("#PUSH_PERMISSION_CHANGED") + print("Permission:: ", permission) + + DispatchQueue.main.async { + self.vm?.isPushEnabled = permission + } + } + + func onPushSubscriptionDidChange(state: OSPushSubscriptionChangedState) { + print("#PUSH_SUBSCRIPTION_CHANGED") + print("State:: ", state.jsonRepresentation()) + + DispatchQueue.main.async { + self.vm?.isSubscribed = state.current.optedIn + } + } + + func onUserStateDidChange(state: OneSignalUser.OSUserChangedState) { + print("#USER_CHANGED") + print("OneSignal ID:: ", state.current.onesignalId ?? "Unknown OneSignal ID") + print("External ID:: ", state.current.externalId ?? "Anonymous User") + print("State:: ", state.current.jsonRepresentation()) + + DispatchQueue.main.async { + self.vm?.isLoggedIn = state.current.externalId != nil + } + } + }