@fressh/react-native-terminal 0.1.0

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.
Files changed (73) hide show
  1. package/README.md +182 -0
  2. package/ReactNativeTerminal.podspec +82 -0
  3. package/android/CMakeLists.txt +76 -0
  4. package/android/build.gradle +121 -0
  5. package/android/fix-prefab.gradle +51 -0
  6. package/android/src/main/assets/fonts/DejaVuSansMono.ttf +0 -0
  7. package/android/src/main/cpp/cpp-adapter.cpp +180 -0
  8. package/android/src/main/java/com/margelo/nitro/fressh/HybridTerminal.kt +146 -0
  9. package/android/src/main/java/com/margelo/nitro/fressh/ReactNativeTerminalModule.kt +43 -0
  10. package/android/src/main/java/com/margelo/nitro/fressh/ReactNativeTerminalPackage.kt +32 -0
  11. package/android/src/main/jniLibs/arm64-v8a/libshim_uniffi.so +0 -0
  12. package/android/src/main/jniLibs/x86_64/libshim_uniffi.so +0 -0
  13. package/babel.config.js +12 -0
  14. package/cpp/README.md +14 -0
  15. package/cpp/generated/shim_uniffi.cpp +4246 -0
  16. package/cpp/generated/shim_uniffi.hpp +364 -0
  17. package/ios/FresshTerminalRenderABI.h +46 -0
  18. package/ios/HybridTerminal.swift +144 -0
  19. package/ios/ReactNativeTerminalUniffi.mm +77 -0
  20. package/ios/fetch-angle.sh +39 -0
  21. package/ios/fonts/DejaVuSansMono.ttf +0 -0
  22. package/libEGL.xcframework/Info.plist +44 -0
  23. package/libEGL.xcframework/ios-arm64/libEGL.framework/Info.plist +0 -0
  24. package/libEGL.xcframework/ios-arm64/libEGL.framework/libEGL +0 -0
  25. package/libEGL.xcframework/ios-arm64_x86_64-simulator/libEGL.framework/Info.plist +0 -0
  26. package/libEGL.xcframework/ios-arm64_x86_64-simulator/libEGL.framework/libEGL +0 -0
  27. package/libGLESv2.xcframework/Info.plist +44 -0
  28. package/libGLESv2.xcframework/ios-arm64/libGLESv2.framework/Info.plist +0 -0
  29. package/libGLESv2.xcframework/ios-arm64/libGLESv2.framework/libGLESv2 +0 -0
  30. package/libGLESv2.xcframework/ios-arm64_x86_64-simulator/libGLESv2.framework/Info.plist +0 -0
  31. package/libGLESv2.xcframework/ios-arm64_x86_64-simulator/libGLESv2.framework/libGLESv2 +0 -0
  32. package/nitro/Terminal.nitro.ts +40 -0
  33. package/nitrogen/generated/.gitattributes +1 -0
  34. package/nitrogen/generated/android/ReactNativeTerminal+autolinking.cmake +83 -0
  35. package/nitrogen/generated/android/ReactNativeTerminal+autolinking.gradle +27 -0
  36. package/nitrogen/generated/android/ReactNativeTerminalOnLoad.cpp +56 -0
  37. package/nitrogen/generated/android/ReactNativeTerminalOnLoad.hpp +34 -0
  38. package/nitrogen/generated/android/c++/JHybridTerminalSpec.cpp +76 -0
  39. package/nitrogen/generated/android/c++/JHybridTerminalSpec.hpp +68 -0
  40. package/nitrogen/generated/android/c++/views/JHybridTerminalStateUpdater.cpp +64 -0
  41. package/nitrogen/generated/android/c++/views/JHybridTerminalStateUpdater.hpp +49 -0
  42. package/nitrogen/generated/android/kotlin/com/margelo/nitro/fressh/HybridTerminalSpec.kt +69 -0
  43. package/nitrogen/generated/android/kotlin/com/margelo/nitro/fressh/ReactNativeTerminalOnLoad.kt +35 -0
  44. package/nitrogen/generated/android/kotlin/com/margelo/nitro/fressh/views/HybridTerminalManager.kt +80 -0
  45. package/nitrogen/generated/android/kotlin/com/margelo/nitro/fressh/views/HybridTerminalStateUpdater.kt +23 -0
  46. package/nitrogen/generated/ios/ReactNativeTerminal+autolinking.rb +62 -0
  47. package/nitrogen/generated/ios/ReactNativeTerminal-Swift-Cxx-Bridge.cpp +33 -0
  48. package/nitrogen/generated/ios/ReactNativeTerminal-Swift-Cxx-Bridge.hpp +57 -0
  49. package/nitrogen/generated/ios/ReactNativeTerminal-Swift-Cxx-Umbrella.hpp +43 -0
  50. package/nitrogen/generated/ios/ReactNativeTerminalAutolinking.mm +33 -0
  51. package/nitrogen/generated/ios/ReactNativeTerminalAutolinking.swift +26 -0
  52. package/nitrogen/generated/ios/c++/HybridTerminalSpecSwift.cpp +11 -0
  53. package/nitrogen/generated/ios/c++/HybridTerminalSpecSwift.hpp +96 -0
  54. package/nitrogen/generated/ios/c++/views/HybridTerminalComponent.mm +132 -0
  55. package/nitrogen/generated/ios/swift/HybridTerminalSpec.swift +57 -0
  56. package/nitrogen/generated/ios/swift/HybridTerminalSpec_cxx.swift +204 -0
  57. package/nitrogen/generated/shared/c++/HybridTerminalSpec.cpp +26 -0
  58. package/nitrogen/generated/shared/c++/HybridTerminalSpec.hpp +68 -0
  59. package/nitrogen/generated/shared/c++/views/HybridTerminalComponent.cpp +110 -0
  60. package/nitrogen/generated/shared/c++/views/HybridTerminalComponent.hpp +113 -0
  61. package/nitrogen/generated/shared/json/TerminalConfig.json +12 -0
  62. package/package.json +97 -0
  63. package/react-native.config.js +12 -0
  64. package/shim_uniffi.xcframework/Info.plist +44 -0
  65. package/shim_uniffi.xcframework/ios-arm64/libshim_uniffi.a +0 -0
  66. package/shim_uniffi.xcframework/ios-arm64_x86_64-simulator/libshim_uniffi.a +0 -0
  67. package/src/Terminal.tsx +135 -0
  68. package/src/generated/shim_uniffi-ffi.ts +320 -0
  69. package/src/generated/shim_uniffi.ts +2527 -0
  70. package/src/index.ts +52 -0
  71. package/src/ssh.ts +239 -0
  72. package/tsconfig.json +31 -0
  73. package/ubrn.config.yaml +24 -0
