diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 6b949dcb..2c3d27b7 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,6 +1,8 @@ plugins { id("com.android.application") + id("dagger.hilt.android.plugin") kotlin("android") + kotlin("kapt") } android { @@ -43,4 +45,11 @@ dependencies { implementation(libs.androidx.compose.runtime) implementation(libs.androidx.preference) implementation(libs.google.material) + implementation(libs.hilt.android) + implementation(libs.okhttp) + kapt(libs.hilt.android.compiler) +} + +kapt { + correctErrorTypes = true } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c01c259d..19d5665e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -5,6 +5,7 @@ () as ClipboardManager +} diff --git a/build.gradle.kts b/build.gradle.kts index d388db81..7beeb5c5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,6 +9,7 @@ buildscript { } dependencies { classpath("com.android.tools.build:gradle:7.2.1") + classpath("com.google.dagger:hilt-android-gradle-plugin:${libs.versions.hilt.get()}") classpath(kotlin("gradle-plugin", libs.versions.kotlin.get())) } } diff --git a/feature/pusher/build.gradle.kts b/feature/pusher/build.gradle.kts index b8d03638..bb9dde89 100644 --- a/feature/pusher/build.gradle.kts +++ b/feature/pusher/build.gradle.kts @@ -1,7 +1,9 @@ plugins { id("com.android.library") + id("dagger.hilt.android.plugin") id("kotlin-parcelize") kotlin("android") + kotlin("kapt") } android { @@ -9,8 +11,6 @@ android { defaultConfig { minSdk = 21 targetSdk = 31 - - consumerProguardFiles("consumer-rules.pro") } buildFeatures { compose = true @@ -41,8 +41,10 @@ dependencies { implementation(libs.androidx.lifecycle.viewmodel) implementation(libs.liveevent) implementation(libs.google.material) + implementation(libs.hilt.android) implementation(libs.kotlin.result) implementation(libs.okhttp) + kapt(libs.hilt.android.compiler) testImplementation(libs.junit) } diff --git a/feature/pusher/consumer-rules.pro b/feature/pusher/consumer-rules.pro deleted file mode 100644 index e69de29b..00000000 diff --git a/feature/pusher/src/main/java/com/chesire/pushie/pusher/ClipboardInteractor.kt b/feature/pusher/src/main/java/com/chesire/pushie/pusher/ClipboardInteractor.kt index 06ecaf62..71777d9d 100644 --- a/feature/pusher/src/main/java/com/chesire/pushie/pusher/ClipboardInteractor.kt +++ b/feature/pusher/src/main/java/com/chesire/pushie/pusher/ClipboardInteractor.kt @@ -2,11 +2,12 @@ package com.chesire.pushie.pusher import android.content.ClipData import android.content.ClipboardManager +import javax.inject.Inject /** * Interacts with the Clipboard to push new values into it. */ -class ClipboardInteractor(private val clipboard: ClipboardManager) { +class ClipboardInteractor @Inject constructor(private val clipboard: ClipboardManager) { /** * Copies [value] directly into the Android clipboard. diff --git a/feature/pusher/src/main/java/com/chesire/pushie/pusher/PusherFragment.kt b/feature/pusher/src/main/java/com/chesire/pushie/pusher/PusherFragment.kt index f63b790f..7bd743e4 100644 --- a/feature/pusher/src/main/java/com/chesire/pushie/pusher/PusherFragment.kt +++ b/feature/pusher/src/main/java/com/chesire/pushie/pusher/PusherFragment.kt @@ -1,59 +1,25 @@ package com.chesire.pushie.pusher -import android.content.ClipboardManager import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.platform.ComposeView -import androidx.core.content.ContextCompat.getSystemService import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels -import androidx.lifecycle.AbstractSavedStateViewModelFactory -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.ViewModel -import androidx.savedstate.SavedStateRegistryOwner import com.chesire.pushie.compose.PushieTheme -import com.chesire.pushie.datasource.pwpush.PWPushRepository -import com.chesire.pushie.datasource.pwpush.remote.PusherApi -import com.chesire.pushie.datastore.PreferenceStore import com.google.android.material.snackbar.Snackbar -import okhttp3.OkHttpClient +import dagger.hilt.android.AndroidEntryPoint /** * Fragment for the main screen of the application, that allows users to use the api service. */ +@AndroidEntryPoint class PusherFragment : Fragment() { - inner class PusherViewModelFactory( - owner: SavedStateRegistryOwner, - defaultArgs: Bundle? = null - ) : AbstractSavedStateViewModelFactory(owner, defaultArgs) { - // TODO: Use Hilt instead here - private val okHttpClient = OkHttpClient() - private val preferenceStore = PreferenceStore(requireContext().applicationContext) - private val pusherApi = PusherApi(okHttpClient, preferenceStore) - private val pusherRepository = PWPushRepository(pusherApi) - private val pusherInteractor = PusherInteractor(pusherRepository) - private val clipboard = getSystemService( - requireContext(), - ClipboardManager::class.java - ) as ClipboardManager - private val clipboardInteractor = ClipboardInteractor(clipboard) - - override fun create( - key: String, - modelClass: Class, - handle: SavedStateHandle - ): T { - @Suppress("UNCHECKED_CAST") - return PusherViewModel(handle, pusherInteractor, clipboardInteractor) as T - } - } - - private val viewModel: PusherViewModel by viewModels { PusherViewModelFactory(this) } + private val viewModel by viewModels() override fun onCreateView( inflater: LayoutInflater, diff --git a/feature/pusher/src/main/java/com/chesire/pushie/pusher/PusherInteractor.kt b/feature/pusher/src/main/java/com/chesire/pushie/pusher/PusherInteractor.kt index d7ae499d..6481c9ba 100644 --- a/feature/pusher/src/main/java/com/chesire/pushie/pusher/PusherInteractor.kt +++ b/feature/pusher/src/main/java/com/chesire/pushie/pusher/PusherInteractor.kt @@ -3,11 +3,12 @@ package com.chesire.pushie.pusher import com.chesire.pushie.datasource.pwpush.PWPushRepository import com.github.michaelbull.result.Result import com.github.michaelbull.result.mapEither +import javax.inject.Inject /** * Interacts with the [PWPushRepository] to send up passwords and generate urls. */ -class PusherInteractor(private val repository: PWPushRepository) { +class PusherInteractor @Inject constructor(private val repository: PWPushRepository) { /** * Sends a new password to the API, and returns a [SendPasswordResult]. diff --git a/feature/pusher/src/main/java/com/chesire/pushie/pusher/PusherViewModel.kt b/feature/pusher/src/main/java/com/chesire/pushie/pusher/PusherViewModel.kt index 8218f554..c3d93c09 100644 --- a/feature/pusher/src/main/java/com/chesire/pushie/pusher/PusherViewModel.kt +++ b/feature/pusher/src/main/java/com/chesire/pushie/pusher/PusherViewModel.kt @@ -9,6 +9,8 @@ import androidx.lifecycle.viewModelScope import com.github.michaelbull.result.onFailure import com.github.michaelbull.result.onSuccess import com.hadilq.liveevent.LiveEvent +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject import kotlinx.coroutines.launch import kotlinx.parcelize.Parcelize @@ -17,7 +19,8 @@ private const val VIEW_KEY = "PusherViewKey" /** * ViewModel to use with the [PusherFragment]. */ -class PusherViewModel( +@HiltViewModel +class PusherViewModel @Inject constructor( state: SavedStateHandle, private val pushInteractor: PusherInteractor, private val clipboardInteractor: ClipboardInteractor diff --git a/feature/settings/build.gradle.kts b/feature/settings/build.gradle.kts index 4ae0cbfe..c2403739 100644 --- a/feature/settings/build.gradle.kts +++ b/feature/settings/build.gradle.kts @@ -8,8 +8,6 @@ android { defaultConfig { minSdk = 21 targetSdk = 31 - - consumerProguardFiles("consumer-rules.pro") } buildFeatures { diff --git a/feature/settings/consumer-rules.pro b/feature/settings/consumer-rules.pro deleted file mode 100644 index e69de29b..00000000 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1125e583..94e87f7f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,7 @@ [versions] compose = "1.1.1" coroutines = "1.6.2" +hilt = "2.38.1" kotlin = "1.6.10" lifecycle = "2.4.1" @@ -17,6 +18,8 @@ androidx-lifecycle-livedata = { module = "androidx.lifecycle:lifecycle-livedata- androidx-lifecycle-viewmodel = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycle" } androidx-preference = { module = "androidx.preference:preference-ktx", version = "1.2.0" } google-material = { module = "com.google.android.material:material", version = "1.6.1" } +hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt"} +hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hilt"} junit = { module = "junit:junit", version = "4.13.2" } kotlin-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "coroutines" } kotlin-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" } diff --git a/library/common/build.gradle.kts b/library/common/build.gradle.kts index c3c5c07a..91d7e5ff 100644 --- a/library/common/build.gradle.kts +++ b/library/common/build.gradle.kts @@ -8,7 +8,5 @@ android { defaultConfig { minSdk = 21 targetSdk = 31 - - consumerProguardFiles("consumer-rules.pro") } } diff --git a/library/common/consumer-rules.pro b/library/common/consumer-rules.pro deleted file mode 100644 index e69de29b..00000000 diff --git a/library/common/src/main/java/com/chesire/pushie/common/ActivityExtensions.kt b/library/common/src/main/java/com/chesire/pushie/common/ActivityExtensions.kt deleted file mode 100644 index 2bede0fb..00000000 --- a/library/common/src/main/java/com/chesire/pushie/common/ActivityExtensions.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.chesire.pushie.common - -import android.app.Activity -import android.content.Context -import android.view.inputmethod.InputMethodManager - -/** - * Closes the soft keyboard. - */ -fun Activity.closeKeyboard() { - currentFocus?.let { - (getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager) - ?.hideSoftInputFromWindow(it.windowToken, 0) - } -} diff --git a/library/compose/build.gradle.kts b/library/compose/build.gradle.kts index 1fde6494..726ded16 100644 --- a/library/compose/build.gradle.kts +++ b/library/compose/build.gradle.kts @@ -8,8 +8,6 @@ android { defaultConfig { minSdk = 21 targetSdk = 31 - - consumerProguardFiles("consumer-rules.pro") } buildFeatures { compose = true diff --git a/library/compose/consumer-rules.pro b/library/compose/consumer-rules.pro deleted file mode 100644 index e69de29b..00000000 diff --git a/library/datasource/pwpush/build.gradle.kts b/library/datasource/pwpush/build.gradle.kts index fc01a427..45664e05 100644 --- a/library/datasource/pwpush/build.gradle.kts +++ b/library/datasource/pwpush/build.gradle.kts @@ -1,6 +1,8 @@ plugins { id("com.android.library") + id("dagger.hilt.android.plugin") kotlin("android") + kotlin("kapt") } android { @@ -8,8 +10,6 @@ android { defaultConfig { minSdk = 21 targetSdk = 31 - - consumerProguardFiles("consumer-rules.pro") } } @@ -18,10 +18,12 @@ dependencies { implementation(project(":library:datastore")) implementation(libs.androidx.appcompat) implementation(libs.androidx.core) + implementation(libs.hilt.android) implementation(libs.kotlin.coroutines.android) implementation(libs.kotlin.coroutines.core) implementation(libs.kotlin.result) implementation(libs.okhttp) + kapt(libs.hilt.android.compiler) testImplementation(libs.junit) } diff --git a/library/datasource/pwpush/consumer-rules.pro b/library/datasource/pwpush/consumer-rules.pro deleted file mode 100644 index e69de29b..00000000 diff --git a/library/datasource/pwpush/src/main/java/com/chesire/pushie/datasource/pwpush/PWPushRepository.kt b/library/datasource/pwpush/src/main/java/com/chesire/pushie/datasource/pwpush/PWPushRepository.kt index 3a39b8d8..7dfcfdb2 100644 --- a/library/datasource/pwpush/src/main/java/com/chesire/pushie/datasource/pwpush/PWPushRepository.kt +++ b/library/datasource/pwpush/src/main/java/com/chesire/pushie/datasource/pwpush/PWPushRepository.kt @@ -5,12 +5,13 @@ import com.chesire.pushie.datasource.pwpush.remote.PushedModel import com.chesire.pushie.datasource.pwpush.remote.PusherApi import com.github.michaelbull.result.Result import com.github.michaelbull.result.onSuccess +import javax.inject.Inject /** * Repository to interact with the [PusherApi] remote data source, and to interact with any local * data sources that store urls. */ -class PWPushRepository(private val passwordAPI: PusherApi) { +class PWPushRepository @Inject constructor(private val pusherApi: PusherApi) { /** * Sends the [password] up to the API. @@ -20,7 +21,7 @@ class PWPushRepository(private val passwordAPI: PusherApi) { expiryDays: Int, expiryViews: Int ): Result { - return passwordAPI + return pusherApi .sendPassword(password, expiryDays, expiryViews) .onSuccess { // TODO: store in local db. Use a flow from there to return these urls diff --git a/library/datasource/pwpush/src/main/java/com/chesire/pushie/datasource/pwpush/remote/PusherApi.kt b/library/datasource/pwpush/src/main/java/com/chesire/pushie/datasource/pwpush/remote/PusherApi.kt index 000f2069..3603bbc2 100644 --- a/library/datasource/pwpush/src/main/java/com/chesire/pushie/datasource/pwpush/remote/PusherApi.kt +++ b/library/datasource/pwpush/src/main/java/com/chesire/pushie/datasource/pwpush/remote/PusherApi.kt @@ -6,6 +6,7 @@ import com.github.michaelbull.result.Err import com.github.michaelbull.result.Ok import com.github.michaelbull.result.Result import java.io.IOException +import javax.inject.Inject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import okhttp3.OkHttpClient @@ -18,7 +19,7 @@ import org.json.JSONObject /** * Interacts with the `pwpush.com` API. */ -class PusherApi( +class PusherApi @Inject constructor( private val client: OkHttpClient, private val preferenceStore: PreferenceStore ) { diff --git a/library/datastore/build.gradle.kts b/library/datastore/build.gradle.kts index c3c5c07a..aa81a6bc 100644 --- a/library/datastore/build.gradle.kts +++ b/library/datastore/build.gradle.kts @@ -1,6 +1,8 @@ plugins { id("com.android.library") + id("dagger.hilt.android.plugin") kotlin("android") + kotlin("kapt") } android { @@ -8,7 +10,10 @@ android { defaultConfig { minSdk = 21 targetSdk = 31 - - consumerProguardFiles("consumer-rules.pro") } } + +dependencies { + implementation(libs.hilt.android) + kapt(libs.hilt.android.compiler) +} diff --git a/library/datastore/consumer-rules.pro b/library/datastore/consumer-rules.pro deleted file mode 100644 index e69de29b..00000000 diff --git a/library/datastore/src/main/java/com/chesire/pushie/datastore/PreferenceStore.kt b/library/datastore/src/main/java/com/chesire/pushie/datastore/PreferenceStore.kt index fd5568f6..8045343a 100644 --- a/library/datastore/src/main/java/com/chesire/pushie/datastore/PreferenceStore.kt +++ b/library/datastore/src/main/java/com/chesire/pushie/datastore/PreferenceStore.kt @@ -3,8 +3,10 @@ package com.chesire.pushie.datastore import android.content.Context import android.content.Context.MODE_PRIVATE import android.content.SharedPreferences +import dagger.hilt.android.qualifiers.ApplicationContext +import javax.inject.Inject -class PreferenceStore(context: Context) { +class PreferenceStore @Inject constructor(@ApplicationContext context: Context) { private val preferences = context.getSharedPreferences( context.getString(R.string.preference_file_name), MODE_PRIVATE diff --git a/library/resources/build.gradle.kts b/library/resources/build.gradle.kts index c3c5c07a..91d7e5ff 100644 --- a/library/resources/build.gradle.kts +++ b/library/resources/build.gradle.kts @@ -8,7 +8,5 @@ android { defaultConfig { minSdk = 21 targetSdk = 31 - - consumerProguardFiles("consumer-rules.pro") } } diff --git a/library/resources/consumer-rules.pro b/library/resources/consumer-rules.pro deleted file mode 100644 index e69de29b..00000000