Skip to content

Commit 33bc17a

Browse files
committed
Rework back button processing
1 parent 865b6bf commit 33bc17a

File tree

53 files changed

+777
-334
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+777
-334
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,9 @@
135135
android:theme="@style/AppTheme"
136136
android:requestLegacyExternalStorage="true"
137137
android:preserveLegacyExternalStorage="true"
138-
tools:targetApi="r">
138+
android:enableOnBackInvokedCallback="true"
139+
tools:targetApi="35"
140+
tools:ignore="RtlEnabled">
139141

140142
<meta-data
141143
android:name="firebase_analytics_collection_deactivated"

app/src/main/java/org/thunderdog/challegram/BaseActivity.java

Lines changed: 150 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@
6060
import android.widget.TextView;
6161
import android.widget.Toast;
6262

63+
import androidx.activity.BackEventCompat;
6364
import androidx.activity.ComponentActivity;
65+
import androidx.activity.OnBackPressedCallback;
6466
import androidx.annotation.DrawableRes;
6567
import androidx.annotation.NonNull;
6668
import androidx.annotation.Nullable;
@@ -85,16 +87,19 @@
8587
import org.thunderdog.challegram.data.TGReaction;
8688
import org.thunderdog.challegram.mediaview.MediaViewController;
8789
import org.thunderdog.challegram.navigation.ActivityResultHandler;
90+
import org.thunderdog.challegram.navigation.BackPressMode;
8891
import org.thunderdog.challegram.navigation.DrawerController;
8992
import org.thunderdog.challegram.navigation.HeaderView;
9093
import org.thunderdog.challegram.navigation.InterceptLayout;
9194
import org.thunderdog.challegram.navigation.MenuMoreWrap;
9295
import org.thunderdog.challegram.navigation.NavigationController;
9396
import org.thunderdog.challegram.navigation.NavigationGestureController;
97+
import org.thunderdog.challegram.navigation.NavigationStack;
9498
import org.thunderdog.challegram.navigation.OptionsLayout;
9599
import org.thunderdog.challegram.navigation.OverlayView;
96100
import org.thunderdog.challegram.navigation.ReactionsOverlayView;
97101
import org.thunderdog.challegram.navigation.RootDrawable;
102+
import org.thunderdog.challegram.navigation.SystemBackEventListener;
98103
import org.thunderdog.challegram.navigation.TooltipOverlayView;
99104
import org.thunderdog.challegram.navigation.ViewController;
100105
import org.thunderdog.challegram.player.RecordAudioVideoController;
@@ -242,7 +247,11 @@ public ClickBait getSettingsClickBait () {
242247
}
243248

244249
public boolean isAnimating (boolean intercept) {
245-
return (navigation != null && (intercept ? navigation.isAnimatingWithEffect() : navigation.isAnimating())) || (drawer != null && drawer.isAnimating()) || isProgressShowing || (cameraAnimator != null && cameraAnimator.isAnimating());
250+
return
251+
(navigation != null && (intercept ? navigation.isAnimatingWithEffect() : navigation.isAnimating())) ||
252+
(drawer != null && drawer.isAnimating()) ||
253+
isProgressShowing ||
254+
(cameraAnimator != null && cameraAnimator.isAnimating());
246255
}
247256

