Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6a87a4140e | |||
| ad81c4819b | |||
| 49018ed84c | |||
| fbfe3ce2e9 |
@@ -8,11 +8,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: set up JDK 11
|
||||
- name: set up JDK 17
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
java-version: '17'
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Test with Gradle
|
||||
@@ -24,11 +24,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: set up JDK 11
|
||||
- name: set up JDK 17
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
java-version: '17'
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Release with Gradle
|
||||
|
||||
+11
-9
@@ -18,6 +18,7 @@ import org.jetbrains.uast.UMethod;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public final class ControllerChangeHandlerIssueDetector extends Detector implements Detector.UastScanner {
|
||||
|
||||
static final Issue ISSUE =
|
||||
@@ -31,7 +32,7 @@ public final class ControllerChangeHandlerIssueDetector extends Detector impleme
|
||||
|
||||
@Override
|
||||
public List<Class<? extends UElement>> getApplicableUastTypes() {
|
||||
return Collections.singletonList(UClass.class);
|
||||
return Collections.<Class<? extends UElement>>singletonList(UClass.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -46,41 +47,42 @@ public final class ControllerChangeHandlerIssueDetector extends Detector impleme
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean hasSuperType = evaluator.extendsClass(node.getJavaPsi(), CLASS_NAME, true);
|
||||
final boolean hasSuperType = evaluator.extendsClass(node.getPsi(), CLASS_NAME, true);
|
||||
if (!hasSuperType) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!evaluator.isPublic(node)) {
|
||||
String message = String.format("This ControllerChangeHandler class should be public (%1$s)", node.getQualifiedName());
|
||||
context.report(ISSUE, node, context.getLocation(Identify.byName(node)), message);
|
||||
context.report(ISSUE, node, context.getLocation((UElement) node), message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.getContainingClass() != null && !evaluator.isStatic(node)) {
|
||||
String message = String.format("This ControllerChangeHandler inner class should be static (%1$s)", node.getQualifiedName());
|
||||
context.report(ISSUE, node, context.getLocation(Identify.byName(node)), message);
|
||||
context.report(ISSUE, node, context.getLocation((UElement) node), message);
|
||||
return;
|
||||
}
|
||||
|
||||
UMethod constructor = null;
|
||||
boolean hasConstructor = false;
|
||||
boolean hasDefaultConstructor = false;
|
||||
for (UMethod method : node.getMethods()) {
|
||||
if (method.isConstructor()) {
|
||||
constructor = method;
|
||||
if (evaluator.isPublic(method) && method.getUastParameters().isEmpty()) {
|
||||
hasConstructor = true;
|
||||
if (evaluator.isPublic(method) && method.getUastParameters().size() == 0) {
|
||||
hasDefaultConstructor = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (constructor != null && !hasDefaultConstructor) {
|
||||
if (hasConstructor && !hasDefaultConstructor) {
|
||||
String message = String.format(
|
||||
"This ControllerChangeHandler needs to have a public default constructor (`%1$s`)", node.getQualifiedName());
|
||||
context.report(ISSUE, node, context.getLocation(Identify.byName(constructor)), message);
|
||||
context.report(ISSUE, node, context.getLocation((UElement) node), message);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+14
-15
@@ -10,7 +10,6 @@ import com.android.tools.lint.detector.api.Issue;
|
||||
import com.android.tools.lint.detector.api.JavaContext;
|
||||
import com.android.tools.lint.detector.api.Scope;
|
||||
import com.android.tools.lint.detector.api.Severity;
|
||||
import com.intellij.psi.PsiType;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.uast.UClass;
|
||||
@@ -21,6 +20,7 @@ import org.jetbrains.uast.UParameter;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public final class ControllerIssueDetector extends Detector implements Detector.UastScanner {
|
||||
|
||||
static final Issue ISSUE =
|
||||
@@ -48,53 +48,52 @@ public final class ControllerIssueDetector extends Detector implements Detector.
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean hasSuperType = evaluator.extendsClass(node.getJavaPsi(), CLASS_NAME, true);
|
||||
final boolean hasSuperType = evaluator.extendsClass(node.getPsi(), CLASS_NAME, true);
|
||||
if (!hasSuperType) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!evaluator.isPublic(node)) {
|
||||
String message = String.format("This Controller class should be public (%1$s)", node.getQualifiedName());
|
||||
context.report(ISSUE, node, context.getLocation(Identify.byName(node)), message);
|
||||
context.report(ISSUE, node, context.getLocation((UElement) node), message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.getContainingClass() != null && !evaluator.isStatic(node)) {
|
||||
String message = String.format("This Controller inner class should be static (%1$s)", node.getQualifiedName());
|
||||
context.report(ISSUE, node, context.getLocation(Identify.byName(node)), message);
|
||||
context.report(ISSUE, node, context.getLocation((UElement) node), message);
|
||||
return;
|
||||
}
|
||||
|
||||
UMethod constructor = null;
|
||||
boolean hasConstructor = false;
|
||||
boolean hasDefaultConstructor = false;
|
||||
boolean hasBundleConstructor = false;
|
||||
for (UMethod method : node.getMethods()) {
|
||||
if (method.isConstructor()) {
|
||||
constructor = method;
|
||||
hasConstructor = true;
|
||||
if (evaluator.isPublic(method)) {
|
||||
List<UParameter> parameters = method.getUastParameters();
|
||||
if (parameters.isEmpty()) {
|
||||
if (parameters.size() == 0) {
|
||||
hasDefaultConstructor = true;
|
||||
break;
|
||||
} else if (parameters.size() == 1) {
|
||||
PsiType type = parameters.get(0).getType();
|
||||
if (type.equalsToText(SdkConstants.CLASS_BUNDLE) || type.equalsToText("Bundle")) {
|
||||
hasBundleConstructor = true;
|
||||
break;
|
||||
}
|
||||
} else if (parameters.size() == 1 &&
|
||||
(parameters.get(0).getType().equalsToText(SdkConstants.CLASS_BUNDLE)) ||
|
||||
parameters.get(0).getType().equalsToText("Bundle")) {
|
||||
hasBundleConstructor = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (constructor != null && !hasDefaultConstructor && !hasBundleConstructor) {
|
||||
if (hasConstructor && !hasDefaultConstructor && !hasBundleConstructor) {
|
||||
String message = String.format(
|
||||
"This Controller needs to have either a public default constructor or a" +
|
||||
" public single-argument constructor that takes a Bundle. (`%1$s`)",
|
||||
node.getQualifiedName());
|
||||
context.report(ISSUE, node, context.getLocation(Identify.byName(constructor)), message);
|
||||
context.report(ISSUE, node, context.getLocation((UElement) node), message);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
package com.bluelinelabs.conductor.lint;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiNameIdentifierOwner;
|
||||
|
||||
final class Identify {
|
||||
private Identify() {}
|
||||
|
||||
static PsiElement byName(PsiNameIdentifierOwner psiNameIdentifierOwner) {
|
||||
if (psiNameIdentifierOwner.getNameIdentifier() != null) {
|
||||
return psiNameIdentifierOwner.getNameIdentifier();
|
||||
}
|
||||
return psiNameIdentifierOwner;
|
||||
}
|
||||
}
|
||||
+11
-14
@@ -8,8 +8,15 @@ import com.android.tools.lint.checks.infrastructure.TestFile;
|
||||
import org.intellij.lang.annotations.Language;
|
||||
import org.junit.Test;
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public class ControllerChangeHandlerDetectorTest {
|
||||
|
||||
private static final String CONSTRUCTOR =
|
||||
"src/test/SampleHandler.java:2: Error: This ControllerChangeHandler needs to have a public default constructor (test.SampleHandler) [ValidControllerChangeHandler]\n"
|
||||
+ "public class SampleHandler extends com.bluelinelabs.conductor.ControllerChangeHandler {\n"
|
||||
+ "^\n"
|
||||
+ "1 errors, 0 warnings\n";
|
||||
|
||||
private final TestFile controllerChangeHandlerStub = java(
|
||||
"package com.bluelinelabs.conductor;\n"
|
||||
+ "abstract class ControllerChangeHandler {}"
|
||||
@@ -56,12 +63,7 @@ public class ControllerChangeHandlerDetectorTest {
|
||||
.files(controllerChangeHandlerStub, java(source))
|
||||
.issues(ControllerIssueDetector.ISSUE, ControllerChangeHandlerIssueDetector.ISSUE)
|
||||
.run()
|
||||
.expect(""
|
||||
+ "src/test/SampleHandler.java:3: Error: This ControllerChangeHandler needs to have a public default constructor (test.SampleHandler) [ValidControllerChangeHandler]\n"
|
||||
+ " public SampleHandler(int number) { }\n"
|
||||
+ " ~~~~~~~~~~~~~\n"
|
||||
+ "1 errors, 0 warnings\n"
|
||||
);
|
||||
.expect(CONSTRUCTOR);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -92,12 +94,7 @@ public class ControllerChangeHandlerDetectorTest {
|
||||
.files(controllerChangeHandlerStub, java(source))
|
||||
.issues(ControllerIssueDetector.ISSUE, ControllerChangeHandlerIssueDetector.ISSUE)
|
||||
.run()
|
||||
.expect(""
|
||||
+ "src/test/SampleHandler.java:3: Error: This ControllerChangeHandler needs to have a public default constructor (test.SampleHandler) [ValidControllerChangeHandler]\n"
|
||||
+ " private SampleHandler() { }\n"
|
||||
+ " ~~~~~~~~~~~~~\n"
|
||||
+ "1 errors, 0 warnings\n"
|
||||
);
|
||||
.expect(CONSTRUCTOR);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -114,7 +111,7 @@ public class ControllerChangeHandlerDetectorTest {
|
||||
.run()
|
||||
.expect("src/test/SampleHandler.java:2: Error: This ControllerChangeHandler class should be public (test.SampleHandler) [ValidControllerChangeHandler]\n"
|
||||
+ "private class SampleHandler extends com.bluelinelabs.conductor.ControllerChangeHandler {\n"
|
||||
+ " ~~~~~~~~~~~~~\n"
|
||||
+ "^\n"
|
||||
+ "1 errors, 0 warnings\n");
|
||||
}
|
||||
|
||||
@@ -134,7 +131,7 @@ public class ControllerChangeHandlerDetectorTest {
|
||||
.run()
|
||||
.expect("src/test/SampleHandler.java:2: Error: This ControllerChangeHandler class should be public (test.SampleHandler) [ValidControllerChangeHandler]\n" +
|
||||
"private class SampleHandler extends test.BaseChangeHandler {}\n" +
|
||||
" ~~~~~~~~~~~~~\n" +
|
||||
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
|
||||
"1 errors, 0 warnings");
|
||||
}
|
||||
}
|
||||
|
||||
+14
-18
@@ -8,12 +8,18 @@ import com.android.tools.lint.checks.infrastructure.TestFile;
|
||||
import org.intellij.lang.annotations.Language;
|
||||
import org.junit.Test;
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public class ControllerDetectorTest {
|
||||
|
||||
private static final String CONSTRUCTOR_ERROR =
|
||||
"src/test/SampleController.java:2: Error: This Controller needs to have either a public default constructor or a public single-argument constructor that takes a Bundle. (test.SampleController) [ValidController]\n"
|
||||
+ "public class SampleController extends com.bluelinelabs.conductor.Controller {\n"
|
||||
+ "^\n"
|
||||
+ "1 errors, 0 warnings\n";
|
||||
private static final String CLASS_ERROR =
|
||||
"src/test/SampleController.java:2: Error: This Controller class should be public (test.SampleController) [ValidController]\n"
|
||||
+ "private class SampleController extends com.bluelinelabs.conductor.Controller {\n"
|
||||
+ " ~~~~~~~~~~~~~~~~\n"
|
||||
+ "^\n"
|
||||
+ "1 errors, 0 warnings\n";
|
||||
|
||||
private final TestFile controllerStub = java(
|
||||
@@ -63,12 +69,7 @@ public class ControllerDetectorTest {
|
||||
.files(controllerStub, java(source))
|
||||
.issues(ControllerIssueDetector.ISSUE, ControllerChangeHandlerIssueDetector.ISSUE)
|
||||
.run()
|
||||
.expect(""
|
||||
+ "src/test/SampleController.java:3: Error: This Controller needs to have either a public default constructor or a public single-argument constructor that takes a Bundle. (test.SampleController) [ValidController]\n"
|
||||
+ " public SampleController(int number) { }\n"
|
||||
+ " ~~~~~~~~~~~~~~~~\n"
|
||||
+ "1 errors, 0 warnings\n"
|
||||
);
|
||||
.expect(CONSTRUCTOR_ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -105,11 +106,11 @@ public class ControllerDetectorTest {
|
||||
.files(controllerStub, java(baseClass), java(source))
|
||||
.issues(ControllerIssueDetector.ISSUE, ControllerChangeHandlerIssueDetector.ISSUE)
|
||||
.run()
|
||||
.expect(""
|
||||
+ "src/test/SampleController.java:3: Error: This Controller needs to have either a public default constructor or a public single-argument constructor that takes a Bundle. (test.SampleController) [ValidController]\n"
|
||||
+ " private SampleController() { }\n"
|
||||
+ " ~~~~~~~~~~~~~~~~\n"
|
||||
+ "1 errors, 0 warnings"
|
||||
.expect(
|
||||
"src/test/SampleController.java:2: Error: This Controller needs to have either a public default constructor or a public single-argument constructor that takes a Bundle. (test.SampleController) [ValidController]\n" +
|
||||
"public class SampleController extends BaseController {\n" +
|
||||
"^\n" +
|
||||
"1 errors, 0 warnings"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -125,12 +126,7 @@ public class ControllerDetectorTest {
|
||||
.files(controllerStub, java(source))
|
||||
.issues(ControllerIssueDetector.ISSUE, ControllerChangeHandlerIssueDetector.ISSUE)
|
||||
.run()
|
||||
.expect(""
|
||||
+ "src/test/SampleController.java:3: Error: This Controller needs to have either a public default constructor or a public single-argument constructor that takes a Bundle. (test.SampleController) [ValidController]\n"
|
||||
+ " private SampleController() { }\n"
|
||||
+ " ~~~~~~~~~~~~~~~~\n"
|
||||
+ "1 errors, 0 warnings\n"
|
||||
);
|
||||
.expect(CONSTRUCTOR_ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -4,7 +4,12 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion libs.versions.compilesdk.get() as Integer
|
||||
compileSdk libs.versions.compilesdk.get() as Integer
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion libs.versions.minsdk.get()
|
||||
@@ -12,6 +17,8 @@ android {
|
||||
versionCode Integer.parseInt(project.VERSION_CODE)
|
||||
versionName project.VERSION_NAME
|
||||
}
|
||||
|
||||
namespace "com.bluelinelabs.conductor.androidxtransition"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<manifest package="com.bluelinelabs.conductor.androidxtransition">
|
||||
<application />
|
||||
</manifest>
|
||||
@@ -5,7 +5,16 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion libs.versions.compilesdk.get() as Integer
|
||||
compileSdk libs.versions.compilesdk.get() as Integer
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "11"
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion libs.versions.minsdk.get()
|
||||
@@ -13,6 +22,8 @@ android {
|
||||
versionCode Integer.parseInt(project.VERSION_CODE)
|
||||
versionName project.VERSION_NAME
|
||||
}
|
||||
|
||||
namespace "com.bluelinelabs.conductor.viewpager"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<manifest package="com.bluelinelabs.conductor.viewpager">
|
||||
<application />
|
||||
</manifest>
|
||||
@@ -6,7 +6,16 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion libs.versions.compilesdk.get() as Integer
|
||||
compileSdk libs.versions.compilesdk.get() as Integer
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "11"
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion libs.versions.minsdk.get()
|
||||
@@ -20,6 +29,8 @@ android {
|
||||
includeAndroidResources = true
|
||||
}
|
||||
}
|
||||
|
||||
namespace "com.bluelinelabs.conductor.viewpager2"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<manifest package="com.bluelinelabs.conductor.viewpager2">
|
||||
<application />
|
||||
</manifest>
|
||||
+12
-1
@@ -6,7 +6,16 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion libs.versions.compilesdk.get() as Integer
|
||||
compileSdk libs.versions.compilesdk.get() as Integer
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "11"
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion libs.versions.minsdk.get()
|
||||
@@ -15,6 +24,8 @@ android {
|
||||
versionName project.VERSION_NAME
|
||||
consumerProguardFiles 'proguard-rules.txt'
|
||||
}
|
||||
|
||||
namespace "com.bluelinelabs.conductor"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<manifest package="com.bluelinelabs.conductor">
|
||||
<application />
|
||||
</manifest>
|
||||
@@ -8,6 +8,7 @@ import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
@@ -16,6 +17,7 @@ import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.activity.BackEventCompat;
|
||||
import androidx.activity.ComponentActivity;
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.activity.OnBackPressedDispatcher;
|
||||
@@ -24,6 +26,8 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
|
||||
import com.bluelinelabs.conductor.internal.BackGestureControllerView;
|
||||
import com.bluelinelabs.conductor.internal.BackGestureViewState;
|
||||
import com.bluelinelabs.conductor.internal.ClassUtils;
|
||||
import com.bluelinelabs.conductor.internal.ControllerLifecycleOwner;
|
||||
import com.bluelinelabs.conductor.internal.OwnViewTreeLifecycleAndRegistry;
|
||||
@@ -97,6 +101,9 @@ public abstract class Controller {
|
||||
private boolean isContextAvailable;
|
||||
|
||||
final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(true) {
|
||||
ControllerChangeHandler.ChangeTransaction popTransaction = null;
|
||||
BackGestureViewState backGestureViewState = null;
|
||||
|
||||
@Override
|
||||
public void handleOnBackPressed() {
|
||||
// Root-level routers should have PopRootControllerMode.NEVER, and so should never return false here.
|
||||
@@ -111,6 +118,116 @@ public abstract class Controller {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleOnBackStarted(@NonNull BackEventCompat backEvent) {
|
||||
Log.d("KUCK", "it has begun");
|
||||
ControllerChangeHandler.ChangeTransaction transaction = getPopTransaction();
|
||||
if (transaction != null && transaction.changeHandler != null && transaction.changeHandler.getEnableOnBackGestureCallbacks()) {
|
||||
List<BackGestureControllerView> toViews;
|
||||
if (transaction.to != null && transaction.to.view == null) {
|
||||
toViews = toViewsForGesture(transaction, new ArrayList<>());
|
||||
} else {
|
||||
toViews = Collections.emptyList();
|
||||
}
|
||||
|
||||
for (int i = toViews.size() - 1; i > 0; i--) {
|
||||
transaction.container.addView(toViews.get(i).getView());
|
||||
}
|
||||
|
||||
backGestureViewState = new BackGestureViewState(transaction.from.view, toViews);
|
||||
|
||||
transaction.changeHandler.handleOnBackStarted(
|
||||
transaction.container,
|
||||
getToView(),
|
||||
backGestureViewState.getFromView(),
|
||||
backEvent
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleOnBackProgressed(@NonNull BackEventCompat backEvent) {
|
||||
Log.d("KUCK", "it has progressed");
|
||||
|
||||
ControllerChangeHandler.ChangeTransaction transaction = getPopTransaction();
|
||||
if (transaction != null && transaction.changeHandler != null && transaction.changeHandler.getEnableOnBackGestureCallbacks()) {
|
||||
transaction.changeHandler.handleOnBackProgressed(
|
||||
transaction.container,
|
||||
getToView(),
|
||||
backGestureViewState.getFromView(),
|
||||
backEvent
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleOnBackCancelled() {
|
||||
Log.d("KUCK", "it has canceled");
|
||||
|
||||
ControllerChangeHandler.ChangeTransaction transaction = getPopTransaction();
|
||||
if (transaction != null && transaction.changeHandler != null && transaction.changeHandler.getEnableOnBackGestureCallbacks()) {
|
||||
transaction.changeHandler.handleOnBackCancelled(
|
||||
transaction.container,
|
||||
getToView(),
|
||||
backGestureViewState.getFromView()
|
||||
);
|
||||
|
||||
for (int i = 0; i < backGestureViewState.getToViews().size(); i++) {
|
||||
BackGestureControllerView state = backGestureViewState.getToViews().get(i);
|
||||
ViewGroup parent = (ViewGroup) state.getView().getParent();
|
||||
if (parent != null) {
|
||||
parent.removeView(state.getView());
|
||||
}
|
||||
|
||||
if (state.getInflatedForGesture()) {
|
||||
state.getController().removeViewReference(state.getView().getContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
backGestureViewState = null;
|
||||
}
|
||||
|
||||
private ControllerChangeHandler.ChangeTransaction getPopTransaction() {
|
||||
if (popTransaction == null) {
|
||||
popTransaction = router.popTransaction(Controller.this);
|
||||
}
|
||||
return popTransaction;
|
||||
}
|
||||
|
||||
private List<BackGestureControllerView> toViewsForGesture(
|
||||
ControllerChangeHandler.ChangeTransaction transaction,
|
||||
List<BackGestureControllerView> aggregator
|
||||
) {
|
||||
if (transaction.to != null) {
|
||||
View view = transaction.to.view;
|
||||
boolean inflated = false;
|
||||
if (view == null) {
|
||||
view = transaction.to.inflate(transaction.container);
|
||||
inflated = true;
|
||||
} else if (view.getParent() != null) {
|
||||
return aggregator;
|
||||
}
|
||||
|
||||
aggregator.add(new BackGestureControllerView(transaction.to, view, inflated));
|
||||
|
||||
if (!transaction.changeHandler.getRemovesFromViewOnPush()) {
|
||||
toViewsForGesture(router.popTransaction(transaction.to), aggregator);
|
||||
}
|
||||
}
|
||||
|
||||
return aggregator;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private View getToView() {
|
||||
if (backGestureViewState.getToViews().size() == 0) {
|
||||
return null;
|
||||
} else {
|
||||
return backGestureViewState.getToViews().get(0).getView();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public final LifecycleOwner lifecycleOwner = new ControllerLifecycleOwner(this);
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.bluelinelabs.conductor
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.BackEventCompat
|
||||
import androidx.annotation.RestrictTo
|
||||
import com.bluelinelabs.conductor.changehandler.SimpleSwapChangeHandler
|
||||
import com.bluelinelabs.conductor.internal.ClassUtils
|
||||
@@ -50,6 +51,8 @@ abstract class ControllerChangeHandler {
|
||||
|
||||
private var hasBeenUsed = false
|
||||
|
||||
open val enableOnBackGestureCallbacks = false
|
||||
|
||||
init {
|
||||
try {
|
||||
javaClass.getConstructor()
|
||||
@@ -112,9 +115,9 @@ abstract class ControllerChangeHandler {
|
||||
*/
|
||||
open fun copy(): ControllerChangeHandler = fromBundle(toBundle())!!
|
||||
|
||||
open fun handleOnBackStarted(container: ViewGroup, to: View?, from: View, swipeEdge: Int) {}
|
||||
open fun handleOnBackStarted(container: ViewGroup, to: View?, from: View, event: BackEventCompat) {}
|
||||
|
||||
open fun handleOnBackProgressed(container: ViewGroup, to: View?, from: View, progress: Float, swipeEdge: Int) {}
|
||||
open fun handleOnBackProgressed(container: ViewGroup, to: View?, from: View, event: BackEventCompat) {}
|
||||
|
||||
open fun handleOnBackCancelled(container: ViewGroup, to: View?, from: View) {}
|
||||
|
||||
|
||||
@@ -804,6 +804,37 @@ public abstract class Router {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
ChangeTransaction popTransaction(@NonNull Controller controller) {
|
||||
RouterTransaction from = null;
|
||||
RouterTransaction to = null;
|
||||
|
||||
Iterator<RouterTransaction> iterator = backstack.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
RouterTransaction transaction = iterator.next();
|
||||
if (transaction.controller() == controller) {
|
||||
from = transaction;
|
||||
if (iterator.hasNext()) {
|
||||
to = iterator.next();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (from == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ChangeTransaction(
|
||||
to != null ? to.controller() : null,
|
||||
from.controller(),
|
||||
false,
|
||||
container,
|
||||
from.popChangeHandler(),
|
||||
Collections.emptyList()
|
||||
);
|
||||
}
|
||||
|
||||
void watchContainerAttach() {
|
||||
container.post(new Runnable() {
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.bluelinelabs.conductor.internal
|
||||
|
||||
import android.view.View
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
|
||||
class BackGestureViewState(
|
||||
val fromView: View,
|
||||
val toViews: List<BackGestureControllerView>,
|
||||
)
|
||||
|
||||
class BackGestureControllerView(
|
||||
val controller: Controller,
|
||||
val view: View,
|
||||
val inflatedForGesture: Boolean,
|
||||
)
|
||||
+2
-3
@@ -14,7 +14,6 @@ import androidx.savedstate.setViewTreeSavedStateRegistryOwner
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.ControllerChangeType
|
||||
import com.bluelinelabs.conductor.R
|
||||
|
||||
/**
|
||||
* This class sets the [ViewTreeLifecycleOwner] and [ViewTreeSavedStateRegistryOwner] which is
|
||||
@@ -56,8 +55,8 @@ internal class OwnViewTreeLifecycleAndRegistry private constructor(
|
||||
* it on purpose.
|
||||
*/
|
||||
if (
|
||||
view.getTag(R.id.view_tree_lifecycle_owner) == null &&
|
||||
view.getTag(R.id.view_tree_saved_state_registry_owner) == null
|
||||
view.getTag(androidx.lifecycle.runtime.R.id.view_tree_lifecycle_owner) == null &&
|
||||
view.getTag(androidx.savedstate.R.id.view_tree_saved_state_registry_owner) == null
|
||||
) {
|
||||
view.setViewTreeLifecycleOwner(this@OwnViewTreeLifecycleAndRegistry)
|
||||
view.setViewTreeSavedStateRegistryOwner(this@OwnViewTreeLifecycleAndRegistry)
|
||||
|
||||
+6
-4
@@ -27,20 +27,22 @@ android {
|
||||
compose = true
|
||||
}
|
||||
|
||||
compileSdkVersion 33
|
||||
compileSdk 34
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
jvmTarget = "11"
|
||||
}
|
||||
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion libs.versions.compose.compiler.get()
|
||||
}
|
||||
|
||||
namespace "com.bluelinelabs.conductor.demo"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.bluelinelabs.conductor.demo">
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:fullBackupContent="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme"
|
||||
tools:ignore="GoogleAppIndexingWarning">
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
android:fullBackupContent="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme"
|
||||
tools:ignore="GoogleAppIndexingWarning">
|
||||
|
||||
<activity
|
||||
android:name="com.bluelinelabs.conductor.demo.MainActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="com.bluelinelabs.conductor.demo.MainActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
@@ -10,6 +10,7 @@ import android.text.style.URLSpan
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.BackEventCompat
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.content.ContextCompat
|
||||
@@ -18,6 +19,7 @@ import androidx.core.graphics.BlendModeCompat
|
||||
import androidx.core.text.buildSpannedString
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.RouterTransaction
|
||||
import com.bluelinelabs.conductor.asTransaction
|
||||
import com.bluelinelabs.conductor.changehandler.FadeChangeHandler
|
||||
@@ -76,12 +78,13 @@ class HomeController : BaseController(R.layout.controller_home) {
|
||||
}
|
||||
|
||||
private fun onModelRowClick(model: DemoModel, position: Int) {
|
||||
println("onModelRowClick")
|
||||
when (model) {
|
||||
DemoModel.NAVIGATION -> {
|
||||
router.pushController(
|
||||
RouterTransaction.with(NavigationDemoController(0, DisplayUpMode.SHOW_FOR_CHILDREN_ONLY))
|
||||
.pushChangeHandler(FadeChangeHandler())
|
||||
.popChangeHandler(FadeChangeHandler())
|
||||
.pushChangeHandler(WhateverChangeHandler())
|
||||
.popChangeHandler(WhateverChangeHandler())
|
||||
.tag(NavigationDemoController.TAG_UP_TRANSACTION)
|
||||
)
|
||||
}
|
||||
@@ -233,3 +236,47 @@ private class HomeAdapter(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class WhateverChangeHandler : ControllerChangeHandler() {
|
||||
override val enableOnBackGestureCallbacks = true
|
||||
|
||||
override fun handleOnBackStarted(container: ViewGroup, to: View?, from: View, event: BackEventCompat) {
|
||||
println("handleOnBackStarted")
|
||||
to?.let { container.addView(it) }
|
||||
}
|
||||
|
||||
override fun handleOnBackProgressed(container: ViewGroup, to: View?, from: View, event: BackEventCompat) {
|
||||
if (event.swipeEdge == BackEventCompat.EDGE_LEFT) {
|
||||
from.translationX = event.progress * container.width
|
||||
to?.translationX = -container.width + event.progress * container.width
|
||||
} else {
|
||||
from.translationX = -event.progress * container.width
|
||||
to?.translationX = container.width + -event.progress * container.width
|
||||
}
|
||||
}
|
||||
|
||||
override fun handleOnBackCancelled(container: ViewGroup, to: View?, from: View) {
|
||||
to?.let { container.removeView(it) }
|
||||
}
|
||||
|
||||
override fun performChange(
|
||||
container: ViewGroup,
|
||||
from: View?,
|
||||
to: View?,
|
||||
isPush: Boolean,
|
||||
changeListener: ControllerChangeCompletedListener,
|
||||
) {
|
||||
from?.translationX = 0f
|
||||
to?.translationX = 0f
|
||||
println("perform change called")
|
||||
if (isPush) {
|
||||
to?.let { container.addView(it) }
|
||||
from?.let { container.removeView(it) }
|
||||
} else {
|
||||
to?.let { if (it.parent == null) container.addView(it) }
|
||||
from?.let { container.removeView(it) }
|
||||
}
|
||||
|
||||
changeListener.onChangeCompleted()
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
VERSION_CODE=4
|
||||
VERSION_NAME=4.0.0-SNAPSHOT
|
||||
VERSION_NAME=4.0.0-SNAPSHOT-PREDICTIVE
|
||||
android.useAndroidX=true
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
|
||||
|
||||
+21
-26
@@ -1,32 +1,30 @@
|
||||
[versions]
|
||||
minsdk = "16"
|
||||
compilesdk = "33"
|
||||
minsdk = "19"
|
||||
compilesdk = "34"
|
||||
targetsdk = "28"
|
||||
|
||||
agp = "7.4.2" # Note: update lint version whenever this is updated
|
||||
androidx-activity = "1.6.1"
|
||||
androidx-annotation = "1.1.0"
|
||||
androidx-appcompat = "1.4.2"
|
||||
androidx-collection = "1.1.0"
|
||||
androidx-core = "1.3.2"
|
||||
androidx-lifecycle = "2.6.0"
|
||||
androidx-savedstate = "1.2.0"
|
||||
androidx-transition = "1.3.1"
|
||||
agp = "8.1.4" # Note: update lint version whenever this is updated
|
||||
androidx-activity = "1.8.2"
|
||||
androidx-annotation = "1.7.1"
|
||||
androidx-appcompat = "1.6.1"
|
||||
androidx-collection = "1.3.0"
|
||||
androidx-core = "1.12.0"
|
||||
androidx-lifecycle = "2.7.0"
|
||||
androidx-savedstate = "1.2.1"
|
||||
androidx-transition = "1.4.1"
|
||||
androidx-viewpager2 = "1.0.0"
|
||||
autodispose = "1.0.0"
|
||||
compose = "1.3.1"
|
||||
compose-compiler = "1.4.3"
|
||||
dokka = "1.8.10"
|
||||
junit = "4.13"
|
||||
compose = "1.5.4"
|
||||
compose-compiler = "1.5.3"
|
||||
dokka = "1.9.0"
|
||||
junit = "4.13.2"
|
||||
kotest = "4.6.0"
|
||||
kotlin = "1.8.10"
|
||||
leakCanary = "2.7"
|
||||
lint = "30.4.2" # Should always be agp + 23
|
||||
material = "1.2.1"
|
||||
mvnpublish = "0.23.2"
|
||||
kotlin = "1.9.10"
|
||||
leakCanary = "2.12"
|
||||
lint = "31.1.4" # Should always be agp + 23
|
||||
material = "1.11.0"
|
||||
mvnpublish = "0.27.0"
|
||||
picasso = "2.5.2"
|
||||
robolectric = "4.5.1"
|
||||
rxjava2 = "2.1.14"
|
||||
robolectric = "4.11.1"
|
||||
|
||||
[libraries]
|
||||
activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity" }
|
||||
@@ -37,14 +35,12 @@ androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "a
|
||||
androidx-collection = { module = "androidx.collection:collection", version.ref = "androidx-collection" }
|
||||
androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
|
||||
androidx-lifecycle-runtime = { module = "androidx.lifecycle:lifecycle-runtime", version.ref = "androidx-lifecycle" }
|
||||
androidx-lifecycle-livedata-core = { module = "androidx.lifecycle:lifecycle-livedata-core", version.ref = "androidx-lifecycle" }
|
||||
androidx-savedstate-ktx = { module = "androidx.savedstate:savedstate-ktx", version.ref = "androidx-savedstate" }
|
||||
androidx-transition = { module = "androidx.transition:transition", version.ref = "androidx-transition" }
|
||||
androidx-viewpager2 = { module = "androidx.viewpager2:viewpager2", version.ref = "androidx-viewpager2" }
|
||||
compose-foundation = { module = "androidx.compose.foundation:foundation", version.ref = "compose" }
|
||||
compose-ui = { module = "androidx.compose.ui:ui", version.ref = "compose" }
|
||||
compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "compose" }
|
||||
compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview", version.ref = "compose" }
|
||||
compose-material = { module = "androidx.compose.material:material", version.ref = "compose" }
|
||||
dokka = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "dokka" }
|
||||
junit = { module = "junit:junit", version.ref = "junit" }
|
||||
@@ -59,7 +55,6 @@ lint-tests = { module = "com.android.tools.lint:lint-tests", version.ref = "lint
|
||||
material = { module = "com.google.android.material:material", version.ref = "material" }
|
||||
picasso = { module = "com.squareup.picasso:picasso", version.ref = "picasso" }
|
||||
robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectric" }
|
||||
rxjava2 = { module = "io.reactivex.rxjava2:rxjava", version.ref = "rxjava2" }
|
||||
|
||||
[plugins]
|
||||
mvnpublish = { id = "com.vanniktech.maven.publish", version.ref = "mvnpublish" }
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
Reference in New Issue
Block a user