Skip to content

Commit 6ec163c

Browse files
authored
feat: Migrate from turbo-(ios|android) to hotwire-native-(ios|android) (#220)
1 parent 1d2a225 commit 6ec163c

33 files changed

+435
-424
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ yarn-error.log*
4848
npm-debug.log
4949
yarn-error.log
5050
vendor/
51-
turbo-android-dependencies.gradle
51+
hotwire-native-android-dependencies.gradle
5252

5353
# macOS
5454
.DS_Store

examples/turbo-demo-expo-example/app.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
"expo-build-properties",
3535
{
3636
"android": {
37-
"minSdkVersion": 26
37+
"minSdkVersion": 28,
38+
"kotlinVersion": "1.9.25"
3839
},
3940
"ios": {
4041
"deploymentTarget": "15.6"

packages/turbo/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ For Android you need to adjust your SDK version in your `build.gradle`.
2525

2626
> [_Turbo Documentation:_](https://github.com/hotwired/turbo-android#requirements)
2727
>
28-
> Android SDK 26+ is required as the minSdkVersion in your build.gradle.
28+
> Android SDK 28+ is required as the minSdkVersion in your build.gradle.
2929
30-
For iOS, you need to set the deployment target to 14.0 or higher.
30+
For iOS, you need to set the deployment target to 15.6 or higher.
3131

3232
## Example
3333

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ require "json"
33
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
44
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
55

6-
turbo_ios_source_files = "ios/vendor/turbo-ios/Source/**/*.{h,m,mm,swift}"
7-
turbo_ios_resource_files = "ios/vendor/turbo-ios/Source/**/*.{js}"
6+
hotwire_native_ios_source_files = "ios/vendor/hotwire-native-ios/Source/**/*.{h,m,mm,swift}"
7+
hotwire_native_ios_resource_files = "ios/vendor/hotwire-native-ios/Source/**/*.{js}"
88

99
Pod::Spec.new do |s|
10-
s.name = "RNTurbo"
10+
s.name = "RNHotwireNative"
1111
s.version = package["version"]
1212
s.summary = package["description"]
1313
s.homepage = package["homepage"]
@@ -17,8 +17,8 @@ Pod::Spec.new do |s|
1717
s.platforms = { :ios => "14.0" }
1818
s.source = { :git => "https://github.com/software-mansion-labs/react-native-turbo-demo.git", :tag => "#{s.version}" }
1919

20-
s.source_files = "ios/*.{h,m,mm,swift}", turbo_ios_source_files
21-
s.resource = turbo_ios_resource_files
20+
s.source_files = "ios/*.{h,m,mm,swift}", hotwire_native_ios_source_files
21+
s.resource = hotwire_native_ios_resource_files
2222

2323
s.dependency "React-Core"
2424

packages/turbo/android/build.gradle

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
apply from: './turbo-android-dependencies.gradle'
1+
apply from: './hotwire-native-android-dependencies.gradle'
22

33
buildscript {
44
// 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["TurboWebview_kotlinVersion"]
5+
def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["HotwireWebview_kotlinVersion"]
66

77
repositories {
88
google()
@@ -28,11 +28,11 @@ if (isNewArchitectureEnabled()) {
2828
}
2929

3030
def getExtOrDefault(name) {
31-
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["TurboWebview_" + name]
31+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["HotwireWebview_" + name]
3232
}
3333

3434
def getExtOrIntegerDefault(name) {
35-
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["TurboWebview_" + name]).toInteger()
35+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["HotwireWebview_" + name]).toInteger()
3636
}
3737

3838
def supportsNamespace() {
@@ -44,7 +44,7 @@ def supportsNamespace() {
4444
return (major == 7 && minor >= 3) || major >= 8
4545
}
4646

47-
def addTurboDependencies(Map<String, String> libraries) {
47+
def addHotwireDependencies(Map<String, String> libraries) {
4848
libraries.each { type, lib ->
4949
if (type.startsWith("dep")) {
5050
dependencies {
@@ -68,9 +68,10 @@ allprojects {
6868
}
6969
}
7070

71+
7172
android {
7273
if (supportsNamespace()) {
73-
namespace "com.reactnativeturbowebview"
74+
namespace "com.reactnativehotwirewebview"
7475

7576
sourceSets {
7677
main {
@@ -113,6 +114,7 @@ repositories {
113114
}
114115
}
115116

117+
116118
def kotlin_version = getExtOrDefault("kotlinVersion")
117119

118120
dependencies {
@@ -121,8 +123,9 @@ dependencies {
121123
//noinspection GradleDynamicVersion
122124
implementation "com.facebook.react:react-native:+"
123125
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
124-
implementation "dev.hotwire:turbo:local"
126+
implementation "dev.hotwire:core:local"
127+
implementation "dev.hotwire:navigation-fragments:local"
125128
}
126129

127-
addTurboDependencies(deps)
128-
addTurboDependencies(apis)
130+
addHotwireDependencies(deps)
131+
addHotwireDependencies(apis)
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
TurboWebview_kotlinVersion=1.9.10
2-
TurboWebview_minSdkVersion=26
3-
TurboWebview_targetSdkVersion=31
4-
TurboWebview_compileSdkVersion=31
5-
TurboWebview_ndkversion=21.4.7075529
1+
HotwireWebview_kotlinVersion=1.9.25
2+
HotwireWebview_minSdkVersion=26
3+
HotwireWebview_targetSdkVersion=31
4+
HotwireWebview_compileSdkVersion=31
5+
HotwireWebview_ndkversion=21.4.7075529

packages/turbo/android/src/main/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2-
package="com.reactnativeturbowebview">
2+
package="com.reactnativehotwirewebview">
33
<queries>
44
<intent>
55
<action android:name="android.intent.action.VIEW" />

packages/turbo/android/src/main/java/com/reactnativeturbowebview/RNFileChooserDelegate.kt renamed to packages/turbo/android/src/main/java/com/reactnativehotwirewebview/RNFileChooserDelegate.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.reactnativeturbowebview
1+
package com.reactnativehotwirewebview
22

33
import android.Manifest
44
import android.app.Activity

packages/turbo/android/src/main/java/com/reactnativeturbowebview/RNSession.kt renamed to packages/turbo/android/src/main/java/com/reactnativehotwirewebview/RNSession.kt

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.reactnativeturbowebview
1+
package com.reactnativehotwirewebview
22

33
import android.webkit.JavascriptInterface
44
import android.webkit.WebSettings
@@ -8,12 +8,17 @@ import androidx.lifecycle.LifecycleOwner
88
import androidx.lifecycle.lifecycleScope
99
import androidx.lifecycle.whenStateAtLeast
1010
import com.facebook.react.bridge.ReactApplicationContext
11-
import dev.hotwire.turbo.errors.TurboVisitError
12-
import dev.hotwire.turbo.session.TurboSession
13-
import dev.hotwire.turbo.views.TurboWebView
14-
import dev.hotwire.turbo.visit.TurboVisit
15-
import dev.hotwire.turbo.visit.TurboVisitAction
16-
import dev.hotwire.turbo.visit.TurboVisitOptions
11+
import com.reactnativehotwirewebview.RNWebChromeClient
12+
import com.reactnativehotwirewebview.SessionCallbackAdapter
13+
import com.reactnativehotwirewebview.SessionSubscriber
14+
import com.reactnativehotwirewebview.Utils
15+
import dev.hotwire.core.config.Hotwire
16+
import dev.hotwire.core.turbo.errors.VisitError
17+
import dev.hotwire.core.turbo.session.Session
18+
import dev.hotwire.core.turbo.webview.HotwireWebView
19+
import dev.hotwire.core.turbo.visit.Visit
20+
import dev.hotwire.core.turbo.visit.VisitAction
21+
import dev.hotwire.core.turbo.visit.VisitOptions
1722
import kotlinx.coroutines.Dispatchers
1823
import kotlinx.coroutines.launch
1924
import kotlinx.coroutines.withContext
@@ -27,10 +32,10 @@ class RNSession(
2732

2833
var visitableView: SessionSubscriber? = null
2934

30-
private val turboSession: TurboSession = run {
35+
private val turboSession: Session = run {
3136
val activity = reactContext.currentActivity as AppCompatActivity
32-
val webView = TurboWebView(activity, null)
33-
val session = TurboSession(sessionHandle, activity, webView)
37+
val webView = HotwireWebView(activity, null)
38+
val session = Session(sessionHandle, activity, webView)
3439

3540
webView.settings.setJavaScriptEnabled(true)
3641
webView.addJavascriptInterface(JavaScriptInterface(), "AndroidInterface")
@@ -39,38 +44,38 @@ class RNSession(
3944
session.isRunningInAndroidNavigation = false
4045
session
4146
}
42-
val webView: TurboWebView get() = turboSession.webView
43-
val currentVisit: TurboVisit? get() = turboSession.currentVisit
47+
val webView: HotwireWebView get() = turboSession.webView
48+
val currentVisit: Visit? get() = turboSession.currentVisit
4449

4550
internal fun registerVisitableView(newView: SessionSubscriber) {
4651
visitableView = newView
4752
}
4853

49-
private fun setUserAgentString(webView: TurboWebView, applicationNameForUserAgent: String?) {
54+
private fun setUserAgentString(webView: HotwireWebView, applicationNameForUserAgent: String?) {
5055
var userAgentString = WebSettings.getDefaultUserAgent(webView.context)
5156
if (applicationNameForUserAgent != null) {
5257
userAgentString = "$userAgentString $applicationNameForUserAgent"
5358
}
5459
webView.settings.userAgentString = userAgentString
5560
}
5661

57-
fun visit(url: String, restoreWithCachedSnapshot: Boolean, reload: Boolean, viewTreeLifecycleOwner: LifecycleOwner?, visitOptions: TurboVisitOptions?){
62+
fun visit(url: String, restoreWithCachedSnapshot: Boolean, reload: Boolean, viewTreeLifecycleOwner: LifecycleOwner?, visitOptions: VisitOptions?){
5863
val restore = restoreWithCachedSnapshot && !reload
5964

6065
val options = visitOptions ?: when {
61-
restore -> TurboVisitOptions(action = TurboVisitAction.RESTORE)
62-
else -> TurboVisitOptions()
66+
restore -> VisitOptions(action = VisitAction.RESTORE)
67+
else -> VisitOptions()
6368
}
6469

6570
viewTreeLifecycleOwner?.lifecycleScope?.launch {
6671
val snapshot = when (options.action) {
67-
TurboVisitAction.ADVANCE -> fetchCachedSnapshot(url)
72+
VisitAction.ADVANCE -> fetchCachedSnapshot(url)
6873
else -> null
6974
}
7075

7176
viewTreeLifecycleOwner.lifecycle.whenStateAtLeast(Lifecycle.State.STARTED) {
7277
turboSession.visit(
73-
TurboVisit(
78+
Visit(
7479
location = url,
7580
destinationIdentifier = url.hashCode(),
7681
restoreWithCachedSnapshot = restoreWithCachedSnapshot,
@@ -85,7 +90,7 @@ class RNSession(
8590

8691
private suspend fun fetchCachedSnapshot(url: String): String? {
8792
return withContext(Dispatchers.IO) {
88-
val response = turboSession.offlineRequestHandler?.getCachedSnapshot(
93+
val response = Hotwire.config.offlineRequestHandler?.getCachedSnapshot(
8994
url = url
9095
)
9196
response?.data?.use {
@@ -120,15 +125,15 @@ class RNSession(
120125
}
121126

122127
fun clearSnapshotCache() {
123-
// turbo-android doesn't expose a way to clear the snapshot cache, so we have to do it manually
128+
// hotwire-native-android doesn't expose a way to clear the snapshot cache, so we have to do it manually
124129
webView.post {
125130
webView.evaluateJavascript("window.Turbo.session.clearCache();", null)
126131
}
127132
}
128133

129134
// region SessionCallbackAdapter
130135

131-
override fun onReceivedError(error: TurboVisitError) {
136+
override fun onReceivedError(error: VisitError) {
132137
visitableView?.onReceivedError(error)
133138
}
134139

@@ -152,7 +157,11 @@ class RNSession(
152157
visitableView?.visitLocationStarted(location)
153158
}
154159

155-
override fun visitProposedToLocation(location: String, options: TurboVisitOptions) {
160+
override fun visitProposedToCrossOriginRedirect(location: String) {
161+
visitableView?.visitProposedToCrossOriginRedirect(location)
162+
}
163+
164+
override fun visitProposedToLocation(location: String, options: VisitOptions) {
156165
visitableView?.visitProposedToLocation(location, options)
157166
}
158167

@@ -168,7 +177,7 @@ class RNSession(
168177
visitableView?.didFinishFormSubmission(location)
169178
}
170179

171-
override fun requestFailedWithError(visitHasCachedSnapshot: Boolean, error: TurboVisitError) {
180+
override fun requestFailedWithError(visitHasCachedSnapshot: Boolean, error: VisitError) {
172181
visitableView?.requestFailedWithError(visitHasCachedSnapshot, error)
173182
}
174183

packages/turbo/android/src/main/java/com/reactnativeturbowebview/RNSessionManager.kt renamed to packages/turbo/android/src/main/java/com/reactnativehotwirewebview/RNSessionManager.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
package com.reactnativeturbowebview
1+
package com.reactnativehotwirewebview
22

33
import com.facebook.react.bridge.Arguments
44
import com.facebook.react.bridge.ReactApplicationContext
55
import com.facebook.react.bridge.ReactContextBaseJavaModule
66
import com.facebook.react.bridge.ReactMethod
77
import com.facebook.react.bridge.Promise;
88
import com.facebook.react.module.annotations.ReactModule
9+
import com.reactnativehotwirewebview.RNSession
910

1011
private const val NAME = "RNSessionManager"
1112

0 commit comments

Comments
 (0)