diff --git a/husky/app/build.gradle b/husky/app/build.gradle index 38c5304..650953e 100644 --- a/husky/app/build.gradle +++ b/husky/app/build.gradle @@ -185,6 +185,7 @@ android { dependencies { implementation fileTree(dir: "libs", include: ["*.jar", "*.aar"]) + // AndroidX dependencies implementation deps.androidx.appCompat implementation deps.androidx.browser implementation deps.androidx.cardView @@ -210,32 +211,43 @@ dependencies { implementation deps.androidx.lifecycle.reactiveStreamsKtx implementation deps.androidx.lifecycle.viewmodelKtx + // Dagger dependencies implementation deps.dagger.dagger implementation deps.dagger.daggerAndroid kapt deps.dagger.daggerCompiler kapt deps.dagger.daggerProcessor implementation deps.dagger.daggerSupport + // Glide dependencies implementation deps.glide.glide kapt deps.glide.glideCompiler implementation deps.glide.glideImage implementation deps.glide.glideImageViewFactory implementation deps.glide.glideOkhttp + // Google dependencies implementation deps.google.flexbox implementation deps.google.exoplayer implementation deps.google.materialDesign + // Kotlin dependencies implementation deps.kotlin.stdlib implementation deps.kotlin.stdlibJdk + // KotlinX dependencies + implementation deps.kotlinx.coroutinesCore + implementation deps.kotlinx.coroutinesAndroid + + // RxJava dependencies implementation deps.rxjava.rxAndroid implementation deps.rxjava.rxJava implementation deps.rxjava.rxKotlin + // simple-stack dependencies implementation deps.simplestack.ext implementation deps.simplestack.lib + // Square dependencies implementation deps.square.retrofit implementation deps.square.retrofitAdapterRxJ2 implementation deps.square.retrofitConvGson @@ -243,6 +255,7 @@ dependencies { implementation deps.square.okhttp implementation deps.square.okhttpBrotli + // Other dependencies implementation deps.acraMail implementation deps.acraNotification implementation deps.androidImageCropper @@ -260,6 +273,7 @@ dependencies { implementation deps.sparkButton implementation deps.timber + // Testing dependencies testImplementation deps.testing.extJunit testImplementation deps.testing.junit testImplementation deps.testing.mockitoInline diff --git a/husky/app/src/newhusky/java/com/husky/project/core/di/GlobalServices.kt b/husky/app/src/newhusky/java/com/husky/project/core/di/GlobalServices.kt index bc68b52..6aca453 100644 --- a/husky/app/src/newhusky/java/com/husky/project/core/di/GlobalServices.kt +++ b/husky/app/src/newhusky/java/com/husky/project/core/di/GlobalServices.kt @@ -5,11 +5,10 @@ import com.zhuinden.simplestack.GlobalServices class HuskyServices(private val appContext: Context) { - fun getGlobalServices() : GlobalServices { + fun getGlobalServices(): GlobalServices { val builder = GlobalServices.builder() with(builder) { - } return builder.build() diff --git a/husky/app/src/newhusky/java/com/husky/project/core/extensions/JobExt.kt b/husky/app/src/newhusky/java/com/husky/project/core/extensions/JobExt.kt new file mode 100644 index 0000000..4e3ecb5 --- /dev/null +++ b/husky/app/src/newhusky/java/com/husky/project/core/extensions/JobExt.kt @@ -0,0 +1,9 @@ +package com.husky.project.core.extensions + +import kotlinx.coroutines.Job + +fun Job?.cancelIfActive() { + if(this?.isActive == true) { + this.cancel() + } +} diff --git a/husky/app/src/newhusky/java/com/husky/project/core/extensions/LifecycleExt.kt b/husky/app/src/newhusky/java/com/husky/project/core/extensions/LifecycleExt.kt index 3a77a5a..e402896 100644 --- a/husky/app/src/newhusky/java/com/husky/project/core/extensions/LifecycleExt.kt +++ b/husky/app/src/newhusky/java/com/husky/project/core/extensions/LifecycleExt.kt @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.keylesspalace.tusky.core.extensions +package com.husky.project.core.extensions import androidx.fragment.app.Fragment import androidx.lifecycle.LiveData @@ -26,7 +26,6 @@ import androidx.lifecycle.Observer fun > Fragment.viewObserve(liveData: L, body: (T?) -> Unit) = liveData.observe(viewLifecycleOwner, Observer(body)) -// TODO: When Failure class is ready /*fun > Fragment.viewFailureObserve( liveData: L, body: (Failure?) -> Unit diff --git a/husky/app/src/newhusky/java/com/husky/project/core/navigation/NavigationActivity.kt b/husky/app/src/newhusky/java/com/husky/project/core/navigation/NavigationActivity.kt index 65cd95c..1fbf0f9 100644 --- a/husky/app/src/newhusky/java/com/husky/project/core/navigation/NavigationActivity.kt +++ b/husky/app/src/newhusky/java/com/husky/project/core/navigation/NavigationActivity.kt @@ -22,9 +22,11 @@ package com.husky.project.core.navigation import android.os.Bundle import androidx.appcompat.app.AppCompatActivity 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.databinding.ActivityNavigationBinding -import com.husky.project.features.splash.view.navigation.SplashKey import com.zhuinden.simplestack.History import com.zhuinden.simplestack.SimpleStateChanger import com.zhuinden.simplestack.StateChange @@ -47,10 +49,16 @@ class NavigationActivity : AppCompatActivity(), SimpleStateChanger.NavigationHan } override fun onBackPressed() { - if(!backstack.goBack()) { - Timber.i("No keys found, exiting the application...") + val currentFragment = supportFragmentManager.findFragmentByTag( + backstack.top().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() + } } } diff --git a/husky/app/src/newhusky/java/com/husky/project/core/ui/fragment/BaseBackFragment.kt b/husky/app/src/newhusky/java/com/husky/project/core/ui/fragment/BaseBackFragment.kt deleted file mode 100644 index 958ecb8..0000000 --- a/husky/app/src/newhusky/java/com/husky/project/core/ui/fragment/BaseBackFragment.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.husky.project.core.ui.fragment - -abstract class BaseBackFragment(layoutRes: Int) : BaseFragment(layoutRes) { - - abstract fun onHandleBack(): Boolean -} diff --git a/husky/app/src/newhusky/java/com/husky/project/core/ui/fragment/BaseFragment.kt b/husky/app/src/newhusky/java/com/husky/project/core/ui/fragment/BaseFragment.kt index c43fd1e..bc59cad 100644 --- a/husky/app/src/newhusky/java/com/husky/project/core/ui/fragment/BaseFragment.kt +++ b/husky/app/src/newhusky/java/com/husky/project/core/ui/fragment/BaseFragment.kt @@ -19,6 +19,12 @@ package com.husky.project.core.ui.fragment +import androidx.annotation.LayoutRes 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 + } +} diff --git a/husky/app/src/newhusky/java/com/husky/project/core/ui/viewmodel/BaseViewModel.kt b/husky/app/src/newhusky/java/com/husky/project/core/ui/viewmodel/BaseViewModel.kt index eae221a..8f1263a 100644 --- a/husky/app/src/newhusky/java/com/husky/project/core/ui/viewmodel/BaseViewModel.kt +++ b/husky/app/src/newhusky/java/com/husky/project/core/ui/viewmodel/BaseViewModel.kt @@ -20,5 +20,14 @@ package com.husky.project.core.ui.viewmodel 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) + } +} diff --git a/husky/app/src/newhusky/java/com/husky/project/core/ui/viewmodel/CloseableCoroutineScope.kt b/husky/app/src/newhusky/java/com/husky/project/core/ui/viewmodel/CloseableCoroutineScope.kt new file mode 100644 index 0000000..c00d4dc --- /dev/null +++ b/husky/app/src/newhusky/java/com/husky/project/core/ui/viewmodel/CloseableCoroutineScope.kt @@ -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() + } +} diff --git a/husky/app/src/newhusky/java/com/husky/project/core/ui/viewmodel/ServicesViewModel.kt b/husky/app/src/newhusky/java/com/husky/project/core/ui/viewmodel/ServicesViewModel.kt deleted file mode 100644 index d53e39b..0000000 --- a/husky/app/src/newhusky/java/com/husky/project/core/ui/viewmodel/ServicesViewModel.kt +++ /dev/null @@ -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) - } -} diff --git a/husky/app/src/newhusky/java/com/husky/project/features/login/view/fragments/LoginFragment.kt b/husky/app/src/newhusky/java/com/husky/project/features/login/view/fragments/LoginFragment.kt index bbfdb12..616736d 100644 --- a/husky/app/src/newhusky/java/com/husky/project/features/login/view/fragments/LoginFragment.kt +++ b/husky/app/src/newhusky/java/com/husky/project/features/login/view/fragments/LoginFragment.kt @@ -7,7 +7,7 @@ import com.keylesspalace.tusky.R import com.keylesspalace.tusky.core.extensions.addHttpsProtocolUrl import com.keylesspalace.tusky.core.extensions.dialogWithLink 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.keylesspalace.tusky.databinding.ActivityLoginBinding import com.husky.project.features.login.view.viewmodel.LoginViewModel diff --git a/husky/app/src/newhusky/java/com/husky/project/features/login/view/navigation/LoginKey.kt b/husky/app/src/newhusky/java/com/husky/project/features/login/view/navigation/LoginKey.kt index c8d7b54..0ccec42 100644 --- a/husky/app/src/newhusky/java/com/husky/project/features/login/view/navigation/LoginKey.kt +++ b/husky/app/src/newhusky/java/com/husky/project/features/login/view/navigation/LoginKey.kt @@ -16,6 +16,8 @@ class LoginKey : BaseServiceKey() { } override fun bindServices(serviceBinder: ServiceBinder) { - serviceBinder.add(LoginViewModel()) + with(serviceBinder) { + add(LoginViewModel()) + } } } diff --git a/husky/app/src/newhusky/java/com/husky/project/features/login/view/viewmodel/LoginViewModel.kt b/husky/app/src/newhusky/java/com/husky/project/features/login/view/viewmodel/LoginViewModel.kt index c503916..bfb60c3 100644 --- a/husky/app/src/newhusky/java/com/husky/project/features/login/view/viewmodel/LoginViewModel.kt +++ b/husky/app/src/newhusky/java/com/husky/project/features/login/view/viewmodel/LoginViewModel.kt @@ -3,38 +3,40 @@ package com.husky.project.features.login.view.viewmodel import android.util.Patterns import androidx.lifecycle.LiveData 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.keylesspalace.tusky.core.extensions.orEmpty -import com.husky.project.core.ui.viewmodel.ServicesViewModel import com.zhuinden.statebundle.StateBundle +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch -class LoginViewModel : ServicesViewModel() { +class LoginViewModel : BaseViewModel() { - private val mVerifyUrl = MutableLiveData() + private var ver: Job? = null + + private val _verifyUrl = MutableLiveData() val verifyUrl: LiveData - get() = mVerifyUrl + get() = _verifyUrl override fun toBundle(): StateBundle = StateBundle().apply { putBoolean( Bundle.VERIFY_URL, - mVerifyUrl.value.orEmpty() + _verifyUrl.value.orEmpty() ) } override fun fromBundle(bundle: StateBundle?) { 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) { - mVerifyUrl.value = Patterns.WEB_URL.matcher(url).matches() + ver?.cancelIfActive() + ver = viewModelScope.launch { + + } + _verifyUrl.value = Patterns.WEB_URL.matcher(url).matches() } } diff --git a/husky/dependencies.gradle b/husky/dependencies.gradle index 4b8619b..7b0c61e 100644 --- a/husky/dependencies.gradle +++ b/husky/dependencies.gradle @@ -72,6 +72,12 @@ kotlin.stdlib = "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}" kotlin.stdlibJdk = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlin_version}" 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 = [:] rxjava.rxAndroid = "io.reactivex.rxjava2:rxandroid:${versions.rxAndroid}" rxjava.rxJava = "io.reactivex.rxjava2:rxjava:${versions.rxJava}" diff --git a/husky/settings.gradle b/husky/settings.gradle index ba63a5a..d66f4ee 100644 --- a/husky/settings.gradle +++ b/husky/settings.gradle @@ -1,4 +1,3 @@ rootProject.name = "husky" include ":app" -include ':newhusky' diff --git a/husky/versions.gradle b/husky/versions.gradle index 0d06192..441e9fe 100644 --- a/husky/versions.gradle +++ b/husky/versions.gradle @@ -30,7 +30,7 @@ versions.fragmentKtx = "1.2.5" versions.fragmentviewbindingdelegateKt = "1.0.0" versions.glide = "4.13.1" versions.glideImage = "1.8.1" -versions.kotlin = "1.6.10" +versions.kotlinx = "1.6.0" versions.lifecycle = "2.3.1" versions.markdownEdit = "1.0.0" versions.materialDesign = "1.4.0"