@@ -0,0 +1,180 @@
1
+ // JNI bridge for the single package .so:
2
+ // 1. Render plane: HybridTerminal.kt <-> the Rust render C-ABI (attach/draw/
3
+ // resize/send_input/destroy) in libshim_uniffi.so.
4
+ // 2. Control plane install: ReactNativeTerminalModule.nativeInstallRustCrate ->
5
+ // NativeShimUniffi::registerModule (installs globalThis.NativeShimUniffi so the
6
+ // ubrn-generated TS bindings can call the uniffi scaffolding). See docs §8/§10.
7
+
8
+ #include <android/native_window_jni.h>
9
+ #include <cstddef>
10
+ #include <cstdint>
11
+ #include <jni.h>
12
+
13
+ #include <ReactCommon/CallInvoker.h>
14
+ #include <ReactCommon/CallInvokerHolder.h>
15
+ #include <fbjni/fbjni.h>
16
+ #include <jsi/jsi.h>
17
+
18
+ #include "shim_uniffi.hpp" // generated: NativeShimUniffi::registerModule
19
+ #include "ReactNativeTerminalOnLoad.hpp" // generated: registerAllNatives()
20
+
21
+ namespace jsi = facebook::jsi;
22
+ namespace jni = facebook::jni;
23
+
24
+ // ─────────────────────────── render plane (C-ABI) ───────────────────────────
25
+
26
+ extern "C" {
27
+ void *fressh_terminal_attach(void *window, const char *font_path,
28
+ const char *config_json, const char *shell_id);
29
+ void fressh_terminal_set_shell(void *handle, const char *shell_id);
30
+ void fressh_terminal_set_config(void *handle, const char *config_json);
31
+ void fressh_terminal_draw(void *handle);
32
+ void fressh_terminal_resize(void *handle);
33
+ void fressh_terminal_send_input(void *handle, const uint8_t *data, size_t len);
34
+ void fressh_terminal_destroy(void *handle);
35
+ }
36
+
37
+ // Track the ANativeWindow alongside the Rust handle so we can release the window
38
+ // reference (taken by ANativeWindow_fromSurface) on teardown.
39
+ namespace {
40
+ struct TerminalHandle {
41
+ ANativeWindow *window;
42
+ void *rust;
43
+ };
44
+
45
+ const char *orNull(JNIEnv *env, jstring s, const char **owned) {
46
+ if (s == nullptr) {
47
+ *owned = nullptr;
48
+ return nullptr;
49
+ }
50
+ *owned = env->GetStringUTFChars(s, nullptr);
51
+ return *owned;
52
+ }
53
+ } // namespace
54
+
55
+ extern "C" JNIEXPORT jlong JNICALL
56
+ Java_com_margelo_nitro_fressh_HybridTerminal_nativeAttach(
57
+ JNIEnv *env, jobject /* this */, jobject surface, jstring font_path,
58
+ jstring config_json, jstring shell_id) {
59
+ ANativeWindow *window = ANativeWindow_fromSurface(env, surface);
60
+ if (window == nullptr) {
61
+ return 0;
62
+ }
63
+
64
+ const char *fontOwned = nullptr;
65
+ const char *configOwned = nullptr;
66
+ const char *shellOwned = nullptr;
67
+ const char *font = orNull(env, font_path, &fontOwned);
68
+ const char *config = orNull(env, config_json, &configOwned);
69
+ const char *shell = orNull(env, shell_id, &shellOwned);
70
+
71
+ void *rust = fressh_terminal_attach(window, font, config, shell);
72
+
73
+ if (fontOwned) env->ReleaseStringUTFChars(font_path, fontOwned);
74
+ if (configOwned) env->ReleaseStringUTFChars(config_json, configOwned);
75
+ if (shellOwned) env->ReleaseStringUTFChars(shell_id, shellOwned);
76
+
77
+ if (rust == nullptr) {
78
+ ANativeWindow_release(window);
79
+ return 0;
80
+ }
81
+ auto *handle = new TerminalHandle{window, rust};
82
+ return reinterpret_cast<jlong>(handle);
83
+ }
84
+
85
+ extern "C" JNIEXPORT void JNICALL
86
+ Java_com_margelo_nitro_fressh_HybridTerminal_nativeSetShell(
87
+ JNIEnv *env, jobject /* this */, jlong handle, jstring shell_id) {
88
+ auto *h = reinterpret_cast<TerminalHandle *>(handle);
89
+ if (h == nullptr) return;
90
+ const char *owned = nullptr;
91
+ const char *shell = orNull(env, shell_id, &owned);
92
+ fressh_terminal_set_shell(h->rust, shell);
93
+ if (owned) env->ReleaseStringUTFChars(shell_id, owned);
94
+ }
95
+
96
+ extern "C" JNIEXPORT void JNICALL
97
+ Java_com_margelo_nitro_fressh_HybridTerminal_nativeSetConfig(
98
+ JNIEnv *env, jobject /* this */, jlong handle, jstring config_json) {
99
+ auto *h = reinterpret_cast<TerminalHandle *>(handle);
100
+ if (h == nullptr) return;
101
+ const char *owned = nullptr;
102
+ const char *config = orNull(env, config_json, &owned);
103
+ fressh_terminal_set_config(h->rust, config);
104
+ if (owned) env->ReleaseStringUTFChars(config_json, owned);
105
+ }
106
+
107
+ extern "C" JNIEXPORT void JNICALL
108
+ Java_com_margelo_nitro_fressh_HybridTerminal_nativeDraw(
109
+ JNIEnv * /* env */, jobject /* this */, jlong handle) {
110
+ auto *h = reinterpret_cast<TerminalHandle *>(handle);
111
+ if (h != nullptr) fressh_terminal_draw(h->rust);
112
+ }
113
+
114
+ extern "C" JNIEXPORT void JNICALL
115
+ Java_com_margelo_nitro_fressh_HybridTerminal_nativeResize(
116
+ JNIEnv * /* env */, jobject /* this */, jlong handle) {
117
+ auto *h = reinterpret_cast<TerminalHandle *>(handle);
118
+ if (h != nullptr) fressh_terminal_resize(h->rust);
119
+ }
120
+
121
+ extern "C" JNIEXPORT void JNICALL
122
+ Java_com_margelo_nitro_fressh_HybridTerminal_nativeSendInput(
123
+ JNIEnv *env, jobject /* this */, jlong handle, jbyteArray data) {
124
+ auto *h = reinterpret_cast<TerminalHandle *>(handle);
125
+ if (h == nullptr || data == nullptr) return;
126
+ const jsize len = env->GetArrayLength(data);
127
+ if (len <= 0) return;
128
+ jbyte *bytes = env->GetByteArrayElements(data, nullptr);
129
+ fressh_terminal_send_input(h->rust, reinterpret_cast<const uint8_t *>(bytes),
130
+ static_cast<size_t>(len));
131
+ env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
132
+ }
133
+
134
+ extern "C" JNIEXPORT void JNICALL
135
+ Java_com_margelo_nitro_fressh_HybridTerminal_nativeDestroy(
136
+ JNIEnv * /* env */, jobject /* this */, jlong handle) {
137
+ auto *h = reinterpret_cast<TerminalHandle *>(handle);
138
+ if (h != nullptr) {
139
+ fressh_terminal_destroy(h->rust);
140
+ ANativeWindow_release(h->window);
141
+ delete h;
142
+ }
143
+ }
144
+
145
+ // ─────────────────────────── control plane install ───────────────────────────
146
+
147
+ extern "C" JNIEXPORT jboolean JNICALL
148
+ Java_com_margelo_nitro_fressh_ReactNativeTerminalModule_nativeInstallRustCrate(
149
+ JNIEnv * /* env */, jobject /* this */, jlong jsiRuntimePtr,
150
+ jobject callInvokerHolderJavaObj) {
151
+ if (jsiRuntimePtr == 0 || callInvokerHolderJavaObj == nullptr) {
152
+ return JNI_FALSE;
153
+ }
154
+ // RN 0.85 removed CallInvokerHolderImpl.mHybridData; reach the C++ instance via
155
+ // fbjni cthis() instead of the (gone) field.
156
+ using JCallInvokerHolder = facebook::react::CallInvokerHolder;
157
+ auto holderLocal = jni::make_local(callInvokerHolderJavaObj);
158
+ auto holderRef =
159
+ jni::static_ref_cast<JCallInvokerHolder::javaobject>(holderLocal);
160
+ auto *holderCxx = holderRef->cthis();
161
+ std::shared_ptr<facebook::react::CallInvoker> jsCallInvoker =
162
+ holderCxx->getCallInvoker();
163
+
164
+ auto *runtime = reinterpret_cast<jsi::Runtime *>(jsiRuntimePtr);
165
+ NativeShimUniffi::registerModule(*runtime, jsCallInvoker);
166
+ return JNI_TRUE;
167
+ }
168
+
169
+ // ─────────────────────────── Nitro view registration ───────────────────────────
170
+
171
+ // Nitro registers the "Terminal" Fabric component descriptor (plus the HybridObject
172
+ // constructor and the fbjni natives) in registerAllNatives(). It MUST run from this
173
+ // library's JNI_OnLoad — without it, Fabric never learns about the "Terminal"
174
+ // component and falls back to legacy ViewManager interop, which creates the view but
175
+ // silently drops every prop (so `shellId` never reaches HybridTerminal and the
176
+ // renderer draws an unbound/black frame). See ReactNativeTerminalOnLoad.hpp.
177
+ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /* reserved */) {
178
+ return facebook::jni::initialize(
179
+ vm, [] { margelo::nitro::fressh::registerAllNatives(); });
180
+ }
@@ -0,0 +1,146 @@
1
+ package com.margelo.nitro.fressh
2
+
3
+ import android.view.Choreographer
4
+ import android.view.Surface
5
+ import android.view.SurfaceHolder
6
+ import android.view.SurfaceView
7
+ import android.view.View
8
+ import androidx.annotation.Keep
9
+ import com.facebook.proguard.annotations.DoNotStrip
10
+ import com.facebook.react.uimanager.ThemedReactContext
11
+
12
+ /**
13
+ * Native terminal view (Nitro HybridView, the render plane §10). Owns a
14
+ * [SurfaceView]; on surface creation it hands the `ANativeWindow` + the bound
15
+ * `shellId` to the Rust render C-ABI (via JNI) and drives a Choreographer (vsync)
16
+ * loop that draws the shell's durable `Term` from fressh-core's registry. The
17
+ * byte stream never reaches JS. See docs §5/§10.
18
+ */
19
+ @Keep
20
+ @DoNotStrip
21
+ class HybridTerminal(
22
+ val context: ThemedReactContext,
23
+ ) : HybridTerminalSpec() {
24
+ // Plain SurfaceView: the buffer auto-tracks the view bounds. Keeping the grid in
25
+ // lockstep with the on-screen size when the keyboard opens/closes is handled on the
26
+ // Rust side, which polls the *settled* surface size from the draw loop (eglQuerySurface
27
+ // lags the new geometry by a frame, so a one-shot read in surfaceChanged is unreliable
28
+ // — esp. on GROW). The JS side (terminal flex:1 + the toolbar's keyboard-height-driven
29
+ // marginBottom) is what actually resizes this view in both directions. See
30
+ // docs/projects/complete/renderer-mismatched-selection-cutoff-scrollback.md.
31
+ private val surfaceView = SurfaceView(context)
32
+
33
+ /** Opaque pointer to the native render handle (0 = none). */
34
+ private var nativeHandle: Long = 0L
35
+ private var frameCallback: Choreographer.FrameCallback? = null
36
+
37
+ override val view: View = surfaceView
38
+
39
+ // Prop: bundled monospace font file path (no fontconfig on mobile, §6).
40
+ override var fontPath: String = ""
41
+
42
+ // Prop: render config as a JSON blob (physical px), assembled by the JS
43
+ // <Terminal config={...}> wrapper. Carries color scheme, padding, cursor style,
44
+ // bold-is-bright, font size. Live changes reflow the shell — a bonus over
45
+ // desktop alacritty's restart-to-apply. We just forward the string; the renderer
46
+ // parses + diffs it.
47
+ override var configJson: String? = null
48
+ set(value) {
49
+ field = value
50
+ if (nativeHandle != 0L) {
51
+ nativeSetConfig(nativeHandle, value)
52
+ }
53
+ }
54
+
55
+ // Prop: the durable shell to render. Rebinds the native view on change so the
56
+ // same surface can follow a (re)started shell without a remount.
57
+ override var shellId: String? = null
58
+ set(value) {
59
+ field = value
60
+ if (nativeHandle != 0L) {
61
+ nativeSetShell(nativeHandle, value)
62
+ }
63
+ }
64
+
65
+ init {
66
+ surfaceView.holder.addCallback(
67
+ object : SurfaceHolder.Callback {
68
+ override fun surfaceCreated(holder: SurfaceHolder) {
69
+ nativeHandle = nativeAttach(holder.surface, resolveFontPath(), configJson, shellId)
70
+ if (nativeHandle != 0L) startRenderLoop()
71
+ }
72
+
73
+ override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
74
+ if (nativeHandle != 0L) nativeResize(nativeHandle)
75
+ }
76
+
77
+ override fun surfaceDestroyed(holder: SurfaceHolder) {
78
+ stopRenderLoop()
79
+ if (nativeHandle != 0L) {
80
+ nativeDestroy(nativeHandle)
81
+ nativeHandle = 0L
82
+ }
83
+ }
84
+ },
85
+ )
86
+ }
87
+
88
+ /**
89
+ * The native renderer needs a font *file* path. If RN didn't supply one, fall
90
+ * back to the bundled DejaVu Sans Mono asset, extracted to filesDir once.
91
+ */
92
+ private fun resolveFontPath(): String {
93
+ if (fontPath.isNotEmpty()) return fontPath
94
+ val out = java.io.File(context.filesDir, "DejaVuSansMono.ttf")
95
+ if (!out.exists()) {
96
+ context.assets.open("fonts/DejaVuSansMono.ttf").use { input ->
97
+ out.outputStream().use { output -> input.copyTo(output) }
98
+ }
99
+ }
100
+ return out.absolutePath
101
+ }
102
+
103
+ private fun startRenderLoop() {
104
+ val callback =
105
+ object : Choreographer.FrameCallback {
106
+ override fun doFrame(frameTimeNanos: Long) {
107
+ if (nativeHandle == 0L) return
108
+ nativeDraw(nativeHandle)
109
+ Choreographer.getInstance().postFrameCallback(this)
110
+ }
111
+ }
112
+ frameCallback = callback
113
+ Choreographer.getInstance().postFrameCallback(callback)
114
+ }
115
+
116
+ private fun stopRenderLoop() {
117
+ frameCallback?.let { Choreographer.getInstance().removeFrameCallback(it) }
118
+ frameCallback = null
119
+ }
120
+
121
+ // JNI bridge -> Rust render C-ABI (see android/src/main/cpp/cpp-adapter.cpp).
122
+ private external fun nativeAttach(
123
+ surface: Surface,
124
+ fontPath: String,
125
+ configJson: String?,
126
+ shellId: String?,
127
+ ): Long
128
+
129
+ private external fun nativeSetShell(handle: Long, shellId: String?)
130
+
131
+ private external fun nativeSetConfig(handle: Long, configJson: String?)
132
+
133
+ private external fun nativeDraw(handle: Long)
134
+
135
+ private external fun nativeResize(handle: Long)
136
+
137
+ private external fun nativeSendInput(handle: Long, data: ByteArray)
138
+
139
+ private external fun nativeDestroy(handle: Long)
140
+
141
+ companion object {
142
+ init {
143
+ System.loadLibrary("ReactNativeTerminal")
144
+ }
145
+ }
146
+ }
@@ -0,0 +1,43 @@
1
+ package com.margelo.nitro.fressh
2
+
3
+ import com.facebook.react.bridge.ReactApplicationContext
4
+ import com.facebook.react.bridge.ReactContextBaseJavaModule
5
+ import com.facebook.react.bridge.ReactMethod
6
+ import com.facebook.react.module.annotations.ReactModule
7
+ import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder
8
+
9
+ /**
10
+ * Installs the uniffi control-plane JSI bindings (the `globalThis.NativeShimUniffi`
11
+ * host object the ubrn-generated TS calls). JS invokes [installRustCrate] once at
12
+ * startup (see `src/ssh.ts`), which hands the JSI runtime pointer + the
13
+ * `CallInvokerHolder` to native; `nativeInstallRustCrate` (cpp-adapter.cpp) reaches
14
+ * the C++ CallInvoker via fbjni `cthis()` (RN 0.85 dropped the old field) and calls
15
+ * `NativeShimUniffi::registerModule`. Lives in the SAME .so as the Nitro render
16
+ * plane so both share one `fressh-core` registry. (§8/§10)
17
+ */
18
+ @ReactModule(name = ReactNativeTerminalModule.NAME)
19
+ class ReactNativeTerminalModule(
20
+ private val reactContext: ReactApplicationContext,
21
+ ) : ReactContextBaseJavaModule(reactContext) {
22
+ override fun getName() = NAME
23
+
24
+ @ReactMethod(isBlockingSynchronousMethod = true)
25
+ fun installRustCrate(): Boolean {
26
+ val runtimePointer = reactContext.javaScriptContextHolder?.get() ?: return false
27
+ val callInvokerHolder = reactContext.jsCallInvokerHolder ?: return false
28
+ return nativeInstallRustCrate(runtimePointer, callInvokerHolder)
29
+ }
30
+
31
+ private external fun nativeInstallRustCrate(
32
+ runtimePointer: Long,
33
+ callInvokerHolder: CallInvokerHolder,
34
+ ): Boolean
35
+
36
+ companion object {
37
+ const val NAME = "ReactNativeTerminalUniffi"
38
+
39
+ init {
40
+ System.loadLibrary("ReactNativeTerminal")
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,32 @@
1
+ package com.margelo.nitro.fressh
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
+ import com.margelo.nitro.fressh.views.HybridTerminalManager
8
+
9
+ /**
10
+ * ReactPackage for the terminal package. Three jobs:
11
+ * 1. Its mere presence lets React Native autolinking detect this package and
12
+ * build/link its `android/build.gradle` (and thus libReactNativeTerminal.so).
13
+ * 2. Registers the "Terminal" Nitro HybridView's generated ViewManager so Fabric
14
+ * can resolve <Terminal/> (else: "Can't find ViewManager 'Terminal'").
15
+ * 3. Registers [ReactNativeTerminalModule], whose `installRustCrate()` installs
16
+ * the uniffi control-plane JSI bindings (globalThis.NativeShimUniffi).
17
+ * The Nitro native C++ side (HybridObjects) is registered via [ReactNativeTerminalOnLoad]
18
+ * in the static initializer below.
19
+ */
20
+ class ReactNativeTerminalPackage : ReactPackage {
21
+ override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> =
22
+ listOf(ReactNativeTerminalModule(reactContext))
23
+
24
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> =
25
+ listOf(HybridTerminalManager())
26
+
27
+ companion object {
28
+ init {
29
+ ReactNativeTerminalOnLoad.initializeNative()
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,12 @@
1
+ export default {
2
+ overrides: [
3
+ {
4
+ exclude: /\/node_modules\//,
5
+ presets: ['module:react-native-builder-bob/babel-preset'],
6
+ },
7
+ {
8
+ include: /\/node_modules\//,
9
+ presets: ['module:@react-native/babel-preset'],
10
+ },
11
+ ],
12
+ };
package/cpp/README.md ADDED
@@ -0,0 +1,14 @@
1
+ # `cpp/` — native umbrella glue
2
+
3
+ Hand-authored C++ that ties the package's one `.so`/framework together (§8):
4
+
5
+ - the umbrella adapter that registers the TurboModule + Nitro view
6
+ - the Nitro view's C++ that calls **fressh-core's C-ABI** for the render plane
7
+ (`attach(shellId, surface)`, `render_frame`, `send_input`, `detach`)
8
+
9
+ Generated C++ (regenerated, gitignored) lands in `cpp/generated/` (ubrn shim)
10
+ and `nitrogen/generated/` (Nitro view). This dir holds only the hand-written
11
+ adapter sources.
12
+
13
+ > Scaffold stub — empty until the umbrella build is wired (see
14
+ > `../android/CMakeLists.txt`).