Skip to content

Commit 67f2905

Browse files
authored
Migrate to Kotlin (#16)
1 parent d36414d commit 67f2905

32 files changed

+4412
-4182
lines changed

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ openBrowser("https://swan.io", {
8080
});
8181
```
8282

83+
> [!IMPORTANT]
84+
> On Android, the Chrome app must be opened at least once for this to work — a step often overlooked when using emulators in development.
85+
8386
## Handle deeplinks
8487

8588
In order to receive deeplink on browser close event, you have to setup them first. We **highly** recommand defining a custom schema + url for this specific task. For example, `com.company.myapp://close`.

android/build.gradle

+7-5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ buildscript {
77
gradlePluginPortal()
88
}
99
dependencies {
10+
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${safeExtGet("kotlinVersion", "1.8.0")}")
1011
classpath("com.android.tools.build:gradle:7.3.1")
1112
}
1213
}
@@ -16,14 +17,15 @@ def isNewArchitectureEnabled() {
1617
}
1718

1819
apply plugin: "com.android.library"
20+
apply plugin: "kotlin-android"
1921

2022
if (isNewArchitectureEnabled()) {
2123
apply plugin: "com.facebook.react"
2224
}
2325

2426
android {
25-
buildToolsVersion safeExtGet("buildToolsVersion", "33.0.0")
26-
compileSdkVersion safeExtGet("compileSdkVersion", 33)
27+
buildToolsVersion safeExtGet("buildToolsVersion", "34.0.0")
28+
compileSdkVersion safeExtGet("compileSdkVersion", 34)
2729

2830
if (project.android.hasProperty("namespace")) {
2931
namespace "io.swan.rnbrowser"
@@ -39,8 +41,8 @@ android {
3941
}
4042
defaultConfig {
4143
buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString())
42-
minSdkVersion safeExtGet("minSdkVersion", 21)
43-
targetSdkVersion safeExtGet("targetSdkVersion", 33)
44+
minSdkVersion safeExtGet("minSdkVersion", 23)
45+
targetSdkVersion safeExtGet("targetSdkVersion", 34)
4446
}
4547
lintOptions {
4648
abortOnError false
@@ -68,5 +70,5 @@ repositories {
6870
dependencies {
6971
//noinspection GradleDynamicVersion
7072
implementation "com.facebook.react:react-native:+" // From node_modules
71-
implementation "androidx.browser:browser:${safeExtGet("androidXBrowserVersion", "1.5.0")}"
73+
implementation "androidx.browser:browser:${safeExtGet("androidXBrowserVersion", "1.8.0")}"
7274
}

android/src/main/java/io/swan/rnbrowser/RNSwanBrowserModuleImpl.java

-84
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package io.swan.rnbrowser
2+
3+
import android.content.Intent
4+
import android.net.Uri
5+
6+
import androidx.annotation.ColorInt
7+
import androidx.browser.customtabs.CustomTabColorSchemeParams
8+
import androidx.browser.customtabs.CustomTabsIntent
9+
import androidx.core.content.ContextCompat
10+
import androidx.core.graphics.ColorUtils
11+
12+
import com.facebook.react.bridge.Promise
13+
import com.facebook.react.bridge.ReactApplicationContext
14+
import com.facebook.react.bridge.ReadableMap
15+
import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter
16+
17+
import io.swan.rnbrowser.helpers.CustomTabActivityHelper
18+
19+
object RNSwanBrowserModuleImpl {
20+
const val NAME = "RNSwanBrowser"
21+
private var browserVisible = false
22+
23+
internal fun onHostResume(reactContext: ReactApplicationContext) {
24+
if (browserVisible && reactContext.hasActiveReactInstance()) {
25+
browserVisible = false
26+
27+
reactContext
28+
.getJSModule(RCTDeviceEventEmitter::class.java)
29+
.emit("swanBrowserDidClose", null)
30+
}
31+
}
32+
33+
internal fun open(
34+
reactContext: ReactApplicationContext,
35+
url: String,
36+
options: ReadableMap,
37+
promise: Promise
38+
) {
39+
if (browserVisible) {
40+
return promise.reject(
41+
"swan_browser_visible",
42+
"An instance of the swan browser is already visible"
43+
)
44+
}
45+
46+
val activity = reactContext.currentActivity
47+
?: return promise.reject(
48+
"no_current_activity",
49+
"Couldn't call open() when the app is in background"
50+
)
51+
52+
browserVisible = true
53+
54+
val intentBuilder = CustomTabsIntent.Builder().apply {
55+
setBookmarksButtonEnabled(false)
56+
setDownloadButtonEnabled(false)
57+
setInstantAppsEnabled(false)
58+
setSendToExternalDefaultHandlerEnabled(false)
59+
setShowTitle(false)
60+
61+
if (options.getString("animationType") == "fade") {
62+
setStartAnimations(activity, com.facebook.react.R.anim.catalyst_fade_in, R.anim.inert)
63+
setExitAnimations(activity, R.anim.inert, com.facebook.react.R.anim.catalyst_fade_out)
64+
} else {
65+
setStartAnimations(activity, com.facebook.react.R.anim.catalyst_slide_up, R.anim.inert)
66+
setExitAnimations(activity, R.anim.inert, com.facebook.react.R.anim.catalyst_slide_down)
67+
}
68+
}
69+
70+
@ColorInt val blackColor = ContextCompat.getColor(activity ,android.R.color.black)
71+
72+
val paramsBuilder = CustomTabColorSchemeParams.Builder().apply {
73+
setNavigationBarColor(blackColor)
74+
75+
if (options.hasKey("barTintColor")) {
76+
@ColorInt val barTintColor = options.getInt("barTintColor")
77+
78+
setToolbarColor(barTintColor)
79+
setSecondaryToolbarColor(barTintColor)
80+
81+
intentBuilder.setColorScheme(
82+
when (ColorUtils.calculateLuminance(barTintColor) > 0.5) {
83+
true -> CustomTabsIntent.COLOR_SCHEME_LIGHT
84+
false -> CustomTabsIntent.COLOR_SCHEME_DARK
85+
}
86+
)
87+
}
88+
}
89+
90+
intentBuilder.setDefaultColorSchemeParams(paramsBuilder.build())
91+
92+
val customTabsIntent = intentBuilder.build().apply {
93+
intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
94+
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
95+
}
96+
97+
CustomTabActivityHelper.openCustomTab(
98+
activity, customTabsIntent, Uri.parse(url)
99+
) { currentActivity, uri ->
100+
currentActivity.startActivity(Intent(Intent.ACTION_VIEW, uri))
101+
}
102+
103+
promise.resolve(null)
104+
}
105+
}

android/src/main/java/io/swan/rnbrowser/RNSwanBrowserPackage.java

-47
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package io.swan.rnbrowser
2+
3+
import com.facebook.react.TurboReactPackage
4+
import com.facebook.react.bridge.NativeModule
5+
import com.facebook.react.bridge.ReactApplicationContext
6+
import com.facebook.react.module.model.ReactModuleInfo
7+
import com.facebook.react.module.model.ReactModuleInfoProvider
8+
9+
class RNSwanBrowserPackage : TurboReactPackage() {
10+
11+
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
12+
return when (name) {
13+
RNSwanBrowserModuleImpl.NAME -> RNSwanBrowserModule(reactContext)
14+
else -> null
15+
}
16+
}
17+
18+
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
19+
return ReactModuleInfoProvider {
20+
val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
21+
val isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
22+
23+
val moduleInfo = ReactModuleInfo(
24+
RNSwanBrowserModuleImpl.NAME,
25+
RNSwanBrowserModuleImpl.NAME,
26+
false,
27+
false,
28+
true,
29+
false,
30+
isTurboModule
31+
)
32+
33+
moduleInfos[RNSwanBrowserModuleImpl.NAME] = moduleInfo
34+
moduleInfos
35+
}
36+
}
37+
}

android/src/main/java/io/swan/rnbrowser/helpers/CustomTabActivityHelper.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// https://github.com/GoogleChrome/android-browser-helper/blob/master/demos/custom-tabs-example-app/src/main/java/org/chromium/customtabsdemos/CustomTabActivityHelper.java
1+
// https://github.com/GoogleChrome/android-browser-helper/blob/main/demos/custom-tabs-example-app/src/main/java/org/chromium/customtabsdemos/CustomTabActivityHelper.java
22
//
33
// Copyright 2015 Google Inc. All Rights Reserved.
44
//

android/src/main/java/io/swan/rnbrowser/helpers/CustomTabsHelper.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// https://github.com/GoogleChrome/android-browser-helper/blob/master/demos/custom-tabs-example-app/src/main/java/org/chromium/customtabsdemos/CustomTabsHelper.java
1+
// https://github.com/GoogleChrome/android-browser-helper/blob/main/demos/custom-tabs-example-app/src/main/java/org/chromium/customtabsdemos/CustomTabsHelper.java
22
//
33
// Copyright 2015 Google Inc. All Rights Reserved.
44
//

android/src/main/java/io/swan/rnbrowser/helpers/ServiceConnection.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// https://github.com/GoogleChrome/android-browser-helper/blob/master/demos/custom-tabs-example-app/src/main/java/org/chromium/customtabsdemos/ServiceConnection.java
1+
// https://github.com/GoogleChrome/android-browser-helper/blob/main/demos/custom-tabs-example-app/src/main/java/org/chromium/customtabsdemos/ServiceConnection.java
22
//
33
// Copyright 2015 Google Inc. All Rights Reserved.
44
//

android/src/main/java/io/swan/rnbrowser/helpers/ServiceConnectionCallback.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// https://github.com/GoogleChrome/android-browser-helper/blob/master/demos/custom-tabs-example-app/src/main/java/org/chromium/customtabsdemos/ServiceConnectionCallback.java
1+
// https://github.com/GoogleChrome/android-browser-helper/blob/main/demos/custom-tabs-example-app/src/main/java/org/chromium/customtabsdemos/ServiceConnectionCallback.java
22
//
33
// Copyright 2015 Google Inc. All Rights Reserved.
44
//

0 commit comments

Comments
 (0)