diff --git a/kotlin-extensions/build.gradle b/kotlin-extensions/build.gradle index 007e067..acea491 100644 --- a/kotlin-extensions/build.gradle +++ b/kotlin-extensions/build.gradle @@ -2,6 +2,7 @@ apply from: "../android-configs/lib-config.gradle" dependencies { implementation "androidx.recyclerview:recyclerview" + implementation project(path: ':logging') constraints { implementation("androidx.recyclerview:recyclerview") { diff --git a/kotlin-extensions/src/main/java/ru/touchin/extensions/Context.kt b/kotlin-extensions/src/main/java/ru/touchin/extensions/Context.kt index 54b0f09..aa7b8a2 100644 --- a/kotlin-extensions/src/main/java/ru/touchin/extensions/Context.kt +++ b/kotlin-extensions/src/main/java/ru/touchin/extensions/Context.kt @@ -1,14 +1,17 @@ package ru.touchin.extensions +import android.content.ActivityNotFoundException import android.content.Context import android.content.Intent import android.net.Uri import android.os.Bundle +import ru.touchin.roboswag.core.log.Lc -fun Context.safeStartActivity(intent: Intent, options: Bundle? = null, resolveFlags: Int = 0) = +fun Context.safeStartActivity(intent: Intent, options: Bundle? = null) = try { startActivity(intent, options) - } catch (e: Throwable) { + } catch (e: ActivityNotFoundException) { + Lc.e(e, "Couldn't find activity with this parameters") } fun Context.openBrowser(url: String) = Intent(Intent.ACTION_VIEW) 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 5602cef..48f7085 100644 --- a/kotlin-extensions/src/main/java/ru/touchin/extensions/View.kt +++ b/kotlin-extensions/src/main/java/ru/touchin/extensions/View.kt @@ -2,6 +2,9 @@ package ru.touchin.extensions import android.os.Build import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import androidx.coordinatorlayout.widget.CoordinatorLayout import ru.touchin.utils.ActionThrottler const val RIPPLE_EFFECT_DELAY_MS = 150L @@ -22,3 +25,31 @@ fun View.setOnRippleClickListener(listener: () -> Unit) { setOnClickListener { listener() } } } + + +/** + * Used for finding suitable parent view for snackbar + * Method was taken from com.google.android.material.snackbar.Snackbar.findSuitableParent + */ +fun View?.findSuitableParent(): ViewGroup? { + var view = this + var fallback: ViewGroup? = null + do { + if (view is CoordinatorLayout) { + return view + } else if (view is FrameLayout) { + if (view.id == android.R.id.content) { + return view + } else { + fallback = view + } + } + + if (view != null) { + val parent = view.parent + view = if (parent is View) parent else null + } + } while (view != null) + + return fallback +} diff --git a/mvi-arch/build.gradle b/mvi-arch/build.gradle index 6059357..bfaa0aa 100644 --- a/mvi-arch/build.gradle +++ b/mvi-arch/build.gradle @@ -6,6 +6,7 @@ dependencies { implementation project(":lifecycle") implementation project(":kotlin-extensions") implementation project(":logging") + implementation project(":utils") implementation("androidx.core:core-ktx") implementation("androidx.appcompat:appcompat") diff --git a/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/core/MviFragment.kt b/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/core/MviFragment.kt index e373227..dca3412 100644 --- a/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/core/MviFragment.kt +++ b/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/core/MviFragment.kt @@ -9,7 +9,6 @@ import androidx.annotation.LayoutRes import androidx.annotation.MainThread import androidx.core.os.bundleOf import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentActivity import androidx.lifecycle.Observer import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider @@ -18,6 +17,7 @@ import ru.touchin.roboswag.mvi_arch.di.ViewModelAssistedFactory import ru.touchin.roboswag.mvi_arch.di.ViewModelFactory import ru.touchin.roboswag.mvi_arch.marker.ViewAction import ru.touchin.roboswag.mvi_arch.marker.ViewState +import ru.touchin.roboswag.navigation_base.activities.BaseActivity import ru.touchin.roboswag.navigation_base.fragments.BaseFragment import ru.touchin.roboswag.navigation_base.fragments.EmptyState import javax.inject.Inject @@ -47,7 +47,7 @@ import javax.inject.Inject */ abstract class MviFragment( @LayoutRes layout: Int -) : BaseFragment(layout) +) : BaseFragment(layout) where NavArgs : Parcelable, State : ViewState, Action : ViewAction, diff --git a/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/core/MviKeyboardResizableFragment.kt b/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/core/MviKeyboardResizableFragment.kt new file mode 100644 index 0000000..2d2df30 --- /dev/null +++ b/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/core/MviKeyboardResizableFragment.kt @@ -0,0 +1,96 @@ +package ru.touchin.roboswag.mvi_arch.core + +import android.os.Bundle +import android.os.Parcelable +import android.view.View +import androidx.annotation.LayoutRes +import androidx.lifecycle.LifecycleObserver +import ru.touchin.roboswag.components.utils.hideSoftInput +import ru.touchin.roboswag.mvi_arch.marker.ViewAction +import ru.touchin.roboswag.mvi_arch.marker.ViewState +import ru.touchin.roboswag.navigation_base.activities.OnBackPressedListener + +// CPD-OFF +/** + * Same code as in [ru.touchin.roboswag.navigation_base.keyboard_resizeable.KeyboardResizeableFragment] but inherited from MviFragment + * Used to detect IME events (show, hide) + */ + +abstract class MviKeyboardResizableFragment( + @LayoutRes layout: Int +) : MviFragment(layout) + where NavArgs : Parcelable, + State : ViewState, + Action : ViewAction, + VM : MviViewModel { + + private var isKeyboardVisible: Boolean = false + + private val keyboardHideListener = OnBackPressedListener { + if (isKeyboardVisible) { + activity.hideSoftInput() + true + } else { + false + } + } + + private var isHideKeyboardOnBackEnabled = false + + protected open fun onKeyboardShow(diff: Int = 0) {} + + protected open fun onKeyboardHide() {} + + protected fun hideKeyboardOnBackPressed() { + isHideKeyboardOnBackEnabled = true + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + view.requestApplyInsets() + lifecycle.addObserver(activity.keyboardBehaviorDetector as LifecycleObserver) + } + + override fun onResume() { + super.onResume() + if (isHideKeyboardOnBackEnabled) activity.addOnBackPressedListener(keyboardHideListener) + } + + override fun onPause() { + super.onPause() + notifyKeyboardHidden() + if (isHideKeyboardOnBackEnabled) activity.removeOnBackPressedListener(keyboardHideListener) + } + + override fun onStart() { + super.onStart() + activity.keyboardBehaviorDetector?.apply { + keyboardHideListener = { + if (isKeyboardVisible) { + onKeyboardHide() + } + isKeyboardVisible = false + } + keyboardShowListener = { diff -> + onKeyboardShow(diff) + isKeyboardVisible = true + } + } + } + + override fun onStop() { + super.onStop() + activity.keyboardBehaviorDetector?.apply { + keyboardHideListener = null + keyboardShowListener = null + } + } + + private fun notifyKeyboardHidden() { + if (isKeyboardVisible) onKeyboardHide() + isKeyboardVisible = false + } + +} +// CPD-ON diff --git a/utils/src/main/java/ru/touchin/roboswag/components/utils/spans/SpanUtils.kt b/utils/src/main/java/ru/touchin/roboswag/components/utils/spans/SpanUtils.kt index b69a0cd..6d60745 100644 --- a/utils/src/main/java/ru/touchin/roboswag/components/utils/spans/SpanUtils.kt +++ b/utils/src/main/java/ru/touchin/roboswag/components/utils/spans/SpanUtils.kt @@ -4,7 +4,6 @@ import android.text.SpannableString import android.text.Spanned import android.text.TextPaint import android.text.style.ClickableSpan -import android.text.style.ForegroundColorSpan import android.text.style.URLSpan import android.text.util.Linkify import android.view.View diff --git a/views/src/main/res/font/roboto_bold.ttf b/views/src/main/res/font/roboto_bold.ttf new file mode 100644 index 0000000..d3f01ad Binary files /dev/null and b/views/src/main/res/font/roboto_bold.ttf differ diff --git a/views/src/main/res/font/roboto_regular.ttf b/views/src/main/res/font/roboto_regular.ttf new file mode 100644 index 0000000..2c97eea Binary files /dev/null and b/views/src/main/res/font/roboto_regular.ttf differ