@wscsports/blaze-rtn-sdk 0.1.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/android/build.gradle +11 -10
  2. package/android/src/main/java/com/blaze/rtnblazesdk/BlazeMomentsGridViewManager.kt +16 -8
  3. package/android/src/main/java/com/blaze/rtnblazesdk/BlazeMomentsRowViewManager.kt +16 -8
  4. package/android/src/main/java/com/blaze/rtnblazesdk/BlazeSdkModule.kt +4 -0
  5. package/android/src/main/java/com/blaze/rtnblazesdk/BlazeSdkModuleImp.kt +57 -30
  6. package/android/src/main/java/com/blaze/rtnblazesdk/BlazeStoriesGridViewManager.kt +18 -0
  7. package/android/src/main/java/com/blaze/rtnblazesdk/BlazeStoriesRowViewManager.kt +19 -9
  8. package/android/src/main/java/com/blaze/rtnblazesdk/NativeBlazeSdkSpec.java +4 -0
  9. package/android/src/main/java/com/blaze/rtnblazesdk/base/BaseViewManager.kt +23 -5
  10. package/android/src/main/java/com/blaze/rtnblazesdk/base/BaseWidgetView.kt +18 -19
  11. package/android/src/main/java/com/blaze/rtnblazesdk/customization/BlazeColorParser.kt +43 -0
  12. package/android/src/main/java/com/blaze/rtnblazesdk/customization/BlazeReactCommonMerger.kt +1 -1
  13. package/android/src/main/java/com/blaze/rtnblazesdk/customization/BlazeReactMomentThemeMerger.kt +12 -0
  14. package/android/src/main/java/com/blaze/rtnblazesdk/customization/BlazeReactStoriesThemeMerger.kt +26 -0
  15. package/android/src/main/java/com/blaze/rtnblazesdk/customization/BlazeReactWidgetMomentTheme.kt +11 -4
  16. package/android/src/main/java/com/blaze/rtnblazesdk/customization/BlazeReactWidgetStoriesTheme.kt +26 -13
  17. package/android/src/main/java/com/blaze/rtnblazesdk/events/WidgetCTAClickEvent.kt +5 -3
  18. package/android/src/main/java/com/blaze/rtnblazesdk/events/WidgetDataLoadCompletedEvent.kt +21 -6
  19. package/android/src/main/java/com/blaze/rtnblazesdk/events/WidgetDataLoadStartedEvent.kt +12 -5
  20. package/android/src/main/java/com/blaze/rtnblazesdk/events/WidgetItemClickedEvent.kt +14 -5
  21. package/android/src/main/java/com/blaze/rtnblazesdk/events/WidgetPlayerDismissedEvent.kt +9 -4
  22. package/android/src/main/java/com/blaze/rtnblazesdk/moments/BlazeMomentsGridView.kt +29 -8
  23. package/android/src/main/java/com/blaze/rtnblazesdk/moments/BlazeMomentsRowView.kt +30 -8
  24. package/android/src/main/java/com/blaze/rtnblazesdk/stories/BlazeStoriesGridView.kt +29 -8
  25. package/android/src/main/java/com/blaze/rtnblazesdk/stories/BlazeStoriesRowView.kt +29 -8
  26. package/blaze-rtn-sdk.podspec +1 -1
  27. package/ios/Sources/BlazeMomentsGridWidgetManager/BlazeMomentsGridWidgetManager.swift +20 -1
  28. package/ios/Sources/BlazeMomentsRowWidgetManager/BlazeMomentsRowWidgetManager.swift +19 -0
  29. package/ios/Sources/BlazeNativeSDKModule/BlazeNativeSDKModule.m +4 -0
  30. package/ios/Sources/BlazeNativeSDKModule/BlazeNativeSDKModule.swift +65 -27
  31. package/ios/Sources/BlazeStoriesGridWidgetManager/BlazeStoriesGridWidgetManager.swift +20 -0
  32. package/ios/Sources/BlazeStoriesRowWidgetManager/BlazeStoriesRowWidgetManager.swift +19 -0
  33. package/ios/Sources/LayoutCustomization/BlazeReactLayoutMerger.swift +78 -6
  34. package/ios/Sources/LayoutCustomization/BlazeReactWidgetLayout.swift +43 -9
  35. package/ios/Sources/Utils/UIColor+Extensions.swift +28 -22
  36. package/ios/Sources/Widgets/Base/BlazeWidgetBase.swift +49 -14
  37. package/ios/Sources/Widgets/Base/BlazeWidgetViewManagerBase.m +9 -4
  38. package/ios/Sources/Widgets/BlazeMomentsGridWidget.swift +1 -1
  39. package/ios/Sources/Widgets/BlazeMomentsRowWidget.swift +1 -1
  40. package/ios/Sources/Widgets/BlazeStoriesGridWidget.swift +1 -1
  41. package/ios/Sources/Widgets/BlazeStoriesRowWidget.swift +1 -1
  42. package/lib/commonjs/BlazeMomentsGridViewNativeComponent.js +59 -0
  43. package/lib/commonjs/BlazeMomentsGridViewNativeComponent.js.map +1 -0
  44. package/lib/commonjs/BlazeMomentsRowViewNativeComponent.js +59 -0
  45. package/lib/commonjs/BlazeMomentsRowViewNativeComponent.js.map +1 -0
  46. package/lib/commonjs/BlazeStoriesGridViewNativeComponent.js +59 -0
  47. package/lib/commonjs/BlazeStoriesGridViewNativeComponent.js.map +1 -0
  48. package/lib/commonjs/BlazeStoriesRowViewNativeComponent.js +59 -0
  49. package/lib/commonjs/BlazeStoriesRowViewNativeComponent.js.map +1 -0
  50. package/lib/commonjs/NativeBlazeSdk.js +49 -0
  51. package/lib/commonjs/NativeBlazeSdk.js.map +1 -0
  52. package/lib/commonjs/classes/blaze-widget-label.js +36 -0
  53. package/lib/commonjs/classes/blaze-widget-label.js.map +1 -0
  54. package/lib/commonjs/constants/widgets-constants.js +11 -0
  55. package/lib/commonjs/constants/widgets-constants.js.map +1 -0
  56. package/lib/commonjs/index.js +57 -0
  57. package/lib/commonjs/index.js.map +1 -0
  58. package/lib/commonjs/interfaces/actions-options.interface.js +2 -0
  59. package/lib/commonjs/interfaces/actions-options.interface.js.map +1 -0
  60. package/lib/commonjs/interfaces/blaze-analytics.interface.js +91 -0
  61. package/lib/commonjs/interfaces/blaze-analytics.interface.js.map +1 -0
  62. package/lib/commonjs/interfaces/blaze-result.interface.js +25 -0
  63. package/lib/commonjs/interfaces/blaze-result.interface.js.map +1 -0
  64. package/lib/commonjs/interfaces/common.interface.js +6 -0
  65. package/lib/commonjs/interfaces/common.interface.js.map +1 -0
  66. package/lib/commonjs/interfaces/index.js +105 -0
  67. package/lib/commonjs/interfaces/index.js.map +1 -0
  68. package/lib/commonjs/interfaces/init-options.interface.js +14 -0
  69. package/lib/commonjs/interfaces/init-options.interface.js.map +1 -0
  70. package/lib/commonjs/interfaces/widget-layout.interface.js +6 -0
  71. package/lib/commonjs/interfaces/widget-layout.interface.js.map +1 -0
  72. package/lib/commonjs/interfaces/widget-moment-theme.interface.js +6 -0
  73. package/lib/commonjs/interfaces/widget-moment-theme.interface.js.map +1 -0
  74. package/lib/commonjs/interfaces/widget-story-theme.interface.js +6 -0
  75. package/lib/commonjs/interfaces/widget-story-theme.interface.js.map +1 -0
  76. package/lib/commonjs/interfaces/widgets-props.interface.js +6 -0
  77. package/lib/commonjs/interfaces/widgets-props.interface.js.map +1 -0
  78. package/lib/commonjs/utils/viewComponents.util.js +20 -0
  79. package/lib/commonjs/utils/viewComponents.util.js.map +1 -0
  80. package/lib/module/BlazeMomentsGridViewNativeComponent.js +50 -0
  81. package/lib/module/BlazeMomentsGridViewNativeComponent.js.map +1 -0
  82. package/lib/module/BlazeMomentsRowViewNativeComponent.js +50 -0
  83. package/lib/module/BlazeMomentsRowViewNativeComponent.js.map +1 -0
  84. package/lib/module/BlazeStoriesGridViewNativeComponent.js +50 -0
  85. package/lib/module/BlazeStoriesGridViewNativeComponent.js.map +1 -0
  86. package/lib/module/BlazeStoriesRowViewNativeComponent.js +50 -0
  87. package/lib/module/BlazeStoriesRowViewNativeComponent.js.map +1 -0
  88. package/lib/module/NativeBlazeSdk.js +42 -0
  89. package/lib/module/NativeBlazeSdk.js.map +1 -0
  90. package/lib/module/classes/blaze-widget-label.js +29 -0
  91. package/lib/module/classes/blaze-widget-label.js.map +1 -0
  92. package/lib/module/constants/widgets-constants.js +5 -0
  93. package/lib/module/constants/widgets-constants.js.map +1 -0
  94. package/lib/module/index.js +10 -0
  95. package/lib/module/index.js.map +1 -0
  96. package/lib/module/interfaces/actions-options.interface.js +2 -0
  97. package/lib/module/interfaces/actions-options.interface.js.map +1 -0
  98. package/lib/module/interfaces/blaze-analytics.interface.js +85 -0
  99. package/lib/module/interfaces/blaze-analytics.interface.js.map +1 -0
  100. package/lib/module/interfaces/blaze-result.interface.js +23 -0
  101. package/lib/module/interfaces/blaze-result.interface.js.map +1 -0
  102. package/lib/module/interfaces/common.interface.js +2 -0
  103. package/lib/module/interfaces/common.interface.js.map +1 -0
  104. package/lib/module/interfaces/index.js +10 -0
  105. package/lib/module/interfaces/index.js.map +1 -0
  106. package/lib/module/interfaces/init-options.interface.js +8 -0
  107. package/lib/module/interfaces/init-options.interface.js.map +1 -0
  108. package/lib/module/interfaces/widget-layout.interface.js +2 -0
  109. package/lib/module/interfaces/widget-layout.interface.js.map +1 -0
  110. package/lib/module/interfaces/widget-moment-theme.interface.js +2 -0
  111. package/lib/module/interfaces/widget-moment-theme.interface.js.map +1 -0
  112. package/lib/module/interfaces/widget-story-theme.interface.js +2 -0
  113. package/lib/module/interfaces/widget-story-theme.interface.js.map +1 -0
  114. package/lib/module/interfaces/widgets-props.interface.js +2 -0
  115. package/lib/module/interfaces/widgets-props.interface.js.map +1 -0
  116. package/lib/module/utils/viewComponents.util.js +12 -0
  117. package/lib/module/utils/viewComponents.util.js.map +1 -0
  118. package/lib/typescript/BlazeMomentsGridViewNativeComponent.d.ts +29 -0
  119. package/lib/typescript/BlazeMomentsGridViewNativeComponent.d.ts.map +1 -0
  120. package/lib/typescript/BlazeMomentsRowViewNativeComponent.d.ts +28 -0
  121. package/lib/typescript/BlazeMomentsRowViewNativeComponent.d.ts.map +1 -0
  122. package/lib/typescript/BlazeStoriesGridViewNativeComponent.d.ts +29 -0
  123. package/lib/typescript/BlazeStoriesGridViewNativeComponent.d.ts.map +1 -0
  124. package/lib/typescript/BlazeStoriesRowViewNativeComponent.d.ts +28 -0
  125. package/lib/typescript/BlazeStoriesRowViewNativeComponent.d.ts.map +1 -0
  126. package/lib/typescript/NativeBlazeSdk.d.ts +30 -0
  127. package/lib/typescript/NativeBlazeSdk.d.ts.map +1 -0
  128. package/lib/typescript/classes/blaze-widget-label.d.ts +11 -0
  129. package/lib/typescript/classes/blaze-widget-label.d.ts.map +1 -0
  130. package/lib/typescript/constants/widgets-constants.d.ts +5 -0
  131. package/lib/typescript/constants/widgets-constants.d.ts.map +1 -0
  132. package/lib/typescript/index.d.ts +11 -0
  133. package/lib/typescript/index.d.ts.map +1 -0
  134. package/lib/typescript/interfaces/actions-options.interface.d.ts +8 -0
  135. package/lib/typescript/interfaces/actions-options.interface.d.ts.map +1 -0
  136. package/lib/typescript/interfaces/blaze-analytics.interface.d.ts +174 -0
  137. package/lib/typescript/interfaces/blaze-analytics.interface.d.ts.map +1 -0
  138. package/lib/typescript/interfaces/blaze-result.interface.d.ts +30 -0
  139. package/lib/typescript/interfaces/blaze-result.interface.d.ts.map +1 -0
  140. package/lib/typescript/interfaces/common.interface.d.ts +54 -0
  141. package/lib/typescript/interfaces/common.interface.d.ts.map +1 -0
  142. package/lib/typescript/interfaces/index.d.ts +10 -0
  143. package/lib/typescript/interfaces/index.d.ts.map +1 -0
  144. package/lib/typescript/interfaces/init-options.interface.d.ts +14 -0
  145. package/lib/typescript/interfaces/init-options.interface.d.ts.map +1 -0
  146. package/lib/typescript/interfaces/widget-layout.interface.d.ts +115 -0
  147. package/lib/typescript/interfaces/widget-layout.interface.d.ts.map +1 -0
  148. package/lib/typescript/interfaces/widget-moment-theme.interface.d.ts +70 -0
  149. package/lib/typescript/interfaces/widget-moment-theme.interface.d.ts.map +1 -0
  150. package/lib/typescript/interfaces/widget-story-theme.interface.d.ts +80 -0
  151. package/lib/typescript/interfaces/widget-story-theme.interface.d.ts.map +1 -0
  152. package/lib/typescript/interfaces/widgets-props.interface.d.ts +38 -0
  153. package/lib/typescript/interfaces/widgets-props.interface.d.ts.map +1 -0
  154. package/lib/typescript/utils/viewComponents.util.d.ts +4 -0
  155. package/lib/typescript/utils/viewComponents.util.d.ts.map +1 -0
  156. package/package.json +36 -12
  157. package/src/BlazeMomentsGridViewNativeComponent.tsx +110 -23
  158. package/src/BlazeMomentsRowViewNativeComponent.tsx +110 -23
  159. package/src/BlazeStoriesGridViewNativeComponent.tsx +110 -23
  160. package/src/BlazeStoriesRowViewNativeComponent.tsx +110 -22
  161. package/src/NativeBlazeSdk.tsx +58 -36
  162. package/src/constants/widgets-constants.tsx +4 -0
  163. package/src/index.tsx +33 -0
  164. package/src/interfaces/actions-options.interface.tsx +8 -0
  165. package/src/interfaces/blaze-analytics.interface.tsx +202 -0
  166. package/src/interfaces/common.interface.tsx +81 -0
  167. package/src/interfaces/index.tsx +10 -0
  168. package/src/interfaces/init-options.interface.tsx +14 -0
  169. package/src/interfaces/{widget-layout.interface.ts → widget-layout.interface.tsx} +3 -13
  170. package/src/interfaces/{widget-moment-theme.interface.ts → widget-moment-theme.interface.tsx} +26 -28
  171. package/src/interfaces/{widget-story-theme.interface.ts → widget-story-theme.interface.tsx} +23 -39
  172. package/src/interfaces/widgets-props.interface.tsx +46 -0
  173. package/src/utils/viewComponents.util.tsx +31 -0
  174. package/index.js +0 -7
  175. package/src/interfaces/common.interface.ts +0 -45
  176. package/src/interfaces/index.ts +0 -4
  177. package/src/interfaces/init-options.interface.ts +0 -3
  178. package/src/interfaces/widgets-props.interface.ts +0 -19
  179. /package/src/classes/{blaze-widget-label.ts → blaze-widget-label.tsx} +0 -0
  180. /package/src/interfaces/{blaze-result.interface.ts → blaze-result.interface.tsx} +0 -0
@@ -5,7 +5,7 @@ buildscript {
5
5
  rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
6
6
  }
7
7
 
8
- ext.kotlinVersion = "1.9.10"
8
+ ext.blaze_kotlin_version = safeExtGet('kotlinVersion', '1.7.20')
9
9
 
10
10
  repositories {
11
11
  google()
@@ -13,16 +13,16 @@ buildscript {
13
13
  }
14
14
 
15
15
  dependencies {
16
- classpath("com.android.tools.build:gradle:7.4.2")
17
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
16
+ classpath("com.android.tools.build:gradle:8.1.4")
17
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$blaze_kotlin_version"
18
18
  }
19
19
  }
20
20
 
21
21
  apply plugin: 'com.android.library'
22
- apply plugin: "kotlin-android"
22
+ apply plugin: 'kotlin-android'
23
23
 
24
24
  android {
25
- compileSdkVersion safeExtGet('compileSdkVersion', 33)
25
+ compileSdkVersion safeExtGet('compileSdkVersion', 34)
26
26
  namespace "com.blaze.rtnblazesdk"
27
27
 
28
28
  def versionJsonFile = file('../package.json')
@@ -31,7 +31,7 @@ android {
31
31
 
32
32
  defaultConfig {
33
33
  minSdkVersion safeExtGet('minSdkVersion', 24)
34
- targetSdkVersion safeExtGet('targetSdkVersion', 33)
34
+ targetSdkVersion safeExtGet('targetSdkVersion', 34)
35
35
  versionCode 1
36
36
  versionName packageVersion
37
37
 
@@ -56,7 +56,9 @@ android {
56
56
  kotlinOptions {
57
57
  jvmTarget = '1.8'
58
58
  }
59
-
59
+ buildFeatures {
60
+ buildConfig = true
61
+ }
60
62
  }
61
63
 
62
64
  repositories {
@@ -79,12 +81,11 @@ repositories {
79
81
  }
80
82
 
81
83
  dependencies {
82
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
84
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$blaze_kotlin_version"
83
85
 
84
86
  // noinspection GradleDynamicVersion
85
87
  api 'com.facebook.react:react-native:+'
86
88
 
87
- def blazeSDK = '0.30.35'
89
+ def blazeSDK = '0.60.12'
88
90
  implementation group: "com.blaze", name: "blazesdk", version: "${blazeSDK}"
89
- implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
90
91
  }
@@ -8,6 +8,7 @@ import com.blaze.rtnblazesdk.moments.BlazeMomentsGridView
8
8
  import com.blaze.rtnblazesdk.viewmanagers.RTNBlazeMomentsGridViewManagerDelegate
9
9
  import com.blaze.rtnblazesdk.viewmanagers.RTNBlazeMomentsGridViewManagerInterface
10
10
  import com.facebook.react.bridge.ReactApplicationContext
11
+ import com.facebook.react.bridge.ReadableArray
11
12
  import com.facebook.react.bridge.ReadableMap
12
13
  import com.facebook.react.common.MapBuilder
13
14
  import com.facebook.react.module.annotations.ReactModule
@@ -42,16 +43,23 @@ class BlazeMomentsGridViewManager(
42
43
  return view
43
44
  }
44
45
 
45
- override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any>? {
46
- return MapBuilder.of<String, Any>(
47
- WidgetDataLoadStartedEvent.EVENT_NAME,
48
- MapBuilder.of("registrationName", "onWidgetDataLoadStarted"),
49
- WidgetDataLoadCompletedEvent.EVENT_NAME,
50
- MapBuilder.of("registrationName", "onWidgetDataLoadCompleted")
51
- )
46
+ override fun receiveCommand(
47
+ view: BlazeMomentsGridView,
48
+ commandId: Int,
49
+ args: ReadableArray?
50
+ ) {
51
+ when (commandId) {
52
+ COMMAND_RELOAD_DATA_ID -> view.reloadData()
53
+
54
+ COMMAND_UPDATE_DATA_SOURCE_ID -> if (args != null && args.size() > 0) {
55
+ val dataSource = args.getMap(0)
56
+ if (dataSource != null) {
57
+ view.updateDataSource(dataSource)
58
+ }
59
+ }
60
+ }
52
61
  }
53
62
 
54
-
55
63
  override fun updateProperties(viewToUpdate: BlazeMomentsGridView, props: ReactStylesDiffMap) {
56
64
  super.updateProperties(viewToUpdate, props)
57
65
 
@@ -5,10 +5,10 @@ import com.blaze.rtnblazesdk.events.WidgetDataLoadCompletedEvent
5
5
  import com.blaze.rtnblazesdk.events.WidgetDataLoadStartedEvent
6
6
  import com.blaze.rtnblazesdk.moments.BlazeMomentsRowView
7
7
  import com.blaze.rtnblazesdk.moments.BlazeRowViewManagerImp
8
- import com.blaze.rtnblazesdk.stories.BlazeStoriesRowView
9
8
  import com.blaze.rtnblazesdk.viewmanagers.RTNBlazeMomentsRowViewManagerDelegate
10
9
  import com.blaze.rtnblazesdk.viewmanagers.RTNBlazeMomentsRowViewManagerInterface
11
10
  import com.facebook.react.bridge.ReactApplicationContext
11
+ import com.facebook.react.bridge.ReadableArray
12
12
  import com.facebook.react.bridge.ReadableMap
13
13
  import com.facebook.react.common.MapBuilder
14
14
  import com.facebook.react.module.annotations.ReactModule
@@ -39,13 +39,21 @@ class BlazeMomentsRowViewManager(context: ReactApplicationContext?) :
39
39
  return BlazeRowViewManagerImp.createViewInstance(context)
40
40
  }
41
41
 
42
- override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any>? {
43
- return MapBuilder.of<String, Any>(
44
- WidgetDataLoadStartedEvent.EVENT_NAME,
45
- MapBuilder.of("registrationName", "onWidgetDataLoadStarted"),
46
- WidgetDataLoadCompletedEvent.EVENT_NAME,
47
- MapBuilder.of("registrationName", "onWidgetDataLoadCompleted")
48
- )
42
+ override fun receiveCommand(
43
+ view: BlazeMomentsRowView,
44
+ commandId: Int,
45
+ args: ReadableArray?
46
+ ) {
47
+ when (commandId) {
48
+ COMMAND_RELOAD_DATA_ID -> view.reloadData()
49
+
50
+ COMMAND_UPDATE_DATA_SOURCE_ID -> if (args != null && args.size() > 0) {
51
+ val dataSource = args.getMap(0)
52
+ if (dataSource != null) {
53
+ view.updateDataSource(dataSource)
54
+ }
55
+ }
56
+ }
49
57
  }
50
58
 
51
59
  override fun updateProperties(viewToUpdate: BlazeMomentsRowView, props: ReactStylesDiffMap) {
@@ -50,4 +50,8 @@ class BlazeSdkModule(context: ReactApplicationContext) : NativeBlazeSdkSpec(cont
50
50
  override fun handleUniversalLink(link: String, promise: Promise) {
51
51
  return implementation.handleUniversalLink(link, promise)
52
52
  }
53
+
54
+ override fun updateGeoRestriction(geoLocation: String?, promise: Promise) {
55
+ return implementation.updateGeoRestriction(geoLocation, promise)
56
+ }
53
57
  }
@@ -2,14 +2,14 @@ package com.blaze.rtnblazesdk
2
2
 
3
3
  import android.app.Application
4
4
  import com.blaze.blazesdk.BlazeSDK
5
+ import com.blaze.blazesdk.core.analytics.models.BlazeAnalyticsEvent
5
6
  import com.blaze.blazesdk.core.external_modules.BlazeExternalModulesBinder
6
7
  import com.blaze.blazesdk.core.managers.CachingLevel
7
8
  import com.blaze.blazesdk.core.models.BlazeResult
8
9
  import com.blaze.blazesdk.features.moments.theme.player.MomentPlayerTheme
9
10
  import com.blaze.blazesdk.features.stories.theme.player.StoryPlayerTheme
10
- import com.blaze.blazesdk.features.widgets.labels.BlazeDataSourceType
11
- import com.blaze.blazesdk.features.widgets.labels.BlazeWidgetLabel
12
11
  import com.blaze.blazesdk.features.widgets.shared.GlobalDelegates
12
+ import com.blaze.rtnblazesdk.base.extractDataSource
13
13
  import com.blaze.rtnblazesdk.utils.handleResult
14
14
  import com.blaze.rtnblazesdk.utils.rejectWith
15
15
  import com.facebook.react.bridge.Arguments
@@ -31,13 +31,11 @@ class BlazeSdkModuleImp(private val context: ReactApplicationContext) {
31
31
  val storyPlayerTheme = StoryPlayerTheme()
32
32
  val momentPlayerTheme = MomentPlayerTheme()
33
33
  try {
34
-
35
-
36
-
37
34
  BlazeSDK.init(
38
35
  apiKey = options.getString("apiKey")!!,
39
36
  application = (context.applicationContext as Application),
40
37
  externalUserId = null,
38
+ geoLocation = options.getString("geoLocation"),
41
39
  cachingSize = options.getInt("cachingSize"),
42
40
  globalStoryAppearanceLayout = storyPlayerTheme,
43
41
  globalMomentsAppearanceTheme = momentPlayerTheme,
@@ -111,7 +109,7 @@ class BlazeSdkModuleImp(private val context: ReactApplicationContext) {
111
109
 
112
110
  fun playMoments(options: ReadableMap, promise: Promise) {
113
111
  try {
114
- val dataSource = extractDataSource(options) ?: run {
112
+ val dataSource = options.extractDataSource() ?: run {
115
113
  promise.rejectWith("Error parsing data source")
116
114
  return
117
115
  }
@@ -125,51 +123,80 @@ class BlazeSdkModuleImp(private val context: ReactApplicationContext) {
125
123
 
126
124
  fun handleUniversalLink(link: String, promise: Promise) {
127
125
  try {
128
- BlazeSDK.handleUniversalLink(link)
129
- promise.resolve(link)
126
+ BlazeSDK.handleUniversalLink(link){ result ->
127
+ promise.handleResult(result)
128
+ }
130
129
  } catch (e: Exception) {
131
130
  promise.rejectWith(e.toString())
132
131
  }
133
132
  }
134
133
 
135
- private fun extractDataSource(options: ReadableMap): BlazeDataSourceType? {
136
- val labelsDataSource = options.getString("labels")
137
- val idsDataSource = options.getArray("ids")?.toArrayList() as? List<String>
138
- val dataSource =
139
- if (labelsDataSource != null) {
140
- BlazeDataSourceType.Labels(BlazeWidgetLabel.singleLabel(labelsDataSource))
141
- } else if (
142
- idsDataSource != null
143
- ) {
144
- BlazeDataSourceType.Ids(idsDataSource)
145
- } else {
146
- null
134
+ fun updateGeoRestriction(geoLocation: String?, promise: Promise) {
135
+ val updatedGeoLocation = if (geoLocation.isNullOrEmpty()) null else geoLocation
136
+ try {
137
+ BlazeSDK.updateGeoRestriction(updatedGeoLocation){ result ->
138
+ promise.handleResult(result)
147
139
  }
148
- return dataSource
140
+ } catch (e: Exception) {
141
+ promise.rejectWith(e.toString())
142
+ }
149
143
  }
150
144
 
151
145
  private fun registerGlobalDelegateMethods() {
152
146
 
153
147
  GlobalDelegates.onStoryPlayerDidAppear = {
154
- context.emitDeviceEvent("Blaze.onStoryPlayerDidAppear")
148
+ onStoryPlayerDidAppear()
155
149
  }
150
+
156
151
  GlobalDelegates.onStoryPlayerDismissed = {
157
- context.emitDeviceEvent("Blaze.onStoryPlayerDismissed")
152
+ onStoryPlayerDismissed()
158
153
  }
154
+
159
155
  GlobalDelegates.onMomentsPlayerDidAppear = {
160
- context.emitDeviceEvent("Blaze.onMomentsPlayerDidAppear")
156
+ onMomentsPlayerDidAppear()
161
157
  }
158
+
162
159
  GlobalDelegates.onMomentsPlayerDismissed = {
163
- context.emitDeviceEvent("Blaze.onMomentsPlayerDismissed")
160
+ onMomentsPlayerDismissed()
164
161
  }
162
+
165
163
  GlobalDelegates.onErrorThrown = { error ->
166
- val params = Arguments.createMap()
167
- params.putString("domain", error.domain.toString())
168
- params.putString("reason", error.reason.toString())
169
- params.putString("message", error.message)
170
- context.emitDeviceEvent("Blaze.onErrorThrown", params)
164
+ onErrorThrown(error)
171
165
  }
172
166
 
167
+ GlobalDelegates.onEventTriggered = { eventData ->
168
+ onEventTriggered(eventData)
169
+ }
170
+ }
171
+
172
+ private fun onStoryPlayerDidAppear() {
173
+ context.emitDeviceEvent("Blaze.onStoryPlayerDidAppear")
174
+ }
175
+
176
+ private fun onStoryPlayerDismissed() {
177
+ context.emitDeviceEvent("Blaze.onStoryPlayerDismissed")
178
+ }
179
+
180
+ private fun onMomentsPlayerDidAppear() {
181
+ context.emitDeviceEvent("Blaze.onMomentsPlayerDidAppear")
182
+ }
183
+
184
+ private fun onMomentsPlayerDismissed() {
185
+ context.emitDeviceEvent("Blaze.onMomentsPlayerDismissed")
186
+ }
187
+
188
+ private fun onErrorThrown(error: BlazeResult.Error) {
189
+ val params = Arguments.createMap()
190
+ params.putString("domain", error.domain.toString())
191
+ params.putString("reason", error.reason.toString())
192
+ params.putString("message", error.message)
193
+ context.emitDeviceEvent("Blaze.onErrorThrown", params)
194
+ }
195
+
196
+ private fun onEventTriggered(eventData: BlazeAnalyticsEvent) {
197
+ val eventJson = eventData.asJsonString ?: return
198
+
199
+ context.emitDeviceEvent("Blaze.onEventTriggered", eventJson)
173
200
  }
174
201
 
175
202
  companion object {
@@ -6,6 +6,7 @@ import com.blaze.rtnblazesdk.stories.BlazeStoriesGridView
6
6
  import com.blaze.rtnblazesdk.viewmanagers.RTNBlazeStoriesGridViewManagerDelegate
7
7
  import com.blaze.rtnblazesdk.viewmanagers.RTNBlazeStoriesGridViewManagerInterface
8
8
  import com.facebook.react.bridge.ReactApplicationContext
9
+ import com.facebook.react.bridge.ReadableArray
9
10
  import com.facebook.react.bridge.ReadableMap
10
11
  import com.facebook.react.module.annotations.ReactModule
11
12
  import com.facebook.react.uimanager.ReactStylesDiffMap
@@ -22,6 +23,23 @@ class BlazeStoriesGridViewManager(
22
23
  RTNBlazeStoriesGridViewManagerInterface<BlazeStoriesGridView?> {
23
24
  private val mDelegate: ViewManagerDelegate<BlazeStoriesGridView>
24
25
 
26
+ override fun receiveCommand(
27
+ view: BlazeStoriesGridView,
28
+ commandId: Int,
29
+ args: ReadableArray?
30
+ ) {
31
+ when (commandId) {
32
+ COMMAND_RELOAD_DATA_ID -> view.reloadData()
33
+
34
+ COMMAND_UPDATE_DATA_SOURCE_ID -> if (args != null && args.size() > 0) {
35
+ val dataSource = args.getMap(0)
36
+ if (dataSource != null) {
37
+ view.updateDataSource(dataSource)
38
+ }
39
+ }
40
+ }
41
+ }
42
+
25
43
  init {
26
44
  mDelegate = RTNBlazeStoriesGridViewManagerDelegate(this)
27
45
  }
@@ -8,6 +8,7 @@ import com.blaze.rtnblazesdk.stories.BlazeStoriesRowView
8
8
  import com.blaze.rtnblazesdk.viewmanagers.RTNBlazeStoriesRowViewManagerDelegate
9
9
  import com.blaze.rtnblazesdk.viewmanagers.RTNBlazeStoriesRowViewManagerInterface
10
10
  import com.facebook.react.bridge.ReactApplicationContext
11
+ import com.facebook.react.bridge.ReadableArray
11
12
  import com.facebook.react.bridge.ReadableMap
12
13
  import com.facebook.react.common.MapBuilder
13
14
  import com.facebook.react.module.annotations.ReactModule
@@ -22,6 +23,24 @@ class BlazeStoriesRowViewManager(context: ReactApplicationContext?) :
22
23
  RTNBlazeStoriesRowViewManagerInterface<BlazeStoriesRowView?> {
23
24
  private val mDelegate: ViewManagerDelegate<BlazeStoriesRowView>
24
25
 
26
+ override fun receiveCommand(
27
+ view: BlazeStoriesRowView,
28
+ commandId: Int,
29
+ args: ReadableArray?
30
+ ) {
31
+ when (commandId) {
32
+ COMMAND_RELOAD_DATA_ID -> view.reloadData()
33
+
34
+ COMMAND_UPDATE_DATA_SOURCE_ID -> if (args != null && args.size() > 0) {
35
+ val dataSource = args.getMap(0)
36
+ if (dataSource != null) {
37
+ view.updateDataSource(dataSource)
38
+ }
39
+ }
40
+ }
41
+ }
42
+
43
+
25
44
  init {
26
45
  mDelegate = RTNBlazeStoriesRowViewManagerDelegate(this)
27
46
  }
@@ -38,15 +57,6 @@ class BlazeStoriesRowViewManager(context: ReactApplicationContext?) :
38
57
  return BlazeRowViewManagerImp.createViewInstance(context)
39
58
  }
40
59
 
41
- override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any>? {
42
- return MapBuilder.of<String, Any>(
43
- WidgetDataLoadStartedEvent.EVENT_NAME,
44
- MapBuilder.of("registrationName", "onWidgetDataLoadStarted"),
45
- WidgetDataLoadCompletedEvent.EVENT_NAME,
46
- MapBuilder.of("registrationName", "onWidgetDataLoadCompleted")
47
- )
48
- }
49
-
50
60
  override fun updateProperties(viewToUpdate: BlazeStoriesRowView, props: ReactStylesDiffMap) {
51
61
  super.updateProperties(viewToUpdate, props)
52
62
  viewToUpdate.onPropsUpdate(props)
@@ -58,4 +58,8 @@ public abstract class NativeBlazeSdkSpec extends ReactContextBaseJavaModule impl
58
58
  @ReactMethod
59
59
  @DoNotStrip
60
60
  public abstract void handleUniversalLink(String link, Promise promise);
61
+
62
+ @ReactMethod
63
+ @DoNotStrip
64
+ public abstract void updateGeoRestriction(String geoLocation, Promise promise);
61
65
  }
@@ -5,7 +5,9 @@ import com.blaze.rtnblazesdk.events.WidgetDataLoadCompletedEvent
5
5
  import com.blaze.rtnblazesdk.events.WidgetDataLoadStartedEvent
6
6
  import com.blaze.rtnblazesdk.events.WidgetItemClickedEvent
7
7
  import com.blaze.rtnblazesdk.events.WidgetPlayerDismissedEvent
8
+ import com.blaze.rtnblazesdk.stories.BlazeStoriesRowView
8
9
  import com.facebook.react.bridge.ReactApplicationContext
10
+ import com.facebook.react.bridge.ReactMethod
9
11
  import com.facebook.react.common.MapBuilder
10
12
  import com.facebook.react.uimanager.LayoutShadowNode
11
13
  import com.facebook.react.uimanager.SimpleViewManager
@@ -18,15 +20,15 @@ abstract class BaseViewManager<TView : BaseWidgetView>(
18
20
  override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any>? {
19
21
  return MapBuilder.of<String, Any>(
20
22
  WidgetDataLoadStartedEvent.EVENT_NAME,
21
- MapBuilder.of("registrationName", "onWidgetDataLoadStarted"),
23
+ MapBuilder.of("registrationName", "onWidgetDataLoadStartedInternal"),
22
24
  WidgetDataLoadCompletedEvent.EVENT_NAME,
23
- MapBuilder.of("registrationName", "onWidgetDataLoadCompleted"),
25
+ MapBuilder.of("registrationName", "onWidgetDataLoadCompletedInternal"),
24
26
  WidgetPlayerDismissedEvent.EVENT_NAME,
25
- MapBuilder.of("registrationName", "onWidgetPlayerDismissed"),
27
+ MapBuilder.of("registrationName", "onWidgetPlayerDismissedInternal"),
26
28
  WidgetItemClickedEvent.EVENT_NAME,
27
- MapBuilder.of("registrationName", "onItemClicked"),
29
+ MapBuilder.of("registrationName", "onItemClickedInternal"),
28
30
  WidgetCTAClickEvent.EVENT_NAME,
29
- MapBuilder.of("registrationName", "onTriggerCTA"),
31
+ MapBuilder.of("registrationName", "onTriggerCTAInternal"),
30
32
  )
31
33
  }
32
34
 
@@ -34,4 +36,20 @@ abstract class BaseViewManager<TView : BaseWidgetView>(
34
36
  return BlazeWidgetViewShadowNode()
35
37
  }
36
38
 
39
+ companion object {
40
+ const val COMMAND_RELOAD_DATA = "reloadData"
41
+ const val COMMAND_UPDATE_DATA_SOURCE = "updateDataSource"
42
+
43
+ //COMMAND IDs
44
+ const val COMMAND_RELOAD_DATA_ID = 0
45
+ const val COMMAND_UPDATE_DATA_SOURCE_ID = 1
46
+ }
47
+
48
+ override fun getCommandsMap(): MutableMap<String, Int> {
49
+ return mutableMapOf(
50
+ COMMAND_RELOAD_DATA to Companion.COMMAND_RELOAD_DATA_ID,
51
+ COMMAND_UPDATE_DATA_SOURCE to Companion.COMMAND_UPDATE_DATA_SOURCE_ID,
52
+ )
53
+ }
54
+
37
55
  }
@@ -11,7 +11,6 @@ import com.blaze.rtnblazesdk.customization.mergedWith
11
11
  import com.blaze.rtnblazesdk.events.BaseEvent
12
12
  import com.facebook.react.bridge.ReactContext
13
13
  import com.facebook.react.bridge.ReadableMap
14
- import com.facebook.react.uimanager.ReactStylesDiffMap
15
14
  import com.facebook.react.uimanager.UIManagerHelper
16
15
  import com.facebook.react.uimanager.events.EventDispatcher
17
16
  import toBlazeReactPlayerStoryTheme
@@ -39,23 +38,6 @@ abstract class BaseWidgetView @JvmOverloads constructor(
39
38
  }
40
39
  }
41
40
 
42
- protected fun extractDataSource(dataSource: ReadableMap?): BlazeDataSourceType? {
43
- val rawDataSource = dataSource ?: return null
44
- val labelsDataSource = rawDataSource.getMap("labels")?.getString("value") ?: return null
45
- val idsDataSource = rawDataSource.getArray("ids")?.toArrayList() as? List<String>
46
- val dataSource =
47
- if (labelsDataSource != null){
48
- BlazeDataSourceType.Labels(BlazeWidgetLabel.singleLabel(labelsDataSource))
49
- }else if(
50
- idsDataSource != null
51
- ){
52
- BlazeDataSourceType.Ids(idsDataSource)
53
- } else{
54
- null
55
- }
56
- return dataSource
57
- }
58
-
59
41
  protected fun applyWidgetLayoutCustomization(
60
42
  reactWidgetLayout: ReadableMap?,
61
43
  widgetLayout: BlazeWidgetLayout,
@@ -87,4 +69,21 @@ abstract class BaseWidgetView @JvmOverloads constructor(
87
69
  return momentPlayerTheme.mergedWith(customization = customization,context)
88
70
  }
89
71
 
90
- }
72
+ }
73
+
74
+ fun ReadableMap?.extractDataSource(): BlazeDataSourceType? {
75
+ val rawDataSource = this ?: return null
76
+ val labelsDataSource = rawDataSource.getMap("labels")?.getString("value") ?: return null
77
+ val idsDataSource = rawDataSource.getArray("ids")?.toArrayList() as? List<String>
78
+ val dataSource =
79
+ if (labelsDataSource != null) {
80
+ BlazeDataSourceType.Labels(BlazeWidgetLabel.singleLabel(labelsDataSource))
81
+ } else if (
82
+ idsDataSource != null
83
+ ) {
84
+ BlazeDataSourceType.Ids(idsDataSource)
85
+ } else {
86
+ null
87
+ }
88
+ return dataSource
89
+ }
@@ -0,0 +1,43 @@
1
+ package com.blaze.rtnblazesdk.customization
2
+
3
+ import android.graphics.Color
4
+
5
+ object BlazeColorParser {
6
+
7
+ /**
8
+ * Parses a color string in either RGB (#RRGGBB) or RGBA (#RRGGBBAA) format and returns the corresponding
9
+ * Android color int. If the string is not in a valid format, returns the fallback color.
10
+ *
11
+ * @param colorString The color string to parse. Expected in the format "#RRGGBB" or "#RRGGBBAA".
12
+ * @param fallback The fallback color int to return in case the color string is invalid. Default is null.
13
+ * @return The parsed color int, or the fallback color if the input is invalid.
14
+ */
15
+ internal fun rgbaToColorInt(colorString: String, fallback: Int? = null): Int? {
16
+ return try {
17
+ // Remove any "#" prefix and trim whitespace
18
+ val hexString = colorString.trim().trimStart('#')
19
+
20
+ // Format the string correctly for parsing
21
+ val formattedString = when (hexString.length) {
22
+ 6 -> { // RGB format
23
+ "FF$hexString" // Prepend full opacity for ARGB
24
+ }
25
+ 8 -> { // RGBA format
26
+ val alpha = hexString.takeLast(2)
27
+ val color = hexString.dropLast(2)
28
+ "$alpha$color" // Rearrange to ARGB format
29
+ }
30
+ else -> {
31
+ return fallback // Return fallback if format is incorrect
32
+ }
33
+ }
34
+
35
+ // Parse the ARGB color string to an int
36
+ Color.parseColor("#$formattedString")
37
+ } catch (e: IllegalArgumentException) {
38
+ // In case of exception, return fallback value or null
39
+ fallback
40
+ }
41
+ }
42
+
43
+ }
@@ -101,7 +101,7 @@ fun safeParseColor(hexString: String?): Int? {
101
101
  hexString ?: return null
102
102
 
103
103
  return try {
104
- Color.parseColor(hexString)
104
+ BlazeColorParser.rgbaToColorInt(colorString = hexString)
105
105
  } catch (e: Throwable) {
106
106
  null
107
107
  }
@@ -12,11 +12,13 @@ import BlazeReactMomentsGradient
12
12
  import BlazeReactMomentsSeekBar
13
13
  import BlazeReactMomentsText
14
14
  import BlazeReactWidgetMomentTheme
15
+ import PlayerReactFooterGradientPositioning
15
16
  import android.content.Context
16
17
  import com.blaze.blazesdk.core.base_classes.models.Padding
17
18
  import com.blaze.blazesdk.core.first_time_slide.models.MomentPlayerFirstTimeSlide
18
19
  import com.blaze.blazesdk.core.first_time_slide.models.MomentPlayerFirstTimeSlideInstructions
19
20
  import com.blaze.blazesdk.core.theme.player.BlazeScaleType
21
+ import com.blaze.blazesdk.core.theme.player.PlayerFooterGradientPositioning
20
22
  import com.blaze.blazesdk.features.moments.theme.player.MomentPlayerGradientFooterTheme
21
23
  import com.blaze.blazesdk.features.moments.theme.player.MomentPlayerGradientHeaderTheme
22
24
  import com.blaze.blazesdk.features.moments.theme.player.MomentPlayerItemButtonExitTheme
@@ -261,6 +263,16 @@ fun MomentPlayerGradientFooterTheme.mergedWith(
261
263
  merged.isVisible = customization.isVisible ?: this.isVisible
262
264
  merged.startColor = safeParseColor(customization.startColor) ?: this.startColor
263
265
  merged.endColor = safeParseColor(customization.endColor) ?: this.endColor
266
+ merged.endPositioning = merged.endPositioning.mergeWith(customization.endPositioning)
264
267
 
265
268
  return merged
269
+ }
270
+
271
+ fun PlayerFooterGradientPositioning.mergeWith(customization: PlayerReactFooterGradientPositioning?): PlayerFooterGradientPositioning {
272
+ customization ?: return this
273
+
274
+ return when (customization) {
275
+ PlayerReactFooterGradientPositioning.BOTTOM_TO_PLAYER -> PlayerFooterGradientPositioning.BOTTOM_TO_PLAYER
276
+ PlayerReactFooterGradientPositioning.BOTTOM_TO_CONTAINER -> PlayerFooterGradientPositioning.BOTTOM_TO_CONTAINER
277
+ }
266
278
  }
@@ -1,5 +1,6 @@
1
1
  package com.blaze.rtnblazesdk.customization
2
2
 
3
+ import BlazeReactCTAPositioning
3
4
  import BlazeReactPaddings
4
5
  import BlazeReactPlayerStoryTheme
5
6
  import BlazeReactStoryButton
@@ -14,11 +15,15 @@ import BlazeReactStoryIconThumbnail
14
15
  import BlazeReactStoryLastUpdateText
15
16
  import BlazeReactStoryProgressBarStyle
16
17
  import BlazeReactStoryText
18
+ import BlazeReactTextCase
17
19
  import android.content.Context
18
20
  import com.blaze.blazesdk.core.base_classes.models.Padding
19
21
  import com.blaze.blazesdk.core.first_time_slide.models.StoryPlayerFirstTimeSlide
20
22
  import com.blaze.blazesdk.core.first_time_slide.models.StoryPlayerFirstTimeSlideInstructions
21
23
  import com.blaze.blazesdk.core.theme.player.BlazeScaleType
24
+ import com.blaze.blazesdk.core.theme.player.PlayerCtaPositioning
25
+ import com.blaze.blazesdk.core.theme.player.PlayerFooterGradientPositioning
26
+ import com.blaze.blazesdk.core.theme.player.PlayerTextCase
22
27
  import com.blaze.blazesdk.features.stories.models.blaze.StoryPlayerItemIconThumbnail
23
28
  import com.blaze.blazesdk.features.stories.theme.player.StoryPlayerGradientTheme
24
29
  import com.blaze.blazesdk.features.stories.theme.player.StoryPlayerItemButtonExitTheme
@@ -126,9 +131,19 @@ fun StoryPlayerItemLastUpdateTheme.mergedWith(
126
131
  merged.fontResId = customization.font?.toFontResId(context)
127
132
  merged.textColor = safeParseColor(customization.textColor) ?: this.textColor
128
133
  merged.textSize = customization.textSize ?: merged.textSize
134
+ merged.textCase = merged.textCase.mergeWith(customization.textCase)
129
135
  return merged
130
136
  }
131
137
 
138
+ fun PlayerTextCase.mergeWith(customization: BlazeReactTextCase?): PlayerTextCase {
139
+ customization ?: return this
140
+
141
+ return when (customization) {
142
+ BlazeReactTextCase.UPPERCASE -> PlayerTextCase.UPPERCASE
143
+ BlazeReactTextCase.LOWERCASE -> PlayerTextCase.LOWERCASE
144
+ }
145
+ }
146
+
132
147
  fun StoryPlayerItemButtonsTheme.mergedWith(
133
148
  customization: BlazeReactStoryButtons?,
134
149
  context: Context
@@ -179,10 +194,21 @@ fun StoryPlayerItemCtaTheme.mergedWith(
179
194
  merged.cornerRadius = (customization.cornerRadius ?: this.cornerRadius).toFloat()
180
195
  merged.textSize = customization.textSize ?: this.textSize
181
196
  merged.fontResId = customization.font?.toFontResId(context)
197
+ merged.layoutPositioning = merged.layoutPositioning.mergeWith(customization.position)
182
198
 
183
199
  return merged
184
200
  }
185
201
 
202
+ fun PlayerCtaPositioning.mergeWith(customization: BlazeReactCTAPositioning?): PlayerCtaPositioning {
203
+ customization ?: return this
204
+
205
+ return when (customization) {
206
+ BlazeReactCTAPositioning.CTA_BELLOW_SHARE -> PlayerCtaPositioning.CTA_BELOW_SHARE
207
+ BlazeReactCTAPositioning.CTA_NEXT_TO_SHARE -> PlayerCtaPositioning.CTA_NEXT_TO_SHARE
208
+ }
209
+ }
210
+
211
+
186
212
  fun StoryPlayerItemChipsTheme.mergedWith(
187
213
  customization: BlazeReactStoryChips?,
188
214
  ): StoryPlayerItemChipsTheme {