Skip to content

Commit

Permalink
add custom backup and restore
Browse files Browse the repository at this point in the history
  • Loading branch information
Razeeman committed Sep 28, 2024
1 parent 6efd98d commit 0bf87a0
Show file tree
Hide file tree
Showing 104 changed files with 2,975 additions and 501 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ import com.example.util.simpletimetracker.feature_dialogs.recordTagSelection.Rec
import com.example.util.simpletimetracker.feature_dialogs.typesSelection.view.TypesSelectionDialogFragment
import com.example.util.simpletimetracker.feature_dialogs.standard.StandardDialogFragment
import com.example.util.simpletimetracker.feature_records_filter.view.RecordsFilterFragment
import com.example.util.simpletimetracker.feature_settings.partialRestoreSelection.PartialRestoreSelectionFragment
import com.example.util.simpletimetracker.feature_settings.partialRestoreSelection.model.PartialRestoreSelectionDialogParams
import com.example.util.simpletimetracker.navigation.NavigationData
import com.example.util.simpletimetracker.navigation.bundleCreator.BundleCreator
import com.example.util.simpletimetracker.navigation.bundleCreator.bundleCreatorDelegate
import com.example.util.simpletimetracker.navigation.params.screen.ArchiveDialogParams
import com.example.util.simpletimetracker.navigation.params.screen.BackupOptionsParams
import com.example.util.simpletimetracker.navigation.params.screen.CardOrderDialogParams
import com.example.util.simpletimetracker.navigation.params.screen.CardSizeDialogParams
import com.example.util.simpletimetracker.navigation.params.screen.ChartFilterDialogParams
Expand All @@ -35,6 +38,7 @@ import com.example.util.simpletimetracker.navigation.params.screen.DefaultTypesS
import com.example.util.simpletimetracker.navigation.params.screen.DurationDialogParams
import com.example.util.simpletimetracker.navigation.params.screen.EmojiSelectionDialogParams
import com.example.util.simpletimetracker.navigation.params.screen.HelpDialogParams
import com.example.util.simpletimetracker.navigation.params.screen.PartialRestoreParams
import com.example.util.simpletimetracker.navigation.params.screen.PomodoroSettingsParams
import com.example.util.simpletimetracker.navigation.params.screen.RecordQuickActionsParams
import com.example.util.simpletimetracker.navigation.params.screen.RecordTagSelectionParams
Expand Down Expand Up @@ -270,4 +274,34 @@ class NavigationDialogMapModule {
bundleCreatorDelegate(RecordQuickActionsDialogFragment::createBundle),
)
}

@IntoMap
@Provides
@ScreenKey(BackupOptionsParams::class)
fun backupOptionsDialogFragment(): NavigationData {
return NavigationData(
R.id.backupOptionsDialogFragment,
BundleCreator.empty(),
)
}

@IntoMap
@Provides
@ScreenKey(PartialRestoreParams::class)
fun backupPartialRestoreFragment(): NavigationData {
return NavigationData(
R.id.partialRestoreDialogFragment,
BundleCreator.empty(),
)
}

