Skip to content

Commit

Permalink
Merge pull request #149 from jpudysz/feature/insets
Browse files Browse the repository at this point in the history
feat: add support for insets and status bar metadata
  • Loading branch information
jpudysz authored Feb 27, 2024
2 parents 31677ce + e0e24e1 commit de865e8
Show file tree
Hide file tree
Showing 38 changed files with 1,264 additions and 246 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,13 @@
[How to become a sponsor?](https://reactnativeunistyles.vercel.app/other/for-sponsors/)

<a href="https://codemask.com">
<img src="https://avatars.githubusercontent.com/u/51229884?s=200&v=4" height="70px" width="70px" />
<img src="https://avatars.githubusercontent.com/u/51229884?s=200&v=4" height="70px" width="70px" alt="codemask" />
</a>
<a href="https://galaxies.dev">
<img src="https://avatars.githubusercontent.com/u/118431096?s=200&v=4" height="70px" width="70px" />
<img src="https://avatars.githubusercontent.com/u/118431096?s=200&v=4" height="70px" width="70px" alt="galaxies-dev" />
</a>
<a href="https://github.com/kmartinezmedia">
<img src="https://avatars.githubusercontent.com/u/6308123?s=200&v=4" height="70px" width="70px" alt="kmartinezmedia" />
</a>


Expand Down
1 change: 1 addition & 0 deletions android/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ add_library(unistyles
SHARED
../cxx/UnistylesRuntime.cpp
./src/main/cxx/cpp-adapter.cpp
./src/main/cxx/helpers.cpp
)

include_directories(
Expand Down
57 changes: 33 additions & 24 deletions android/src/main/cxx/cpp-adapter.cpp
Original file line number Diff line number Diff line change
@@ -1,34 +1,26 @@
#include <jni.h>
#include <jsi/jsi.h>
#include <map>
#include "UnistylesRuntime.h"
#include "helpers.h"

using namespace facebook;

static jobject unistylesModule = nullptr;
std::shared_ptr<UnistylesRuntime> unistylesRuntime = nullptr;

void throwKotlinException(
JNIEnv *env,
const char *message
) {
jclass runtimeExceptionClass = env->FindClass("java/lang/RuntimeException");

if (runtimeExceptionClass != nullptr) {
env->ThrowNew(runtimeExceptionClass, message);
env->DeleteLocalRef(runtimeExceptionClass);
}
}

extern "C"
JNIEXPORT void JNICALL
Java_com_unistyles_UnistylesModule_nativeInstall(
JNIEnv *env,
jobject thiz,
jlong jsi,
jint screenWidth,
jint screenHeight,
jobject screen,
jstring colorScheme,
jstring contentSizeCategory
jstring contentSizeCategory,
jobject insets,
jobject statusBar,
jobject navigationBar
) {
auto runtime = reinterpret_cast<facebook::jsi::Runtime *>(jsi);

Expand All @@ -49,10 +41,12 @@ Java_com_unistyles_UnistylesModule_nativeInstall(
env->ReleaseStringUTFChars(contentSizeCategory, contentSizeCategoryChars);

unistylesRuntime = std::make_shared<UnistylesRuntime>(
screenWidth,
screenHeight,
jobjectToDimensions(env, screen),
colorSchemeStr,
contentSizeCategoryStr
contentSizeCategoryStr,
jobjectToInsets(env, insets),
jobjectToDimensions(env, statusBar),
jobjectToDimensions(env, navigationBar)
);

unistylesRuntime->onThemeChange([=](const std::string &theme) {
Expand All @@ -65,13 +59,23 @@ Java_com_unistyles_UnistylesModule_nativeInstall(
env->DeleteLocalRef(cls);
});

unistylesRuntime->onLayoutChange([=](const std::string &breakpoint, const std::string &orientation, int width, int height) {
unistylesRuntime->onLayoutChange([=](const std::string &breakpoint, const std::string &orientation, Dimensions& screen, Dimensions& statusBar, Insets& insets, Dimensions& navigationBar) {
jstring breakpointStr = env->NewStringUTF(breakpoint.c_str());
jstring orientationStr = env->NewStringUTF(orientation.c_str());
jclass cls = env->GetObjectClass(unistylesModule);
jmethodID methodId = env->GetMethodID(cls, "onLayoutChange", "(Ljava/lang/String;Ljava/lang/String;II)V");

env->CallVoidMethod(unistylesModule, methodId, breakpointStr, orientationStr, width, height);
jclass dimensionsClass = env->FindClass("com/unistyles/Dimensions");
jmethodID dimensionsConstructor = env->GetMethodID(dimensionsClass, "<init>", "(II)V");
jobject screenObj = env->NewObject(dimensionsClass, dimensionsConstructor, screen.width, screen.height);
jobject statusBarObj = env->NewObject(dimensionsClass, dimensionsConstructor, statusBar.width, statusBar.height);
jobject navigationBarObj = env->NewObject(dimensionsClass, dimensionsConstructor, navigationBar.width, navigationBar.height);

jclass insetsClass = env->FindClass("com/unistyles/Insets");
jmethodID insetsConstructor = env->GetMethodID(insetsClass, "<init>", "(IIII)V");
jobject insetsObj = env->NewObject(insetsClass, insetsConstructor, insets.left, insets.top, insets.right, insets.bottom);
jmethodID methodId = env->GetMethodID(cls, "onLayoutChange",
"(Ljava/lang/String;Ljava/lang/String;Lcom/unistyles/Dimensions;Lcom/unistyles/Dimensions;Lcom/unistyles/Insets;Lcom/unistyles/Dimensions;)V");

env->CallVoidMethod(unistylesModule, methodId, breakpointStr, orientationStr, screenObj, statusBarObj, insetsObj, navigationBarObj);
env->DeleteLocalRef(breakpointStr);
env->DeleteLocalRef(orientationStr);
env->DeleteLocalRef(cls);
Expand Down Expand Up @@ -109,9 +113,14 @@ Java_com_unistyles_UnistylesModule_nativeDestroy(JNIEnv *env, jobject thiz) {

extern "C"
JNIEXPORT void JNICALL
Java_com_unistyles_UnistylesModule_nativeOnOrientationChange(JNIEnv *env, jobject thiz, jint width, jint height) {
Java_com_unistyles_UnistylesModule_nativeOnOrientationChange(JNIEnv *env, jobject thiz, jobject screen, jobject insets, jobject statusBar, jobject navigationBar) {
if (unistylesRuntime != nullptr) {
unistylesRuntime->handleScreenSizeChange(width, height);
Dimensions screenDimensions = jobjectToDimensions(env, screen);
Dimensions statusBarDimensions = jobjectToDimensions(env, statusBar);
Insets screenInsets = jobjectToInsets(env, insets);
Dimensions navigationBarDimensions = jobjectToDimensions(env, navigationBar);

unistylesRuntime->handleScreenSizeChange(screenDimensions, screenInsets, statusBarDimensions, navigationBarDimensions);
}
}

Expand Down
44 changes: 44 additions & 0 deletions android/src/main/cxx/helpers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "helpers.h"
#include "UnistylesRuntime.h"

Dimensions jobjectToDimensions(JNIEnv *env, jobject dimensionObj) {
jclass dimensionClass = env->FindClass("com/unistyles/Dimensions");
jfieldID widthFieldID = env->GetFieldID(dimensionClass, "width", "I");
jfieldID heightFieldID = env->GetFieldID(dimensionClass, "height", "I");

int width = env->GetIntField(dimensionObj, widthFieldID);
int height = env->GetIntField(dimensionObj, heightFieldID);

env->DeleteLocalRef(dimensionClass);

return Dimensions{width, height};
}

Insets jobjectToInsets(JNIEnv *env, jobject insetsObj) {
jclass insetsClass = env->FindClass("com/unistyles/Insets");
jfieldID leftFieldID = env->GetFieldID(insetsClass, "left", "I");
jfieldID topFieldID = env->GetFieldID(insetsClass, "top", "I");
jfieldID rightFieldID = env->GetFieldID(insetsClass, "right", "I");
jfieldID bottomFieldID = env->GetFieldID(insetsClass, "bottom", "I");

int left = env->GetIntField(insetsObj, leftFieldID);
int top = env->GetIntField(insetsObj, topFieldID);
int right = env->GetIntField(insetsObj, rightFieldID);
int bottom = env->GetIntField(insetsObj, bottomFieldID);

env->DeleteLocalRef(insetsClass);

return Insets{top, bottom, left, right};
}

void throwKotlinException(
JNIEnv *env,
const char *message
) {
jclass runtimeExceptionClass = env->FindClass("java/lang/RuntimeException");

if (runtimeExceptionClass != nullptr) {
env->ThrowNew(runtimeExceptionClass, message);
env->DeleteLocalRef(runtimeExceptionClass);
}
}
9 changes: 9 additions & 0 deletions android/src/main/cxx/helpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include <jni.h>
#include <string>
#include <map>
#include <UnistylesRuntime.h>

Dimensions jobjectToDimensions(JNIEnv *env, jobject dimensionObj);
Insets jobjectToInsets(JNIEnv *env, jobject insetsObj);

void throwKotlinException(JNIEnv *env, const char *message);
116 changes: 116 additions & 0 deletions android/src/main/java/com/unistyles/Config.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package com.unistyles

import android.annotation.SuppressLint
import android.content.res.Configuration
import com.facebook.react.bridge.ReactApplicationContext

class UnistylesConfig(private val reactApplicationContext: ReactApplicationContext) {
private val insets: UnistylesInsets = UnistylesInsets(reactApplicationContext)
private val density: Float = reactApplicationContext.resources.displayMetrics.density
private var lastConfig: Config = this.getAppConfig()
private var lastLayoutConfig: LayoutConfig = this.getAppLayoutConfig()

fun hasNewConfig(): Boolean {
val newConfig = this.getAppConfig()
val newContentSizeCategory = newConfig.contentSizeCategory != lastConfig.contentSizeCategory
val newColorScheme = newConfig.colorScheme != lastConfig.colorScheme

if (!newContentSizeCategory && !newColorScheme) {
return false
}

lastConfig = newConfig
lastConfig.hasNewContentSizeCategory = newContentSizeCategory
lastConfig.hasNewColorScheme = newColorScheme

return true
}

fun hasNewLayoutConfig(): Boolean {
val newConfig = this.getAppLayoutConfig()

if (newConfig.isEqual(lastLayoutConfig)) {
return false
}

lastLayoutConfig = newConfig

return true
}

fun getConfig(): Config {
return this.lastConfig
}

fun getLayoutConfig(): LayoutConfig {
return this.lastLayoutConfig
}

private fun getAppConfig(): Config {
val fontScale = reactApplicationContext.resources.configuration.fontScale

return Config(
this.getColorScheme(),
this.getContentSizeCategory(fontScale),
)
}

private fun getAppLayoutConfig(): LayoutConfig {
val displayMetrics = reactApplicationContext.resources.displayMetrics
val screenWidth = (displayMetrics.widthPixels / density).toInt()
val screenHeight = (displayMetrics.heightPixels / density).toInt()

return LayoutConfig(
Dimensions(screenWidth, screenHeight),
this.insets.get(),
Dimensions(screenWidth, getStatusBarHeight()),
Dimensions(screenWidth, getNavigationBarHeight())
)
}

private fun getContentSizeCategory(fontScale: Float): String {
val contentSizeCategory = when {
fontScale <= 0.85f -> "Small"
fontScale <= 1.0f -> "Default"
fontScale <= 1.15f -> "Large"
fontScale <= 1.3f -> "ExtraLarge"
fontScale <= 1.5f -> "Huge"
fontScale <= 1.8 -> "ExtraHuge"
else -> "ExtraExtraHuge"
}

return contentSizeCategory
}

private fun getColorScheme(): String {
val colorScheme = when (reactApplicationContext.resources.configuration.uiMode.and(Configuration.UI_MODE_NIGHT_MASK)) {
Configuration.UI_MODE_NIGHT_YES -> "dark"
Configuration.UI_MODE_NIGHT_NO -> "light"
else -> "unspecified"
}

return colorScheme
}

@SuppressLint("InternalInsetResource", "DiscouragedApi")
private fun getStatusBarHeight(): Int {
val heightResId = reactApplicationContext.resources.getIdentifier("status_bar_height", "dimen", "android")

if (heightResId > 0) {
return (reactApplicationContext.resources.getDimensionPixelSize(heightResId) / density).toInt()
}

return 0
}

@SuppressLint("InternalInsetResource", "DiscouragedApi")
private fun getNavigationBarHeight(): Int {
val heightResId = reactApplicationContext.resources.getIdentifier("navigation_bar_height", "dimen", "android")

if (heightResId > 0) {
return (reactApplicationContext.resources.getDimensionPixelSize(heightResId) / density).toInt()
}

return 0
}
}
Loading

0 comments on commit de865e8

Please sign in to comment.