From e03381b937f19ceeadb3fbd1d6080356b97187b0 Mon Sep 17 00:00:00 2001 From: Daniil Borisovskii Date: Mon, 13 Apr 2020 20:17:38 +0300 Subject: [PATCH 1/8] Add throttling in `View.setOnRippleClickListener()` implementation to prevent multiple actions during ripple delay --- .../main/java/ru/touchin/extensions/View.kt | 9 +++++-- .../java/ru/touchin/utils/ActionThrottler.kt | 26 +++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 kotlin-extensions/src/main/java/ru/touchin/utils/ActionThrottler.kt diff --git a/kotlin-extensions/src/main/java/ru/touchin/extensions/View.kt b/kotlin-extensions/src/main/java/ru/touchin/extensions/View.kt index d6e2920..41217ce 100644 --- a/kotlin-extensions/src/main/java/ru/touchin/extensions/View.kt +++ b/kotlin-extensions/src/main/java/ru/touchin/extensions/View.kt @@ -2,8 +2,9 @@ package ru.touchin.extensions import android.os.Build import android.view.View +import ru.touchin.utils.ActionThrottler -private const val RIPPLE_EFFECT_DELAY = 150L +const val RIPPLE_EFFECT_DELAY = 150L /** * Sets click listener to view. On click it will call something after delay. @@ -12,7 +13,11 @@ private const val RIPPLE_EFFECT_DELAY = 150L */ fun View.setOnRippleClickListener(listener: () -> Unit) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - setOnClickListener { postDelayed({ if (hasWindowFocus()) listener() }, RIPPLE_EFFECT_DELAY) } + setOnClickListener { + ActionThrottler.throttleAction { + postDelayed({ if (hasWindowFocus()) listener() }, RIPPLE_EFFECT_DELAY) + } + } } else { setOnClickListener { listener() } } diff --git a/kotlin-extensions/src/main/java/ru/touchin/utils/ActionThrottler.kt b/kotlin-extensions/src/main/java/ru/touchin/utils/ActionThrottler.kt new file mode 100644 index 0000000..830e89e --- /dev/null +++ b/kotlin-extensions/src/main/java/ru/touchin/utils/ActionThrottler.kt @@ -0,0 +1,26 @@ +package ru.touchin.utils + +import android.os.SystemClock +import ru.touchin.extensions.RIPPLE_EFFECT_DELAY + +object ActionThrottler { + + private const val DELAY = 2 * RIPPLE_EFFECT_DELAY + private var lastActionTime = 0L + + fun throttleAction(action: () -> Unit): Boolean { + val currentTime = SystemClock.elapsedRealtime() + val diff = currentTime - lastActionTime + + return if (diff >= DELAY) { + lastActionTime = currentTime + action.invoke() + true + } else { + false + } + } + +} + + From 2df5e2e3c37ddd7da1f7010aa47526f9b152c474 Mon Sep 17 00:00:00 2001 From: Daniil Borisovskii Date: Mon, 13 Apr 2020 20:42:12 +0300 Subject: [PATCH 2/8] Add explaining comment in `ActionThrottler` --- .../src/main/java/ru/touchin/utils/ActionThrottler.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kotlin-extensions/src/main/java/ru/touchin/utils/ActionThrottler.kt b/kotlin-extensions/src/main/java/ru/touchin/utils/ActionThrottler.kt index 830e89e..f0bc035 100644 --- a/kotlin-extensions/src/main/java/ru/touchin/utils/ActionThrottler.kt +++ b/kotlin-extensions/src/main/java/ru/touchin/utils/ActionThrottler.kt @@ -5,6 +5,8 @@ import ru.touchin.extensions.RIPPLE_EFFECT_DELAY object ActionThrottler { + // Multiplied by 2 because in interval after ripple effect finish and before + // action invoking start user may be in time to click and launch action again private const val DELAY = 2 * RIPPLE_EFFECT_DELAY private var lastActionTime = 0L From 8b2c061528fcfbdc3ab85d81afd08e390e753717 Mon Sep 17 00:00:00 2001 From: Daniil Borisovskii Date: Tue, 14 Apr 2020 13:41:51 +0300 Subject: [PATCH 3/8] Fixed comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/TouchInstinct/RoboSwag/pull/121#discussion_r408021807 – prevention of click again coefficient extracted into a value https://github.com/TouchInstinct/RoboSwag/pull/121#discussion_r408025993 – empty line removed https://github.com/TouchInstinct/RoboSwag/pull/121#discussion_r408027482 – "MS" posfix was added to delay constants --- .../src/main/java/ru/touchin/extensions/View.kt | 4 ++-- .../src/main/java/ru/touchin/utils/ActionThrottler.kt | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/kotlin-extensions/src/main/java/ru/touchin/extensions/View.kt b/kotlin-extensions/src/main/java/ru/touchin/extensions/View.kt index 41217ce..5602cef 100644 --- a/kotlin-extensions/src/main/java/ru/touchin/extensions/View.kt +++ b/kotlin-extensions/src/main/java/ru/touchin/extensions/View.kt @@ -4,7 +4,7 @@ import android.os.Build import android.view.View import ru.touchin.utils.ActionThrottler -const val RIPPLE_EFFECT_DELAY = 150L +const val RIPPLE_EFFECT_DELAY_MS = 150L /** * Sets click listener to view. On click it will call something after delay. @@ -15,7 +15,7 @@ fun View.setOnRippleClickListener(listener: () -> Unit) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { setOnClickListener { ActionThrottler.throttleAction { - postDelayed({ if (hasWindowFocus()) listener() }, RIPPLE_EFFECT_DELAY) + postDelayed({ if (hasWindowFocus()) listener() }, RIPPLE_EFFECT_DELAY_MS) } } } else { diff --git a/kotlin-extensions/src/main/java/ru/touchin/utils/ActionThrottler.kt b/kotlin-extensions/src/main/java/ru/touchin/utils/ActionThrottler.kt index f0bc035..8721e60 100644 --- a/kotlin-extensions/src/main/java/ru/touchin/utils/ActionThrottler.kt +++ b/kotlin-extensions/src/main/java/ru/touchin/utils/ActionThrottler.kt @@ -1,20 +1,21 @@ package ru.touchin.utils import android.os.SystemClock -import ru.touchin.extensions.RIPPLE_EFFECT_DELAY +import ru.touchin.extensions.RIPPLE_EFFECT_DELAY_MS object ActionThrottler { - // Multiplied by 2 because in interval after ripple effect finish and before + // It is necessary because in interval after ripple effect finish and before // action invoking start user may be in time to click and launch action again - private const val DELAY = 2 * RIPPLE_EFFECT_DELAY + private const val PREVENTION_OF_CLICK_AGAIN_COEFFICIENT = 2 + private const val DELAY_MS = PREVENTION_OF_CLICK_AGAIN_COEFFICIENT * RIPPLE_EFFECT_DELAY_MS private var lastActionTime = 0L fun throttleAction(action: () -> Unit): Boolean { val currentTime = SystemClock.elapsedRealtime() val diff = currentTime - lastActionTime - return if (diff >= DELAY) { + return if (diff >= DELAY_MS) { lastActionTime = currentTime action.invoke() true @@ -24,5 +25,3 @@ object ActionThrottler { } } - - From f602f9ce13804b18c687361c6f7dbcba97918e8f Mon Sep 17 00:00:00 2001 From: Daniil Shevtsov Date: Fri, 17 Apr 2020 14:03:09 +0300 Subject: [PATCH 4/8] lifecycle: add toLiveData extension for easy immutable live data fields creation --- .../java/ru/touchin/lifecycle/extensions/ImmutableExt.kt | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 lifecycle/src/main/java/ru/touchin/lifecycle/extensions/ImmutableExt.kt diff --git a/lifecycle/src/main/java/ru/touchin/lifecycle/extensions/ImmutableExt.kt b/lifecycle/src/main/java/ru/touchin/lifecycle/extensions/ImmutableExt.kt new file mode 100644 index 0000000..1449ad7 --- /dev/null +++ b/lifecycle/src/main/java/ru/touchin/lifecycle/extensions/ImmutableExt.kt @@ -0,0 +1,6 @@ +package ru.touchin.lifecycle.extensions + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData + +fun MutableLiveData.toLiveData() = this as LiveData From 98c7f33e277858579a048250e1ef873c06120eac Mon Sep 17 00:00:00 2001 From: Daniil Shevtsov Date: Fri, 17 Apr 2020 14:15:49 +0300 Subject: [PATCH 5/8] Rename toLiveData to toImmutable --- .../main/java/ru/touchin/lifecycle/extensions/ImmutableExt.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lifecycle/src/main/java/ru/touchin/lifecycle/extensions/ImmutableExt.kt b/lifecycle/src/main/java/ru/touchin/lifecycle/extensions/ImmutableExt.kt index 1449ad7..a4c1873 100644 --- a/lifecycle/src/main/java/ru/touchin/lifecycle/extensions/ImmutableExt.kt +++ b/lifecycle/src/main/java/ru/touchin/lifecycle/extensions/ImmutableExt.kt @@ -3,4 +3,4 @@ package ru.touchin.lifecycle.extensions import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -fun MutableLiveData.toLiveData() = this as LiveData +fun MutableLiveData.toImmutable() = this as LiveData From 7ef5facf2ec144a405206378d14916a659db513e Mon Sep 17 00:00:00 2001 From: alex Date: Fri, 24 Apr 2020 15:48:06 +0300 Subject: [PATCH 6/8] removed butterknife from base fragment --- navigation-new/build.gradle | 3 --- .../navigation_new/fragments/BaseFragment.kt | 10 ---------- 2 files changed, 13 deletions(-) diff --git a/navigation-new/build.gradle b/navigation-new/build.gradle index c53d4a0..64af432 100644 --- a/navigation-new/build.gradle +++ b/navigation-new/build.gradle @@ -32,9 +32,6 @@ dependencies { implementation "androidx.fragment:fragment:$versions.fragment" implementation "androidx.fragment:fragment-ktx:$versions.fragment" - implementation "com.jakewharton:butterknife:$versions.butterknife" - kapt "com.jakewharton:butterknife-compiler:$versions.butterknife" - implementation("com.crashlytics.sdk.android:crashlytics:$versions.crashlytics@aar") { transitive = true } diff --git a/navigation-new/src/main/java/ru/touchin/roboswag/components/navigation_new/fragments/BaseFragment.kt b/navigation-new/src/main/java/ru/touchin/roboswag/components/navigation_new/fragments/BaseFragment.kt index 830952a..a1c1128 100644 --- a/navigation-new/src/main/java/ru/touchin/roboswag/components/navigation_new/fragments/BaseFragment.kt +++ b/navigation-new/src/main/java/ru/touchin/roboswag/components/navigation_new/fragments/BaseFragment.kt @@ -15,8 +15,6 @@ import androidx.annotation.LayoutRes import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity -import butterknife.ButterKnife -import butterknife.Unbinder import ru.touchin.roboswag.components.navigation_new.BuildConfig import ru.touchin.roboswag.components.navigation.viewcontrollers.LifecycleLoggingObserver @@ -55,8 +53,6 @@ open class BaseFragment(@Layo protected lateinit var state: TState private set - private lateinit var butterKnifeUnbinder: Unbinder - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -75,12 +71,6 @@ open class BaseFragment(@Layo super.onViewCreated(view, savedInstanceState) lifecycle.addObserver(LifecycleLoggingObserver(this)) - butterKnifeUnbinder = ButterKnife.bind(this, view) - } - - override fun onDestroyView() { - butterKnifeUnbinder.unbind() - super.onDestroyView() } override fun onSaveInstanceState(outState: Bundle) { From fa759e60ccbf016965377edd5e23abf4af02ff18 Mon Sep 17 00:00:00 2001 From: Daniil Borisovskii Date: Mon, 27 Apr 2020 11:16:38 +0300 Subject: [PATCH 7/8] Added module 'rx-extensions' --- rx-extensions/.gitignore | 1 + rx-extensions/build.gradle | 6 ++++++ rx-extensions/src/main/AndroidManifest.xml | 2 ++ 3 files changed, 9 insertions(+) create mode 100644 rx-extensions/.gitignore create mode 100644 rx-extensions/build.gradle create mode 100644 rx-extensions/src/main/AndroidManifest.xml diff --git a/rx-extensions/.gitignore b/rx-extensions/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/rx-extensions/.gitignore @@ -0,0 +1 @@ +/build diff --git a/rx-extensions/build.gradle b/rx-extensions/build.gradle new file mode 100644 index 0000000..3b49d3c --- /dev/null +++ b/rx-extensions/build.gradle @@ -0,0 +1,6 @@ +apply plugin: 'kotlin' + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation "io.reactivex.rxjava2:rxjava:$versions.rxJava" +} diff --git a/rx-extensions/src/main/AndroidManifest.xml b/rx-extensions/src/main/AndroidManifest.xml new file mode 100644 index 0000000..afb773f --- /dev/null +++ b/rx-extensions/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + From 4597623cbffca9cba5797fec651be97d2ddc0f14 Mon Sep 17 00:00:00 2001 From: Daniil Borisovskii Date: Mon, 27 Apr 2020 11:18:02 +0300 Subject: [PATCH 8/8] Added extensions 'emitAfter()' to main RxJava types --- .../src/main/java/ru/touchin/extensions/rx/Flowable.kt | 8 ++++++++ .../src/main/java/ru/touchin/extensions/rx/Maybe.kt | 8 ++++++++ .../src/main/java/ru/touchin/extensions/rx/Observable.kt | 8 ++++++++ .../src/main/java/ru/touchin/extensions/rx/Single.kt | 8 ++++++++ 4 files changed, 32 insertions(+) create mode 100644 rx-extensions/src/main/java/ru/touchin/extensions/rx/Flowable.kt create mode 100644 rx-extensions/src/main/java/ru/touchin/extensions/rx/Maybe.kt create mode 100644 rx-extensions/src/main/java/ru/touchin/extensions/rx/Observable.kt create mode 100644 rx-extensions/src/main/java/ru/touchin/extensions/rx/Single.kt diff --git a/rx-extensions/src/main/java/ru/touchin/extensions/rx/Flowable.kt b/rx-extensions/src/main/java/ru/touchin/extensions/rx/Flowable.kt new file mode 100644 index 0000000..043cf09 --- /dev/null +++ b/rx-extensions/src/main/java/ru/touchin/extensions/rx/Flowable.kt @@ -0,0 +1,8 @@ +package ru.touchin.extensions.rx + +import io.reactivex.Completable +import io.reactivex.Flowable + +fun Flowable.emitAfter(other: Completable): Flowable = this.flatMap { value -> + other.andThen(Flowable.just(value)) +} diff --git a/rx-extensions/src/main/java/ru/touchin/extensions/rx/Maybe.kt b/rx-extensions/src/main/java/ru/touchin/extensions/rx/Maybe.kt new file mode 100644 index 0000000..5f5fe6c --- /dev/null +++ b/rx-extensions/src/main/java/ru/touchin/extensions/rx/Maybe.kt @@ -0,0 +1,8 @@ +package ru.touchin.extensions.rx + +import io.reactivex.Completable +import io.reactivex.Maybe + +fun Maybe.emitAfter(other: Completable): Maybe = this.flatMap { value -> + other.andThen(Maybe.just(value)) +} diff --git a/rx-extensions/src/main/java/ru/touchin/extensions/rx/Observable.kt b/rx-extensions/src/main/java/ru/touchin/extensions/rx/Observable.kt new file mode 100644 index 0000000..0c5a8c5 --- /dev/null +++ b/rx-extensions/src/main/java/ru/touchin/extensions/rx/Observable.kt @@ -0,0 +1,8 @@ +package ru.touchin.extensions.rx + +import io.reactivex.Completable +import io.reactivex.Observable + +fun Observable.emitAfter(other: Completable): Observable = this.flatMap { value -> + other.andThen(Observable.just(value)) +} diff --git a/rx-extensions/src/main/java/ru/touchin/extensions/rx/Single.kt b/rx-extensions/src/main/java/ru/touchin/extensions/rx/Single.kt new file mode 100644 index 0000000..9c3b6c7 --- /dev/null +++ b/rx-extensions/src/main/java/ru/touchin/extensions/rx/Single.kt @@ -0,0 +1,8 @@ +package ru.touchin.extensions.rx + +import io.reactivex.Completable +import io.reactivex.Single + +fun Single.emitAfter(other: Completable): Single = this.flatMap { value -> + other.andThen(Single.just(value)) +}