react-native-unistyles 2.8.0-beta.4 → 2.8.0-rc.1
Sign up to get free protection for your applications and to get access to all the features.
- package/android/src/main/cxx/cpp-adapter.cpp +1 -1
- package/android/src/main/cxx/helpers.cpp +61 -0
- package/android/src/main/cxx/helpers.h +5 -0
- package/android/src/main/cxx/platform.cpp +51 -41
- package/android/src/main/cxx/platform.h +7 -4
- package/android/src/main/java/com/unistyles/Models.kt +13 -50
- package/android/src/main/java/com/unistyles/Platform.kt +175 -40
- package/android/src/main/java/com/unistyles/UnistylesModule.kt +17 -87
- package/cxx/UnistylesImpl.cpp +57 -2
- package/cxx/UnistylesModel.cpp +6 -2
- package/cxx/UnistylesModel.h +34 -8
- package/cxx/UnistylesRuntime.h +9 -1
- package/ios/platform/Platform_Shared.h +2 -0
- package/ios/platform/Platform_Shared.mm +84 -1
- package/ios/platform/Platform_iOS.h +2 -0
- package/ios/platform/Platform_iOS.mm +57 -14
- package/lib/commonjs/core/UnistylesModule.js +17 -2
- package/lib/commonjs/core/UnistylesModule.js.map +1 -1
- package/lib/commonjs/core/UnistylesRuntime.js +65 -4
- package/lib/commonjs/core/UnistylesRuntime.js.map +1 -1
- package/lib/commonjs/core/mocks/UnistylesMockedBridge.js +4 -0
- package/lib/commonjs/core/mocks/UnistylesMockedBridge.js.map +1 -1
- package/lib/commonjs/core/mocks/UnistylesMockedRuntime.js +12 -2
- package/lib/commonjs/core/mocks/UnistylesMockedRuntime.js.map +1 -1
- package/lib/commonjs/types/color.js +2 -0
- package/lib/commonjs/types/color.js.map +1 -0
- package/lib/commonjs/types/index.js +11 -0
- package/lib/commonjs/types/index.js.map +1 -1
- package/lib/commonjs/useStyles.js +1 -1
- package/lib/commonjs/useStyles.js.map +1 -1
- package/lib/commonjs/utils/index.js +7 -0
- package/lib/commonjs/utils/index.js.map +1 -1
- package/lib/commonjs/utils/parseColor.js +30 -0
- package/lib/commonjs/utils/parseColor.js.map +1 -0
- package/lib/module/core/UnistylesModule.js +17 -2
- package/lib/module/core/UnistylesModule.js.map +1 -1
- package/lib/module/core/UnistylesRuntime.js +66 -4
- package/lib/module/core/UnistylesRuntime.js.map +1 -1
- package/lib/module/core/index.js +2 -1
- package/lib/module/core/index.js.map +1 -1
- package/lib/module/core/mocks/UnistylesMockedBridge.js +4 -0
- package/lib/module/core/mocks/UnistylesMockedBridge.js.map +1 -1
- package/lib/module/core/mocks/UnistylesMockedRuntime.js +12 -2
- package/lib/module/core/mocks/UnistylesMockedRuntime.js.map +1 -1
- package/lib/module/types/color.js +2 -0
- package/lib/module/types/color.js.map +1 -0
- package/lib/module/types/index.js +1 -0
- package/lib/module/types/index.js.map +1 -1
- package/lib/module/useStyles.js +1 -1
- package/lib/module/useStyles.js.map +1 -1
- package/lib/module/utils/index.js +1 -0
- package/lib/module/utils/index.js.map +1 -1
- package/lib/module/utils/parseColor.js +23 -0
- package/lib/module/utils/parseColor.js.map +1 -0
- package/lib/typescript/src/core/UnistylesModule.d.ts +1 -0
- package/lib/typescript/src/core/UnistylesModule.d.ts.map +1 -1
- package/lib/typescript/src/core/UnistylesRuntime.d.ts +52 -5
- package/lib/typescript/src/core/UnistylesRuntime.d.ts.map +1 -1
- package/lib/typescript/src/core/index.d.ts +3 -1
- package/lib/typescript/src/core/index.d.ts.map +1 -1
- package/lib/typescript/src/core/mocks/UnistylesMockedBridge.d.ts +4 -0
- package/lib/typescript/src/core/mocks/UnistylesMockedBridge.d.ts.map +1 -1
- package/lib/typescript/src/core/mocks/UnistylesMockedRuntime.d.ts +7 -1
- package/lib/typescript/src/core/mocks/UnistylesMockedRuntime.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/types/breakpoints.d.ts +2 -2
- package/lib/typescript/src/types/breakpoints.d.ts.map +1 -1
- package/lib/typescript/src/types/color.d.ts +4 -0
- package/lib/typescript/src/types/color.d.ts.map +1 -0
- package/lib/typescript/src/types/index.d.ts +1 -0
- package/lib/typescript/src/types/index.d.ts.map +1 -1
- package/lib/typescript/src/types/stylesheet.d.ts +2 -2
- package/lib/typescript/src/types/stylesheet.d.ts.map +1 -1
- package/lib/typescript/src/types/unistyles.d.ts +8 -2
- package/lib/typescript/src/types/unistyles.d.ts.map +1 -1
- package/lib/typescript/src/utils/index.d.ts +1 -0
- package/lib/typescript/src/utils/index.d.ts.map +1 -1
- package/lib/typescript/src/utils/parseColor.d.ts +3 -0
- package/lib/typescript/src/utils/parseColor.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/core/UnistylesModule.ts +19 -3
- package/src/core/UnistylesRuntime.ts +67 -5
- package/src/core/index.ts +7 -1
- package/src/core/mocks/UnistylesMockedBridge.ts +4 -0
- package/src/core/mocks/UnistylesMockedRuntime.ts +15 -3
- package/src/index.ts +3 -2
- package/src/types/breakpoints.ts +2 -2
- package/src/types/color.ts +26 -0
- package/src/types/index.ts +1 -0
- package/src/types/stylesheet.ts +2 -2
- package/src/types/unistyles.ts +10 -4
- package/src/useStyles.ts +1 -1
- package/src/utils/index.ts +1 -0
- package/src/utils/parseColor.ts +27 -0
@@ -4,8 +4,6 @@ import android.content.BroadcastReceiver
|
|
4
4
|
import android.content.Context
|
5
5
|
import android.content.Intent
|
6
6
|
import android.content.IntentFilter
|
7
|
-
import android.content.res.Configuration
|
8
|
-
import android.graphics.Color
|
9
7
|
import android.os.Handler
|
10
8
|
import android.os.Looper
|
11
9
|
import android.util.Log
|
@@ -20,7 +18,7 @@ import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder
|
|
20
18
|
|
21
19
|
class UnistylesModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext), LifecycleEventListener {
|
22
20
|
private var isCxxReady: Boolean = false
|
23
|
-
private
|
21
|
+
private var platform: Platform = Platform(reactContext)
|
24
22
|
|
25
23
|
private val configurationChangeReceiver = object : BroadcastReceiver() {
|
26
24
|
override fun onReceive(context: Context, intent: Intent) {
|
@@ -36,11 +34,9 @@ class UnistylesModule(reactContext: ReactApplicationContext) : ReactContextBaseJ
|
|
36
34
|
|
37
35
|
val newConfig = context.resources.configuration
|
38
36
|
|
39
|
-
if (newConfig.orientation
|
40
|
-
|
41
|
-
}
|
37
|
+
if (newConfig.orientation != platform.orientation) {
|
38
|
+
platform.orientation = newConfig.orientation
|
42
39
|
|
43
|
-
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
44
40
|
this@UnistylesModule.onLayoutConfigChange()
|
45
41
|
}
|
46
42
|
}
|
@@ -51,7 +47,6 @@ class UnistylesModule(reactContext: ReactApplicationContext) : ReactContextBaseJ
|
|
51
47
|
const val NAME = "Unistyles"
|
52
48
|
}
|
53
49
|
|
54
|
-
//region Lifecycle
|
55
50
|
init {
|
56
51
|
reactApplicationContext.registerReceiver(configurationChangeReceiver, IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED))
|
57
52
|
reactApplicationContext.addLifecycleEventListener(this)
|
@@ -66,8 +61,6 @@ class UnistylesModule(reactContext: ReactApplicationContext) : ReactContextBaseJ
|
|
66
61
|
}
|
67
62
|
}
|
68
63
|
|
69
|
-
//endregion
|
70
|
-
//region Event handlers
|
71
64
|
private fun onConfigChange() {
|
72
65
|
val colorScheme = this.platform.getColorScheme()
|
73
66
|
val contentSizeCategory = this.platform.getContentSizeCategory()
|
@@ -79,10 +72,10 @@ class UnistylesModule(reactContext: ReactApplicationContext) : ReactContextBaseJ
|
|
79
72
|
}
|
80
73
|
|
81
74
|
private fun onLayoutConfigChange() {
|
82
|
-
val screen = this.getScreenDimensions()
|
83
|
-
val insets = this.getInsets()
|
84
|
-
val statusBar = this.getStatusBarDimensions()
|
85
|
-
val navigationBar = this.getNavigationBarDimensions()
|
75
|
+
val screen = this.platform.getScreenDimensions()
|
76
|
+
val insets = this.platform.getInsets()
|
77
|
+
val statusBar = this.platform.getStatusBarDimensions()
|
78
|
+
val navigationBar = this.platform.getNavigationBarDimensions()
|
86
79
|
|
87
80
|
reactApplicationContext.runOnJSQueueThread {
|
88
81
|
this.nativeOnOrientationChange(
|
@@ -94,16 +87,11 @@ class UnistylesModule(reactContext: ReactApplicationContext) : ReactContextBaseJ
|
|
94
87
|
}
|
95
88
|
}
|
96
89
|
|
97
|
-
//endregion
|
98
|
-
//region Core
|
99
90
|
@ReactMethod(isBlockingSynchronousMethod = true)
|
100
91
|
fun install(): Boolean {
|
101
92
|
return try {
|
102
93
|
System.loadLibrary("unistyles")
|
103
94
|
|
104
|
-
this.platform = Platform(reactApplicationContext)
|
105
|
-
this.enableEdgeToEdge()
|
106
|
-
|
107
95
|
this.reactApplicationContext.javaScriptContextHolder?.let { contextHolder ->
|
108
96
|
this.reactApplicationContext.catalystInstance.jsCallInvokerHolder?.let { callInvokerHolder: CallInvokerHolder ->
|
109
97
|
this.nativeInstall(contextHolder.get(), callInvokerHolder)
|
@@ -125,68 +113,10 @@ class UnistylesModule(reactContext: ReactApplicationContext) : ReactContextBaseJ
|
|
125
113
|
|
126
114
|
private external fun nativeInstall(jsi: Long, callInvoker: CallInvokerHolder)
|
127
115
|
private external fun nativeDestroy()
|
128
|
-
private external fun nativeOnOrientationChange(screen:
|
116
|
+
private external fun nativeOnOrientationChange(screen: Screen, insets: Insets, statusBar: Dimensions, navigationBar: Dimensions)
|
129
117
|
private external fun nativeOnAppearanceChange(colorScheme: String)
|
130
118
|
private external fun nativeOnContentSizeCategoryChange(contentSizeCategory: String)
|
131
119
|
|
132
|
-
//endregion
|
133
|
-
|
134
|
-
private fun getScreenDimensions(): Dimensions {
|
135
|
-
return platform.getScreenDimensions()
|
136
|
-
}
|
137
|
-
|
138
|
-
private fun getColorScheme(): String {
|
139
|
-
return platform.getColorScheme()
|
140
|
-
}
|
141
|
-
|
142
|
-
private fun getStatusBarDimensions(): Dimensions {
|
143
|
-
return platform.getStatusBarDimensions()
|
144
|
-
}
|
145
|
-
|
146
|
-
private fun getNavigationBarDimensions(): Dimensions {
|
147
|
-
return platform.getNavigationBarDimensions()
|
148
|
-
}
|
149
|
-
|
150
|
-
private fun getContentSizeCategory(): String {
|
151
|
-
return platform.getContentSizeCategory()
|
152
|
-
}
|
153
|
-
|
154
|
-
private fun getInsets(): Insets {
|
155
|
-
return platform.getInsets()
|
156
|
-
}
|
157
|
-
|
158
|
-
private fun onSetNavigationBarColor(color: String) {
|
159
|
-
val activity = currentActivity ?: return
|
160
|
-
|
161
|
-
if (platform.defaultNavigationBarColor == null) {
|
162
|
-
platform.defaultNavigationBarColor = activity.window.navigationBarColor
|
163
|
-
}
|
164
|
-
|
165
|
-
try {
|
166
|
-
activity.runOnUiThread {
|
167
|
-
activity.window.navigationBarColor = if (color == "") platform.defaultNavigationBarColor!! else Color.parseColor(color)
|
168
|
-
}
|
169
|
-
} catch (_: Exception) {
|
170
|
-
Log.d("Unistyles", "Failed to set navigation bar color: $color")
|
171
|
-
}
|
172
|
-
}
|
173
|
-
|
174
|
-
private fun onSetStatusBarColor(color: String) {
|
175
|
-
val activity = currentActivity ?: return
|
176
|
-
|
177
|
-
if (platform.defaultStatusBarColor == null) {
|
178
|
-
platform.defaultStatusBarColor = activity.window.statusBarColor
|
179
|
-
}
|
180
|
-
|
181
|
-
try {
|
182
|
-
activity.runOnUiThread {
|
183
|
-
activity.window.statusBarColor = if (color == "") platform.defaultStatusBarColor!! else Color.parseColor(color)
|
184
|
-
}
|
185
|
-
} catch (_: Exception) {
|
186
|
-
Log.d("Unistyles", "Failed to set status bar color: $color")
|
187
|
-
}
|
188
|
-
}
|
189
|
-
|
190
120
|
private fun enableEdgeToEdge() {
|
191
121
|
this.reactApplicationContext.currentActivity?.let { activity ->
|
192
122
|
activity.runOnUiThread {
|
@@ -200,23 +130,24 @@ class UnistylesModule(reactContext: ReactApplicationContext) : ReactContextBaseJ
|
|
200
130
|
|
201
131
|
@ReactMethod
|
202
132
|
fun removeListeners(count: Double) = Unit
|
133
|
+
|
203
134
|
override fun onHostResume() {
|
135
|
+
this.enableEdgeToEdge()
|
136
|
+
|
204
137
|
if (isCxxReady) {
|
205
138
|
this.onConfigChange()
|
206
139
|
}
|
207
140
|
|
208
141
|
this.reactApplicationContext.currentActivity?.let { activity ->
|
209
142
|
activity.findViewById<View>(android.R.id.content)?.let { mainView ->
|
210
|
-
|
211
|
-
|
212
|
-
this.platform.setInsetsCompat(insets, decorView)
|
143
|
+
ViewCompat.setOnApplyWindowInsetsListener(mainView) { _, insets ->
|
144
|
+
this.platform.setInsetsCompat(insets, activity.window)
|
213
145
|
|
214
|
-
|
215
|
-
|
216
|
-
}
|
217
|
-
|
218
|
-
insets
|
146
|
+
if (this.isCxxReady) {
|
147
|
+
this.onLayoutConfigChange()
|
219
148
|
}
|
149
|
+
|
150
|
+
insets
|
220
151
|
}
|
221
152
|
}
|
222
153
|
}
|
@@ -231,5 +162,4 @@ class UnistylesModule(reactContext: ReactApplicationContext) : ReactContextBaseJ
|
|
231
162
|
}
|
232
163
|
|
233
164
|
override fun onHostDestroy() {}
|
234
|
-
//endregion
|
235
165
|
}
|
package/cxx/UnistylesImpl.cpp
CHANGED
@@ -177,9 +177,19 @@ jsi::Value UnistylesRuntime::getStatusBar(jsi::Runtime& rt, std::string fnName)
|
|
177
177
|
auto statusBar = jsi::Object(rt);
|
178
178
|
auto setStatusBarColorFunction = HOST_FN("setColor", 1, {
|
179
179
|
std::string color = arguments[0].asString(rt).utf8(rt);
|
180
|
+
float alpha = arguments[1].asNumber();
|
180
181
|
|
181
182
|
if (this->setStatusBarColor.has_value()) {
|
182
|
-
this->setStatusBarColor.value()(color);
|
183
|
+
this->setStatusBarColor.value()(color, alpha);
|
184
|
+
}
|
185
|
+
|
186
|
+
return jsi::Value::undefined();
|
187
|
+
});
|
188
|
+
auto setStatusBarHiddenFunction = HOST_FN("setHidden", 1, {
|
189
|
+
bool hidden = arguments[0].asBool();
|
190
|
+
|
191
|
+
if (this->setStatusBarHidden.has_value()) {
|
192
|
+
this->setStatusBarHidden.value()(hidden);
|
183
193
|
}
|
184
194
|
|
185
195
|
return jsi::Value::undefined();
|
@@ -188,6 +198,7 @@ jsi::Value UnistylesRuntime::getStatusBar(jsi::Runtime& rt, std::string fnName)
|
|
188
198
|
statusBar.setProperty(rt, "width", this->statusBar.width);
|
189
199
|
statusBar.setProperty(rt, "height", this->statusBar.height);
|
190
200
|
statusBar.setProperty(rt, "setColor", setStatusBarColorFunction);
|
201
|
+
statusBar.setProperty(rt, "setHidden", setStatusBarHiddenFunction);
|
191
202
|
|
192
203
|
return statusBar;
|
193
204
|
}
|
@@ -196,9 +207,19 @@ jsi::Value UnistylesRuntime::getNavigationBar(jsi::Runtime& rt, std::string fnNa
|
|
196
207
|
auto navigationBarValue = jsi::Object(rt);
|
197
208
|
auto setNavigationBarColorFunction = HOST_FN("setColor", 1, {
|
198
209
|
std::string color = arguments[0].asString(rt).utf8(rt);
|
210
|
+
float alpha = arguments[1].asNumber();
|
199
211
|
|
200
212
|
if (this->setNavigationBarColor.has_value()) {
|
201
|
-
this->setNavigationBarColor.value()(color);
|
213
|
+
this->setNavigationBarColor.value()(color, alpha);
|
214
|
+
}
|
215
|
+
|
216
|
+
return jsi::Value::undefined();
|
217
|
+
});
|
218
|
+
auto setHiddenFunction = HOST_FN("setHidden", 1, {
|
219
|
+
bool hidden = arguments[0].asBool();
|
220
|
+
|
221
|
+
if (this->setNavigationBarHidden.has_value()) {
|
222
|
+
this->setNavigationBarHidden.value()(hidden);
|
202
223
|
}
|
203
224
|
|
204
225
|
return jsi::Value::undefined();
|
@@ -207,10 +228,19 @@ jsi::Value UnistylesRuntime::getNavigationBar(jsi::Runtime& rt, std::string fnNa
|
|
207
228
|
navigationBarValue.setProperty(rt, "width", this->navigationBar.width);
|
208
229
|
navigationBarValue.setProperty(rt, "height", this->navigationBar.height);
|
209
230
|
navigationBarValue.setProperty(rt, "setColor", setNavigationBarColorFunction);
|
231
|
+
navigationBarValue.setProperty(rt, "setHidden", setHiddenFunction);
|
210
232
|
|
211
233
|
return navigationBarValue;
|
212
234
|
}
|
213
235
|
|
236
|
+
jsi::Value UnistylesRuntime::getPixelRatio(jsi::Runtime& rt, std::string fnName) {
|
237
|
+
return jsi::Value(roundf(this->pixelRatio * 100)/ 100);
|
238
|
+
}
|
239
|
+
|
240
|
+
jsi::Value UnistylesRuntime::getFontScale(jsi::Runtime& rt, std::string fnName) {
|
241
|
+
return jsi::Value(roundf(this->fontScale * 100) / 100);
|
242
|
+
}
|
243
|
+
|
214
244
|
std::optional<jsi::Value> UnistylesRuntime::setThemes(jsi::Runtime& rt, const jsi::Value& value) {
|
215
245
|
jsi::Array themes = value.asObject(rt).asArray(rt);
|
216
246
|
std::vector<std::string> themesVector;
|
@@ -239,3 +269,28 @@ std::optional<jsi::Value> UnistylesRuntime::setThemes(jsi::Runtime& rt, const js
|
|
239
269
|
|
240
270
|
return std::nullopt;
|
241
271
|
}
|
272
|
+
|
273
|
+
jsi::Value UnistylesRuntime::setImmersiveModeEnabled(jsi::Runtime& rt, std::string fnName) {
|
274
|
+
return HOST_FN(fnName, 1, {
|
275
|
+
bool enabled = arguments[0].asBool();
|
276
|
+
|
277
|
+
if (this->setImmersiveMode.has_value()) {
|
278
|
+
this->setImmersiveMode.value()(enabled);
|
279
|
+
}
|
280
|
+
|
281
|
+
return jsi::Value::undefined();
|
282
|
+
});
|
283
|
+
}
|
284
|
+
|
285
|
+
jsi::Value UnistylesRuntime::setRootBackgroundColor(jsi::Runtime& rt, std::string fnName) {
|
286
|
+
return HOST_FN(fnName, 1, {
|
287
|
+
std::string color = arguments[0].asString(rt).utf8(rt);
|
288
|
+
float alpha = arguments[1].asNumber();
|
289
|
+
|
290
|
+
if (this->setRootViewBackgroundColor.has_value()) {
|
291
|
+
this->setRootViewBackgroundColor.value()(color, alpha);
|
292
|
+
}
|
293
|
+
|
294
|
+
return jsi::Value::undefined();
|
295
|
+
});
|
296
|
+
}
|
package/cxx/UnistylesModel.cpp
CHANGED
@@ -13,19 +13,23 @@ std::string UnistylesModel::getBreakpointFromScreenWidth(int width, const std::v
|
|
13
13
|
return sortedBreakpointPairs.empty() ? "" : sortedBreakpointPairs.back().first;
|
14
14
|
}
|
15
15
|
|
16
|
-
void UnistylesModel::handleScreenSizeChange(
|
16
|
+
void UnistylesModel::handleScreenSizeChange(Screen& screen, std::optional<Insets> insets, std::optional<Dimensions> statusBar, std::optional<Dimensions> navigationBar) {
|
17
17
|
std::string breakpoint = this->getBreakpointFromScreenWidth(screen.width, this->sortedBreakpointPairs);
|
18
18
|
bool hasDifferentBreakpoint = this->breakpoint != breakpoint;
|
19
19
|
bool hasDifferentScreenDimensions = this->screen.width != screen.width || this->screen.height != screen.height;
|
20
|
+
bool hasDifferentPixelRatio = this->pixelRatio != screen.pixelRatio;
|
21
|
+
bool hasDifferentFontScale = this->fontScale != screen.fontScale;
|
20
22
|
bool hasDifferentInsets = insets.has_value()
|
21
23
|
? this->insets.top != insets->top || this->insets.bottom != insets->bottom || this->insets.left != insets->left || this->insets.right != insets->right
|
22
24
|
: false;
|
23
25
|
|
24
26
|
// we don't need to check statusBar/navigationBar as they will only change on orientation change witch is equal to hasDifferentScreenDimensions
|
25
|
-
bool shouldNotify = hasDifferentBreakpoint || hasDifferentScreenDimensions || hasDifferentInsets;
|
27
|
+
bool shouldNotify = hasDifferentBreakpoint || hasDifferentScreenDimensions || hasDifferentInsets || hasDifferentPixelRatio || hasDifferentFontScale;
|
26
28
|
|
27
29
|
this->breakpoint = breakpoint;
|
28
30
|
this->screen = {screen.width, screen.height};
|
31
|
+
this->pixelRatio = screen.pixelRatio;
|
32
|
+
this->fontScale = screen.fontScale;
|
29
33
|
|
30
34
|
if (insets.has_value()) {
|
31
35
|
this->insets = {insets->top, insets->bottom, insets->left, insets->right};
|
package/cxx/UnistylesModel.h
CHANGED
@@ -6,6 +6,7 @@
|
|
6
6
|
#include <map>
|
7
7
|
#include <optional>
|
8
8
|
#include <variant>
|
9
|
+
#include <math.h>
|
9
10
|
|
10
11
|
using namespace facebook;
|
11
12
|
|
@@ -26,6 +27,13 @@ struct Dimensions {
|
|
26
27
|
int height;
|
27
28
|
};
|
28
29
|
|
30
|
+
struct Screen {
|
31
|
+
int width;
|
32
|
+
int height;
|
33
|
+
float pixelRatio;
|
34
|
+
float fontScale;
|
35
|
+
};
|
36
|
+
|
29
37
|
struct Insets {
|
30
38
|
int top;
|
31
39
|
int bottom;
|
@@ -46,16 +54,20 @@ struct UnistylesModel {
|
|
46
54
|
jsi::Object parseEventPayload(EventPayload payload);
|
47
55
|
jsi::Object parseEventNestedPayload(EventNestedValue payload);
|
48
56
|
|
49
|
-
std::function<
|
57
|
+
std::function<Screen()> getScreenDimensions;
|
50
58
|
std::function<std::string()> getContentSizeCategory;
|
51
59
|
std::function<std::string()> getColorScheme;
|
52
60
|
std::function<Dimensions()> getStatusBarDimensions;
|
53
61
|
std::function<Dimensions()> getNavigationBarDimensions;
|
54
62
|
std::function<Insets()> getInsets;
|
55
|
-
std::optional<std::function<void(std::string)>> setStatusBarColor;
|
56
|
-
std::optional<std::function<void(std::string)>> setNavigationBarColor;
|
57
|
-
|
58
|
-
|
63
|
+
std::optional<std::function<void(std::string, float alpha)>> setStatusBarColor;
|
64
|
+
std::optional<std::function<void(std::string, float alpha)>> setNavigationBarColor;
|
65
|
+
std::optional<std::function<void(bool)>> setNavigationBarHidden;
|
66
|
+
std::optional<std::function<void(bool)>> setStatusBarHidden;
|
67
|
+
std::optional<std::function<void(bool)>> setImmersiveMode;
|
68
|
+
std::optional<std::function<void(std::string, float alpha)>> setRootViewBackgroundColor;
|
69
|
+
|
70
|
+
void setScreenDimensionsCallback(std::function<Screen()> callback) {
|
59
71
|
this->getScreenDimensions = callback;
|
60
72
|
}
|
61
73
|
void setContentSizeCategoryCallback(std::function<std::string()> callback) {
|
@@ -73,17 +85,31 @@ struct UnistylesModel {
|
|
73
85
|
void setInsetsCallback(std::function<Insets()> callback) {
|
74
86
|
this->getInsets = callback;
|
75
87
|
}
|
76
|
-
void setStatusBarColorCallback(std::function<void(std::string color)> callback) {
|
88
|
+
void setStatusBarColorCallback(std::function<void(std::string color, float alpha)> callback) {
|
77
89
|
this->setStatusBarColor = callback;
|
78
90
|
}
|
79
|
-
void setNavigationBarColorCallback(std::function<void(std::string color)> callback) {
|
91
|
+
void setNavigationBarColorCallback(std::function<void(std::string color, float alpha)> callback) {
|
80
92
|
this->setNavigationBarColor = callback;
|
81
93
|
}
|
94
|
+
void setNavigationBarHiddenCallback(std::function<void(bool hidden)> callback) {
|
95
|
+
this->setNavigationBarHidden = callback;
|
96
|
+
}
|
97
|
+
void setStatusBarHiddenCallback(std::function<void(bool hidden)> callback) {
|
98
|
+
this->setStatusBarHidden = callback;
|
99
|
+
}
|
100
|
+
void setImmersiveModeCallback(std::function<void(bool enabled)> callback) {
|
101
|
+
this->setImmersiveMode = callback;
|
102
|
+
}
|
103
|
+
void setRootViewBackgroundColorCallback(std::function<void(std::string color, float alpha)> callback) {
|
104
|
+
this->setRootViewBackgroundColor = callback;
|
105
|
+
}
|
82
106
|
|
83
107
|
Dimensions screen = {0, 0};
|
84
108
|
Dimensions statusBar = {0, 0};
|
85
109
|
Dimensions navigationBar = {0, 0};
|
86
110
|
Insets insets = {0, 0, 0, 0};
|
111
|
+
float pixelRatio = 1.0;
|
112
|
+
float fontScale = 1.0;
|
87
113
|
std::string colorScheme = UnistylesUnspecifiedScheme;
|
88
114
|
std::string contentSizeCategory = UnistylesUnspecifiedScheme;
|
89
115
|
|
@@ -98,7 +124,7 @@ struct UnistylesModel {
|
|
98
124
|
std::vector<std::string> themes;
|
99
125
|
std::vector<std::pair<std::string, double>> sortedBreakpointPairs;
|
100
126
|
|
101
|
-
void handleScreenSizeChange(
|
127
|
+
void handleScreenSizeChange(Screen& screen, std::optional<Insets> insets, std::optional<Dimensions> statusBar, std::optional<Dimensions> navigationBar);
|
102
128
|
void handleAppearanceChange(std::string colorScheme);
|
103
129
|
void handleContentSizeCategoryChange(std::string contentSizeCategory);
|
104
130
|
|
package/cxx/UnistylesRuntime.h
CHANGED
@@ -30,7 +30,11 @@ struct JSI_EXPORT UnistylesRuntime : public jsi::HostObject, UnistylesModel {
|
|
30
30
|
{"enabledPlugins", BIND_FN(getEnabledPlugins)},
|
31
31
|
{"insets", BIND_FN(getInsets)},
|
32
32
|
{"statusBar", BIND_FN(getStatusBar)},
|
33
|
-
{"navigationBar", BIND_FN(getNavigationBar)}
|
33
|
+
{"navigationBar", BIND_FN(getNavigationBar)},
|
34
|
+
{"pixelRatio", BIND_FN(getPixelRatio)},
|
35
|
+
{"fontScale", BIND_FN(getFontScale)},
|
36
|
+
{"setRootViewBackgroundColor", BIND_FN(setRootBackgroundColor)},
|
37
|
+
{"setImmersiveMode", BIND_FN(setImmersiveModeEnabled)}
|
34
38
|
};
|
35
39
|
|
36
40
|
this->setters = {
|
@@ -56,6 +60,10 @@ struct JSI_EXPORT UnistylesRuntime : public jsi::HostObject, UnistylesModel {
|
|
56
60
|
jsi::Value getInsets(jsi::Runtime&, std::string);
|
57
61
|
jsi::Value getStatusBar(jsi::Runtime&, std::string);
|
58
62
|
jsi::Value getNavigationBar(jsi::Runtime&, std::string);
|
63
|
+
jsi::Value getPixelRatio(jsi::Runtime&, std::string);
|
64
|
+
jsi::Value getFontScale(jsi::Runtime&, std::string);
|
65
|
+
jsi::Value setRootBackgroundColor(jsi::Runtime&, std::string);
|
66
|
+
jsi::Value setImmersiveModeEnabled(jsi::Runtime&, std::string);
|
59
67
|
|
60
68
|
std::optional<jsi::Value> setThemes(jsi::Runtime&, const jsi::Value&);
|
61
69
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
std::string getContentSizeCategory() {
|
4
4
|
UIContentSizeCategory contentSizeCategory = [[UIApplication sharedApplication] preferredContentSizeCategory];
|
5
|
-
|
5
|
+
|
6
6
|
if ([contentSizeCategory isEqualToString:UIContentSizeCategoryExtraExtraExtraLarge]) {
|
7
7
|
return std::string([@"xxxLarge" UTF8String]);
|
8
8
|
}
|
@@ -54,6 +54,63 @@ std::string getContentSizeCategory() {
|
|
54
54
|
return std::string([@"unspecified" UTF8String]);
|
55
55
|
}
|
56
56
|
|
57
|
+
// based on Apple Human Interface Guidelines
|
58
|
+
// https://developer.apple.com/design/human-interface-guidelines/typography#Specifications
|
59
|
+
float getFontScale() {
|
60
|
+
UIContentSizeCategory contentSizeCategory = [[UIApplication sharedApplication] preferredContentSizeCategory];
|
61
|
+
float defaultMultiplier = 17.0;
|
62
|
+
|
63
|
+
if ([contentSizeCategory isEqualToString:UIContentSizeCategoryExtraExtraExtraLarge]) {
|
64
|
+
return 23.0 / defaultMultiplier;
|
65
|
+
}
|
66
|
+
|
67
|
+
if ([contentSizeCategory isEqualToString:UIContentSizeCategoryExtraExtraLarge]) {
|
68
|
+
return 21.0 / defaultMultiplier;
|
69
|
+
}
|
70
|
+
|
71
|
+
if ([contentSizeCategory isEqualToString:UIContentSizeCategoryExtraLarge]) {
|
72
|
+
return 19.0 / defaultMultiplier;
|
73
|
+
}
|
74
|
+
|
75
|
+
if ([contentSizeCategory isEqualToString:UIContentSizeCategoryLarge]) {
|
76
|
+
return 17.0 / defaultMultiplier;
|
77
|
+
}
|
78
|
+
|
79
|
+
if ([contentSizeCategory isEqualToString:UIContentSizeCategoryMedium]) {
|
80
|
+
return 16.0 / defaultMultiplier;
|
81
|
+
}
|
82
|
+
|
83
|
+
if ([contentSizeCategory isEqualToString:UIContentSizeCategorySmall]) {
|
84
|
+
return 15.0 / defaultMultiplier;
|
85
|
+
}
|
86
|
+
|
87
|
+
if ([contentSizeCategory isEqualToString:UIContentSizeCategoryExtraSmall]) {
|
88
|
+
return 14.0 / defaultMultiplier;
|
89
|
+
}
|
90
|
+
|
91
|
+
if ([contentSizeCategory isEqualToString:UIContentSizeCategoryAccessibilityMedium]) {
|
92
|
+
return 29.0 / defaultMultiplier;
|
93
|
+
}
|
94
|
+
|
95
|
+
if ([contentSizeCategory isEqualToString:UIContentSizeCategoryAccessibilityLarge]) {
|
96
|
+
return 33.0 / defaultMultiplier;
|
97
|
+
}
|
98
|
+
|
99
|
+
if ([contentSizeCategory isEqualToString:UIContentSizeCategoryAccessibilityExtraLarge]) {
|
100
|
+
return 40.0 / defaultMultiplier;
|
101
|
+
}
|
102
|
+
|
103
|
+
if ([contentSizeCategory isEqualToString:UIContentSizeCategoryAccessibilityExtraExtraLarge]) {
|
104
|
+
return 47.0 / defaultMultiplier;
|
105
|
+
}
|
106
|
+
|
107
|
+
if ([contentSizeCategory isEqualToString:UIContentSizeCategoryAccessibilityExtraExtraExtraLarge]) {
|
108
|
+
return 53.0 / defaultMultiplier;
|
109
|
+
}
|
110
|
+
|
111
|
+
return 1.0;
|
112
|
+
}
|
113
|
+
|
57
114
|
std::string getColorScheme() {
|
58
115
|
UIUserInterfaceStyle colorScheme = [UIScreen mainScreen].traitCollection.userInterfaceStyle;
|
59
116
|
|
@@ -67,3 +124,29 @@ std::string getColorScheme() {
|
|
67
124
|
return UnistylesUnspecifiedScheme;
|
68
125
|
}
|
69
126
|
}
|
127
|
+
|
128
|
+
UIColor* colorFromHexString(NSString* hexString, float alpha) {
|
129
|
+
unsigned rgbValue = 0;
|
130
|
+
unsigned alphaValue = 0xFF;
|
131
|
+
|
132
|
+
NSScanner *scanner = [NSScanner scannerWithString:hexString];
|
133
|
+
|
134
|
+
if (![hexString hasPrefix:@"#"]) {
|
135
|
+
return nil;
|
136
|
+
}
|
137
|
+
|
138
|
+
[scanner setScanLocation:1];
|
139
|
+
|
140
|
+
if ((hexString.length == 9 && ![scanner scanHexInt:&alphaValue]) || ![scanner scanHexInt:&rgbValue]) {
|
141
|
+
return nil;
|
142
|
+
}
|
143
|
+
|
144
|
+
if (hexString.length == 9) {
|
145
|
+
alpha = alphaValue / 255.0;
|
146
|
+
}
|
147
|
+
|
148
|
+
return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16) / 255.0
|
149
|
+
green:((rgbValue & 0x00FF00) >> 8) / 255.0
|
150
|
+
blue:(rgbValue & 0x0000FF) / 255.0
|
151
|
+
alpha:alpha];
|
152
|
+
}
|
@@ -14,5 +14,7 @@
|
|
14
14
|
- (void)onWindowChange:(NSNotification *)notification;
|
15
15
|
- (void)onAppearanceChange:(NSNotification *)notification;
|
16
16
|
- (void)onContentSizeCategoryChange:(NSNotification *)notification;
|
17
|
+
- (void)setStatusBarHidden:(bool)isHidden;
|
18
|
+
- (void)setRootViewBackgroundColor:(std::string)color alpha:(float)alpha;
|
17
19
|
|
18
20
|
@end
|
@@ -46,35 +46,51 @@
|
|
46
46
|
|
47
47
|
- (void)makeShared:(void*)runtime {
|
48
48
|
self.unistylesRuntime = runtime;
|
49
|
-
|
49
|
+
|
50
50
|
auto unistylesRuntime = ((UnistylesRuntime*)self.unistylesRuntime);
|
51
|
-
|
51
|
+
|
52
52
|
unistylesRuntime->setScreenDimensionsCallback([self](){
|
53
53
|
return [self getScreenDimensions];
|
54
54
|
});
|
55
|
-
|
55
|
+
|
56
56
|
unistylesRuntime->setContentSizeCategoryCallback([](){
|
57
57
|
return getContentSizeCategory();
|
58
58
|
});
|
59
|
-
|
59
|
+
|
60
60
|
unistylesRuntime->setColorSchemeCallback([self](){
|
61
61
|
return getColorScheme();
|
62
62
|
});
|
63
|
-
|
63
|
+
|
64
64
|
unistylesRuntime->setStatusBarDimensionsCallback([self](){
|
65
65
|
return [self getStatusBarDimensions];
|
66
66
|
});
|
67
|
-
|
67
|
+
|
68
68
|
unistylesRuntime->setInsetsCallback([self](){
|
69
69
|
return [self getInsets];
|
70
70
|
});
|
71
|
-
|
71
|
+
|
72
|
+
unistylesRuntime->setStatusBarHiddenCallback([self](bool hidden){
|
73
|
+
return [self setStatusBarHidden:hidden];
|
74
|
+
});
|
75
|
+
|
76
|
+
unistylesRuntime->setImmersiveModeCallback([self](bool hidden){
|
77
|
+
return [self setStatusBarHidden:hidden];
|
78
|
+
});
|
79
|
+
|
80
|
+
unistylesRuntime->setRootViewBackgroundColorCallback([self](const std::string &color, float alpha){
|
81
|
+
return [self setRootViewBackgroundColor:color alpha:alpha];
|
82
|
+
});
|
83
|
+
|
72
84
|
dispatch_async(dispatch_get_main_queue(), ^{
|
73
|
-
|
85
|
+
Screen screen = [self getScreenDimensions];
|
86
|
+
|
87
|
+
unistylesRuntime->screen = Dimensions({ screen.width, screen.height });
|
74
88
|
unistylesRuntime->contentSizeCategory = getContentSizeCategory();
|
75
89
|
unistylesRuntime->colorScheme = getColorScheme();
|
76
90
|
unistylesRuntime->statusBar = [self getStatusBarDimensions];
|
77
91
|
unistylesRuntime->insets = [self getInsets];
|
92
|
+
unistylesRuntime->pixelRatio = screen.pixelRatio;
|
93
|
+
unistylesRuntime->fontScale = screen.fontScale;
|
78
94
|
});
|
79
95
|
}
|
80
96
|
|
@@ -92,7 +108,7 @@
|
|
92
108
|
|
93
109
|
- (void)onWindowChange:(NSNotification *)notification {
|
94
110
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
95
|
-
|
111
|
+
Screen screen = [self getScreenDimensions];
|
96
112
|
Insets insets = [self getInsets];
|
97
113
|
Dimensions statusBar = [self getStatusBarDimensions];
|
98
114
|
|
@@ -112,16 +128,43 @@
|
|
112
128
|
- (Dimensions)getStatusBarDimensions {
|
113
129
|
UIWindow *window = UIApplication.sharedApplication.windows.firstObject;
|
114
130
|
CGRect statusBarFrame = window.windowScene.statusBarManager.statusBarFrame;
|
115
|
-
|
131
|
+
|
116
132
|
return {(int)statusBarFrame.size.width, (int)statusBarFrame.size.height};
|
117
133
|
}
|
118
134
|
|
119
|
-
- (
|
135
|
+
- (Screen)getScreenDimensions {
|
120
136
|
UIViewController *presentedViewController = RCTPresentedViewController();
|
121
137
|
CGRect windowFrame = presentedViewController.view.window.frame;
|
122
|
-
|
123
|
-
|
124
|
-
|
138
|
+
int width = (int)windowFrame.size.width;
|
139
|
+
int height = (int)windowFrame.size.height;
|
140
|
+
float pixelRatio = presentedViewController.view.window.screen.scale;
|
141
|
+
float fontScale = getFontScale();
|
142
|
+
|
143
|
+
return Screen({width, height, pixelRatio, fontScale});
|
144
|
+
}
|
145
|
+
|
146
|
+
- (void)setStatusBarHidden:(bool)isHidden {
|
147
|
+
// forward it to React Native ViewController
|
148
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
149
|
+
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
150
|
+
[RCTSharedApplication() setStatusBarHidden:isHidden animated:true];
|
151
|
+
});
|
152
|
+
}
|
153
|
+
|
154
|
+
- (void)setRootViewBackgroundColor:(std::string)color alpha:(float)alpha {
|
155
|
+
UIViewController *presentedViewController = RCTPresentedViewController();
|
156
|
+
NSString *colorString = [NSString stringWithUTF8String:color.c_str()];
|
157
|
+
UIColor *backgroundColor = colorFromHexString(colorString, alpha);
|
158
|
+
|
159
|
+
if (backgroundColor == nil) {
|
160
|
+
NSLog(@"🦄 Unistyles: Couldn't set rootView to %@ color", colorString);
|
161
|
+
|
162
|
+
return;
|
163
|
+
}
|
164
|
+
|
165
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
166
|
+
presentedViewController.view.backgroundColor = backgroundColor;
|
167
|
+
});
|
125
168
|
}
|
126
169
|
|
127
170
|
@end
|