mirror of
https://github.com/afollestad/nock-nock.git
synced 2025-04-19 19:15:23 +00:00
Switch from Dagger to Koin, resolves #35
This commit is contained in:
parent
c9750f5f66
commit
1e92644904
61 changed files with 385 additions and 660 deletions
2
.idea/modules.xml
generated
2
.idea/modules.xml
generated
|
@ -3,11 +3,11 @@
|
|||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/common/common.iml" filepath="$PROJECT_DIR$/common/common.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/data/data.iml" filepath="$PROJECT_DIR$/data/data.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/engine/engine.iml" filepath="$PROJECT_DIR$/engine/engine.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/nock-nock.iml" filepath="$PROJECT_DIR$/nock-nock.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/notifications/notifications.iml" filepath="$PROJECT_DIR$/notifications/notifications.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/utilities/utilities.iml" filepath="$PROJECT_DIR$/utilities/utilities.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/viewcomponents/viewcomponents.iml" filepath="$PROJECT_DIR$/viewcomponents/viewcomponents.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
|
|
|
@ -18,7 +18,7 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':utilities')
|
||||
implementation project(':common')
|
||||
implementation project(':engine')
|
||||
implementation project(':data')
|
||||
implementation project(':notifications')
|
||||
|
@ -32,16 +32,22 @@ dependencies {
|
|||
|
||||
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:' + versions.kotlin
|
||||
|
||||
implementation 'com.google.dagger:dagger:' + versions.dagger
|
||||
kapt 'com.google.dagger:dagger-compiler:' + versions.dagger
|
||||
implementation 'org.koin:koin-android:' + versions.koin
|
||||
implementation 'org.koin:koin-androidx-scope:' + versions.koin
|
||||
implementation 'org.koin:koin-androidx-viewmodel:' + versions.koin
|
||||
|
||||
implementation 'com.afollestad.material-dialogs:core:' + versions.materialDialogs
|
||||
|
||||
implementation 'com.jakewharton.timber:timber:' + versions.timber
|
||||
|
||||
testImplementation 'junit:junit:' + versions.junit
|
||||
testImplementation 'org.mockito:mockito-core:' + versions.mockito
|
||||
testImplementation 'com.nhaarman.mockitokotlin2:mockito-kotlin:' + versions.mockitoKotlin
|
||||
testImplementation 'com.google.truth:truth:' + versions.truth
|
||||
testImplementation 'androidx.arch.core:core-testing:' + versions.archTesting
|
||||
|
||||
androidTestImplementation 'androidx.test:runner:' + versions.androidxTestRunner
|
||||
androidTestImplementation 'androidx.test:rules:' + versions.androidxTestRunner
|
||||
}
|
||||
|
||||
apply from: '../spotless.gradle'
|
|
@ -16,55 +16,42 @@
|
|||
package com.afollestad.nocknock
|
||||
|
||||
import android.app.Application
|
||||
import com.afollestad.nocknock.di.AppComponent
|
||||
import com.afollestad.nocknock.di.DaggerAppComponent
|
||||
import com.afollestad.nocknock.engine.validation.BootReceiver
|
||||
import com.afollestad.nocknock.engine.validation.ValidationJob
|
||||
import com.afollestad.nocknock.engine.engineModule
|
||||
import com.afollestad.nocknock.koin.mainModule
|
||||
import com.afollestad.nocknock.koin.viewModelModule
|
||||
import com.afollestad.nocknock.notifications.NockNotificationManager
|
||||
import com.afollestad.nocknock.ui.addsite.AddSiteActivity
|
||||
import com.afollestad.nocknock.ui.main.MainActivity
|
||||
import com.afollestad.nocknock.ui.viewsite.ViewSiteActivity
|
||||
import com.afollestad.nocknock.utilities.Injector
|
||||
import com.afollestad.nocknock.utilities.ext.systemService
|
||||
import okhttp3.OkHttpClient
|
||||
import com.afollestad.nocknock.notifications.notificationsModule
|
||||
import com.afollestad.nocknock.utilities.utilitiesModule
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.android.ext.android.startKoin
|
||||
import timber.log.Timber
|
||||
import timber.log.Timber.DebugTree
|
||||
import javax.inject.Inject
|
||||
import timber.log.Timber.d as log
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
class NockNockApp : Application(), Injector {
|
||||
|
||||
private lateinit var appComponent: AppComponent
|
||||
@Inject lateinit var nockNotificationManager: NockNotificationManager
|
||||
class NockNockApp : Application() {
|
||||
|
||||
private var resumedActivities: Int = 0
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
Timber.plant(DebugTree())
|
||||
}
|
||||
|
||||
val okHttpClient = OkHttpClient.Builder()
|
||||
.addNetworkInterceptor { chain ->
|
||||
val request = chain.request()
|
||||
.newBuilder()
|
||||
.addHeader("User-Agent", "com.afollestad.nocknock")
|
||||
.build()
|
||||
chain.proceed(request)
|
||||
}
|
||||
.build()
|
||||
|
||||
appComponent = DaggerAppComponent.builder()
|
||||
.application(this)
|
||||
.okHttpClient(okHttpClient)
|
||||
.jobScheduler(systemService(JOB_SCHEDULER_SERVICE))
|
||||
.notificationManager(systemService(NOTIFICATION_SERVICE))
|
||||
.build()
|
||||
appComponent.inject(this)
|
||||
val modules = listOf(
|
||||
mainModule,
|
||||
engineModule,
|
||||
utilitiesModule,
|
||||
notificationsModule,
|
||||
viewModelModule
|
||||
)
|
||||
startKoin(
|
||||
androidContext = this,
|
||||
modules = modules
|
||||
)
|
||||
|
||||
val nockNotificationManager by inject<NockNotificationManager>()
|
||||
onActivityLifeChange { activity, resumed ->
|
||||
if (resumed) {
|
||||
resumedActivities++
|
||||
|
@ -77,13 +64,4 @@ class NockNockApp : Application(), Injector {
|
|||
nockNotificationManager.setIsAppOpen(resumedActivities > 0)
|
||||
}
|
||||
}
|
||||
|
||||
override fun injectInto(target: Any) = when (target) {
|
||||
is MainActivity -> appComponent.inject(target)
|
||||
is ViewSiteActivity -> appComponent.inject(target)
|
||||
is AddSiteActivity -> appComponent.inject(target)
|
||||
is ValidationJob -> appComponent.inject(target)
|
||||
is BootReceiver -> appComponent.inject(target)
|
||||
else -> throw IllegalStateException("Can't inject into $target")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
* Designed and developed by Aidan Follestad (@afollestad)
|
||||
*
|
||||
* 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.afollestad.nocknock.di;
|
||||
|
||||
import android.app.Application;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.job.JobScheduler;
|
||||
import com.afollestad.nocknock.NockNockApp;
|
||||
import com.afollestad.nocknock.di.viewmodels.ViewModelModule;
|
||||
import com.afollestad.nocknock.engine.EngineModule;
|
||||
import com.afollestad.nocknock.engine.validation.BootReceiver;
|
||||
import com.afollestad.nocknock.engine.validation.ValidationJob;
|
||||
import com.afollestad.nocknock.notifications.NotificationsModule;
|
||||
import com.afollestad.nocknock.ui.addsite.AddSiteActivity;
|
||||
import com.afollestad.nocknock.ui.main.MainActivity;
|
||||
import com.afollestad.nocknock.ui.viewsite.ViewSiteActivity;
|
||||
import com.afollestad.nocknock.utilities.UtilitiesModule;
|
||||
import dagger.BindsInstance;
|
||||
import dagger.Component;
|
||||
import javax.inject.Singleton;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
@Singleton
|
||||
@Component(
|
||||
modules = {
|
||||
MainModule.class,
|
||||
ViewModelModule.class,
|
||||
EngineModule.class,
|
||||
NotificationsModule.class,
|
||||
UtilitiesModule.class
|
||||
}
|
||||
)
|
||||
public interface AppComponent {
|
||||
|
||||
void inject(NockNockApp app);
|
||||
|
||||
void inject(MainActivity activity);
|
||||
|
||||
void inject(ViewSiteActivity activity);
|
||||
|
||||
void inject(AddSiteActivity activity);
|
||||
|
||||
void inject(ValidationJob job);
|
||||
|
||||
void inject(BootReceiver bootReceiver);
|
||||
|
||||
@Component.Builder interface Builder {
|
||||
|
||||
@BindsInstance
|
||||
Builder application(Application application);
|
||||
|
||||
@BindsInstance
|
||||
Builder okHttpClient(OkHttpClient okHttpClient);
|
||||
|
||||
@BindsInstance
|
||||
Builder jobScheduler(JobScheduler jobScheduler);
|
||||
|
||||
@BindsInstance
|
||||
Builder notificationManager(NotificationManager notificationManager);
|
||||
|
||||
AppComponent build();
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* Designed and developed by Aidan Follestad (@afollestad)
|
||||
*
|
||||
* 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.afollestad.nocknock.di;
|
||||
|
||||
import android.app.Application;
|
||||
import com.afollestad.nocknock.R;
|
||||
import com.afollestad.nocknock.data.AppDatabase;
|
||||
import com.afollestad.nocknock.ui.main.MainActivity;
|
||||
import com.afollestad.nocknock.utilities.qualifiers.AppIconRes;
|
||||
import com.afollestad.nocknock.di.qualifiers.IoDispatcher;
|
||||
import com.afollestad.nocknock.utilities.qualifiers.MainActivityClass;
|
||||
import com.afollestad.nocknock.di.qualifiers.MainDispatcher;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import javax.inject.Singleton;
|
||||
import kotlinx.coroutines.CoroutineDispatcher;
|
||||
import kotlinx.coroutines.Dispatchers;
|
||||
|
||||
import static androidx.room.Room.databaseBuilder;
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
@Module
|
||||
abstract class MainModule {
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private static String DATABASE_NAME = "NockNock.db";
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@AppIconRes
|
||||
static int provideAppIconRes() {
|
||||
return R.mipmap.ic_launcher;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@MainActivityClass
|
||||
static Class<?> provideMainActivityClass() {
|
||||
return MainActivity.class;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
static AppDatabase provideAppDatabase(Application app) {
|
||||
return databaseBuilder(app, AppDatabase.class, DATABASE_NAME).build();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@MainDispatcher
|
||||
static CoroutineDispatcher provideMainDispatcher() {
|
||||
return Dispatchers.getMain();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@IoDispatcher
|
||||
static CoroutineDispatcher provideIoDispatcher() {
|
||||
return Dispatchers.getIO();
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
/**
|
||||
* Designed and developed by Aidan Follestad (@afollestad)
|
||||
*
|
||||
* 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.afollestad.nocknock.di.qualifiers
|
||||
|
||||
import javax.inject.Qualifier
|
||||
import kotlin.annotation.AnnotationRetention.RUNTIME
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
@Qualifier
|
||||
@Retention(RUNTIME)
|
||||
annotation class IoDispatcher
|
|
@ -1,24 +0,0 @@
|
|||
/**
|
||||
* Designed and developed by Aidan Follestad (@afollestad)
|
||||
*
|
||||
* 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.afollestad.nocknock.di.qualifiers
|
||||
|
||||
import javax.inject.Qualifier
|
||||
import kotlin.annotation.AnnotationRetention.RUNTIME
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
@Qualifier
|
||||
@Retention(RUNTIME)
|
||||
annotation class MainDispatcher
|
|
@ -1,48 +0,0 @@
|
|||
/**
|
||||
* Designed and developed by Aidan Follestad (@afollestad)
|
||||
*
|
||||
* 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.afollestad.nocknock.di.viewmodels
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import dagger.MapKey
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Provider
|
||||
import javax.inject.Singleton
|
||||
import kotlin.annotation.AnnotationRetention.RUNTIME
|
||||
import kotlin.annotation.AnnotationTarget.FUNCTION
|
||||
import kotlin.annotation.AnnotationTarget.PROPERTY_GETTER
|
||||
import kotlin.annotation.AnnotationTarget.PROPERTY_SETTER
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
typealias ViewModelMap = MutableMap<Class<out ViewModel>, Provider<ViewModel>>
|
||||
|
||||
@Target(FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER)
|
||||
@Retention(RUNTIME)
|
||||
@MapKey
|
||||
annotation class ViewModelKey(val value: KClass<out ViewModel>)
|
||||
|
||||
/**
|
||||
* https://proandroiddev.com/viewmodel-with-dagger2-architecture-components-2e06f06c9455
|
||||
*/
|
||||
@Singleton
|
||||
class ViewModelFactory @Inject constructor(private val viewModels: ViewModelMap) :
|
||||
ViewModelProvider.Factory {
|
||||
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return viewModels[modelClass]?.get() as T
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
package com.afollestad.nocknock.di.viewmodels;
|
||||
|
||||
import androidx.lifecycle.ViewModel;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import com.afollestad.nocknock.ui.addsite.AddSiteViewModel;
|
||||
import com.afollestad.nocknock.ui.main.MainViewModel;
|
||||
import com.afollestad.nocknock.ui.viewsite.ViewSiteViewModel;
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import dagger.multibindings.IntoMap;
|
||||
|
||||
/** https://proandroiddev.com/viewmodel-with-dagger2-architecture-components-2e06f06c9455 */
|
||||
@Module
|
||||
public abstract class ViewModelModule {
|
||||
|
||||
@Binds
|
||||
abstract ViewModelProvider.Factory bindViewModelFactory(ViewModelFactory factory);
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ViewModelKey(MainViewModel.class)
|
||||
abstract ViewModel mainViewModel(MainViewModel viewModel);
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ViewModelKey(AddSiteViewModel.class)
|
||||
abstract ViewModel addSiteViewModel(AddSiteViewModel viewModel);
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ViewModelKey(ViewSiteViewModel.class)
|
||||
abstract ViewModel viewSiteViewModel(ViewSiteViewModel viewModel);
|
||||
}
|
63
app/src/main/java/com/afollestad/nocknock/koin/MainModule.kt
Normal file
63
app/src/main/java/com/afollestad/nocknock/koin/MainModule.kt
Normal file
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* Designed and developed by Aidan Follestad (@afollestad)
|
||||
*
|
||||
* 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.afollestad.nocknock.koin
|
||||
|
||||
import android.app.Application
|
||||
import android.app.NotificationManager
|
||||
import android.app.job.JobScheduler
|
||||
import android.content.Context.JOB_SCHEDULER_SERVICE
|
||||
import android.content.Context.NOTIFICATION_SERVICE
|
||||
import androidx.room.Room.databaseBuilder
|
||||
import com.afollestad.nocknock.R
|
||||
import com.afollestad.nocknock.data.AppDatabase
|
||||
import com.afollestad.nocknock.notifications.Qualifiers.APP_ICON_RES
|
||||
import com.afollestad.nocknock.ui.main.MainActivity
|
||||
import com.afollestad.nocknock.utilities.Qualifiers.MAIN_ACTIVITY_CLASS
|
||||
import com.afollestad.nocknock.utilities.ext.systemService
|
||||
import okhttp3.OkHttpClient
|
||||
import org.koin.dsl.module.module
|
||||
|
||||
const val MAIN_MODULE = "main"
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
val mainModule = module(MAIN_MODULE) {
|
||||
|
||||
single(name = APP_ICON_RES) { R.mipmap.ic_launcher }
|
||||
|
||||
single(name = MAIN_ACTIVITY_CLASS) { MainActivity::class.java }
|
||||
|
||||
single { databaseBuilder(get(), AppDatabase::class.java, "NockNock.db").build() }
|
||||
|
||||
single {
|
||||
OkHttpClient.Builder()
|
||||
.addNetworkInterceptor { chain ->
|
||||
val request = chain.request()
|
||||
.newBuilder()
|
||||
.addHeader("User-Agent", "com.afollestad.nocknock")
|
||||
.build()
|
||||
chain.proceed(request)
|
||||
}
|
||||
.build()
|
||||
}
|
||||
|
||||
single<JobScheduler> {
|
||||
get<Application>().systemService(JOB_SCHEDULER_SERVICE)
|
||||
}
|
||||
|
||||
single<NotificationManager> {
|
||||
get<Application>().systemService(NOTIFICATION_SERVICE)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* Designed and developed by Aidan Follestad (@afollestad)
|
||||
*
|
||||
* 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.afollestad.nocknock.koin
|
||||
|
||||
import com.afollestad.nocknock.ui.addsite.AddSiteViewModel
|
||||
import com.afollestad.nocknock.ui.main.MainViewModel
|
||||
import com.afollestad.nocknock.ui.viewsite.ViewSiteViewModel
|
||||
import com.afollestad.nocknock.utilities.Qualifiers.IO_DISPATCHER
|
||||
import com.afollestad.nocknock.utilities.Qualifiers.MAIN_DISPATCHER
|
||||
import org.koin.androidx.viewmodel.ext.koin.viewModel
|
||||
import org.koin.dsl.module.module
|
||||
|
||||
const val VIEW_MODEL_MODULE = "view_models"
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
val viewModelModule = module(VIEW_MODEL_MODULE) {
|
||||
|
||||
viewModel {
|
||||
MainViewModel(
|
||||
get(),
|
||||
get(),
|
||||
get(),
|
||||
get(name = MAIN_DISPATCHER),
|
||||
get(name = IO_DISPATCHER)
|
||||
)
|
||||
}
|
||||
|
||||
viewModel {
|
||||
AddSiteViewModel(
|
||||
get(),
|
||||
get(),
|
||||
get(name = MAIN_DISPATCHER),
|
||||
get(name = IO_DISPATCHER)
|
||||
)
|
||||
}
|
||||
|
||||
viewModel {
|
||||
ViewSiteViewModel(
|
||||
get(),
|
||||
get(),
|
||||
get(),
|
||||
get(),
|
||||
get(name = MAIN_DISPATCHER),
|
||||
get(name = IO_DISPATCHER)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -13,21 +13,16 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.afollestad.nocknock.di.viewmodels
|
||||
package com.afollestad.nocknock.ui
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.afollestad.nocknock.di.qualifiers.MainDispatcher
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import javax.inject.Inject
|
||||
|
||||
abstract class ScopedViewModel : ViewModel() {
|
||||
|
||||
@Inject
|
||||
@MainDispatcher
|
||||
lateinit var mainDispatcher: CoroutineDispatcher
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
abstract class ScopedViewModel(mainDispatcher: CoroutineDispatcher) : ViewModel() {
|
||||
|
||||
private val job = Job()
|
||||
protected val scope = CoroutineScope(job + mainDispatcher)
|
|
@ -19,11 +19,8 @@ import android.annotation.SuppressLint
|
|||
import android.os.Bundle
|
||||
import android.widget.ArrayAdapter
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import com.afollestad.nocknock.R
|
||||
import com.afollestad.nocknock.data.model.ValidationMode
|
||||
import com.afollestad.nocknock.utilities.ext.injector
|
||||
import com.afollestad.nocknock.viewcomponents.ext.attachLiveData
|
||||
import com.afollestad.nocknock.viewcomponents.ext.conceal
|
||||
import com.afollestad.nocknock.viewcomponents.ext.onLayout
|
||||
|
@ -43,7 +40,7 @@ import kotlinx.android.synthetic.main.activity_addsite.scriptInputLayout
|
|||
import kotlinx.android.synthetic.main.activity_addsite.textUrlWarning
|
||||
import kotlinx.android.synthetic.main.activity_addsite.toolbar
|
||||
import kotlinx.android.synthetic.main.activity_addsite.validationModeDescription
|
||||
import javax.inject.Inject
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import kotlin.math.max
|
||||
import kotlin.properties.Delegates.notNull
|
||||
|
||||
|
@ -58,19 +55,13 @@ class AddSiteActivity : AppCompatActivity() {
|
|||
var revealCy by notNull<Int>()
|
||||
var revealRadius by notNull<Float>()
|
||||
|
||||
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
|
||||
|
||||
internal var isClosing = false
|
||||
private val viewModel by lazy {
|
||||
return@lazy ViewModelProviders.of(this, viewModelFactory)
|
||||
.get(AddSiteViewModel::class.java)
|
||||
}
|
||||
|
||||
private val viewModel by viewModel<AddSiteViewModel>()
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
injector().injectInto(this)
|
||||
setContentView(R.layout.activity_addsite)
|
||||
setupUi(savedInstanceState)
|
||||
|
||||
|
|
|
@ -28,23 +28,22 @@ import com.afollestad.nocknock.data.model.ValidationMode.JAVASCRIPT
|
|||
import com.afollestad.nocknock.data.model.ValidationMode.STATUS_CODE
|
||||
import com.afollestad.nocknock.data.model.ValidationMode.TERM_SEARCH
|
||||
import com.afollestad.nocknock.data.putSite
|
||||
import com.afollestad.nocknock.di.viewmodels.ScopedViewModel
|
||||
import com.afollestad.nocknock.engine.validation.ValidationManager
|
||||
import com.afollestad.nocknock.di.qualifiers.IoDispatcher
|
||||
import com.afollestad.nocknock.ui.ScopedViewModel
|
||||
import com.afollestad.nocknock.viewcomponents.ext.isNullOrLessThan
|
||||
import com.afollestad.nocknock.viewcomponents.ext.map
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.HttpUrl
|
||||
import javax.inject.Inject
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
class AddSiteViewModel @Inject constructor(
|
||||
class AddSiteViewModel(
|
||||
private val database: AppDatabase,
|
||||
private val validationManager: ValidationManager,
|
||||
@field:IoDispatcher private val ioDispatcher: CoroutineDispatcher
|
||||
) : ScopedViewModel(), LifecycleObserver {
|
||||
mainDispatcher: CoroutineDispatcher,
|
||||
private val ioDispatcher: CoroutineDispatcher
|
||||
) : ScopedViewModel(mainDispatcher), LifecycleObserver {
|
||||
|
||||
// Public properties
|
||||
val name = MutableLiveData<String>()
|
||||
|
|
|
@ -19,8 +19,6 @@ import android.content.Intent
|
|||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.DividerItemDecoration.VERTICAL
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
|
@ -28,31 +26,27 @@ import com.afollestad.materialdialogs.MaterialDialog
|
|||
import com.afollestad.materialdialogs.list.listItems
|
||||
import com.afollestad.nocknock.R
|
||||
import com.afollestad.nocknock.adapter.ServerAdapter
|
||||
import com.afollestad.nocknock.broadcasts.StatusUpdateIntentReceiver
|
||||
import com.afollestad.nocknock.data.model.Site
|
||||
import com.afollestad.nocknock.dialogs.AboutDialog
|
||||
import com.afollestad.nocknock.notifications.NockNotificationManager
|
||||
import com.afollestad.nocknock.broadcasts.StatusUpdateIntentReceiver
|
||||
import com.afollestad.nocknock.utilities.ext.injector
|
||||
import com.afollestad.nocknock.viewcomponents.ext.showOrHide
|
||||
import kotlinx.android.synthetic.main.activity_main.fab
|
||||
import kotlinx.android.synthetic.main.activity_main.list
|
||||
import kotlinx.android.synthetic.main.activity_main.loadingProgress
|
||||
import kotlinx.android.synthetic.main.activity_main.toolbar
|
||||
import kotlinx.android.synthetic.main.include_empty_view.emptyText
|
||||
import javax.inject.Inject
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
@Inject lateinit var notificationManager: NockNotificationManager
|
||||
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
|
||||
private val notificationManager by inject<NockNotificationManager>()
|
||||
internal val viewModel by viewModel<MainViewModel>()
|
||||
|
||||
private lateinit var adapter: ServerAdapter
|
||||
|
||||
internal val viewModel by lazy {
|
||||
return@lazy ViewModelProviders.of(this, viewModelFactory)
|
||||
.get(MainViewModel::class.java)
|
||||
}
|
||||
private val statusUpdateReceiver =
|
||||
StatusUpdateIntentReceiver(application) {
|
||||
viewModel.postSiteUpdate(it)
|
||||
|
@ -60,7 +54,6 @@ class MainActivity : AppCompatActivity() {
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
injector().injectInto(this)
|
||||
setContentView(R.layout.activity_main)
|
||||
setupUi()
|
||||
|
||||
|
|
|
@ -25,22 +25,21 @@ import com.afollestad.nocknock.data.AppDatabase
|
|||
import com.afollestad.nocknock.data.allSites
|
||||
import com.afollestad.nocknock.data.deleteSite
|
||||
import com.afollestad.nocknock.data.model.Site
|
||||
import com.afollestad.nocknock.di.viewmodels.ScopedViewModel
|
||||
import com.afollestad.nocknock.engine.validation.ValidationManager
|
||||
import com.afollestad.nocknock.notifications.NockNotificationManager
|
||||
import com.afollestad.nocknock.di.qualifiers.IoDispatcher
|
||||
import com.afollestad.nocknock.ui.ScopedViewModel
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
class MainViewModel @Inject constructor(
|
||||
class MainViewModel(
|
||||
private val database: AppDatabase,
|
||||
private val notificationManager: NockNotificationManager,
|
||||
private val validationManager: ValidationManager,
|
||||
@field:IoDispatcher private val ioDispatcher: CoroutineDispatcher
|
||||
) : ScopedViewModel(), LifecycleObserver {
|
||||
mainDispatcher: CoroutineDispatcher,
|
||||
private val ioDispatcher: CoroutineDispatcher
|
||||
) : ScopedViewModel(mainDispatcher), LifecycleObserver {
|
||||
|
||||
private val sites = MutableLiveData<List<Site>>()
|
||||
private val isLoading = MutableLiveData<Boolean>()
|
||||
|
|
|
@ -21,13 +21,10 @@ import android.os.Bundle
|
|||
import android.widget.ArrayAdapter
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import com.afollestad.nocknock.R
|
||||
import com.afollestad.nocknock.broadcasts.StatusUpdateIntentReceiver
|
||||
import com.afollestad.nocknock.data.model.Site
|
||||
import com.afollestad.nocknock.data.model.ValidationMode
|
||||
import com.afollestad.nocknock.broadcasts.StatusUpdateIntentReceiver
|
||||
import com.afollestad.nocknock.utilities.ext.injector
|
||||
import com.afollestad.nocknock.viewcomponents.ext.attachLiveData
|
||||
import com.afollestad.nocknock.viewcomponents.ext.dimenFloat
|
||||
import com.afollestad.nocknock.viewcomponents.ext.onScroll
|
||||
|
@ -51,17 +48,13 @@ import kotlinx.android.synthetic.main.activity_viewsite.textNextCheck
|
|||
import kotlinx.android.synthetic.main.activity_viewsite.textUrlWarning
|
||||
import kotlinx.android.synthetic.main.activity_viewsite.toolbar
|
||||
import kotlinx.android.synthetic.main.activity_viewsite.validationModeDescription
|
||||
import javax.inject.Inject
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
class ViewSiteActivity : AppCompatActivity() {
|
||||
|
||||
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
|
||||
internal val viewModel by viewModel<ViewSiteViewModel>()
|
||||
|
||||
internal val viewModel by lazy {
|
||||
return@lazy ViewModelProviders.of(this, viewModelFactory)
|
||||
.get(ViewSiteViewModel::class.java)
|
||||
}
|
||||
private val statusUpdateReceiver =
|
||||
StatusUpdateIntentReceiver(application) {
|
||||
viewModel.setModel(it)
|
||||
|
@ -70,8 +63,6 @@ class ViewSiteActivity : AppCompatActivity() {
|
|||
@SuppressLint("SetTextI18n")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
injector().injectInto(this)
|
||||
setContentView(R.layout.activity_viewsite)
|
||||
setupUi()
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package com.afollestad.nocknock.ui.viewsite
|
||||
|
||||
import android.app.Application
|
||||
import androidx.annotation.CheckResult
|
||||
import androidx.lifecycle.LifecycleObserver
|
||||
import androidx.lifecycle.LiveData
|
||||
|
@ -33,11 +32,11 @@ import com.afollestad.nocknock.data.model.ValidationMode.TERM_SEARCH
|
|||
import com.afollestad.nocknock.data.model.ValidationResult
|
||||
import com.afollestad.nocknock.data.model.textRes
|
||||
import com.afollestad.nocknock.data.updateSite
|
||||
import com.afollestad.nocknock.di.viewmodels.ScopedViewModel
|
||||
import com.afollestad.nocknock.engine.validation.ValidationManager
|
||||
import com.afollestad.nocknock.notifications.NockNotificationManager
|
||||
import com.afollestad.nocknock.ui.ScopedViewModel
|
||||
import com.afollestad.nocknock.utilities.ext.formatDate
|
||||
import com.afollestad.nocknock.di.qualifiers.IoDispatcher
|
||||
import com.afollestad.nocknock.utilities.providers.StringProvider
|
||||
import com.afollestad.nocknock.viewcomponents.ext.isNullOrLessThan
|
||||
import com.afollestad.nocknock.viewcomponents.ext.map
|
||||
import com.afollestad.nocknock.viewcomponents.ext.zip
|
||||
|
@ -46,16 +45,16 @@ import kotlinx.coroutines.launch
|
|||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.HttpUrl
|
||||
import java.lang.System.currentTimeMillis
|
||||
import javax.inject.Inject
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
class ViewSiteViewModel @Inject constructor(
|
||||
private val app: Application,
|
||||
class ViewSiteViewModel(
|
||||
private val stringProvider: StringProvider,
|
||||
private val database: AppDatabase,
|
||||
private val notificationManager: NockNotificationManager,
|
||||
private val validationManager: ValidationManager,
|
||||
@field:IoDispatcher private val ioDispatcher: CoroutineDispatcher
|
||||
) : ScopedViewModel(), LifecycleObserver {
|
||||
mainDispatcher: CoroutineDispatcher,
|
||||
private val ioDispatcher: CoroutineDispatcher
|
||||
) : ScopedViewModel(mainDispatcher), LifecycleObserver {
|
||||
|
||||
lateinit var site: Site
|
||||
|
||||
|
@ -134,13 +133,13 @@ class ViewSiteViewModel @Inject constructor(
|
|||
|
||||
@CheckResult fun onLastCheckResultText(): LiveData<String> = lastResult.map {
|
||||
if (it == null) {
|
||||
app.getString(R.string.none)
|
||||
stringProvider.get(R.string.none)
|
||||
} else {
|
||||
val statusText = it.status.textRes()
|
||||
if (statusText == 0) {
|
||||
it.reason
|
||||
} else {
|
||||
app.getString(statusText)
|
||||
stringProvider.get(statusText)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -151,7 +150,7 @@ class ViewSiteViewModel @Inject constructor(
|
|||
val disabled = it.first
|
||||
val lastResult = it.second
|
||||
if (disabled) {
|
||||
app.getString(R.string.auto_checks_disabled)
|
||||
stringProvider.get(R.string.auto_checks_disabled)
|
||||
} else {
|
||||
val lastCheck = lastResult?.timestampMs ?: currentTimeMillis()
|
||||
(lastCheck + getCheckIntervalMs()).formatDate()
|
||||
|
|
|
@ -1,8 +1,24 @@
|
|||
/**
|
||||
* Designed and developed by Aidan Follestad (@afollestad)
|
||||
*
|
||||
* 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.afollestad.nocknock
|
||||
|
||||
import androidx.annotation.CheckResult
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.google.common.truth.Truth.assertWithMessage
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
|
@ -22,12 +38,11 @@ class TestLiveData<T>(data: LiveData<T>) {
|
|||
|
||||
fun assertValues(vararg assertValues: T) {
|
||||
val assertList = assertValues.toList()
|
||||
assertWithMessage("Expected: $assertList, but got: $receivedValues").that(receivedValues)
|
||||
.isEqualTo(assertList)
|
||||
assertThat(receivedValues).isEqualTo(assertList)
|
||||
receivedValues.clear()
|
||||
}
|
||||
|
||||
@CheckResult fun values(): List<T> = receivedValues
|
||||
}
|
||||
|
||||
@CheckResult fun <T> LiveData<T>.test() = TestLiveData(this)
|
||||
@CheckResult fun <T> LiveData<T>.test() = TestLiveData(this)
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/**
|
||||
* Designed and developed by Aidan Follestad (@afollestad)
|
||||
*
|
||||
* 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.afollestad.nocknock.broadcasts
|
||||
|
||||
import android.app.Application
|
||||
|
@ -52,4 +67,4 @@ class StatusUpdateIntentReceiverTest {
|
|||
receiver.onPause()
|
||||
verify(app).unregisterReceiver(receiver.intentReceiver)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ package com.afollestad.nocknock.ui.addsite
|
|||
//import org.junit.Before
|
||||
//import org.junit.Test
|
||||
//
|
||||
//class AddSitePresenterTest {
|
||||
//class AddSiteViewModelTest {
|
||||
//
|
||||
// private val database = mockDatabase()
|
||||
// private val checkStatusManager = mock<ValidationManager>()
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package com.afollestad.nocknock.ui.main
|
||||
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import com.afollestad.nocknock.ALL_MOCK_MODELS
|
||||
import com.afollestad.nocknock.MOCK_MODEL_1
|
||||
import com.afollestad.nocknock.MOCK_MODEL_2
|
||||
|
@ -28,22 +29,25 @@ import com.nhaarman.mockitokotlin2.verify
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.After
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
class MainViewModelTest {
|
||||
|
||||
private val database = mockDatabase()
|
||||
private val notificationManager = mock<NockNotificationManager>()
|
||||
private val validationManager = mock<ValidationManager>()
|
||||
|
||||
@Rule @JvmField val rule = InstantTaskExecutorRule()
|
||||
|
||||
private val viewModel = MainViewModel(
|
||||
database,
|
||||
notificationManager,
|
||||
validationManager,
|
||||
Dispatchers.Default
|
||||
).apply {
|
||||
this.mainDispatcher = Dispatchers.Default
|
||||
}
|
||||
Dispatchers.Unconfined,
|
||||
Dispatchers.Unconfined
|
||||
)
|
||||
|
||||
@After fun tearDown() = viewModel.destroy()
|
||||
|
||||
|
@ -92,7 +96,6 @@ class MainViewModelTest {
|
|||
viewModel.postSiteUpdate(updatedModel2)
|
||||
|
||||
sites.assertValues(updatedSites)
|
||||
|
||||
}
|
||||
|
||||
@Test fun refreshSite() {
|
||||
|
@ -116,6 +119,7 @@ class MainViewModelTest {
|
|||
listOf(),
|
||||
ALL_MOCK_MODELS
|
||||
)
|
||||
isLoading.assertValues(true, false)
|
||||
|
||||
val modifiedModel = MOCK_MODEL_1.copy(id = 11111)
|
||||
viewModel.removeSite(modifiedModel)
|
||||
|
@ -140,6 +144,7 @@ class MainViewModelTest {
|
|||
listOf(),
|
||||
ALL_MOCK_MODELS
|
||||
)
|
||||
isLoading.assertValues(true, false)
|
||||
|
||||
val modelsWithout1 = ALL_MOCK_MODELS.toMutableList()
|
||||
.apply {
|
||||
|
|
|
@ -15,6 +15,6 @@
|
|||
*/
|
||||
package com.afollestad.nocknock.ui.viewsite
|
||||
|
||||
class ViewSitePresenterTest {
|
||||
class ViewSiteViewModelTest
|
||||
|
||||
}
|
||||
// TODO this will be mostly identical to the add site test
|
0
utilities/.gitignore → common/.gitignore
vendored
0
utilities/.gitignore → common/.gitignore
vendored
|
@ -26,9 +26,7 @@ dependencies {
|
|||
api 'org.jetbrains.kotlinx:kotlinx-coroutines-core:' + versions.coroutines
|
||||
api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:' + versions.coroutines
|
||||
|
||||
implementation 'com.google.dagger:dagger:' + versions.dagger
|
||||
kapt 'com.google.dagger:dagger-compiler:' + versions.dagger
|
||||
|
||||
implementation 'org.koin:koin-android:' + versions.koin
|
||||
implementation 'org.mozilla:rhino:' + versions.rhino
|
||||
|
||||
testImplementation 'junit:junit:' + versions.junit
|
|
@ -1,11 +1,11 @@
|
|||
/*
|
||||
/**
|
||||
* Designed and developed by Aidan Follestad (@afollestad)
|
||||
*
|
||||
* 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
|
||||
* 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,
|
||||
|
@ -13,63 +13,62 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.afollestad.nocknock.utilities;
|
||||
package com.afollestad.nocknock.utilities
|
||||
|
||||
import com.afollestad.nocknock.utilities.providers.BitmapProvider;
|
||||
import com.afollestad.nocknock.utilities.providers.BundleProvider;
|
||||
import com.afollestad.nocknock.utilities.providers.IntentProvider;
|
||||
import com.afollestad.nocknock.utilities.providers.JobInfoProvider;
|
||||
import com.afollestad.nocknock.utilities.providers.NotificationChannelProvider;
|
||||
import com.afollestad.nocknock.utilities.providers.NotificationProvider;
|
||||
import com.afollestad.nocknock.utilities.providers.RealBitmapProvider;
|
||||
import com.afollestad.nocknock.utilities.providers.RealBundleProvider;
|
||||
import com.afollestad.nocknock.utilities.providers.RealIntentProvider;
|
||||
import com.afollestad.nocknock.utilities.providers.RealJobInfoProvider;
|
||||
import com.afollestad.nocknock.utilities.providers.RealNotificationChannelProvider;
|
||||
import com.afollestad.nocknock.utilities.providers.RealNotificationProvider;
|
||||
import com.afollestad.nocknock.utilities.providers.RealSdkProvider;
|
||||
import com.afollestad.nocknock.utilities.providers.RealStringProvider;
|
||||
import com.afollestad.nocknock.utilities.providers.SdkProvider;
|
||||
import com.afollestad.nocknock.utilities.providers.StringProvider;
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import javax.inject.Singleton;
|
||||
import com.afollestad.nocknock.utilities.Qualifiers.IO_DISPATCHER
|
||||
import com.afollestad.nocknock.utilities.Qualifiers.MAIN_ACTIVITY_CLASS
|
||||
import com.afollestad.nocknock.utilities.Qualifiers.MAIN_DISPATCHER
|
||||
import com.afollestad.nocknock.utilities.providers.BitmapProvider
|
||||
import com.afollestad.nocknock.utilities.providers.BundleProvider
|
||||
import com.afollestad.nocknock.utilities.providers.IntentProvider
|
||||
import com.afollestad.nocknock.utilities.providers.JobInfoProvider
|
||||
import com.afollestad.nocknock.utilities.providers.NotificationChannelProvider
|
||||
import com.afollestad.nocknock.utilities.providers.NotificationProvider
|
||||
import com.afollestad.nocknock.utilities.providers.RealBitmapProvider
|
||||
import com.afollestad.nocknock.utilities.providers.RealBundleProvider
|
||||
import com.afollestad.nocknock.utilities.providers.RealIntentProvider
|
||||
import com.afollestad.nocknock.utilities.providers.RealJobInfoProvider
|
||||
import com.afollestad.nocknock.utilities.providers.RealNotificationChannelProvider
|
||||
import com.afollestad.nocknock.utilities.providers.RealNotificationProvider
|
||||
import com.afollestad.nocknock.utilities.providers.RealSdkProvider
|
||||
import com.afollestad.nocknock.utilities.providers.RealStringProvider
|
||||
import com.afollestad.nocknock.utilities.providers.SdkProvider
|
||||
import com.afollestad.nocknock.utilities.providers.StringProvider
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import org.koin.dsl.module.module
|
||||
|
||||
const val UTILITIES_MODULE = "utilities"
|
||||
|
||||
object Qualifiers {
|
||||
const val MAIN_ACTIVITY_CLASS = "main.main_activity_class"
|
||||
const val MAIN_DISPATCHER = "main.main_dispatcher"
|
||||
const val IO_DISPATCHER = "main.io_dispatcher"
|
||||
}
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
@Module
|
||||
public abstract class UtilitiesModule {
|
||||
val utilitiesModule = module(UTILITIES_MODULE) {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
abstract SdkProvider provideSdkProvider(RealSdkProvider sdkProvider);
|
||||
factory(name = MAIN_DISPATCHER) { Dispatchers.Main }
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
abstract BitmapProvider provideBitmapProvider(RealBitmapProvider bitmapProvider);
|
||||
factory(name = IO_DISPATCHER) { Dispatchers.IO }
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
abstract StringProvider provideStringProvider(RealStringProvider stringProvider);
|
||||
factory { RealSdkProvider() } bind SdkProvider::class
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
abstract IntentProvider provideIntentProvider(RealIntentProvider intentProvider);
|
||||
factory { RealBitmapProvider(get()) } bind BitmapProvider::class
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
abstract NotificationChannelProvider provideChannelProvider(
|
||||
RealNotificationChannelProvider channelProvider);
|
||||
factory { RealStringProvider(get()) } bind StringProvider::class
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
abstract NotificationProvider provideNotificationProvider(
|
||||
RealNotificationProvider notificationProvider);
|
||||
factory {
|
||||
RealIntentProvider(get(), get(name = MAIN_ACTIVITY_CLASS))
|
||||
} bind IntentProvider::class
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
abstract BundleProvider provideBundleProvider(RealBundleProvider bundleProvider);
|
||||
factory {
|
||||
RealNotificationChannelProvider(get())
|
||||
} bind NotificationChannelProvider::class
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
abstract JobInfoProvider provideJobInfoProvider(RealJobInfoProvider jobInfoProvider);
|
||||
factory { RealNotificationProvider(get()) } bind NotificationProvider::class
|
||||
|
||||
factory { RealBundleProvider() } bind BundleProvider::class
|
||||
|
||||
factory { RealJobInfoProvider(get()) } bind JobInfoProvider::class
|
||||
}
|
|
@ -15,11 +15,10 @@
|
|||
*/
|
||||
package com.afollestad.nocknock.utilities.providers
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory.decodeResource
|
||||
import androidx.annotation.DrawableRes
|
||||
import javax.inject.Inject
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
interface BitmapProvider {
|
||||
|
@ -28,11 +27,11 @@ interface BitmapProvider {
|
|||
}
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
class RealBitmapProvider @Inject constructor(
|
||||
private val app: Application
|
||||
class RealBitmapProvider(
|
||||
private val context: Context
|
||||
) : BitmapProvider {
|
||||
|
||||
override fun get(res: Int): Bitmap {
|
||||
return decodeResource(app.resources, res)
|
||||
return decodeResource(context.resources, res)
|
||||
}
|
||||
}
|
|
@ -16,7 +16,6 @@
|
|||
package com.afollestad.nocknock.utilities.providers
|
||||
|
||||
import android.os.PersistableBundle
|
||||
import javax.inject.Inject
|
||||
|
||||
interface IBundle {
|
||||
fun putLong(
|
||||
|
@ -34,7 +33,7 @@ interface BundleProvider {
|
|||
}
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
class RealBundleProvider @Inject constructor() : BundleProvider {
|
||||
class RealBundleProvider : BundleProvider {
|
||||
|
||||
override fun createPersistable(bundler: IBundler): PersistableBundle {
|
||||
val realBundle = PersistableBundle()
|
|
@ -15,13 +15,11 @@
|
|||
*/
|
||||
package com.afollestad.nocknock.utilities.providers
|
||||
|
||||
import android.app.Application
|
||||
import android.app.PendingIntent
|
||||
import android.app.PendingIntent.FLAG_CANCEL_CURRENT
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import com.afollestad.nocknock.utilities.qualifiers.MainActivityClass
|
||||
import java.io.Serializable
|
||||
import javax.inject.Inject
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
interface CanNotifyModel : Serializable {
|
||||
|
@ -42,9 +40,9 @@ interface IntentProvider {
|
|||
}
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
class RealIntentProvider @Inject constructor(
|
||||
private val app: Application,
|
||||
@MainActivityClass private val mainActivity: Class<*>
|
||||
class RealIntentProvider(
|
||||
private val context: Context,
|
||||
private val mainActivityClass: Class<*>
|
||||
) : IntentProvider {
|
||||
|
||||
companion object {
|
||||
|
@ -55,7 +53,7 @@ class RealIntentProvider @Inject constructor(
|
|||
override fun getPendingIntentForViewSite(model: CanNotifyModel): PendingIntent {
|
||||
val openIntent = getIntentForViewSite(model)
|
||||
return PendingIntent.getActivity(
|
||||
app,
|
||||
context,
|
||||
BASE_NOTIFICATION_REQUEST_CODE + model.notiId(),
|
||||
openIntent,
|
||||
FLAG_CANCEL_CURRENT
|
||||
|
@ -63,7 +61,7 @@ class RealIntentProvider @Inject constructor(
|
|||
}
|
||||
|
||||
private fun getIntentForViewSite(model: CanNotifyModel) =
|
||||
Intent(app, mainActivity).apply {
|
||||
Intent(context, mainActivityClass).apply {
|
||||
putExtra(KEY_VIEW_NOTIFICATION_MODEL, model)
|
||||
}
|
||||
}
|
|
@ -15,13 +15,12 @@
|
|||
*/
|
||||
package com.afollestad.nocknock.utilities.providers
|
||||
|
||||
import android.app.Application
|
||||
import android.app.job.JobInfo
|
||||
import android.app.job.JobInfo.NETWORK_TYPE_ANY
|
||||
import android.app.job.JobInfo.NETWORK_TYPE_UNMETERED
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.os.PersistableBundle
|
||||
import javax.inject.Inject
|
||||
|
||||
interface JobInfoProvider {
|
||||
|
||||
|
@ -34,8 +33,8 @@ interface JobInfoProvider {
|
|||
): JobInfo
|
||||
}
|
||||
|
||||
class RealJobInfoProvider @Inject constructor(
|
||||
private val app: Application
|
||||
class RealJobInfoProvider(
|
||||
private val context: Context
|
||||
) : JobInfoProvider {
|
||||
|
||||
// Note: we don't use the periodic feature of JobScheduler because it requires a
|
||||
|
@ -48,7 +47,7 @@ class RealJobInfoProvider @Inject constructor(
|
|||
extras: PersistableBundle,
|
||||
target: Class<*>
|
||||
): JobInfo {
|
||||
val component = ComponentName(app, target)
|
||||
val component = ComponentName(context, target)
|
||||
val networkType = if (onlyUnmeteredNetwork) {
|
||||
NETWORK_TYPE_UNMETERED
|
||||
} else {
|
|
@ -18,7 +18,6 @@ package com.afollestad.nocknock.utilities.providers
|
|||
import android.annotation.TargetApi
|
||||
import android.app.NotificationChannel
|
||||
import android.os.Build.VERSION_CODES
|
||||
import javax.inject.Inject
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
interface NotificationChannelProvider {
|
||||
|
@ -33,7 +32,7 @@ interface NotificationChannelProvider {
|
|||
}
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
class RealNotificationChannelProvider @Inject constructor(
|
||||
class RealNotificationChannelProvider(
|
||||
private val sdkProvider: SdkProvider
|
||||
) : NotificationChannelProvider {
|
||||
|
|
@ -15,13 +15,12 @@
|
|||
*/
|
||||
package com.afollestad.nocknock.utilities.providers
|
||||
|
||||
import android.app.Application
|
||||
import android.app.Notification
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationCompat.DEFAULT_VIBRATE
|
||||
import javax.inject.Inject
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
interface NotificationProvider {
|
||||
|
@ -37,8 +36,8 @@ interface NotificationProvider {
|
|||
}
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
class RealNotificationProvider @Inject constructor(
|
||||
private val app: Application
|
||||
class RealNotificationProvider(
|
||||
private val context: Context
|
||||
) : NotificationProvider {
|
||||
|
||||
override fun create(
|
||||
|
@ -49,7 +48,7 @@ class RealNotificationProvider @Inject constructor(
|
|||
smallIcon: Int,
|
||||
largeIcon: Bitmap
|
||||
): Notification {
|
||||
return NotificationCompat.Builder(app, channelId)
|
||||
return NotificationCompat.Builder(context, channelId)
|
||||
.setContentTitle(title)
|
||||
.setContentText(content)
|
||||
.setContentIntent(intent)
|
|
@ -17,7 +17,6 @@ package com.afollestad.nocknock.utilities.providers
|
|||
|
||||
import android.os.Build.VERSION.SDK_INT
|
||||
import android.os.Build.VERSION_CODES.O
|
||||
import javax.inject.Inject
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
interface SdkProvider {
|
||||
|
@ -26,7 +25,7 @@ interface SdkProvider {
|
|||
}
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
class RealSdkProvider @Inject constructor() : SdkProvider {
|
||||
class RealSdkProvider : SdkProvider {
|
||||
|
||||
override fun hasOreo() = SDK_INT >= O
|
||||
}
|
|
@ -15,9 +15,8 @@
|
|||
*/
|
||||
package com.afollestad.nocknock.utilities.providers
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import androidx.annotation.StringRes
|
||||
import javax.inject.Inject
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
interface StringProvider {
|
||||
|
@ -26,11 +25,11 @@ interface StringProvider {
|
|||
}
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
class RealStringProvider @Inject constructor(
|
||||
private val app: Application
|
||||
class RealStringProvider(
|
||||
private val context: Context
|
||||
) : StringProvider {
|
||||
|
||||
override fun get(res: Int): String {
|
||||
return app.resources.getString(res)
|
||||
return context.resources.getString(res)
|
||||
}
|
||||
}
|
|
@ -17,13 +17,10 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':utilities')
|
||||
implementation project(':common')
|
||||
|
||||
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:' + versions.kotlin
|
||||
|
||||
implementation 'com.google.dagger:dagger:' + versions.dagger
|
||||
annotationProcessor 'com.google.dagger:dagger-compiler:' + versions.dagger
|
||||
|
||||
api 'androidx.room:room-runtime:' + versions.room
|
||||
kapt 'androidx.room:room-compiler:' + versions.room
|
||||
|
||||
|
|
|
@ -12,9 +12,9 @@ ext.versions = [
|
|||
okHttp : '3.12.0',
|
||||
rhino : '1.7.10',
|
||||
|
||||
dagger : '2.19',
|
||||
kotlin : '1.3.10',
|
||||
coroutines : '1.0.1',
|
||||
koin : '1.0.2',
|
||||
|
||||
androidx : '1.0.0',
|
||||
room : '2.0.0',
|
||||
|
@ -30,6 +30,8 @@ ext.versions = [
|
|||
mockito : '2.23.0',
|
||||
mockitoKotlin : '2.0.0-RC1',
|
||||
truth : '0.42',
|
||||
|
||||
androidxTestRunner: '1.1.0',
|
||||
androidxTest : '1.0.0',
|
||||
archTesting : '2.0.0'
|
||||
]
|
||||
|
|
|
@ -14,7 +14,7 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':utilities')
|
||||
implementation project(':common')
|
||||
implementation project(':data')
|
||||
implementation project(':notifications')
|
||||
|
||||
|
@ -22,12 +22,12 @@ dependencies {
|
|||
api 'org.jetbrains.kotlinx:kotlinx-coroutines-core:' + versions.coroutines
|
||||
api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:' + versions.coroutines
|
||||
|
||||
implementation 'org.koin:koin-android:' + versions.koin
|
||||
|
||||
api 'com.squareup.okhttp3:okhttp:' + versions.okHttp
|
||||
|
||||
implementation 'com.google.dagger:dagger:' + versions.dagger
|
||||
kapt 'com.google.dagger:dagger-compiler:' + versions.dagger
|
||||
|
||||
implementation 'com.jakewharton.timber:timber:' + versions.timber
|
||||
|
||||
testImplementation 'junit:junit:' + versions.junit
|
||||
testImplementation 'org.mockito:mockito-core:' + versions.mockito
|
||||
testImplementation 'com.nhaarman.mockitokotlin2:mockito-kotlin:' + versions.mockitoKotlin
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/**
|
||||
* Designed and developed by Aidan Follestad (@afollestad)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -13,19 +13,18 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.afollestad.nocknock.engine;
|
||||
package com.afollestad.nocknock.engine
|
||||
|
||||
import com.afollestad.nocknock.engine.validation.RealValidationManager;
|
||||
import com.afollestad.nocknock.engine.validation.ValidationManager;
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import javax.inject.Singleton;
|
||||
import com.afollestad.nocknock.engine.validation.RealValidationManager
|
||||
import com.afollestad.nocknock.engine.validation.ValidationManager
|
||||
import org.koin.dsl.module.module
|
||||
|
||||
const val ENGINE_MODULE = "engine"
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
@Module
|
||||
public abstract class EngineModule {
|
||||
val engineModule = module(ENGINE_MODULE) {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
abstract ValidationManager provideValidationManager(RealValidationManager checkStatusManager);
|
||||
single {
|
||||
RealValidationManager(get(), get(), get(), get(), get(), get())
|
||||
} bind ValidationManager::class
|
||||
}
|
|
@ -19,19 +19,22 @@ import android.content.BroadcastReceiver
|
|||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.Intent.ACTION_BOOT_COMPLETED
|
||||
import com.afollestad.nocknock.utilities.ext.injector
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.Dispatchers.Main
|
||||
import com.afollestad.nocknock.utilities.Qualifiers.IO_DISPATCHER
|
||||
import com.afollestad.nocknock.utilities.Qualifiers.MAIN_DISPATCHER
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koin.standalone.KoinComponent
|
||||
import org.koin.standalone.inject
|
||||
import timber.log.Timber.d as log
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
class BootReceiver : BroadcastReceiver() {
|
||||
class BootReceiver : BroadcastReceiver(), KoinComponent {
|
||||
|
||||
@Inject lateinit var checkStatusManager: ValidationManager
|
||||
private val validationManager by inject<ValidationManager>()
|
||||
private val mainDispatcher by inject<CoroutineDispatcher>(name = MAIN_DISPATCHER)
|
||||
private val ioDispatcher by inject<CoroutineDispatcher>(name = IO_DISPATCHER)
|
||||
|
||||
override fun onReceive(
|
||||
context: Context,
|
||||
|
@ -42,12 +45,10 @@ class BootReceiver : BroadcastReceiver() {
|
|||
}
|
||||
|
||||
log("Received boot event! Let's go.")
|
||||
context.injector()
|
||||
.injectInto(this)
|
||||
|
||||
val pendingResult = goAsync()
|
||||
GlobalScope.launch(Main) {
|
||||
async(IO) { checkStatusManager.ensureScheduledChecks() }.await()
|
||||
GlobalScope.launch(mainDispatcher) {
|
||||
withContext(ioDispatcher) { validationManager.ensureScheduledChecks() }
|
||||
pendingResult.resultCode = 0
|
||||
pendingResult.finish()
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import android.app.job.JobParameters
|
|||
import android.app.job.JobService
|
||||
import android.content.Intent
|
||||
import com.afollestad.nocknock.data.AppDatabase
|
||||
import com.afollestad.nocknock.data.getSite
|
||||
import com.afollestad.nocknock.data.model.Site
|
||||
import com.afollestad.nocknock.data.model.Status
|
||||
import com.afollestad.nocknock.data.model.Status.CHECKING
|
||||
|
@ -29,11 +30,9 @@ import com.afollestad.nocknock.data.model.ValidationMode.JAVASCRIPT
|
|||
import com.afollestad.nocknock.data.model.ValidationMode.STATUS_CODE
|
||||
import com.afollestad.nocknock.data.model.ValidationMode.TERM_SEARCH
|
||||
import com.afollestad.nocknock.data.model.isPending
|
||||
import com.afollestad.nocknock.data.getSite
|
||||
import com.afollestad.nocknock.data.updateSite
|
||||
import com.afollestad.nocknock.engine.BuildConfig.APPLICATION_ID
|
||||
import com.afollestad.nocknock.notifications.NockNotificationManager
|
||||
import com.afollestad.nocknock.utilities.ext.injector
|
||||
import com.afollestad.nocknock.utilities.js.JavaScript
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.Dispatchers.Main
|
||||
|
@ -41,8 +40,8 @@ import kotlinx.coroutines.GlobalScope
|
|||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koin.android.ext.android.inject
|
||||
import java.lang.System.currentTimeMillis
|
||||
import javax.inject.Inject
|
||||
import timber.log.Timber.d as log
|
||||
|
||||
/**
|
||||
|
@ -59,12 +58,11 @@ class ValidationJob : JobService() {
|
|||
const val KEY_SITE_ID = "site.id"
|
||||
}
|
||||
|
||||
@Inject lateinit var database: AppDatabase
|
||||
@Inject lateinit var checkStatusManager: ValidationManager
|
||||
@Inject lateinit var notificationManager: NockNotificationManager
|
||||
private val database by inject<AppDatabase>()
|
||||
private val validaitonManager by inject<ValidationManager>()
|
||||
private val notificationManager by inject<NockNotificationManager>()
|
||||
|
||||
override fun onStartJob(params: JobParameters): Boolean {
|
||||
injector().injectInto(this)
|
||||
val siteId = params.extras.getLong(KEY_SITE_ID)
|
||||
|
||||
GlobalScope.launch(Main) {
|
||||
|
@ -84,7 +82,7 @@ class ValidationJob : JobService() {
|
|||
|
||||
val jobResult = async(IO) {
|
||||
updateStatus(site, CHECKING)
|
||||
val checkResult = checkStatusManager.performCheck(site)
|
||||
val checkResult = validaitonManager.performCheck(site)
|
||||
val resultModel = checkResult.model
|
||||
val resultResponse = checkResult.response
|
||||
val result = resultModel.lastResult!!
|
||||
|
@ -144,7 +142,7 @@ class ValidationJob : JobService() {
|
|||
notificationManager.postStatusNotification(jobResult)
|
||||
}
|
||||
|
||||
checkStatusManager.scheduleCheck(
|
||||
validaitonManager.scheduleCheck(
|
||||
site = jobResult,
|
||||
fromFinishingJob = true
|
||||
)
|
||||
|
|
|
@ -33,7 +33,6 @@ import okhttp3.Response
|
|||
import org.jetbrains.annotations.TestOnly
|
||||
import java.net.SocketTimeoutException
|
||||
import java.util.concurrent.TimeUnit.MILLISECONDS
|
||||
import javax.inject.Inject
|
||||
import timber.log.Timber.d as log
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
|
@ -61,7 +60,7 @@ interface ValidationManager {
|
|||
suspend fun performCheck(site: Site): CheckResult
|
||||
}
|
||||
|
||||
class RealValidationManager @Inject constructor(
|
||||
class RealValidationManager(
|
||||
private val jobScheduler: JobScheduler,
|
||||
private val okHttpClient: OkHttpClient,
|
||||
private val stringProvider: StringProvider,
|
||||
|
|
|
@ -14,7 +14,7 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':utilities')
|
||||
implementation project(':common')
|
||||
|
||||
api 'androidx.appcompat:appcompat:' + versions.androidx
|
||||
|
||||
|
@ -22,10 +22,10 @@ dependencies {
|
|||
api 'org.jetbrains.kotlinx:kotlinx-coroutines-core:' + versions.coroutines
|
||||
api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:' + versions.coroutines
|
||||
|
||||
implementation 'com.google.dagger:dagger:' + versions.dagger
|
||||
kapt 'com.google.dagger:dagger-compiler:' + versions.dagger
|
||||
implementation 'org.koin:koin-android:' + versions.koin
|
||||
|
||||
implementation 'com.jakewharton.timber:timber:' + versions.timber
|
||||
|
||||
testImplementation 'junit:junit:' + versions.junit
|
||||
testImplementation 'org.mockito:mockito-core:' + versions.mockito
|
||||
testImplementation 'com.nhaarman.mockitokotlin2:mockito-kotlin:' + versions.mockitoKotlin
|
||||
|
|
|
@ -26,8 +26,6 @@ import com.afollestad.nocknock.utilities.providers.NotificationChannelProvider
|
|||
import com.afollestad.nocknock.utilities.providers.NotificationProvider
|
||||
import com.afollestad.nocknock.utilities.providers.RealIntentProvider.Companion.BASE_NOTIFICATION_REQUEST_CODE
|
||||
import com.afollestad.nocknock.utilities.providers.StringProvider
|
||||
import com.afollestad.nocknock.utilities.qualifiers.AppIconRes
|
||||
import javax.inject.Inject
|
||||
import timber.log.Timber.d as log
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
|
@ -45,8 +43,8 @@ interface NockNotificationManager {
|
|||
}
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
class RealNockNotificationManager @Inject constructor(
|
||||
@AppIconRes private val appIconRes: Int,
|
||||
class RealNockNotificationManager(
|
||||
private val appIconRes: Int,
|
||||
private val stockManager: NotificationManager,
|
||||
private val bitmapProvider: BitmapProvider,
|
||||
private val stringProvider: StringProvider,
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* Designed and developed by Aidan Follestad (@afollestad)
|
||||
*
|
||||
* 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.afollestad.nocknock.notifications;
|
||||
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
@Module
|
||||
public abstract class NotificationsModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
abstract NockNotificationManager provideNockNotificationManager(
|
||||
RealNockNotificationManager notificationManager);
|
||||
}
|
|
@ -13,10 +13,28 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.afollestad.nocknock.utilities
|
||||
package com.afollestad.nocknock.notifications
|
||||
|
||||
/** @author Aidan Follestad (@afollestad)*/
|
||||
interface Injector {
|
||||
import com.afollestad.nocknock.notifications.Qualifiers.APP_ICON_RES
|
||||
import org.koin.dsl.module.module
|
||||
|
||||
fun injectInto(target: Any)
|
||||
const val NOTIFICATIONS_MODULE = "notifications"
|
||||
|
||||
object Qualifiers {
|
||||
const val APP_ICON_RES = "main.app_icon_res"
|
||||
}
|
||||
|
||||
val notificationsModule = module(NOTIFICATIONS_MODULE) {
|
||||
|
||||
single {
|
||||
RealNockNotificationManager(
|
||||
get(name = APP_ICON_RES),
|
||||
get(),
|
||||
get(),
|
||||
get(),
|
||||
get(),
|
||||
get(),
|
||||
get()
|
||||
)
|
||||
} bind NockNotificationManager::class
|
||||
}
|
|
@ -1 +1 @@
|
|||
include ':app', ':engine', ':notifications', ':data', ':utilities', ':viewcomponents'
|
||||
include ':app', ':engine', ':notifications', ':data', ':common', ':viewcomponents'
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
/**
|
||||
* Designed and developed by Aidan Follestad (@afollestad)
|
||||
*
|
||||
* 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.afollestad.nocknock.utilities.ext
|
||||
|
||||
import android.app.job.JobService
|
||||
import android.content.Context
|
||||
import com.afollestad.nocknock.utilities.Injector
|
||||
|
||||
fun Context.injector() = applicationContext as Injector
|
||||
|
||||
fun JobService.injector() = applicationContext as Injector
|
|
@ -1,24 +0,0 @@
|
|||
/**
|
||||
* Designed and developed by Aidan Follestad (@afollestad)
|
||||
*
|
||||
* 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.afollestad.nocknock.utilities.qualifiers
|
||||
|
||||
import javax.inject.Qualifier
|
||||
import kotlin.annotation.AnnotationRetention.RUNTIME
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
@Qualifier
|
||||
@Retention(RUNTIME)
|
||||
annotation class AppIconRes
|
|
@ -1,24 +0,0 @@
|
|||
/**
|
||||
* Designed and developed by Aidan Follestad (@afollestad)
|
||||
*
|
||||
* 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.afollestad.nocknock.utilities.qualifiers
|
||||
|
||||
import javax.inject.Qualifier
|
||||
import kotlin.annotation.AnnotationRetention.RUNTIME
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
@Qualifier
|
||||
@Retention(RUNTIME)
|
||||
annotation class MainActivityClass
|
|
@ -15,16 +15,13 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':utilities')
|
||||
implementation project(':common')
|
||||
implementation project(':data')
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:' + versions.androidx
|
||||
api 'androidx.lifecycle:lifecycle-extensions:' + versions.lifecycle
|
||||
|
||||
api 'com.squareup.okhttp3:okhttp:' + versions.okHttp
|
||||
|
||||
implementation 'com.google.dagger:dagger:' + versions.dagger
|
||||
kapt 'com.google.dagger:dagger-compiler:' + versions.dagger
|
||||
}
|
||||
|
||||
apply from: '../spotless.gradle'
|
|
@ -46,7 +46,14 @@ class LoadingIndicatorFrame(
|
|||
isFocusable = true
|
||||
}
|
||||
|
||||
fun setIsLoading(isLoading: Boolean) {
|
||||
fun observe(
|
||||
owner: LifecycleOwner,
|
||||
data: LiveData<Boolean>
|
||||
) = data.observe(owner, Observer {
|
||||
setIsLoading(it)
|
||||
})
|
||||
|
||||
private fun setIsLoading(isLoading: Boolean) {
|
||||
delayHandler.removeCallbacks(showRunnable)
|
||||
if (isLoading) {
|
||||
delayHandler.postDelayed(showRunnable, SHOW_DELAY_MS)
|
||||
|
@ -54,11 +61,4 @@ class LoadingIndicatorFrame(
|
|||
hide()
|
||||
}
|
||||
}
|
||||
|
||||
fun observe(
|
||||
owner: LifecycleOwner,
|
||||
data: LiveData<Boolean>
|
||||
) = data.observe(owner, Observer {
|
||||
setIsLoading(it)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue