Skip to content

Commit 31002e3

Browse files
author
Piotr Trocki
committed
feat: iOS and Android implementation
1 parent a9d156c commit 31002e3

File tree

19 files changed

+3328
-66
lines changed

19 files changed

+3328
-66
lines changed

android/CMakeLists.txt

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
project(TimezoneHermesFix)
2+
cmake_minimum_required(VERSION 3.9.0)
3+
4+
set(PACKAGE_NAME "timezone-hermes-fix")
5+
6+
# Add your sources
7+
add_library(
8+
${PACKAGE_NAME}
9+
SHARED
10+
src/main/cpp/TimezoneHermesFix.cpp
11+
src/main/cpp/OnLoad.cpp
12+
)
13+
14+
# Configure C++ 17
15+
set_target_properties(
16+
${PACKAGE_NAME}
17+
PROPERTIES
18+
CXX_STANDARD 17
19+
CXX_EXTENSIONS OFF
20+
POSITION_INDEPENDENT_CODE ON
21+
LINKER_LANGUAGE CXX
22+
)
23+
24+
find_package(fbjni REQUIRED CONFIG)
25+
find_package(ReactAndroid REQUIRED CONFIG)
26+
find_package(hermes-engine REQUIRED CONFIG)
27+
string(APPEND CMAKE_CXX_FLAGS " -DJS_RUNTIME_HERMES=1")
28+
29+
target_link_libraries(
30+
${PACKAGE_NAME}
31+
hermes-engine::libhermes
32+
)
33+
34+
target_include_directories(
35+
${PACKAGE_NAME}
36+
PRIVATE
37+
"src/main/cpp"
38+
"${REACT_NATIVE_DIR}/ReactCommon"
39+
"${REACT_NATIVE_DIR}/ReactCommon/callinvoker"
40+
"${REACT_NATIVE_DIR}/ReactAndroid/src/main/jni/react/turbomodule"
41+
# Add Hermes include directories
42+
"${REACT_NATIVE_DIR}/ReactCommon/hermes"
43+
"${REACT_NATIVE_DIR}/third-party/hermes/API"
44+
)
45+
46+
# Link libraries
47+
if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)
48+
target_link_libraries(
49+
${PACKAGE_NAME}
50+
ReactAndroid::reactnative
51+
)
52+
else()
53+
target_link_libraries(
54+
${PACKAGE_NAME}
55+
ReactAndroid::reactnativejni
56+
)
57+
endif()
58+
59+
target_link_libraries(
60+
${PACKAGE_NAME}
61+
android
62+
log
63+
fbjni::fbjni
64+
ReactAndroid::jsi
65+
)
66+

android/build.gradle

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,29 @@ def getExtOrIntegerDefault(name) {
2525
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["TimezoneHermesFix_" + name]).toInteger()
2626
}
2727

28+
def REACT_NATIVE_BUILD_FROM_SOURCE = findProject(":packages:react-native:ReactAndroid") != null
29+
def REACT_NATIVE_DIR = REACT_NATIVE_BUILD_FROM_SOURCE
30+
? findProject(":packages:react-native:ReactAndroid").getProjectDir().parent
31+
: file(providers.exec {
32+
workingDir(rootDir)
33+
commandLine("node", "--print", "require.resolve('react-native/package.json')")
34+
}.standardOutput.asText.get().trim()).parent
35+
36+
def reactNativeArchitectures() {
37+
def value = project.getProperties().get("reactNativeArchitectures")
38+
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
39+
}
40+
41+
def resolveBuildType() {
42+
Gradle gradle = getGradle()
43+
String tskReqStr = gradle.getStartParameter().getTaskRequests()['args'].toString()
44+
45+
return tskReqStr.contains('Release') ? 'release' : 'debug'
46+
}
47+
48+
def reactProperties = new Properties()
49+
file("$REACT_NATIVE_DIR/ReactAndroid/gradle.properties").withInputStream { reactProperties.load(it) }
50+
2851
android {
2952
namespace "com.timezonehermesfix"
3053

@@ -33,10 +56,19 @@ android {
3356
defaultConfig {
3457
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
3558
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
59+
externalNativeBuild {
60+
cmake {
61+
cppFlags "-O2 -frtti -fexceptions -Wall -Wno-unused-variable -fstack-protector-all"
62+
arguments "-DANDROID_STL=c++_shared",
63+
"-DREACT_NATIVE_DIR=${REACT_NATIVE_DIR}"
64+
abiFilters(*reactNativeArchitectures())
65+
}
66+
}
3667
}
3768

3869
buildFeatures {
3970
buildConfig true
71+
prefab true
4072
}
4173

4274
buildTypes {
@@ -62,6 +94,12 @@ android {
6294
]
6395
}
6496
}
97+
98+
externalNativeBuild {
99+
cmake {
100+
path "CMakeLists.txt"
101+
}
102+
}
65103
}
66104

