Code for New Husky
This commit is contained in:
parent
603557d90d
commit
de86283212
16 changed files with 112 additions and 52 deletions
|
@ -185,6 +185,7 @@ android {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(dir: "libs", include: ["*.jar", "*.aar"])
|
implementation fileTree(dir: "libs", include: ["*.jar", "*.aar"])
|
||||||
|
|
||||||
|
// AndroidX dependencies
|
||||||
implementation deps.androidx.appCompat
|
implementation deps.androidx.appCompat
|
||||||
implementation deps.androidx.browser
|
implementation deps.androidx.browser
|
||||||
implementation deps.androidx.cardView
|
implementation deps.androidx.cardView
|
||||||
|
@ -210,32 +211,43 @@ dependencies {
|
||||||
implementation deps.androidx.lifecycle.reactiveStreamsKtx
|
implementation deps.androidx.lifecycle.reactiveStreamsKtx
|
||||||
implementation deps.androidx.lifecycle.viewmodelKtx
|
implementation deps.androidx.lifecycle.viewmodelKtx
|
||||||
|
|
||||||
|
// Dagger dependencies
|
||||||
implementation deps.dagger.dagger
|
implementation deps.dagger.dagger
|
||||||
implementation deps.dagger.daggerAndroid
|
implementation deps.dagger.daggerAndroid
|
||||||
kapt deps.dagger.daggerCompiler
|
kapt deps.dagger.daggerCompiler
|
||||||
kapt deps.dagger.daggerProcessor
|
kapt deps.dagger.daggerProcessor
|
||||||
implementation deps.dagger.daggerSupport
|
implementation deps.dagger.daggerSupport
|
||||||
|
|
||||||
|
// Glide dependencies
|
||||||
implementation deps.glide.glide
|
implementation deps.glide.glide
|
||||||
kapt deps.glide.glideCompiler
|
kapt deps.glide.glideCompiler
|
||||||
implementation deps.glide.glideImage
|
implementation deps.glide.glideImage
|
||||||
implementation deps.glide.glideImageViewFactory
|
implementation deps.glide.glideImageViewFactory
|
||||||
implementation deps.glide.glideOkhttp
|
implementation deps.glide.glideOkhttp
|
||||||
|
|
||||||
|
// Google dependencies
|
||||||
implementation deps.google.flexbox
|
implementation deps.google.flexbox
|
||||||
implementation deps.google.exoplayer
|
implementation deps.google.exoplayer
|
||||||
implementation deps.google.materialDesign
|
implementation deps.google.materialDesign
|
||||||
|
|
||||||
|
// Kotlin dependencies
|
||||||
implementation deps.kotlin.stdlib
|
implementation deps.kotlin.stdlib
|
||||||
implementation deps.kotlin.stdlibJdk
|
implementation deps.kotlin.stdlibJdk
|
||||||
|
|
||||||
|
// KotlinX dependencies
|
||||||
|
implementation deps.kotlinx.coroutinesCore
|
||||||
|
implementation deps.kotlinx.coroutinesAndroid
|
||||||
|
|
||||||
|
// RxJava dependencies
|
||||||
implementation deps.rxjava.rxAndroid
|
implementation deps.rxjava.rxAndroid
|
||||||
implementation deps.rxjava.rxJava
|
implementation deps.rxjava.rxJava
|
||||||
implementation deps.rxjava.rxKotlin
|
implementation deps.rxjava.rxKotlin
|
||||||
|
|
||||||
|
// simple-stack dependencies
|
||||||
implementation deps.simplestack.ext
|
implementation deps.simplestack.ext
|
||||||
implementation deps.simplestack.lib
|
implementation deps.simplestack.lib
|
||||||
|
|
||||||
|
// Square dependencies
|
||||||
implementation deps.square.retrofit
|
implementation deps.square.retrofit
|
||||||
implementation deps.square.retrofitAdapterRxJ2
|
implementation deps.square.retrofitAdapterRxJ2
|
||||||
implementation deps.square.retrofitConvGson
|
implementation deps.square.retrofitConvGson
|
||||||
|
@ -243,6 +255,7 @@ dependencies {
|
||||||
implementation deps.square.okhttp
|
implementation deps.square.okhttp
|
||||||
implementation deps.square.okhttpBrotli
|
implementation deps.square.okhttpBrotli
|
||||||
|
|
||||||
|
// Other dependencies
|
||||||
implementation deps.acraMail
|
implementation deps.acraMail
|
||||||
implementation deps.acraNotification
|
implementation deps.acraNotification
|
||||||
implementation deps.androidImageCropper
|
implementation deps.androidImageCropper
|
||||||
|
@ -260,6 +273,7 @@ dependencies {
|
||||||
implementation deps.sparkButton
|
implementation deps.sparkButton
|
||||||
implementation deps.timber
|
implementation deps.timber
|
||||||
|
|
||||||
|
// Testing dependencies
|
||||||
testImplementation deps.testing.extJunit
|
testImplementation deps.testing.extJunit
|
||||||
testImplementation deps.testing.junit
|
testImplementation deps.testing.junit
|
||||||
testImplementation deps.testing.mockitoInline
|
testImplementation deps.testing.mockitoInline
|
||||||
|
|
|
@ -5,11 +5,10 @@ import com.zhuinden.simplestack.GlobalServices
|
||||||
|
|
||||||
class HuskyServices(private val appContext: Context) {
|
class HuskyServices(private val appContext: Context) {
|
||||||
|
|
||||||
fun getGlobalServices() : GlobalServices {
|
fun getGlobalServices(): GlobalServices {
|
||||||
val builder = GlobalServices.builder()
|
val builder = GlobalServices.builder()
|
||||||
|
|
||||||
with(builder) {
|
with(builder) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.build()
|
return builder.build()
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.husky.project.core.extensions
|
||||||
|
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
|
||||||
|
fun Job?.cancelIfActive() {
|
||||||
|
if(this?.isActive == true) {
|
||||||
|
this.cancel()
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,7 +17,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.keylesspalace.tusky.core.extensions
|
package com.husky.project.core.extensions
|
||||||
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
|
@ -26,7 +26,6 @@ import androidx.lifecycle.Observer
|
||||||
fun <T : Any, L : LiveData<T>> Fragment.viewObserve(liveData: L, body: (T?) -> Unit) =
|
fun <T : Any, L : LiveData<T>> Fragment.viewObserve(liveData: L, body: (T?) -> Unit) =
|
||||||
liveData.observe(viewLifecycleOwner, Observer(body))
|
liveData.observe(viewLifecycleOwner, Observer(body))
|
||||||
|
|
||||||
// TODO: When Failure class is ready
|
|
||||||
/*fun <L : LiveData<Failure>> Fragment.viewFailureObserve(
|
/*fun <L : LiveData<Failure>> Fragment.viewFailureObserve(
|
||||||
liveData: L,
|
liveData: L,
|
||||||
body: (Failure?) -> Unit
|
body: (Failure?) -> Unit
|
||||||
|
|
|
@ -22,9 +22,11 @@ package com.husky.project.core.navigation
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.husky.project.core.di.HuskyServices
|
import com.husky.project.core.di.HuskyServices
|
||||||
|
import com.husky.project.core.ui.fragment.BaseFragment
|
||||||
|
import com.husky.project.core.ui.navigation.BaseKey
|
||||||
|
import com.husky.project.features.splash.view.navigation.SplashKey
|
||||||
import com.keylesspalace.tusky.core.extensions.viewBinding
|
import com.keylesspalace.tusky.core.extensions.viewBinding
|
||||||
import com.keylesspalace.tusky.databinding.ActivityNavigationBinding
|
import com.keylesspalace.tusky.databinding.ActivityNavigationBinding
|
||||||
import com.husky.project.features.splash.view.navigation.SplashKey
|
|
||||||
import com.zhuinden.simplestack.History
|
import com.zhuinden.simplestack.History
|
||||||
import com.zhuinden.simplestack.SimpleStateChanger
|
import com.zhuinden.simplestack.SimpleStateChanger
|
||||||
import com.zhuinden.simplestack.StateChange
|
import com.zhuinden.simplestack.StateChange
|
||||||
|
@ -47,10 +49,16 @@ class NavigationActivity : AppCompatActivity(), SimpleStateChanger.NavigationHan
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed() {
|
override fun onBackPressed() {
|
||||||
if(!backstack.goBack()) {
|
val currentFragment = supportFragmentManager.findFragmentByTag(
|
||||||
Timber.i("No keys found, exiting the application...")
|
backstack.top<BaseKey>().fragmentTag
|
||||||
|
)
|
||||||
|
if(currentFragment is BaseFragment && currentFragment.onHandleBack()) {
|
||||||
|
Timber.i("Handled back from Fragment[${currentFragment.tag}]")
|
||||||
|
if(!backstack.goBack()) {
|
||||||
|
Timber.i("No keys found, exiting the application...")
|
||||||
|
|
||||||
this.finishAndRemoveTask()
|
this.finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
package com.husky.project.core.ui.fragment
|
|
||||||
|
|
||||||
abstract class BaseBackFragment(layoutRes: Int) : BaseFragment(layoutRes) {
|
|
||||||
|
|
||||||
abstract fun onHandleBack(): Boolean
|
|
||||||
}
|
|
|
@ -19,6 +19,12 @@
|
||||||
|
|
||||||
package com.husky.project.core.ui.fragment
|
package com.husky.project.core.ui.fragment
|
||||||
|
|
||||||
|
import androidx.annotation.LayoutRes
|
||||||
import com.zhuinden.simplestackextensions.fragments.KeyedFragment
|
import com.zhuinden.simplestackextensions.fragments.KeyedFragment
|
||||||
|
|
||||||
open class BaseFragment(layoutRes: Int) : KeyedFragment(layoutRes)
|
open class BaseFragment(@LayoutRes layoutRes: Int) : KeyedFragment(layoutRes) {
|
||||||
|
|
||||||
|
fun onHandleBack(): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -20,5 +20,14 @@
|
||||||
package com.husky.project.core.ui.viewmodel
|
package com.husky.project.core.ui.viewmodel
|
||||||
|
|
||||||
import com.zhuinden.simplestack.Bundleable
|
import com.zhuinden.simplestack.Bundleable
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
|
||||||
abstract class BaseViewModel : Bundleable
|
abstract class BaseViewModel : Bundleable {
|
||||||
|
|
||||||
|
val viewModelScope: CoroutineScope
|
||||||
|
get() {
|
||||||
|
return CloseableCoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.husky.project.core.ui.viewmodel
|
||||||
|
|
||||||
|
import java.io.Closeable
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
|
|
||||||
|
internal class CloseableCoroutineScope(context: CoroutineContext) : Closeable, CoroutineScope {
|
||||||
|
|
||||||
|
override val coroutineContext: CoroutineContext = context
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
coroutineContext.cancel()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,18 +0,0 @@
|
||||||
package com.husky.project.core.ui.viewmodel
|
|
||||||
|
|
||||||
import com.zhuinden.simplestack.ScopedServices
|
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
|
||||||
import io.reactivex.disposables.Disposable
|
|
||||||
|
|
||||||
abstract class ServicesViewModel : BaseViewModel(), ScopedServices.Registered {
|
|
||||||
|
|
||||||
private val compositeDisposable = CompositeDisposable()
|
|
||||||
|
|
||||||
override fun onServiceUnregistered() {
|
|
||||||
compositeDisposable.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addDisposable(disposable: Disposable) {
|
|
||||||
compositeDisposable.add(disposable)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,7 +7,7 @@ import com.keylesspalace.tusky.R
|
||||||
import com.keylesspalace.tusky.core.extensions.addHttpsProtocolUrl
|
import com.keylesspalace.tusky.core.extensions.addHttpsProtocolUrl
|
||||||
import com.keylesspalace.tusky.core.extensions.dialogWithLink
|
import com.keylesspalace.tusky.core.extensions.dialogWithLink
|
||||||
import com.keylesspalace.tusky.core.extensions.viewBinding
|
import com.keylesspalace.tusky.core.extensions.viewBinding
|
||||||
import com.keylesspalace.tusky.core.extensions.viewObserve
|
import com.husky.project.core.extensions.viewObserve
|
||||||
import com.husky.project.core.ui.fragment.BaseFragment
|
import com.husky.project.core.ui.fragment.BaseFragment
|
||||||
import com.keylesspalace.tusky.databinding.ActivityLoginBinding
|
import com.keylesspalace.tusky.databinding.ActivityLoginBinding
|
||||||
import com.husky.project.features.login.view.viewmodel.LoginViewModel
|
import com.husky.project.features.login.view.viewmodel.LoginViewModel
|
||||||
|
|
|
@ -16,6 +16,8 @@ class LoginKey : BaseServiceKey() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun bindServices(serviceBinder: ServiceBinder) {
|
override fun bindServices(serviceBinder: ServiceBinder) {
|
||||||
serviceBinder.add(LoginViewModel())
|
with(serviceBinder) {
|
||||||
|
add(LoginViewModel())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,38 +3,40 @@ package com.husky.project.features.login.view.viewmodel
|
||||||
import android.util.Patterns
|
import android.util.Patterns
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import com.husky.project.core.extensions.cancelIfActive
|
||||||
|
import com.husky.project.core.ui.viewmodel.BaseViewModel
|
||||||
import com.husky.project.features.login.view.viewmodel.LoginViewModelKeys.Bundle
|
import com.husky.project.features.login.view.viewmodel.LoginViewModelKeys.Bundle
|
||||||
import com.keylesspalace.tusky.core.extensions.orEmpty
|
import com.keylesspalace.tusky.core.extensions.orEmpty
|
||||||
import com.husky.project.core.ui.viewmodel.ServicesViewModel
|
|
||||||
import com.zhuinden.statebundle.StateBundle
|
import com.zhuinden.statebundle.StateBundle
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class LoginViewModel : ServicesViewModel() {
|
class LoginViewModel : BaseViewModel() {
|
||||||
|
|
||||||
private val mVerifyUrl = MutableLiveData<Boolean>()
|
private var ver: Job? = null
|
||||||
|
|
||||||
|
private val _verifyUrl = MutableLiveData<Boolean>()
|
||||||
val verifyUrl: LiveData<Boolean>
|
val verifyUrl: LiveData<Boolean>
|
||||||
get() = mVerifyUrl
|
get() = _verifyUrl
|
||||||
|
|
||||||
override fun toBundle(): StateBundle = StateBundle().apply {
|
override fun toBundle(): StateBundle = StateBundle().apply {
|
||||||
putBoolean(
|
putBoolean(
|
||||||
Bundle.VERIFY_URL,
|
Bundle.VERIFY_URL,
|
||||||
mVerifyUrl.value.orEmpty()
|
_verifyUrl.value.orEmpty()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun fromBundle(bundle: StateBundle?) {
|
override fun fromBundle(bundle: StateBundle?) {
|
||||||
bundle?.run {
|
bundle?.run {
|
||||||
mVerifyUrl.value = getBoolean(Bundle.VERIFY_URL)
|
_verifyUrl.value = getBoolean(Bundle.VERIFY_URL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onServiceRegistered() {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onServiceUnregistered() {
|
|
||||||
super.onServiceUnregistered()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun verifyUrl(url: String) {
|
fun verifyUrl(url: String) {
|
||||||
mVerifyUrl.value = Patterns.WEB_URL.matcher(url).matches()
|
ver?.cancelIfActive()
|
||||||
|
ver = viewModelScope.launch {
|
||||||
|
|
||||||
|
}
|
||||||
|
_verifyUrl.value = Patterns.WEB_URL.matcher(url).matches()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,12 @@ kotlin.stdlib = "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}"
|
||||||
kotlin.stdlibJdk = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlin_version}"
|
kotlin.stdlibJdk = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlin_version}"
|
||||||
deps.kotlin = kotlin
|
deps.kotlin = kotlin
|
||||||
|
|
||||||
|
def kotlinx = [:]
|
||||||
|
kotlinx.coroutinesCore = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${versions.kotlinx}"
|
||||||
|
kotlinx.coroutinesAndroid = "org.jetbrains.kotlinx:kotlinx-coroutines-android:${versions.kotlinx}"
|
||||||
|
kotlinx.coroutinesTest = "org.jetbrains.kotlinx:kotlinx-coroutines-test:${versions.kotlinx}"
|
||||||
|
deps.kotlinx = kotlinx
|
||||||
|
|
||||||
def rxjava = [:]
|
def rxjava = [:]
|
||||||
rxjava.rxAndroid = "io.reactivex.rxjava2:rxandroid:${versions.rxAndroid}"
|
rxjava.rxAndroid = "io.reactivex.rxjava2:rxandroid:${versions.rxAndroid}"
|
||||||
rxjava.rxJava = "io.reactivex.rxjava2:rxjava:${versions.rxJava}"
|
rxjava.rxJava = "io.reactivex.rxjava2:rxjava:${versions.rxJava}"
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
rootProject.name = "husky"
|
rootProject.name = "husky"
|
||||||
|
|
||||||
include ":app"
|
include ":app"
|
||||||
include ':newhusky'
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ versions.fragmentKtx = "1.2.5"
|
||||||
versions.fragmentviewbindingdelegateKt = "1.0.0"
|
versions.fragmentviewbindingdelegateKt = "1.0.0"
|
||||||
versions.glide = "4.13.1"
|
versions.glide = "4.13.1"
|
||||||
versions.glideImage = "1.8.1"
|
versions.glideImage = "1.8.1"
|
||||||
versions.kotlin = "1.6.10"
|
versions.kotlinx = "1.6.0"
|
||||||
versions.lifecycle = "2.3.1"
|
versions.lifecycle = "2.3.1"
|
||||||
versions.markdownEdit = "1.0.0"
|
versions.markdownEdit = "1.0.0"
|
||||||
versions.materialDesign = "1.4.0"
|
versions.materialDesign = "1.4.0"
|
||||||
|
|
Loading…
Reference in a new issue