@IntoMap
@Provides
@ScreenKey(PartialRestoreSelectionDialogParams::class)
fun partialRestoreSelectionDialog(): NavigationData {
return NavigationData(
R.id.partialRestoreSelectionDialogFragment,
bundleCreatorDelegate(PartialRestoreSelectionFragment::createBundle),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ package com.example.util.simpletimetracker.ui
import android.view.LayoutInflater
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.manager.ThemeManager
import com.example.util.simpletimetracker.core.provider.ContextProvider
import com.example.util.simpletimetracker.feature_settings.viewModel.BackupViewModel
import com.example.util.simpletimetracker.feature_views.extension.visible
import com.example.util.simpletimetracker.navigation.Router
import dagger.hilt.android.AndroidEntryPoint
Expand All @@ -27,30 +25,20 @@ class MainActivity : BaseActivity<Binding>() {
@Inject
lateinit var router: Router

@Inject
lateinit var backupViewModelFactory: BaseViewModelFactory<BackupViewModel>

private val backupViewModel: BackupViewModel by viewModels(
factoryProducer = { backupViewModelFactory },
)
private val viewModel: MainActivityViewModel by viewModels()

override fun onResume() {
super.onResume()
router.bind(this)
backupViewModel.onVisible()
viewModel.onVisible()
}

override fun initUi() {
router.bind(this)
router.onCreate(this)
}

override fun initViewModel() {
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()
}
override fun initViewModel() = with(viewModel) {
progressVisibility.observe { binding.mainProgress.visible = it }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.example.util.simpletimetracker.ui

import androidx.lifecycle.MediatorLiveData
import com.example.util.simpletimetracker.core.base.BaseViewModel
import com.example.util.simpletimetracker.core.extension.set
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.FileWorkRepo
import com.example.util.simpletimetracker.domain.extension.orFalse
import com.example.util.simpletimetracker.feature_settings.viewModel.delegate.SettingsFileWorkDelegate
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject

@HiltViewModel
class MainActivityViewModel @Inject constructor(
private val dataEditRepo: DataEditRepo,
private val automaticBackupRepo: AutomaticBackupRepo,
private val automaticExportRepo: AutomaticExportRepo,
private val fileWorkRepo: FileWorkRepo,
private val settingsFileWorkDelegate: SettingsFileWorkDelegate,
) : BaseViewModel() {

val progressVisibility: MediatorLiveData<Boolean> = MediatorLiveData<Boolean>().apply {
addSource(automaticBackupRepo.inProgress) { updateProgress() }
addSource(automaticExportRepo.inProgress) { updateProgress() }
addSource(dataEditRepo.inProgress) { updateProgress() }
addSource(fileWorkRepo.inProgress) { updateProgress() }
}

fun onVisible() {
settingsFileWorkDelegate.onAppVisible()
}

private fun updateProgress() {
val visible = dataEditRepo.inProgress.value.orFalse() ||
automaticBackupRepo.inProgress.value.orFalse() ||
automaticExportRepo.inProgress.value.orFalse() ||
fileWorkRepo.inProgress.value.orFalse()

progressVisibility.set(visible)
// Here to check that if automatic update finishes with error while app is opened.
settingsFileWorkDelegate.onFileWork()
}
}
1 change: 1 addition & 0 deletions app/src/main/res/layout/main_activity.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@
android:indeterminate="true" />

</FrameLayout>

</FrameLayout>
15 changes: 15 additions & 0 deletions app/src/main/res/navigation/nav_graph.xml
Original file line number Diff line number Diff line change
Expand Up @@ -331,4 +331,19 @@
android:name="com.example.util.simpletimetracker.feature_dialogs.recordQuickActions.view.RecordQuickActionsDialogFragment"
android:label="RecordQuickActionsDialogFragment"
tools:layout="@layout/record_quick_actions_dialog_fragment" />
<dialog
android:id="@+id/backupOptionsDialogFragment"
android:name="com.example.util.simpletimetracker.feature_settings.backupOptions.view.BackupOptionsFragment"
android:label="BackupOptionsDialogFragment"
tools:layout="@layout/settings_backup_options_fragment" />
<dialog
android:id="@+id/partialRestoreDialogFragment"
android:name="com.example.util.simpletimetracker.feature_settings.partialRestore.view.PartialRestoreFragment"
android:label="PartialRestoreDialogFragment"
tools:layout="@layout/settings_partial_restore_fragment" />
<dialog
android:id="@+id/partialRestoreSelectionDialogFragment"
android:name="com.example.util.simpletimetracker.feature_settings.partialRestoreSelection.PartialRestoreSelectionFragment"
android:label="PartialRestoreSelectionDialogFragment"
tools:layout="@layout/settings_partial_restore_selection_fragment" />
</navigation>
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@ import com.example.util.simpletimetracker.core.utils.getStatusBarInsets
import com.example.util.simpletimetracker.navigation.Router
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import kotlinx.coroutines.Job
import javax.inject.Inject

abstract class BaseBottomSheetFragment<T : ViewBinding> : BottomSheetDialogFragment() {
abstract class BaseBottomSheetFragment<T : ViewBinding> : BottomSheetDialogFragment(), Throttler {

@Inject
lateinit var router: Router

abstract val inflater: (LayoutInflater, ViewGroup?, Boolean) -> T
override var throttleJob: Job? = null
protected val binding: T get() = _binding!!
private var _binding: T? = null

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package com.example.util.simpletimetracker.core.base

import com.example.util.simpletimetracker.core.extension.allowDiskRead
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel

abstract class ViewModelDelegate : ScopeHolder {

val delegateScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
val delegateScope = allowDiskRead {
CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
}

override fun getScope(): CoroutineScope {
return delegateScope
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.example.util.simpletimetracker.core.delegates.iconSelection.mapper

import androidx.annotation.ColorInt
import com.example.util.simpletimetracker.core.R
import com.example.util.simpletimetracker.core.delegates.iconSelection.viewData.IconSelectionCategoryInfoViewData
import com.example.util.simpletimetracker.core.delegates.iconSelection.viewData.IconSelectionCategoryViewData
Expand Down Expand Up @@ -35,17 +36,10 @@ class IconSelectionMapper @Inject constructor(
private val colorMapper: ColorMapper,
) {

fun mapIconImageData(
newColor: AppColor,
search: String,
fun mapFavouriteIconImages(
favourites: List<FavouriteIcon>,
isDarkTheme: Boolean,
): List<ViewHolderType> {
val isSearching = search.isNotBlank()
val actualSearch = search.lowercase().split(" ")
val favouriteIconImages = favourites
.takeUnless { isSearching }
.orEmpty()
): List<IconImage> {
return favourites
.filter { IconMapperUtils.isImageIcon(it.icon) }
.mapNotNull {
val resId = iconMapper.mapIcon(it.icon)
Expand All @@ -57,6 +51,33 @@ class IconSelectionMapper @Inject constructor(
iconSearch = "",
)
}
}

fun mapFavouriteIconEmojis(
favourites: List<FavouriteIcon>,
): List<IconEmoji> {
return favourites
.filter { !IconMapperUtils.isImageIcon(it.icon) }
.map {
IconEmoji(
emojiCode = it.icon,
emojiSearch = "",
)
}
}

fun mapIconImageData(
newColor: AppColor,
search: String,
favourites: List<FavouriteIcon>,
isDarkTheme: Boolean,
): List<ViewHolderType> {
val isSearching = search.isNotBlank()
val actualSearch = search.lowercase().split(" ")
val favouriteIconImages = favourites
.takeUnless { isSearching }
.orEmpty()
.let(::mapFavouriteIconImages)
val iconCategories = iconImageMapper.getAvailableImages(
loadSearchHints = isSearching,
)
Expand Down Expand Up @@ -89,8 +110,7 @@ class IconSelectionMapper @Inject constructor(
mapImageViewData(
iconName = it.iconName,
iconResId = it.iconResId,
newColor = newColor,
isDarkTheme = isDarkTheme,
newColor = newColor.let { colorMapper.mapToColorInt(it, isDarkTheme) },
)
}

Expand All @@ -109,13 +129,7 @@ class IconSelectionMapper @Inject constructor(
val favouriteEmojiTexts = favourites
.takeUnless { isSearching }
.orEmpty()
.filter { !IconMapperUtils.isImageIcon(it.icon) }
.map {
IconEmoji(
emojiCode = it.icon,
emojiSearch = "",
)
}
.let(::mapFavouriteIconEmojis)
val iconCategories = iconEmojiMapper.getAvailableEmojis(
loadSearchHints = isSearching,
)
Expand Down Expand Up @@ -146,8 +160,7 @@ class IconSelectionMapper @Inject constructor(

mapEmojiViewData(
codes = it.emojiCode,
newColor = newColor,
isDarkTheme = isDarkTheme,
newColor = newColor.let { colorMapper.mapToColorInt(it, isDarkTheme) },
)
}

Expand Down Expand Up @@ -255,30 +268,26 @@ class IconSelectionMapper @Inject constructor(
}.let(resourceRepo::getString)
}

private fun mapImageViewData(
fun mapImageViewData(
iconName: String,
iconResId: Int,
newColor: AppColor,
isDarkTheme: Boolean,
@ColorInt newColor: Int,
): ViewHolderType {
return IconSelectionViewData(
iconName = iconName,
iconResId = iconResId,
colorInt = newColor
.let { colorMapper.mapToColorInt(it, isDarkTheme) },
colorInt = newColor,
)
}

private fun mapEmojiViewData(
fun mapEmojiViewData(
codes: String,
newColor: AppColor,
isDarkTheme: Boolean,
@ColorInt newColor: Int,
): ViewHolderType {
return EmojiViewData(
emojiText = iconEmojiMapper.toEmojiString(codes),
emojiCodes = codes,
colorInt = newColor
.let { colorMapper.mapToColorInt(it, isDarkTheme) },
colorInt = newColor,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,18 @@ class ActivityFilterViewDataMapper @Inject constructor(
filter: ActivityFilter,
isDarkTheme: Boolean,
): ActivityFilterViewData {
val selected = filter.selected
return mapFiltered(
filter = filter,
isDarkTheme = isDarkTheme,
selected = filter.selected,
)
}

fun mapFiltered(
filter: ActivityFilter,
isDarkTheme: Boolean,
selected: Boolean,
): ActivityFilterViewData {
return ActivityFilterViewData(
id = filter.id,
name = filter.name,
Expand Down
Loading

0 comments on commit 0bf87a0

Please sign in to comment.