react-native-unistyles 3.0.0-alpha.36 → 3.0.0-alpha.37
Sign up to get free protection for your applications and to get access to all the features.
- package/Unistyles.podspec +1 -1
- package/android/CMakeLists.txt +3 -15
- package/android/src/main/cxx/NativeUnistylesModule.cpp +1 -1
- package/android/src/main/java/com/unistyles/Equatable.kt +61 -0
- package/android/src/main/java/com/unistyles/NativePlatform+android.kt +302 -0
- package/android/src/main/java/com/unistyles/NativePlatform+insets.kt +148 -0
- package/android/src/main/java/com/unistyles/NativePlatform+listener.kt +54 -0
- package/android/src/main/java/com/unistyles/UnistylesModule.kt +5 -1
- package/cxx/core/UnistyleData.h +1 -1
- package/cxx/core/UnistyleWrapper.h +1 -2
- package/cxx/core/UnistylesCommitHook.cpp +1 -1
- package/cxx/core/UnistylesMountHook.cpp +1 -1
- package/cxx/core/UnistylesRegistry.cpp +4 -13
- package/cxx/core/UnistylesRegistry.h +1 -2
- package/cxx/core/UnistylesState.cpp +10 -7
- package/cxx/hybridObjects/HybridStyleSheet.cpp +21 -18
- package/cxx/hybridObjects/HybridUnistylesRuntime.cpp +0 -4
- package/cxx/hybridObjects/HybridUnistylesRuntime.h +0 -1
- package/cxx/parser/Parser.cpp +3 -27
- package/cxx/parser/Parser.h +2 -3
- package/cxx/shadowTree/ShadowTrafficController.h +9 -5
- package/cxx/shadowTree/ShadowTreeManager.cpp +10 -5
- package/cxx/shadowTree/ShadowTreeManager.h +1 -1
- package/package.json +3 -3
- package/android/src/main/java/com/unistyles/NativePlatform.kt +0 -184
- package/android/src/main/java/com/unistyles/UnistylesModule+insets.kt +0 -8
package/Unistyles.podspec
CHANGED
@@ -19,7 +19,7 @@ Pod::Spec.new do |s|
|
|
19
19
|
]
|
20
20
|
s.pod_target_xcconfig = {
|
21
21
|
"CLANG_CXX_LANGUAGE_STANDARD" => "c++20",
|
22
|
-
"GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) FOLLY_NO_CONFIG FOLLY_CFG_NO_COROUTINES"
|
22
|
+
"GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) FOLLY_NO_CONFIG FOLLY_CFG_NO_COROUTINES FOLLY_MOBILE"
|
23
23
|
}
|
24
24
|
|
25
25
|
s.public_header_files = [
|
package/android/CMakeLists.txt
CHANGED
@@ -23,7 +23,7 @@ include_directories(
|
|
23
23
|
../cxx/shadowTree
|
24
24
|
)
|
25
25
|
|
26
|
-
string(APPEND CMAKE_CXX_FLAGS "-DFOLLY_NO_CONFIG")
|
26
|
+
string(APPEND CMAKE_CXX_FLAGS "-DFOLLY_NO_CONFIG=1 -DFOLLY_CFG_NO_COROUTINES=1 -DFOLLY_MOBILE=1")
|
27
27
|
|
28
28
|
set_target_properties(unistyles PROPERTIES
|
29
29
|
CXX_STANDARD 20
|
@@ -32,17 +32,5 @@ set_target_properties(unistyles PROPERTIES
|
|
32
32
|
POSITION_INDEPENDENT_CODE ON
|
33
33
|
)
|
34
34
|
|
35
|
-
#
|
36
|
-
#
|
37
|
-
# find_package(fbjni REQUIRED CONFIG)
|
38
|
-
|
39
|
-
#if (ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)
|
40
|
-
# target_link_libraries(unistyles ReactAndroid::reactnative)
|
41
|
-
#else()
|
42
|
-
# target_link_libraries(unistyles
|
43
|
-
# ReactAndroid::turbomodulejsijni
|
44
|
-
# ReactAndroid::react_nativemodule_core
|
45
|
-
# android
|
46
|
-
# fbjni::fbjni
|
47
|
-
# )
|
48
|
-
#endif()
|
35
|
+
# For React Native 0.76 and above, we don't need to link anything
|
36
|
+
# as NitroModules will automatically add ReactAndroid::reactnative prefab
|
@@ -49,7 +49,7 @@ jni::local_ref<BindingsInstallerHolder::javaobject> UnistylesModule::getBindings
|
|
49
49
|
}
|
50
50
|
|
51
51
|
auto runOnJSThread = [&runtimeExecutor](std::function<void(jsi::Runtime&)>&& callback) {
|
52
|
-
runtimeExecutor([
|
52
|
+
runtimeExecutor([callback = std::move(callback)](jsi::Runtime &rt) {
|
53
53
|
callback(rt);
|
54
54
|
});
|
55
55
|
};
|
@@ -0,0 +1,61 @@
|
|
1
|
+
package com.unistyles
|
2
|
+
|
3
|
+
import com.margelo.nitro.unistyles.Dimensions
|
4
|
+
import com.margelo.nitro.unistyles.Insets
|
5
|
+
import com.margelo.nitro.unistyles.UnistyleDependency
|
6
|
+
import com.margelo.nitro.unistyles.UnistylesNativeMiniRuntime
|
7
|
+
|
8
|
+
fun Dimensions.isEqualTo(other: Dimensions): Boolean {
|
9
|
+
return this.width == other.width && this.height == other.height
|
10
|
+
}
|
11
|
+
|
12
|
+
fun Insets.isEqualTo(other: Insets): Boolean {
|
13
|
+
return this.top == other.top && this.bottom == other.bottom &&
|
14
|
+
this.left == other.left && this.right == other.right &&
|
15
|
+
this.ime == other.ime
|
16
|
+
}
|
17
|
+
|
18
|
+
fun NativePlatformAndroid.diffMiniRuntimes(lhs: UnistylesNativeMiniRuntime, rhs: UnistylesNativeMiniRuntime): Array<UnistyleDependency> {
|
19
|
+
val dependencies: MutableList<UnistyleDependency> = mutableListOf()
|
20
|
+
|
21
|
+
if (lhs.colorScheme != rhs.colorScheme) {
|
22
|
+
dependencies.add(UnistyleDependency.COLORSCHEME)
|
23
|
+
}
|
24
|
+
|
25
|
+
if (!lhs.screen.isEqualTo(rhs.screen)) {
|
26
|
+
dependencies.add(UnistyleDependency.DIMENSIONS)
|
27
|
+
}
|
28
|
+
|
29
|
+
if (lhs.screen.width != rhs.screen.width) {
|
30
|
+
dependencies.add(UnistyleDependency.BREAKPOINTS)
|
31
|
+
}
|
32
|
+
|
33
|
+
// no need to check isLandscape, as it's always opposite
|
34
|
+
if (lhs.isPortrait != rhs.isPortrait) {
|
35
|
+
dependencies.add(UnistyleDependency.ORIENTATION)
|
36
|
+
}
|
37
|
+
|
38
|
+
if (lhs.contentSizeCategory != rhs.contentSizeCategory) {
|
39
|
+
dependencies.add(UnistyleDependency.CONTENTSIZECATEGORY)
|
40
|
+
}
|
41
|
+
|
42
|
+
if (!lhs.insets.isEqualTo(rhs.insets)) {
|
43
|
+
dependencies.add(UnistyleDependency.INSETS)
|
44
|
+
}
|
45
|
+
|
46
|
+
if (lhs.fontScale != rhs.fontScale) {
|
47
|
+
dependencies.add(UnistyleDependency.FONTSCALE)
|
48
|
+
}
|
49
|
+
|
50
|
+
if (!lhs.statusBar.isEqualTo(rhs.statusBar)) {
|
51
|
+
dependencies.add(UnistyleDependency.STATUSBAR)
|
52
|
+
}
|
53
|
+
|
54
|
+
if (!lhs.navigationBar.isEqualTo(rhs.navigationBar)) {
|
55
|
+
dependencies.add(UnistyleDependency.NAVIGATIONBAR)
|
56
|
+
}
|
57
|
+
|
58
|
+
// rtl and pixel ratio are not dynamic
|
59
|
+
|
60
|
+
return dependencies.toTypedArray()
|
61
|
+
}
|
@@ -0,0 +1,302 @@
|
|
1
|
+
package com.unistyles
|
2
|
+
|
3
|
+
import android.content.Context
|
4
|
+
import android.content.res.Configuration
|
5
|
+
import android.os.Build
|
6
|
+
import android.util.DisplayMetrics
|
7
|
+
import android.view.View
|
8
|
+
import android.view.WindowManager
|
9
|
+
import androidx.core.text.TextUtilsCompat
|
10
|
+
import androidx.core.view.ViewCompat
|
11
|
+
import androidx.core.view.WindowCompat
|
12
|
+
import androidx.core.view.WindowInsetsCompat
|
13
|
+
import androidx.core.view.WindowInsetsControllerCompat
|
14
|
+
import com.facebook.react.bridge.LifecycleEventListener
|
15
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
16
|
+
import com.margelo.nitro.unistyles.ColorScheme
|
17
|
+
import com.margelo.nitro.unistyles.Dimensions
|
18
|
+
import com.margelo.nitro.unistyles.HybridNativePlatformSpec
|
19
|
+
import com.margelo.nitro.unistyles.Insets
|
20
|
+
import com.margelo.nitro.unistyles.Orientation
|
21
|
+
import com.margelo.nitro.unistyles.UnistyleDependency
|
22
|
+
import com.margelo.nitro.unistyles.UnistylesNativeMiniRuntime
|
23
|
+
import java.util.Locale
|
24
|
+
|
25
|
+
class NativePlatformAndroid(private val reactContext: ReactApplicationContext): HybridNativePlatformSpec(), LifecycleEventListener {
|
26
|
+
private val _insets = NativePlatformInsets(reactContext) { this.diffMiniRuntime() }
|
27
|
+
private var _miniRuntime: UnistylesNativeMiniRuntime = buildMiniRuntime()
|
28
|
+
private val _listener = NativePlatformListener(reactContext) { this.diffMiniRuntime() }
|
29
|
+
|
30
|
+
init {
|
31
|
+
reactContext.addLifecycleEventListener(this)
|
32
|
+
}
|
33
|
+
|
34
|
+
fun invalidate() {
|
35
|
+
reactContext.removeLifecycleEventListener(this)
|
36
|
+
_listener.invalidate()
|
37
|
+
}
|
38
|
+
|
39
|
+
override fun onHostResume() {
|
40
|
+
enableEdgeToEdge()
|
41
|
+
_insets.startInsetsListener()
|
42
|
+
}
|
43
|
+
|
44
|
+
override fun onHostPause() {
|
45
|
+
_insets.stopInsetsListener()
|
46
|
+
}
|
47
|
+
|
48
|
+
override fun onHostDestroy() {}
|
49
|
+
|
50
|
+
override val memorySize: Long
|
51
|
+
get() = 0
|
52
|
+
|
53
|
+
override fun getInsets(): Insets {
|
54
|
+
return _insets.getInsets()
|
55
|
+
}
|
56
|
+
|
57
|
+
override fun getColorScheme(): ColorScheme {
|
58
|
+
val uiMode = reactContext.resources.configuration.uiMode
|
59
|
+
|
60
|
+
val colorScheme = when (uiMode.and(Configuration.UI_MODE_NIGHT_MASK)) {
|
61
|
+
Configuration.UI_MODE_NIGHT_YES -> ColorScheme.DARK
|
62
|
+
Configuration.UI_MODE_NIGHT_NO -> ColorScheme.LIGHT
|
63
|
+
else -> ColorScheme.UNSPECIFIED
|
64
|
+
}
|
65
|
+
|
66
|
+
return colorScheme
|
67
|
+
}
|
68
|
+
|
69
|
+
override fun getFontScale(): Double {
|
70
|
+
return reactContext.resources.configuration.fontScale.toDouble()
|
71
|
+
}
|
72
|
+
|
73
|
+
override fun getPixelRatio(): Double {
|
74
|
+
return reactContext.resources.displayMetrics.density.toDouble()
|
75
|
+
}
|
76
|
+
|
77
|
+
override fun getOrientation(): Orientation {
|
78
|
+
val orientation = when (reactContext.resources.configuration.orientation) {
|
79
|
+
Configuration.ORIENTATION_PORTRAIT -> Orientation.PORTRAIT
|
80
|
+
Configuration.ORIENTATION_LANDSCAPE -> Orientation.LANDSCAPE
|
81
|
+
else -> Orientation.PORTRAIT
|
82
|
+
}
|
83
|
+
|
84
|
+
return orientation
|
85
|
+
}
|
86
|
+
|
87
|
+
override fun getContentSizeCategory(): String {
|
88
|
+
val fontScale = getFontScale()
|
89
|
+
|
90
|
+
val contentSizeCategory = when {
|
91
|
+
fontScale <= 0.85f -> "Small"
|
92
|
+
fontScale <= 1.0f -> "Default"
|
93
|
+
fontScale <= 1.15f -> "Large"
|
94
|
+
fontScale <= 1.3f -> "ExtraLarge"
|
95
|
+
fontScale <= 1.5f -> "Huge"
|
96
|
+
fontScale <= 1.8 -> "ExtraHuge"
|
97
|
+
else -> "ExtraExtraHuge"
|
98
|
+
}
|
99
|
+
|
100
|
+
return contentSizeCategory
|
101
|
+
}
|
102
|
+
|
103
|
+
override fun getScreenDimensions(): Dimensions {
|
104
|
+
// function takes in count edge-to-edge layout
|
105
|
+
when {
|
106
|
+
Build.VERSION.SDK_INT < Build.VERSION_CODES.R -> {
|
107
|
+
val windowManager = reactContext.getSystemService(Context.WINDOW_SERVICE) as WindowManager
|
108
|
+
val metrics = DisplayMetrics()
|
109
|
+
|
110
|
+
@Suppress("DEPRECATION")
|
111
|
+
windowManager.defaultDisplay.getRealMetrics(metrics)
|
112
|
+
|
113
|
+
val screenWidth = (metrics.widthPixels / metrics.density).toDouble()
|
114
|
+
val screenHeight = (metrics.heightPixels / metrics.density).toDouble()
|
115
|
+
|
116
|
+
return Dimensions(screenWidth, screenHeight)
|
117
|
+
}
|
118
|
+
else -> {
|
119
|
+
val displayMetrics = reactContext.resources.displayMetrics
|
120
|
+
|
121
|
+
reactContext.currentActivity?.windowManager?.currentWindowMetrics?.bounds?.let {
|
122
|
+
val boundsWidth = (it.width() / displayMetrics.density).toDouble()
|
123
|
+
val boundsHeight = (it.height() / displayMetrics.density).toDouble()
|
124
|
+
|
125
|
+
return Dimensions(boundsWidth, boundsHeight)
|
126
|
+
} ?: run {
|
127
|
+
val screenWidth = (displayMetrics.widthPixels / displayMetrics.density).toDouble()
|
128
|
+
val screenHeight = (displayMetrics.heightPixels / displayMetrics.density).toDouble()
|
129
|
+
|
130
|
+
return Dimensions(screenWidth, screenHeight)
|
131
|
+
}
|
132
|
+
}
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
override fun getStatusBarDimensions(): Dimensions {
|
137
|
+
val screenWidth = getScreenDimensions().width
|
138
|
+
|
139
|
+
return Dimensions(screenWidth, _insets.getInsets().top)
|
140
|
+
}
|
141
|
+
|
142
|
+
override fun getNavigationBarDimensions(): Dimensions {
|
143
|
+
val screenWidth = getScreenDimensions().width
|
144
|
+
|
145
|
+
return Dimensions(screenWidth, _insets.getInsets().bottom)
|
146
|
+
}
|
147
|
+
|
148
|
+
override fun getPrefersRtlDirection(): Boolean {
|
149
|
+
// forced by React Native
|
150
|
+
val sharedPrefs = reactContext.getSharedPreferences(
|
151
|
+
"com.facebook.react.modules.i18nmanager.I18nUtil",
|
152
|
+
Context.MODE_PRIVATE
|
153
|
+
)
|
154
|
+
val hasForcedRtl = sharedPrefs.getBoolean("RCTI18nUtil_forceRTL", false)
|
155
|
+
// user preferences
|
156
|
+
val isRtl = TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL
|
157
|
+
|
158
|
+
return hasForcedRtl || isRtl
|
159
|
+
}
|
160
|
+
|
161
|
+
override fun setRootViewBackgroundColor(color: Double) {
|
162
|
+
reactContext.currentActivity?.let { activity ->
|
163
|
+
activity.window?.decorView?.let { decorView ->
|
164
|
+
activity.runOnUiThread {
|
165
|
+
decorView.rootView.setBackgroundColor(color.toInt())
|
166
|
+
}
|
167
|
+
}
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
171
|
+
@Suppress("DEPRECATION")
|
172
|
+
override fun setNavigationBarBackgroundColor(color: Double) {
|
173
|
+
reactContext.currentActivity?.let { activity ->
|
174
|
+
activity.runOnUiThread {
|
175
|
+
activity.window.navigationBarColor = color.toInt()
|
176
|
+
}
|
177
|
+
}
|
178
|
+
}
|
179
|
+
|
180
|
+
override fun setNavigationBarHidden(isHidden: Boolean) {
|
181
|
+
reactContext.currentActivity?.let { activity ->
|
182
|
+
WindowInsetsControllerCompat(activity.window, activity.window.decorView).apply {
|
183
|
+
activity.window?.decorView?.let { decorView ->
|
184
|
+
@Suppress("DEPRECATION")
|
185
|
+
activity.runOnUiThread {
|
186
|
+
if (isHidden) {
|
187
|
+
// below Android 11, we need to use window flags to hide the navigation bar
|
188
|
+
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
|
189
|
+
decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
190
|
+
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
|
191
|
+
} else {
|
192
|
+
hide(WindowInsetsCompat.Type.navigationBars())
|
193
|
+
systemBarsBehavior =
|
194
|
+
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
195
|
+
}
|
196
|
+
|
197
|
+
// dispatch new insets to invoke the insets listener
|
198
|
+
val newInsets = WindowInsetsCompat.Builder()
|
199
|
+
.setInsets(WindowInsetsCompat.Type.navigationBars(), androidx.core.graphics.Insets.of(0, 0, 0, 0))
|
200
|
+
.build()
|
201
|
+
|
202
|
+
ViewCompat.dispatchApplyWindowInsets(activity.findViewById(android.R.id.content), newInsets)
|
203
|
+
} else {
|
204
|
+
show(WindowInsetsCompat.Type.navigationBars())
|
205
|
+
}
|
206
|
+
}
|
207
|
+
}
|
208
|
+
}
|
209
|
+
}
|
210
|
+
}
|
211
|
+
|
212
|
+
override fun setStatusBarHidden(isHidden: Boolean) {
|
213
|
+
reactContext.currentActivity?.let { activity ->
|
214
|
+
WindowInsetsControllerCompat(activity.window, activity.window.decorView).apply {
|
215
|
+
activity.window?.let { window ->
|
216
|
+
@Suppress("DEPRECATION")
|
217
|
+
activity.runOnUiThread {
|
218
|
+
if (isHidden) {
|
219
|
+
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
|
220
|
+
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
|
221
|
+
window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
|
222
|
+
} else {
|
223
|
+
hide(WindowInsetsCompat.Type.statusBars())
|
224
|
+
}
|
225
|
+
} else {
|
226
|
+
show(WindowInsetsCompat.Type.statusBars())
|
227
|
+
}
|
228
|
+
}
|
229
|
+
}
|
230
|
+
}
|
231
|
+
}
|
232
|
+
}
|
233
|
+
|
234
|
+
@Suppress("DEPRECATION")
|
235
|
+
override fun setStatusBarBackgroundColor(color: Double) {
|
236
|
+
reactContext.currentActivity?.let { activity ->
|
237
|
+
activity.runOnUiThread {
|
238
|
+
activity.window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
|
239
|
+
activity.window.statusBarColor = color.toInt()
|
240
|
+
}
|
241
|
+
}
|
242
|
+
}
|
243
|
+
|
244
|
+
override fun setImmersiveMode(isEnabled: Boolean) {
|
245
|
+
this.setStatusBarHidden(isEnabled)
|
246
|
+
this.setNavigationBarHidden(isEnabled)
|
247
|
+
}
|
248
|
+
|
249
|
+
override fun getMiniRuntime(): UnistylesNativeMiniRuntime {
|
250
|
+
return _miniRuntime
|
251
|
+
}
|
252
|
+
|
253
|
+
private fun buildMiniRuntime(): UnistylesNativeMiniRuntime {
|
254
|
+
val orientation = this.getOrientation()
|
255
|
+
|
256
|
+
return UnistylesNativeMiniRuntime(
|
257
|
+
colorScheme = this.getColorScheme(),
|
258
|
+
screen = this.getScreenDimensions(),
|
259
|
+
contentSizeCategory = this.getContentSizeCategory(),
|
260
|
+
insets = this.getInsets(),
|
261
|
+
pixelRatio = this.getPixelRatio(),
|
262
|
+
fontScale = this.getFontScale(),
|
263
|
+
rtl = this.getPrefersRtlDirection(),
|
264
|
+
statusBar = this.getStatusBarDimensions(),
|
265
|
+
navigationBar = this.getNavigationBarDimensions(),
|
266
|
+
isPortrait = orientation == Orientation.PORTRAIT,
|
267
|
+
isLandscape = orientation == Orientation.LANDSCAPE
|
268
|
+
)
|
269
|
+
}
|
270
|
+
|
271
|
+
private fun diffMiniRuntime(): Array<UnistyleDependency> {
|
272
|
+
val newMiniRuntime = this.buildMiniRuntime()
|
273
|
+
val changedDependencies = diffMiniRuntimes(this._miniRuntime, newMiniRuntime)
|
274
|
+
|
275
|
+
if (changedDependencies.isNotEmpty()) {
|
276
|
+
this._miniRuntime = newMiniRuntime
|
277
|
+
}
|
278
|
+
|
279
|
+
return changedDependencies
|
280
|
+
}
|
281
|
+
|
282
|
+
override fun registerPlatformListener(callback: (dependencies: Array<UnistyleDependency>) -> Unit) {
|
283
|
+
this._listener.addPlatformListener(callback)
|
284
|
+
}
|
285
|
+
|
286
|
+
override fun registerImeListener(callback: () -> Unit) {
|
287
|
+
this._insets.addImeListener(callback)
|
288
|
+
}
|
289
|
+
|
290
|
+
override fun unregisterPlatformListeners() {
|
291
|
+
this._listener.removePlatformListeners()
|
292
|
+
this._insets.removeImeListeners()
|
293
|
+
}
|
294
|
+
|
295
|
+
private fun enableEdgeToEdge() {
|
296
|
+
reactContext.currentActivity?.let { activity ->
|
297
|
+
activity.runOnUiThread {
|
298
|
+
WindowCompat.setDecorFitsSystemWindows(activity.window, false)
|
299
|
+
}
|
300
|
+
}
|
301
|
+
}
|
302
|
+
}
|
@@ -0,0 +1,148 @@
|
|
1
|
+
package com.unistyles
|
2
|
+
|
3
|
+
import android.graphics.Rect
|
4
|
+
import android.os.Build
|
5
|
+
import android.view.View
|
6
|
+
import android.view.Window
|
7
|
+
import android.view.WindowManager
|
8
|
+
import androidx.core.view.ViewCompat
|
9
|
+
import androidx.core.view.WindowInsetsAnimationCompat
|
10
|
+
import androidx.core.view.WindowInsetsCompat
|
11
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
12
|
+
import com.margelo.nitro.unistyles.Insets
|
13
|
+
import com.margelo.nitro.unistyles.UnistyleDependency
|
14
|
+
|
15
|
+
typealias CxxImeListener = () -> Unit
|
16
|
+
|
17
|
+
class NativePlatformInsets(private val reactContext: ReactApplicationContext, private val diffMiniRuntime: () -> Array<UnistyleDependency>) {
|
18
|
+
private val _imeListeners: MutableList<CxxImeListener> = mutableListOf()
|
19
|
+
private var _insets: Insets = Insets(0.0, 0.0, 0.0, 0.0, 0.0)
|
20
|
+
|
21
|
+
fun getInsets(): Insets {
|
22
|
+
val density = reactContext.resources.displayMetrics.density
|
23
|
+
|
24
|
+
return Insets(
|
25
|
+
this._insets.top / density,
|
26
|
+
this._insets.bottom / density,
|
27
|
+
this._insets.left / density,
|
28
|
+
this._insets.right / density,
|
29
|
+
this._insets.ime / density
|
30
|
+
)
|
31
|
+
}
|
32
|
+
|
33
|
+
fun setInsets(insetsCompat: WindowInsetsCompat, window: Window, animatedBottomInsets: Double?) {
|
34
|
+
// below Android 11, we need to use window flags to detect status bar visibility
|
35
|
+
val isStatusBarVisible = when(Build.VERSION.SDK_INT) {
|
36
|
+
in 30..Int.MAX_VALUE -> {
|
37
|
+
insetsCompat.isVisible(WindowInsetsCompat.Type.statusBars())
|
38
|
+
}
|
39
|
+
else -> {
|
40
|
+
@Suppress("DEPRECATION")
|
41
|
+
window.attributes.flags and WindowManager.LayoutParams.FLAG_FULLSCREEN != WindowManager.LayoutParams.FLAG_FULLSCREEN
|
42
|
+
}
|
43
|
+
}
|
44
|
+
// React Native is forcing insets to make status bar translucent
|
45
|
+
// so we need to calculate top inset manually, as WindowInsetCompat will always return 0
|
46
|
+
val statusBarTopInset = when(isStatusBarVisible) {
|
47
|
+
true -> {
|
48
|
+
val visibleRect = Rect()
|
49
|
+
|
50
|
+
window.decorView.getWindowVisibleDisplayFrame(visibleRect)
|
51
|
+
|
52
|
+
visibleRect.top
|
53
|
+
}
|
54
|
+
false -> 0
|
55
|
+
}
|
56
|
+
|
57
|
+
val insets = insetsCompat.getInsets(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout())
|
58
|
+
|
59
|
+
// Android 10 and below - set bottom insets to 0 while keyboard is visible and use default bottom insets otherwise
|
60
|
+
// Android 11 and above - animate bottom insets while keyboard is appearing and disappearing
|
61
|
+
val imeInsets = if (Build.VERSION.SDK_INT >= 30) {
|
62
|
+
animatedBottomInsets ?: this._insets.ime
|
63
|
+
} else {
|
64
|
+
val nextBottomInset = insetsCompat.getInsets(WindowInsetsCompat.Type.ime()).bottom - insets.bottom
|
65
|
+
|
66
|
+
// call new IME event here, as for SDK >= 30 it's called in AnimationCallback
|
67
|
+
this@NativePlatformInsets.emitImeEvent()
|
68
|
+
|
69
|
+
if (nextBottomInset < 0) {
|
70
|
+
0
|
71
|
+
} else {
|
72
|
+
nextBottomInset
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
this._insets = Insets(
|
77
|
+
statusBarTopInset.toDouble(),
|
78
|
+
insets.bottom.toDouble(),
|
79
|
+
insets.left.toDouble(),
|
80
|
+
insets.right.toDouble(),
|
81
|
+
imeInsets.toDouble()
|
82
|
+
)
|
83
|
+
|
84
|
+
diffMiniRuntime()
|
85
|
+
}
|
86
|
+
|
87
|
+
fun startInsetsListener() {
|
88
|
+
reactContext.currentActivity?.let { activity ->
|
89
|
+
activity.findViewById<View>(android.R.id.content)?.let { mainView ->
|
90
|
+
ViewCompat.setOnApplyWindowInsetsListener(mainView) { _, insets ->
|
91
|
+
setInsets(insets, activity.window, null)
|
92
|
+
|
93
|
+
insets
|
94
|
+
}
|
95
|
+
|
96
|
+
// IME insets are available from Android 11
|
97
|
+
if (Build.VERSION.SDK_INT >= 30) {
|
98
|
+
ViewCompat.setWindowInsetsAnimationCallback(
|
99
|
+
mainView,
|
100
|
+
object : WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_STOP) {
|
101
|
+
override fun onProgress(
|
102
|
+
insets: WindowInsetsCompat,
|
103
|
+
runningAnimations: List<WindowInsetsAnimationCompat>
|
104
|
+
): WindowInsetsCompat {
|
105
|
+
runningAnimations.firstOrNull()?.let {
|
106
|
+
val bottomInset = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom.toDouble() - this@NativePlatformInsets._insets.bottom
|
107
|
+
val nextBottomInset = if (bottomInset < 0) {
|
108
|
+
0.0
|
109
|
+
} else {
|
110
|
+
bottomInset
|
111
|
+
}
|
112
|
+
|
113
|
+
this@NativePlatformInsets.setInsets(insets, activity.window, nextBottomInset)
|
114
|
+
this@NativePlatformInsets.emitImeEvent()
|
115
|
+
}
|
116
|
+
|
117
|
+
return insets
|
118
|
+
}
|
119
|
+
}
|
120
|
+
)
|
121
|
+
}
|
122
|
+
}
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
fun emitImeEvent() {
|
127
|
+
_imeListeners.forEach { listener ->
|
128
|
+
listener()
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
132
|
+
fun stopInsetsListener() {
|
133
|
+
reactContext.currentActivity?.let { activity ->
|
134
|
+
activity.window?.decorView?.let { view ->
|
135
|
+
ViewCompat.setOnApplyWindowInsetsListener(view, null)
|
136
|
+
ViewCompat.setWindowInsetsAnimationCallback(view, null)
|
137
|
+
}
|
138
|
+
}
|
139
|
+
}
|
140
|
+
|
141
|
+
fun addImeListener(listener: CxxImeListener) {
|
142
|
+
this._imeListeners.add(listener)
|
143
|
+
}
|
144
|
+
|
145
|
+
fun removeImeListeners() {
|
146
|
+
this._imeListeners.clear()
|
147
|
+
}
|
148
|
+
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
package com.unistyles
|
2
|
+
|
3
|
+
import android.content.BroadcastReceiver
|
4
|
+
import android.content.Context
|
5
|
+
import android.content.Intent
|
6
|
+
import android.content.IntentFilter
|
7
|
+
import android.os.Handler
|
8
|
+
import android.os.Looper
|
9
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
10
|
+
import com.margelo.nitro.unistyles.UnistyleDependency
|
11
|
+
|
12
|
+
typealias CxxDependencyListener = (dependencies: Array<UnistyleDependency>) -> Unit
|
13
|
+
|
14
|
+
class NativePlatformListener(private val reactContext: ReactApplicationContext, private val diffMiniRuntime: () -> Array<UnistyleDependency>) {
|
15
|
+
private val _dependencyListeners: MutableList<CxxDependencyListener> = mutableListOf()
|
16
|
+
|
17
|
+
private val configurationChangeReceiver = object : BroadcastReceiver() {
|
18
|
+
override fun onReceive(context: Context, intent: Intent) {
|
19
|
+
Handler(Looper.getMainLooper()).postDelayed({
|
20
|
+
this@NativePlatformListener.onConfigChange()
|
21
|
+
}, 10)
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
init {
|
26
|
+
reactContext.registerReceiver(configurationChangeReceiver, IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED))
|
27
|
+
}
|
28
|
+
|
29
|
+
fun invalidate() {
|
30
|
+
reactContext.unregisterReceiver(configurationChangeReceiver)
|
31
|
+
}
|
32
|
+
|
33
|
+
fun addPlatformListener(listener: CxxDependencyListener) {
|
34
|
+
this._dependencyListeners.add(listener)
|
35
|
+
}
|
36
|
+
|
37
|
+
fun removePlatformListeners() {
|
38
|
+
this._dependencyListeners.clear()
|
39
|
+
}
|
40
|
+
|
41
|
+
private fun emitCxxEvent(dependencies: Array<UnistyleDependency>) {
|
42
|
+
this._dependencyListeners.forEach { listener ->
|
43
|
+
listener(dependencies)
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
fun onConfigChange() {
|
48
|
+
val changedDependencies = diffMiniRuntime()
|
49
|
+
|
50
|
+
if (changedDependencies.isNotEmpty()) {
|
51
|
+
emitCxxEvent(changedDependencies)
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
@@ -16,7 +16,7 @@ import com.margelo.nitro.unistyles.HybridNativePlatformSpec
|
|
16
16
|
class UnistylesModule(reactContext: ReactApplicationContext): NativeTurboUnistylesSpec(reactContext), TurboModuleWithJSIBindings {
|
17
17
|
@DoNotStrip
|
18
18
|
private var mHybridData: HybridData?
|
19
|
-
private val _nativePlatform =
|
19
|
+
private val _nativePlatform = NativePlatformAndroid(reactContext)
|
20
20
|
|
21
21
|
companion object {
|
22
22
|
const val NAME = NativeTurboUnistylesSpec.NAME
|
@@ -26,6 +26,10 @@ class UnistylesModule(reactContext: ReactApplicationContext): NativeTurboUnistyl
|
|
26
26
|
mHybridData = initializeHybridData(reactContext)
|
27
27
|
}
|
28
28
|
|
29
|
+
override fun invalidate() {
|
30
|
+
_nativePlatform.invalidate()
|
31
|
+
}
|
32
|
+
|
29
33
|
private fun initializeHybridData(reactContext: ReactApplicationContext): HybridData {
|
30
34
|
val runtimeExecutor = reactContext.catalystInstance?.runtimeExecutor
|
31
35
|
?: throw IllegalStateException("Unistyles: React Native runtime executor is not available. Please follow installation guides.")
|
package/cxx/core/UnistyleData.h
CHANGED
@@ -12,7 +12,7 @@ struct UnistyleData {
|
|
12
12
|
: unistyle{unistyle}, variants(std::move(variants)), dynamicFunctionMetadata{std::move(arguments)} {}
|
13
13
|
|
14
14
|
UnistyleData(const UnistyleData&) = delete;
|
15
|
-
UnistyleData(UnistyleData&& other)
|
15
|
+
UnistyleData(UnistyleData&& other) = delete;
|
16
16
|
|
17
17
|
core::Unistyle::Shared unistyle;
|
18
18
|
core::Variants variants;
|
@@ -32,7 +32,6 @@ inline static Unistyle::Shared unistyleFromStaticStyleSheet(jsi::Runtime& rt, js
|
|
32
32
|
return exoticUnistyle;
|
33
33
|
}
|
34
34
|
|
35
|
-
|
36
35
|
inline static std::vector<Unistyle::Shared> unistylesFromNonExistentNativeState(jsi::Runtime& rt, jsi::Object& value) {
|
37
36
|
auto hasUnistyleName = value.hasProperty(rt, helpers::NAME_STYLE_KEY.c_str());
|
38
37
|
|
@@ -71,7 +70,7 @@ inline static jsi::Object generateUnistylesPrototype(
|
|
71
70
|
auto hostFn = jsi::Function::createFromHostFunction(rt, jsi::PropNameID::forUtf8(rt, "getStyle"), 0, [unistyle, unistylesRuntime](jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *args, size_t count){
|
72
71
|
auto variants = helpers::variantsToPairs(rt, thisValue.asObject(rt).getProperty(rt, "variants").asObject(rt));
|
73
72
|
auto arguments = helpers::parseDynamicFunctionArguments(rt, thisValue.asObject(rt).getProperty(rt, "arguments").asObject(rt).asArray(rt));
|
74
|
-
|
73
|
+
|
75
74
|
parser::Parser(unistylesRuntime).rebuildUnistyle(rt, unistyle->parent, unistyle, variants, std::make_optional<std::vector<folly::dynamic>>(arguments));
|
76
75
|
|
77
76
|
return jsi::Value(rt, unistyle->parsedStyle.value()).asObject(rt);
|
@@ -31,7 +31,7 @@ RootShadowNode::Unshared core::UnistylesCommitHook::shadowTreeWillCommit(
|
|
31
31
|
auto& registry = core::UnistylesRegistry::get();
|
32
32
|
auto& shadowLeafUpdates = registry.trafficController.getUpdates();
|
33
33
|
|
34
|
-
// oops,
|
34
|
+
// oops, no updates from Unistyles yet, skip it!
|
35
35
|
if (shadowLeafUpdates.size() == 0) {
|
36
36
|
return newRootShadowNode;
|
37
37
|
}
|
@@ -23,6 +23,6 @@ void core::UnistylesMountHook::shadowTreeDidMount(RootShadowNode::Shared const &
|
|
23
23
|
auto& registry = core::UnistylesRegistry::get();
|
24
24
|
|
25
25
|
if (!registry.trafficController.shouldStop()) {
|
26
|
-
shadow::ShadowTreeManager::updateShadowTree(this->
|
26
|
+
shadow::ShadowTreeManager::updateShadowTree(this->_uiManager->getShadowTreeRegistry());
|
27
27
|
}
|
28
28
|
}
|
@@ -78,10 +78,6 @@ void core::UnistylesRegistry::linkShadowNodeWithUnistyle(
|
|
78
78
|
auto parser = parser::Parser(nullptr);
|
79
79
|
shadow::ShadowLeafUpdates updates;
|
80
80
|
|
81
|
-
if (!this->_shadowRegistry[&rt].contains(shadowNodeFamily)) {
|
82
|
-
this->_shadowRegistry[&rt][shadowNodeFamily] = {};
|
83
|
-
}
|
84
|
-
|
85
81
|
std::for_each(unistyles.begin(), unistyles.end(), [&, this](Unistyle::Shared unistyle){
|
86
82
|
this->_shadowRegistry[&rt][shadowNodeFamily].emplace_back(std::make_shared<UnistyleData>(unistyle, variants, arguments));
|
87
83
|
|
@@ -104,16 +100,11 @@ void core::UnistylesRegistry::linkShadowNodeWithUnistyle(
|
|
104
100
|
|
105
101
|
void core::UnistylesRegistry::unlinkShadowNodeWithUnistyles(jsi::Runtime& rt, const ShadowNodeFamily* shadowNodeFamily) {
|
106
102
|
this->_shadowRegistry[&rt].erase(shadowNodeFamily);
|
107
|
-
|
103
|
+
this->trafficController.removeShadowNode(shadowNodeFamily);
|
108
104
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
if (targetStyleSheet == nullptr) {
|
113
|
-
return nullptr;
|
105
|
+
if (this->_shadowRegistry[&rt].empty()) {
|
106
|
+
this->_shadowRegistry.erase(&rt);
|
114
107
|
}
|
115
|
-
|
116
|
-
return targetStyleSheet.get()->unistyles[styleKey];
|
117
108
|
}
|
118
109
|
|
119
110
|
std::shared_ptr<core::StyleSheet> core::UnistylesRegistry::addStyleSheet(jsi::Runtime& rt, int unid, core::StyleSheetType type, jsi::Object&& rawValue) {
|
@@ -162,7 +153,7 @@ void core::UnistylesRegistry::shadowLeafUpdateFromUnistyle(jsi::Runtime& rt, Uni
|
|
162
153
|
for (const auto& [family, unistyles] : this->_shadowRegistry[&rt]) {
|
163
154
|
for (const auto& unistyleData : unistyles) {
|
164
155
|
if (unistyleData->unistyle == unistyle) {
|
165
|
-
updates[family] = parser.parseStylesToShadowTreeStyles(rt, {unistyleData});
|
156
|
+
updates[family] = parser.parseStylesToShadowTreeStyles(rt, { unistyleData });
|
166
157
|
}
|
167
158
|
}
|
168
159
|
}
|
@@ -41,7 +41,6 @@ struct UnistylesRegistry: public StyleSheetRegistry {
|
|
41
41
|
void unlinkShadowNodeWithUnistyles(jsi::Runtime& rt, const ShadowNodeFamily*);
|
42
42
|
std::shared_ptr<core::StyleSheet> addStyleSheet(jsi::Runtime& rt, int tag, core::StyleSheetType type, jsi::Object&& rawValue);
|
43
43
|
DependencyMap buildDependencyMap(jsi::Runtime& rt, std::vector<UnistyleDependency>& deps);
|
44
|
-
Unistyle::Shared findUnistyleFromKey(jsi::Runtime& rt, std::string styleKey, int tag);
|
45
44
|
void shadowLeafUpdateFromUnistyle(jsi::Runtime& rt, Unistyle::Shared unistyle);
|
46
45
|
shadow::ShadowTrafficController trafficController{};
|
47
46
|
|
@@ -50,7 +49,7 @@ private:
|
|
50
49
|
|
51
50
|
std::unordered_map<jsi::Runtime*, UnistylesState> _states{};
|
52
51
|
std::unordered_map<jsi::Runtime*, std::unordered_map<int, std::shared_ptr<core::StyleSheet>>> _styleSheetRegistry{};
|
53
|
-
std::unordered_map<jsi::Runtime*, std::unordered_map<const ShadowNodeFamily*, std::vector<std::shared_ptr<UnistyleData>>>> _shadowRegistry{};
|
52
|
+
std::unordered_map<jsi::Runtime*, std::unordered_map<const ShadowNodeFamily*, std::vector<const std::shared_ptr<UnistyleData>>>> _shadowRegistry{};
|
54
53
|
};
|
55
54
|
|
56
55
|
inline UnistylesRegistry& UnistylesRegistry::get() {
|
@@ -25,7 +25,7 @@ std::optional<std::string>& core::UnistylesState::getCurrentThemeName() {
|
|
25
25
|
|
26
26
|
jsi::Object core::UnistylesState::getCurrentJSTheme() {
|
27
27
|
auto hasSomeThemes = _registeredThemeNames.size() > 0;
|
28
|
-
|
28
|
+
|
29
29
|
if (!hasSomeThemes && !this->hasUserConfig) {
|
30
30
|
helpers::assertThat(*_rt, false, "Unistyles: One of your stylesheets is trying to get the theme, but no theme has been selected yet. Did you forget to call StyleSheet.configure? If you called it, make sure you did so before any StyleSheet.create.");
|
31
31
|
}
|
@@ -99,15 +99,18 @@ int core::UnistylesState::parseColor(jsi::Value& maybeColor) {
|
|
99
99
|
if (!maybeColor.isString()) {
|
100
100
|
return 0;
|
101
101
|
}
|
102
|
-
|
102
|
+
|
103
103
|
auto colorString = maybeColor.asString(*_rt);
|
104
|
-
|
104
|
+
|
105
105
|
if (!this->_colorCache.contains(colorString.utf8(*_rt).c_str())) {
|
106
|
-
|
107
|
-
|
108
|
-
|
106
|
+
#ifdef ANDROID
|
107
|
+
int color = this->_processColorFn.get()->call(*_rt, colorString).asNumber();
|
108
|
+
#else
|
109
|
+
uint32_t color = this->_processColorFn.get()->call(*_rt, colorString).asNumber();
|
110
|
+
#endif
|
111
|
+
|
109
112
|
this->_colorCache[colorString.utf8(*_rt).c_str()] = color ? color : 0;
|
110
113
|
}
|
111
|
-
|
114
|
+
|
112
115
|
return this->_colorCache[colorString.utf8(*_rt).c_str()];
|
113
116
|
}
|
@@ -15,7 +15,7 @@ double HybridStyleSheet::getUnid() {
|
|
15
15
|
|
16
16
|
jsi::Value HybridStyleSheet::create(jsi::Runtime& rt, const jsi::Value &thisVal, const jsi::Value *arguments, size_t count) {
|
17
17
|
if (count == 1) {
|
18
|
-
helpers::assertThat(rt,
|
18
|
+
helpers::assertThat(rt, false, "Unistyles is not initialized correctly. Please add babel plugin to your babel config.");
|
19
19
|
}
|
20
20
|
|
21
21
|
// second argument is hidden, so validation is perfectly fine
|
@@ -128,7 +128,7 @@ void HybridStyleSheet::parseSettings(jsi::Runtime &rt, jsi::Object settings) {
|
|
128
128
|
void HybridStyleSheet::parseBreakpoints(jsi::Runtime &rt, jsi::Object breakpoints){
|
129
129
|
helpers::Breakpoints sortedBreakpoints = helpers::jsiBreakpointsToVecPairs(rt, std::move(breakpoints));
|
130
130
|
|
131
|
-
helpers::assertThat(rt, sortedBreakpoints.
|
131
|
+
helpers::assertThat(rt, !sortedBreakpoints.empty(), "StyleSheet.configure's breakpoints can't be empty.");
|
132
132
|
helpers::assertThat(rt, sortedBreakpoints.front().second == 0, "StyleSheet.configure's first breakpoint must start from 0.");
|
133
133
|
|
134
134
|
auto& registry = core::UnistylesRegistry::get();
|
@@ -197,7 +197,7 @@ void HybridStyleSheet::verifyAndSelectTheme(jsi::Runtime &rt) {
|
|
197
197
|
|
198
198
|
void HybridStyleSheet::setThemeFromColorScheme(jsi::Runtime& rt) {
|
199
199
|
auto& state = core::UnistylesRegistry::get().getState(rt);
|
200
|
-
|
200
|
+
auto colorScheme = static_cast<ColorScheme>(this->_unistylesRuntime->getColorScheme());
|
201
201
|
|
202
202
|
switch (colorScheme) {
|
203
203
|
case ColorScheme::LIGHT:
|
@@ -232,7 +232,7 @@ void HybridStyleSheet::loadExternalMethods(const jsi::Value& thisValue, jsi::Run
|
|
232
232
|
void HybridStyleSheet::registerHooks(jsi::Runtime& rt) {
|
233
233
|
// cleanup Shadow updates
|
234
234
|
core::UnistylesRegistry::get().trafficController.restore();
|
235
|
-
|
235
|
+
|
236
236
|
this->_unistylesCommitHook = std::make_shared<core::UnistylesCommitHook>(this->_uiManager);
|
237
237
|
this->_unistylesMountHook = std::make_shared<core::UnistylesMountHook>(this->_uiManager, this->_unistylesRuntime);
|
238
238
|
}
|
@@ -248,20 +248,20 @@ void HybridStyleSheet::onPlatformDependenciesChange(std::vector<UnistyleDependen
|
|
248
248
|
auto dependencies = std::move(unistylesDependencies);
|
249
249
|
|
250
250
|
// re-compute new breakpoint
|
251
|
-
auto dimensionsIt = std::find(
|
251
|
+
auto dimensionsIt = std::find(unistylesDependencies.begin(), unistylesDependencies.end(), UnistyleDependency::DIMENSIONS);
|
252
252
|
|
253
|
-
if (dimensionsIt !=
|
253
|
+
if (dimensionsIt != unistylesDependencies.end()) {
|
254
254
|
registry.getState(rt).computeCurrentBreakpoint(this->_unistylesRuntime->getScreen().width);
|
255
255
|
}
|
256
256
|
|
257
257
|
// check if color scheme changed and then if Unistyles state depend on it (adaptive themes)
|
258
|
-
auto colorSchemeIt = std::find(
|
259
|
-
auto hasNewColorScheme = colorSchemeIt !=
|
258
|
+
auto colorSchemeIt = std::find(unistylesDependencies.begin(), unistylesDependencies.end(), UnistyleDependency::COLORSCHEME);
|
259
|
+
auto hasNewColorScheme = colorSchemeIt != unistylesDependencies.end();
|
260
260
|
|
261
261
|
// in a later step, we will rebuild only Unistyles with mounted StyleSheets
|
262
262
|
// however, user may have StyleSheets with components that haven't mounted yet
|
263
263
|
// we need to rebuild all dependent StyleSheets as well
|
264
|
-
auto dependentStyleSheets = registry.getStyleSheetsToRefresh(rt, hasNewColorScheme,
|
264
|
+
auto dependentStyleSheets = registry.getStyleSheetsToRefresh(rt, hasNewColorScheme, unistylesDependencies.size() > 1);
|
265
265
|
|
266
266
|
if (hasNewColorScheme) {
|
267
267
|
this->_unistylesRuntime->includeDependenciesForColorSchemeChange(dependencies);
|
@@ -269,17 +269,17 @@ void HybridStyleSheet::onPlatformDependenciesChange(std::vector<UnistyleDependen
|
|
269
269
|
|
270
270
|
auto dependencyMap = registry.buildDependencyMap(rt, dependencies);
|
271
271
|
|
272
|
-
if (dependencyMap.
|
272
|
+
if (dependencyMap.empty()) {
|
273
273
|
this->notifyJSListeners(dependencies);
|
274
274
|
|
275
275
|
return;
|
276
276
|
}
|
277
277
|
|
278
278
|
parser.rebuildUnistylesInDependencyMap(rt, dependencyMap, dependentStyleSheets);
|
279
|
-
parser.rebuildShadowLeafUpdates(dependencyMap);
|
280
|
-
|
279
|
+
parser.rebuildShadowLeafUpdates(rt, dependencyMap);
|
280
|
+
|
281
281
|
this->notifyJSListeners(dependencies);
|
282
|
-
shadow::ShadowTreeManager::updateShadowTree(rt);
|
282
|
+
shadow::ShadowTreeManager::updateShadowTree(UIManagerBinding::getBinding(rt)->getUIManager().getShadowTreeRegistry());
|
283
283
|
});
|
284
284
|
}
|
285
285
|
|
@@ -298,18 +298,21 @@ void HybridStyleSheet::onImeChange() {
|
|
298
298
|
|
299
299
|
auto dependencyMap = registry.buildDependencyMap(rt, dependencies);
|
300
300
|
|
301
|
-
if (dependencyMap.
|
301
|
+
if (dependencyMap.empty()) {
|
302
302
|
return;
|
303
303
|
}
|
304
|
+
|
305
|
+
std::vector<std::shared_ptr<core::StyleSheet>> styleSheet;
|
306
|
+
|
307
|
+
parser.rebuildUnistylesInDependencyMap(rt, dependencyMap, styleSheet);
|
308
|
+
parser.rebuildShadowLeafUpdates(rt, dependencyMap);
|
304
309
|
|
305
|
-
|
306
|
-
parser.rebuildShadowLeafUpdates(dependencyMap);
|
307
|
-
shadow::ShadowTreeManager::updateShadowTree(rt);
|
310
|
+
shadow::ShadowTreeManager::updateShadowTree(UIManagerBinding::getBinding(rt)->getUIManager().getShadowTreeRegistry());
|
308
311
|
});
|
309
312
|
}
|
310
313
|
|
311
314
|
void HybridStyleSheet::notifyJSListeners(std::vector<UnistyleDependency>& dependencies) {
|
312
|
-
if (dependencies.
|
315
|
+
if (!dependencies.empty()) {
|
313
316
|
std::for_each(this->_changeListeners.begin(), this->_changeListeners.end(), [&](auto& listener){
|
314
317
|
(*listener)(dependencies);
|
315
318
|
});
|
@@ -228,10 +228,6 @@ jsi::Value HybridUnistylesRuntime::getMiniRuntimeAsValue(jsi::Runtime& rt) {
|
|
228
228
|
return obj;
|
229
229
|
}
|
230
230
|
|
231
|
-
jsi::Runtime& HybridUnistylesRuntime::getRuntime() {
|
232
|
-
return *this->_rt;
|
233
|
-
}
|
234
|
-
|
235
231
|
void HybridUnistylesRuntime::registerPlatformListener(const std::function<void(std::vector<UnistyleDependency>)>& listener) {
|
236
232
|
this->_nativePlatform.registerPlatformListener(listener);
|
237
233
|
this->_onDependenciesChange = listener;
|
@@ -67,7 +67,6 @@ struct HybridUnistylesRuntime: public HybridUnistylesRuntimeSpec {
|
|
67
67
|
std::unordered_map<std::string, double> getBreakpoints() override;
|
68
68
|
|
69
69
|
jsi::Value getMiniRuntimeAsValue(jsi::Runtime& rt);
|
70
|
-
jsi::Runtime& getRuntime();
|
71
70
|
void includeDependenciesForColorSchemeChange(std::vector<UnistyleDependency>& deps);
|
72
71
|
void calculateNewThemeAndDependencies(std::vector<UnistyleDependency>& deps);
|
73
72
|
std::function<void(std::function<void(jsi::Runtime&)>&&)> runOnJSThread;
|
package/cxx/parser/Parser.cpp
CHANGED
@@ -93,13 +93,12 @@ void parser::Parser::rebuildUnistylesWithVariants(jsi::Runtime& rt, std::shared_
|
|
93
93
|
continue;
|
94
94
|
}
|
95
95
|
|
96
|
-
// todo skip dynamic functions
|
97
96
|
this->rebuildUnistyle(rt, styleSheet, unistyle, variants, std::nullopt);
|
98
97
|
}
|
99
98
|
}
|
100
99
|
|
101
100
|
// rebuild all unistyles that are affected by platform event
|
102
|
-
void parser::Parser::rebuildUnistylesInDependencyMap(jsi::Runtime& rt, DependencyMap& dependencyMap, std::vector<std::shared_ptr<core::StyleSheet
|
101
|
+
void parser::Parser::rebuildUnistylesInDependencyMap(jsi::Runtime& rt, DependencyMap& dependencyMap, std::vector<std::shared_ptr<core::StyleSheet>>& styleSheets) {
|
103
102
|
std::unordered_map<std::shared_ptr<StyleSheet>, jsi::Value> parsedStyleSheets{};
|
104
103
|
std::unordered_map<std::shared_ptr<core::Unistyle>, bool> parsedUnistyles{};
|
105
104
|
|
@@ -121,7 +120,7 @@ void parser::Parser::rebuildUnistylesInDependencyMap(jsi::Runtime& rt, Dependenc
|
|
121
120
|
auto& unistyle = unistyleData->unistyle;
|
122
121
|
|
123
122
|
// for RN styles or inline styles, compute styles only once
|
124
|
-
if (unistyle->styleKey == helpers::EXOTIC_STYLE_KEY
|
123
|
+
if (unistyle->styleKey == helpers::EXOTIC_STYLE_KEY) {
|
125
124
|
if (!unistyleData->parsedStyle.has_value()) {
|
126
125
|
unistyleData->parsedStyle = jsi::Value(rt, unistyle->rawValue).asObject(rt);
|
127
126
|
|
@@ -206,10 +205,9 @@ void parser::Parser::rebuildUnistyle(jsi::Runtime& rt, std::shared_ptr<StyleShee
|
|
206
205
|
}
|
207
206
|
|
208
207
|
// convert dependency map to shadow tree updates
|
209
|
-
void parser::Parser::rebuildShadowLeafUpdates(core::DependencyMap& dependencyMap) {
|
208
|
+
void parser::Parser::rebuildShadowLeafUpdates(jsi::Runtime& rt, core::DependencyMap& dependencyMap) {
|
210
209
|
shadow::ShadowLeafUpdates updates;
|
211
210
|
auto& registry = core::UnistylesRegistry::get();
|
212
|
-
auto& rt = this->_unistylesRuntime->getRuntime();
|
213
211
|
|
214
212
|
for (const auto& [shadowNode, unistyles] : dependencyMap) {
|
215
213
|
auto rawProps = this->parseStylesToShadowTreeStyles(rt, unistyles);
|
@@ -218,8 +216,6 @@ void parser::Parser::rebuildShadowLeafUpdates(core::DependencyMap& dependencyMap
|
|
218
216
|
}
|
219
217
|
|
220
218
|
registry.trafficController.setUpdates(updates);
|
221
|
-
|
222
|
-
// this is required, we need to indicate that there are new changes
|
223
219
|
registry.trafficController.resumeUnistylesTraffic();
|
224
220
|
}
|
225
221
|
|
@@ -764,26 +760,6 @@ folly::dynamic parser::Parser::parseStylesToShadowTreeStyles(jsi::Runtime& rt, c
|
|
764
760
|
return jsi::dynamicFromValue(rt, std::move(convertedStyles));
|
765
761
|
}
|
766
762
|
|
767
|
-
folly::dynamic parser::Parser::parseUnistyleToShadowTreeStyles(jsi::Runtime& rt, const Unistyle::Shared unistyle) {
|
768
|
-
jsi::Object convertedStyles = jsi::Object(rt);
|
769
|
-
auto& state = core::UnistylesRegistry::get().getState(rt);
|
770
|
-
|
771
|
-
// can happen for exotic styles
|
772
|
-
if (!unistyle->parsedStyle.has_value()) {
|
773
|
-
return nullptr;
|
774
|
-
}
|
775
|
-
|
776
|
-
helpers::enumerateJSIObject(rt, unistyle->parsedStyle.value(), [&](const std::string& propertyName, jsi::Value& propertyValue){
|
777
|
-
if (this->isColor(propertyName)) {
|
778
|
-
return convertedStyles.setProperty(rt, propertyName.c_str(), jsi::Value(state.parseColor(propertyValue)));
|
779
|
-
}
|
780
|
-
|
781
|
-
convertedStyles.setProperty(rt, propertyName.c_str(), propertyValue);
|
782
|
-
});
|
783
|
-
|
784
|
-
return jsi::dynamicFromValue(rt, std::move(convertedStyles));
|
785
|
-
}
|
786
|
-
|
787
763
|
// check is styleKey contains color
|
788
764
|
bool parser::Parser::isColor(const std::string& propertyName) {
|
789
765
|
std::string str = propertyName;
|
package/cxx/parser/Parser.h
CHANGED
@@ -24,9 +24,8 @@ struct Parser {
|
|
24
24
|
void buildUnistyles(jsi::Runtime& rt, std::shared_ptr<StyleSheet> styleSheet);
|
25
25
|
void parseUnistyles(jsi::Runtime& rt, std::shared_ptr<StyleSheet> styleSheet);
|
26
26
|
void rebuildUnistylesWithVariants(jsi::Runtime& rt, std::shared_ptr<StyleSheet> styleSheet, Variants& variants);
|
27
|
-
void rebuildUnistylesInDependencyMap(jsi::Runtime& rt, core::DependencyMap& dependencyMap, std::vector<std::shared_ptr<core::StyleSheet
|
28
|
-
void rebuildShadowLeafUpdates(core::DependencyMap& dependencyMap);
|
29
|
-
folly::dynamic parseUnistyleToShadowTreeStyles(jsi::Runtime& rt, const Unistyle::Shared unistyle);
|
27
|
+
void rebuildUnistylesInDependencyMap(jsi::Runtime& rt, core::DependencyMap& dependencyMap, std::vector<std::shared_ptr<core::StyleSheet>>& styleSheets);
|
28
|
+
void rebuildShadowLeafUpdates(jsi::Runtime& rt, core::DependencyMap& dependencyMap);
|
30
29
|
folly::dynamic parseStylesToShadowTreeStyles(jsi::Runtime& rt, const std::vector<std::shared_ptr<UnistyleData>>& unistyles);
|
31
30
|
void rebuildUnistyle(jsi::Runtime& rt, std::shared_ptr<StyleSheet> styleSheet, Unistyle::Shared unistyle, const Variants& variants, std::optional<std::vector<folly::dynamic>>);
|
32
31
|
|
@@ -13,20 +13,16 @@ struct ShadowTrafficController {
|
|
13
13
|
}
|
14
14
|
|
15
15
|
inline void stopUnistylesTraffic() {
|
16
|
-
std::lock_guard<std::mutex> lock(_mutex);
|
17
|
-
|
18
16
|
this->_canCommit = false;
|
19
17
|
}
|
20
18
|
|
21
19
|
inline void resumeUnistylesTraffic() {
|
22
|
-
std::lock_guard<std::mutex> lock(_mutex);
|
23
|
-
|
24
20
|
this->_canCommit = true;
|
25
21
|
}
|
26
22
|
|
27
23
|
inline shadow::ShadowLeafUpdates& getUpdates() {
|
28
24
|
std::lock_guard<std::mutex> lock(_mutex);
|
29
|
-
|
25
|
+
|
30
26
|
return _unistylesUpdates;
|
31
27
|
}
|
32
28
|
|
@@ -47,6 +43,14 @@ struct ShadowTrafficController {
|
|
47
43
|
targetUpdates.emplace(pair.first, std::move(pair.second));
|
48
44
|
});
|
49
45
|
}
|
46
|
+
|
47
|
+
inline void removeShadowNode(const ShadowNodeFamily* shadowNodeFamily) {
|
48
|
+
std::lock_guard<std::mutex> lock(_mutex);
|
49
|
+
|
50
|
+
if (_unistylesUpdates.contains(shadowNodeFamily)) {
|
51
|
+
_unistylesUpdates.erase(shadowNodeFamily);
|
52
|
+
}
|
53
|
+
}
|
50
54
|
|
51
55
|
inline void restore() {
|
52
56
|
std::lock_guard<std::mutex> lock(_mutex);
|
@@ -6,13 +6,11 @@ using namespace facebook;
|
|
6
6
|
|
7
7
|
using AffectedNodes = std::unordered_map<const ShadowNodeFamily*, std::unordered_set<int>>;
|
8
8
|
|
9
|
-
void shadow::ShadowTreeManager::updateShadowTree(
|
9
|
+
void shadow::ShadowTreeManager::updateShadowTree(const ShadowTreeRegistry& shadowTreeRegistry) {
|
10
10
|
auto& registry = core::UnistylesRegistry::get();
|
11
|
-
auto& uiManager = UIManagerBinding::getBinding(rt)->getUIManager();
|
12
|
-
const auto &shadowTreeRegistry = uiManager.getShadowTreeRegistry();
|
13
11
|
auto updates = registry.trafficController.getUpdates();
|
14
12
|
|
15
|
-
if (updates.
|
13
|
+
if (updates.empty()) {
|
16
14
|
return;
|
17
15
|
}
|
18
16
|
|
@@ -111,9 +109,16 @@ ShadowNode::Unshared shadow::ShadowTreeManager::cloneShadowTree(const ShadowNode
|
|
111
109
|
*shadowNode.getContextContainer()
|
112
110
|
};
|
113
111
|
|
112
|
+
#ifdef ANDROID
|
113
|
+
auto safeProps = rawPropsIt->second == nullptr ? folly::dynamic::object() : rawPropsIt->second;
|
114
|
+
auto newProps = folly::dynamic::merge(shadowNode.getProps()->rawProps, safeProps);
|
115
|
+
#else
|
116
|
+
auto newProps = rawPropsIt->second;
|
117
|
+
#endif
|
118
|
+
|
114
119
|
updatedProps = shadowNode
|
115
120
|
.getComponentDescriptor()
|
116
|
-
.cloneProps(propsParserContext, shadowNode.getProps(), RawProps(
|
121
|
+
.cloneProps(propsParserContext, shadowNode.getProps(), RawProps(newProps));
|
117
122
|
}
|
118
123
|
|
119
124
|
return shadowNode.clone({
|
@@ -16,7 +16,7 @@ using namespace facebook;
|
|
16
16
|
using AffectedNodes = std::unordered_map<const ShadowNodeFamily *, std::unordered_set<int>>;
|
17
17
|
|
18
18
|
struct ShadowTreeManager {
|
19
|
-
static void updateShadowTree(
|
19
|
+
static void updateShadowTree(const ShadowTreeRegistry& shadowTreeRegistry);
|
20
20
|
static AffectedNodes findAffectedNodes(const RootShadowNode& rootNode, ShadowLeafUpdates& updates);
|
21
21
|
static ShadowNode::Unshared cloneShadowTree(const ShadowNode &shadowNode, ShadowLeafUpdates& updates, AffectedNodes& affectedNodes);
|
22
22
|
};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "react-native-unistyles",
|
3
|
-
"version": "3.0.0-alpha.
|
3
|
+
"version": "3.0.0-alpha.37",
|
4
4
|
"description": "Level up your React Native StyleSheet",
|
5
5
|
"scripts": {
|
6
6
|
"test": "jest",
|
@@ -74,11 +74,11 @@
|
|
74
74
|
"husky": "9.1.6",
|
75
75
|
"jest": "29.7.0",
|
76
76
|
"metro-react-native-babel-preset": "0.77.0",
|
77
|
-
"nitro-codegen": "0.
|
77
|
+
"nitro-codegen": "0.16.2",
|
78
78
|
"react": "18.3.1",
|
79
79
|
"react-native": "0.76.0",
|
80
80
|
"react-native-builder-bob": "0.30.2",
|
81
|
-
"react-native-nitro-modules": "0.
|
81
|
+
"react-native-nitro-modules": "0.16.2",
|
82
82
|
"react-test-renderer": "18.3.1",
|
83
83
|
"release-it": "17.10.0",
|
84
84
|
"typescript": "5.6.3"
|
@@ -1,184 +0,0 @@
|
|
1
|
-
package com.unistyles
|
2
|
-
|
3
|
-
import UnistylesModuleInsets
|
4
|
-
import android.content.Context
|
5
|
-
import android.content.res.Configuration
|
6
|
-
import android.os.Build
|
7
|
-
import android.util.DisplayMetrics
|
8
|
-
import android.view.WindowManager
|
9
|
-
import androidx.core.text.TextUtilsCompat
|
10
|
-
import androidx.core.view.ViewCompat
|
11
|
-
import com.facebook.react.bridge.ReactApplicationContext
|
12
|
-
import com.margelo.nitro.unistyles.ColorScheme
|
13
|
-
import com.margelo.nitro.unistyles.Dimensions
|
14
|
-
import com.margelo.nitro.unistyles.HybridNativePlatformSpec
|
15
|
-
import com.margelo.nitro.unistyles.Insets
|
16
|
-
import com.margelo.nitro.unistyles.Orientation
|
17
|
-
import com.margelo.nitro.unistyles.UnistyleDependency
|
18
|
-
import com.margelo.nitro.unistyles.UnistylesNativeMiniRuntime
|
19
|
-
import java.util.Locale
|
20
|
-
|
21
|
-
class NativePlatform(private val reactContext: ReactApplicationContext): HybridNativePlatformSpec() {
|
22
|
-
private val _insets = UnistylesModuleInsets(reactContext)
|
23
|
-
|
24
|
-
override fun getInsets(): Insets {
|
25
|
-
return _insets.getInsets()
|
26
|
-
}
|
27
|
-
|
28
|
-
override fun getColorScheme(): ColorScheme {
|
29
|
-
val uiMode = reactContext.resources.configuration.uiMode
|
30
|
-
|
31
|
-
val colorScheme = when (uiMode.and(Configuration.UI_MODE_NIGHT_MASK)) {
|
32
|
-
Configuration.UI_MODE_NIGHT_YES -> ColorScheme.DARK
|
33
|
-
Configuration.UI_MODE_NIGHT_NO -> ColorScheme.LIGHT
|
34
|
-
else -> ColorScheme.UNSPECIFIED
|
35
|
-
}
|
36
|
-
|
37
|
-
return colorScheme
|
38
|
-
}
|
39
|
-
|
40
|
-
override fun getFontScale(): Double {
|
41
|
-
return reactContext.resources.configuration.fontScale.toDouble()
|
42
|
-
}
|
43
|
-
|
44
|
-
override fun getPixelRatio(): Double {
|
45
|
-
return reactContext.resources.displayMetrics.density.toDouble()
|
46
|
-
}
|
47
|
-
|
48
|
-
override fun getOrientation(): Orientation {
|
49
|
-
val orientation = when (reactContext.resources.configuration.orientation) {
|
50
|
-
Configuration.ORIENTATION_PORTRAIT -> Orientation.PORTRAIT
|
51
|
-
Configuration.ORIENTATION_LANDSCAPE -> Orientation.LANDSCAPE
|
52
|
-
else -> Orientation.PORTRAIT
|
53
|
-
}
|
54
|
-
|
55
|
-
return orientation
|
56
|
-
}
|
57
|
-
|
58
|
-
override fun getContentSizeCategory(): String {
|
59
|
-
val fontScale = reactContext.resources.configuration.fontScale
|
60
|
-
|
61
|
-
val contentSizeCategory = when {
|
62
|
-
fontScale <= 0.85f -> "Small"
|
63
|
-
fontScale <= 1.0f -> "Default"
|
64
|
-
fontScale <= 1.15f -> "Large"
|
65
|
-
fontScale <= 1.3f -> "ExtraLarge"
|
66
|
-
fontScale <= 1.5f -> "Huge"
|
67
|
-
fontScale <= 1.8 -> "ExtraHuge"
|
68
|
-
else -> "ExtraExtraHuge"
|
69
|
-
}
|
70
|
-
|
71
|
-
return contentSizeCategory
|
72
|
-
}
|
73
|
-
|
74
|
-
override fun getScreenDimensions(): Dimensions {
|
75
|
-
// function takes in count edge-to-edge layout
|
76
|
-
when {
|
77
|
-
Build.VERSION.SDK_INT < Build.VERSION_CODES.R -> {
|
78
|
-
val windowManager = reactContext.getSystemService(Context.WINDOW_SERVICE) as WindowManager
|
79
|
-
val metrics = DisplayMetrics()
|
80
|
-
|
81
|
-
windowManager.defaultDisplay.getRealMetrics(metrics)
|
82
|
-
|
83
|
-
val screenWidth = (metrics.widthPixels / metrics.density).toDouble()
|
84
|
-
val screenHeight = (metrics.heightPixels / metrics.density).toDouble()
|
85
|
-
|
86
|
-
return Dimensions(screenWidth, screenHeight)
|
87
|
-
}
|
88
|
-
else -> {
|
89
|
-
val displayMetrics = reactContext.resources.displayMetrics
|
90
|
-
|
91
|
-
reactContext.currentActivity?.windowManager?.currentWindowMetrics?.bounds?.let {
|
92
|
-
val boundsWidth = (it.width() / displayMetrics.density).toDouble()
|
93
|
-
val boundsHeight = (it.height() / displayMetrics.density).toDouble()
|
94
|
-
|
95
|
-
return Dimensions(boundsWidth, boundsHeight)
|
96
|
-
} ?: run {
|
97
|
-
val screenWidth = (displayMetrics.widthPixels / displayMetrics.density).toDouble()
|
98
|
-
val screenHeight = (displayMetrics.heightPixels / displayMetrics.density).toDouble()
|
99
|
-
|
100
|
-
return Dimensions(screenWidth, screenHeight)
|
101
|
-
}
|
102
|
-
}
|
103
|
-
}
|
104
|
-
}
|
105
|
-
|
106
|
-
override fun getStatusBarDimensions(): Dimensions {
|
107
|
-
// todo
|
108
|
-
return Dimensions(0.0, 0.0)
|
109
|
-
}
|
110
|
-
|
111
|
-
override fun getNavigationBarDimensions(): Dimensions {
|
112
|
-
// todo
|
113
|
-
return Dimensions(0.0, 0.0)
|
114
|
-
}
|
115
|
-
|
116
|
-
override fun getPrefersRtlDirection(): Boolean {
|
117
|
-
// forced by React Native
|
118
|
-
val sharedPrefs = reactContext.getSharedPreferences(
|
119
|
-
"com.facebook.react.modules.i18nmanager.I18nUtil",
|
120
|
-
Context.MODE_PRIVATE
|
121
|
-
)
|
122
|
-
val hasForcedRtl = sharedPrefs.getBoolean("RCTI18nUtil_forceRTL", false)
|
123
|
-
// user preferences
|
124
|
-
val isRtl = TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL
|
125
|
-
|
126
|
-
return hasForcedRtl || isRtl
|
127
|
-
}
|
128
|
-
|
129
|
-
override fun setRootViewBackgroundColor(color: Double) {
|
130
|
-
// todo
|
131
|
-
}
|
132
|
-
|
133
|
-
override fun setNavigationBarBackgroundColor(color: Double) {
|
134
|
-
// todo
|
135
|
-
}
|
136
|
-
|
137
|
-
override fun setNavigationBarHidden(isHidden: Boolean) {
|
138
|
-
// todo
|
139
|
-
}
|
140
|
-
|
141
|
-
override fun setStatusBarHidden(isHidden: Boolean) {
|
142
|
-
// todo
|
143
|
-
}
|
144
|
-
|
145
|
-
override fun setStatusBarBackgroundColor(color: Double) {
|
146
|
-
// todo
|
147
|
-
}
|
148
|
-
|
149
|
-
override fun setImmersiveMode(isEnabled: Boolean) {
|
150
|
-
this.setStatusBarHidden(isEnabled)
|
151
|
-
this.setNavigationBarHidden(isEnabled)
|
152
|
-
}
|
153
|
-
|
154
|
-
override fun getMiniRuntime(): UnistylesNativeMiniRuntime {
|
155
|
-
return UnistylesNativeMiniRuntime(
|
156
|
-
colorScheme = this.getColorScheme(),
|
157
|
-
screen = this.getScreenDimensions(),
|
158
|
-
contentSizeCategory = this.getContentSizeCategory(),
|
159
|
-
insets = this.getInsets(),
|
160
|
-
pixelRatio = this.getPixelRatio(),
|
161
|
-
fontScale = this.getFontScale(),
|
162
|
-
rtl = this.getPrefersRtlDirection(),
|
163
|
-
statusBar = this.getStatusBarDimensions(),
|
164
|
-
navigationBar = this.getNavigationBarDimensions(),
|
165
|
-
isPortrait = this.getOrientation() == Orientation.PORTRAIT,
|
166
|
-
isLandscape = this.getOrientation() == Orientation.LANDSCAPE
|
167
|
-
)
|
168
|
-
}
|
169
|
-
|
170
|
-
override fun registerPlatformListener(callback: (dependencies: Array<UnistyleDependency>) -> Unit) {
|
171
|
-
// todo
|
172
|
-
}
|
173
|
-
|
174
|
-
override fun registerImeListener(callback: () -> Unit) {
|
175
|
-
// todo
|
176
|
-
}
|
177
|
-
|
178
|
-
override fun unregisterPlatformListeners() {
|
179
|
-
// todo
|
180
|
-
}
|
181
|
-
|
182
|
-
override val memorySize: Long
|
183
|
-
get() = 0
|
184
|
-
}
|
@@ -1,8 +0,0 @@
|
|
1
|
-
import com.facebook.react.bridge.ReactApplicationContext
|
2
|
-
import com.margelo.nitro.unistyles.Insets
|
3
|
-
|
4
|
-
class UnistylesModuleInsets(private val reactContext: ReactApplicationContext) {
|
5
|
-
fun getInsets(): Insets {
|
6
|
-
return Insets(top = 0.0, bottom = 0.0, left = 0.0, right = 0.0, ime = 0.0)
|
7
|
-
}
|
8
|
-
}
|