Use Hilt for DI
This commit is contained in:
parent
ed05d9bd97
commit
1e3788c670
30 changed files with 200 additions and 245 deletions
|
@ -1,10 +1,13 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'kotlin-android-extensions'
|
||||
id 'kotlin-kapt'
|
||||
id 'dagger.hilt.android.plugin'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
compileSdkVersion 31
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
|
@ -15,7 +18,7 @@ android {
|
|||
defaultConfig {
|
||||
applicationId "com.wbrawner.budget"
|
||||
minSdkVersion 26
|
||||
targetSdkVersion 30
|
||||
targetSdkVersion 31
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
vectorDrawables {
|
||||
|
@ -32,6 +35,12 @@ android {
|
|||
sourceSets {
|
||||
androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
|
||||
}
|
||||
buildFeatures {
|
||||
compose true
|
||||
}
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion rootProject.extensions.getExtraProperties().get("compose")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
@ -39,7 +48,7 @@ dependencies {
|
|||
implementation project(':budgetlib')
|
||||
implementation project(':storage')
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||
implementation 'androidx.core:core-ktx:1.6.0'
|
||||
|
@ -49,15 +58,26 @@ dependencies {
|
|||
implementation 'androidx.emoji:emoji-bundled:1.1.0'
|
||||
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
||||
// Dagger
|
||||
implementation "com.google.dagger:dagger:$dagger"
|
||||
kapt "com.google.dagger:dagger-compiler:$dagger"
|
||||
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi"
|
||||
implementation "com.google.dagger:hilt-android:$dagger"
|
||||
kapt "com.google.dagger:hilt-compiler:$dagger"
|
||||
testImplementation 'junit:junit:4.13.1'
|
||||
androidTestImplementation 'androidx.test:runner:1.4.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0'
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
|
||||
def navigation = '2.4.0-alpha07'
|
||||
implementation "androidx.navigation:navigation-fragment-ktx:$navigation"
|
||||
implementation "androidx.navigation:navigation-ui-ktx:$navigation"
|
||||
implementation "androidx.navigation:navigation-compose:$navigation"
|
||||
implementation "androidx.compose.ui:ui:$compose"
|
||||
implementation "androidx.compose.ui:ui-tooling:$compose"
|
||||
implementation "androidx.compose.foundation:foundation:$compose"
|
||||
implementation "androidx.compose.material:material:$compose"
|
||||
implementation "androidx.compose.material:material-icons-core:$compose"
|
||||
implementation "androidx.compose.material:material-icons-extended:$compose"
|
||||
implementation "androidx.compose.animation:animation:$compose"
|
||||
implementation 'androidx.activity:activity-compose:1.3.1'
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:1.0.0-alpha07'
|
||||
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose"
|
||||
|
||||
debugImplementation "com.willowtreeapps.hyperion:hyperion-core:$hyperion"
|
||||
debugImplementation "com.willowtreeapps.hyperion:hyperion-attr:$hyperion"
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
package com.wbrawner.budget
|
||||
|
||||
import android.content.Context
|
||||
import com.wbrawner.budget.common.util.ErrorHandler
|
||||
import com.wbrawner.budget.lib.network.NetworkModule
|
||||
import com.wbrawner.budget.storage.StorageModule
|
||||
import com.wbrawner.budget.ui.MainViewModel
|
||||
import com.wbrawner.budget.ui.SplashViewModel
|
||||
import com.wbrawner.budget.ui.budgets.BudgetFormViewModel
|
||||
import com.wbrawner.budget.ui.budgets.BudgetListViewModel
|
||||
import com.wbrawner.budget.ui.categories.CategoryDetailsViewModel
|
||||
import com.wbrawner.budget.ui.categories.CategoryFormViewModel
|
||||
import com.wbrawner.budget.ui.categories.CategoryListViewModel
|
||||
import com.wbrawner.budget.ui.overview.OverviewViewModel
|
||||
import com.wbrawner.budget.ui.transactions.TransactionFormViewModel
|
||||
import com.wbrawner.budget.ui.transactions.TransactionListViewModel
|
||||
import dagger.BindsInstance
|
||||
import dagger.Component
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@Component(modules = [AppModule::class, StorageModule::class, NetworkModule::class])
|
||||
interface AppComponent {
|
||||
fun inject(app: TwigsApplication)
|
||||
fun inject(viewModel: OverviewViewModel)
|
||||
fun inject(viewModel: SplashViewModel)
|
||||
fun inject(viewModel: MainViewModel)
|
||||
fun inject(viewMode: BudgetListViewModel)
|
||||
fun inject(viewModel: BudgetFormViewModel)
|
||||
fun inject(viewModel: CategoryListViewModel)
|
||||
fun inject(viewModel: CategoryDetailsViewModel)
|
||||
fun inject(viewModel: CategoryFormViewModel)
|
||||
fun inject(viewModel: TransactionListViewModel)
|
||||
fun inject(viewModel: TransactionFormViewModel)
|
||||
|
||||
@Singleton
|
||||
val errorHandler: ErrorHandler
|
||||
|
||||
@Component.Builder
|
||||
interface Builder {
|
||||
@BindsInstance
|
||||
fun context(context: Context): Builder
|
||||
fun build(): AppComponent
|
||||
}
|
||||
}
|
|
@ -5,8 +5,11 @@ import android.util.Log
|
|||
import com.wbrawner.budget.common.util.ErrorHandler
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
class AppModule {
|
||||
@Provides
|
||||
fun provideErrorHandler(): ErrorHandler = object : ErrorHandler {
|
||||
|
|
|
@ -3,28 +3,25 @@ package com.wbrawner.budget
|
|||
import android.app.Application
|
||||
import com.wbrawner.budget.common.budget.BudgetRepository
|
||||
import com.wbrawner.budget.common.user.UserRepository
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
@HiltAndroidApp
|
||||
class TwigsApplication : Application(), CoroutineScope {
|
||||
override val coroutineContext: CoroutineContext = Dispatchers.Main
|
||||
lateinit var appComponent: AppComponent
|
||||
private set
|
||||
|
||||
@Inject
|
||||
lateinit var budgetRepository: BudgetRepository
|
||||
|
||||
@Inject
|
||||
lateinit var userRepository: UserRepository
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
appComponent = DaggerAppComponent.builder()
|
||||
.context(this)
|
||||
.build()
|
||||
appComponent.errorHandler.init(this)
|
||||
appComponent.inject(this)
|
||||
launch {
|
||||
try {
|
||||
userRepository.getProfile()
|
||||
|
|
|
@ -11,7 +11,7 @@ import androidx.navigation.findNavController
|
|||
import androidx.navigation.ui.setupWithNavController
|
||||
import com.google.android.material.navigation.NavigationView
|
||||
import com.wbrawner.budget.R
|
||||
import com.wbrawner.budget.TwigsApplication
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -20,6 +20,7 @@ private const val MENU_GROUP_BUDGETS = 50
|
|||
private const val MENU_ITEM_ADD_BUDGET = 100
|
||||
private const val MENU_ITEM_SETTINGS = 101
|
||||
|
||||
@AndroidEntryPoint
|
||||
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
|
||||
private lateinit var toggle: ActionBarDrawerToggle
|
||||
private val viewModel: MainViewModel by viewModels()
|
||||
|
@ -28,7 +29,6 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
|||
super.onCreate(savedInstanceState)
|
||||
EmojiCompat.init(androidx.emoji.bundled.BundledEmojiCompatConfig(this))
|
||||
setContentView(R.layout.activity_main)
|
||||
(application as TwigsApplication).appComponent.inject(viewModel)
|
||||
setSupportActionBar(action_bar)
|
||||
toggle = ActionBarDrawerToggle(this, drawerLayout, R.string.action_open, R.string.action_close)
|
||||
toggle.isDrawerIndicatorEnabled = true
|
||||
|
|
|
@ -5,29 +5,30 @@ import androidx.lifecycle.viewModelScope
|
|||
import com.wbrawner.budget.common.budget.Budget
|
||||
import com.wbrawner.budget.common.budget.BudgetRepository
|
||||
import com.wbrawner.budget.common.user.UserRepository
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class MainViewModel : ViewModel() {
|
||||
@Inject
|
||||
lateinit var budgetRepository: BudgetRepository
|
||||
|
||||
@Inject
|
||||
lateinit var userRepository: UserRepository
|
||||
@HiltViewModel
|
||||
class MainViewModel @Inject constructor(
|
||||
val budgetRepository: BudgetRepository,
|
||||
val userRepository: UserRepository
|
||||
) : ViewModel() {
|
||||
|
||||
private val budgets = MutableSharedFlow<BudgetList>(replay = 1)
|
||||
|
||||
fun loadBudgets(): SharedFlow<BudgetList> {
|
||||
viewModelScope.launch {
|
||||
val list = budgetRepository.findAll().sortedBy { it.name }
|
||||
budgets.emit(BudgetList(
|
||||
budgets.emit(
|
||||
BudgetList(
|
||||
list,
|
||||
budgetRepository.currentBudget.replayCache.firstOrNull()?.let {
|
||||
list.indexOf(it)
|
||||
}
|
||||
))
|
||||
))
|
||||
}
|
||||
return budgets
|
||||
}
|
||||
|
|
|
@ -8,15 +8,15 @@ import androidx.lifecycle.lifecycleScope
|
|||
import androidx.navigation.findNavController
|
||||
import com.wbrawner.budget.AsyncState
|
||||
import com.wbrawner.budget.R
|
||||
import com.wbrawner.budget.TwigsApplication
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@AndroidEntryPoint
|
||||
class SplashActivity : AppCompatActivity() {
|
||||
private val viewModel: SplashViewModel by viewModels()
|
||||
val viewModel: SplashViewModel by viewModels()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
(application as TwigsApplication).appComponent.inject(viewModel)
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_splash)
|
||||
window.decorView.apply {
|
||||
|
|
|
@ -11,22 +11,19 @@ import com.wbrawner.budget.common.budget.BudgetRepository
|
|||
import com.wbrawner.budget.common.user.UserRepository
|
||||
import com.wbrawner.budget.lib.network.PREF_KEY_BASE_URL
|
||||
import com.wbrawner.budget.load
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import javax.inject.Inject
|
||||
|
||||
class SplashViewModel : ViewModel(), AsyncViewModel<AuthenticationState> {
|
||||
@HiltViewModel
|
||||
class SplashViewModel @Inject constructor(
|
||||
val budgetRepository: BudgetRepository,
|
||||
val userRepository: UserRepository,
|
||||
val sharedPreferences: SharedPreferences,
|
||||
) : ViewModel(), AsyncViewModel<AuthenticationState> {
|
||||
override val state: MutableStateFlow<AsyncState<AuthenticationState>> =
|
||||
MutableStateFlow(AsyncState.Loading)
|
||||
|
||||
@Inject
|
||||
lateinit var budgetRepository: BudgetRepository
|
||||
|
||||
@Inject
|
||||
lateinit var sharedPreferences: SharedPreferences
|
||||
|
||||
@Inject
|
||||
lateinit var userRepository: UserRepository
|
||||
|
||||
suspend fun checkForExistingCredentials() {
|
||||
if (!sharedPreferences.contains(PREF_KEY_TOKEN)) {
|
||||
state.emit(AsyncState.Success(AuthenticationState.Unauthenticated()))
|
||||
|
|
|
@ -10,12 +10,13 @@ import androidx.fragment.app.viewModels
|
|||
import androidx.lifecycle.Observer
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.wbrawner.budget.R
|
||||
import com.wbrawner.budget.TwigsApplication
|
||||
import com.wbrawner.budget.common.budget.Budget
|
||||
import com.wbrawner.budget.common.user.User
|
||||
import com.wbrawner.budget.ui.EXTRA_BUDGET_ID
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.android.synthetic.main.fragment_add_edit_budget.*
|
||||
|
||||
@AndroidEntryPoint
|
||||
class AddEditBudgetFragment : Fragment() {
|
||||
private val viewModel: BudgetFormViewModel by viewModels()
|
||||
|
||||
|
@ -28,17 +29,14 @@ class AddEditBudgetFragment : Fragment() {
|
|||
}
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
(requireActivity().application as TwigsApplication)
|
||||
.appComponent
|
||||
.inject(viewModel)
|
||||
super.onAttach(context)
|
||||
viewModel.getBudget(arguments?.getString(EXTRA_BUDGET_ID))
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? = inflater.inflate(R.layout.fragment_add_edit_budget, container, false)
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
|
@ -51,9 +49,9 @@ class AddEditBudgetFragment : Fragment() {
|
|||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
val suggestionsAdapter = ArrayAdapter<User>(
|
||||
requireContext(),
|
||||
android.R.layout.simple_spinner_item,
|
||||
mutableListOf()
|
||||
requireContext(),
|
||||
android.R.layout.simple_spinner_item,
|
||||
mutableListOf()
|
||||
)
|
||||
usersSearch.setAdapter(suggestionsAdapter)
|
||||
viewModel.userSuggestions.observe(viewLifecycleOwner, Observer {
|
||||
|
@ -87,10 +85,10 @@ class AddEditBudgetFragment : Fragment() {
|
|||
android.R.id.home -> findNavController().navigateUp()
|
||||
R.id.action_save -> {
|
||||
viewModel.saveBudget(Budget(
|
||||
id = id,
|
||||
name = name.text.toString(),
|
||||
description = description.text.toString(),
|
||||
users = emptyList()
|
||||
id = id,
|
||||
name = name.text.toString(),
|
||||
description = description.text.toString(),
|
||||
users = emptyList()
|
||||
))
|
||||
}
|
||||
R.id.action_delete -> {
|
||||
|
|
|
@ -10,21 +10,20 @@ import com.wbrawner.budget.common.budget.BudgetRepository
|
|||
import com.wbrawner.budget.common.user.User
|
||||
import com.wbrawner.budget.common.user.UserRepository
|
||||
import com.wbrawner.budget.common.util.randomId
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class BudgetFormViewModel : ViewModel() {
|
||||
@HiltViewModel
|
||||
class BudgetFormViewModel @Inject constructor(
|
||||
val budgetRepository: BudgetRepository,
|
||||
val userRepository: UserRepository
|
||||
) : ViewModel() {
|
||||
|
||||
val state = MutableLiveData<BudgetFormState>(BudgetFormState.Loading)
|
||||
val users = MutableLiveData<List<User>>()
|
||||
val userSuggestions = MutableLiveData<List<User>>()
|
||||
|
||||
@Inject
|
||||
lateinit var budgetRepository: BudgetRepository
|
||||
|
||||
@Inject
|
||||
lateinit var userRepository: UserRepository
|
||||
|
||||
fun getBudget(id: String? = null) {
|
||||
viewModelScope.launch {
|
||||
state.postValue(BudgetFormState.Loading)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.wbrawner.budget.ui.budgets
|
||||
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
|
@ -9,21 +8,17 @@ import androidx.fragment.app.viewModels
|
|||
import androidx.navigation.NavController
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.wbrawner.budget.R
|
||||
import com.wbrawner.budget.TwigsApplication
|
||||
import com.wbrawner.budget.common.budget.Budget
|
||||
import com.wbrawner.budget.ui.EXTRA_BUDGET_ID
|
||||
import com.wbrawner.budget.ui.base.BindableAdapter
|
||||
import com.wbrawner.budget.ui.base.BindableData
|
||||
import com.wbrawner.budget.ui.base.ListWithAddButtonFragment
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
class BudgetListFragment : ListWithAddButtonFragment<Budget, BudgetListViewModel>() {
|
||||
override val noItemsStringRes: Int = R.string.overview_no_data
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
(requireActivity().application as TwigsApplication).appComponent.inject(viewModel)
|
||||
super.onAttach(context)
|
||||
}
|
||||
|
||||
override val viewModel: BudgetListViewModel by viewModels()
|
||||
|
||||
override fun reloadItems() {
|
||||
|
|
|
@ -6,18 +6,20 @@ import com.wbrawner.budget.AsyncViewModel
|
|||
import com.wbrawner.budget.common.budget.Budget
|
||||
import com.wbrawner.budget.common.budget.BudgetRepository
|
||||
import com.wbrawner.budget.load
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import javax.inject.Inject
|
||||
|
||||
class BudgetListViewModel : ViewModel(), AsyncViewModel<List<Budget>> {
|
||||
override val state: MutableStateFlow<AsyncState<List<Budget>>> = MutableStateFlow(AsyncState.Loading)
|
||||
|
||||
@Inject
|
||||
lateinit var budgetRepo: BudgetRepository
|
||||
@HiltViewModel
|
||||
class BudgetListViewModel @Inject constructor(
|
||||
val budgetRepository: BudgetRepository
|
||||
) : ViewModel(), AsyncViewModel<List<Budget>> {
|
||||
override val state: MutableStateFlow<AsyncState<List<Budget>>> =
|
||||
MutableStateFlow(AsyncState.Loading)
|
||||
|
||||
fun getBudgets() {
|
||||
load {
|
||||
budgetRepo.findAll().toList()
|
||||
budgetRepository.findAll().toList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.wbrawner.budget.ui.categories
|
||||
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.*
|
||||
|
@ -12,27 +11,20 @@ import androidx.lifecycle.lifecycleScope
|
|||
import androidx.navigation.fragment.findNavController
|
||||
import com.wbrawner.budget.AsyncState
|
||||
import com.wbrawner.budget.R
|
||||
import com.wbrawner.budget.TwigsApplication
|
||||
import com.wbrawner.budget.ui.EXTRA_BUDGET_ID
|
||||
import com.wbrawner.budget.ui.EXTRA_CATEGORY_ID
|
||||
import com.wbrawner.budget.ui.EXTRA_CATEGORY_NAME
|
||||
import com.wbrawner.budget.ui.toAmountSpannable
|
||||
import com.wbrawner.budget.ui.transactions.TransactionListFragment
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.android.synthetic.main.fragment_category_details.*
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
* A simple [Fragment] subclass.
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class CategoryDetailsFragment : Fragment() {
|
||||
val viewModel: CategoryDetailsViewModel by viewModels()
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
(requireActivity().application as TwigsApplication).appComponent.inject(viewModel)
|
||||
super.onAttach(context)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
|
|
|
@ -7,15 +7,17 @@ import com.wbrawner.budget.AsyncViewModel
|
|||
import com.wbrawner.budget.common.category.Category
|
||||
import com.wbrawner.budget.common.category.CategoryRepository
|
||||
import com.wbrawner.budget.load
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class CategoryDetailsViewModel : ViewModel(), AsyncViewModel<CategoryDetails> {
|
||||
override val state: MutableStateFlow<AsyncState<CategoryDetails>> = MutableStateFlow(AsyncState.Loading)
|
||||
|
||||
@Inject
|
||||
lateinit var categoryRepo: CategoryRepository
|
||||
@HiltViewModel
|
||||
class CategoryDetailsViewModel @Inject constructor(
|
||||
val categoryRepo: CategoryRepository
|
||||
) : ViewModel(), AsyncViewModel<CategoryDetails> {
|
||||
override val state: MutableStateFlow<AsyncState<CategoryDetails>> =
|
||||
MutableStateFlow(AsyncState.Loading)
|
||||
|
||||
fun getCategory(id: String? = null) {
|
||||
viewModelScope.launch {
|
||||
|
|
|
@ -14,15 +14,16 @@ import androidx.core.app.TaskStackBuilder
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import com.wbrawner.budget.AsyncState
|
||||
import com.wbrawner.budget.R
|
||||
import com.wbrawner.budget.TwigsApplication
|
||||
import com.wbrawner.budget.common.budget.Budget
|
||||
import com.wbrawner.budget.common.category.Category
|
||||
import com.wbrawner.budget.ui.EXTRA_CATEGORY_ID
|
||||
import com.wbrawner.budget.ui.transactions.toLong
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.android.synthetic.main.activity_add_edit_category.*
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@AndroidEntryPoint
|
||||
class CategoryFormActivity : AppCompatActivity() {
|
||||
val viewModel: CategoryFormViewModel by viewModels()
|
||||
var id: String? = null
|
||||
|
@ -33,7 +34,6 @@ class CategoryFormActivity : AppCompatActivity() {
|
|||
setContentView(R.layout.activity_add_edit_category)
|
||||
setSupportActionBar(action_bar)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
(application as TwigsApplication).appComponent.inject(viewModel)
|
||||
lifecycleScope.launch {
|
||||
viewModel.state.collect { state ->
|
||||
when (state) {
|
||||
|
|
|
@ -12,17 +12,18 @@ import com.wbrawner.budget.common.category.Category
|
|||
import com.wbrawner.budget.common.category.CategoryRepository
|
||||
import com.wbrawner.budget.common.util.randomId
|
||||
import com.wbrawner.budget.load
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class CategoryFormViewModel : ViewModel(), AsyncViewModel<CategoryFormState> {
|
||||
override val state: MutableStateFlow<AsyncState<CategoryFormState>> = MutableStateFlow(AsyncState.Loading)
|
||||
@Inject
|
||||
lateinit var categoryRepository: CategoryRepository
|
||||
|
||||
@Inject
|
||||
lateinit var budgetRepository: BudgetRepository
|
||||
@HiltViewModel
|
||||
class CategoryFormViewModel @Inject constructor(
|
||||
val categoryRepository: CategoryRepository,
|
||||
val budgetRepository: BudgetRepository
|
||||
) : ViewModel(), AsyncViewModel<CategoryFormState> {
|
||||
override val state: MutableStateFlow<AsyncState<CategoryFormState>> =
|
||||
MutableStateFlow(AsyncState.Loading)
|
||||
|
||||
fun loadCategory(categoryId: String? = null) {
|
||||
load {
|
||||
|
@ -30,8 +31,8 @@ class CategoryFormViewModel : ViewModel(), AsyncViewModel<CategoryFormState> {
|
|||
categoryRepository.findById(it)
|
||||
} ?: Category("", title = "", amount = 0)
|
||||
CategoryFormState(
|
||||
category,
|
||||
budgetRepository.findAll().toList()
|
||||
category,
|
||||
budgetRepository.findAll().toList()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -65,15 +66,15 @@ class CategoryFormViewModel : ViewModel(), AsyncViewModel<CategoryFormState> {
|
|||
}
|
||||
|
||||
data class CategoryFormState(
|
||||
val category: Category,
|
||||
val budgets: List<Budget>,
|
||||
@StringRes val titleRes: Int,
|
||||
val showDeleteButton: Boolean
|
||||
val category: Category,
|
||||
val budgets: List<Budget>,
|
||||
@StringRes val titleRes: Int,
|
||||
val showDeleteButton: Boolean
|
||||
) {
|
||||
constructor(category: Category, budgets: List<Budget>) : this(
|
||||
category,
|
||||
budgets,
|
||||
category.id?.let { R.string.title_edit_category } ?: R.string.title_add_category,
|
||||
category.id != null
|
||||
category,
|
||||
budgets,
|
||||
category.id?.let { R.string.title_edit_category } ?: R.string.title_add_category,
|
||||
category.id != null
|
||||
)
|
||||
}
|
|
@ -10,15 +10,16 @@ import androidx.fragment.app.viewModels
|
|||
import androidx.navigation.NavController
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.wbrawner.budget.R
|
||||
import com.wbrawner.budget.TwigsApplication
|
||||
import com.wbrawner.budget.common.category.Category
|
||||
import com.wbrawner.budget.ui.EXTRA_CATEGORY_ID
|
||||
import com.wbrawner.budget.ui.EXTRA_CATEGORY_NAME
|
||||
import com.wbrawner.budget.ui.base.BindableAdapter
|
||||
import com.wbrawner.budget.ui.base.BindableData
|
||||
import com.wbrawner.budget.ui.base.ListWithAddButtonFragment
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@AndroidEntryPoint
|
||||
class CategoryListFragment : ListWithAddButtonFragment<Category, CategoryListViewModel>() {
|
||||
override val noItemsStringRes: Int = R.string.categories_no_data
|
||||
override val viewModel: CategoryListViewModel by viewModels()
|
||||
|
@ -30,11 +31,6 @@ class CategoryListFragment : ListWithAddButtonFragment<Category, CategoryListVie
|
|||
|
||||
override val constructors: Map<Int, (View) -> BindableAdapter.BindableViewHolder<Category>> = mapOf(CATEGORY_VIEW to { v -> CategoryViewHolder(v, viewModel, findNavController()) })
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
(requireActivity().application as TwigsApplication).appComponent.inject(viewModel)
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun addItem() {
|
||||
startActivity(Intent(activity, CategoryFormActivity::class.java))
|
||||
}
|
||||
|
|
|
@ -7,21 +7,20 @@ import com.wbrawner.budget.common.budget.BudgetRepository
|
|||
import com.wbrawner.budget.common.category.Category
|
||||
import com.wbrawner.budget.common.category.CategoryRepository
|
||||
import com.wbrawner.budget.load
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class CategoryListViewModel : ViewModel(), AsyncViewModel<List<Category>> {
|
||||
@HiltViewModel
|
||||
class CategoryListViewModel @Inject constructor(
|
||||
val budgetRepo: BudgetRepository,
|
||||
val categoryRepo: CategoryRepository
|
||||
) : ViewModel(), AsyncViewModel<List<Category>> {
|
||||
override val state: MutableStateFlow<AsyncState<List<Category>>> =
|
||||
MutableStateFlow(AsyncState.Loading)
|
||||
|
||||
@Inject
|
||||
lateinit var budgetRepo: BudgetRepository
|
||||
|
||||
@Inject
|
||||
lateinit var categoryRepo: CategoryRepository
|
||||
|
||||
fun getCategories() {
|
||||
viewModelScope.launch {
|
||||
budgetRepo.currentBudget.collect {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.wbrawner.budget.ui.overview
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
|
@ -11,22 +10,18 @@ import androidx.fragment.app.viewModels
|
|||
import androidx.lifecycle.Observer
|
||||
import com.wbrawner.budget.AsyncState
|
||||
import com.wbrawner.budget.R
|
||||
import com.wbrawner.budget.TwigsApplication
|
||||
import com.wbrawner.budget.ui.toAmountSpannable
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.android.synthetic.main.fragment_overview.*
|
||||
|
||||
@AndroidEntryPoint
|
||||
class OverviewFragment : Fragment() {
|
||||
val viewModel: OverviewViewModel by viewModels()
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
(requireActivity().application as TwigsApplication).appComponent.inject(viewModel)
|
||||
super.onAttach(context)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? = inflater.inflate(R.layout.fragment_overview, container, false)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
|
|
|
@ -5,19 +5,18 @@ import com.wbrawner.budget.AsyncState
|
|||
import com.wbrawner.budget.common.budget.Budget
|
||||
import com.wbrawner.budget.common.budget.BudgetRepository
|
||||
import com.wbrawner.budget.common.transaction.TransactionRepository
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class OverviewViewModel : ViewModel() {
|
||||
@HiltViewModel
|
||||
class OverviewViewModel @Inject constructor(
|
||||
val budgetRepo: BudgetRepository,
|
||||
val transactionRepo: TransactionRepository
|
||||
) : ViewModel() {
|
||||
val state = MutableLiveData<AsyncState<OverviewState>>(AsyncState.Loading)
|
||||
|
||||
@Inject
|
||||
lateinit var budgetRepo: BudgetRepository
|
||||
|
||||
@Inject
|
||||
lateinit var transactionRepo: TransactionRepository
|
||||
|
||||
fun loadOverview() {
|
||||
viewModelScope.launch {
|
||||
budgetRepo.currentBudget.collect { budget ->
|
||||
|
|
|
@ -16,12 +16,12 @@ import androidx.core.app.NavUtils
|
|||
import androidx.core.app.TaskStackBuilder
|
||||
import com.google.android.material.datepicker.MaterialDatePicker
|
||||
import com.wbrawner.budget.R
|
||||
import com.wbrawner.budget.TwigsApplication
|
||||
import com.wbrawner.budget.common.budget.Budget
|
||||
import com.wbrawner.budget.common.category.Category
|
||||
import com.wbrawner.budget.common.transaction.Transaction
|
||||
import com.wbrawner.budget.ui.EXTRA_TRANSACTION_ID
|
||||
import com.wbrawner.budget.ui.MainActivity
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.android.synthetic.main.activity_add_edit_transaction.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
@ -31,6 +31,7 @@ import java.util.*
|
|||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.math.max
|
||||
|
||||
@AndroidEntryPoint
|
||||
class TransactionFormActivity : AppCompatActivity(), CoroutineScope {
|
||||
override val coroutineContext: CoroutineContext = Dispatchers.Main
|
||||
|
||||
|
@ -47,7 +48,6 @@ class TransactionFormActivity : AppCompatActivity(), CoroutineScope {
|
|||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
setTitle(R.string.title_add_transaction)
|
||||
edit_transaction_type_expense.isChecked = true
|
||||
(application as TwigsApplication).appComponent.inject(viewModel)
|
||||
launch {
|
||||
val accounts = viewModel.getAccounts().toTypedArray()
|
||||
setCategories()
|
||||
|
|
|
@ -7,22 +7,18 @@ import com.wbrawner.budget.common.category.CategoryRepository
|
|||
import com.wbrawner.budget.common.transaction.Transaction
|
||||
import com.wbrawner.budget.common.transaction.TransactionRepository
|
||||
import com.wbrawner.budget.common.user.UserRepository
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class TransactionFormViewModel : ViewModel() {
|
||||
@Inject
|
||||
lateinit var budgetRepository: BudgetRepository
|
||||
|
||||
@Inject
|
||||
lateinit var categoryRepository: CategoryRepository
|
||||
|
||||
@Inject
|
||||
lateinit var transactionRepository: TransactionRepository
|
||||
|
||||
@Inject
|
||||
lateinit var userRepository: UserRepository
|
||||
@HiltViewModel
|
||||
class TransactionFormViewModel @Inject constructor(
|
||||
val budgetRepository: BudgetRepository,
|
||||
val categoryRepository: CategoryRepository,
|
||||
val transactionRepository: TransactionRepository,
|
||||
val userRepository: UserRepository,
|
||||
) : ViewModel() {
|
||||
|
||||
var currentUserId: String? = null
|
||||
private set
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.wbrawner.budget.ui.transactions
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
|
@ -15,7 +14,6 @@ import androidx.fragment.app.viewModels
|
|||
import androidx.navigation.NavController
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.wbrawner.budget.R
|
||||
import com.wbrawner.budget.TwigsApplication
|
||||
import com.wbrawner.budget.common.transaction.Transaction
|
||||
import com.wbrawner.budget.ui.EXTRA_BUDGET_ID
|
||||
import com.wbrawner.budget.ui.EXTRA_CATEGORY_ID
|
||||
|
@ -23,8 +21,10 @@ import com.wbrawner.budget.ui.EXTRA_TRANSACTION_ID
|
|||
import com.wbrawner.budget.ui.base.BindableAdapter
|
||||
import com.wbrawner.budget.ui.base.BindableData
|
||||
import com.wbrawner.budget.ui.base.ListWithAddButtonFragment
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import java.text.SimpleDateFormat
|
||||
|
||||
@AndroidEntryPoint
|
||||
class TransactionListFragment : ListWithAddButtonFragment<Transaction, TransactionListViewModel>() {
|
||||
override val noItemsStringRes: Int = R.string.transactions_no_data
|
||||
override val viewModel: TransactionListViewModel by viewModels()
|
||||
|
@ -37,11 +37,6 @@ class TransactionListFragment : ListWithAddButtonFragment<Transaction, Transacti
|
|||
|
||||
override fun bindData(data: Transaction): BindableData<Transaction> = BindableData(data, TRANSACTION_VIEW)
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
(requireActivity().application as TwigsApplication).appComponent.inject(viewModel)
|
||||
super.onAttach(context)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
|
@ -57,15 +52,15 @@ class TransactionListFragment : ListWithAddButtonFragment<Transaction, Transacti
|
|||
}
|
||||
// TODO: Launch a Google Drive-style search/filter screen
|
||||
AlertDialog.Builder(requireContext(), R.style.DialogTheme)
|
||||
.setTitle("Filter Transactions")
|
||||
.setPositiveButton(R.string.action_submit) { _, _ ->
|
||||
reloadItems()
|
||||
}
|
||||
.setNegativeButton(R.string.action_cancel) { _, _ ->
|
||||
// Do nothing
|
||||
}
|
||||
.create()
|
||||
.show()
|
||||
.setTitle("Filter Transactions")
|
||||
.setPositiveButton(R.string.action_submit) { _, _ ->
|
||||
reloadItems()
|
||||
}
|
||||
.setNegativeButton(R.string.action_cancel) { _, _ ->
|
||||
// Do nothing
|
||||
}
|
||||
.create()
|
||||
.show()
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
@ -8,21 +8,22 @@ import com.wbrawner.budget.common.budget.BudgetRepository
|
|||
import com.wbrawner.budget.common.transaction.Transaction
|
||||
import com.wbrawner.budget.common.transaction.TransactionRepository
|
||||
import com.wbrawner.budget.load
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class TransactionListViewModel : ViewModel(), AsyncViewModel<List<Transaction>> {
|
||||
@Inject
|
||||
lateinit var budgetRepository: BudgetRepository
|
||||
|
||||
@Inject
|
||||
lateinit var transactionRepo: TransactionRepository
|
||||
override val state: MutableStateFlow<AsyncState<List<Transaction>>> = MutableStateFlow(AsyncState.Loading)
|
||||
@HiltViewModel
|
||||
class TransactionListViewModel @Inject constructor(
|
||||
val budgetRepository: BudgetRepository,
|
||||
val transactionRepo: TransactionRepository,
|
||||
) : ViewModel(), AsyncViewModel<List<Transaction>> {
|
||||
override val state: MutableStateFlow<AsyncState<List<Transaction>>> =
|
||||
MutableStateFlow(AsyncState.Loading)
|
||||
|
||||
fun getTransactions(
|
||||
categoryId: String? = null,
|
||||
categoryId: String? = null,
|
||||
) {
|
||||
viewModelScope.launch {
|
||||
budgetRepository.currentBudget.collect { budget ->
|
||||
|
|
|
@ -2,14 +2,15 @@ plugins {
|
|||
id 'com.android.library'
|
||||
id 'kotlin-android'
|
||||
id 'kotlin-kapt'
|
||||
id 'dagger.hilt.android.plugin'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
compileSdkVersion 31
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 26
|
||||
targetSdkVersion 30
|
||||
targetSdkVersion 31
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
@ -35,8 +36,8 @@ dependencies {
|
|||
implementation "io.ktor:ktor-client-logging:$ktor_version"
|
||||
implementation "ch.qos.logback:logback-classic:1.2.5"
|
||||
// Dagger
|
||||
implementation "com.google.dagger:dagger:$rootProject.ext.dagger"
|
||||
kapt "com.google.dagger:dagger-compiler:$rootProject.ext.dagger"
|
||||
implementation "com.google.dagger:hilt-android:$rootProject.ext.dagger"
|
||||
kapt "com.google.dagger:hilt-compiler:$rootProject.ext.dagger"
|
||||
testImplementation 'junit:junit:4.13.1'
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
}
|
||||
|
|
|
@ -12,11 +12,14 @@ import com.wbrawner.budget.lib.repository.NetworkTransactionRepository
|
|||
import com.wbrawner.budget.lib.repository.NetworkUserRepository
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
const val PREF_KEY_BASE_URL = "baseUrl"
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
class NetworkModule {
|
||||
@Singleton
|
||||
@Provides
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.compose = '1.0.1'
|
||||
ext.dagger = '2.38.1'
|
||||
ext.hyperion = '0.9.33'
|
||||
ext.kotlin_version = '1.5.21'
|
||||
|
@ -15,6 +16,7 @@ buildscript {
|
|||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.0.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "com.google.dagger:hilt-android-gradle-plugin:$dagger"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,11 +6,11 @@ plugins {
|
|||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
compileSdkVersion 31
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 26
|
||||
targetSdkVersion 30
|
||||
targetSdkVersion 31
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
plugins {
|
||||
id 'com.android.library'
|
||||
id 'kotlin-android'
|
||||
id 'kotlin-kapt'
|
||||
id 'dagger.hilt.android.plugin'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
|
||||
compileSdkVersion 31
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 30
|
||||
targetSdkVersion 31
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
|
@ -32,8 +34,8 @@ dependencies {
|
|||
implementation "androidx.security:security-crypto:$security_version"
|
||||
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||
// Dagger
|
||||
implementation "com.google.dagger:dagger:$rootProject.ext.dagger"
|
||||
kapt "com.google.dagger:dagger-compiler:$rootProject.ext.dagger"
|
||||
implementation "com.google.dagger:hilt-android:$rootProject.ext.dagger"
|
||||
kapt "com.google.dagger:hilt-compiler:$rootProject.ext.dagger"
|
||||
testImplementation 'junit:junit:4.13.1'
|
||||
androidTestImplementation 'androidx.test:runner:1.4.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
|
|
|
@ -5,20 +5,24 @@ import android.content.SharedPreferences
|
|||
import androidx.security.crypto.EncryptedSharedPreferences
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
const val ENCRYPTED_SHARED_PREFS_FILE_NAME = "shared-prefs.encrypted"
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
class StorageModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideSharedPreferences(context: Context): SharedPreferences =
|
||||
EncryptedSharedPreferences.create(
|
||||
ENCRYPTED_SHARED_PREFS_FILE_NAME,
|
||||
"budget",
|
||||
context,
|
||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
||||
)
|
||||
fun provideSharedPreferences(@ApplicationContext context: Context): SharedPreferences =
|
||||
EncryptedSharedPreferences.create(
|
||||
ENCRYPTED_SHARED_PREFS_FILE_NAME,
|
||||
"budget",
|
||||
context,
|
||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
||||
)
|
||||
}
|
Loading…
Reference in a new issue