Compare commits

..

1 Commits

Author SHA1 Message Date
Jameson Williams 56bff9a5cf Refine highlighting and error reporting in Lint rules (#693) 2024-04-10 17:00:41 -04:00
25 changed files with 153 additions and 369 deletions
+4 -4
View File
@@ -8,11 +8,11 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: set up JDK 17
- name: set up JDK 11
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '17'
java-version: '11'
- 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 17
- name: set up JDK 11
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '17'
java-version: '11'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Release with Gradle
@@ -18,7 +18,6 @@ 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 =
@@ -32,7 +31,7 @@ public final class ControllerChangeHandlerIssueDetector extends Detector impleme
@Override
public List<Class<? extends UElement>> getApplicableUastTypes() {
return Collections.<Class<? extends UElement>>singletonList(UClass.class);
return Collections.singletonList(UClass.class);
}
@Override
@@ -47,42 +46,41 @@ public final class ControllerChangeHandlerIssueDetector extends Detector impleme
return;
}
final boolean hasSuperType = evaluator.extendsClass(node.getPsi(), CLASS_NAME, true);
final boolean hasSuperType = evaluator.extendsClass(node.getJavaPsi(), 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((UElement) node), message);
context.report(ISSUE, node, context.getLocation(Identify.byName(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((UElement) node), message);
context.report(ISSUE, node, context.getLocation(Identify.byName(node)), message);
return;
}
boolean hasConstructor = false;
UMethod constructor = null;
boolean hasDefaultConstructor = false;
for (UMethod method : node.getMethods()) {
if (method.isConstructor()) {
hasConstructor = true;
if (evaluator.isPublic(method) && method.getUastParameters().size() == 0) {
constructor = method;
if (evaluator.isPublic(method) && method.getUastParameters().isEmpty()) {
hasDefaultConstructor = true;
break;
}
}
}
if (hasConstructor && !hasDefaultConstructor) {
if (constructor != null && !hasDefaultConstructor) {
String message = String.format(
"This ControllerChangeHandler needs to have a public default constructor (`%1$s`)", node.getQualifiedName());
context.report(ISSUE, node, context.getLocation((UElement) node), message);
context.report(ISSUE, node, context.getLocation(Identify.byName(constructor)), message);
}
}
};
}
}
@@ -10,6 +10,7 @@ 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;
@@ -20,7 +21,6 @@ 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,52 +48,53 @@ public final class ControllerIssueDetector extends Detector implements Detector.
return;
}
final boolean hasSuperType = evaluator.extendsClass(node.getPsi(), CLASS_NAME, true);
final boolean hasSuperType = evaluator.extendsClass(node.getJavaPsi(), 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((UElement) node), message);
context.report(ISSUE, node, context.getLocation(Identify.byName(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((UElement) node), message);
context.report(ISSUE, node, context.getLocation(Identify.byName(node)), message);
return;
}
boolean hasConstructor = false;
UMethod constructor = null;
boolean hasDefaultConstructor = false;
boolean hasBundleConstructor = false;
for (UMethod method : node.getMethods()) {
if (method.isConstructor()) {
hasConstructor = true;
constructor = method;
if (evaluator.isPublic(method)) {
List<UParameter> parameters = method.getUastParameters();
if (parameters.size() == 0) {
if (parameters.isEmpty()) {
hasDefaultConstructor = true;
break;
} else if (parameters.size() == 1 &&
(parameters.get(0).getType().equalsToText(SdkConstants.CLASS_BUNDLE)) ||
parameters.get(0).getType().equalsToText("Bundle")) {
hasBundleConstructor = true;
} else if (parameters.size() == 1) {
PsiType type = parameters.get(0).getType();
if (type.equalsToText(SdkConstants.CLASS_BUNDLE) || type.equalsToText("Bundle")) {
hasBundleConstructor = true;
break;
}
}
}
}
}
if (hasConstructor && !hasDefaultConstructor && !hasBundleConstructor) {
if (constructor != null && !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((UElement) node), message);
context.report(ISSUE, node, context.getLocation(Identify.byName(constructor)), message);
}
}
};
}
}
@@ -0,0 +1,15 @@
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;
}
}
@@ -8,15 +8,8 @@ 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 {}"
@@ -63,7 +56,12 @@ public class ControllerChangeHandlerDetectorTest {
.files(controllerChangeHandlerStub, java(source))
.issues(ControllerIssueDetector.ISSUE, ControllerChangeHandlerIssueDetector.ISSUE)
.run()
.expect(CONSTRUCTOR);
.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"
);
}
@Test
@@ -94,7 +92,12 @@ public class ControllerChangeHandlerDetectorTest {
.files(controllerChangeHandlerStub, java(source))
.issues(ControllerIssueDetector.ISSUE, ControllerChangeHandlerIssueDetector.ISSUE)
.run()
.expect(CONSTRUCTOR);
.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"
);
}
@Test
@@ -111,7 +114,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");
}
@@ -131,7 +134,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");
}
}
@@ -8,18 +8,12 @@ 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(
@@ -69,7 +63,12 @@ public class ControllerDetectorTest {
.files(controllerStub, java(source))
.issues(ControllerIssueDetector.ISSUE, ControllerChangeHandlerIssueDetector.ISSUE)
.run()
.expect(CONSTRUCTOR_ERROR);
.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"
);
}
@Test
@@ -106,11 +105,11 @@ public class ControllerDetectorTest {
.files(controllerStub, java(baseClass), java(source))
.issues(ControllerIssueDetector.ISSUE, ControllerChangeHandlerIssueDetector.ISSUE)
.run()
.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"
.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"
);
}
@@ -126,7 +125,12 @@ public class ControllerDetectorTest {
.files(controllerStub, java(source))
.issues(ControllerIssueDetector.ISSUE, ControllerChangeHandlerIssueDetector.ISSUE)
.run()
.expect(CONSTRUCTOR_ERROR);
.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"
);
}
@Test
@@ -4,12 +4,7 @@ plugins {
}
android {
compileSdk libs.versions.compilesdk.get() as Integer
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
compileSdkVersion libs.versions.compilesdk.get() as Integer
defaultConfig {
minSdkVersion libs.versions.minsdk.get()
@@ -17,8 +12,6 @@ android {
versionCode Integer.parseInt(project.VERSION_CODE)
versionName project.VERSION_NAME
}
namespace "com.bluelinelabs.conductor.androidxtransition"
}
dependencies {
@@ -0,0 +1,3 @@
<manifest package="com.bluelinelabs.conductor.androidxtransition">
<application />
</manifest>
+1 -12
View File
@@ -5,16 +5,7 @@ plugins {
}
android {
compileSdk libs.versions.compilesdk.get() as Integer
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
compileSdkVersion libs.versions.compilesdk.get() as Integer
defaultConfig {
minSdkVersion libs.versions.minsdk.get()
@@ -22,8 +13,6 @@ android {
versionCode Integer.parseInt(project.VERSION_CODE)
versionName project.VERSION_NAME
}
namespace "com.bluelinelabs.conductor.viewpager"
}
dependencies {
@@ -0,0 +1,3 @@
<manifest package="com.bluelinelabs.conductor.viewpager">
<application />
</manifest>
+1 -12
View File
@@ -6,16 +6,7 @@ plugins {
}
android {
compileSdk libs.versions.compilesdk.get() as Integer
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
compileSdkVersion libs.versions.compilesdk.get() as Integer
defaultConfig {
minSdkVersion libs.versions.minsdk.get()
@@ -29,8 +20,6 @@ android {
includeAndroidResources = true
}
}
namespace "com.bluelinelabs.conductor.viewpager2"
}
dependencies {
@@ -0,0 +1,3 @@
<manifest package="com.bluelinelabs.conductor.viewpager2">
<application />
</manifest>
+1 -12
View File
@@ -6,16 +6,7 @@ plugins {
}
android {
compileSdk libs.versions.compilesdk.get() as Integer
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
compileSdkVersion libs.versions.compilesdk.get() as Integer
defaultConfig {
minSdkVersion libs.versions.minsdk.get()
@@ -24,8 +15,6 @@ android {
versionName project.VERSION_NAME
consumerProguardFiles 'proguard-rules.txt'
}
namespace "com.bluelinelabs.conductor"
}
dependencies {
+3
View File
@@ -0,0 +1,3 @@
<manifest package="com.bluelinelabs.conductor">
<application />
</manifest>
@@ -8,7 +8,6 @@ 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;
@@ -17,7 +16,6 @@ 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;
@@ -26,8 +24,6 @@ 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;
@@ -101,9 +97,6 @@ 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.
@@ -118,116 +111,6 @@ 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,7 +3,6 @@ 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
@@ -51,8 +50,6 @@ abstract class ControllerChangeHandler {
private var hasBeenUsed = false
open val enableOnBackGestureCallbacks = false
init {
try {
javaClass.getConstructor()
@@ -115,9 +112,9 @@ abstract class ControllerChangeHandler {
*/
open fun copy(): ControllerChangeHandler = fromBundle(toBundle())!!
open fun handleOnBackStarted(container: ViewGroup, to: View?, from: View, event: BackEventCompat) {}
open fun handleOnBackStarted(container: ViewGroup, to: View?, from: View, swipeEdge: Int) {}
open fun handleOnBackProgressed(container: ViewGroup, to: View?, from: View, event: BackEventCompat) {}
open fun handleOnBackProgressed(container: ViewGroup, to: View?, from: View, progress: Float, swipeEdge: Int) {}
open fun handleOnBackCancelled(container: ViewGroup, to: View?, from: View) {}
@@ -804,37 +804,6 @@ 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
@@ -1,15 +0,0 @@
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,
)
@@ -14,6 +14,7 @@ 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
@@ -55,8 +56,8 @@ internal class OwnViewTreeLifecycleAndRegistry private constructor(
* it on purpose.
*/
if (
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.getTag(R.id.view_tree_lifecycle_owner) == null &&
view.getTag(R.id.view_tree_saved_state_registry_owner) == null
) {
view.setViewTreeLifecycleOwner(this@OwnViewTreeLifecycleAndRegistry)
view.setViewTreeSavedStateRegistryOwner(this@OwnViewTreeLifecycleAndRegistry)
+4 -6
View File
@@ -27,22 +27,20 @@ android {
compose = true
}
compileSdk 34
compileSdkVersion 33
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "11"
jvmTarget = "1.8"
}
composeOptions {
kotlinCompilerExtensionVersion libs.versions.compose.compiler.get()
}
namespace "com.bluelinelabs.conductor.demo"
}
dependencies {
+23 -23
View File
@@ -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">
xmlns:tools="http://schemas.android.com/tools"
package="com.bluelinelabs.conductor.demo">
<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:enableOnBackInvokedCallback="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: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,7 +10,6 @@ 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
@@ -19,7 +18,6 @@ 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
@@ -78,13 +76,12 @@ 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(WhateverChangeHandler())
.popChangeHandler(WhateverChangeHandler())
.pushChangeHandler(FadeChangeHandler())
.popChangeHandler(FadeChangeHandler())
.tag(NavigationDemoController.TAG_UP_TRANSACTION)
)
}
@@ -236,47 +233,3 @@ 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
View File
@@ -1,5 +1,5 @@
VERSION_CODE=4
VERSION_NAME=4.0.0-SNAPSHOT-PREDICTIVE
VERSION_NAME=4.0.0-SNAPSHOT
android.useAndroidX=true
org.gradle.jvmargs=-Xmx1536m
+26 -21
View File
@@ -1,30 +1,32 @@
[versions]
minsdk = "19"
compilesdk = "34"
minsdk = "16"
compilesdk = "33"
targetsdk = "28"
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"
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"
androidx-viewpager2 = "1.0.0"
compose = "1.5.4"
compose-compiler = "1.5.3"
dokka = "1.9.0"
junit = "4.13.2"
autodispose = "1.0.0"
compose = "1.3.1"
compose-compiler = "1.4.3"
dokka = "1.8.10"
junit = "4.13"
kotest = "4.6.0"
kotlin = "1.9.10"
leakCanary = "2.12"
lint = "31.1.4" # Should always be agp + 23
material = "1.11.0"
mvnpublish = "0.27.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"
picasso = "2.5.2"
robolectric = "4.11.1"
robolectric = "4.5.1"
rxjava2 = "2.1.14"
[libraries]
activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity" }
@@ -35,12 +37,14 @@ 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" }
@@ -55,6 +59,7 @@ 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
View File
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists