mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-31 06:17:57 +01:00 
			
		
		
		
	Migrate Migrate Manga screen to Compose (#7045)
* Migrate Migrate Manga screen to Compose * Changes from review comments
This commit is contained in:
		| @@ -0,0 +1,15 @@ | ||||
| package eu.kanade.data.manga | ||||
|  | ||||
| import eu.kanade.data.DatabaseHandler | ||||
| import eu.kanade.domain.manga.model.Manga | ||||
| import eu.kanade.domain.manga.repository.MangaRepository | ||||
| import kotlinx.coroutines.flow.Flow | ||||
|  | ||||
| class MangaRepositoryImpl( | ||||
|     private val databaseHandler: DatabaseHandler | ||||
| ) : MangaRepository { | ||||
|  | ||||
|     override fun getFavoritesBySourceId(sourceId: Long): Flow<List<Manga>> { | ||||
|         return databaseHandler.subscribeToList { mangasQueries.getFavoriteBySourceId(sourceId, mangaMapper) } | ||||
|     } | ||||
| } | ||||
| @@ -1,6 +1,7 @@ | ||||
| package eu.kanade.domain | ||||
|  | ||||
| import eu.kanade.data.history.HistoryRepositoryImpl | ||||
| import eu.kanade.data.manga.MangaRepositoryImpl | ||||
| import eu.kanade.data.source.SourceRepositoryImpl | ||||
| import eu.kanade.domain.history.interactor.DeleteHistoryTable | ||||
| import eu.kanade.domain.history.interactor.GetHistory | ||||
| @@ -8,6 +9,8 @@ import eu.kanade.domain.history.interactor.GetNextChapterForManga | ||||
| import eu.kanade.domain.history.interactor.RemoveHistoryById | ||||
| import eu.kanade.domain.history.interactor.RemoveHistoryByMangaId | ||||
| import eu.kanade.domain.history.repository.HistoryRepository | ||||
| import eu.kanade.domain.manga.interactor.GetFavoritesBySourceId | ||||
| import eu.kanade.domain.manga.repository.MangaRepository | ||||
| import eu.kanade.domain.source.interactor.DisableSource | ||||
| import eu.kanade.domain.source.interactor.GetEnabledSources | ||||
| import eu.kanade.domain.source.interactor.GetSourcesWithFavoriteCount | ||||
| @@ -23,6 +26,8 @@ import uy.kohesive.injekt.api.get | ||||
| class DomainModule : InjektModule { | ||||
|  | ||||
|     override fun InjektRegistrar.registerInjectables() { | ||||
|         addSingletonFactory<MangaRepository> { MangaRepositoryImpl(get()) } | ||||
|         addFactory { GetFavoritesBySourceId(get()) } | ||||
|         addFactory { GetNextChapterForManga(get()) } | ||||
|  | ||||
|         addSingletonFactory<HistoryRepository> { HistoryRepositoryImpl(get()) } | ||||
|   | ||||
| @@ -0,0 +1,14 @@ | ||||
| package eu.kanade.domain.manga.interactor | ||||
|  | ||||
| import eu.kanade.domain.manga.model.Manga | ||||
| import eu.kanade.domain.manga.repository.MangaRepository | ||||
| import kotlinx.coroutines.flow.Flow | ||||
|  | ||||
| class GetFavoritesBySourceId( | ||||
|     private val mangaRepository: MangaRepository | ||||
| ) { | ||||
|  | ||||
|     fun subscribe(sourceId: Long): Flow<List<Manga>> { | ||||
|         return mangaRepository.getFavoritesBySourceId(sourceId) | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,9 @@ | ||||
| package eu.kanade.domain.manga.repository | ||||
|  | ||||
| import eu.kanade.domain.manga.model.Manga | ||||
| import kotlinx.coroutines.flow.Flow | ||||
|  | ||||
| interface MangaRepository { | ||||
|  | ||||
|     fun getFavoritesBySourceId(sourceId: Long): Flow<List<Manga>> | ||||
| } | ||||
| @@ -0,0 +1,65 @@ | ||||
| package eu.kanade.presentation.manga.components | ||||
|  | ||||
| import androidx.compose.foundation.clickable | ||||
| import androidx.compose.foundation.layout.Box | ||||
| import androidx.compose.foundation.layout.Row | ||||
| import androidx.compose.foundation.layout.RowScope | ||||
| import androidx.compose.foundation.layout.fillMaxHeight | ||||
| import androidx.compose.foundation.layout.height | ||||
| import androidx.compose.foundation.layout.padding | ||||
| import androidx.compose.material3.MaterialTheme | ||||
| import androidx.compose.material3.Text | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.Alignment | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.text.style.TextOverflow | ||||
| import androidx.compose.ui.unit.dp | ||||
| import eu.kanade.domain.manga.model.Manga | ||||
| import eu.kanade.presentation.components.MangaCover | ||||
| import eu.kanade.presentation.util.horizontalPadding | ||||
|  | ||||
| @Composable | ||||
| fun BaseMangaListItem( | ||||
|     modifier: Modifier = Modifier, | ||||
|     manga: Manga, | ||||
|     onClickItem: () -> Unit = {}, | ||||
|     onClickCover: () -> Unit = onClickItem, | ||||
|     cover: @Composable RowScope.() -> Unit = { defaultCover(manga, onClickCover) }, | ||||
|     actions: @Composable RowScope.() -> Unit = {}, | ||||
|     content: @Composable RowScope.() -> Unit = { defaultContent(manga) }, | ||||
| ) { | ||||
|     Row( | ||||
|         modifier = modifier | ||||
|             .clickable(onClick = onClickItem) | ||||
|             .height(56.dp) | ||||
|             .padding(horizontal = horizontalPadding), | ||||
|         verticalAlignment = Alignment.CenterVertically | ||||
|     ) { | ||||
|         cover() | ||||
|         content() | ||||
|         actions() | ||||
|     } | ||||
| } | ||||
|  | ||||
| private val defaultCover: @Composable RowScope.(Manga, () -> Unit) -> Unit = { manga, onClick -> | ||||
|     MangaCover.Square( | ||||
|         modifier = Modifier | ||||
|             .padding(vertical = 8.dp) | ||||
|             .clickable(onClick = onClick) | ||||
|             .fillMaxHeight(), | ||||
|         data = manga.thumbnailUrl | ||||
|     ) | ||||
| } | ||||
|  | ||||
| private val defaultContent: @Composable RowScope.(Manga) -> Unit = { | ||||
|     Box(modifier = Modifier.weight(1f)) { | ||||
|         Text( | ||||
|             text = it.title, | ||||
|             modifier = Modifier | ||||
|                 .padding(start = horizontalPadding), | ||||
|             overflow = TextOverflow.Ellipsis, | ||||
|             maxLines = 1, | ||||
|             style = MaterialTheme.typography.bodyMedium | ||||
|         ) | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,84 @@ | ||||
| package eu.kanade.presentation.source | ||||
|  | ||||
| import androidx.compose.foundation.layout.WindowInsets | ||||
| import androidx.compose.foundation.layout.asPaddingValues | ||||
| import androidx.compose.foundation.layout.navigationBars | ||||
| import androidx.compose.foundation.lazy.LazyColumn | ||||
| import androidx.compose.foundation.lazy.items | ||||
| import androidx.compose.material3.Text | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.runtime.collectAsState | ||||
| import androidx.compose.runtime.getValue | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.input.nestedscroll.NestedScrollConnection | ||||
| import androidx.compose.ui.input.nestedscroll.nestedScroll | ||||
| import eu.kanade.domain.manga.model.Manga | ||||
| import eu.kanade.presentation.components.EmptyScreen | ||||
| import eu.kanade.presentation.components.LoadingScreen | ||||
| import eu.kanade.presentation.manga.components.BaseMangaListItem | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.ui.browse.migration.manga.MigrateMangaState | ||||
| import eu.kanade.tachiyomi.ui.browse.migration.manga.MigrationMangaPresenter | ||||
|  | ||||
| @Composable | ||||
| fun MigrateMangaScreen( | ||||
|     nestedScrollInterop: NestedScrollConnection, | ||||
|     presenter: MigrationMangaPresenter, | ||||
|     onClickItem: (Manga) -> Unit, | ||||
|     onClickCover: (Manga) -> Unit | ||||
| ) { | ||||
|     val state by presenter.state.collectAsState() | ||||
|  | ||||
|     when (state) { | ||||
|         MigrateMangaState.Loading -> LoadingScreen() | ||||
|         is MigrateMangaState.Error -> Text(text = (state as MigrateMangaState.Error).error.message!!) | ||||
|         is MigrateMangaState.Success -> { | ||||
|             MigrateMangaContent( | ||||
|                 nestedScrollInterop = nestedScrollInterop, | ||||
|                 list = (state as MigrateMangaState.Success).list, | ||||
|                 onClickItem = onClickItem, | ||||
|                 onClickCover = onClickCover, | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @Composable | ||||
| fun MigrateMangaContent( | ||||
|     nestedScrollInterop: NestedScrollConnection, | ||||
|     list: List<Manga>, | ||||
|     onClickItem: (Manga) -> Unit, | ||||
|     onClickCover: (Manga) -> Unit | ||||
| ) { | ||||
|     if (list.isEmpty()) { | ||||
|         EmptyScreen(textResource = R.string.migrate_empty_screen) | ||||
|         return | ||||
|     } | ||||
|     LazyColumn( | ||||
|         modifier = Modifier.nestedScroll(nestedScrollInterop), | ||||
|         contentPadding = WindowInsets.navigationBars.asPaddingValues(), | ||||
|     ) { | ||||
|         items(list) { manga -> | ||||
|             MigrateMangaItem( | ||||
|                 manga = manga, | ||||
|                 onClickItem = onClickItem, | ||||
|                 onClickCover = onClickCover | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @Composable | ||||
| fun MigrateMangaItem( | ||||
|     modifier: Modifier = Modifier, | ||||
|     manga: Manga, | ||||
|     onClickItem: (Manga) -> Unit, | ||||
|     onClickCover: (Manga) -> Unit | ||||
| ) { | ||||
|     BaseMangaListItem( | ||||
|         modifier = modifier, | ||||
|         manga = manga, | ||||
|         onClickItem = { onClickItem(manga) }, | ||||
|         onClickCover = { onClickCover(manga) } | ||||
|     ) | ||||
| } | ||||
| @@ -1,5 +1,6 @@ | ||||
| package eu.kanade.tachiyomi.ui.base.controller | ||||
|  | ||||
| import android.os.Bundle | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import androidx.compose.runtime.Composable | ||||
| @@ -13,7 +14,7 @@ import nucleus.presenter.Presenter | ||||
| /** | ||||
|  * Compose controller with a Nucleus presenter. | ||||
|  */ | ||||
| abstract class ComposeController<P : Presenter<*>> : NucleusController<ComposeControllerBinding, P>() { | ||||
| abstract class ComposeController<P : Presenter<*>>(bundle: Bundle? = null) : NucleusController<ComposeControllerBinding, P>(bundle) { | ||||
|  | ||||
|     override fun createBinding(inflater: LayoutInflater): ComposeControllerBinding = | ||||
|         ComposeControllerBinding.inflate(inflater) | ||||
| @@ -54,7 +55,7 @@ abstract class BasicComposeController : BaseController<ComposeControllerBinding> | ||||
|     @Composable abstract fun ComposeContent(nestedScrollInterop: NestedScrollConnection) | ||||
| } | ||||
|  | ||||
| abstract class SearchableComposeController<P : BasePresenter<*>> : SearchableNucleusController<ComposeControllerBinding, P>() { | ||||
| abstract class SearchableComposeController<P : BasePresenter<*>>(bundle: Bundle? = null) : SearchableNucleusController<ComposeControllerBinding, P>(bundle) { | ||||
|  | ||||
|     override fun createBinding(inflater: LayoutInflater): ComposeControllerBinding = | ||||
|         ComposeControllerBinding.inflate(inflater) | ||||
|   | ||||
| @@ -1,14 +0,0 @@ | ||||
| package eu.kanade.tachiyomi.ui.browse.migration.manga | ||||
|  | ||||
| import eu.davidea.flexibleadapter.FlexibleAdapter | ||||
| import eu.davidea.flexibleadapter.items.IFlexible | ||||
|  | ||||
| class MigrationMangaAdapter(controller: MigrationMangaController) : | ||||
|     FlexibleAdapter<IFlexible<*>>(null, controller, true) { | ||||
|  | ||||
|     val coverClickListener: OnCoverClickListener = controller | ||||
|  | ||||
|     interface OnCoverClickListener { | ||||
|         fun onCoverClick(position: Int) | ||||
|     } | ||||
| } | ||||
| @@ -1,24 +1,16 @@ | ||||
| package eu.kanade.tachiyomi.ui.browse.migration.manga | ||||
|  | ||||
| import android.os.Bundle | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.input.nestedscroll.NestedScrollConnection | ||||
| import androidx.core.os.bundleOf | ||||
| import androidx.recyclerview.widget.LinearLayoutManager | ||||
| import dev.chrisbanes.insetter.applyInsetter | ||||
| import eu.davidea.flexibleadapter.FlexibleAdapter | ||||
| import eu.kanade.tachiyomi.databinding.MigrationMangaControllerBinding | ||||
| import eu.kanade.tachiyomi.ui.base.controller.NucleusController | ||||
| import eu.kanade.presentation.source.MigrateMangaScreen | ||||
| import eu.kanade.tachiyomi.ui.base.controller.ComposeController | ||||
| import eu.kanade.tachiyomi.ui.base.controller.pushController | ||||
| import eu.kanade.tachiyomi.ui.browse.migration.search.SearchController | ||||
| import eu.kanade.tachiyomi.ui.manga.MangaController | ||||
|  | ||||
| class MigrationMangaController : | ||||
|     NucleusController<MigrationMangaControllerBinding, MigrationMangaPresenter>, | ||||
|     FlexibleAdapter.OnItemClickListener, | ||||
|     MigrationMangaAdapter.OnCoverClickListener { | ||||
|  | ||||
|     private var adapter: MigrationMangaAdapter? = null | ||||
| class MigrationMangaController : ComposeController<MigrationMangaPresenter> { | ||||
|  | ||||
|     constructor(sourceId: Long, sourceName: String?) : super( | ||||
|         bundleOf( | ||||
| @@ -36,50 +28,22 @@ class MigrationMangaController : | ||||
|     private val sourceId: Long = args.getLong(SOURCE_ID_EXTRA) | ||||
|     private val sourceName: String? = args.getString(SOURCE_NAME_EXTRA) | ||||
|  | ||||
|     override fun getTitle(): String? { | ||||
|         return sourceName | ||||
|     } | ||||
|     override fun getTitle(): String? = sourceName | ||||
|  | ||||
|     override fun createPresenter(): MigrationMangaPresenter { | ||||
|         return MigrationMangaPresenter(sourceId) | ||||
|     } | ||||
|     override fun createPresenter(): MigrationMangaPresenter = MigrationMangaPresenter(sourceId) | ||||
|  | ||||
|     override fun createBinding(inflater: LayoutInflater) = MigrationMangaControllerBinding.inflate(inflater) | ||||
|  | ||||
|     override fun onViewCreated(view: View) { | ||||
|         super.onViewCreated(view) | ||||
|  | ||||
|         binding.recycler.applyInsetter { | ||||
|             type(navigationBars = true) { | ||||
|                 padding() | ||||
|     @Composable | ||||
|     override fun ComposeContent(nestedScrollInterop: NestedScrollConnection) { | ||||
|         MigrateMangaScreen( | ||||
|             nestedScrollInterop = nestedScrollInterop, | ||||
|             presenter = presenter, | ||||
|             onClickItem = { | ||||
|                 router.pushController(SearchController(it.id)) | ||||
|             }, | ||||
|             onClickCover = { | ||||
|                 router.pushController(MangaController(it.id)) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         adapter = MigrationMangaAdapter(this) | ||||
|         binding.recycler.layoutManager = LinearLayoutManager(view.context) | ||||
|         binding.recycler.adapter = adapter | ||||
|         adapter?.fastScroller = binding.fastScroller | ||||
|     } | ||||
|  | ||||
|     override fun onDestroyView(view: View) { | ||||
|         adapter = null | ||||
|         super.onDestroyView(view) | ||||
|     } | ||||
|  | ||||
|     fun setManga(manga: List<MigrationMangaItem>) { | ||||
|         adapter?.updateDataSet(manga) | ||||
|     } | ||||
|  | ||||
|     override fun onItemClick(view: View, position: Int): Boolean { | ||||
|         val item = adapter?.getItem(position) as? MigrationMangaItem ?: return false | ||||
|         val controller = SearchController(item.manga) | ||||
|         router.pushController(controller) | ||||
|         return false | ||||
|     } | ||||
|  | ||||
|     override fun onCoverClick(position: Int) { | ||||
|         val mangaItem = adapter?.getItem(position) as? MigrationMangaItem ?: return | ||||
|         router.pushController(MangaController(mangaItem.manga)) | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     companion object { | ||||
|   | ||||
| @@ -1,29 +0,0 @@ | ||||
| package eu.kanade.tachiyomi.ui.browse.migration.manga | ||||
|  | ||||
| import android.view.View | ||||
| import coil.dispose | ||||
| import coil.load | ||||
| import eu.davidea.viewholders.FlexibleViewHolder | ||||
| import eu.kanade.tachiyomi.databinding.SourceListItemBinding | ||||
|  | ||||
| class MigrationMangaHolder( | ||||
|     view: View, | ||||
|     private val adapter: MigrationMangaAdapter, | ||||
| ) : FlexibleViewHolder(view, adapter) { | ||||
|  | ||||
|     private val binding = SourceListItemBinding.bind(view) | ||||
|  | ||||
|     init { | ||||
|         binding.thumbnail.setOnClickListener { | ||||
|             adapter.coverClickListener.onCoverClick(bindingAdapterPosition) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fun bind(item: MigrationMangaItem) { | ||||
|         binding.title.text = item.manga.title | ||||
|  | ||||
|         // Update the cover | ||||
|         binding.thumbnail.dispose() | ||||
|         binding.thumbnail.load(item.manga) | ||||
|     } | ||||
| } | ||||
| @@ -1,40 +0,0 @@ | ||||
| package eu.kanade.tachiyomi.ui.browse.migration.manga | ||||
|  | ||||
| import android.view.View | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import eu.davidea.flexibleadapter.FlexibleAdapter | ||||
| import eu.davidea.flexibleadapter.items.AbstractFlexibleItem | ||||
| import eu.davidea.flexibleadapter.items.IFlexible | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.data.database.models.Manga | ||||
|  | ||||
| class MigrationMangaItem(val manga: Manga) : AbstractFlexibleItem<MigrationMangaHolder>() { | ||||
|  | ||||
|     override fun getLayoutRes(): Int { | ||||
|         return R.layout.source_list_item | ||||
|     } | ||||
|  | ||||
|     override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): MigrationMangaHolder { | ||||
|         return MigrationMangaHolder(view, adapter as MigrationMangaAdapter) | ||||
|     } | ||||
|  | ||||
|     override fun bindViewHolder( | ||||
|         adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>, | ||||
|         holder: MigrationMangaHolder, | ||||
|         position: Int, | ||||
|         payloads: List<Any?>?, | ||||
|     ) { | ||||
|         holder.bind(this) | ||||
|     } | ||||
|  | ||||
|     override fun equals(other: Any?): Boolean { | ||||
|         if (other is MigrationMangaItem) { | ||||
|             return manga.id == other.manga.id | ||||
|         } | ||||
|         return false | ||||
|     } | ||||
|  | ||||
|     override fun hashCode(): Int { | ||||
|         return manga.id!!.hashCode() | ||||
|     } | ||||
| } | ||||
| @@ -1,31 +1,43 @@ | ||||
| package eu.kanade.tachiyomi.ui.browse.migration.manga | ||||
|  | ||||
| import android.os.Bundle | ||||
| import eu.kanade.tachiyomi.data.database.DatabaseHelper | ||||
| import eu.kanade.tachiyomi.data.database.models.Manga | ||||
| import eu.kanade.domain.manga.interactor.GetFavoritesBySourceId | ||||
| import eu.kanade.domain.manga.model.Manga | ||||
| import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter | ||||
| import rx.android.schedulers.AndroidSchedulers | ||||
| import eu.kanade.tachiyomi.util.lang.launchIO | ||||
| import kotlinx.coroutines.flow.MutableStateFlow | ||||
| import kotlinx.coroutines.flow.StateFlow | ||||
| import kotlinx.coroutines.flow.asStateFlow | ||||
| import kotlinx.coroutines.flow.catch | ||||
| import kotlinx.coroutines.flow.collectLatest | ||||
| import uy.kohesive.injekt.Injekt | ||||
| import uy.kohesive.injekt.api.get | ||||
|  | ||||
| class MigrationMangaPresenter( | ||||
|     private val sourceId: Long, | ||||
|     private val db: DatabaseHelper = Injekt.get(), | ||||
|     private val getFavoritesBySourceId: GetFavoritesBySourceId = Injekt.get() | ||||
| ) : BasePresenter<MigrationMangaController>() { | ||||
|  | ||||
|     private val _state: MutableStateFlow<MigrateMangaState> = MutableStateFlow(MigrateMangaState.Loading) | ||||
|     val state: StateFlow<MigrateMangaState> = _state.asStateFlow() | ||||
|  | ||||
|     override fun onCreate(savedState: Bundle?) { | ||||
|         super.onCreate(savedState) | ||||
|  | ||||
|         db.getFavoriteMangas() | ||||
|             .asRxObservable() | ||||
|             .observeOn(AndroidSchedulers.mainThread()) | ||||
|             .map { libraryToMigrationItem(it) } | ||||
|             .subscribeLatestCache(MigrationMangaController::setManga) | ||||
|     } | ||||
|  | ||||
|     private fun libraryToMigrationItem(library: List<Manga>): List<MigrationMangaItem> { | ||||
|         return library.filter { it.source == sourceId } | ||||
|             .sortedBy { it.title } | ||||
|             .map { MigrationMangaItem(it) } | ||||
|         presenterScope.launchIO { | ||||
|             getFavoritesBySourceId | ||||
|                 .subscribe(sourceId) | ||||
|                 .catch { exception -> | ||||
|                     _state.emit(MigrateMangaState.Error(exception)) | ||||
|                 } | ||||
|                 .collectLatest { list -> | ||||
|                     _state.emit(MigrateMangaState.Success(list)) | ||||
|                 } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| sealed class MigrateMangaState { | ||||
|     object Loading : MigrateMangaState() | ||||
|     data class Error(val error: Throwable) : MigrateMangaState() | ||||
|     data class Success(val list: List<Manga>) : MigrateMangaState() | ||||
| } | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import com.bluelinelabs.conductor.Controller | ||||
| import com.bluelinelabs.conductor.RouterTransaction | ||||
| import com.google.android.material.dialog.MaterialAlertDialogBuilder | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.data.database.DatabaseHelper | ||||
| import eu.kanade.tachiyomi.data.database.models.Manga | ||||
| import eu.kanade.tachiyomi.data.preference.PreferencesHelper | ||||
| import eu.kanade.tachiyomi.source.CatalogueSource | ||||
| @@ -16,12 +17,20 @@ import eu.kanade.tachiyomi.ui.browse.migration.MigrationFlags | ||||
| import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchController | ||||
| import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchPresenter | ||||
| import eu.kanade.tachiyomi.ui.manga.MangaController | ||||
| import uy.kohesive.injekt.Injekt | ||||
| import uy.kohesive.injekt.api.get | ||||
| import uy.kohesive.injekt.injectLazy | ||||
|  | ||||
| class SearchController( | ||||
|     private var manga: Manga? = null, | ||||
| ) : GlobalSearchController(manga?.title) { | ||||
|  | ||||
|     constructor(mangaId: Long) : this( | ||||
|         Injekt.get<DatabaseHelper>() | ||||
|             .getManga(mangaId) | ||||
|             .executeAsBlocking() | ||||
|     ) | ||||
|  | ||||
|     private var newManga: Manga? = null | ||||
|  | ||||
|     override fun createPresenter(): GlobalSearchPresenter { | ||||
|   | ||||
| @@ -1,21 +0,0 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="wrap_content"> | ||||
|  | ||||
|     <androidx.recyclerview.widget.RecyclerView | ||||
|         android:id="@+id/recycler" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" /> | ||||
|  | ||||
|     <eu.kanade.tachiyomi.widget.MaterialFastScroll | ||||
|         android:id="@+id/fast_scroller" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="match_parent" | ||||
|         android:layout_gravity="end" | ||||
|         app:fastScrollerBubbleEnabled="false" | ||||
|         tools:visibility="visible" /> | ||||
|  | ||||
| </FrameLayout> | ||||
| @@ -717,6 +717,7 @@ | ||||
|     <string name="migration_selection_prompt">Select a source to migrate from</string> | ||||
|     <string name="migrate">Migrate</string> | ||||
|     <string name="copy">Copy</string> | ||||
|     <string name="migrate_empty_screen">Well, this is awkward</string> | ||||
|  | ||||
|     <!-- Downloads activity and service --> | ||||
|     <string name="download_queue_error">Couldn\'t download chapters. You can try again in the downloads section</string> | ||||
|   | ||||
| @@ -36,4 +36,10 @@ source, | ||||
| count(*) | ||||
| FROM mangas | ||||
| WHERE favorite = 1 | ||||
| GROUP BY source; | ||||
| GROUP BY source; | ||||
|  | ||||
| getFavoriteBySourceId: | ||||
| SELECT * | ||||
| FROM mangas | ||||
| WHERE favorite = 1 | ||||
| AND source = :sourceId; | ||||
		Reference in New Issue
	
	Block a user