From c8141c6046b710984c3e9577d6b94458cd8d2da8 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sat, 11 Mar 2023 12:37:00 +0200 Subject: [PATCH] Got rid of AssistedInject for ViewModels --- .../kotatsu/base/domain/MangaIntent.kt | 8 ++++ .../koitharu/kotatsu/base/ui/BaseActivity.kt | 16 +++++++ .../base/ui/util/DefaultTextWatcher.kt | 13 +++++ .../kotatsu/core/parser/MangaRepository.kt | 2 + .../kotatsu/details/ui/DetailsActivity.kt | 9 +--- .../kotatsu/details/ui/DetailsViewModel.kt | 19 +++----- .../edit/FavouritesCategoryEditActivity.kt | 24 +++------- .../edit/FavouritesCategoryEditViewModel.kt | 41 ++++++++-------- .../select/FavouriteCategoriesBottomSheet.kt | 14 ++---- .../select/MangaCategoriesViewModel.kt | 22 ++++----- .../ui/list/FavouritesListFragment.kt | 13 ++--- .../ui/list/FavouritesListViewModel.kt | 20 ++++---- .../kotatsu/reader/ui/ReaderActivity.kt | 19 ++------ .../kotatsu/reader/ui/ReaderViewModel.kt | 28 ++++------- .../colorfilter/ColorFilterConfigActivity.kt | 17 ++----- .../colorfilter/ColorFilterConfigViewModel.kt | 48 ++++++++++--------- .../ui/thumbnails/PagesThumbnailsSheet.kt | 14 +++--- .../remotelist/ui/RemoteListFragment.kt | 21 +++----- .../remotelist/ui/RemoteListViewModel.kt | 19 ++++---- .../ui/config/ScrobblerConfigActivity.kt | 33 +++---------- .../ui/config/ScrobblerConfigViewModel.kt | 33 +++++++++---- .../selector/ScrobblingSelectorBottomSheet.kt | 12 +---- .../selector/ScrobblingSelectorViewModel.kt | 23 +++++---- .../kotatsu/search/ui/SearchFragment.kt | 19 ++------ .../kotatsu/search/ui/SearchViewModel.kt | 23 ++++----- .../search/ui/multi/MultiSearchActivity.kt | 30 ++++-------- .../search/ui/multi/MultiSearchViewModel.kt | 21 ++++---- .../settings/backup/RestoreDialogFragment.kt | 13 ++--- .../settings/backup/RestoreViewModel.kt | 27 ++++------- .../org/koitharu/kotatsu/utils/ext/Bundle.kt | 7 +++ .../koitharu/kotatsu/utils/ext/FragmentExt.kt | 2 + .../koitharu/kotatsu/utils/ext/ViewModel.kt | 29 ----------- 32 files changed, 264 insertions(+), 375 deletions(-) create mode 100644 app/src/main/java/org/koitharu/kotatsu/base/ui/util/DefaultTextWatcher.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/base/domain/MangaIntent.kt b/app/src/main/java/org/koitharu/kotatsu/base/domain/MangaIntent.kt index 20786cbf1..162bcb1c7 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/domain/MangaIntent.kt +++ b/app/src/main/java/org/koitharu/kotatsu/base/domain/MangaIntent.kt @@ -3,6 +3,8 @@ package org.koitharu.kotatsu.base.domain import android.content.Intent import android.net.Uri import android.os.Bundle +import androidx.lifecycle.SavedStateHandle +import org.koitharu.kotatsu.base.ui.BaseActivity import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.utils.ext.getParcelableCompat @@ -20,6 +22,12 @@ class MangaIntent private constructor( uri = intent?.data, ) + constructor(savedStateHandle: SavedStateHandle) : this( + manga = savedStateHandle.get(KEY_MANGA)?.manga, + mangaId = savedStateHandle[KEY_ID] ?: ID_NONE, + uri = savedStateHandle[BaseActivity.EXTRA_DATA], + ) + constructor(args: Bundle?) : this( manga = args?.getParcelableCompat(KEY_MANGA)?.manga, mangaId = args?.getLong(KEY_ID, ID_NONE) ?: ID_NONE, diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseActivity.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseActivity.kt index 68eb5701a..db2015823 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseActivity.kt @@ -1,5 +1,6 @@ package org.koitharu.kotatsu.base.ui +import android.content.Intent import android.content.res.Configuration import android.os.Build import android.os.Bundle @@ -59,6 +60,12 @@ abstract class BaseActivity : super.onCreate(savedInstanceState) WindowCompat.setDecorFitsSystemWindows(window, false) insetsDelegate.handleImeInsets = true + putDataToExtras(intent) + } + + override fun onNewIntent(intent: Intent?) { + putDataToExtras(intent) + super.onNewIntent(intent) } @Deprecated("Use ViewBinding", level = DeprecationLevel.ERROR) @@ -144,4 +151,13 @@ abstract class BaseActivity : super.onBackPressed() } } + + private fun putDataToExtras(intent: Intent?) { + intent?.putExtra(EXTRA_DATA, intent.data) + } + + companion object { + + const val EXTRA_DATA = "data" + } } diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/DefaultTextWatcher.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/util/DefaultTextWatcher.kt new file mode 100644 index 000000000..a382f488c --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/util/DefaultTextWatcher.kt @@ -0,0 +1,13 @@ +package org.koitharu.kotatsu.base.ui.util + +import android.text.Editable +import android.text.TextWatcher + +interface DefaultTextWatcher : TextWatcher { + + override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit + + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit + + override fun afterTextChanged(s: Editable?) = Unit +} diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaRepository.kt index 934acc008..b90b10b52 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaRepository.kt @@ -1,5 +1,6 @@ package org.koitharu.kotatsu.core.parser +import androidx.annotation.AnyThread import org.koitharu.kotatsu.core.cache.ContentCache import org.koitharu.kotatsu.local.domain.LocalMangaRepository import org.koitharu.kotatsu.parsers.MangaLoaderContext @@ -42,6 +43,7 @@ interface MangaRepository { private val cache = EnumMap>(MangaSource::class.java) + @AnyThread fun create(source: MangaSource): MangaRepository { if (source == MangaSource.LOCAL) { return localMangaRepository diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt index 8b8cae8f8..0ac1023a4 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt @@ -13,6 +13,7 @@ import android.view.View import android.view.ViewGroup import android.view.animation.AccelerateDecelerateInterpolator import android.widget.Toast +import androidx.activity.viewModels import androidx.appcompat.widget.PopupMenu import androidx.core.graphics.Insets import androidx.core.view.isGone @@ -42,7 +43,6 @@ import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.reader.ui.ReaderActivity import org.koitharu.kotatsu.reader.ui.ReaderState import org.koitharu.kotatsu.utils.ViewBadge -import org.koitharu.kotatsu.utils.ext.assistedViewModels import org.koitharu.kotatsu.utils.ext.getDisplayMessage import org.koitharu.kotatsu.utils.ext.setNavigationBarTransparentCompat import org.koitharu.kotatsu.utils.ext.textAndVisible @@ -58,17 +58,12 @@ class DetailsActivity : override val bsHeader: BottomSheetHeaderBar? get() = binding.headerChapters - @Inject - lateinit var viewModelFactory: DetailsViewModel.Factory - @Inject lateinit var shortcutsUpdater: ShortcutsUpdater private lateinit var viewBadge: ViewBadge - private val viewModel: DetailsViewModel by assistedViewModels { - viewModelFactory.create(MangaIntent(intent)) - } + private val viewModel: DetailsViewModel by viewModels() private lateinit var chaptersMenuProvider: ChaptersMenuProvider private val downloadReceiver = object : BroadcastReceiver() { diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt index 888a5f751..86180d8f8 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt @@ -7,12 +7,11 @@ import android.text.style.ForegroundColorSpan import androidx.core.text.getSpans import androidx.core.text.parseAsHtml import androidx.lifecycle.LiveData +import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.asFlow import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject +import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow @@ -55,9 +54,11 @@ import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct import org.koitharu.kotatsu.utils.ext.printStackTraceDebug import org.koitharu.kotatsu.utils.ext.runCatchingCancellable import java.io.IOException +import javax.inject.Inject -class DetailsViewModel @AssistedInject constructor( - @Assisted intent: MangaIntent, +@HiltViewModel +class DetailsViewModel @Inject constructor( + savedStateHandle: SavedStateHandle, private val historyRepository: HistoryRepository, favouritesRepository: FavouritesRepository, private val localMangaRepository: LocalMangaRepository, @@ -71,7 +72,7 @@ class DetailsViewModel @AssistedInject constructor( ) : BaseViewModel() { private val delegate = MangaDetailsDelegate( - intent = intent, + intent = MangaIntent(savedStateHandle), mangaDataRepository = mangaDataRepository, historyRepository = historyRepository, localMangaRepository = localMangaRepository, @@ -321,10 +322,4 @@ class DetailsViewModel @AssistedInject constructor( } return scrobbler } - - @AssistedFactory - interface Factory { - - fun create(intent: MangaIntent): DetailsViewModel - } } diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt index 0cdbc597e..91d02135a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt @@ -4,43 +4,37 @@ import android.content.Context import android.content.Intent import android.os.Bundle import android.text.Editable -import android.text.TextWatcher import android.view.View import android.view.ViewGroup import android.widget.AdapterView import android.widget.ArrayAdapter import android.widget.Filter +import androidx.activity.viewModels import androidx.core.graphics.Insets import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams import androidx.core.view.updatePadding -import com.google.android.material.R as materialR import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.ui.BaseActivity +import org.koitharu.kotatsu.base.ui.util.DefaultTextWatcher import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.ui.titleRes import org.koitharu.kotatsu.databinding.ActivityCategoryEditBinding import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesActivity import org.koitharu.kotatsu.parsers.model.SortOrder -import org.koitharu.kotatsu.utils.ext.assistedViewModels import org.koitharu.kotatsu.utils.ext.getDisplayMessage import org.koitharu.kotatsu.utils.ext.getSerializableCompat +import com.google.android.material.R as materialR @AndroidEntryPoint class FavouritesCategoryEditActivity : BaseActivity(), AdapterView.OnItemClickListener, View.OnClickListener, - TextWatcher { + DefaultTextWatcher { - @Inject - lateinit var viewModelFactory: FavouritesCategoryEditViewModel.Factory - - private val viewModel by assistedViewModels { - viewModelFactory.create(intent.getLongExtra(EXTRA_ID, NO_ID)) - } + private val viewModel by viewModels() private var selectedSortOrder: SortOrder? = null override fun onCreate(savedInstanceState: Bundle?) { @@ -87,10 +81,6 @@ class FavouritesCategoryEditActivity : } } - override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit - - override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit - override fun afterTextChanged(s: Editable?) { binding.buttonDone.isEnabled = !s.isNullOrBlank() } @@ -167,9 +157,9 @@ class FavouritesCategoryEditActivity : companion object { - private const val EXTRA_ID = "id" + const val EXTRA_ID = "id" + const val NO_ID = -1L private const val KEY_SORT_ORDER = "sort" - private const val NO_ID = -1L fun newIntent(context: Context, id: Long = NO_ID): Intent { return Intent(context, FavouritesCategoryEditActivity::class.java) diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt index 108966280..53d339c6d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt @@ -1,27 +1,30 @@ package org.koitharu.kotatsu.favourites.ui.categories.edit import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.liveData import androidx.lifecycle.viewModelScope -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject +import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.favourites.domain.FavouritesRepository +import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity.Companion.EXTRA_ID +import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity.Companion.NO_ID import org.koitharu.kotatsu.parsers.model.SortOrder import org.koitharu.kotatsu.utils.SingleLiveEvent +import javax.inject.Inject -private const val NO_ID = -1L - -class FavouritesCategoryEditViewModel @AssistedInject constructor( - @Assisted private val categoryId: Long, +@HiltViewModel +class FavouritesCategoryEditViewModel @Inject constructor( + savedStateHandle: SavedStateHandle, private val repository: FavouritesRepository, private val settings: AppSettings, ) : BaseViewModel() { + private val categoryId = savedStateHandle[EXTRA_ID] ?: NO_ID + val onSaved = SingleLiveEvent() val category = MutableLiveData() @@ -30,12 +33,14 @@ class FavouritesCategoryEditViewModel @AssistedInject constructor( } init { - launchLoadingJob { - category.value = if (categoryId != NO_ID) { - repository.getCategory(categoryId) - } else { - null - } + launchLoadingJob(Dispatchers.Default) { + category.postValue( + if (categoryId != NO_ID) { + repository.getCategory(categoryId) + } else { + null + }, + ) } } @@ -44,20 +49,14 @@ class FavouritesCategoryEditViewModel @AssistedInject constructor( sortOrder: SortOrder, isTrackerEnabled: Boolean, ) { - launchLoadingJob { + launchLoadingJob(Dispatchers.Default) { check(title.isNotEmpty()) if (categoryId == NO_ID) { repository.createCategory(title, sortOrder, isTrackerEnabled) } else { repository.updateCategory(categoryId, title, sortOrder, isTrackerEnabled) } - onSaved.call(Unit) + onSaved.postCall(Unit) } } - - @AssistedFactory - interface Factory { - - fun create(categoryId: Long): FavouritesCategoryEditViewModel - } } diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesBottomSheet.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesBottomSheet.kt index 00941a4be..93bf67e1d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesBottomSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesBottomSheet.kt @@ -8,8 +8,8 @@ import android.view.ViewGroup import android.widget.Toast import androidx.appcompat.widget.Toolbar import androidx.fragment.app.FragmentManager +import androidx.fragment.app.viewModels import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.ui.BaseBottomSheet import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener @@ -19,7 +19,6 @@ import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEdit import org.koitharu.kotatsu.favourites.ui.categories.select.adapter.MangaCategoriesAdapter import org.koitharu.kotatsu.favourites.ui.categories.select.model.MangaCategoryItem import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.utils.ext.assistedViewModels import org.koitharu.kotatsu.utils.ext.getDisplayMessage import org.koitharu.kotatsu.utils.ext.withArgs @@ -30,14 +29,7 @@ class FavouriteCategoriesBottomSheet : View.OnClickListener, Toolbar.OnMenuItemClickListener { - @Inject - lateinit var viewModelFactory: MangaCategoriesViewModel.Factory - - private val viewModel: MangaCategoriesViewModel by assistedViewModels { - viewModelFactory.create( - requireNotNull(arguments?.getParcelableArrayList(KEY_MANGA_LIST)).map { it.manga }, - ) - } + private val viewModel: MangaCategoriesViewModel by viewModels() private var adapter: MangaCategoriesAdapter? = null @@ -91,7 +83,7 @@ class FavouriteCategoriesBottomSheet : companion object { private const val TAG = "FavouriteCategoriesDialog" - private const val KEY_MANGA_LIST = "manga_list" + const val KEY_MANGA_LIST = "manga_list" fun show(fm: FragmentManager, manga: Manga) = Companion.show(fm, listOf(manga)) diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt index 4172fa79a..49b554c63 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt @@ -1,23 +1,27 @@ package org.koitharu.kotatsu.favourites.ui.categories.select +import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject +import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.combine import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.model.ids +import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.favourites.domain.FavouritesRepository +import org.koitharu.kotatsu.favourites.ui.categories.select.FavouriteCategoriesBottomSheet.Companion.KEY_MANGA_LIST import org.koitharu.kotatsu.favourites.ui.categories.select.model.MangaCategoryItem -import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct +import javax.inject.Inject -class MangaCategoriesViewModel @AssistedInject constructor( - @Assisted private val manga: List, +@HiltViewModel +class MangaCategoriesViewModel @Inject constructor( + savedStateHandle: SavedStateHandle, private val favouritesRepository: FavouritesRepository, ) : BaseViewModel() { + private val manga = requireNotNull(savedStateHandle.get>(KEY_MANGA_LIST)).map { it.manga } + val content = combine( favouritesRepository.observeCategories(), observeCategoriesIds(), @@ -61,10 +65,4 @@ class MangaCategoriesViewModel @AssistedInject constructor( result } } - - @AssistedFactory - interface Factory { - - fun create(manga: List): MangaCategoriesViewModel - } } diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt index 80366111f..d37f33c56 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt @@ -6,6 +6,7 @@ import android.view.MenuItem import android.view.View import androidx.appcompat.view.ActionMode import androidx.appcompat.widget.PopupMenu +import androidx.fragment.app.viewModels import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.ui.list.ListSelectionController @@ -14,20 +15,12 @@ import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesActivity import org.koitharu.kotatsu.list.ui.MangaListFragment import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.utils.ext.addMenuProvider -import org.koitharu.kotatsu.utils.ext.assistedViewModels import org.koitharu.kotatsu.utils.ext.withArgs -import javax.inject.Inject @AndroidEntryPoint class FavouritesListFragment : MangaListFragment(), PopupMenu.OnMenuItemClickListener { - @Inject - lateinit var viewModelFactory: FavouritesListViewModel.Factory - - override val viewModel by assistedViewModels { viewModelFactory.create(categoryId) } - - private val categoryId: Long - get() = arguments?.getLong(ARG_CATEGORY_ID) ?: NO_ID + override val viewModel by viewModels() override val isSwipeRefreshEnabled = false @@ -83,7 +76,7 @@ class FavouritesListFragment : MangaListFragment(), PopupMenu.OnMenuItemClickLis companion object { const val NO_ID = 0L - private const val ARG_CATEGORY_ID = "category_id" + const val ARG_CATEGORY_ID = "category_id" fun newInstance(categoryId: Long) = FavouritesListFragment().withArgs(1) { putLong(ARG_CATEGORY_ID, categoryId) diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt index f10371dc2..42deff770 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt @@ -2,10 +2,9 @@ package org.koitharu.kotatsu.favourites.ui.list import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject +import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.combine @@ -16,6 +15,7 @@ import org.koitharu.kotatsu.base.ui.util.ReversibleAction import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.favourites.domain.FavouritesRepository +import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.ARG_CATEGORY_ID import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.NO_ID import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.history.domain.PROGRESS_NONE @@ -30,9 +30,11 @@ import org.koitharu.kotatsu.tracker.domain.TrackingRepository import org.koitharu.kotatsu.utils.asFlowLiveData import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct import org.koitharu.kotatsu.utils.ext.runCatchingCancellable +import javax.inject.Inject -class FavouritesListViewModel @AssistedInject constructor( - @Assisted val categoryId: Long, +@HiltViewModel +class FavouritesListViewModel @Inject constructor( + savedStateHandle: SavedStateHandle, private val repository: FavouritesRepository, private val trackingRepository: TrackingRepository, private val historyRepository: HistoryRepository, @@ -40,6 +42,8 @@ class FavouritesListViewModel @AssistedInject constructor( private val tagHighlighter: MangaTagHighlighter, ) : MangaListViewModel(settings), ListExtraProvider { + val categoryId: Long = savedStateHandle[ARG_CATEGORY_ID] ?: NO_ID + var categoryName: String? = null private set @@ -133,10 +137,4 @@ class FavouritesListViewModel @AssistedInject constructor( PROGRESS_NONE } } - - @AssistedFactory - interface Factory { - - fun create(categoryId: Long): FavouritesListViewModel - } } diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt index b02b2896b..c9ae128c3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt @@ -15,6 +15,7 @@ import android.view.MenuItem import android.view.MotionEvent import android.view.View import android.view.WindowManager +import androidx.activity.viewModels import androidx.core.graphics.Insets import androidx.core.view.OnApplyWindowInsetsListener import androidx.core.view.WindowInsetsCompat @@ -48,14 +49,11 @@ import org.koitharu.kotatsu.settings.SettingsActivity import org.koitharu.kotatsu.utils.GridTouchHelper import org.koitharu.kotatsu.utils.IdlingDetector import org.koitharu.kotatsu.utils.ShareHelper -import org.koitharu.kotatsu.utils.ext.assistedViewModels -import org.koitharu.kotatsu.utils.ext.getParcelableExtraCompat import org.koitharu.kotatsu.utils.ext.hasGlobalPoint import org.koitharu.kotatsu.utils.ext.observeWithPrevious import org.koitharu.kotatsu.utils.ext.postDelayed import org.koitharu.kotatsu.utils.ext.setValueRounded import java.util.concurrent.TimeUnit -import javax.inject.Inject @AndroidEntryPoint class ReaderActivity : @@ -68,18 +66,9 @@ class ReaderActivity : OnApplyWindowInsetsListener, IdlingDetector.Callback { - @Inject - lateinit var viewModelFactory: ReaderViewModel.Factory - private val idlingDetector = IdlingDetector(TimeUnit.SECONDS.toMillis(10), this) - val viewModel by assistedViewModels { - viewModelFactory.create( - intent = MangaIntent(intent), - initialState = intent?.getParcelableExtraCompat(EXTRA_STATE), - preselectedBranch = intent?.getStringExtra(EXTRA_BRANCH), - ) - } + private val viewModel: ReaderViewModel by viewModels() override var pageSwitchDelay: Float get() = pageSwitchTimer.delaySec @@ -392,8 +381,8 @@ class ReaderActivity : companion object { const val ACTION_MANGA_READ = "${BuildConfig.APPLICATION_ID}.action.READ_MANGA" - private const val EXTRA_STATE = "state" - private const val EXTRA_BRANCH = "branch" + const val EXTRA_STATE = "state" + const val EXTRA_BRANCH = "branch" private const val TOAST_DURATION = 1500L fun newIntent(context: Context, manga: Manga): Intent { diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt index d059e1325..f4c28fe7d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt @@ -6,10 +6,9 @@ import androidx.activity.result.ActivityResultLauncher import androidx.annotation.AnyThread import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject +import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -56,15 +55,15 @@ import org.koitharu.kotatsu.utils.ext.processLifecycleScope import org.koitharu.kotatsu.utils.ext.requireValue import org.koitharu.kotatsu.utils.ext.runCatchingCancellable import java.util.Date +import javax.inject.Inject import javax.inject.Provider private const val BOUNDS_PAGE_OFFSET = 2 private const val PREFETCH_LIMIT = 10 -class ReaderViewModel @AssistedInject constructor( - @Assisted private val intent: MangaIntent, - @Assisted initialState: ReaderState?, - @Assisted private val preselectedBranch: String?, +@HiltViewModel +class ReaderViewModel @Inject constructor( + savedStateHandle: SavedStateHandle, private val mangaRepositoryFactory: MangaRepository.Factory, private val dataRepository: MangaDataRepository, private val historyRepository: HistoryRepository, @@ -74,10 +73,13 @@ class ReaderViewModel @AssistedInject constructor( pageLoaderFactory: Provider, ) : BaseViewModel() { + private val intent = MangaIntent(savedStateHandle) + private val preselectedBranch = savedStateHandle.get(ReaderActivity.EXTRA_BRANCH) + private var loadingJob: Job? = null private var pageSaveJob: Job? = null private var bookmarkJob: Job? = null - private val currentState = MutableStateFlow(initialState) + private val currentState = MutableStateFlow(savedStateHandle[ReaderActivity.EXTRA_STATE]) private val mangaData = MutableStateFlow(intent.manga) private val chapters: LongSparseArray get() = chaptersLoader.chapters @@ -393,16 +395,6 @@ class ReaderViewModel @AssistedInject constructor( val ppc = 1f / chaptersCount return ppc * chapterIndex + ppc * pagePercent } - - @AssistedFactory - interface Factory { - - fun create( - intent: MangaIntent, - initialState: ReaderState?, - preselectedBranch: String?, - ): ReaderViewModel - } } /** diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt index ec57f5847..d90e4f705 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt @@ -6,6 +6,7 @@ import android.content.res.Resources import android.os.Bundle import android.view.View import android.view.ViewGroup +import androidx.activity.viewModels import androidx.core.graphics.Insets import androidx.core.view.updateLayoutParams import androidx.core.view.updatePadding @@ -25,10 +26,8 @@ import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.util.format import org.koitharu.kotatsu.reader.domain.ReaderColorFilter -import org.koitharu.kotatsu.utils.ext.assistedViewModels import org.koitharu.kotatsu.utils.ext.decodeRegion import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.getParcelableExtraCompat import org.koitharu.kotatsu.utils.ext.setValueRounded import javax.inject.Inject import com.google.android.material.R as materialR @@ -42,15 +41,7 @@ class ColorFilterConfigActivity : @Inject lateinit var coil: ImageLoader - @Inject - lateinit var viewModelFactory: ColorFilterConfigViewModel.Factory - - private val viewModel: ColorFilterConfigViewModel by assistedViewModels { - viewModelFactory.create( - manga = checkNotNull(intent.getParcelableExtraCompat(EXTRA_MANGA)?.manga), - page = checkNotNull(intent.getParcelableExtraCompat(EXTRA_PAGES)?.pages?.firstOrNull()), - ) - } + private val viewModel: ColorFilterConfigViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -144,8 +135,8 @@ class ColorFilterConfigActivity : companion object { - private const val EXTRA_PAGES = "pages" - private const val EXTRA_MANGA = "manga_id" + const val EXTRA_PAGES = "pages" + const val EXTRA_MANGA = "manga_id" fun newIntent(context: Context, manga: Manga, page: MangaPage) = Intent(context, ColorFilterConfigActivity::class.java) diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt index 36074c4d7..401d45b32 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt @@ -1,24 +1,29 @@ package org.koitharu.kotatsu.reader.ui.colorfilter import androidx.lifecycle.MutableLiveData -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject +import androidx.lifecycle.SavedStateHandle +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers import org.koitharu.kotatsu.base.domain.MangaDataRepository import org.koitharu.kotatsu.base.ui.BaseViewModel +import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga +import org.koitharu.kotatsu.core.model.parcelable.ParcelableMangaPages import org.koitharu.kotatsu.core.parser.MangaRepository -import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.reader.domain.ReaderColorFilter +import org.koitharu.kotatsu.reader.ui.colorfilter.ColorFilterConfigActivity.Companion.EXTRA_MANGA import org.koitharu.kotatsu.utils.SingleLiveEvent +import javax.inject.Inject -class ColorFilterConfigViewModel @AssistedInject constructor( - @Assisted private val manga: Manga, - @Assisted page: MangaPage, +@HiltViewModel +class ColorFilterConfigViewModel @Inject constructor( + savedStateHandle: SavedStateHandle, private val mangaRepositoryFactory: MangaRepository.Factory, private val mangaDataRepository: MangaDataRepository, ) : BaseViewModel() { + private val manga = checkNotNull(savedStateHandle.get(EXTRA_MANGA)?.manga) + private var initialColorFilter: ReaderColorFilter? = null val colorFilter = MutableLiveData(null) val onDismiss = SingleLiveEvent() @@ -28,19 +33,24 @@ class ColorFilterConfigViewModel @AssistedInject constructor( get() = colorFilter.value != initialColorFilter init { + val page = checkNotNull( + savedStateHandle.get(ColorFilterConfigActivity.EXTRA_PAGES)?.pages?.firstOrNull(), + ) launchLoadingJob { initialColorFilter = mangaDataRepository.getColorFilter(manga.id) colorFilter.value = initialColorFilter } - launchLoadingJob { + launchLoadingJob(Dispatchers.Default) { val repository = mangaRepositoryFactory.create(page.source) val url = repository.getPageUrl(page) - preview.value = MangaPage( - id = page.id, - url = url, - referer = page.referer, - preview = page.preview, - source = page.source, + preview.postValue( + MangaPage( + id = page.id, + url = url, + referer = page.referer, + preview = page.preview, + source = page.source, + ), ) } } @@ -60,15 +70,9 @@ class ColorFilterConfigViewModel @AssistedInject constructor( } fun save() { - launchLoadingJob { + launchLoadingJob(Dispatchers.Default) { mangaDataRepository.saveColorFilter(manga, colorFilter.value) - onDismiss.call(Unit) + onDismiss.postCall(Unit) } } - - @AssistedFactory - interface Factory { - - fun create(manga: Manga, page: MangaPage): ColorFilterConfigViewModel - } } diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt index fe9122989..8a60e6a4e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt @@ -4,12 +4,11 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.activity.viewModels import androidx.fragment.app.FragmentManager import androidx.recyclerview.widget.GridLayoutManager import coil.ImageLoader import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject -import javax.inject.Provider import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.ui.BaseBottomSheet import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener @@ -23,10 +22,13 @@ import org.koitharu.kotatsu.list.ui.MangaListSpanResolver import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.ui.ReaderActivity +import org.koitharu.kotatsu.reader.ui.ReaderViewModel import org.koitharu.kotatsu.reader.ui.thumbnails.adapter.PageThumbnailAdapter import org.koitharu.kotatsu.utils.ext.getParcelableCompat import org.koitharu.kotatsu.utils.ext.viewLifecycleScope import org.koitharu.kotatsu.utils.ext.withArgs +import javax.inject.Inject +import javax.inject.Provider @AndroidEntryPoint class PagesThumbnailsSheet : @@ -117,9 +119,9 @@ class PagesThumbnailsSheet : (parentFragment as? OnPageSelectListener) ?: (activity as? OnPageSelectListener) )?.run { - onPageSelected(item) - dismiss() - } + onPageSelected(item) + dismiss() + } } override fun onExpansionStateChanged(headerBar: BottomSheetHeaderBar, isExpanded: Boolean) { @@ -135,7 +137,7 @@ class PagesThumbnailsSheet : } private fun getPageLoader(): PageLoader { - val viewModel = (activity as? ReaderActivity)?.viewModel + val viewModel = (activity as? ReaderActivity)?.viewModels()?.value return viewModel?.pageLoader ?: pageLoaderProvider.get().also { pageLoader = it } } diff --git a/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt index 2779c5d33..e597c90a5 100644 --- a/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt @@ -8,8 +8,8 @@ import android.view.View import androidx.appcompat.view.ActionMode import androidx.appcompat.widget.SearchView import androidx.core.view.MenuProvider +import androidx.fragment.app.viewModels import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.ui.list.ListSelectionController import org.koitharu.kotatsu.list.ui.MangaListFragment @@ -19,21 +19,12 @@ import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.search.ui.SearchActivity import org.koitharu.kotatsu.settings.SettingsActivity import org.koitharu.kotatsu.utils.ext.addMenuProvider -import org.koitharu.kotatsu.utils.ext.assistedViewModels -import org.koitharu.kotatsu.utils.ext.serializableArgument import org.koitharu.kotatsu.utils.ext.withArgs @AndroidEntryPoint class RemoteListFragment : MangaListFragment() { - @Inject - lateinit var viewModelFactory: RemoteListViewModel.Factory - - public override val viewModel by assistedViewModels { - viewModelFactory.create(source) - } - - private val source by serializableArgument(ARG_SOURCE) + public override val viewModel by viewModels() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -74,13 +65,15 @@ class RemoteListFragment : MangaListFragment() { override fun onMenuItemSelected(menuItem: MenuItem): Boolean = when (menuItem.itemId) { R.id.action_source_settings -> { - startActivity(SettingsActivity.newSourceSettingsIntent(requireContext(), source)) + startActivity(SettingsActivity.newSourceSettingsIntent(requireContext(), viewModel.source)) true } + R.id.action_filter -> { onFilterClick(null) true } + else -> false } @@ -90,7 +83,7 @@ class RemoteListFragment : MangaListFragment() { } val intent = SearchActivity.newIntent( context = this@RemoteListFragment.context ?: return false, - source = source, + source = viewModel.source, query = query, ) startActivity(intent) @@ -113,7 +106,7 @@ class RemoteListFragment : MangaListFragment() { companion object { - private const val ARG_SOURCE = "provider" + const val ARG_SOURCE = "provider" fun newInstance(provider: MangaSource) = RemoteListFragment().withArgs(1) { putSerializable(ARG_SOURCE, provider) diff --git a/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt index ce2d3edb9..416b0383b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt @@ -1,10 +1,9 @@ package org.koitharu.kotatsu.remotelist.ui import androidx.lifecycle.LiveData +import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject +import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -40,12 +39,15 @@ import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.search.domain.MangaSearchRepository import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct import org.koitharu.kotatsu.utils.ext.printStackTraceDebug +import org.koitharu.kotatsu.utils.ext.require import java.util.LinkedList +import javax.inject.Inject private const val FILTER_MIN_INTERVAL = 250L -class RemoteListViewModel @AssistedInject constructor( - @Assisted source: MangaSource, +@HiltViewModel +class RemoteListViewModel @Inject constructor( + savedStateHandle: SavedStateHandle, mangaRepositoryFactory: MangaRepository.Factory, private val searchRepository: MangaSearchRepository, settings: AppSettings, @@ -53,6 +55,7 @@ class RemoteListViewModel @AssistedInject constructor( private val tagHighlighter: MangaTagHighlighter, ) : MangaListViewModel(settings), OnFilterChangedListener { + val source = savedStateHandle.require(RemoteListFragment.ARG_SOURCE) private val repository = mangaRepositoryFactory.create(source) as RemoteMangaRepository private val filter = FilterCoordinator(repository, dataRepository, viewModelScope) private val mangaList = MutableStateFlow?>(null) @@ -218,10 +221,4 @@ class RemoteListViewModel @AssistedInject constructor( } return result } - - @AssistedFactory - interface Factory { - - fun create(source: MangaSource): RemoteListViewModel - } } diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt index 55e64d871..fd9c39d22 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt @@ -4,6 +4,7 @@ import android.content.Context import android.content.Intent import android.os.Bundle import android.view.View +import androidx.activity.viewModels import androidx.core.graphics.Insets import androidx.core.view.isVisible import androidx.core.view.updatePadding @@ -22,7 +23,6 @@ import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerUser import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo import org.koitharu.kotatsu.scrobbling.common.ui.config.adapter.ScrobblingMangaAdapter import org.koitharu.kotatsu.tracker.ui.feed.adapter.FeedAdapter -import org.koitharu.kotatsu.utils.ext.assistedViewModels import org.koitharu.kotatsu.utils.ext.disposeImageRequest import org.koitharu.kotatsu.utils.ext.enqueueWith import org.koitharu.kotatsu.utils.ext.hideCompat @@ -34,15 +34,10 @@ import javax.inject.Inject class ScrobblerConfigActivity : BaseActivity(), OnListItemClickListener, View.OnClickListener { - @Inject - lateinit var viewModelFactory: ScrobblerConfigViewModel.Factory - @Inject lateinit var coil: ImageLoader - private val viewModel: ScrobblerConfigViewModel by assistedViewModels { - viewModelFactory.create(requireNotNull(getScrobblerService(intent))) - } + private val viewModel: ScrobblerConfigViewModel by viewModels() private var paddingVertical = 0 private var paddingHorizontal = 0 @@ -150,30 +145,14 @@ class ScrobblerConfigActivity : BaseActivity(), companion object { - private const val EXTRA_SERVICE_ID = "service" + const val EXTRA_SERVICE_ID = "service" - private const val HOST_SHIKIMORI_AUTH = "shikimori-auth" - private const val HOST_ANILIST_AUTH = "anilist-auth" - private const val HOST_MAL_AUTH = "mal-auth" + const val HOST_SHIKIMORI_AUTH = "shikimori-auth" + const val HOST_ANILIST_AUTH = "anilist-auth" + const val HOST_MAL_AUTH = "mal-auth" fun newIntent(context: Context, service: ScrobblerService) = Intent(context, ScrobblerConfigActivity::class.java) .putExtra(EXTRA_SERVICE_ID, service.id) - - private fun getScrobblerService( - intent: Intent - ): ScrobblerService? { - val serviceId = intent.getIntExtra(EXTRA_SERVICE_ID, 0) - if (serviceId != 0) { - return enumValues().first { it.id == serviceId } - } - val uri = intent.data ?: return null - return when (uri.host) { - HOST_SHIKIMORI_AUTH -> ScrobblerService.SHIKIMORI - HOST_ANILIST_AUTH -> ScrobblerService.ANILIST - HOST_MAL_AUTH -> ScrobblerService.MAL - else -> null - } - } } } diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigViewModel.kt index c4c3ac324..770e38986 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigViewModel.kt @@ -1,10 +1,10 @@ package org.koitharu.kotatsu.scrobbling.common.ui.config +import android.net.Uri import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject +import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.launchIn @@ -13,6 +13,7 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.plus import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.base.ui.BaseActivity import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.ListModel @@ -24,12 +25,16 @@ import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingStatus import org.koitharu.kotatsu.utils.SingleLiveEvent import org.koitharu.kotatsu.utils.asFlowLiveData import org.koitharu.kotatsu.utils.ext.onFirst +import org.koitharu.kotatsu.utils.ext.require +import javax.inject.Inject -class ScrobblerConfigViewModel @AssistedInject constructor( - @Assisted scrobblerService: ScrobblerService, +@HiltViewModel +class ScrobblerConfigViewModel @Inject constructor( + savedStateHandle: SavedStateHandle, scrobblers: Set<@JvmSuppressWildcards Scrobbler>, ) : BaseViewModel() { + private val scrobblerService = getScrobblerService(savedStateHandle) private val scrobbler = scrobblers.first { it.scrobblerService == scrobblerService } val titleResId = scrobbler.scrobblerService.titleResId @@ -90,9 +95,19 @@ class ScrobblerConfigViewModel @AssistedInject constructor( return result } - @AssistedFactory - interface Factory { - - fun create(service: ScrobblerService): ScrobblerConfigViewModel + private fun getScrobblerService( + savedStateHandle: SavedStateHandle, + ): ScrobblerService { + val serviceId = savedStateHandle.get(ScrobblerConfigActivity.EXTRA_SERVICE_ID) ?: 0 + if (serviceId != 0) { + return enumValues().first { it.id == serviceId } + } + val uri = savedStateHandle.require(BaseActivity.EXTRA_DATA) + return when (uri.host) { + ScrobblerConfigActivity.HOST_SHIKIMORI_AUTH -> ScrobblerService.SHIKIMORI + ScrobblerConfigActivity.HOST_ANILIST_AUTH -> ScrobblerService.ANILIST + ScrobblerConfigActivity.HOST_MAL_AUTH -> ScrobblerService.MAL + else -> error("Wrong scrobbler uri: $uri") + } } } diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorBottomSheet.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorBottomSheet.kt index a000c8b8a..76b5d8de0 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorBottomSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorBottomSheet.kt @@ -9,6 +9,7 @@ import android.widget.Toast import androidx.appcompat.widget.SearchView import androidx.core.view.isVisible import androidx.fragment.app.FragmentManager +import androidx.fragment.app.viewModels import coil.ImageLoader import com.google.android.material.tabs.TabLayout import dagger.hilt.android.AndroidEntryPoint @@ -26,10 +27,8 @@ import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerManga import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService import org.koitharu.kotatsu.scrobbling.common.ui.selector.adapter.ScrobblerMangaSelectionDecoration import org.koitharu.kotatsu.scrobbling.common.ui.selector.adapter.ScrobblerSelectorAdapter -import org.koitharu.kotatsu.utils.ext.assistedViewModels import org.koitharu.kotatsu.utils.ext.firstVisibleItemPosition import org.koitharu.kotatsu.utils.ext.getDisplayMessage -import org.koitharu.kotatsu.utils.ext.requireParcelable import org.koitharu.kotatsu.utils.ext.withArgs import javax.inject.Inject @@ -44,19 +43,12 @@ class ScrobblingSelectorBottomSheet : TabLayout.OnTabSelectedListener, ListStateHolderListener { - @Inject - lateinit var viewModelFactory: ScrobblingSelectorViewModel.Factory - @Inject lateinit var coil: ImageLoader private var collapsibleActionViewCallback: CollapseActionViewCallback? = null - private val viewModel by assistedViewModels { - viewModelFactory.create( - requireArguments().requireParcelable(MangaIntent.KEY_MANGA).manga, - ) - } + private val viewModel by viewModels() override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): SheetScrobblingSelectorBinding { return SheetScrobblingSelectorBinding.inflate(inflater, container, false) diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt index 318d2a2f8..357736cc5 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt @@ -2,21 +2,21 @@ package org.koitharu.kotatsu.scrobbling.common.ui.selector import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import androidx.recyclerview.widget.RecyclerView.NO_ID -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject +import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.base.domain.MangaIntent import org.koitharu.kotatsu.base.ui.BaseViewModel +import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.LoadingFooter import org.koitharu.kotatsu.list.ui.model.LoadingState -import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.scrobbling.common.domain.Scrobbler import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerManga @@ -24,13 +24,18 @@ import org.koitharu.kotatsu.scrobbling.common.ui.selector.model.ScrobblerHint import org.koitharu.kotatsu.utils.SingleLiveEvent import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct import org.koitharu.kotatsu.utils.ext.printStackTraceDebug +import org.koitharu.kotatsu.utils.ext.require import org.koitharu.kotatsu.utils.ext.requireValue +import javax.inject.Inject -class ScrobblingSelectorViewModel @AssistedInject constructor( - @Assisted val manga: Manga, +@HiltViewModel +class ScrobblingSelectorViewModel @Inject constructor( + savedStateHandle: SavedStateHandle, scrobblers: Set<@JvmSuppressWildcards Scrobbler>, ) : BaseViewModel() { + val manga = savedStateHandle.require(MangaIntent.KEY_MANGA).manga + val availableScrobblers = scrobblers.filter { it.isAvailable } val selectedScrobblerIndex = MutableLiveData(0) @@ -172,10 +177,4 @@ class ScrobblingSelectorViewModel @AssistedInject constructor( textSecondary = 0, actionStringRes = R.string.try_again, ) - - @AssistedFactory - interface Factory { - - fun create(manga: Manga): ScrobblingSelectorViewModel - } } diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchFragment.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchFragment.kt index 6e83fac82..b5fa580fe 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchFragment.kt @@ -2,29 +2,18 @@ package org.koitharu.kotatsu.search.ui import android.view.Menu import androidx.appcompat.view.ActionMode +import androidx.fragment.app.viewModels import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.ui.list.ListSelectionController import org.koitharu.kotatsu.list.ui.MangaListFragment import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.utils.ext.assistedViewModels -import org.koitharu.kotatsu.utils.ext.serializableArgument -import org.koitharu.kotatsu.utils.ext.stringArgument import org.koitharu.kotatsu.utils.ext.withArgs @AndroidEntryPoint class SearchFragment : MangaListFragment() { - @Inject - lateinit var viewModelFactory: SearchViewModel.Factory - - override val viewModel by assistedViewModels { - viewModelFactory.create(source, query.orEmpty()) - } - - private val query by stringArgument(ARG_QUERY) - private val source by serializableArgument(ARG_SOURCE) + override val viewModel by viewModels() override fun onScrolledToEnd() { viewModel.loadNextPage() @@ -37,8 +26,8 @@ class SearchFragment : MangaListFragment() { companion object { - private const val ARG_QUERY = "query" - private const val ARG_SOURCE = "source" + const val ARG_QUERY = "query" + const val ARG_SOURCE = "source" fun newInstance(source: MangaSource, query: String) = SearchFragment().withArgs(2) { putSerializable(ARG_SOURCE, source) diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchViewModel.kt index a7976bfe8..d2ea88c4f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchViewModel.kt @@ -1,9 +1,8 @@ package org.koitharu.kotatsu.search.ui +import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject +import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -22,18 +21,20 @@ import org.koitharu.kotatsu.list.ui.model.toErrorFooter import org.koitharu.kotatsu.list.ui.model.toErrorState import org.koitharu.kotatsu.list.ui.model.toUi import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct +import org.koitharu.kotatsu.utils.ext.require +import javax.inject.Inject -class SearchViewModel @AssistedInject constructor( - @Assisted source: MangaSource, - @Assisted private val query: String, +@HiltViewModel +class SearchViewModel @Inject constructor( + savedStateHandle: SavedStateHandle, repositoryFactory: MangaRepository.Factory, settings: AppSettings, private val tagHighlighter: MangaTagHighlighter, ) : MangaListViewModel(settings) { - private val repository = repositoryFactory.create(source) + private val query = savedStateHandle.require(SearchFragment.ARG_QUERY) + private val repository = repositoryFactory.create(savedStateHandle.require(SearchFragment.ARG_SOURCE)) private val mangaList = MutableStateFlow?>(null) private val hasNextPage = MutableStateFlow(false) private val listError = MutableStateFlow(null) @@ -111,10 +112,4 @@ class SearchViewModel @AssistedInject constructor( } } } - - @AssistedFactory - interface Factory { - - fun create(source: MangaSource, query: String): SearchViewModel - } } diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt index 1e762e3ef..63413999a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt @@ -6,6 +6,7 @@ import android.os.Bundle import android.view.Menu import android.view.MenuItem import android.view.View +import androidx.activity.viewModels import androidx.appcompat.view.ActionMode import androidx.core.content.ContextCompat import androidx.core.graphics.Insets @@ -31,7 +32,6 @@ import org.koitharu.kotatsu.search.ui.MangaListActivity import org.koitharu.kotatsu.search.ui.SearchActivity import org.koitharu.kotatsu.search.ui.multi.adapter.MultiSearchAdapter import org.koitharu.kotatsu.utils.ShareHelper -import org.koitharu.kotatsu.utils.ext.assistedViewModels import org.koitharu.kotatsu.utils.ext.invalidateNestedItemDecorations import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf import javax.inject.Inject @@ -40,17 +40,12 @@ import javax.inject.Inject class MultiSearchActivity : BaseActivity(), MangaListListener, - ListSelectionController.Callback { - - @Inject - lateinit var viewModelFactory: MultiSearchViewModel.Factory + ListSelectionController.Callback2 { @Inject lateinit var coil: ImageLoader - private val viewModel by assistedViewModels { - viewModelFactory.create(intent.getStringExtra(EXTRA_QUERY).orEmpty()) - } + private val viewModel by viewModels() private lateinit var adapter: MultiSearchAdapter private lateinit var selectionController: ListSelectionController @@ -139,17 +134,16 @@ class MultiSearchActivity : override fun onListHeaderClick(item: ListHeader, view: View) = Unit - override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean { + override fun onSelectionChanged(controller: ListSelectionController, count: Int) { + binding.recyclerView.invalidateNestedItemDecorations() + } + + override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { mode.menuInflater.inflate(R.menu.mode_remote, menu) return true } - override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean { - mode.title = selectionController.count.toString() - return true - } - - override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean { + override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode, item: MenuItem): Boolean { return when (item.itemId) { R.id.action_share -> { ShareHelper(this).shareMangaLinks(collectSelectedItems()) @@ -173,17 +167,13 @@ class MultiSearchActivity : } } - override fun onSelectionChanged(count: Int) { - binding.recyclerView.invalidateNestedItemDecorations() - } - private fun collectSelectedItems(): Set { return viewModel.getItems(selectionController.peekCheckedIds()) } companion object { - private const val EXTRA_QUERY = "query" + const val EXTRA_QUERY = "query" fun newIntent(context: Context, query: String) = Intent(context, MultiSearchActivity::class.java) diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt index c0eaeaa4d..d32717f6f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt @@ -2,10 +2,9 @@ package org.koitharu.kotatsu.search.ui.multi import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject +import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -31,12 +30,14 @@ import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct import org.koitharu.kotatsu.utils.ext.printStackTraceDebug import org.koitharu.kotatsu.utils.ext.runCatchingCancellable +import javax.inject.Inject private const val MAX_PARALLELISM = 4 private const val MIN_HAS_MORE_ITEMS = 8 -class MultiSearchViewModel @AssistedInject constructor( - @Assisted initialQuery: String, +@HiltViewModel +class MultiSearchViewModel @Inject constructor( + savedStateHandle: SavedStateHandle, private val settings: AppSettings, private val mangaRepositoryFactory: MangaRepository.Factory, ) : BaseViewModel() { @@ -46,7 +47,7 @@ class MultiSearchViewModel @AssistedInject constructor( private val loadingData = MutableStateFlow(false) private var listError = MutableStateFlow(null) - val query = MutableLiveData(initialQuery) + val query = MutableLiveData(savedStateHandle.get(MultiSearchActivity.EXTRA_QUERY).orEmpty()) val list: LiveData> = combine( listData, loadingData, @@ -72,7 +73,7 @@ class MultiSearchViewModel @AssistedInject constructor( }.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState)) init { - doSearch(initialQuery) + doSearch(query.value.orEmpty()) } fun getItems(ids: Set): Set { @@ -145,10 +146,4 @@ class MultiSearchViewModel @AssistedInject constructor( } } } - - @AssistedFactory - interface Factory { - - fun create(initialQuery: String): MultiSearchViewModel - } } diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt index 68edfe874..84341d278 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt @@ -6,28 +6,21 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.core.view.isVisible +import androidx.fragment.app.viewModels import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.ui.AlertDialogFragment import org.koitharu.kotatsu.core.backup.CompositeResult import org.koitharu.kotatsu.databinding.DialogProgressBinding -import org.koitharu.kotatsu.utils.ext.assistedViewModels import org.koitharu.kotatsu.utils.ext.getDisplayMessage -import org.koitharu.kotatsu.utils.ext.toUriOrNull import org.koitharu.kotatsu.utils.ext.withArgs import org.koitharu.kotatsu.utils.progress.Progress @AndroidEntryPoint class RestoreDialogFragment : AlertDialogFragment() { - @Inject - lateinit var viewModelFactory: RestoreViewModel.Factory - - private val viewModel by assistedViewModels { - viewModelFactory.create(arguments?.getString(ARG_FILE)?.toUriOrNull()) - } + private val viewModel: RestoreViewModel by viewModels() override fun onInflateView( inflater: LayoutInflater, @@ -74,12 +67,14 @@ class RestoreDialogFragment : AlertDialogFragment() { when { result.isAllSuccess -> builder.setTitle(R.string.data_restored) .setMessage(R.string.data_restored_success) + result.isAllFailed -> builder.setTitle(R.string.error) .setMessage( result.failures.map { it.getDisplayMessage(resources) }.distinct().joinToString("\n"), ) + else -> builder.setTitle(R.string.data_restored) .setMessage(R.string.data_restored_with_errors) } diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt index 01631986f..ffb29d8f9 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt @@ -1,15 +1,10 @@ package org.koitharu.kotatsu.settings.backup import android.content.Context -import android.net.Uri import androidx.lifecycle.MutableLiveData -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject +import androidx.lifecycle.SavedStateHandle import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext -import java.io.File -import java.io.FileNotFoundException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runInterruptible import org.koitharu.kotatsu.base.ui.BaseViewModel @@ -18,10 +13,15 @@ import org.koitharu.kotatsu.core.backup.BackupRepository import org.koitharu.kotatsu.core.backup.BackupZipInput import org.koitharu.kotatsu.core.backup.CompositeResult import org.koitharu.kotatsu.utils.SingleLiveEvent +import org.koitharu.kotatsu.utils.ext.toUriOrNull import org.koitharu.kotatsu.utils.progress.Progress +import java.io.File +import java.io.FileNotFoundException +import javax.inject.Inject -class RestoreViewModel @AssistedInject constructor( - @Assisted uri: Uri?, +@HiltViewModel +class RestoreViewModel @Inject constructor( + savedStateHandle: SavedStateHandle, private val repository: BackupRepository, @ApplicationContext context: Context, ) : BaseViewModel() { @@ -31,9 +31,8 @@ class RestoreViewModel @AssistedInject constructor( init { launchLoadingJob { - if (uri == null) { - throw FileNotFoundException() - } + val uri = savedStateHandle.get(RestoreDialogFragment.ARG_FILE) + ?.toUriOrNull() ?: throw FileNotFoundException() val contentResolver = context.contentResolver val backup = runInterruptible(Dispatchers.IO) { @@ -65,10 +64,4 @@ class RestoreViewModel @AssistedInject constructor( } } } - - @AssistedFactory - interface Factory { - - fun create(uri: Uri?): RestoreViewModel - } } diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/Bundle.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/Bundle.kt index 27ed10082..2203c4fb9 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/Bundle.kt +++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/Bundle.kt @@ -7,6 +7,7 @@ import android.os.Build import android.os.Bundle import android.os.Parcel import android.os.Parcelable +import androidx.lifecycle.SavedStateHandle import org.koitharu.kotatsu.core.model.parcelable.ParcelableMangaTags import java.io.Serializable @@ -47,3 +48,9 @@ inline fun Bundle.requireParcelable(key: String): T { "Parcelable of type \"${T::class.java.name}\" not found at \"$key\"" } } + +fun SavedStateHandle.require(key: String): T { + return checkNotNull(get(key)) { + "Value $key not found in SavedStateHandle or has a wrong type" + } +} diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/FragmentExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/FragmentExt.kt index e154a5b45..8370d01c1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/FragmentExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/FragmentExt.kt @@ -23,6 +23,7 @@ inline fun T.withArgs(size: Int, block: Bundle.() -> Unit): T { val Fragment.viewLifecycleScope inline get() = viewLifecycleOwner.lifecycle.coroutineScope +@Deprecated("") fun Fragment.serializableArgument(name: String): Lazy { return lazy(LazyThreadSafetyMode.NONE) { @Suppress("UNCHECKED_CAST") @@ -32,6 +33,7 @@ fun Fragment.serializableArgument(name: String): Lazy { } } +@Deprecated("") fun Fragment.stringArgument(name: String) = lazy(LazyThreadSafetyMode.NONE) { arguments?.getString(name) } diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/ViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/ViewModel.kt index 2dded9f99..3b840ade1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/ViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/ViewModel.kt @@ -1,41 +1,12 @@ package org.koitharu.kotatsu.utils.ext -import androidx.activity.ComponentActivity -import androidx.activity.viewModels import androidx.annotation.MainThread import androidx.fragment.app.Fragment import androidx.fragment.app.createViewModelLazy -import androidx.fragment.app.viewModels -import androidx.lifecycle.AbstractSavedStateViewModelFactory -import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewmodel.CreationExtras -@Deprecated("Migrate to SavedStateHandle in vm") -@MainThread -inline fun ComponentActivity.assistedViewModels( - noinline viewModelProducer: (SavedStateHandle) -> VM, -): Lazy = viewModels { - object : AbstractSavedStateViewModelFactory(this@assistedViewModels, intent.extras) { - override fun create(key: String, modelClass: Class, handle: SavedStateHandle): T { - return requireNotNull(modelClass.cast(viewModelProducer(handle))) - } - } -} - -@Deprecated("Migrate to SavedStateHandle in vm") -@MainThread -inline fun Fragment.assistedViewModels( - noinline viewModelProducer: (SavedStateHandle) -> VM, -): Lazy = viewModels { - object : AbstractSavedStateViewModelFactory(this@assistedViewModels, arguments) { - override fun create(key: String, modelClass: Class, handle: SavedStateHandle): T { - return requireNotNull(modelClass.cast(viewModelProducer(handle))) - } - } -} - @MainThread inline fun Fragment.parentFragmentViewModels( noinline extrasProducer: (() -> CreationExtras)? = null,