67105
repositories {
@@ -74,6 +112,7 @@ def kotlin_version = getExtOrDefault("kotlinVersion")
74112
dependencies {
75113
implementation "com.facebook.react:react-android"
76114
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
115+
implementation "com.facebook.react:hermes-android"
77116
}
78117

79118
react {

android/src/main/cpp/OnLoad.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#include <jni.h>
2+
#include <fbjni/fbjni.h>
3+
#include "TimezoneHermesFix.h"
4+
5+
using namespace facebook::jni;
6+
7+
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
8+
return initialize(vm, [] {
9+
TimezoneHermesFix::registerNatives();
10+
});
11+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#include "TimezoneHermesFix.h"
2+
#include <jsi/jsi.h>
3+
#include <ReactCommon/CallInvokerHolder.h>
4+
#include <fbjni/fbjni.h>
5+
#include <hermes/hermes.h>
6+
#include <android/log.h>
7+
8+
using namespace facebook;
9+
using namespace facebook::jni;
10+
using namespace facebook::react;
11+
using namespace facebook::hermes;
12+
13+
#define LOG_TAG "TimezoneHermesFix"
14+
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
15+
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
16+
17+
void TimezoneHermesFix::registerNatives() {
18+
registerHybrid({
19+
makeNativeMethod("initHybrid", TimezoneHermesFix::initHybrid),
20+
makeNativeMethod("coSieDzieje", TimezoneHermesFix::coSieDzieje),
21+
});
22+
}
23+
24+
jni::local_ref<TimezoneHermesFix::jhybriddata> TimezoneHermesFix::initHybrid(
25+
jni::alias_ref<jhybridobject>) {
26+
return makeCxxInstance();
27+
}
28+
29+
void TimezoneHermesFix::coSieDzieje(jlong jsRuntimePtr) {
30+
LOGD("coSieDzieje called with jsRuntimePtr: %ld", jsRuntimePtr);
31+
32+
// Get JSI Runtime pointer (equivalent to iOS cxxBridge.runtime)
33+
auto jsiRuntime = reinterpret_cast<jsi::Runtime*>(jsRuntimePtr);
34+
if (jsiRuntime == nullptr) {
35+
LOGE("jsiRuntime is null");
36+
return;
37+
}
38+
39+
// Cast to HermesRuntime (equivalent to iOS reinterpret_cast)
40+
auto hermesRuntime = reinterpret_cast<HermesRuntime*>(jsiRuntime);
41+
if (hermesRuntime == nullptr) {
42+
LOGE("hermesRuntime is null - not running on Hermes");
43+
return;
44+
}
45+
46+
try {
47+
// Call resetTimezoneCache on Hermes runtime (same as iOS)
48+
hermesRuntime->resetTimezoneCache();
49+
LOGD("Successfully called resetTimezoneCache on Hermes runtime");
50+
51+
} catch (const jsi::JSError& error) {
52+
LOGE("JSI Error calling resetTimezoneCache: %s", error.getMessage().c_str());
53+
} catch (const std::exception& error) {
54+
LOGE("Exception calling resetTimezoneCache: %s", error.what());
55+
}
56+
}
57+
58+
//void TimezoneHermesFix::resetHermesTimezoneCacheNative(
59+
// JNIEnv* env,
60+
// jclass clazz,
61+
// jlong jsRuntimePtr,
62+
// jobject callInvokerHolder
63+
//) {
64+
// LOGD("resetHermesTimezoneCacheNative called with jsRuntimePtr: %ld", jsRuntimePtr);
65+
//
66+
// // Get JSI Runtime pointer (equivalent to iOS cxxBridge.runtime)
67+
// auto jsiRuntime = reinterpret_cast<jsi::Runtime*>(jsRuntimePtr);
68+
// if (jsiRuntime == nullptr) {
69+
// LOGE("jsiRuntime is null");
70+
// return;
71+
// }
72+
//
73+
// // Cast to HermesRuntime (equivalent to iOS reinterpret_cast)
74+
//// auto hermesRuntime = reinterpret_cast<HermesRuntime*>(jsiRuntime);
75+
//// if (hermesRuntime == nullptr) {
76+
//// LOGE("hermesRuntime is null - not running on Hermes");
77+
//// return;
78+
//// }
79+
//
80+
// try {
81+
// // Call resetTimezoneCache on Hermes runtime (same as iOS)
82+
//// hermesRuntime->resetTimezoneCache();
83+
// LOGD("Successfully called resetTimezoneCache on Hermes runtime");
84+
//
85+
// } catch (const jsi::JSError& error) {
86+
// LOGE("JSI Error calling resetTimezoneCache: %s", error.getMessage().c_str());
87+
// } catch (const std::exception& error) {
88+
// LOGE("Exception calling resetTimezoneCache: %s", error.what());
89+
// }
90+
//}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
3+
#include <jni.h>
4+
#include <jsi/jsi.h>
5+
#include <ReactCommon/CallInvokerHolder.h>
6+
#include <fbjni/fbjni.h>
7+
8+
using namespace facebook;
9+
10+
class TimezoneHermesFix: public jni::HybridClass<TimezoneHermesFix> {
11+
public:
12+
static constexpr auto kJavaDescriptor = "Lcom/timezonehermesfix/TimezoneHermesFixModule;";
13+
static void registerNatives();
14+
static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject>);
15+
16+
void coSieDzieje(jlong jsRuntimePtr);
17+
18+
private:
19+
friend HybridBase;
20+
TimezoneHermesFix() {}
21+
};

0 commit comments

Comments
 (0)