mirror of
https://github.com/EthanShoeDev/fressh.git
synced 2026-01-11 06:12:51 +00:00
Merge commit '8cb7603b81735909e54f9dddda69d202fa5059e9' into russh
This commit is contained in:
@@ -60,10 +60,18 @@ const config: ExpoConfig = {
|
||||
// https://github.com/dylankenneally/react-native-ssh-sftp/issues/20#issuecomment-3286693445
|
||||
// ../../docs/ios-sim-not-working.md (Update 1)
|
||||
extraPods: [
|
||||
{ name: 'CSSH-Binary', podspec: 'https://gist.githubusercontent.com/EthanShoeDev/1ab212949007d7aeabfeb199b7b9e951/raw/8602ec55efdf8c620dbbae93cd54023e2a36a8b9/CSSH-Binary.podspec' },
|
||||
{ name: 'NMSSH', git: 'https://github.com/EthanShoeDev/NMSSH.git', branch: 'master' },
|
||||
{
|
||||
name: 'CSSH-Binary',
|
||||
podspec:
|
||||
'https://gist.githubusercontent.com/EthanShoeDev/1ab212949007d7aeabfeb199b7b9e951/raw/8602ec55efdf8c620dbbae93cd54023e2a36a8b9/CSSH-Binary.podspec',
|
||||
},
|
||||
{
|
||||
name: 'NMSSH',
|
||||
git: 'https://github.com/EthanShoeDev/NMSSH.git',
|
||||
branch: 'master',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
|
||||
@@ -35,21 +35,21 @@
|
||||
"@react-navigation/native": "^7.1.8",
|
||||
"@tanstack/react-form": "^1.19.5",
|
||||
"@tanstack/react-query": "^5.87.1",
|
||||
"expo": "54.0.3",
|
||||
"expo": "54.0.6",
|
||||
"expo-build-properties": "~1.0.8",
|
||||
"expo-clipboard": "~8.0.7",
|
||||
"expo-constants": "~18.0.8",
|
||||
"expo-crypto": "~15.0.7",
|
||||
"expo-dev-client": "~6.0.12",
|
||||
"expo-document-picker": "~14.0.7",
|
||||
"expo-file-system": "~19.0.13",
|
||||
"expo-file-system": "~19.0.14",
|
||||
"expo-font": "~14.0.8",
|
||||
"expo-haptics": "~15.0.7",
|
||||
"expo-image": "~3.0.8",
|
||||
"expo-linking": "~8.0.8",
|
||||
"expo-router": "6.0.1",
|
||||
"expo-router": "6.0.3",
|
||||
"expo-secure-store": "~15.0.7",
|
||||
"expo-splash-screen": "~31.0.9",
|
||||
"expo-splash-screen": "~31.0.10",
|
||||
"expo-status-bar": "~3.0.8",
|
||||
"expo-symbols": "~1.0.7",
|
||||
"expo-system-ui": "~6.0.7",
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
# React Native SSH — iOS simulator limitations & paths forward
|
||||
|
||||
*Last updated: 2025-09-12*
|
||||
_Last updated: 2025-09-12_
|
||||
|
||||
## TL;DR
|
||||
|
||||
* Our current stack (`react-native-ssh-sftp` → `NMSSH (aanah0 fork)` → prebuilt OpenSSL/libssh2) **fails on the iOS Simulator** because the vendored native libraries are compiled for **iOS device** only (platform: `iphoneos`), not **iOS Simulator** (platform: `iphonesimulator`).
|
||||
* The proper modern fix is to use **XCFrameworks** that include **both** device and simulator slices, and have NMSSH link against those instead of raw static `.a` libraries.
|
||||
* We have two main paths:
|
||||
|
||||
1. Keep using the existing RN package, but swap NMSSH’s underlying crypto/SSH libs to an **XCFramework** (e.g., from `DimaRU/Libssh2Prebuild`), via a tiny CocoaPods change.
|
||||
2. Build our **own RN native module** (TurboModule/JSI) that links **libssh2** and **OpenSSL** directly (using or adapting the Libssh2Prebuild scripts), fixing iOS Simulator support and also addressing Android reliability issues (like double “disconnect” callbacks).
|
||||
- Our current stack (`react-native-ssh-sftp` → `NMSSH (aanah0 fork)` → prebuilt
|
||||
OpenSSL/libssh2) **fails on the iOS Simulator** because the vendored native
|
||||
libraries are compiled for **iOS device** only (platform: `iphoneos`), not
|
||||
**iOS Simulator** (platform: `iphonesimulator`).
|
||||
- The proper modern fix is to use **XCFrameworks** that include **both** device
|
||||
and simulator slices, and have NMSSH link against those instead of raw static
|
||||
`.a` libraries.
|
||||
- We have two main paths:
|
||||
1. Keep using the existing RN package, but swap NMSSH’s underlying crypto/SSH
|
||||
libs to an **XCFramework** (e.g., from `DimaRU/Libssh2Prebuild`), via a
|
||||
tiny CocoaPods change.
|
||||
2. Build our **own RN native module** (TurboModule/JSI) that links **libssh2**
|
||||
and **OpenSSL** directly (using or adapting the Libssh2Prebuild scripts),
|
||||
fixing iOS Simulator support and also addressing Android reliability issues
|
||||
(like double “disconnect” callbacks).
|
||||
|
||||
---
|
||||
|
||||
@@ -17,42 +26,54 @@
|
||||
|
||||
### Stack
|
||||
|
||||
* App → `react-native-ssh-sftp`
|
||||
* iOS native → `NMSSH` (via the `aanah0/NMSSH` fork for a newer libssh2 baseline)
|
||||
* `NMSSH` bundles **precompiled OpenSSL + libssh2** as static libraries.
|
||||
- App → `react-native-ssh-sftp`
|
||||
- iOS native → `NMSSH` (via the `aanah0/NMSSH` fork for a newer libssh2
|
||||
baseline)
|
||||
- `NMSSH` bundles **precompiled OpenSSL + libssh2** as static libraries.
|
||||
|
||||
### Why iOS Simulator builds fail
|
||||
|
||||
* Xcode treats **device** and **simulator** as **different platforms**. Since Apple Silicon, both may be `arm64`, but they are **not interchangeable**:
|
||||
- Xcode treats **device** and **simulator** as **different platforms**. Since
|
||||
Apple Silicon, both may be `arm64`, but they are **not interchangeable**:
|
||||
- Device slice: `ios-arm64` (platform: `iphoneos`)
|
||||
- Simulator slices: `ios-arm64` and/or `ios-x86_64` (platform:
|
||||
`iphonesimulator`)
|
||||
|
||||
* Device slice: `ios-arm64` (platform: `iphoneos`)
|
||||
* Simulator slices: `ios-arm64` and/or `ios-x86_64` (platform: `iphonesimulator`)
|
||||
* NMSSH’s vendored libs are device-only (`iphoneos`). When the Simulator build links those, the linker throws:
|
||||
- NMSSH’s vendored libs are device-only (`iphoneos`). When the Simulator build
|
||||
links those, the linker throws:
|
||||
|
||||
```
|
||||
ld: building for 'iOS-simulator', but linking in object file .../libcrypto.a[arm64] built for 'iOS'
|
||||
```
|
||||
* **XCFrameworks** solve this: they are a bundle containing the correct slices for both platforms. Xcode picks the proper slice automatically.
|
||||
|
||||
> Temporary hack (not recommended): exclude `arm64` for the simulator (`EXCLUDED_ARCHS[sdk=iphonesimulator*]=arm64`) to force an x86\_64 sim under Rosetta. This “works” but loses native-sim performance and is brittle.
|
||||
- **XCFrameworks** solve this: they are a bundle containing the correct slices
|
||||
for both platforms. Xcode picks the proper slice automatically.
|
||||
|
||||
> Temporary hack (not recommended): exclude `arm64` for the simulator
|
||||
> (`EXCLUDED_ARCHS[sdk=iphonesimulator*]=arm64`) to force an x86_64 sim under
|
||||
> Rosetta. This “works” but loses native-sim performance and is brittle.
|
||||
|
||||
---
|
||||
|
||||
## Path 1 — Keep current RN package; replace NMSSH’s vendored libs with an XCFramework
|
||||
|
||||
**Goal:** Do *not* change `react-native-ssh-sftp` or the NMSSH **API**. Only change how NMSSH links to OpenSSL/libssh2.
|
||||
**Goal:** Do _not_ change `react-native-ssh-sftp` or the NMSSH **API**. Only
|
||||
change how NMSSH links to OpenSSL/libssh2.
|
||||
|
||||
### What we’ll use
|
||||
|
||||
* **`DimaRU/Libssh2Prebuild`**: ships a ready-made **XCFramework** (“CSSH”) that bundles **libssh2 + OpenSSL** with both **device** and **simulator** slices.
|
||||
* CocoaPods can consume XCFrameworks via a **binary pod** (`vendored_frameworks`), but Libssh2Prebuild is published for **SwiftPM**. So we add a tiny **`CSSH-Binary` podspec** that points to its zipped XCFramework.
|
||||
- **`DimaRU/Libssh2Prebuild`**: ships a ready-made **XCFramework** (“CSSH”) that
|
||||
bundles **libssh2 + OpenSSL** with both **device** and **simulator** slices.
|
||||
- CocoaPods can consume XCFrameworks via a **binary pod**
|
||||
(`vendored_frameworks`), but Libssh2Prebuild is published for **SwiftPM**. So
|
||||
we add a tiny **`CSSH-Binary` podspec** that points to its zipped XCFramework.
|
||||
|
||||
### Minimal changes
|
||||
|
||||
1. **Fork NMSSH** (from `aanah0/NMSSH`) and edit **`NMSSH.podspec`**
|
||||
|
||||
* **Remove** the vendored static libs (the `.a` files).
|
||||
* **Add** a dependency on `CSSH-Binary` (our binary pod that vends `CSSH.xcframework`).
|
||||
- **Remove** the vendored static libs (the `.a` files).
|
||||
- **Add** a dependency on `CSSH-Binary` (our binary pod that vends
|
||||
`CSSH.xcframework`).
|
||||
|
||||
**Podspec diff (conceptual):**
|
||||
|
||||
@@ -89,30 +110,40 @@
|
||||
end
|
||||
```
|
||||
|
||||
* You can host the zip yourself if you want deterministic supply (recommended for CI).
|
||||
* Ensure license attributions (OpenSSL 3.x: Apache-2.0; libssh2: BSD-3-Clause) are included in our OSS notices.
|
||||
- You can host the zip yourself if you want deterministic supply (recommended
|
||||
for CI).
|
||||
- Ensure license attributions (OpenSSL 3.x: Apache-2.0; libssh2:
|
||||
BSD-3-Clause) are included in our OSS notices.
|
||||
|
||||
3. **Wire via Expo** (`expo-build-properties`) in `app.config.ts`
|
||||
|
||||
```ts
|
||||
[
|
||||
'expo-build-properties',
|
||||
{
|
||||
ios: {
|
||||
extraPods: [
|
||||
// Binary pod that vends the XCFramework
|
||||
{ name: 'CSSH-Binary', podspec: 'https://raw.githubusercontent.com/your-org/cssh-binary/main/CSSH-Binary.podspec' },
|
||||
// Our NMSSH fork that depends on CSSH-Binary
|
||||
{ name: 'NMSSH', git: 'https://github.com/your-org/NMSSH.git', branch: 'cssh-xcframework' },
|
||||
],
|
||||
},
|
||||
android: {
|
||||
packagingOptions: {
|
||||
pickFirst: ['META-INF/versions/9/OSGI-INF/MANIFEST.MF'],
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
'expo-build-properties',
|
||||
{
|
||||
ios: {
|
||||
extraPods: [
|
||||
// Binary pod that vends the XCFramework
|
||||
{
|
||||
name: 'CSSH-Binary',
|
||||
podspec:
|
||||
'https://raw.githubusercontent.com/your-org/cssh-binary/main/CSSH-Binary.podspec',
|
||||
},
|
||||
// Our NMSSH fork that depends on CSSH-Binary
|
||||
{
|
||||
name: 'NMSSH',
|
||||
git: 'https://github.com/your-org/NMSSH.git',
|
||||
branch: 'cssh-xcframework',
|
||||
},
|
||||
],
|
||||
},
|
||||
android: {
|
||||
packagingOptions: {
|
||||
pickFirst: ['META-INF/versions/9/OSGI-INF/MANIFEST.MF'],
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
4. **Rebuild**
|
||||
@@ -125,88 +156,109 @@
|
||||
|
||||
**Pros**
|
||||
|
||||
* Small surface area; we keep the RN package API intact.
|
||||
* Correct, future-proof device/simulator packaging via XCFrameworks.
|
||||
* Easy to maintain once the podspecs are set.
|
||||
- Small surface area; we keep the RN package API intact.
|
||||
- Correct, future-proof device/simulator packaging via XCFrameworks.
|
||||
- Easy to maintain once the podspecs are set.
|
||||
|
||||
**Cons/Risks**
|
||||
|
||||
* We maintain a **fork of NMSSH** (podspec only).
|
||||
* Potential conflicts with tools like **Flipper** if they also touch OpenSSL (rare; we can disable Flipper if needed).
|
||||
* We rely on Libssh2Prebuild versions/tags (or build our own artifacts using their scripts).
|
||||
- We maintain a **fork of NMSSH** (podspec only).
|
||||
- Potential conflicts with tools like **Flipper** if they also touch OpenSSL
|
||||
(rare; we can disable Flipper if needed).
|
||||
- We rely on Libssh2Prebuild versions/tags (or build our own artifacts using
|
||||
their scripts).
|
||||
|
||||
---
|
||||
|
||||
## Path 2 — Build our own RN module (TurboModule/JSI) with libssh2/OpenSSL
|
||||
|
||||
**Goal:** Replace `react-native-ssh-sftp` + NMSSH with a **modern RN Native Module** that links libssh2 directly and ships correct device/simulator binaries out of the box.
|
||||
**Goal:** Replace `react-native-ssh-sftp` + NMSSH with a **modern RN Native
|
||||
Module** that links libssh2 directly and ships correct device/simulator binaries
|
||||
out of the box.
|
||||
|
||||
### Why consider this
|
||||
|
||||
* Full control over the native surface (events, error handling, cancellation, reconnects).
|
||||
* Fix Android reliability issues we’ve observed (e.g., “disconnect” callback firing multiple times, causing dev crashes).
|
||||
* Avoid legacy Objective-C wrapper constraints; use **TurboModules/JSI**.
|
||||
- Full control over the native surface (events, error handling, cancellation,
|
||||
reconnects).
|
||||
- Fix Android reliability issues we’ve observed (e.g., “disconnect” callback
|
||||
firing multiple times, causing dev crashes).
|
||||
- Avoid legacy Objective-C wrapper constraints; use **TurboModules/JSI**.
|
||||
|
||||
### High-level plan
|
||||
|
||||
**iOS**
|
||||
|
||||
* Use (or adapt) **Libssh2Prebuild build scripts** to produce our own **`libssh2.xcframework`** and **`OpenSSL.xcframework`** (or one combined framework).
|
||||
* Publish them as a **binary CocoaPod** (like `CSSH-Binary`) *or* vendor the XCFrameworks in our module pod.
|
||||
* Write a thin Obj-C++/C++ wrapper exposing the SSH API needed by JS (connect/auth/exec/sftp/streaming).
|
||||
* Export via **TurboModule** (codegen) or **JSI** (C++), and provide a typed TS API in the RN package.
|
||||
- Use (or adapt) **Libssh2Prebuild build scripts** to produce our own
|
||||
**`libssh2.xcframework`** and **`OpenSSL.xcframework`** (or one combined
|
||||
framework).
|
||||
- Publish them as a **binary CocoaPod** (like `CSSH-Binary`) _or_ vendor the
|
||||
XCFrameworks in our module pod.
|
||||
- Write a thin Obj-C++/C++ wrapper exposing the SSH API needed by JS
|
||||
(connect/auth/exec/sftp/streaming).
|
||||
- Export via **TurboModule** (codegen) or **JSI** (C++), and provide a typed TS
|
||||
API in the RN package.
|
||||
|
||||
**Android**
|
||||
|
||||
* Build **libssh2** against **OpenSSL** (or MbedTLS) with the **NDK**.
|
||||
* Package `.so` libs per ABI (`arm64-v8a`, `x86_64`, etc.).
|
||||
* Implement JNI layer with strict **once-only** callbacks (disconnect must be idempotent), and make the public JS API promise/observable based.
|
||||
* Add tests that assert no multiple “disconnect” emissions.
|
||||
- Build **libssh2** against **OpenSSL** (or MbedTLS) with the **NDK**.
|
||||
- Package `.so` libs per ABI (`arm64-v8a`, `x86_64`, etc.).
|
||||
- Implement JNI layer with strict **once-only** callbacks (disconnect must be
|
||||
idempotent), and make the public JS API promise/observable based.
|
||||
- Add tests that assert no multiple “disconnect” emissions.
|
||||
|
||||
**Common**
|
||||
|
||||
* Define a **stable JS API**:
|
||||
- Define a **stable JS API**:
|
||||
- Connection lifecycle (`connect`, `ready`, `disconnect`),
|
||||
- Auth variants (password, key, agent if supported),
|
||||
- Exec/PTY streaming,
|
||||
- SFTP (get/put/mkdir/list/stat),
|
||||
- Structured errors (error codes, host key checks, timeouts),
|
||||
- Events (`onData`, `onExit`, `onError`, `onDisconnect`).
|
||||
|
||||
* Connection lifecycle (`connect`, `ready`, `disconnect`),
|
||||
* Auth variants (password, key, agent if supported),
|
||||
* Exec/PTY streaming,
|
||||
* SFTP (get/put/mkdir/list/stat),
|
||||
* Structured errors (error codes, host key checks, timeouts),
|
||||
* Events (`onData`, `onExit`, `onError`, `onDisconnect`).
|
||||
* **Testing/CI**: Simulated hosts (Docker) for integration tests; E2E with detox where feasible; CI matrix includes iOS Simulator and Android emulators.
|
||||
- **Testing/CI**: Simulated hosts (Docker) for integration tests; E2E with detox
|
||||
where feasible; CI matrix includes iOS Simulator and Android emulators.
|
||||
|
||||
**Pros**
|
||||
|
||||
* Clean slate, better DX, fewer legacy constraints.
|
||||
* We can ensure **simulator** support is first-class.
|
||||
* Fixes Android issues definitively.
|
||||
- Clean slate, better DX, fewer legacy constraints.
|
||||
- We can ensure **simulator** support is first-class.
|
||||
- Fixes Android issues definitively.
|
||||
|
||||
**Cons**
|
||||
|
||||
* More initial engineering time.
|
||||
* We own native maintenance across platforms.
|
||||
- More initial engineering time.
|
||||
- We own native maintenance across platforms.
|
||||
|
||||
---
|
||||
|
||||
## Known Android issue in current package
|
||||
|
||||
We’ve observed that **disconnect** can trigger the callback **more than once**, which crashes the app in dev (double resolve/reject or repeated event emission). If we keep the current package for now:
|
||||
We’ve observed that **disconnect** can trigger the callback **more than once**,
|
||||
which crashes the app in dev (double resolve/reject or repeated event emission).
|
||||
If we keep the current package for now:
|
||||
|
||||
* Add a JS-side **guard** to make `disconnect()` idempotent (ignore subsequent calls/notifications after the first).
|
||||
* If we fork, fix the native layer so it emits exactly once and cleans up listeners predictably.
|
||||
- Add a JS-side **guard** to make `disconnect()` idempotent (ignore subsequent
|
||||
calls/notifications after the first).
|
||||
- If we fork, fix the native layer so it emits exactly once and cleans up
|
||||
listeners predictably.
|
||||
|
||||
(If we pursue **Path 2**, we’ll design the native layer so all callbacks/promises are strictly single-shot and lifecycle-scoped.)
|
||||
(If we pursue **Path 2**, we’ll design the native layer so all
|
||||
callbacks/promises are strictly single-shot and lifecycle-scoped.)
|
||||
|
||||
---
|
||||
|
||||
## Recommendation
|
||||
|
||||
* **Short term:** Implement **Path 1**. It’s the smallest change to unblock Simulator builds:
|
||||
- **Short term:** Implement **Path 1**. It’s the smallest change to unblock
|
||||
Simulator builds:
|
||||
- Add a `CSSH-Binary` binary pod (vend `CSSH.xcframework`).
|
||||
- Fork NMSSH podspec to depend on it.
|
||||
- Wire both via `expo-build-properties` `ios.extraPods`.
|
||||
|
||||
* Add a `CSSH-Binary` binary pod (vend `CSSH.xcframework`).
|
||||
* Fork NMSSH podspec to depend on it.
|
||||
* Wire both via `expo-build-properties` `ios.extraPods`.
|
||||
* **Medium term:** Plan **Path 2** to remove legacy NMSSH constraints and resolve Android issues thoroughly using a Nitro/TurboModule with direct libssh2 bindings.
|
||||
- **Medium term:** Plan **Path 2** to remove legacy NMSSH constraints and
|
||||
resolve Android issues thoroughly using a Nitro/TurboModule with direct
|
||||
libssh2 bindings.
|
||||
|
||||
---
|
||||
|
||||
@@ -245,37 +297,46 @@ end
|
||||
|
||||
```ts
|
||||
plugins: [
|
||||
// ...
|
||||
[
|
||||
'expo-build-properties',
|
||||
{
|
||||
ios: {
|
||||
extraPods: [
|
||||
{ name: 'CSSH-Binary', podspec: 'https://raw.githubusercontent.com/your-org/cssh-binary/main/CSSH-Binary.podspec' },
|
||||
{ name: 'NMSSH', git: 'https://github.com/your-org/NMSSH.git', branch: 'cssh-xcframework' },
|
||||
],
|
||||
},
|
||||
android: {
|
||||
packagingOptions: {
|
||||
pickFirst: ['META-INF/versions/9/OSGI-INF/MANIFEST.MF'],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
]
|
||||
// ...
|
||||
[
|
||||
'expo-build-properties',
|
||||
{
|
||||
ios: {
|
||||
extraPods: [
|
||||
{
|
||||
name: 'CSSH-Binary',
|
||||
podspec:
|
||||
'https://raw.githubusercontent.com/your-org/cssh-binary/main/CSSH-Binary.podspec',
|
||||
},
|
||||
{
|
||||
name: 'NMSSH',
|
||||
git: 'https://github.com/your-org/NMSSH.git',
|
||||
branch: 'cssh-xcframework',
|
||||
},
|
||||
],
|
||||
},
|
||||
android: {
|
||||
packagingOptions: {
|
||||
pickFirst: ['META-INF/versions/9/OSGI-INF/MANIFEST.MF'],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
];
|
||||
```
|
||||
|
||||
### D. Build/Release notes
|
||||
|
||||
* **Rebuild steps**
|
||||
- **Rebuild steps**
|
||||
|
||||
```bash
|
||||
npx expo prebuild --platform ios --clean
|
||||
npx pod-install
|
||||
npx expo run:ios
|
||||
```
|
||||
* **Licenses**: Include OpenSSL and libssh2 license texts in our OSS notice.
|
||||
* **Flipper**: If linking conflicts appear, disable Flipper in iOS debug builds.
|
||||
|
||||
- **Licenses**: Include OpenSSL and libssh2 license texts in our OSS notice.
|
||||
- **Flipper**: If linking conflicts appear, disable Flipper in iOS debug builds.
|
||||
|
||||
### E. Temporary simulator workaround (not recommended long-term)
|
||||
|
||||
@@ -285,16 +346,17 @@ In both the app target and Pods project:
|
||||
EXCLUDED_ARCHS[sdk=iphonesimulator*] = arm64
|
||||
```
|
||||
|
||||
This forces an x86\_64 Simulator under Rosetta, avoiding the immediate link error but losing native-sim performance.
|
||||
This forces an x86_64 Simulator under Rosetta, avoiding the immediate link error
|
||||
but losing native-sim performance.
|
||||
|
||||
---
|
||||
|
||||
**Decision log**
|
||||
|
||||
* ✅ Adopt Path 1 now (XCFramework via CSSH + NMSSH podspec tweak).
|
||||
* 🕒 Plan Path 2 (custom RN module) to address Android bugs and own the full stack.
|
||||
|
||||
- ✅ Adopt Path 1 now (XCFramework via CSSH + NMSSH podspec tweak).
|
||||
- 🕒 Plan Path 2 (custom RN module) to address Android bugs and own the full
|
||||
stack.
|
||||
|
||||
# Updates
|
||||
|
||||
- 1. Implemented option 1. Seems to be working in simulator
|
||||
- 1. Implemented option 1. Seems to be working in simulator
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#### Styling and components
|
||||
|
||||
- https://www.unistyl.es/
|
||||
- https://reactnativereusables.com/
|
||||
- https://reactnativereusables.com/
|
||||
- https://github.com/Shopify/restyle
|
||||
- https://docs.expo.dev/versions/latest/sdk/segmented-control/
|
||||
- https://docs.expo.dev/versions/latest/sdk/ui/
|
||||
@@ -34,4 +34,4 @@
|
||||
- https://docs.expo.dev/versions/latest/sdk/webview/
|
||||
- https://docs.expo.dev/versions/latest/sdk/gl-view/
|
||||
- https://code.visualstudio.com/docs/terminal/shell-integration
|
||||
- https://github.com/termux/termux-app/wiki/Termux-Libraries/bd010af15b8434ba136c32fa70a50c504ea04363
|
||||
- https://github.com/termux/termux-app/wiki/Termux-Libraries/bd010af15b8434ba136c32fa70a50c504ea04363
|
||||
|
||||
11933
pnpm-lock.yaml
generated
11933
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user