248257
public boolean processTouchEvent (MotionEvent event) {
@@ -485,7 +494,6 @@ public void onCreate (Bundle savedInstanceState) {
485494
if (Config.USE_CUSTOM_NAVIGATION_COLOR) {
486495
this.isWindowLight = !Theme.isDark();
487496
}
488-
this.isGestureNavigationEnabled = Screen.isGesturalNavigationEnabled(getResources());
489497
// UI.resetSizes();
490498
setActivityState(UI.State.RESUMED);
491499
TdlibManager.instance().watchDog().onActivityCreate(this);
@@ -500,6 +508,7 @@ public void onCreate (Bundle savedInstanceState) {
500508

501509
Screen.checkDensity();
502510

511+
this.isGestureNavigationEnabled = Screen.isGesturalNavigationEnabled(getResources());
503512
mHasSoftwareKeys = hasSoftwareKeys();
504513

505514
currentOrientation = UI.getOrientation();
@@ -569,9 +578,9 @@ public void onCreate (Bundle savedInstanceState) {
569578

570579
Lang.addLanguageListener(this);
571580

572-
/*if (BuildConfig.DEBUG) {
573-
addRemoveRtlSwitch();
574-
}*/
581+
navigation.getStack().addChangeListener(navigationStackChangeListener);
582+
backPressedCallback.setEnabled(isBackPressActionAvailable(handleOnBackPress(false, false)));
583+
getOnBackPressedDispatcher().addCallback(backPressedCallback);
575584
}
576585

577586
private View rtlSwitchView;
@@ -1197,6 +1206,7 @@ public void onDestroy () {
11971206
}
11981207
setOrientationLockFlags(0);
11991208
if (navigation != null) {
1209+
navigation.getStack().removeChangeListener(navigationStackChangeListener);
12001210
navigation.destroy();
12011211
}
12021212
Lang.removeLanguageListener(this);
@@ -1342,57 +1352,140 @@ public void onConfigurationChanged (@NonNull Configuration newConfig) {
13421352
}
13431353
}
13441354

1345-
@Override
1346-
@SuppressWarnings("deprecation")
1347-
public void onBackPressed () {
1348-
if (isPasscodeShowing) {
1349-
super.onBackPressed();
1350-
} else {
1351-
onBackPressed(false);
1355+
private final NavigationStack.ChangeListener navigationStackChangeListener = stack -> {
1356+
notifyBackPressAvailabilityChanged();
1357+
};
1358+
1359+
private final OnBackPressedCallback backPressedCallback = new OnBackPressedCallback(false) {
1360+
@Override
1361+
public void handleOnBackPressed () {
1362+
boolean handled = false;
1363+
if (backPressTarget != null) {
1364+
handled = backPressTarget.onSystemBackPressed();
1365+
backPressTarget = null;
1366+
}
1367+
if (!handled) {
1368+
performBackPress(false);
1369+
}
1370+
}
1371+
1372+
private SystemBackEventListener backPressTarget;
1373+
1374+
@Override
1375+
public void handleOnBackStarted (@NonNull BackEventCompat backEvent) {
1376+
@BackPressMode int mode = backPressMode;
1377+
SystemBackEventListener target;
1378+
switch (mode) {
1379+
case BackPressMode.NAVIGATE_BACK_IN_STACK:
1380+
target = navigation;
1381+
break;
1382+
case BackPressMode.CLOSE_NAVIGATION_DRAWER:
1383+
target = drawer;
1384+
break;
1385+
case BackPressMode.CUSTOM_ACTION_PERFORMED:
1386+
case BackPressMode.SYSTEM_ACTION_REQUIRED:
1387+
target = null;
1388+
break;
1389+
default:
1390+
throw new AssertionError(Integer.toString(mode));
1391+
}
1392+
if (target != null && target.onSystemBackStarted(backEvent)) {
1393+
backPressTarget = target;
1394+
} else {
1395+
backPressTarget = null;
1396+
}
1397+
}
1398+
1399+
@Override
1400+
public void handleOnBackCancelled () {
1401+
if (backPressTarget != null) {
1402+
backPressTarget.onSystemBackCancelled();
1403+
backPressTarget = null;
1404+
}
1405+
}
1406+
1407+
@Override
1408+
public void handleOnBackProgressed (@NonNull BackEventCompat backEvent) {
1409+
if (backPressTarget != null) {
1410+
backPressTarget.onSystemBackProgressed(backEvent);
1411+
}
1412+
}
1413+
};
1414+
1415+
private static boolean isBackPressActionAvailable (@BackPressMode int backPressMode) {
1416+
return backPressMode != BackPressMode.SYSTEM_ACTION_REQUIRED;
1417+
}
1418+
1419+
private @BackPressMode int backPressMode = BackPressMode.SYSTEM_ACTION_REQUIRED;
1420+
1421+
public void notifyBackPressAvailabilityChanged () {
1422+
@BackPressMode int backPressMode = handleOnBackPress(false, false);
1423+
this.backPressMode = backPressMode;
1424+
boolean isEnabled = isBackPressActionAvailable(backPressMode);
1425+
if (backPressedCallback.isEnabled() != isEnabled) {
1426+
backPressedCallback.setEnabled(isEnabled);
13521427
}
13531428
}
13541429

1355-
@SuppressWarnings("deprecation")
1356-
public void onBackPressed (boolean fromTop) {
1430+
public void performBackPress (boolean fromTop) {
1431+
if (handleOnBackPress(fromTop, true) == BackPressMode.SYSTEM_ACTION_REQUIRED) {
1432+
backPressedCallback.setEnabled(false);
1433+
getOnBackPressedDispatcher().onBackPressed();
1434+
}
1435+
}
1436+
1437+
public @BackPressMode int handleOnBackPress (boolean fromTop, boolean commit) {
1438+
if (isPasscodeShowing) {
1439+
return BackPressMode.SYSTEM_ACTION_REQUIRED;
1440+
}
13571441
if (isProgressShowing) {
1358-
if (progressListener != null) {
1442+
if (progressListener != null && commit) {
13591443
hideProgress(true);
13601444
}
1361-
return;
1445+
return BackPressMode.CUSTOM_ACTION_PERFORMED;
13621446
}
1363-
if (tooltipOverlayView != null && tooltipOverlayView.onBackPressed()) {
1364-
return;
1447+
if (tooltipOverlayView != null && tooltipOverlayView.handleOnBackPress(commit)) {
1448+
return BackPressMode.CUSTOM_ACTION_PERFORMED;
13651449
}
1366-
if (dismissLastOpenWindow(false, true, fromTop)) {
1367-
return;
1450+
if (dismissLastOpenWindow(false, true, fromTop, commit)) {
1451+
return BackPressMode.CUSTOM_ACTION_PERFORMED;
13681452
}
13691453
if (isCameraOpen) {
1370-
closeCameraByBackPress();
1371-
return;
1454+
if (commit) {
1455+
closeCameraByBackPress();
1456+
}
1457+
return BackPressMode.CUSTOM_ACTION_PERFORMED;
13721458
}
13731459
if (recordAudioVideoController.isOpen()) {
1374-
recordAudioVideoController.onBackPressed();
1375-
return;
1376-
}
1377-
if (!isAnimating(false)) {
1378-
if (navigation.passBackPressToActivity(fromTop)) {
1379-
super.onBackPressed();
1380-
return;
1381-
}
1382-
if (navigation.onBackPressed(fromTop)) {
1383-
return;
1460+
if (commit) {
1461+
recordAudioVideoController.onBackPressed();
13841462
}
1385-
if (drawer != null && drawer.isVisible()) {
1463+
return BackPressMode.CUSTOM_ACTION_PERFORMED;
1464+
}
1465+
if (isAnimating(false)) {
1466+
return BackPressMode.CUSTOM_ACTION_PERFORMED;
1467+
}
1468+
if (navigation.passBackPressToActivity(fromTop)) {
1469+
return BackPressMode.SYSTEM_ACTION_REQUIRED;
1470+
}
1471+
@BackPressMode int navigationBackPress = navigation.performOnBackPressed(fromTop, commit);
1472+
if (navigationBackPress != BackPressMode.SYSTEM_ACTION_REQUIRED) {
1473+
return navigationBackPress;
1474+
}
1475+
if (drawer != null && drawer.isVisible()) {
1476+
if (commit) {
13861477
drawer.close(0f, null);
1478+
}
1479+
return BackPressMode.CLOSE_NAVIGATION_DRAWER;
1480+
} else {
1481+
ViewController<?> c = navigation.getCurrentStackItem();
1482+
if (c != null && (c.inSelectMode() || c.inSearchMode() || c.inCustomMode())) {
1483+
navigationBackPress = navigation.performOnBackPressed(fromTop, commit);
1484+
return navigationBackPress != BackPressMode.SYSTEM_ACTION_REQUIRED ?
1485+
navigationBackPress :
1486+
BackPressMode.CUSTOM_ACTION_PERFORMED;
13871487
} else {
1388-
ViewController<?> c = navigation.getCurrentStackItem();
1389-
if (c == null) {
1390-
super.onBackPressed();
1391-
} else if (c.inSelectMode() || c.inSearchMode() || c.inCustomMode()) {
1392-
navigation.onBackPressed(fromTop);
1393-
} else {
1394-
super.onBackPressed();
1395-
}
1488+
return BackPressMode.SYSTEM_ACTION_REQUIRED;
13961489
}
13971490
}
13981491
}
@@ -1595,6 +1688,7 @@ public void removePasscodeListener (PasscodeListener listener) {
15951688
private void setIsPasscodeShowing (boolean isShowing) {
15961689
if (this.isPasscodeShowing != isShowing) {
15971690
this.isPasscodeShowing = isShowing;
1691+
notifyBackPressAvailabilityChanged();
15981692
if (isShowing) {
15991693
removeAllWindows();
16001694
} else {
@@ -1777,6 +1871,7 @@ public void showProgress (String message, ProgressPopupListener listener) {
17771871
return;
17781872
}
17791873
isProgressShowing = true;
1874+
notifyBackPressAvailabilityChanged();
17801875
final boolean firstTime;
17811876
if (progressWrap == null) {
17821877
progressWrap = new ProgressWrap(this);
@@ -1853,6 +1948,7 @@ public void hideProgress (boolean forced) {
18531948

18541949
isProgressShowing = false;
18551950
isProgressAnimating = true;
1951+
notifyBackPressAvailabilityChanged();
18561952

18571953
ValueAnimator obj;
18581954
obj = AnimatorUtils.simpleValueAnimator();
@@ -2361,6 +2457,7 @@ public void showPopupWindow (PopupLayout window) {
23612457
windows.add(window);
23622458
checkDisallowScreenshots();
23632459
window.showBoundWindow(rootView);
2460+
notifyBackPressAvailabilityChanged();
23642461
}
23652462

23662463
public boolean hasAnimatingWindow () {
@@ -2385,6 +2482,7 @@ public void removeWindowFromList (PopupLayout window) {
23852482
if (!windows.remove(window)) {
23862483
completelyForgetThisWindow(window);
23872484
}
2485+
notifyBackPressAvailabilityChanged();
23882486
checkDisallowScreenshots();
23892487
}
23902488

@@ -2393,18 +2491,20 @@ public void removeWindowFromList (PopupLayout window) {
23932491
return popupLayout != null ? popupLayout.getBoundController() : null;
23942492
}
23952493

2396-
public boolean dismissLastOpenWindow (boolean byKeyPress, boolean byBackPress, boolean byHeaderBackPress) {
2494+
public boolean dismissLastOpenWindow (boolean byKeyPress, boolean byBackPress, boolean byHeaderBackPress, boolean commit) {
23972495
final int size = windows.size();
23982496
for (int i = size - 1; i >= 0; i--) {
23992497
PopupLayout window = windows.get(i);
24002498
if (window.isBoundWindowShowing()) {
24012499
if (byKeyPress && window.canHideKeyboard()) {
2402-
return window.hideSoftwareKeyboard();
2500+
return commit || window.hideSoftwareKeyboard();
24032501
}
2404-
if (byBackPress && window.onBackPressed(byHeaderBackPress)) {
2502+
if (byBackPress && window.performOnBackPressed(byHeaderBackPress, commit)) {
24052503
return true;
24062504
}
2407-
window.hideWindow(true);
2505+
if (commit) {
2506+
window.hideWindow(true);
2507+
}
24082508
return true;
24092509
}
24102510
}
@@ -2422,6 +2522,7 @@ public void pretendYouDontKnowThisWindow (PopupLayout window) {
24222522
}
24232523
forgottenWindows.put(i, window);
24242524
}
2525+
notifyBackPressAvailabilityChanged();
24252526
}
24262527

24272528
private int indexOfForgottenWindow (PopupLayout window) {
@@ -2446,6 +2547,7 @@ public void letsRememberAboutThisWindow (PopupLayout window) {
24462547
}
24472548
forgottenWindows.remove(oldIndex);
24482549
checkDisallowScreenshots();
2550+
notifyBackPressAvailabilityChanged();
24492551
}
24502552
}
24512553

@@ -2789,6 +2891,7 @@ public void onFactorChangeFinished (int id, float finalFactor, FactorAnimator ca
27892891
switch (id) {
27902892
case ANIMATOR_ID_CAMERA: {
27912893
processCameraAnimationFinish(finalFactor);
2894+
notifyBackPressAvailabilityChanged();
27922895
break;
27932896
}
27942897
}
@@ -3038,6 +3141,7 @@ private void checkCameraOrientationBlocked () {
30383141
private void setCameraOpen (ViewController.CameraOpenOptions options, boolean isOpen, boolean byDrag) {
30393142
if (this.isCameraOpen != isOpen) {
30403143
this.isCameraOpen = isOpen;
3144+
notifyBackPressAvailabilityChanged();
30413145
if (isOpen) {
30423146
this.cameraOptions = options;
30433147
}
@@ -3111,6 +3215,7 @@ private void processCameraAnimationFinish (final float toFactor) {
31113215
} else if (toFactor == 0f && !isCameraOpen) {
31123216
onCameraCompletelyClosed();
31133217
}
3218+
notifyBackPressAvailabilityChanged();
31143219
});
31153220
}
31163221

app/src/main/java/org/thunderdog/challegram/component/attach/MediaBottomBaseController.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,14 @@ protected boolean useGraySearchHeader () {
116116
}
117117

118118
@Override
119-
public boolean onBackPressed (boolean fromTop) {
119+
public boolean performOnBackPressed (boolean fromTop, boolean commit) {
120120
if (inSearchMode()) {
121-
mediaLayout.getHeaderView().closeSearchMode(true, null);
121+
if (commit) {
122+
mediaLayout.getHeaderView().closeSearchMode(true, null);
123+
}
122124
return true;
123125
}
124-
return false;
126+
return super.performOnBackPressed(fromTop, commit);
125127
}
126128

127129
public boolean canMoveRecycler () {
@@ -205,7 +207,7 @@ protected boolean canMinimizeHeight () {
205207
return true;
206208
}
207209

208-
public boolean showExitWarning (boolean isExitingSelection) {
210+
public boolean showExitWarning (boolean isExitingSelection, boolean commit) {
209211
// override
210212
return false;
211213
}

0 commit comments

Comments
 (0)