-
Notifications
You must be signed in to change notification settings - Fork 107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Chore: migrate repack native modules to turbo modules #344
Changes from 18 commits
4b9a9df
e68eb4d
46e4f1c
80a85c8
f74ed2a
bae8035
f27ae60
742f9fb
1e18f7d
391900f
5f345dc
6c382d4
626c32c
4d26acc
4a09696
839de63
ba282bf
9700c52
3740e24
f36769a
ae164e4
8be4291
ef926f4
de5f952
154be1f
98287ae
5c68783
71199f8
a585956
31e119f
5f77968
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package com.callstack.repack | ||
|
||
import android.os.Handler | ||
import com.facebook.react.bridge.* | ||
|
||
object ScriptManagerModuleImpl { | ||
|
||
const val NAME = "ScriptManager" | ||
|
||
private fun runInBackground(fn: () -> Unit) { | ||
val handler = Handler() | ||
val runnable = Runnable { | ||
fn() | ||
} | ||
handler.postDelayed(runnable, 0) | ||
|
||
} | ||
|
||
fun loadScript(scriptId: String, configMap: ReadableMap, promise: Promise, remoteLoader: RemoteScriptLoader, fileSystemLoader: FileSystemScriptLoader) { | ||
runInBackground { | ||
val config = ScriptConfig.fromReadableMap(scriptId, configMap) | ||
|
||
// Currently, `loadScript` supports either `RemoteScriptLoader` or `FileSystemScriptLoader` | ||
// but not both at the same time - it will likely change in the future. | ||
when { | ||
config.url.protocol.startsWith("http") -> { | ||
if (config.fetch) { | ||
remoteLoader.load(config, promise) | ||
} else { | ||
remoteLoader.execute(config, promise) | ||
} | ||
} | ||
config.url.protocol == "file" -> { | ||
fileSystemLoader.load(config, promise) | ||
} | ||
else -> { | ||
promise.reject( | ||
ScriptLoadingError.UnsupportedScheme.code, | ||
"Scheme in URL: '${config.url}' is not supported" | ||
) | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
fun prefetchScript(scriptId: String, configMap: ReadableMap, promise: Promise, remoteLoader: RemoteScriptLoader) { | ||
val config = ScriptConfig.fromReadableMap(scriptId, configMap) | ||
if (!config.fetch) { | ||
// Do nothing, script is already prefetched | ||
promise.resolve(null) | ||
} else { | ||
runInBackground { | ||
when { | ||
config.url.protocol.startsWith("http") -> { | ||
remoteLoader.prefetch(config, promise) | ||
} | ||
else -> { | ||
promise.reject( | ||
ScriptLoadingError.UnsupportedScheme.code, | ||
"Scheme in URL: '${config.url}' is not supported" | ||
) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
fun invalidateScripts(scriptIds: ReadableArray, promise: Promise, remoteLoader: RemoteScriptLoader) { | ||
runInBackground { | ||
if (scriptIds.size() == 0) { | ||
remoteLoader.invalidateAll() | ||
promise.resolve(null) | ||
} else { | ||
try { | ||
for (i in 0 until scriptIds.size()) { | ||
val scriptId = scriptIds.getString(i) | ||
remoteLoader.invalidate(scriptId) | ||
} | ||
promise.resolve(null) | ||
} catch (error: Exception) { | ||
promise.reject( | ||
ScriptLoadingError.ScriptInvalidationFailure.code, | ||
"Cannot invalidate some of the scripts" | ||
) | ||
} | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,30 @@ | ||
package com.callstack.repack | ||
|
||
import com.facebook.react.ReactPackage | ||
import com.facebook.react.bridge.NativeModule | ||
import com.facebook.react.bridge.ReactApplicationContext | ||
import com.facebook.react.uimanager.ViewManager | ||
import com.facebook.react.bridge.* | ||
import com.facebook.react.TurboReactPackage | ||
import com.facebook.react.module.model.ReactModuleInfo | ||
import com.facebook.react.module.model.ReactModuleInfoProvider | ||
|
||
class ScriptManagerPackage : TurboReactPackage() { | ||
override fun getModule(name: String?, reactContext: ReactApplicationContext): NativeModule? = | ||
if (name == ScriptManagerModuleImpl.NAME) { | ||
ScriptManagerModule(reactContext) | ||
} else { | ||
null | ||
} | ||
|
||
class ScriptManagerPackage : ReactPackage { | ||
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> { | ||
return listOf(ScriptManagerModule(reactContext)) | ||
} | ||
|
||
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> { | ||
return emptyList() | ||
override fun getReactModuleInfoProvider() = ReactModuleInfoProvider { | ||
val isTurboModule: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED | ||
mapOf( | ||
ScriptManagerModuleImpl.NAME to ReactModuleInfo( | ||
ScriptManagerModuleImpl.NAME, // name | ||
ScriptManagerModuleImpl.NAME, // className | ||
false, // canOverrideExistingModule | ||
false, // needsEagerInit | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know what exactly Take a look at the Super App Showcase Host App – https://github.com/callstack/super-app-showcase/blob/main/packages/host/index.js ScriptManager is used before the App component is registered. Of course, what I'm saying here might be completely wrong since I'm not that familiar with the New Arch – if that's the case, sorry for the confusion :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On repack side, i'm not sure how eager it needs to be initialised (even though i feel it's still initialised and available), however this is the default spec from docs and i'm sure it can be set to Eagerly initialise. |
||
true, // hasConstants | ||
false, // isCxxModule | ||
isTurboModule // isTurboModule | ||
) | ||
) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package com.callstack.repack | ||
|
||
import android.os.Handler | ||
import com.facebook.react.bridge.* | ||
|
||
class ScriptManagerModule(reactContext: ReactApplicationContext) : NativeScriptManagerSpec(reactContext) { | ||
private val remoteLoader: RemoteScriptLoader = RemoteScriptLoader(reactApplicationContext) | ||
private val fileSystemLoader: FileSystemScriptLoader = FileSystemScriptLoader(reactApplicationContext) | ||
|
||
override fun getName(): String = ScriptManagerModuleImpl.NAME | ||
|
||
override fun loadScript(scriptId: String, configMap: ReadableMap, promise: Promise) { | ||
teneeto marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ScriptManagerModuleImpl.loadScript(scriptId, configMap, promise, remoteLoader, fileSystemLoader) | ||
} | ||
|
||
override fun prefetchScript(scriptId: String, configMap: ReadableMap, promise: Promise) { | ||
ScriptManagerModuleImpl.prefetchScript(scriptId, configMap, promise, remoteLoader) | ||
} | ||
|
||
override fun invalidateScripts(scriptIds: ReadableArray, promise: Promise) { | ||
ScriptManagerModuleImpl.invalidateScripts(scriptIds, promise, remoteLoader) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.callstack.repack | ||
|
||
import android.os.Handler | ||
import com.facebook.react.bridge.* | ||
|
||
class ScriptManagerModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { | ||
private val remoteLoader: RemoteScriptLoader = RemoteScriptLoader(reactApplicationContext) | ||
private val fileSystemLoader: FileSystemScriptLoader = FileSystemScriptLoader(reactApplicationContext) | ||
|
||
override fun getName(): String = ScriptManagerModuleImpl.NAME | ||
|
||
@ReactMethod | ||
fun loadScript(scriptId: String, configMap: ReadableMap, promise: Promise) { | ||
ScriptManagerModuleImpl.loadScript(scriptId, configMap, promise, remoteLoader, fileSystemLoader) | ||
} | ||
|
||
@ReactMethod | ||
fun prefetchScript(scriptId: String, configMap: ReadableMap, promise: Promise) { | ||
ScriptManagerModuleImpl.prefetchScript(scriptId, configMap, promise, remoteLoader) | ||
} | ||
|
||
@ReactMethod | ||
fun invalidateScripts(scriptIds: ReadableArray, promise: Promise) { | ||
ScriptManagerModuleImpl.invalidateScripts(scriptIds, promise, remoteLoader) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nit]: as an improvement, we can consider rewriting it to follow the bob pattern:
https://github.com/callstack/react-native-builder-bob/tree/main/packages/create-react-native-library/templates/java-library-mixed/android/src
cc @thymikee