Skip to content

Commit c70407c

Browse files
committed
Handle packager reconnect message lifecycle
1 parent eec9808 commit c70407c

3 files changed

Lines changed: 88 additions & 5 deletions

File tree

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ public abstract class DevSupportManagerBase(
199199
private var isDevSupportEnabled = false
200200
private var isPackagerConnected = false
201201
private val packagerConnectionStatusNotifier =
202-
PackagerConnectionStatusNotifier(devLoadingViewManager)
202+
PackagerConnectionStatusNotifier(devLoadingViewManagerProvider = { devLoadingViewManager })
203203
private val errorCustomizers: MutableList<ErrorCustomizer> = mutableListOf()
204204
private var packagerLocationCustomizer: PackagerLocationCustomizer? = null
205205
private val jSExecutorDescription: String?
@@ -1018,6 +1018,7 @@ public abstract class DevSupportManagerBase(
10181018
devLoadingViewManager?.hide()
10191019
perfMonitorOverlayManager?.disable()
10201020

1021+
packagerConnectionStatusNotifier.onPackagerConnectionClosed()
10211022
devServerHelper.closePackagerConnection()
10221023
}
10231024
}

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/PackagerConnectionStatusNotifier.kt

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,35 @@
77

88
package com.facebook.react.devsupport
99

10+
import android.os.Handler
11+
import android.os.Looper
1012
import com.facebook.react.devsupport.interfaces.DevLoadingViewManager
1113

1214
internal class PackagerConnectionStatusNotifier(
13-
private val devLoadingViewManager: DevLoadingViewManager?
15+
private val devLoadingViewManagerProvider: () -> DevLoadingViewManager?,
16+
private val postDelayed: (Runnable, Long) -> Unit = { runnable, delayMs ->
17+
Handler(Looper.getMainLooper()).postDelayed(runnable, delayMs)
18+
},
1419
) {
1520
private var hasConnected = false
1621
private var connectionLost = false
22+
private var reconnectMessageToken = 0
1723

1824
fun onPackagerConnected() {
1925
if (connectionLost) {
26+
val devLoadingViewManager = devLoadingViewManagerProvider()
2027
devLoadingViewManager?.showMessage(RECONNECTED_MESSAGE)
28+
if (devLoadingViewManager != null) {
29+
val token = ++reconnectMessageToken
30+
postDelayed(
31+
Runnable {
32+
if (!connectionLost && reconnectMessageToken == token) {
33+
devLoadingViewManager.hide()
34+
}
35+
},
36+
RECONNECTED_MESSAGE_HIDE_DELAY_MS,
37+
)
38+
}
2139
}
2240
hasConnected = true
2341
connectionLost = false
@@ -26,12 +44,20 @@ internal class PackagerConnectionStatusNotifier(
2644
fun onPackagerDisconnected() {
2745
if (hasConnected && !connectionLost) {
2846
connectionLost = true
29-
devLoadingViewManager?.showMessage(CONNECTION_LOST_MESSAGE)
47+
reconnectMessageToken++
48+
devLoadingViewManagerProvider()?.showMessage(CONNECTION_LOST_MESSAGE)
3049
}
3150
}
3251

52+
fun onPackagerConnectionClosed() {
53+
hasConnected = false
54+
connectionLost = false
55+
reconnectMessageToken++
56+
}
57+
3358
private companion object {
3459
const val CONNECTION_LOST_MESSAGE = "Connection to Metro lost. Retrying..."
3560
const val RECONNECTED_MESSAGE = "Reconnected to Metro."
61+
const val RECONNECTED_MESSAGE_HIDE_DELAY_MS = 2_000L
3662
}
3763
}

packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/PackagerConnectionStatusNotifierTest.kt

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ import org.junit.Test
1414
class PackagerConnectionStatusNotifierTest {
1515

1616
private val devLoadingViewManager = RecordingDevLoadingViewManager()
17-
private val notifier = PackagerConnectionStatusNotifier(devLoadingViewManager)
17+
private val delayedActions = mutableListOf<Runnable>()
18+
private val notifier =
19+
PackagerConnectionStatusNotifier({ devLoadingViewManager }) { runnable, _ ->
20+
delayedActions.add(runnable)
21+
}
1822

1923
@Test
2024
fun testInitialConnectionDoesNotShowReconnectedMessage() {
@@ -45,8 +49,58 @@ class PackagerConnectionStatusNotifierTest {
4549
.containsExactly("Connection to Metro lost. Retrying...", "Reconnected to Metro.")
4650
}
4751

52+
@Test
53+
fun testReconnectMessageIsHiddenAfterDelay() {
54+
notifier.onPackagerConnected()
55+
notifier.onPackagerDisconnected()
56+
57+
notifier.onPackagerConnected()
58+
delayedActions.single().run()
59+
60+
assertThat(devLoadingViewManager.hideCount).isEqualTo(1)
61+
}
62+
63+
@Test
64+
fun testReconnectMessageDelayDoesNotHideNewLostConnectionMessage() {
65+
notifier.onPackagerConnected()
66+
notifier.onPackagerDisconnected()
67+
notifier.onPackagerConnected()
68+
69+
notifier.onPackagerDisconnected()
70+
delayedActions.single().run()
71+
72+
assertThat(devLoadingViewManager.hideCount).isEqualTo(0)
73+
}
74+
75+
@Test
76+
fun testIntentionalCloseDoesNotShowConnectionLostMessage() {
77+
notifier.onPackagerConnected()
78+
79+
notifier.onPackagerConnectionClosed()
80+
notifier.onPackagerDisconnected()
81+
82+
assertThat(devLoadingViewManager.messages).isEmpty()
83+
}
84+
85+
@Test
86+
fun testUsesCurrentDevLoadingViewManager() {
87+
var currentDevLoadingViewManager: RecordingDevLoadingViewManager? = null
88+
val notifier =
89+
PackagerConnectionStatusNotifier({ currentDevLoadingViewManager }) { runnable, _ ->
90+
delayedActions.add(runnable)
91+
}
92+
currentDevLoadingViewManager = RecordingDevLoadingViewManager()
93+
94+
notifier.onPackagerConnected()
95+
notifier.onPackagerDisconnected()
96+
97+
assertThat(currentDevLoadingViewManager.messages)
98+
.containsExactly("Connection to Metro lost. Retrying...")
99+
}
100+
48101
private class RecordingDevLoadingViewManager : DevLoadingViewManager {
49102
val messages = mutableListOf<String>()
103+
var hideCount = 0
50104

51105
override fun showMessage(message: String) {
52106
messages.add(message)
@@ -63,6 +117,8 @@ class PackagerConnectionStatusNotifierTest {
63117

64118
override fun updateProgress(status: String?, done: Int?, total: Int?, percent: Int?) = Unit
65119

66-
override fun hide() = Unit
120+
override fun hide() {
121+
hideCount++
122+
}
67123
}
68124
}

0 commit comments

Comments
 (0)