Skip to content

Commit 4a63c7a

Browse files
authoredJan 13, 2021
[Jetchat] Adds consistency with Owl's backhandler and uses rememberUp… (android#351)
1 parent 1b2c720 commit 4a63c7a

File tree

7 files changed

+35
-49
lines changed

7 files changed

+35
-49
lines changed
 

‎Jetchat/app/src/androidTest/java/com/example/compose/jetchat/ConversationTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class ConversationTest {
6666
// Launch the conversation screen
6767
composeTestRule.setContent {
6868
Providers(
69-
AmbientBackPressedDispatcher provides newActivity,
69+
AmbientBackPressedDispatcher provides newActivity.onBackPressedDispatcher,
7070
AmbientWindowInsets provides windowInsets
7171
) {
7272
JetchatTheme(isDarkTheme = themeIsDark.collectAsState(false).value) {

‎Jetchat/app/src/androidTest/java/com/example/compose/jetchat/NavigationTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class NavigationTest {
6565
// Start the app
6666
composeTestRule.setContent {
6767
Providers(
68-
AmbientBackPressedDispatcher provides activity,
68+
AmbientBackPressedDispatcher provides activity.onBackPressedDispatcher,
6969
AmbientWindowInsets provides windowInsets,
7070
) {
7171
JetchatTheme {

‎Jetchat/app/src/androidTest/java/com/example/compose/jetchat/UserInputTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class UserInputTest {
6565
// Launch the conversation screen
6666
composeTestRule.setContent {
6767
Providers(
68-
AmbientBackPressedDispatcher provides activity,
68+
AmbientBackPressedDispatcher provides activity.onBackPressedDispatcher,
6969
AmbientWindowInsets provides windowInsets,
7070
) {
7171
JetchatTheme {

‎Jetchat/app/src/main/java/com/example/compose/jetchat/NavActivity.kt

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import androidx.core.view.WindowCompat
2929
import androidx.navigation.findNavController
3030
import com.example.compose.jetchat.components.JetchatScaffold
3131
import com.example.compose.jetchat.conversation.AmbientBackPressedDispatcher
32-
import com.example.compose.jetchat.conversation.backPressHandler
32+
import com.example.compose.jetchat.conversation.BackPressHandler
3333
import com.example.compose.jetchat.databinding.ContentMainBinding
3434
import dev.chrisbanes.accompanist.insets.ProvideWindowInsets
3535

@@ -50,7 +50,7 @@ class NavActivity : AppCompatActivity() {
5050
// Provide WindowInsets to our content. We don't want to consume them, so that
5151
// they keep being pass down the view hierarchy (since we're using fragments).
5252
ProvideWindowInsets(consumeWindowInsets = false) {
53-
Providers(AmbientBackPressedDispatcher provides this) {
53+
Providers(AmbientBackPressedDispatcher provides this.onBackPressedDispatcher) {
5454
val scaffoldState = rememberScaffoldState()
5555

5656
val openDrawerEvent = viewModel.drawerShouldBeOpened.observeAsState()
@@ -62,11 +62,9 @@ class NavActivity : AppCompatActivity() {
6262
}
6363

6464
// Intercepts back navigation when the drawer is open
65-
backPressHandler(
66-
enabled = scaffoldState.drawerState.isOpen,
67-
onBackPressed = { scaffoldState.drawerState.close() },
68-
highPriority = true
69-
)
65+
if (scaffoldState.drawerState.isOpen) {
66+
BackPressHandler { scaffoldState.drawerState.close() }
67+
}
7068

7169
JetchatScaffold(
7270
scaffoldState,

‎Jetchat/app/src/main/java/com/example/compose/jetchat/conversation/BackHandler.kt

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -17,68 +17,55 @@
1717
package com.example.compose.jetchat.conversation
1818

1919
import androidx.activity.OnBackPressedCallback
20-
import androidx.activity.OnBackPressedDispatcherOwner
20+
import androidx.activity.OnBackPressedDispatcher
2121
import androidx.compose.runtime.Ambient
2222
import androidx.compose.runtime.Composable
23-
import androidx.compose.runtime.onCommit
23+
import androidx.compose.runtime.DisposableEffect
24+
import androidx.compose.runtime.getValue
2425
import androidx.compose.runtime.remember
26+
import androidx.compose.runtime.rememberUpdatedState
2527
import androidx.compose.runtime.staticAmbientOf
2628

2729
/**
28-
* This [Composable] can be used with a [AmbientBackPressedDispatcher] to intercept a back press (if
29-
* [enabled]).
30+
* This [Composable] can be used with a [AmbientBackPressedDispatcher] to intercept a back press.
3031
*
3132
* @param onBackPressed (Event) What to do when back is intercepted
32-
* @param enabled (state) When to intercept the back navigation
33-
* @param highPriority (config) Used to make sure this is the first handler in the dispatcher
3433
*
3534
*/
3635
@Composable
37-
fun backPressHandler(
38-
onBackPressed: () -> Unit,
39-
enabled: Boolean = true,
40-
highPriority: Boolean = false
41-
) {
42-
val dispatcher = AmbientBackPressedDispatcher.current.onBackPressedDispatcher
36+
fun BackPressHandler(onBackPressed: () -> Unit) {
37+
// Safely update the current `onBack` lambda when a new one is provided
38+
val currentOnBackPressed by rememberUpdatedState(onBackPressed)
4339

44-
// This callback is going to be remembered only if onBackPressed is referentially equal.
45-
val backCallback = remember(onBackPressed) {
46-
object : OnBackPressedCallback(enabled) {
40+
// Remember in Composition a back callback that calls the `onBackPressed` lambda
41+
val backCallback = remember {
42+
object : OnBackPressedCallback(true) {
4743
override fun handleOnBackPressed() {
48-
onBackPressed()
44+
currentOnBackPressed()
4945
}
5046
}
5147
}
5248

53-
// Using onCommit guarantees that failed transactions don't incorrectly toggle the
54-
// remembered callback.
55-
onCommit(enabled, highPriority) {
56-
if (enabled && highPriority) {
57-
// Since the Navigation Component is also intercepting the back event, make sure
58-
// that this is the first callback in the dispatcher.
59-
backCallback.remove()
60-
dispatcher.addCallback(backCallback)
61-
}
62-
backCallback.isEnabled = enabled
63-
}
49+
val backDispatcher = AmbientBackPressedDispatcher.current
6450

65-
onCommit(dispatcher, onBackPressed) {
66-
// Whenever there's a new dispatcher set up the callback
67-
dispatcher.addCallback(backCallback)
51+
// Whenever there's a new dispatcher set up the callback
52+
DisposableEffect(backDispatcher) {
53+
backDispatcher.addCallback(backCallback)
54+
// When the effect leaves the Composition, or there's a new dispatcher, remove the callback
6855
onDispose {
6956
backCallback.remove()
7057
}
7158
}
7259
}
7360

7461
/**
75-
* This [Ambient] is used to provide an [OnBackPressedDispatcherOwner]:
62+
* This [Ambient] is used to provide an [OnBackPressedDispatcher]:
7663
*
7764
* ```
78-
* Providers(AmbientBackPressedDispatcher provides requireActivity()) { }
65+
* Providers(AmbientBackPressedDispatcher provides requireActivity().onBackPressedDispatcher) { }
7966
* ```
8067
*
81-
* and setting up the callbacks with [backPressHandler].
68+
* and setting up the callbacks with [BackPressHandler].
8269
*/
8370
val AmbientBackPressedDispatcher =
84-
staticAmbientOf<OnBackPressedDispatcherOwner> { error("Ambient used without Provider") }
71+
staticAmbientOf<OnBackPressedDispatcher> { error("No Back Dispatcher provided") }

‎Jetchat/app/src/main/java/com/example/compose/jetchat/conversation/ConversationFragment.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class ConversationFragment : Fragment() {
5959

6060
setContent {
6161
Providers(
62-
AmbientBackPressedDispatcher provides requireActivity(),
62+
AmbientBackPressedDispatcher provides requireActivity().onBackPressedDispatcher,
6363
AmbientWindowInsets provides windowInsets,
6464
) {
6565
JetchatTheme {

‎Jetchat/app/src/main/java/com/example/compose/jetchat/conversation/UserInput.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,11 @@ fun UserInput(
125125
) {
126126
var currentInputSelector by savedInstanceState { InputSelector.NONE }
127127
val dismissKeyboard = { currentInputSelector = InputSelector.NONE }
128-
backPressHandler(
129-
enabled = currentInputSelector != InputSelector.NONE,
130-
onBackPressed = dismissKeyboard
131-
)
128+
129+
// Intercept back navigation if there's a InputSelector visible
130+
if (currentInputSelector != InputSelector.NONE) {
131+
BackPressHandler(onBackPressed = dismissKeyboard)
132+
}
132133

133134
var textState by remember { mutableStateOf(TextFieldValue()) }
134135

0 commit comments

Comments
 (0)