@dittolive/ditto 4.9.0-rc.3 → 4.9.1-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DittoReactNative.podspec +16 -16
- package/LICENSE.md +17 -0
- package/README.md +2 -2
- package/node/ditto.cjs.js +1 -1
- package/node/ditto.darwin-arm64.node +0 -0
- package/node/ditto.darwin-x64.node +0 -0
- package/node/ditto.linux-arm.node +0 -0
- package/node/ditto.linux-arm64.node +0 -0
- package/node/ditto.linux-x64.node +0 -0
- package/node/ditto.win32-x64.node +0 -0
- package/package.json +2 -4
- package/react-native/android/CMakeLists.txt +15 -6
- package/react-native/android/build.gradle +33 -20
- package/react-native/android/cpp-adapter.cpp +89 -113
- package/react-native/android/src/main/java/com/dittolive/rnsdk/DittoRNSDKModule.kt +59 -0
- package/react-native/android/src/main/java/com/dittolive/rnsdk/DittoRNSDKPackage.kt +17 -0
- package/react-native/cpp/include/DQL.h +1 -0
- package/react-native/cpp/include/GlobalCallInvoker.h +8 -0
- package/react-native/cpp/include/Lifecycle.h +1 -1
- package/react-native/cpp/include/LiveQuery.h +0 -2
- package/react-native/cpp/include/Misc.h +0 -1
- package/react-native/cpp/include/Utils.h +1 -1
- package/react-native/cpp/include/main.h +5 -4
- package/react-native/cpp/src/Attachment.cpp +14 -17
- package/react-native/cpp/src/Authentication.cpp +12 -12
- package/react-native/cpp/src/Collection.cpp +10 -10
- package/react-native/cpp/src/ConnectionRequest.cpp +3 -3
- package/react-native/cpp/src/DQL.cpp +22 -7
- package/react-native/cpp/src/Document.cpp +9 -9
- package/react-native/cpp/src/FFIUtils.cpp +1 -1
- package/react-native/cpp/src/GlobalCallInvoker.cpp +4 -0
- package/react-native/cpp/src/IO.cpp +2 -2
- package/react-native/cpp/src/Lifecycle.cpp +4 -4
- package/react-native/cpp/src/LiveQuery.cpp +5 -5
- package/react-native/cpp/src/Logger.cpp +2 -5
- package/react-native/cpp/src/Misc.cpp +14 -14
- package/react-native/cpp/src/Presence.cpp +9 -11
- package/react-native/cpp/src/SmallPeerInfo.cpp +7 -7
- package/react-native/cpp/src/Transports.cpp +14 -14
- package/react-native/cpp/src/Utils.cpp +55 -41
- package/react-native/cpp/src/main.cpp +7 -2
- package/react-native/ditto.es6.js +1 -1
- package/react-native/ios/DittoRNSDK.mm +8 -2
- package/web/ditto.es6.js +1 -1
- package/web/ditto.umd.js +1 -1
- package/web/ditto.wasm +0 -0
- package/react-native/android/src/main/java/com/dittolive/rnsdk/DittoRNSDKModule.java +0 -55
- package/react-native/android/src/main/java/com/dittolive/rnsdk/DittoRNSDKPackage.java +0 -28
package/DittoReactNative.podspec
CHANGED
|
@@ -36,21 +36,21 @@ Pod::Spec.new do |s|
|
|
|
36
36
|
if respond_to?(:install_modules_dependencies, true)
|
|
37
37
|
install_modules_dependencies(s)
|
|
38
38
|
else
|
|
39
|
-
|
|
39
|
+
s.dependency "React-Core"
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
end
|
|
41
|
+
# Don't install the dependencies when we run `pod install` in the old architecture.
|
|
42
|
+
if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
|
|
43
|
+
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
|
|
44
|
+
s.pod_target_xcconfig = {
|
|
45
|
+
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
|
46
|
+
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
|
47
|
+
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
|
48
|
+
}
|
|
49
|
+
s.dependency "React-Codegen"
|
|
50
|
+
s.dependency "RCT-Folly"
|
|
51
|
+
s.dependency "RCTRequired"
|
|
52
|
+
s.dependency "RCTTypeSafety"
|
|
53
|
+
s.dependency "ReactCommon/turbomodule/core"
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
56
|
end
|
package/LICENSE.md
CHANGED
|
@@ -32,3 +32,20 @@ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
32
32
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
33
33
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
34
34
|
POSSIBILITY OF SUCH DAMAGE.
|
|
35
|
+
|
|
36
|
+
### Third-Party Notices
|
|
37
|
+
|
|
38
|
+
This project includes code from the "MockFinalizationRegistry.js" gist by `cray0000`, available at:
|
|
39
|
+
https://gist.github.com/cray0000/abecb1ca71fd28a1d8efff2be9e0f6c5
|
|
40
|
+
|
|
41
|
+
This code is used under the MIT License:
|
|
42
|
+
|
|
43
|
+
MIT License
|
|
44
|
+
|
|
45
|
+
Copyright (c) 2024 cray0000
|
|
46
|
+
|
|
47
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
48
|
+
|
|
49
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
50
|
+
|
|
51
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
_Ditto is a cross-platform SDK that allows mobile, web, and IoT apps to sync
|
|
4
4
|
with and even without connectivity._
|
|
5
5
|
|
|
6
|
-
Version: **4.9.
|
|
6
|
+
Version: **4.9.1-rc.1**
|
|
7
7
|
|
|
8
8
|
For more information please visit [ditto.live](https://ditto.live), as well as the
|
|
9
|
-
[API Reference](https://software.ditto.live/js/Ditto/4.9.
|
|
9
|
+
[API Reference](https://software.ditto.live/js/Ditto/4.9.1-rc.1/api-reference/) for this particular version.
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
package/node/ditto.cjs.js
CHANGED
|
@@ -2310,7 +2310,7 @@ class AttachmentToken {
|
|
|
2310
2310
|
|
|
2311
2311
|
// NOTE: this is patched up with the actual build version by Jake task
|
|
2312
2312
|
// build:package and has to be a valid semantic version as defined here: https://semver.org.
|
|
2313
|
-
const fullBuildVersionString = '4.9.
|
|
2313
|
+
const fullBuildVersionString = '4.9.1-rc.1';
|
|
2314
2314
|
|
|
2315
2315
|
//
|
|
2316
2316
|
// Copyright © 2021 DittoLive Incorporated. All rights reserved.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dittolive/ditto",
|
|
3
|
-
"version": "4.9.
|
|
3
|
+
"version": "4.9.1-rc.1",
|
|
4
4
|
"description": "Ditto is a cross-platform SDK that allows apps to sync with and even without internet connectivity.",
|
|
5
5
|
"homepage": "https://ditto.live",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
@@ -42,9 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"cbor-redux": "^1.0.0"
|
|
46
|
-
"@ungap/weakrefs": "^0.2.0",
|
|
47
|
-
"fastestsmallesttextencoderdecoder": "^1.0.22"
|
|
45
|
+
"cbor-redux": "^1.0.0"
|
|
48
46
|
},
|
|
49
47
|
|
|
50
48
|
"devDependencies": {
|
|
@@ -2,7 +2,6 @@ cmake_minimum_required(VERSION 3.9.0)
|
|
|
2
2
|
|
|
3
3
|
set(PACKAGE_NAME "dittorn")
|
|
4
4
|
project(PACKAGE_NAME)
|
|
5
|
-
set(BUILD_DIR ../../../)
|
|
6
5
|
set(CMAKE_VERBOSE_MAKEFILE ON)
|
|
7
6
|
set(CMAKE_CXX_STANDARD 17)
|
|
8
7
|
|
|
@@ -20,15 +19,25 @@ add_library(
|
|
|
20
19
|
)
|
|
21
20
|
|
|
22
21
|
find_package(ReactAndroid REQUIRED CONFIG)
|
|
23
|
-
find_library(
|
|
22
|
+
find_library(LOG_LIB log)
|
|
23
|
+
find_package(fbjni REQUIRED CONFIG)
|
|
24
24
|
|
|
25
25
|
add_library(dittoffi SHARED IMPORTED)
|
|
26
26
|
set_target_properties(dittoffi PROPERTIES IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/dittoffi/libs/${ANDROID_ABI}/libdittoffi.so")
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
${PACKAGE_NAME}
|
|
28
|
+
if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)
|
|
29
|
+
target_link_libraries(${PACKAGE_NAME} ReactAndroid::reactnative)
|
|
30
|
+
else()
|
|
31
|
+
target_link_libraries(${PACKAGE_NAME}
|
|
32
|
+
ReactAndroid::turbomodulejsijni
|
|
33
|
+
ReactAndroid::react_nativemodule_core
|
|
34
|
+
android
|
|
35
|
+
)
|
|
36
|
+
endif()
|
|
37
|
+
|
|
38
|
+
target_link_libraries(${PACKAGE_NAME}
|
|
30
39
|
dittoffi
|
|
31
|
-
${
|
|
40
|
+
${LOG_LIB}
|
|
32
41
|
ReactAndroid::jsi
|
|
33
|
-
|
|
42
|
+
fbjni::fbjni
|
|
34
43
|
)
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import java.nio.file.Paths
|
|
2
1
|
import groovy.json.JsonSlurper
|
|
3
2
|
|
|
4
3
|
buildscript {
|
|
4
|
+
// Buildscript is evaluated before everything else so we can't use getExtOrDefault
|
|
5
|
+
def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["rnsdk_kotlinVersion"]
|
|
6
|
+
|
|
5
7
|
repositories {
|
|
6
8
|
google()
|
|
7
9
|
mavenCentral()
|
|
@@ -9,15 +11,22 @@ buildscript {
|
|
|
9
11
|
|
|
10
12
|
dependencies {
|
|
11
13
|
classpath "com.android.tools.build:gradle:7.2.1"
|
|
14
|
+
// noinspection DifferentKotlinGradleVersion
|
|
15
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
12
16
|
}
|
|
13
17
|
}
|
|
14
18
|
|
|
19
|
+
def reactNativeArchitectures() {
|
|
20
|
+
def value = rootProject.getProperties().get("reactNativeArchitectures")
|
|
21
|
+
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
|
|
22
|
+
}
|
|
23
|
+
|
|
15
24
|
def isNewArchitectureEnabled() {
|
|
16
25
|
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
|
|
17
26
|
}
|
|
18
27
|
|
|
19
28
|
apply plugin: "com.android.library"
|
|
20
|
-
|
|
29
|
+
apply plugin: "kotlin-android"
|
|
21
30
|
|
|
22
31
|
if (isNewArchitectureEnabled()) {
|
|
23
32
|
apply plugin: "com.facebook.react"
|
|
@@ -68,7 +77,7 @@ android {
|
|
|
68
77
|
cppFlags "-O2 -frtti -fexceptions -Wall -fstack-protector-all"
|
|
69
78
|
// ESSENTIAL for adding JSI
|
|
70
79
|
arguments "-DANDROID_STL=c++_shared"
|
|
71
|
-
abiFilters
|
|
80
|
+
abiFilters (*reactNativeArchitectures())
|
|
72
81
|
}
|
|
73
82
|
}
|
|
74
83
|
}
|
|
@@ -100,6 +109,8 @@ repositories {
|
|
|
100
109
|
google()
|
|
101
110
|
}
|
|
102
111
|
|
|
112
|
+
def kotlin_version = getExtOrDefault("kotlinVersion")
|
|
113
|
+
|
|
103
114
|
def getVersionFromPackageJson() {
|
|
104
115
|
def packageJsonPath = file('../../package.json')
|
|
105
116
|
if (packageJsonPath.exists()) {
|
|
@@ -117,34 +128,36 @@ dependencies {
|
|
|
117
128
|
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
|
|
118
129
|
//noinspection GradleDynamicVersion
|
|
119
130
|
implementation "com.facebook.react:react-native:+"
|
|
131
|
+
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
120
132
|
|
|
121
|
-
def aarFile = file('dittoffi/aar/ditto.aar')
|
|
122
|
-
def aarExists = aarFile.exists()
|
|
133
|
+
def aarFile = file('dittoffi/aar/ditto.aar')
|
|
134
|
+
def aarExists = aarFile.exists()
|
|
123
135
|
|
|
124
136
|
if (aarExists) {
|
|
125
|
-
|
|
137
|
+
println "Using local `ditto.aar`."
|
|
138
|
+
implementation files('dittoffi/aar/ditto.aar')
|
|
126
139
|
} else {
|
|
127
140
|
implementation "live.ditto:ditto:${project.version}"
|
|
128
141
|
}
|
|
129
142
|
}
|
|
130
143
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
144
|
+
tasks.register('downloadBinaries') {
|
|
145
|
+
doLast {
|
|
146
|
+
def defaultArchitectures = ['arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64']
|
|
134
147
|
|
|
135
|
-
|
|
136
|
-
|
|
148
|
+
defaultArchitectures.each { arch ->
|
|
149
|
+
def fileUrl = "https://software.ditto.live/react-native/ditto/${project.version}/android/${arch}/libdittoffi.so"
|
|
137
150
|
|
|
138
|
-
|
|
139
|
-
|
|
151
|
+
new File("${project.projectDir}/dittoffi/libs/${arch}").mkdirs()
|
|
152
|
+
def localFilePath = "${project.projectDir}/dittoffi/libs/${arch}/libdittoffi.so"
|
|
140
153
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
154
|
+
if (!new File(localFilePath).exists()) {
|
|
155
|
+
println "Downloading file for $arch: $fileUrl"
|
|
156
|
+
ant.get(src: fileUrl, dest: localFilePath, verbose: true)
|
|
157
|
+
} else {
|
|
158
|
+
println "File for $arch already exists, skipping download: $localFilePath"
|
|
159
|
+
}
|
|
148
160
|
}
|
|
161
|
+
}
|
|
149
162
|
}
|
|
150
163
|
preBuild.dependsOn downloadBinaries
|
|
@@ -1,145 +1,103 @@
|
|
|
1
1
|
#include <jni.h>
|
|
2
|
-
#include <sys/types.h>
|
|
3
2
|
#include <jsi/jsi.h>
|
|
4
3
|
#include <pthread.h>
|
|
5
|
-
|
|
6
|
-
#include "main.h"
|
|
7
|
-
#include "TypedArray.hpp"
|
|
8
|
-
#include "dittoffi.h"
|
|
9
4
|
#include <sstream>
|
|
10
5
|
#include <string>
|
|
11
6
|
#include <vector>
|
|
12
7
|
#include <android/log.h>
|
|
8
|
+
#include <ReactCommon/CallInvokerHolder.h>
|
|
9
|
+
|
|
10
|
+
#include "dittoffi.h"
|
|
11
|
+
#include "main.h"
|
|
12
|
+
|
|
13
13
|
|
|
14
|
-
using namespace facebook
|
|
14
|
+
using namespace facebook;
|
|
15
15
|
|
|
16
16
|
JavaVM *java_vm;
|
|
17
|
-
jclass java_class;
|
|
18
17
|
jobject java_object;
|
|
19
18
|
jobject java_context;
|
|
20
19
|
|
|
21
20
|
/**
|
|
22
|
-
* A
|
|
23
|
-
*
|
|
24
|
-
* See https://stackoverflow.com/a/30026231 for detailed explanation
|
|
21
|
+
* A callback function that detaches the current JNI Environment when the thread exits.
|
|
22
|
+
* See https://stackoverflow.com/a/30026231 for detailed explanation.
|
|
25
23
|
*/
|
|
26
|
-
|
|
27
|
-
void DeferThreadDetach(JNIEnv *env)
|
|
28
|
-
{
|
|
24
|
+
void DeferThreadDetach(JNIEnv *env) {
|
|
29
25
|
static pthread_key_t thread_key;
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
// This is only done once, across all threads, and the value
|
|
34
|
-
// associated with the key for any given thread will initially
|
|
35
|
-
// be NULL.
|
|
36
|
-
static auto run_once = []
|
|
37
|
-
{
|
|
38
|
-
const auto err = pthread_key_create(&thread_key, [](void *ts_env)
|
|
39
|
-
{
|
|
27
|
+
static auto run_once = [] {
|
|
28
|
+
const auto err = pthread_key_create(&thread_key, [](void *ts_env) {
|
|
40
29
|
if (ts_env) {
|
|
41
30
|
java_vm->DetachCurrentThread();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
{
|
|
45
|
-
// Failed to create TSD key.
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
if (err) {
|
|
34
|
+
// Failed to create TSD key. Handle error if necessary.
|
|
46
35
|
}
|
|
47
36
|
return 0;
|
|
48
|
-
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
run_once();
|
|
49
40
|
|
|
50
|
-
// For the callback to actually be executed when a thread exits
|
|
51
|
-
// we need to associate a non-NULL value with the key on that thread.
|
|
52
|
-
// We can use the JNIEnv* as that value.
|
|
53
41
|
const auto ts_env = pthread_getspecific(thread_key);
|
|
54
|
-
if (!ts_env)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
{
|
|
58
|
-
// Failed to set thread-specific value for key. Throw an exception if you want to.
|
|
42
|
+
if (!ts_env) {
|
|
43
|
+
if (pthread_setspecific(thread_key, env)) {
|
|
44
|
+
// Failed to set thread-specific value for key. Handle error if necessary.
|
|
59
45
|
}
|
|
60
46
|
}
|
|
61
47
|
}
|
|
62
48
|
|
|
63
49
|
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* If the calling thread is not currently attached to the JVM
|
|
67
|
-
* it will be attached, and then automatically detached when the
|
|
68
|
-
* thread is destroyed.
|
|
69
|
-
*
|
|
70
|
-
* See https://stackoverflow.com/a/30026231 for detailed explanation
|
|
50
|
+
* Gets a JNIEnv* valid for the current thread, attaching to the JVM if necessary.
|
|
51
|
+
* See https://stackoverflow.com/a/30026231 for detailed explanation.
|
|
71
52
|
*/
|
|
72
|
-
JNIEnv *GetJniEnv()
|
|
73
|
-
{
|
|
53
|
+
JNIEnv *GetJniEnv() {
|
|
74
54
|
JNIEnv *env = nullptr;
|
|
75
|
-
// We still call GetEnv first to detect if the thread already
|
|
76
|
-
// is attached. This is done to avoid setting up a DetachCurrentThread
|
|
77
|
-
// call on a Java thread.
|
|
78
|
-
|
|
79
|
-
// g_vm is a global.
|
|
80
55
|
auto get_env_result = java_vm->GetEnv((void **)&env, JNI_VERSION_1_6);
|
|
81
|
-
if (get_env_result == JNI_EDETACHED)
|
|
82
|
-
|
|
83
|
-
if (java_vm->AttachCurrentThread(&env, NULL) == JNI_OK)
|
|
84
|
-
{
|
|
56
|
+
if (get_env_result == JNI_EDETACHED) {
|
|
57
|
+
if (java_vm->AttachCurrentThread(&env, NULL) == JNI_OK) {
|
|
85
58
|
DeferThreadDetach(env);
|
|
59
|
+
} else {
|
|
60
|
+
// Failed to attach thread. Handle error if necessary.
|
|
86
61
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
// Failed to attach thread. Throw an exception if you want to.
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
else if (get_env_result == JNI_EVERSION)
|
|
93
|
-
{
|
|
94
|
-
// Unsupported JNI version. Throw an exception if you want to.
|
|
62
|
+
} else if (get_env_result == JNI_EVERSION) {
|
|
63
|
+
// Unsupported JNI version. Handle error if necessary.
|
|
95
64
|
}
|
|
96
65
|
return env;
|
|
97
66
|
}
|
|
98
67
|
|
|
99
|
-
void install(Runtime &jsiRuntime)
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
return Value(runtime,
|
|
123
|
-
String::createFromUtf8(
|
|
124
|
-
runtime, str));
|
|
125
|
-
});
|
|
68
|
+
void install(Runtime &jsiRuntime) {
|
|
69
|
+
auto defaultDeviceName = Function::createFromHostFunction(
|
|
70
|
+
jsiRuntime,
|
|
71
|
+
PropNameID::forAscii(jsiRuntime, "defaultDeviceName"),
|
|
72
|
+
0,
|
|
73
|
+
[](Runtime &runtime, const Value &thisValue, const Value *arguments, size_t count) -> Value {
|
|
74
|
+
JNIEnv *jniEnv = GetJniEnv();
|
|
75
|
+
|
|
76
|
+
jclass local_java_class = jniEnv->GetObjectClass(java_object);
|
|
77
|
+
jmethodID defaultDeviceNameMethod = jniEnv->GetMethodID(
|
|
78
|
+
local_java_class, "defaultDeviceName", "()Ljava/lang/String;");
|
|
79
|
+
jobject result = jniEnv->CallObjectMethod(java_object, defaultDeviceNameMethod);
|
|
80
|
+
|
|
81
|
+
const char *str = jniEnv->GetStringUTFChars((jstring)result, NULL);
|
|
82
|
+
Value returnValue = Value(runtime, String::createFromUtf8(runtime, str));
|
|
83
|
+
|
|
84
|
+
jniEnv->ReleaseStringUTFChars((jstring)result, str);
|
|
85
|
+
jniEnv->DeleteLocalRef(result);
|
|
86
|
+
jniEnv->DeleteLocalRef(local_java_class);
|
|
87
|
+
|
|
88
|
+
return returnValue;
|
|
89
|
+
});
|
|
126
90
|
|
|
127
91
|
jsiRuntime.global().setProperty(jsiRuntime, "defaultDeviceName", std::move(defaultDeviceName));
|
|
128
92
|
|
|
129
|
-
auto ditto_sdk_transports_set_android_context = Function::createFromHostFunction(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
size_t count) -> Value {
|
|
138
|
-
|
|
139
|
-
return ::ditto_sdk_transports_set_android_context(
|
|
140
|
-
GetJniEnv(),
|
|
141
|
-
java_context);
|
|
142
|
-
});
|
|
93
|
+
auto ditto_sdk_transports_set_android_context = Function::createFromHostFunction(
|
|
94
|
+
jsiRuntime,
|
|
95
|
+
PropNameID::forUtf8(jsiRuntime, "ditto_sdk_transports_set_android_context"),
|
|
96
|
+
1,
|
|
97
|
+
[](Runtime &runtime, const Value &thisArg, const Value *args, size_t count) -> Value {
|
|
98
|
+
int result = ::ditto_sdk_transports_set_android_context(GetJniEnv(), java_context);
|
|
99
|
+
return Value(result);
|
|
100
|
+
});
|
|
143
101
|
|
|
144
102
|
jsiRuntime.global().setProperty(jsiRuntime, "ditto_sdk_transports_set_android_context",
|
|
145
103
|
std::move(ditto_sdk_transports_set_android_context));
|
|
@@ -148,11 +106,8 @@ void install(Runtime &jsiRuntime)
|
|
|
148
106
|
jsiRuntime,
|
|
149
107
|
PropNameID::forUtf8(jsiRuntime, "ditto_sdk_transports_android_missing_permissions"),
|
|
150
108
|
1,
|
|
151
|
-
[](Runtime &runtime,
|
|
152
|
-
|
|
153
|
-
const Value *args,
|
|
154
|
-
size_t count) -> Value {
|
|
155
|
-
char *result = ::ditto_sdk_transports_android_missing_permissions();
|
|
109
|
+
[](Runtime &runtime, const Value &thisArg, const Value *args, size_t count) -> Value {
|
|
110
|
+
const char *result = ::ditto_sdk_transports_android_missing_permissions();
|
|
156
111
|
std::vector<std::string> lines;
|
|
157
112
|
std::stringstream ss(result);
|
|
158
113
|
std::string line;
|
|
@@ -165,6 +120,8 @@ void install(Runtime &jsiRuntime)
|
|
|
165
120
|
jsiArray.setValueAtIndex(runtime, i, String::createFromUtf8(runtime, lines[i]));
|
|
166
121
|
}
|
|
167
122
|
|
|
123
|
+
free(const_cast<char*>(result));
|
|
124
|
+
|
|
168
125
|
return jsiArray;
|
|
169
126
|
});
|
|
170
127
|
|
|
@@ -172,21 +129,40 @@ void install(Runtime &jsiRuntime)
|
|
|
172
129
|
std::move(ditto_sdk_transports_android_missing_permissions));
|
|
173
130
|
}
|
|
174
131
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
132
|
+
|
|
133
|
+
extern "C"
|
|
134
|
+
JNIEXPORT void JNICALL
|
|
135
|
+
Java_com_dittolive_rnsdk_DittoRNSDKModule_nativeInstall(JNIEnv *env, jobject thiz, jobject context, jobject callInvokerHolderObj,
|
|
136
|
+
jlong jsi_ptr, jstring default_dir)
|
|
137
|
+
{
|
|
178
138
|
// Save context, module, java_vm objects globally (thread-safe, as opposed to JNIEnv)
|
|
179
139
|
java_context = env->NewGlobalRef(context);
|
|
180
140
|
java_object = env->NewGlobalRef(thiz);
|
|
181
141
|
env->GetJavaVM(&java_vm);
|
|
182
142
|
|
|
183
|
-
Runtime &runtime = *(reinterpret_cast<Runtime *>(
|
|
143
|
+
Runtime &runtime = *(reinterpret_cast<Runtime *>(jsi_ptr));
|
|
144
|
+
|
|
145
|
+
// We knew we need to pass the callInvoker from Java to JNI and eventually
|
|
146
|
+
// access the cthis() method to get the actual CallInvoker object, just like
|
|
147
|
+
// in the video: https://youtu.be/oLmGInjKU2U?feature=shared&t=1220
|
|
148
|
+
// The details on how to do this were not documented, though.
|
|
149
|
+
// We have to figure a way to get the actual CallInvoker object using the fbjni library.
|
|
150
|
+
//
|
|
151
|
+
// jni::alias_ref<> is a wrapper provided by the React Native JNI layer.
|
|
152
|
+
// It creates an “alias” reference type which helps in managing the
|
|
153
|
+
// lifecycle of JNI references more safely. The alias_ref ensures that the
|
|
154
|
+
// reference is valid within the current scope and automatically deletes
|
|
155
|
+
// the local reference when going out of scope to prevent memory leaks.
|
|
156
|
+
auto callInvokerHolderObjRef = reinterpret_cast<react::CallInvokerHolder::javaobject>(callInvokerHolderObj);
|
|
157
|
+
auto jsCallInvokerHolder = jni::alias_ref<react::CallInvokerHolder::javaobject>(callInvokerHolderObjRef)->cthis();
|
|
158
|
+
auto jsCallInvoker = jsCallInvokerHolder->getCallInvoker();
|
|
184
159
|
|
|
185
160
|
Object parameters(runtime);
|
|
186
|
-
const char *str = env->GetStringUTFChars(
|
|
161
|
+
const char *str = env->GetStringUTFChars(default_dir, NULL);
|
|
187
162
|
String defaultDirStr = String::createFromUtf8(runtime, str);
|
|
188
163
|
parameters.setProperty(runtime, "defaultDirectory", defaultDirStr);
|
|
164
|
+
env->ReleaseStringUTFChars(default_dir, str);
|
|
189
165
|
|
|
190
|
-
sharedjsi::install(runtime, parameters);
|
|
166
|
+
sharedjsi::install(runtime, jsCallInvoker, parameters);
|
|
191
167
|
install(runtime);
|
|
192
168
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
package com.dittolive.rnsdk
|
|
2
|
+
|
|
3
|
+
import android.os.Build
|
|
4
|
+
import android.util.Log
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
7
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
8
|
+
import com.facebook.react.bridge.ReactMethod
|
|
9
|
+
import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@ReactModule(name = DittoRNSDKModule.NAME)
|
|
13
|
+
class DittoRNSDKModule(private val reactContext: ReactApplicationContext) :
|
|
14
|
+
ReactContextBaseJavaModule(reactContext) {
|
|
15
|
+
companion object {
|
|
16
|
+
const val NAME = "DittoRNSDK"
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
private external fun nativeInstall(
|
|
20
|
+
context: ReactApplicationContext,
|
|
21
|
+
callInvoker: CallInvokerHolder,
|
|
22
|
+
jsiPtr: Long,
|
|
23
|
+
defaultDir: String
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
override fun getName(): String = NAME
|
|
27
|
+
|
|
28
|
+
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
29
|
+
fun install(): Boolean {
|
|
30
|
+
return try {
|
|
31
|
+
System.loadLibrary("dittorn")
|
|
32
|
+
|
|
33
|
+
val jsContextHolder = reactContext.javaScriptContextHolder
|
|
34
|
+
val jsCallInvokerHolder = reactContext.catalystInstance.jsCallInvokerHolder
|
|
35
|
+
|
|
36
|
+
if (jsContextHolder != null && jsCallInvokerHolder != null) {
|
|
37
|
+
nativeInstall(
|
|
38
|
+
reactContext,
|
|
39
|
+
jsCallInvokerHolder,
|
|
40
|
+
jsContextHolder.get(),
|
|
41
|
+
reactContext.filesDir.absolutePath
|
|
42
|
+
)
|
|
43
|
+
true
|
|
44
|
+
} else {
|
|
45
|
+
Log.e("ReactNative", "JavaScript context or call invoker holder is null.")
|
|
46
|
+
false
|
|
47
|
+
}
|
|
48
|
+
} catch (exception: Exception) {
|
|
49
|
+
Log.e("ReactNative", "Failed to load library or initialize: ${exception.message}", exception)
|
|
50
|
+
false
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
fun defaultDeviceName(): String {
|
|
55
|
+
val manufacturer = Build.MANUFACTURER
|
|
56
|
+
val model = Build.MODEL
|
|
57
|
+
return if (model.startsWith(manufacturer)) model else "$manufacturer $model"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
package com.dittolive.rnsdk
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.uimanager.ViewManager
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DittoRNSDKPackage : ReactPackage {
|
|
10
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
|
11
|
+
return listOf(DittoRNSDKModule(reactContext))
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
15
|
+
return emptyList()
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -16,6 +16,7 @@ Function dittoffi_query_result_mutated_document_id_count(Runtime &runtime);
|
|
|
16
16
|
Function dittoffi_query_result_mutated_document_id_at(Runtime &runtime);
|
|
17
17
|
Function dittoffi_query_result_item_cbor(Runtime &runtime);
|
|
18
18
|
Function dittoffi_query_result_item_json(Runtime &runtime);
|
|
19
|
+
Function dittoffi_query_result_free(Runtime &runtime);
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
#endif /* DQL_H */
|
|
@@ -10,8 +10,6 @@ namespace sharedjsi
|
|
|
10
10
|
Function ditto_live_query_signal_available_next(Runtime &runtime);
|
|
11
11
|
Function ditto_live_query_start(Runtime &runtime);
|
|
12
12
|
Function ditto_live_query_stop(Runtime &runtime);
|
|
13
|
-
Function ditto_live_query_register_str_detached(Runtime &runtime);
|
|
14
|
-
void v_live_query_update(void *ctx, c_cb_params_t params);
|
|
15
13
|
}
|
|
16
14
|
|
|
17
15
|
#endif /* LiveQuery_H */
|