Merge branch 'master' into vtb/fix-inner-navigation
This commit is contained in:
commit
98acd9af0c
|
|
@ -7,8 +7,6 @@ Roboswag - библиотека решений, ускоряющих разра
|
|||
* Andoroid Api: 19
|
||||
* Kotlin: 1.3.11
|
||||
* Gradle: 3.2.1
|
||||
* Gradle CPD Plugin: 1.1
|
||||
* Detekt Plugin: 1.0.0-RC12
|
||||
|
||||
## Основная архитектура
|
||||
За основу архитектуры взят подход от Google - MVVM на основе [Android Architecture Components](https://developer.android.com/jetpack/docs/guide). Данный подход популярен в сообществе Android разработки, позволяет разбивать код на мелкие и независимые части, что ускоряет разработку и последующую поддержку приложения.
|
||||
|
|
@ -22,10 +20,6 @@ Roboswag позволяет сочетать эти три решения в о
|
|||
## Основные инструменты библиотеки
|
||||
### Работа с RecyclerView
|
||||
RecyclerView - один из самых часто используемых инструментов Android разработчика. Модуль [recyclerview-adapters](/recyclerview-adapters) позволяет сделать работу с RecyclerView более гибкой и делает работу самого элемента быстрее.
|
||||
### BuildScripts
|
||||
[BuildScrpts](https://github.com/TouchInstinct/BuildScripts) - набор скриптов, автоматизирующих разработку. Один из главных скриптов - staticAnalysis - инструмент для автоматической проверки кода на соответствие правилам компании.
|
||||
### Api Generator
|
||||
Внутренний инструмент компании Touch Instinct для генерации общего кода на разные платформы - Android, iOS и Server. Описанные в одном месте общие классы и Http методы используются на разных платформах. Данный инструмент позволяет сократить время разработки в два раза.
|
||||
### Работа с SharedPreferences
|
||||
Чтобы сохранять простые данные в память смартфона, используются SharedPreferences. Модуль [storable](/storable) разработан для облегчения работы с SharedPreferences.
|
||||
### Утилиты и extension функции
|
||||
|
|
|
|||
20
build.gradle
20
build.gradle
|
|
@ -1,5 +1,4 @@
|
|||
buildscript {
|
||||
ext.kotlin_version = '1.3.50'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
|
|
@ -24,22 +23,3 @@ allprojects {
|
|||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
|
||||
ext {
|
||||
versions = [
|
||||
compileSdk : 29,
|
||||
appcompat : '1.0.2',
|
||||
androidx : '1.0.0',
|
||||
material : '1.0.0',
|
||||
lifecycle : '2.0.0',
|
||||
dagger : '2.17',
|
||||
retrofit : '2.4.0',
|
||||
rxJava : '2.2.2',
|
||||
rxAndroid : '2.1.0',
|
||||
crashlytics : '2.9.5',
|
||||
location : '16.0.0',
|
||||
coreKtx : '1.0.1',
|
||||
yandex_mapkit: '3.4.0',
|
||||
google_maps : '16.1.0'
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package ru.touchin.lifecycle.viewmodel
|
||||
|
||||
import android.os.Looper
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.Flowable
|
||||
|
|
@ -13,7 +14,7 @@ import ru.touchin.lifecycle.event.Event
|
|||
class BaseLiveDataDispatcher(private val destroyable: BaseDestroyable = BaseDestroyable()) : LiveDataDispatcher, Destroyable by destroyable {
|
||||
|
||||
override fun <T> Flowable<out T>.dispatchTo(liveData: MutableLiveData<ContentEvent<T>>): Disposable {
|
||||
liveData.value = ContentEvent.Loading(liveData.value?.data)
|
||||
liveData.setLoadingEvent()
|
||||
return untilDestroy(
|
||||
{ data -> liveData.value = ContentEvent.Success(data) },
|
||||
{ throwable -> liveData.value = ContentEvent.Error(throwable, liveData.value?.data) },
|
||||
|
|
@ -21,7 +22,7 @@ class BaseLiveDataDispatcher(private val destroyable: BaseDestroyable = BaseDest
|
|||
}
|
||||
|
||||
override fun <T> Observable<out T>.dispatchTo(liveData: MutableLiveData<ContentEvent<T>>): Disposable {
|
||||
liveData.value = ContentEvent.Loading(liveData.value?.data)
|
||||
liveData.setLoadingEvent()
|
||||
return untilDestroy(
|
||||
{ data -> liveData.value = ContentEvent.Success(data) },
|
||||
{ throwable -> liveData.value = ContentEvent.Error(throwable, liveData.value?.data) },
|
||||
|
|
@ -29,14 +30,14 @@ class BaseLiveDataDispatcher(private val destroyable: BaseDestroyable = BaseDest
|
|||
}
|
||||
|
||||
override fun <T> Single<out T>.dispatchTo(liveData: MutableLiveData<ContentEvent<T>>): Disposable {
|
||||
liveData.value = ContentEvent.Loading(liveData.value?.data)
|
||||
liveData.setLoadingEvent()
|
||||
return untilDestroy(
|
||||
{ data -> liveData.value = ContentEvent.Success(data) },
|
||||
{ throwable -> liveData.value = ContentEvent.Error(throwable, liveData.value?.data) })
|
||||
}
|
||||
|
||||
override fun <T> Maybe<out T>.dispatchTo(liveData: MutableLiveData<ContentEvent<T>>): Disposable {
|
||||
liveData.value = ContentEvent.Loading(liveData.value?.data)
|
||||
liveData.setLoadingEvent()
|
||||
return untilDestroy(
|
||||
{ data -> liveData.value = ContentEvent.Success(data) },
|
||||
{ throwable -> liveData.value = ContentEvent.Error(throwable, liveData.value?.data) },
|
||||
|
|
@ -44,10 +45,29 @@ class BaseLiveDataDispatcher(private val destroyable: BaseDestroyable = BaseDest
|
|||
}
|
||||
|
||||
override fun Completable.dispatchTo(liveData: MutableLiveData<Event>): Disposable {
|
||||
liveData.value = Event.Loading
|
||||
liveData.setLoadingEvent()
|
||||
return untilDestroy(
|
||||
{ liveData.value = Event.Complete },
|
||||
{ throwable -> liveData.value = Event.Error(throwable) })
|
||||
}
|
||||
|
||||
private fun <T> MutableLiveData<ContentEvent<T>>.setLoadingEvent() {
|
||||
val loadingContent = ContentEvent.Loading(this.value?.data)
|
||||
if (Looper.getMainLooper().thread == Thread.currentThread()) {
|
||||
this.value = loadingContent
|
||||
} else {
|
||||
this.postValue(loadingContent)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmName("setCompletableLoadingEvent")
|
||||
private fun MutableLiveData<Event>.setLoadingEvent() {
|
||||
val loadingContent = Event.Loading
|
||||
if (Looper.getMainLooper().thread == Thread.currentThread()) {
|
||||
this.value = loadingContent
|
||||
} else {
|
||||
this.postValue(loadingContent)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@ android {
|
|||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ dependencies {
|
|||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
|
||||
implementation "androidx.appcompat:appcompat:$versions.appcompat"
|
||||
|
||||
|
||||
implementation("com.crashlytics.sdk.android:crashlytics:$versions.crashlytics@aar") {
|
||||
transitive = true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ class BottomNavigationController(
|
|||
|
||||
fun detach() = callback?.let(fragmentManager::unregisterFragmentLifecycleCallbacks)
|
||||
|
||||
@Suppress("detekt.ComplexMethod")
|
||||
fun navigateTo(@IdRes itemId: Int, state: Parcelable? = null) {
|
||||
// Find view controller class that needs to open
|
||||
val (viewControllerClass, defaultViewControllerState, saveStateOnSwitching) = viewControllers[itemId] ?: return
|
||||
|
|
|
|||
|
|
@ -13,8 +13,9 @@ fun String.getSpannedTextWithUrls(
|
|||
removeUnderline: Boolean = true,
|
||||
flags: Int = HtmlCompat.FROM_HTML_MODE_COMPACT
|
||||
): Spanned {
|
||||
|
||||
val spannableText = SpannableString(HtmlCompat.fromHtml(this, flags))
|
||||
// HtmlCompat.fromHtml doesn't respect line breaks
|
||||
val text = this.replace(lineBreakRegex, "<br/>")
|
||||
val spannableText = SpannableString(HtmlCompat.fromHtml(text, flags))
|
||||
|
||||
// Linkify removes all previous URLSpan's, we need to save all created spans for reapply after Linkify
|
||||
val spans = spannableText.getUrlSpans()
|
||||
|
|
@ -38,6 +39,10 @@ fun String.getSpannedTextWithUrls(
|
|||
return spannableText
|
||||
}
|
||||
|
||||
private val lineBreakRegex by lazy(LazyThreadSafetyMode.NONE) {
|
||||
"\r?\n".toRegex()
|
||||
}
|
||||
|
||||
private fun SpannableString.getUrlSpans() = getSpans(0, length, URLSpan::class.java)
|
||||
.map { UrlSpanWithBorders(it, this.getSpanStart(it), this.getSpanEnd(it)) }
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue