diff --git a/android/gradle.properties b/android/gradle.properties index ef8605fd..781b120d 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -3,4 +3,4 @@ Airship_minSdkVersion=21 Airship_targetSdkVersion=34 Airship_compileSdkVersion=34 Airship_ndkversion=26.1.10909125 -Airship_airshipProxyVersion=7.3.0 +Airship_airshipProxyVersion=8.3.0 diff --git a/android/src/main/java/com/urbanairship/reactnative/AirshipModule.kt b/android/src/main/java/com/urbanairship/reactnative/AirshipModule.kt index d140ca04..e333864f 100644 --- a/android/src/main/java/com/urbanairship/reactnative/AirshipModule.kt +++ b/android/src/main/java/com/urbanairship/reactnative/AirshipModule.kt @@ -1,5 +1,7 @@ package com.urbanairship.reactnative +import android.annotation.SuppressLint +import android.os.Build import com.facebook.react.bridge.* import com.facebook.react.modules.core.RCTNativeAppEventEmitter import com.urbanairship.PendingResult @@ -51,6 +53,7 @@ class AirshipModule internal constructor(val context: ReactApplicationContext) : } } + @SuppressLint("RestrictedApi") override fun initialize() { super.initialize() @@ -119,6 +122,7 @@ class AirshipModule internal constructor(val context: ReactApplicationContext) : } } + @SuppressLint("RestrictedApi") @ReactMethod override fun takePendingEvents(eventName: String?, isHeadlessJS: Boolean, promise: Promise) { promise.resolveResult { @@ -235,14 +239,14 @@ class AirshipModule internal constructor(val context: ReactApplicationContext) : @ReactMethod override fun pushEnableUserNotifications(promise: Promise) { - promise.resolvePending { + promise.resolveSuspending(scope) { proxy.push.enableUserPushNotifications() } } @ReactMethod override fun pushGetNotificationStatus(promise: Promise) { - promise.resolveResult { + promise.resolveSuspending(scope) { proxy.push.getNotificationStatus() } } @@ -340,8 +344,12 @@ class AirshipModule internal constructor(val context: ReactApplicationContext) : @ReactMethod override fun pushAndroidIsNotificationChannelEnabled(channel: String?, promise: Promise) { - promise.resolveResult { - proxy.push.isNotificationChannelEnabled(requireNotNull(channel)) + promise.resolveSuspending(scope) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + proxy.push.isNotificationChannelEnabled(requireNotNull(channel)) + } else { + true + } } } @@ -671,16 +679,9 @@ class AirshipModule internal constructor(val context: ReactApplicationContext) : @ReactMethod override fun featureFlagManagerFlag(flagName: String?, promise: Promise) { - promise.resolveDeferred { callback -> - scope.launch { - try { - requireNotNull(flagName) - val flag = proxy.featureFlagManager.flag(flagName) - callback(flag, null) - } catch (e: Exception) { - callback(null, e) - } - } + promise.resolveSuspending(scope) { + requireNotNull(flagName) + proxy.featureFlagManager.flag(flagName) } } @@ -692,6 +693,30 @@ class AirshipModule internal constructor(val context: ReactApplicationContext) : } } + override fun liveActivityList(request: ReadableMap?, promise: Promise) { + promise.resolveResult { + throw IllegalStateException("Not supported on Android") + } + } + + override fun liveActivityCreate(request: ReadableMap?, promise: Promise) { + promise.resolveResult { + throw IllegalStateException("Not supported on Android") + } + } + + override fun liveActivityUpdate(request: ReadableMap?, promise: Promise) { + promise.resolveResult { + throw IllegalStateException("Not supported on Android") + } + } + + override fun liveActivityEnd(request: ReadableMap?, promise: Promise) { + promise.resolveResult { + throw IllegalStateException("Not supported on Android") + } + } + private fun notifyPending() { if (context.hasActiveReactInstance()) { val appEventEmitter = context.getJSModule(RCTNativeAppEventEmitter::class.java) @@ -720,6 +745,30 @@ internal fun Promise.resolveResult(function: () -> Any?) { resolveDeferred { callback -> callback(function(), null) } } +internal fun Promise.resolveSuspending(scope: CoroutineScope, function: suspend () -> Any?) { + scope.launch { + try { + when (val result = function()) { + is Unit -> { + this@resolveSuspending.resolve(null) + } + is JsonSerializable -> { + this@resolveSuspending.resolve(result.toReactType()) + } + is Number -> { + this@resolveSuspending.resolve(result.toDouble()) + } + else -> { + this@resolveSuspending.resolve(result) + } + } + } catch (e: Exception) { + this@resolveSuspending.reject("AIRSHIP_ERROR", e) + } + } + +} + internal fun Promise.resolveDeferred(function: ((T?, Exception?) -> Unit) -> Unit) { try { function { result, error -> diff --git a/android/src/oldarch/java/com/urbanairship/reactnative/AirshipSpec.kt b/android/src/oldarch/java/com/urbanairship/reactnative/AirshipSpec.kt index 988e074e..cd8d914d 100644 --- a/android/src/oldarch/java/com/urbanairship/reactnative/AirshipSpec.kt +++ b/android/src/oldarch/java/com/urbanairship/reactnative/AirshipSpec.kt @@ -404,6 +404,22 @@ abstract class AirshipSpec internal constructor(context: ReactApplicationContext @ReactMethod @com.facebook.proguard.annotations.DoNotStrip abstract fun featureFlagManagerTrackInteraction(flag: ReadableMap?, promise: Promise) + + @ReactMethod + @com.facebook.proguard.annotations.DoNotStrip + abstract fun liveActivityList(request: ReadableMap?, promise: Promise) + + @ReactMethod + @com.facebook.proguard.annotations.DoNotStrip + abstract fun liveActivityCreate(request: ReadableMap?, promise: Promise) + + @ReactMethod + @com.facebook.proguard.annotations.DoNotStrip + abstract fun liveActivityUpdate(request: ReadableMap?, promise: Promise) + + @ReactMethod + @com.facebook.proguard.annotations.DoNotStrip + abstract fun liveActivityEnd(request: ReadableMap?, promise: Promise) } diff --git a/example/ios/AirshipExample.xcodeproj/project.pbxproj b/example/ios/AirshipExample.xcodeproj/project.pbxproj index 409f346c..53e5dea2 100644 --- a/example/ios/AirshipExample.xcodeproj/project.pbxproj +++ b/example/ios/AirshipExample.xcodeproj/project.pbxproj @@ -15,7 +15,15 @@ 30F67F752E2CC8EC2DD20B65 /* libPods-AirshipExampleNotificationServiceExtension.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D225AAD537A45E26F8E01F4 /* libPods-AirshipExampleNotificationServiceExtension.a */; }; 6E1F6ECD2BED7F6400CFC7A7 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E1F6ECC2BED7F6400CFC7A7 /* NotificationService.swift */; }; 6E1F6ED12BED7F6400CFC7A7 /* AirshipExampleNotificationServiceExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 6E1F6ECA2BED7F6400CFC7A7 /* AirshipExampleNotificationServiceExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - 6EC755922A4DE34400851ABB /* AirshipExtender.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EC755912A4DE34400851ABB /* AirshipExtender.swift */; }; + 6E3A029F2CA62A7100B0C5CF /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6E3A029E2CA62A7100B0C5CF /* WidgetKit.framework */; }; + 6E3A02A12CA62A7100B0C5CF /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6E3A02A02CA62A7100B0C5CF /* SwiftUI.framework */; }; + 6E3A02B22CA62A7400B0C5CF /* ExampleWidgetsExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 6E3A029D2CA62A7100B0C5CF /* ExampleWidgetsExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 6EC755922A4DE34400851ABB /* AirshipPluginExtender.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EC755912A4DE34400851ABB /* AirshipPluginExtender.swift */; }; + 6ED117C52CA7661200C41C56 /* ExampleWidgetsAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ED117C02CA7661100C41C56 /* ExampleWidgetsAttributes.swift */; }; + 6ED117C62CA7661200C41C56 /* ExampleWidgetsBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ED117C12CA7661100C41C56 /* ExampleWidgetsBundle.swift */; }; + 6ED117C72CA7661200C41C56 /* ExampleWidgetsLiveActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ED117C22CA7661100C41C56 /* ExampleWidgetsLiveActivity.swift */; }; + 6ED117C92CA7661200C41C56 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6ED117BF2CA7661100C41C56 /* Assets.xcassets */; }; + 6ED117CA2CA7663100C41C56 /* ExampleWidgetsAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ED117C02CA7661100C41C56 /* ExampleWidgetsAttributes.swift */; }; 7F2F1DABF8580D87B80F17E2 /* libPods-AirshipExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 863F8087D5417FA132545EAF /* libPods-AirshipExample.a */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; 9919EE652B23C58300A46BFE /* Fonts in Resources */ = {isa = PBXBuildFile; fileRef = 9919EE642B23C58300A46BFE /* Fonts */; }; @@ -36,6 +44,13 @@ remoteGlobalIDString = 6E1F6EC92BED7F6400CFC7A7; remoteInfo = AirshipExampleNotificationServiceExtension; }; + 6E3A02B02CA62A7400B0C5CF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6E3A029C2CA62A7100B0C5CF; + remoteInfo = ExampleWidgetsExtension; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -46,6 +61,7 @@ dstSubfolderSpec = 13; files = ( 6E1F6ED12BED7F6400CFC7A7 /* AirshipExampleNotificationServiceExtension.appex in Embed Foundation Extensions */, + 6E3A02B22CA62A7400B0C5CF /* ExampleWidgetsExtension.appex in Embed Foundation Extensions */, ); name = "Embed Foundation Extensions"; runOnlyForDeploymentPostprocessing = 0; @@ -69,10 +85,18 @@ 6E1F6ECA2BED7F6400CFC7A7 /* AirshipExampleNotificationServiceExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = AirshipExampleNotificationServiceExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 6E1F6ECC2BED7F6400CFC7A7 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; }; 6E1F6ECE2BED7F6400CFC7A7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6E3A029D2CA62A7100B0C5CF /* ExampleWidgetsExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = ExampleWidgetsExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 6E3A029E2CA62A7100B0C5CF /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; }; + 6E3A02A02CA62A7100B0C5CF /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; }; 6E4CFD1B29899AB400D131A8 /* AirshipExample.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = AirshipExample.entitlements; path = AirshipExample/AirshipExample.entitlements; sourceTree = ""; }; 6E69FDBD50BFBDB4EF69D730 /* Pods-AirshipExampleNotificationServiceExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirshipExampleNotificationServiceExtension.debug.xcconfig"; path = "Target Support Files/Pods-AirshipExampleNotificationServiceExtension/Pods-AirshipExampleNotificationServiceExtension.debug.xcconfig"; sourceTree = ""; }; 6EC755902A4DE34400851ABB /* AirshipExample-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AirshipExample-Bridging-Header.h"; sourceTree = ""; }; - 6EC755912A4DE34400851ABB /* AirshipExtender.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AirshipExtender.swift; sourceTree = ""; }; + 6EC755912A4DE34400851ABB /* AirshipPluginExtender.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AirshipPluginExtender.swift; sourceTree = ""; }; + 6ED117BF2CA7661100C41C56 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 6ED117C02CA7661100C41C56 /* ExampleWidgetsAttributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleWidgetsAttributes.swift; sourceTree = ""; }; + 6ED117C12CA7661100C41C56 /* ExampleWidgetsBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleWidgetsBundle.swift; sourceTree = ""; }; + 6ED117C22CA7661100C41C56 /* ExampleWidgetsLiveActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleWidgetsLiveActivity.swift; sourceTree = ""; }; + 6ED117C32CA7661100C41C56 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 7D225AAD537A45E26F8E01F4 /* libPods-AirshipExampleNotificationServiceExtension.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AirshipExampleNotificationServiceExtension.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = AirshipExample/LaunchScreen.storyboard; sourceTree = ""; }; 863F8087D5417FA132545EAF /* libPods-AirshipExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AirshipExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -109,6 +133,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 6E3A029A2CA62A7100B0C5CF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6E3A02A12CA62A7100B0C5CF /* SwiftUI.framework in Frameworks */, + 6E3A029F2CA62A7100B0C5CF /* WidgetKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -140,7 +173,7 @@ 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, 13B07FB71A68108700A75B9A /* main.m */, 9919EE642B23C58300A46BFE /* Fonts */, - 6EC755912A4DE34400851ABB /* AirshipExtender.swift */, + 6EC755912A4DE34400851ABB /* AirshipPluginExtender.swift */, 6EC755902A4DE34400851ABB /* AirshipExample-Bridging-Header.h */, ); name = AirshipExample; @@ -153,6 +186,8 @@ 863F8087D5417FA132545EAF /* libPods-AirshipExample.a */, 172EB030F35BD75FC2FBDF81 /* libPods-AirshipExample-AirshipExampleTests.a */, 7D225AAD537A45E26F8E01F4 /* libPods-AirshipExampleNotificationServiceExtension.a */, + 6E3A029E2CA62A7100B0C5CF /* WidgetKit.framework */, + 6E3A02A02CA62A7100B0C5CF /* SwiftUI.framework */, ); name = Frameworks; sourceTree = ""; @@ -166,6 +201,18 @@ path = AirshipExampleNotificationServiceExtension; sourceTree = ""; }; + 6E3A02A22CA62A7100B0C5CF /* ExampleWidgets */ = { + isa = PBXGroup; + children = ( + 6ED117BF2CA7661100C41C56 /* Assets.xcassets */, + 6ED117C02CA7661100C41C56 /* ExampleWidgetsAttributes.swift */, + 6ED117C12CA7661100C41C56 /* ExampleWidgetsBundle.swift */, + 6ED117C22CA7661100C41C56 /* ExampleWidgetsLiveActivity.swift */, + 6ED117C32CA7661100C41C56 /* Info.plist */, + ); + path = ExampleWidgets; + sourceTree = ""; + }; 832341AE1AAA6A7D00B99B32 /* Libraries */ = { isa = PBXGroup; children = ( @@ -180,6 +227,7 @@ 832341AE1AAA6A7D00B99B32 /* Libraries */, 00E356EF1AD99517003FC87E /* AirshipExampleTests */, 6E1F6ECB2BED7F6400CFC7A7 /* AirshipExampleNotificationServiceExtension */, + 6E3A02A22CA62A7100B0C5CF /* ExampleWidgets */, 83CBBA001A601CBA00E9B192 /* Products */, 2D16E6871FA4F8E400B85C8A /* Frameworks */, BBD78D7AC51CEA395F1C20DB /* Pods */, @@ -195,6 +243,7 @@ 13B07F961A680F5B00A75B9A /* AirshipExample.app */, 00E356EE1AD99517003FC87E /* AirshipExampleTests.xctest */, 6E1F6ECA2BED7F6400CFC7A7 /* AirshipExampleNotificationServiceExtension.appex */, + 6E3A029D2CA62A7100B0C5CF /* ExampleWidgetsExtension.appex */, ); name = Products; sourceTree = ""; @@ -255,6 +304,7 @@ ); dependencies = ( 6E1F6ED02BED7F6400CFC7A7 /* PBXTargetDependency */, + 6E3A02B12CA62A7400B0C5CF /* PBXTargetDependency */, ); name = AirshipExample; productName = AirshipExample; @@ -279,13 +329,30 @@ productReference = 6E1F6ECA2BED7F6400CFC7A7 /* AirshipExampleNotificationServiceExtension.appex */; productType = "com.apple.product-type.app-extension"; }; + 6E3A029C2CA62A7100B0C5CF /* ExampleWidgetsExtension */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6E3A02B62CA62A7400B0C5CF /* Build configuration list for PBXNativeTarget "ExampleWidgetsExtension" */; + buildPhases = ( + 6E3A02992CA62A7100B0C5CF /* Sources */, + 6E3A029A2CA62A7100B0C5CF /* Frameworks */, + 6E3A029B2CA62A7100B0C5CF /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ExampleWidgetsExtension; + productName = ExampleWidgetsExtension; + productReference = 6E3A029D2CA62A7100B0C5CF /* ExampleWidgetsExtension.appex */; + productType = "com.apple.product-type.app-extension"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 83CBB9F71A601CBA00E9B192 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1530; + LastSwiftUpdateCheck = 1600; LastUpgradeCheck = 1210; TargetAttributes = { 00E356ED1AD99517003FC87E = { @@ -298,6 +365,10 @@ 6E1F6EC92BED7F6400CFC7A7 = { CreatedOnToolsVersion = 15.3; }; + 6E3A029C2CA62A7100B0C5CF = { + CreatedOnToolsVersion = 16.0; + LastSwiftMigration = 1600; + }; }; }; buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "AirshipExample" */; @@ -316,6 +387,7 @@ 13B07F861A680F5B00A75B9A /* AirshipExample */, 00E356ED1AD99517003FC87E /* AirshipExampleTests */, 6E1F6EC92BED7F6400CFC7A7 /* AirshipExampleNotificationServiceExtension */, + 6E3A029C2CA62A7100B0C5CF /* ExampleWidgetsExtension */, ); }; /* End PBXProject section */ @@ -345,6 +417,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 6E3A029B2CA62A7100B0C5CF /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6ED117C92CA7661200C41C56 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ @@ -514,8 +594,9 @@ buildActionMask = 2147483647; files = ( 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */, - 6EC755922A4DE34400851ABB /* AirshipExtender.swift in Sources */, + 6EC755922A4DE34400851ABB /* AirshipPluginExtender.swift in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, + 6ED117CA2CA7663100C41C56 /* ExampleWidgetsAttributes.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -527,6 +608,16 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 6E3A02992CA62A7100B0C5CF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6ED117C52CA7661200C41C56 /* ExampleWidgetsAttributes.swift in Sources */, + 6ED117C62CA7661200C41C56 /* ExampleWidgetsBundle.swift in Sources */, + 6ED117C72CA7661200C41C56 /* ExampleWidgetsLiveActivity.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -540,6 +631,11 @@ target = 6E1F6EC92BED7F6400CFC7A7 /* AirshipExampleNotificationServiceExtension */; targetProxy = 6E1F6ECF2BED7F6400CFC7A7 /* PBXContainerItemProxy */; }; + 6E3A02B12CA62A7400B0C5CF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 6E3A029C2CA62A7100B0C5CF /* ExampleWidgetsExtension */; + targetProxy = 6E3A02B02CA62A7400B0C5CF /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -741,6 +837,93 @@ }; name = Release; }; + 6E3A02B32CA62A7400B0C5CF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = PGJV57GD94; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = ExampleWidgets/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = ExampleWidgets; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 18.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.urbanairship.richpush.ExampleWidgets; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 6E3A02B42CA62A7400B0C5CF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = PGJV57GD94; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = ExampleWidgets/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = ExampleWidgets; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 18.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.urbanairship.richpush.ExampleWidgets; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; 83CBBA201A601CBA00E9B192 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -922,6 +1105,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 6E3A02B62CA62A7400B0C5CF /* Build configuration list for PBXNativeTarget "ExampleWidgetsExtension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6E3A02B32CA62A7400B0C5CF /* Debug */, + 6E3A02B42CA62A7400B0C5CF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "AirshipExample" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/example/ios/AirshipExample.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/AirshipExample.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/example/ios/AirshipExample.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,5 @@ + + + + + diff --git a/example/ios/AirshipExample/AppDelegate.mm b/example/ios/AirshipExample/AppDelegate.mm index db75d773..c2faf6a0 100644 --- a/example/ios/AirshipExample/AppDelegate.mm +++ b/example/ios/AirshipExample/AppDelegate.mm @@ -1,28 +1,15 @@ #import "AppDelegate.h" #import -#import "AirshipExample-Swift.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - [AirshipExtender setup]; - self.moduleName = @"AirshipExample"; // You can add your custom initial props in the dictionary below. // They will be passed down to the ViewController used by React Native. self.initialProps = @{}; - - for (NSString* family in [UIFont familyNames]) - { - NSLog(@"%@", family); - - for (NSString* name in [UIFont fontNamesForFamilyName: family]) - { - NSLog(@"Family name: %@", name); - } - } return [super application:application didFinishLaunchingWithOptions:launchOptions]; } diff --git a/example/ios/AirshipExample/Info.plist b/example/ios/AirshipExample/Info.plist index d1058c2a..a8f63677 100644 --- a/example/ios/AirshipExample/Info.plist +++ b/example/ios/AirshipExample/Info.plist @@ -26,11 +26,10 @@ NSAppTransportSecurity - - NSAllowsArbitraryLoads - - NSAllowsLocalNetworking - + NSAllowsArbitraryLoads + + NSAllowsLocalNetworking + NSLocationWhenInUseUsageDescription @@ -56,5 +55,7 @@ Fonts/MaterialIcons.ttf + NSSupportsLiveActivities + diff --git a/example/ios/AirshipExtender.swift b/example/ios/AirshipExtender.swift deleted file mode 100644 index 0dedb828..00000000 --- a/example/ios/AirshipExtender.swift +++ /dev/null @@ -1,29 +0,0 @@ -import Foundation -import AirshipKit - - -@objc -public class AirshipExtender: NSObject { - - fileprivate static let shared: AirshipExtender = AirshipExtender() - - - @objc - @MainActor - public class func setup() { - if (Airship.isFlying) { - self.shared.airshipReady() - } else { - NotificationCenter.default.addObserver(forName: AirshipNotifications.AirshipReady.name, object: nil, queue: nil) { _ in - Task { @MainActor in - self.shared.airshipReady() - } - } - } - } - - @MainActor - private func airshipReady() { - // Make restore call here - } -} diff --git a/example/ios/AirshipPluginExtender.swift b/example/ios/AirshipPluginExtender.swift new file mode 100644 index 00000000..95f9c5f2 --- /dev/null +++ b/example/ios/AirshipPluginExtender.swift @@ -0,0 +1,22 @@ +import Foundation +import AirshipKit +import AirshipFrameworkProxy +import ActivityKit + +@objc(AirshipPluginExtender) +public class AirshipPluginExtender: NSObject, AirshipPluginExtenderProtocol { + public static func onAirshipReady() { + + if #available(iOS 16.1, *) { + // Will throw if called more than once + try? LiveActivityManager.shared.setup { configurator in + + // Call per widget + await configurator.register(forType: Activity.self) { attributes in + // Track this property as the Airship name for updates + attributes.name + } + } + } + } +} diff --git a/example/ios/ExampleWidgets/AppIntent.swift b/example/ios/ExampleWidgets/AppIntent.swift new file mode 100644 index 00000000..2175923c --- /dev/null +++ b/example/ios/ExampleWidgets/AppIntent.swift @@ -0,0 +1,18 @@ +// +// AppIntent.swift +// ExampleWidgets +// +// Created by Ryan Lepinski on 9/26/24. +// + +import WidgetKit +import AppIntents + +struct ConfigurationAppIntent: WidgetConfigurationIntent { + static var title: LocalizedStringResource { "Configuration" } + static var description: IntentDescription { "This is an example widget." } + + // An example configurable parameter. + @Parameter(title: "Favorite Emoji", default: "😃") + var favoriteEmoji: String +} diff --git a/example/ios/ExampleWidgets/Assets.xcassets/AccentColor.colorset/Contents.json b/example/ios/ExampleWidgets/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/example/ios/ExampleWidgets/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/example/ios/ExampleWidgets/Assets.xcassets/AppIcon.appiconset/Contents.json b/example/ios/ExampleWidgets/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..23058801 --- /dev/null +++ b/example/ios/ExampleWidgets/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,35 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/example/ios/ExampleWidgets/Assets.xcassets/Contents.json b/example/ios/ExampleWidgets/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/example/ios/ExampleWidgets/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/example/ios/ExampleWidgets/Assets.xcassets/WidgetBackground.colorset/Contents.json b/example/ios/ExampleWidgets/Assets.xcassets/WidgetBackground.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/example/ios/ExampleWidgets/Assets.xcassets/WidgetBackground.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/example/ios/ExampleWidgets/ExampleWidgetsAttributes.swift b/example/ios/ExampleWidgets/ExampleWidgetsAttributes.swift new file mode 100644 index 00000000..bebdbc93 --- /dev/null +++ b/example/ios/ExampleWidgets/ExampleWidgetsAttributes.swift @@ -0,0 +1,16 @@ +// +// ExampleWidgetsAttributes.swift +// AirshipExample +// + +import ActivityKit + +struct ExampleWidgetsAttributes: ActivityAttributes { + public struct ContentState: Codable, Hashable { + // Dynamic stateful properties about your activity go here! + var emoji: String + } + + // Fixed non-changing properties about your activity go here! + var name: String +} diff --git a/example/ios/ExampleWidgets/ExampleWidgetsBundle.swift b/example/ios/ExampleWidgets/ExampleWidgetsBundle.swift new file mode 100644 index 00000000..1c9ab05e --- /dev/null +++ b/example/ios/ExampleWidgets/ExampleWidgetsBundle.swift @@ -0,0 +1,14 @@ +// +// ExampleWidgetsBundle.swift +// ExampleWidgets +// + +import WidgetKit +import SwiftUI + +@main +struct ExampleWidgetsBundle: WidgetBundle { + var body: some Widget { + ExampleWidgetsLiveActivity() + } +} diff --git a/example/ios/ExampleWidgets/ExampleWidgetsLiveActivity.swift b/example/ios/ExampleWidgets/ExampleWidgetsLiveActivity.swift new file mode 100644 index 00000000..acf1ecee --- /dev/null +++ b/example/ios/ExampleWidgets/ExampleWidgetsLiveActivity.swift @@ -0,0 +1,69 @@ +// +// ExampleWidgetsLiveActivity.swift +// ExampleWidgets +// + +import ActivityKit +import WidgetKit +import SwiftUI + + +struct ExampleWidgetsLiveActivity: Widget { + var body: some WidgetConfiguration { + ActivityConfiguration(for: ExampleWidgetsAttributes.self) { context in + // Lock screen/banner UI goes here + VStack { + Text("Hello \(context.state.emoji)") + } + .activityBackgroundTint(Color.cyan) + .activitySystemActionForegroundColor(Color.black) + + } dynamicIsland: { context in + DynamicIsland { + // Expanded UI goes here. Compose the expanded UI through + // various regions, like leading/trailing/center/bottom + DynamicIslandExpandedRegion(.leading) { + Text("Leading") + } + DynamicIslandExpandedRegion(.trailing) { + Text("Trailing") + } + DynamicIslandExpandedRegion(.bottom) { + Text("Bottom \(context.state.emoji)") + // more content + } + } compactLeading: { + Text("L") + } compactTrailing: { + Text("T \(context.state.emoji)") + } minimal: { + Text(context.state.emoji) + } + .widgetURL(URL(string: "http://www.apple.com")) + .keylineTint(Color.red) + } + } +} + +extension ExampleWidgetsAttributes { + fileprivate static var preview: ExampleWidgetsAttributes { + ExampleWidgetsAttributes(name: "World") + } +} + +extension ExampleWidgetsAttributes.ContentState { + fileprivate static var smiley: ExampleWidgetsAttributes.ContentState { + ExampleWidgetsAttributes.ContentState(emoji: "😀") + } + + fileprivate static var starEyes: ExampleWidgetsAttributes.ContentState { + ExampleWidgetsAttributes.ContentState(emoji: "🤩") + } +} + +#Preview("Notification", as: .content, using: ExampleWidgetsAttributes.preview) { + ExampleWidgetsLiveActivity() +} contentStates: { + ExampleWidgetsAttributes.ContentState.smiley + ExampleWidgetsAttributes.ContentState.starEyes +} diff --git a/example/ios/ExampleWidgets/Info.plist b/example/ios/ExampleWidgets/Info.plist new file mode 100644 index 00000000..0f118fb7 --- /dev/null +++ b/example/ios/ExampleWidgets/Info.plist @@ -0,0 +1,11 @@ + + + + + NSExtension + + NSExtensionPointIdentifier + com.apple.widgetkit-extension + + + diff --git a/example/ios/Podfile b/example/ios/Podfile index 422d3bf3..8918d455 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -30,6 +30,7 @@ end target 'AirshipExample' do config = use_native_modules! + use_react_native!( :path => config[:reactNativePath], # Enables Flipper. @@ -45,7 +46,7 @@ target 'AirshipExample' do inherit! :complete # Pods for testing end - + post_install do |installer| # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 react_native_post_install( diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 950ef371..203fd248 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,25 +1,25 @@ PODS: - - Airship (18.7.2): - - Airship/Automation (= 18.7.2) - - Airship/Basement (= 18.7.2) - - Airship/Core (= 18.7.2) - - Airship/FeatureFlags (= 18.7.2) - - Airship/MessageCenter (= 18.7.2) - - Airship/PreferenceCenter (= 18.7.2) - - Airship/Automation (18.7.2): + - Airship (18.9.2): + - Airship/Automation (= 18.9.2) + - Airship/Basement (= 18.9.2) + - Airship/Core (= 18.9.2) + - Airship/FeatureFlags (= 18.9.2) + - Airship/MessageCenter (= 18.9.2) + - Airship/PreferenceCenter (= 18.9.2) + - Airship/Automation (18.9.2): - Airship/Core - - Airship/Basement (18.7.2) - - Airship/Core (18.7.2): + - Airship/Basement (18.9.2) + - Airship/Core (18.9.2): - Airship/Basement - - Airship/FeatureFlags (18.7.2): + - Airship/FeatureFlags (18.9.2): - Airship/Core - - Airship/MessageCenter (18.7.2): + - Airship/MessageCenter (18.9.2): - Airship/Core - - Airship/PreferenceCenter (18.7.2): + - Airship/PreferenceCenter (18.9.2): - Airship/Core - - AirshipFrameworkProxy (7.3.0): - - Airship (= 18.7.2) - - AirshipServiceExtension (18.7.2) + - AirshipFrameworkProxy (8.3.0): + - Airship (= 18.9.2) + - AirshipServiceExtension (18.9.2) - boost (1.83.0) - DoubleConversion (1.1.6) - FBLazyVector (0.73.4) @@ -908,7 +908,7 @@ PODS: - glog - React-debug - react-native-airship (19.3.2): - - AirshipFrameworkProxy (= 7.3.0) + - AirshipFrameworkProxy (= 8.3.0) - glog - RCT-Folly (= 2022.05.16.00) - React-Core @@ -1279,9 +1279,9 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/yoga" SPEC CHECKSUMS: - Airship: bb32ff2c5a811352da074480357d9f02dbb8f327 - AirshipFrameworkProxy: 88a5e374efb5841e8cd84e63983c1ded123fe073 - AirshipServiceExtension: 9c73369f426396d9fb9ff222d86d842fac76ba46 + Airship: 7f891aa9bb142d02f35aaef5ebdb09c2b5730a6d + AirshipFrameworkProxy: 48208d21ca1376d9bc111efd31981af84bfcf8f3 + AirshipServiceExtension: 0ed795b521a76f8391e13896fbe1dee6ce9196ca boost: d3f49c53809116a5d38da093a8aa78bf551aed09 DoubleConversion: fea03f2699887d960129cc54bba7e52542b6f953 FBLazyVector: 84f6edbe225f38aebd9deaf1540a4160b1f087d7 @@ -1311,7 +1311,7 @@ SPEC CHECKSUMS: React-jsinspector: 9ac353eccf6ab54d1e0a33862ba91221d1e88460 React-logger: 0a57b68dd2aec7ff738195f081f0520724b35dab React-Mapbuffer: 63913773ed7f96b814a2521e13e6d010282096ad - react-native-airship: 3bfdf6a727ac0c6d5d0c1fdfc7ffb771701a679b + react-native-airship: c68835c32f7b5a100b25bf5f2ecc6e4fae6ddce4 react-native-safe-area-context: b97eb6f9e3b7f437806c2ce5983f479f8eb5de4b React-nativeconfig: d7af5bae6da70fa15ce44f045621cf99ed24087c React-NativeModulesApple: 0123905d5699853ac68519607555a9a4f5c7b3ac @@ -1340,6 +1340,6 @@ SPEC CHECKSUMS: SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 Yoga: 1b901a6d6eeba4e8a2e8f308f708691cdb5db312 -PODFILE CHECKSUM: dbd88b0cf2e018eeff600431486ded3ce68933fb +PODFILE CHECKSUM: 71939b1c0f451ff75f31df2f5e51d1c63f04150d COCOAPODS: 1.15.2 diff --git a/example/src/App.tsx b/example/src/App.tsx index d31cf057..0d00bff7 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -17,6 +17,10 @@ Airship.addListener(EventType.NotificationResponse, (event) => { console.log('NotificationResponse:', JSON.stringify(event)); }); +Airship.addListener(EventType.IOSLiveActivitiesUpdated, (event) => { + console.log('IOSLiveActivitiesUpdated:', JSON.stringify(event)); +}); + Airship.addListener(EventType.PushReceived, (event) => { console.log('PushReceived:', JSON.stringify(event)); }); diff --git a/example/src/screens/HomeScreen.tsx b/example/src/screens/HomeScreen.tsx index 4e3ddec3..835cf737 100644 --- a/example/src/screens/HomeScreen.tsx +++ b/example/src/screens/HomeScreen.tsx @@ -12,9 +12,13 @@ import { Image, KeyboardAvoidingView, Platform, - TouchableOpacity + TouchableOpacity, + Button, } from 'react-native'; -import Airship, { EventType, AirshipEmbeddedView} from '@ua/react-native-airship'; +import Airship, { + EventType, + AirshipEmbeddedView, +} from '@ua/react-native-airship'; import styles from '../Styles'; import NamedUserManagerCell from './Home Elements/NamedUserManagerCell'; @@ -46,7 +50,7 @@ export default function HomeScreen() { const [tags, setTags] = useState([]); const [tagText, setTagText] = useState(''); const [notificationsEnabled, setNotificationsEnabled] = useState(false); - const [isEmbeddedReady, setEmbeddedReady] = useState(false) + const [isEmbeddedReady, setEmbeddedReady] = useState(false); const refreshTags = useCallback(async () => { const fetchedTags = await Airship.channel.getTags(); @@ -84,7 +88,6 @@ export default function HomeScreen() { }, []); useEffect(() => { - // Add takeOff here Airship.push @@ -96,7 +99,7 @@ export default function HomeScreen() { console.error('Error getting notification status:', error); }); - setEmbeddedReady(Airship.inApp.isEmbeddedReady("test")) + setEmbeddedReady(Airship.inApp.isEmbeddedReady('test')); Airship.push.iOS .getAuthorizedNotificationSettings() @@ -144,9 +147,9 @@ export default function HomeScreen() { } ); - Airship.inApp.addEmbeddedReadyListener("test", (isReady) => { - console.log("Test " + isReady) - setEmbeddedReady(isReady) + Airship.inApp.addEmbeddedReadyListener('test', (isReady) => { + console.log('Test ' + isReady); + setEmbeddedReady(isReady); }); return () => { @@ -161,32 +164,87 @@ export default function HomeScreen() { keyboardVerticalOffset={Platform.OS === 'ios' ? 200 : 0} > + {isEmbeddedReady ? ( + + + + ) : ( + + + + )} - - {isEmbeddedReady ? - ( - - - - ) - : ( - - - )} - + {Platform.OS === 'ios' ? ( + +