diff --git a/app/src/main/java/com/example/util/simpletimetracker/ui/MainActivity.kt b/app/src/main/java/com/example/util/simpletimetracker/ui/MainActivity.kt index 2459860c..b63fd481 100644 --- a/app/src/main/java/com/example/util/simpletimetracker/ui/MainActivity.kt +++ b/app/src/main/java/com/example/util/simpletimetracker/ui/MainActivity.kt @@ -4,11 +4,9 @@ import android.os.Bundle import androidx.activity.viewModels import com.example.util.simpletimetracker.core.base.BaseActivity import com.example.util.simpletimetracker.core.di.BaseViewModelFactory -import com.example.util.simpletimetracker.core.extension.combineLiveData import com.example.util.simpletimetracker.core.manager.ThemeManager import com.example.util.simpletimetracker.core.sharedViewModel.BackupViewModel import com.example.util.simpletimetracker.databinding.MainActivityBinding -import com.example.util.simpletimetracker.domain.extension.orFalse import com.example.util.simpletimetracker.feature_views.extension.visible import com.example.util.simpletimetracker.navigation.Router import dagger.hilt.android.AndroidEntryPoint @@ -52,12 +50,10 @@ class MainActivity : BaseActivity() { } private fun initViewModel() { - combineLiveData( - backupViewModel.progressVisibility, - backupViewModel.automaticBackupProgress, - backupViewModel.automaticExportProgress, - ).observe { - binding.mainProgress.visible = it.first.orFalse() || it.second.orFalse() || it.third.orFalse() + backupViewModel.progressVisibility.observe { + binding.mainProgress.visible = it + // TODO here to check that if automatic update finishes with error while app is opened. + // probably can be moved to VM because progress cen be shown for other reasons. backupViewModel.onFileWork() } } diff --git a/core/src/main/java/com/example/util/simpletimetracker/core/repo/DataEditRepo.kt b/core/src/main/java/com/example/util/simpletimetracker/core/repo/DataEditRepo.kt new file mode 100644 index 00000000..eab53ecb --- /dev/null +++ b/core/src/main/java/com/example/util/simpletimetracker/core/repo/DataEditRepo.kt @@ -0,0 +1,8 @@ +package com.example.util.simpletimetracker.core.repo + +import androidx.lifecycle.LiveData + +interface DataEditRepo { + + val inProgress: LiveData +} \ No newline at end of file diff --git a/core/src/main/java/com/example/util/simpletimetracker/core/repo/ResourceRepo.kt b/core/src/main/java/com/example/util/simpletimetracker/core/repo/ResourceRepo.kt index 177ed4d3..bb234170 100644 --- a/core/src/main/java/com/example/util/simpletimetracker/core/repo/ResourceRepo.kt +++ b/core/src/main/java/com/example/util/simpletimetracker/core/repo/ResourceRepo.kt @@ -1,10 +1,12 @@ package com.example.util.simpletimetracker.core.repo import android.content.Context +import android.util.TypedValue import androidx.annotation.ColorRes import androidx.annotation.DimenRes import androidx.annotation.PluralsRes import androidx.annotation.StringRes +import androidx.appcompat.view.ContextThemeWrapper import androidx.core.content.ContextCompat import com.example.util.simpletimetracker.feature_views.extension.pxToDp import dagger.hilt.android.qualifiers.ApplicationContext @@ -33,4 +35,12 @@ class ResourceRepo @Inject constructor( fun getDimenInDp(@DimenRes dimenResId: Int): Int { return context.resources.getDimension(dimenResId).pxToDp() } + + fun getThemedAttr(attrId: Int, themeId: Int): Int { + return TypedValue().apply { + ContextThemeWrapper(context, themeId) + .theme + .resolveAttribute(attrId, this, true) + }.data + } } \ No newline at end of file diff --git a/core/src/main/java/com/example/util/simpletimetracker/core/sharedViewModel/BackupViewModel.kt b/core/src/main/java/com/example/util/simpletimetracker/core/sharedViewModel/BackupViewModel.kt index 2baa7e2e..0860c4bc 100644 --- a/core/src/main/java/com/example/util/simpletimetracker/core/sharedViewModel/BackupViewModel.kt +++ b/core/src/main/java/com/example/util/simpletimetracker/core/sharedViewModel/BackupViewModel.kt @@ -2,6 +2,7 @@ package com.example.util.simpletimetracker.core.sharedViewModel import androidx.annotation.StringRes import androidx.lifecycle.LiveData +import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -10,8 +11,10 @@ import com.example.util.simpletimetracker.core.extension.set import com.example.util.simpletimetracker.core.mapper.TimeMapper import com.example.util.simpletimetracker.core.repo.AutomaticBackupRepo import com.example.util.simpletimetracker.core.repo.AutomaticExportRepo +import com.example.util.simpletimetracker.core.repo.DataEditRepo import com.example.util.simpletimetracker.core.repo.PermissionRepo import com.example.util.simpletimetracker.core.repo.ResourceRepo +import com.example.util.simpletimetracker.domain.extension.orFalse import com.example.util.simpletimetracker.domain.interactor.AutomaticBackupInteractor import com.example.util.simpletimetracker.domain.interactor.AutomaticExportInteractor import com.example.util.simpletimetracker.domain.interactor.BackupInteractor @@ -29,15 +32,16 @@ import com.example.util.simpletimetracker.navigation.params.notification.SnackBa import com.example.util.simpletimetracker.navigation.params.screen.DataExportSettingDialogParams import com.example.util.simpletimetracker.navigation.params.screen.DataExportSettingsResult import com.example.util.simpletimetracker.navigation.params.screen.StandardDialogParams -import kotlinx.coroutines.launch import java.text.SimpleDateFormat import java.util.Date import java.util.Locale import javax.inject.Inject +import kotlinx.coroutines.launch class BackupViewModel @Inject constructor( - automaticBackupRepo: AutomaticBackupRepo, - automaticExportRepo: AutomaticExportRepo, + private val dataEditRepo: DataEditRepo, + private val automaticBackupRepo: AutomaticBackupRepo, + private val automaticExportRepo: AutomaticExportRepo, private val resourceRepo: ResourceRepo, private val permissionRepo: PermissionRepo, private val router: Router, @@ -82,20 +86,16 @@ class BackupViewModel @Inject constructor( initial } } - val progressVisibility: LiveData = MutableLiveData(false) - val automaticBackupProgress: LiveData = automaticBackupRepo.inProgress - val automaticExportProgress: LiveData = automaticExportRepo.inProgress + val progressVisibility: MediatorLiveData = MediatorLiveData().apply { + addSource(automaticBackupRepo.inProgress) { updateProgress() } + addSource(automaticExportRepo.inProgress) { updateProgress() } + addSource(dataEditRepo.inProgress) { updateProgress() } + } private var dataExportSettingsResult: DataExportSettingsResult? = null fun onVisible() { - viewModelScope.launch { - checkForAutomaticBackupError() - updateAutomaticBackupEnabled() - updateAutomaticBackupLastSaveTime() - updateAutomaticExportEnabled() - updateAutomaticExportLastSaveTime() - } + onFileWork() } fun onSaveClick() { @@ -362,7 +362,7 @@ class BackupViewModel @Inject constructor( @StringRes errorMessageId: Int, doWork: suspend () -> ResultCode, ) = viewModelScope.launch { - showProgress(true) + progressVisibility.set(true) val resultCode = doWork() if (resultCode == ResultCode.SUCCESS) { @@ -371,7 +371,7 @@ class BackupViewModel @Inject constructor( errorMessageId }.let(::showMessage) - showProgress(false) + progressVisibility.set(false) } private fun onFileOpenError() { @@ -387,8 +387,12 @@ class BackupViewModel @Inject constructor( router.show(params) } - private fun showProgress(isVisible: Boolean) { - (progressVisibility as MutableLiveData).value = isVisible + private fun updateProgress() { + val visible = dataEditRepo.inProgress.value.orFalse() || + automaticBackupRepo.inProgress.value.orFalse() || + automaticExportRepo.inProgress.value.orFalse() + + progressVisibility.set(visible) } private fun getFileNameTimeStamp(): String { diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 7439215f..96ab0ed9 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -381,6 +381,8 @@ If \"%s\" setting is enabled, app will send events on activity started or Change comment Add tags Remove tags + Change + Data changed Activity diff --git a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/di/DataLocalModuleBinds.kt b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/di/DataLocalModuleBinds.kt index a142c706..cffef3e8 100644 --- a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/di/DataLocalModuleBinds.kt +++ b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/di/DataLocalModuleBinds.kt @@ -1,7 +1,9 @@ package com.example.util.simpletimetracker.data_local.di +import com.example.util.simpletimetracker.core.repo.DataEditRepo import com.example.util.simpletimetracker.data_local.repo.ActivityFilterRepoImpl import com.example.util.simpletimetracker.data_local.repo.CategoryRepoImpl +import com.example.util.simpletimetracker.data_local.repo.DataEditRepoImpl import com.example.util.simpletimetracker.data_local.repo.PrefsRepoImpl import com.example.util.simpletimetracker.data_local.repo.RecordRepoImpl import com.example.util.simpletimetracker.data_local.repo.RecordTagRepoImpl @@ -93,4 +95,8 @@ interface DataLocalModuleBinds { @Binds @Singleton fun ActivityFilterRepoImpl.bindActivityFilterRepo(): ActivityFilterRepo + + @Binds + @Singleton + fun DataEditRepoImpl.bindDataEditRepo(): DataEditRepo } \ No newline at end of file diff --git a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/repo/DataEditRepoImpl.kt b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/repo/DataEditRepoImpl.kt new file mode 100644 index 00000000..dd872b7d --- /dev/null +++ b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/repo/DataEditRepoImpl.kt @@ -0,0 +1,11 @@ +package com.example.util.simpletimetracker.data_local.repo + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import com.example.util.simpletimetracker.core.repo.DataEditRepo +import javax.inject.Inject + +class DataEditRepoImpl @Inject constructor() : DataEditRepo { + + override val inProgress: LiveData = MutableLiveData(false) +} \ No newline at end of file diff --git a/domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/AddRecordMediator.kt b/domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/AddRecordMediator.kt index 1c224746..f9fa59e5 100644 --- a/domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/AddRecordMediator.kt +++ b/domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/AddRecordMediator.kt @@ -14,7 +14,11 @@ class AddRecordMediator @Inject constructor( record: Record, ) { recordInteractor.add(record) - notificationGoalTimeInteractor.checkAndReschedule(record.typeId) + doAfterAdd(record.typeId) + } + + suspend fun doAfterAdd(typeId: Long) { + notificationGoalTimeInteractor.checkAndReschedule(typeId) widgetInteractor.updateWidgets(listOf(WidgetType.STATISTICS_CHART)) } } \ No newline at end of file diff --git a/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/interactor/DateEditChangeInteractor.kt b/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/interactor/DateEditChangeInteractor.kt new file mode 100644 index 00000000..a98af3f2 --- /dev/null +++ b/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/interactor/DateEditChangeInteractor.kt @@ -0,0 +1,40 @@ +package com.example.util.simpletimetracker.feature_data_edit.interactor + +import com.example.util.simpletimetracker.core.interactor.RecordFilterInteractor +import com.example.util.simpletimetracker.domain.interactor.AddRecordMediator +import com.example.util.simpletimetracker.domain.interactor.RecordInteractor +import com.example.util.simpletimetracker.domain.interactor.RecordTagInteractor +import com.example.util.simpletimetracker.domain.model.RecordsFilter +import javax.inject.Inject + +class DateEditChangeInteractor @Inject constructor( + private val recordInteractor: RecordInteractor, + private val addRecordMediator: AddRecordMediator, + private val recordFilterInteractor: RecordFilterInteractor, + private val recordTagInteractor: RecordTagInteractor, +) { + + suspend fun changeData( + newTypeId: Long?, + filters: List + ) { + if (filters.isEmpty()) return + if (newTypeId == null) return + + val records = recordFilterInteractor.getByFilter(filters) + val tags = recordTagInteractor.getAll().associateBy { it.id } + + records.forEach { record -> + // Remove all typed tags. + val newTagIds = record.tagIds.filter { tagId -> tags[tagId]?.typeId == 0L } + // Change activity + record.copy( + typeId = newTypeId, + tagIds = newTagIds + ).let { + recordInteractor.add(it) + } + addRecordMediator.doAfterAdd(newTypeId) + } + } +} \ No newline at end of file diff --git a/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/interactor/DateEditViewDataInteractor.kt b/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/interactor/DateEditViewDataInteractor.kt index 3263de0b..b6a75bfa 100644 --- a/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/interactor/DateEditViewDataInteractor.kt +++ b/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/interactor/DateEditViewDataInteractor.kt @@ -1,14 +1,22 @@ package com.example.util.simpletimetracker.feature_data_edit.interactor import com.example.util.simpletimetracker.core.interactor.RecordFilterInteractor +import com.example.util.simpletimetracker.core.mapper.RecordTypeViewDataMapper import com.example.util.simpletimetracker.core.repo.ResourceRepo +import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor +import com.example.util.simpletimetracker.domain.interactor.RecordTypeInteractor import com.example.util.simpletimetracker.domain.model.RecordsFilter import com.example.util.simpletimetracker.feature_data_edit.R +import com.example.util.simpletimetracker.feature_data_edit.model.DataEditChangeActivityState +import com.example.util.simpletimetracker.feature_data_edit.model.DataEditChangeButtonState import javax.inject.Inject class DateEditViewDataInteractor @Inject constructor( private val resourceRepo: ResourceRepo, private val recordFilterInteractor: RecordFilterInteractor, + private val recordTypeInteractor: RecordTypeInteractor, + private val recordTypeViewDataMapper: RecordTypeViewDataMapper, + private val prefsInteractor: PrefsInteractor, ) { suspend fun getSelectedRecordsCount( @@ -28,4 +36,37 @@ class DateEditViewDataInteractor @Inject constructor( return "$selectedRecordsCount $recordsString" } + + suspend fun getChangeActivityState( + newTypeId: Long?, + ): DataEditChangeActivityState { + val type = newTypeId?.let { recordTypeInteractor.get(it) } + + return if (type == null) { + DataEditChangeActivityState.Disabled + } else { + DataEditChangeActivityState.Enabled( + recordTypeViewDataMapper.map( + recordType = type, + isDarkTheme = prefsInteractor.getDarkMode(), + ) + ) + } + } + + suspend fun getChangeButtonState( + enabled: Boolean, + ): DataEditChangeButtonState { + val theme = if (prefsInteractor.getDarkMode()) { + R.style.AppThemeDark + } else { + R.style.AppTheme + } + + return DataEditChangeButtonState( + enabled = enabled, + backgroundTint = (if (enabled) R.attr.appActiveColor else R.attr.appInactiveColor) + .let { resourceRepo.getThemedAttr(it, theme) }, + ) + } } \ No newline at end of file diff --git a/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/model/DataEditChangeButtonState.kt b/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/model/DataEditChangeButtonState.kt new file mode 100644 index 00000000..806de8a2 --- /dev/null +++ b/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/model/DataEditChangeButtonState.kt @@ -0,0 +1,8 @@ +package com.example.util.simpletimetracker.feature_data_edit.model + +import androidx.annotation.ColorInt + +data class DataEditChangeButtonState( + val enabled: Boolean, + @ColorInt val backgroundTint: Int, +) \ No newline at end of file diff --git a/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/view/DataEditFragment.kt b/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/view/DataEditFragment.kt index 8ab5f28b..9d91176b 100644 --- a/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/view/DataEditFragment.kt +++ b/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/view/DataEditFragment.kt @@ -1,5 +1,6 @@ package com.example.util.simpletimetracker.feature_data_edit.view +import android.content.res.ColorStateList import android.view.LayoutInflater import android.view.ViewGroup import androidx.core.view.isVisible @@ -7,6 +8,7 @@ import androidx.fragment.app.viewModels import com.example.util.simpletimetracker.core.base.BaseFragment import com.example.util.simpletimetracker.feature_data_edit.dialog.DataEditTypeSelectionDialogListener import com.example.util.simpletimetracker.feature_data_edit.model.DataEditChangeActivityState +import com.example.util.simpletimetracker.feature_data_edit.model.DataEditChangeButtonState import com.example.util.simpletimetracker.feature_data_edit.viewModel.DataEditViewModel import com.example.util.simpletimetracker.feature_views.extension.setOnClick import dagger.hilt.android.AndroidEntryPoint @@ -28,30 +30,14 @@ class DataEditFragment : override fun initUx() = with(binding) { checkboxDataEditChangeActivity.setOnClick(viewModel::onChangeActivityClick) + btnDataEditChange.setOnClick(throttle(viewModel::onChangeClick)) } override fun initViewModel(): Unit = with(viewModel) { with(binding) { selectedRecordsCountViewData.observe(tvDataEditSelectedRecords::setText) - changeActivityCheckbox.observe { - when (it) { - is DataEditChangeActivityState.Disabled -> { - checkboxDataEditChangeActivity.isChecked = false - viewDataEditChangeActivityPreview.isVisible = false - } - is DataEditChangeActivityState.Enabled -> { - checkboxDataEditChangeActivity.isChecked = true - viewDataEditChangeActivityPreview.isVisible = true - viewDataEditChangeActivityPreview.apply { - itemColor = it.viewData.color - itemIcon = it.viewData.iconId - itemIconColor = it.viewData.iconColor - itemIconAlpha = it.viewData.iconAlpha - itemName = it.viewData.name - } - } - } - } + changeActivityState.observe(::setChangeActivityState) + changeButtonState.observe(::setChangeButtonState) } } @@ -66,4 +52,33 @@ class DataEditFragment : override fun onTypeSelected(typeId: Long) { viewModel.onTypeSelected(typeId) } + + private fun setChangeActivityState( + state: DataEditChangeActivityState, + ) = with(binding) { + when (state) { + is DataEditChangeActivityState.Disabled -> { + checkboxDataEditChangeActivity.isChecked = false + viewDataEditChangeActivityPreview.isVisible = false + } + is DataEditChangeActivityState.Enabled -> { + checkboxDataEditChangeActivity.isChecked = true + viewDataEditChangeActivityPreview.isVisible = true + viewDataEditChangeActivityPreview.apply { + itemColor = state.viewData.color + itemIcon = state.viewData.iconId + itemIconColor = state.viewData.iconColor + itemIconAlpha = state.viewData.iconAlpha + itemName = state.viewData.name + } + } + } + } + + private fun setChangeButtonState( + state: DataEditChangeButtonState + ) = with(binding) { + btnDataEditChange.isEnabled = state.enabled + btnDataEditChange.backgroundTintList = ColorStateList.valueOf(state.backgroundTint) + } } diff --git a/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/viewModel/DataEditViewModel.kt b/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/viewModel/DataEditViewModel.kt index c20cafa7..8a8acc2b 100644 --- a/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/viewModel/DataEditViewModel.kt +++ b/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/viewModel/DataEditViewModel.kt @@ -6,13 +6,16 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.example.util.simpletimetracker.core.extension.set import com.example.util.simpletimetracker.core.extension.toParams -import com.example.util.simpletimetracker.core.mapper.RecordTypeViewDataMapper -import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor -import com.example.util.simpletimetracker.domain.interactor.RecordTypeInteractor +import com.example.util.simpletimetracker.core.repo.DataEditRepo +import com.example.util.simpletimetracker.core.repo.ResourceRepo import com.example.util.simpletimetracker.domain.model.RecordsFilter +import com.example.util.simpletimetracker.feature_data_edit.R +import com.example.util.simpletimetracker.feature_data_edit.interactor.DateEditChangeInteractor import com.example.util.simpletimetracker.feature_data_edit.interactor.DateEditViewDataInteractor import com.example.util.simpletimetracker.feature_data_edit.model.DataEditChangeActivityState +import com.example.util.simpletimetracker.feature_data_edit.model.DataEditChangeButtonState import com.example.util.simpletimetracker.navigation.Router +import com.example.util.simpletimetracker.navigation.params.notification.SnackBarParams import com.example.util.simpletimetracker.navigation.params.screen.DataEditTypeSelectionDialogParams import com.example.util.simpletimetracker.navigation.params.screen.RecordsFilterParams import dagger.hilt.android.lifecycle.HiltViewModel @@ -22,10 +25,10 @@ import kotlinx.coroutines.launch @HiltViewModel class DataEditViewModel @Inject constructor( private val router: Router, - private val dateEditViewDataInteractor: DateEditViewDataInteractor, - private val recordTypeViewDataMapper: RecordTypeViewDataMapper, - private val prefsInteractor: PrefsInteractor, - private val recordTypeInteractor: RecordTypeInteractor, + private val resourceRepo: ResourceRepo, + private val dataEditRepo: DataEditRepo, + private val dataEditViewDataInteractor: DateEditViewDataInteractor, + private val dataEditChangeInteractor: DateEditChangeInteractor, ) : ViewModel() { val selectedRecordsCountViewData: LiveData by lazy { @@ -34,17 +37,22 @@ class DataEditViewModel @Inject constructor( initial } } - val changeActivityCheckbox: LiveData by lazy { + val changeActivityState: LiveData by lazy { MutableLiveData().let { initial -> - viewModelScope.launch { - initial.value = loadChangeActivityCheckbox() - } + viewModelScope.launch { initial.value = loadChangeActivityState() } + initial + } + } + val changeButtonState: LiveData by lazy { + MutableLiveData().let { initial -> + viewModelScope.launch { initial.value = loadChangeButtonState() } initial } } private var filters: List = emptyList() private var newTypeId: Long? = null + private val changeButtonEnabled: Boolean get() = newTypeId != null fun onSelectRecordsClick() { router.setResultListener(FILTER_TAG) { @@ -61,13 +69,24 @@ class DataEditViewModel @Inject constructor( router.navigate(DataEditTypeSelectionDialogParams) } else { newTypeId = null - updateChangeActivityCheckbox() + updateChangeActivityState() + updateChangeButtonState() } } fun onTypeSelected(typeId: Long) { newTypeId = typeId - updateChangeActivityCheckbox() + updateChangeActivityState() + updateChangeButtonState() + } + + fun onChangeClick() = viewModelScope.launch { + changeButtonState.set(dataEditViewDataInteractor.getChangeButtonState(false)) + dataEditRepo.inProgress.set(true) + dataEditChangeInteractor.changeData(newTypeId, filters) + dataEditRepo.inProgress.set(false) + showMessage(R.string.data_edit_success_message) + router.back() } private fun onFilterSelected(filters: List) { @@ -75,33 +94,36 @@ class DataEditViewModel @Inject constructor( updateSelectedRecordsCountViewData() } + private fun showMessage(stringResId: Int) { + val params = SnackBarParams(message = resourceRepo.getString(stringResId)) + router.show(params) + } + private fun updateSelectedRecordsCountViewData() = viewModelScope.launch { val data = loadSelectedRecordsCountViewData() selectedRecordsCountViewData.set(data) } private suspend fun loadSelectedRecordsCountViewData(): String { - return dateEditViewDataInteractor.getSelectedRecordsCount(filters) + return dataEditViewDataInteractor.getSelectedRecordsCount(filters) } - private fun updateChangeActivityCheckbox() = viewModelScope.launch { - val data = loadChangeActivityCheckbox() - changeActivityCheckbox.set(data) + private fun updateChangeActivityState() = viewModelScope.launch { + val data = loadChangeActivityState() + changeActivityState.set(data) } - private suspend fun loadChangeActivityCheckbox(): DataEditChangeActivityState { - // TODO move to interactor - val type = newTypeId?.let { recordTypeInteractor.get(it) } - return if (type == null) { - DataEditChangeActivityState.Disabled - } else { - DataEditChangeActivityState.Enabled( - recordTypeViewDataMapper.map( - recordType = type, - isDarkTheme = prefsInteractor.getDarkMode(), - ) - ) - } + private suspend fun loadChangeActivityState(): DataEditChangeActivityState { + return dataEditViewDataInteractor.getChangeActivityState(newTypeId) + } + + private fun updateChangeButtonState() = viewModelScope.launch { + val data = loadChangeButtonState() + changeButtonState.set(data) + } + + private suspend fun loadChangeButtonState(): DataEditChangeButtonState { + return dataEditViewDataInteractor.getChangeButtonState(changeButtonEnabled) } companion object { diff --git a/features/feature_data_edit/src/main/res/layout/data_edit_fragment.xml b/features/feature_data_edit/src/main/res/layout/data_edit_fragment.xml index 7bfcfb8b..980e8be9 100644 --- a/features/feature_data_edit/src/main/res/layout/data_edit_fragment.xml +++ b/features/feature_data_edit/src/main/res/layout/data_edit_fragment.xml @@ -38,7 +38,7 @@ + + diff --git a/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/automaticBackup/interactor/AutomaticBackupInteractorImpl.kt b/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/automaticBackup/interactor/AutomaticBackupInteractorImpl.kt index b01b8693..df7fb5f5 100644 --- a/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/automaticBackup/interactor/AutomaticBackupInteractorImpl.kt +++ b/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/automaticBackup/interactor/AutomaticBackupInteractorImpl.kt @@ -36,7 +36,10 @@ class AutomaticBackupInteractorImpl @Inject constructor( val uri = prefsInteractor.getAutomaticBackupUri() .takeUnless { it.isEmpty() } - ?: return + ?: run { + onFinished() + return + } val result = backupInteractor.saveBackupFile(uri) if (result == ResultCode.SUCCESS) { diff --git a/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/automaticExport/interactor/AutomaticExportInteractorImpl.kt b/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/automaticExport/interactor/AutomaticExportInteractorImpl.kt index 1321c86b..672990a2 100644 --- a/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/automaticExport/interactor/AutomaticExportInteractorImpl.kt +++ b/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/automaticExport/interactor/AutomaticExportInteractorImpl.kt @@ -36,7 +36,10 @@ class AutomaticExportInteractorImpl @Inject constructor( val uri = prefsInteractor.getAutomaticExportUri() .takeUnless { it.isEmpty() } - ?: return + ?: run { + onFinished() + return + } val result = csvExportInteractor.saveCsvFile(uri, range = null) if (result == ResultCode.SUCCESS) { diff --git a/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/di/NotificationModule.kt b/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/di/NotificationModule.kt index 5b69cd0e..4f076015 100644 --- a/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/di/NotificationModule.kt +++ b/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/di/NotificationModule.kt @@ -22,6 +22,7 @@ import dagger.Binds import dagger.Module import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) @@ -46,11 +47,13 @@ interface NotificationModule { fun AutomaticBackupInteractorImpl.bindAutomaticBackupInteractor(): AutomaticBackupInteractor @Binds + @Singleton fun AutomaticBackupRepoImpl.bindAutomaticBackupRepo(): AutomaticBackupRepo @Binds fun AutomaticExportInteractorImpl.bindAutomaticExportInteractor(): AutomaticExportInteractor @Binds + @Singleton fun AutomaticExportRepoImpl.bindAutomaticExportRepo(): AutomaticExportRepo } \ No newline at end of file diff --git a/features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/interactor/RecordsFilterViewDataInteractor.kt b/features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/interactor/RecordsFilterViewDataInteractor.kt index 2536eb98..784dad55 100644 --- a/features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/interactor/RecordsFilterViewDataInteractor.kt +++ b/features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/interactor/RecordsFilterViewDataInteractor.kt @@ -112,7 +112,7 @@ class RecordsFilterViewDataInteractor @Inject constructor( } return RecordsFilterSelectedRecordsViewData( - selectedRecordsCount = mapper.mapRecordsCount(count), + selectedRecordsCount = mapper.mapRecordsCount(count, filters), recordsViewData = viewData, ) } diff --git a/features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/mapper/RecordsFilterViewDataMapper.kt b/features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/mapper/RecordsFilterViewDataMapper.kt index 0ac57078..c893de7a 100644 --- a/features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/mapper/RecordsFilterViewDataMapper.kt +++ b/features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/mapper/RecordsFilterViewDataMapper.kt @@ -49,8 +49,13 @@ class RecordsFilterViewDataMapper @Inject constructor( ) } - fun mapRecordsCount(count: Int): String { - if (count == 0) return resourceRepo.getString(R.string.data_edit_select_records) + fun mapRecordsCount( + count: Int, + filter: List, + ): String { + if (count == 0 && filter.isEmpty()) { + return resourceRepo.getString(R.string.data_edit_select_records) + } val selected = resourceRepo.getString(R.string.something_selected) val recordsString: String = resourceRepo.getQuantityString( diff --git a/features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/viewModel/RecordsFilterViewModel.kt b/features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/viewModel/RecordsFilterViewModel.kt index a890bcc0..772ff2c0 100644 --- a/features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/viewModel/RecordsFilterViewModel.kt +++ b/features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/viewModel/RecordsFilterViewModel.kt @@ -68,7 +68,10 @@ class RecordsFilterViewModel @Inject constructor( return@lazy MutableLiveData().let { initial -> viewModelScope.launch { initial.value = RecordsFilterSelectedRecordsViewData( - selectedRecordsCount = recordsFilterViewDataMapper.mapRecordsCount(0), + selectedRecordsCount = recordsFilterViewDataMapper.mapRecordsCount( + count = 0, + filter = emptyList() + ), recordsViewData = listOf(LoaderViewData()), ) initial.value = loadRecordsViewData() @@ -126,6 +129,7 @@ class RecordsFilterViewModel @Inject constructor( } fun onFilterApplied() { + checkIfDefaultDateFilterShouldBeApplied() filterSelectionState = RecordsFilterSelectionState.Hidden updateFilterSelectionVisibility() } @@ -265,6 +269,23 @@ class RecordsFilterViewModel @Inject constructor( // TODO add manual filter } + private fun checkIfDefaultDateFilterShouldBeApplied() { + val state = filterSelectionState + + val shouldApplyDefaultDateFilter = state is RecordsFilterSelectionState.Visible + && state.type == RecordFilterViewData.Type.DATE + && filters.none { it is RecordsFilter.Date } + + if (shouldApplyDefaultDateFilter) { + filters.removeAll { it is RecordsFilter.Date } + filters.add(RecordsFilter.Date(defaultRange)) + + updateFilters() + updateFilterSelectionViewData() + updateRecords() + } + } + private suspend fun checkTagFilterConsistency() { // Update tags according to selected activities val newTypeIds = filters