Skip to content

Commit cf943b7

Browse files
committed
ui: migrate to OnBackPressedDispatcher
This is compatible with Android 13's prediction-based back gesture animation. Signed-off-by: Jason A. Donenfeld <[email protected]>
1 parent b7295cd commit cf943b7

File tree

3 files changed

+28
-10
lines changed

3 files changed

+28
-10
lines changed

ui/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
android:name=".Application"
3636
android:allowBackup="false"
3737
android:banner="@mipmap/banner"
38+
android:enableOnBackInvokedCallback="true"
3839
android:icon="@mipmap/ic_launcher"
3940
android:label="@string/app_name"
4041
android:roundIcon="@mipmap/ic_launcher_round"

ui/src/main/java/com/wireguard/android/activity/MainActivity.kt

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import android.os.Bundle
99
import android.view.Menu
1010
import android.view.MenuItem
1111
import android.view.View
12+
import androidx.activity.OnBackPressedCallback
13+
import androidx.activity.addCallback
1214
import androidx.appcompat.app.ActionBar
1315
import androidx.fragment.app.FragmentManager
1416
import androidx.fragment.app.FragmentTransaction
@@ -26,27 +28,29 @@ import com.wireguard.android.model.ObservableTunnel
2628
class MainActivity : BaseActivity(), FragmentManager.OnBackStackChangedListener {
2729
private var actionBar: ActionBar? = null
2830
private var isTwoPaneLayout = false
31+
private var backPressedCallback: OnBackPressedCallback? = null
2932

30-
override fun onBackPressed() {
33+
private fun handleBackPressed() {
3134
val backStackEntries = supportFragmentManager.backStackEntryCount
3235
// If the two-pane layout does not have an editor open, going back should exit the app.
3336
if (isTwoPaneLayout && backStackEntries <= 1) {
3437
finish()
3538
return
3639
}
37-
// Deselect the current tunnel on navigating back from the detail pane to the one-pane list.
38-
if (!isTwoPaneLayout && backStackEntries == 1) {
40+
41+
if (backStackEntries >= 1)
3942
supportFragmentManager.popBackStack()
43+
44+
// Deselect the current tunnel on navigating back from the detail pane to the one-pane list.
45+
if (backStackEntries == 1)
4046
selectedTunnel = null
41-
return
42-
}
43-
super.onBackPressed()
4447
}
4548

4649
override fun onBackStackChanged() {
50+
val backStackEntries = supportFragmentManager.backStackEntryCount
51+
backPressedCallback?.isEnabled = backStackEntries >= 1
4752
if (actionBar == null) return
4853
// Do not show the home menu when the two-pane layout is at the detail view (see above).
49-
val backStackEntries = supportFragmentManager.backStackEntryCount
5054
val minBackStackEntries = if (isTwoPaneLayout) 2 else 1
5155
actionBar!!.setDisplayHomeAsUpEnabled(backStackEntries >= minBackStackEntries)
5256
}
@@ -57,6 +61,7 @@ class MainActivity : BaseActivity(), FragmentManager.OnBackStackChangedListener
5761
actionBar = supportActionBar
5862
isTwoPaneLayout = findViewById<View?>(R.id.master_detail_wrapper) != null
5963
supportFragmentManager.addOnBackStackChangedListener(this)
64+
backPressedCallback = onBackPressedDispatcher.addCallback(this) { handleBackPressed() }
6065
onBackStackChanged()
6166
}
6267

@@ -69,7 +74,7 @@ class MainActivity : BaseActivity(), FragmentManager.OnBackStackChangedListener
6974
return when (item.itemId) {
7075
android.R.id.home -> {
7176
// The back arrow in the action bar should act the same as the back button.
72-
onBackPressed()
77+
onBackPressedDispatcher.onBackPressed()
7378
true
7479
}
7580
R.id.menu_action_edit -> {

ui/src/main/java/com/wireguard/android/activity/TvMainActivity.kt

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ import android.os.storage.StorageVolume
1616
import android.util.Log
1717
import android.view.View
1818
import android.widget.Toast
19+
import androidx.activity.addCallback
1920
import androidx.activity.result.contract.ActivityResultContracts
2021
import androidx.appcompat.app.AppCompatActivity
2122
import androidx.core.content.ContextCompat
2223
import androidx.core.content.getSystemService
2324
import androidx.core.view.forEach
2425
import androidx.databinding.DataBindingUtil
26+
import androidx.databinding.Observable
2527
import androidx.databinding.ObservableBoolean
2628
import androidx.databinding.ObservableField
2729
import androidx.lifecycle.lifecycleScope
@@ -185,6 +187,17 @@ class TvMainActivity : AppCompatActivity() {
185187
binding.tunnelList.requestFocus()
186188
}
187189
}
190+
191+
val backPressedCallback = onBackPressedDispatcher.addCallback(this) { handleBackPressed() }
192+
val updateBackPressedCallback = object : Observable.OnPropertyChangedCallback() {
193+
override fun onPropertyChanged(sender: Observable?, propertyId: Int) {
194+
backPressedCallback.isEnabled = isDeleting.get() || filesRoot.get()?.isNotEmpty() == true
195+
}
196+
}
197+
isDeleting.addOnPropertyChangedCallback(updateBackPressedCallback)
198+
filesRoot.addOnPropertyChangedCallback(updateBackPressedCallback)
199+
backPressedCallback.isEnabled = false
200+
188201
binding.executePendingBindings()
189202
setContentView(binding.root)
190203

@@ -298,7 +311,7 @@ class TvMainActivity : AppCompatActivity() {
298311
}
299312
}
300313

301-
override fun onBackPressed() {
314+
private fun handleBackPressed() {
302315
when {
303316
isDeleting.get() -> {
304317
isDeleting.set(false)
@@ -313,7 +326,6 @@ class TvMainActivity : AppCompatActivity() {
313326
binding.tunnelList.requestFocus()
314327
}
315328
}
316-
else -> super.onBackPressed()
317329
}
318330
}
319331

0 commit comments

Comments
 (0)