mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-30 22:07:57 +01:00 
			
		
		
		
	Cleanup of olf auto migration
(cherry picked from commit d64754e3e09e92b2e65c181b0b5e84b531490662)
This commit is contained in:
		| @@ -1,16 +0,0 @@ | ||||
| package eu.kanade.tachiyomi.ui.migration | ||||
|  | ||||
| class MigrationStatus { | ||||
|     companion object { | ||||
|         val NOT_INITIALIZED = -1 | ||||
|         val COMPLETED = 0 | ||||
|  | ||||
|         // Migration process | ||||
|         val NOTIFY_USER = 1 | ||||
|         val OPEN_BACKUP_MENU = 2 | ||||
|         val PERFORM_BACKUP = 3 | ||||
|         val FINALIZE_MIGRATION = 4 | ||||
|  | ||||
|         val MAX_MIGRATION_STEPS = 2 | ||||
|     } | ||||
| } | ||||
| @@ -104,9 +104,9 @@ class MigrationBottomSheetDialog( | ||||
|  | ||||
|     private fun setFlags() { | ||||
|         var flags = 0 | ||||
|         if (mig_chapters.isChecked) flags = flags or MigrationFlags.CHAPTERS | ||||
|         if (mig_categories.isChecked) flags = flags or MigrationFlags.CATEGORIES | ||||
|         if (mig_categories.isChecked) flags = flags or MigrationFlags.TRACK | ||||
|         if(mig_chapters.isChecked) flags = flags or MigrationFlags.CHAPTERS | ||||
|         if(mig_categories.isChecked) flags = flags or MigrationFlags.CATEGORIES | ||||
|         if(mig_tracking.isChecked) flags = flags or MigrationFlags.TRACK | ||||
|         preferences.migrateFlags().set(flags) | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,19 +0,0 @@ | ||||
| package eu.kanade.tachiyomi.ui.migration.manga.process | ||||
|  | ||||
| import android.content.Context | ||||
| import android.util.AttributeSet | ||||
| import android.view.MotionEvent | ||||
| import androidx.viewpager.widget.ViewPager | ||||
|  | ||||
| class DeactivatableViewPager : ViewPager { | ||||
|     constructor(context: Context) : super(context) | ||||
|     constructor(context: Context, attrs: AttributeSet) : super(context, attrs) | ||||
|  | ||||
|     override fun onTouchEvent(event: MotionEvent): Boolean { | ||||
|         return !isEnabled || super.onTouchEvent(event) | ||||
|     } | ||||
|  | ||||
|     override fun onInterceptTouchEvent(event: MotionEvent): Boolean { | ||||
|         return isEnabled && super.onInterceptTouchEvent(event) | ||||
|     } | ||||
| } | ||||
| @@ -1,300 +0,0 @@ | ||||
| package eu.kanade.tachiyomi.ui.migration.manga.process | ||||
|  | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import androidx.viewpager.widget.PagerAdapter | ||||
| import com.bumptech.glide.load.engine.DiskCacheStrategy | ||||
| import com.google.gson.Gson | ||||
| 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.glide.GlideApp | ||||
| import eu.kanade.tachiyomi.source.Source | ||||
| import eu.kanade.tachiyomi.source.SourceManager | ||||
| import eu.kanade.tachiyomi.source.model.SManga | ||||
| import eu.kanade.tachiyomi.source.online.all.MergedSource | ||||
| import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction | ||||
| import eu.kanade.tachiyomi.ui.manga.MangaController | ||||
| import eu.kanade.tachiyomi.util.view.gone | ||||
| import eu.kanade.tachiyomi.util.view.inflate | ||||
| import eu.kanade.tachiyomi.util.view.visible | ||||
| import exh.MERGED_SOURCE_ID | ||||
| import java.text.DateFormat | ||||
| import java.text.DecimalFormat | ||||
| import java.util.Date | ||||
| import kotlin.coroutines.CoroutineContext | ||||
| import kotlinx.android.synthetic.main.migration_manga_card.view.loading_group | ||||
| import kotlinx.android.synthetic.main.migration_manga_card.view.manga_artist | ||||
| import kotlinx.android.synthetic.main.migration_manga_card.view.manga_author | ||||
| import kotlinx.android.synthetic.main.migration_manga_card.view.manga_chapters | ||||
| import kotlinx.android.synthetic.main.migration_manga_card.view.manga_cover | ||||
| import kotlinx.android.synthetic.main.migration_manga_card.view.manga_full_title | ||||
| import kotlinx.android.synthetic.main.migration_manga_card.view.manga_last_chapter | ||||
| import kotlinx.android.synthetic.main.migration_manga_card.view.manga_last_update | ||||
| import kotlinx.android.synthetic.main.migration_manga_card.view.manga_source | ||||
| import kotlinx.android.synthetic.main.migration_manga_card.view.manga_source_label | ||||
| import kotlinx.android.synthetic.main.migration_manga_card.view.manga_status | ||||
| import kotlinx.android.synthetic.main.migration_manga_card.view.search_progress | ||||
| import kotlinx.android.synthetic.main.migration_manga_card.view.search_status | ||||
| import kotlinx.android.synthetic.main.migration_process_item.view.accept_migration | ||||
| import kotlinx.android.synthetic.main.migration_process_item.view.migrating_frame | ||||
| import kotlinx.android.synthetic.main.migration_process_item.view.migration_manga_card_from | ||||
| import kotlinx.android.synthetic.main.migration_process_item.view.migration_manga_card_to | ||||
| import kotlinx.android.synthetic.main.migration_process_item.view.skip_migration | ||||
| import kotlinx.coroutines.CoroutineScope | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| import kotlinx.coroutines.Job | ||||
| import kotlinx.coroutines.cancel | ||||
| import kotlinx.coroutines.flow.asFlow | ||||
| import kotlinx.coroutines.flow.collect | ||||
| import kotlinx.coroutines.launch | ||||
| import kotlinx.coroutines.withContext | ||||
| import uy.kohesive.injekt.injectLazy | ||||
|  | ||||
| class MigrationProcedureAdapter( | ||||
|     val controller: MigrationProcedureController, | ||||
|     val migratingManga: List<MigratingManga>, | ||||
|     override val coroutineContext: CoroutineContext | ||||
| ) : PagerAdapter(), CoroutineScope { | ||||
|     private val db: DatabaseHelper by injectLazy() | ||||
|     private val gson: Gson by injectLazy() | ||||
|     private val sourceManager: SourceManager by injectLazy() | ||||
|  | ||||
|     override fun isViewFromObject(p0: View, p1: Any): Boolean { | ||||
|         return p0 == p1 | ||||
|     } | ||||
|  | ||||
|     override fun getCount() = migratingManga.size | ||||
|  | ||||
|     override fun instantiateItem(container: ViewGroup, position: Int): Any { | ||||
|         val item = migratingManga[position] | ||||
|         val view = container.inflate(R.layout.migration_process_item) | ||||
|         container.addView(view) | ||||
|  | ||||
|         view.skip_migration.setOnClickListener { | ||||
|             // controller.nextMigration() | ||||
|         } | ||||
|  | ||||
|         val viewTag = ViewTag(coroutineContext) | ||||
|         view.tag = viewTag | ||||
|         view.setupView(viewTag, item) | ||||
|  | ||||
|         view.accept_migration.setOnClickListener { | ||||
|             viewTag.launch(Dispatchers.Main) { | ||||
|                 view.migrating_frame.visible() | ||||
|                 try { | ||||
|                     withContext(Dispatchers.Default) { | ||||
|                         performMigration(item) | ||||
|                     } | ||||
|                     controller.nextMigration() | ||||
|                 } catch (e: Exception) { | ||||
|                     controller.migrationFailure() | ||||
|                 } | ||||
|                 view.migrating_frame.gone() | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return view | ||||
|     } | ||||
|  | ||||
|     suspend fun performMigration(manga: MigratingManga) { | ||||
|             if (!manga.searchResult.initialized) { | ||||
|                 return | ||||
|             } | ||||
|  | ||||
|             val toMangaObj = db.getManga(manga.searchResult.get() ?: return).executeAsBlocking() ?: return | ||||
|  | ||||
|             withContext(Dispatchers.IO) { | ||||
|                 migrateMangaInternal( | ||||
|                     manga.manga() ?: return@withContext, | ||||
|                     toMangaObj, | ||||
|                     false | ||||
|                 ) | ||||
|             } | ||||
|     } | ||||
|  | ||||
|     private fun migrateMangaInternal( | ||||
|         prevManga: Manga, | ||||
|         manga: Manga, | ||||
|         replace: Boolean | ||||
|     ) { | ||||
|         val config = controller.config ?: return | ||||
|         // db.inTransaction { | ||||
|             // Update chapters read | ||||
|             /* if (MigrationFlags.hasChapters(controller.config.migrationFlags)) { | ||||
|                 val prevMangaChapters = db.getChapters(prevManga).executeAsBlocking() | ||||
|                 val maxChapterRead = prevMangaChapters.filter { it.read } | ||||
|                         .maxBy { it.chapter_number }?.chapter_number | ||||
|                 if (maxChapterRead != null) { | ||||
|                     val dbChapters = db.getChapters(manga).executeAsBlocking() | ||||
|                     for (chapter in dbChapters) { | ||||
|                         if (chapter.isRecognizedNumber && chapter.chapter_number <= maxChapterRead) { | ||||
|                             chapter.read = true | ||||
|                         } | ||||
|                     } | ||||
|                     db.insertChapters(dbChapters).executeAsBlocking() | ||||
|                 } | ||||
|             } | ||||
|             // Update categories | ||||
|             if (MigrationFlags.hasCategories(controller.config.migrationFlags)) { | ||||
|                 val categories = db.getCategoriesForManga(prevManga).executeAsBlocking() | ||||
|                 val mangaCategories = categories.map { MangaCategory.create(manga, it) } | ||||
|                 db.setMangaCategories(mangaCategories, listOf(manga)) | ||||
|             } | ||||
|             // Update track | ||||
|             if (MigrationFlags.hasTracks(controller.config.migrationFlags)) { | ||||
|                 val tracks = db.getTracks(prevManga).executeAsBlocking() | ||||
|                 for (track in tracks) { | ||||
|                     track.id = null | ||||
|                     track.manga_id = manga.id!! | ||||
|                 } | ||||
|                 db.insertTracks(tracks).executeAsBlocking() | ||||
|             } | ||||
|             // Update favorite status | ||||
|             if (replace) { | ||||
|                 prevManga.favorite = false | ||||
|                 db.updateMangaFavorite(prevManga).executeAsBlocking() | ||||
|             } | ||||
|             manga.favorite = true | ||||
|             db.updateMangaFavorite(manga).executeAsBlocking() | ||||
|  | ||||
|             // SearchPresenter#networkToLocalManga may have updated the manga title, so ensure db gets updated title | ||||
|             db.updateMangaTitle(manga).executeAsBlocking() | ||||
|         //}*/ | ||||
|     } | ||||
|  | ||||
|     fun View.setupView(tag: ViewTag, migratingManga: MigratingManga) { | ||||
|         tag.launch { | ||||
|             val manga = migratingManga.manga() | ||||
|             val source = migratingManga.mangaSource() | ||||
|             if (manga != null) { | ||||
|                 withContext(Dispatchers.Main) { | ||||
|                     migration_manga_card_from.loading_group.gone() | ||||
|                     migration_manga_card_from.attachManga(tag, manga, source) | ||||
|                     migration_manga_card_from.setOnClickListener { | ||||
|                         controller.router.pushController(MangaController(manga, true).withFadeTransaction()) | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 tag.launch { | ||||
|                     migratingManga.progress.asFlow().collect { (max, progress) -> | ||||
|                         withContext(Dispatchers.Main) { | ||||
|                             migration_manga_card_to.search_progress.let { progressBar -> | ||||
|                                 progressBar.max = max | ||||
|                                 progressBar.progress = progress | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 val searchResult = migratingManga.searchResult.get()?.let { | ||||
|                     db.getManga(it).executeAsBlocking() | ||||
|                 } | ||||
|                 val resultSource = searchResult?.source?.let { | ||||
|                     sourceManager.get(it) | ||||
|                 } | ||||
|                 withContext(Dispatchers.Main) { | ||||
|                     if (searchResult != null && resultSource != null) { | ||||
|                         migration_manga_card_to.loading_group.gone() | ||||
|                         migration_manga_card_to.attachManga(tag, searchResult, resultSource) | ||||
|                         migration_manga_card_to.setOnClickListener { | ||||
|                             controller.router.pushController(MangaController(searchResult, true).withFadeTransaction()) | ||||
|                         } | ||||
|                         accept_migration.isEnabled = true | ||||
|                         accept_migration.alpha = 1.0f | ||||
|                     } else { | ||||
|                         migration_manga_card_to.search_progress.gone() | ||||
|                         migration_manga_card_to.search_status.text = "Found no manga" | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     suspend fun View.attachManga(tag: ViewTag, manga: Manga, source: Source) { | ||||
|         // TODO Duplicated in MangaInfoController | ||||
|  | ||||
|         GlideApp.with(context) | ||||
|                 .load(manga) | ||||
|                 .diskCacheStrategy(DiskCacheStrategy.RESOURCE) | ||||
|                 .centerCrop() | ||||
|                 .into(manga_cover) | ||||
|  | ||||
|         manga_full_title.text = if (manga.title.isBlank()) { | ||||
|             context.getString(R.string.unknown) | ||||
|         } else { | ||||
|             manga.title | ||||
|         } | ||||
|  | ||||
|         manga_artist.text = if (manga.artist.isNullOrBlank()) { | ||||
|             context.getString(R.string.unknown) | ||||
|         } else { | ||||
|             manga.artist | ||||
|         } | ||||
|  | ||||
|         manga_author.text = if (manga.author.isNullOrBlank()) { | ||||
|             context.getString(R.string.unknown) | ||||
|         } else { | ||||
|             manga.author | ||||
|         } | ||||
|  | ||||
|         manga_source.text = if (source.id == MERGED_SOURCE_ID) { | ||||
|             MergedSource.MangaConfig.readFromUrl(gson, manga.url).children.map { | ||||
|                 sourceManager.getOrStub(it.source).toString() | ||||
|             }.distinct().joinToString() | ||||
|         } else { | ||||
|             source.toString() | ||||
|         } | ||||
|  | ||||
|         if (source.id == MERGED_SOURCE_ID) { | ||||
|             manga_source_label.text = "Sources" | ||||
|         } else { | ||||
|             manga_source_label.setText(R.string.manga_info_source_label) | ||||
|         } | ||||
|  | ||||
|         manga_status.setText(when (manga.status) { | ||||
|             SManga.ONGOING -> R.string.ongoing | ||||
|             SManga.COMPLETED -> R.string.completed | ||||
|             SManga.LICENSED -> R.string.licensed | ||||
|             else -> R.string.unknown | ||||
|         }) | ||||
|  | ||||
|         val mangaChapters = db.getChapters(manga).executeAsBlocking() | ||||
|         manga_chapters.text = mangaChapters.size.toString() | ||||
|         val latestChapter = mangaChapters.maxBy { it.chapter_number }?.chapter_number ?: -1f | ||||
|         val lastUpdate = Date(mangaChapters.maxBy { it.date_upload }?.date_upload ?: 0) | ||||
|  | ||||
|         if (latestChapter > 0f) { | ||||
|             manga_last_chapter.text = DecimalFormat("#.#").format(latestChapter) | ||||
|         } else { | ||||
|             manga_last_chapter.setText(R.string.unknown) | ||||
|         } | ||||
|  | ||||
|         if (lastUpdate.time != 0L) { | ||||
|             manga_last_update.text = DateFormat.getDateInstance(DateFormat.SHORT).format(lastUpdate) | ||||
|         } else { | ||||
|             manga_last_update.setText(R.string.unknown) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { | ||||
|         val objectAsView = `object` as View | ||||
|         container.removeView(objectAsView) | ||||
|         (objectAsView.tag as? ViewTag)?.destroy() | ||||
|     } | ||||
|  | ||||
|     class ViewTag(parent: CoroutineContext) : CoroutineScope { | ||||
|         /** | ||||
|          * The context of this scope. | ||||
|          * Context is encapsulated by the scope and used for implementation of coroutine builders that are extensions on the scope. | ||||
|          * Accessing this property in general code is not recommended for any purposes except accessing the [Job] instance for advanced usages. | ||||
|          * | ||||
|          * By convention, should contain an instance of a [job][Job] to enforce structured concurrency. | ||||
|          */ | ||||
|         override val coroutineContext = parent + Job() + Dispatchers.Default | ||||
|  | ||||
|         fun destroy() { | ||||
|             cancel() | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,239 +0,0 @@ | ||||
| package eu.kanade.tachiyomi.ui.migration.manga.process | ||||
|  | ||||
| import android.content.pm.ActivityInfo | ||||
| import android.os.Bundle | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import com.afollestad.materialdialogs.MaterialDialog | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.data.database.DatabaseHelper | ||||
| import eu.kanade.tachiyomi.smartsearch.SmartSearchEngine | ||||
| import eu.kanade.tachiyomi.source.SourceManager | ||||
| import eu.kanade.tachiyomi.ui.base.controller.BaseController | ||||
| import eu.kanade.tachiyomi.util.system.toast | ||||
| import kotlin.coroutines.CoroutineContext | ||||
| import kotlinx.android.synthetic.main.migration_process.pager | ||||
| import kotlinx.coroutines.CoroutineScope | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| import kotlinx.coroutines.Job | ||||
| import kotlinx.coroutines.cancel | ||||
| import kotlinx.coroutines.launch | ||||
| import uy.kohesive.injekt.injectLazy | ||||
|  | ||||
| // TODO Will probably implode if activity is fully destroyed | ||||
| class MigrationProcedureController(bundle: Bundle? = null) : BaseController(bundle), CoroutineScope { | ||||
|  | ||||
|     private var titleText = "Migrate manga" | ||||
|  | ||||
|     private var adapter: MigrationProcedureAdapter? = null | ||||
|  | ||||
|     override val coroutineContext: CoroutineContext = Job() + Dispatchers.Default | ||||
|  | ||||
|     val config: MigrationProcedureConfig? = args.getParcelable(CONFIG_EXTRA) | ||||
|  | ||||
|     private val db: DatabaseHelper by injectLazy() | ||||
|     private val sourceManager: SourceManager by injectLazy() | ||||
|  | ||||
|     private val smartSearchEngine = SmartSearchEngine(coroutineContext, config?.extraSearchParams) | ||||
|  | ||||
|     private var migrationsJob: Job? = null | ||||
|     private var migratingManga: List<MigratingManga>? = null | ||||
|  | ||||
|     override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { | ||||
|         return inflater.inflate(R.layout.migration_process, container, false) | ||||
|     } | ||||
|  | ||||
|     override fun getTitle(): String { | ||||
|         return titleText | ||||
|     } | ||||
|  | ||||
|     override fun onViewCreated(view: View) { | ||||
|         super.onViewCreated(view) | ||||
|         setTitle() | ||||
|         val config = this.config ?: return | ||||
|         activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT | ||||
|  | ||||
|         val newMigratingManga = migratingManga ?: run { | ||||
|             val new = config.mangaIds.map { | ||||
|                 MigratingManga(db, sourceManager, it, coroutineContext) | ||||
|             } | ||||
|             migratingManga = new | ||||
|             new | ||||
|         } | ||||
|  | ||||
|         adapter = MigrationProcedureAdapter(this, newMigratingManga, coroutineContext) | ||||
|  | ||||
|         pager.adapter = adapter | ||||
|         pager.isEnabled = false | ||||
|  | ||||
|         if (migrationsJob == null) { | ||||
|             migrationsJob = launch { | ||||
|                 runMigrations(newMigratingManga) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         pager.post { | ||||
|             // pager.currentItem doesn't appear to be valid if we don't do this in a post | ||||
|             updateTitle() | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fun updateTitle() { | ||||
|         titleText = "Migrate manga (${pager.currentItem + 1}/${adapter?.count ?: 0})" | ||||
|         setTitle() | ||||
|     } | ||||
|  | ||||
|     fun nextMigration() { | ||||
|         adapter?.let { adapter -> | ||||
|             if (pager.currentItem >= adapter.count - 1) { | ||||
|                 applicationContext?.toast("All migrations complete!") | ||||
|                 router.popCurrentController() | ||||
|             } else { | ||||
|                 adapter.migratingManga[pager.currentItem].migrationJob.cancel() | ||||
|                 pager.setCurrentItem(pager.currentItem + 1, true) | ||||
|                 launch(Dispatchers.Main) { | ||||
|                     updateTitle() | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fun migrationFailure() { | ||||
|         activity?.let { | ||||
|             MaterialDialog.Builder(it) | ||||
|                     .title("Migration failure") | ||||
|                     .content("An unknown error occured while migrating this manga!") | ||||
|                     .positiveText("Ok") | ||||
|                     .show() | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     suspend fun runMigrations(mangas: List<MigratingManga>) { | ||||
|         /*  val sources = config?.targetSourceIds?.mapNotNull { sourceManager.get(it) as? | ||||
|             CatalogueSource } ?: return | ||||
|  | ||||
|         for (manga in mangas) { | ||||
|             if (!manga.searchResult.initialized && manga.migrationJob.isActive) { | ||||
|                 val mangaObj = manga.manga() | ||||
|  | ||||
|                 if (mangaObj == null) { | ||||
|                     manga.searchResult.initialize(null) | ||||
|                     continue | ||||
|                 } | ||||
|  | ||||
|                 val mangaSource = manga.mangaSource() | ||||
|  | ||||
|                 val result = try { | ||||
|                     CoroutineScope(manga.migrationJob).async { | ||||
|                         val validSources = sources.filter { | ||||
|                             it.id != mangaSource.id | ||||
|                         } | ||||
|                         if (config.useSourceWithMostChapters) { | ||||
|                             val sourceSemaphore = Semaphore(3) | ||||
|                             val processedSources = AtomicInteger() | ||||
|  | ||||
|                             validSources.map { source -> | ||||
|                                 async { | ||||
|                                     sourceSemaphore.withPermit { | ||||
|                                         try { | ||||
|                                             val searchResult = if (config.enableLenientSearch) { | ||||
|                                                 smartSearchEngine.smartSearch(source, mangaObj.title) | ||||
|                                             } else { | ||||
|                                                 smartSearchEngine.normalSearch(source, mangaObj.title) | ||||
|                                             } | ||||
|  | ||||
|                                             if (searchResult != null) { | ||||
|                                                 val localManga = smartSearchEngine.networkToLocalManga(searchResult, source.id) | ||||
|                                                 val chapters = source.fetchChapterList(localManga).toSingle().await(Schedulers.io()) | ||||
|                                                 withContext(Dispatchers.IO) { | ||||
|                                                     syncChaptersWithSource(db, chapters, localManga, source) | ||||
|                                                 } | ||||
|                                                 manga.progress.send(validSources.size to processedSources.incrementAndGet()) | ||||
|                                                 localManga to chapters.size | ||||
|                                             } else { | ||||
|                                                 null | ||||
|                                             } | ||||
|                                         } catch (e: CancellationException) { | ||||
|                                             // Ignore cancellations | ||||
|                                             throw e | ||||
|                                         } catch (e: Exception) { | ||||
|                                             null | ||||
|                                         } | ||||
|                                     } | ||||
|                                 } | ||||
|                             }.mapNotNull { it.await() }.maxBy { it.second }?.first | ||||
|                         } else { | ||||
|                             validSources.forEachIndexed { index, source -> | ||||
|                                 val searchResult = try { | ||||
|                                     val searchResult = if (config.enableLenientSearch) { | ||||
|                                         smartSearchEngine.smartSearch(source, mangaObj.title) | ||||
|                                     } else { | ||||
|                                         smartSearchEngine.normalSearch(source, mangaObj.title) | ||||
|                                     } | ||||
|  | ||||
|                                     if (searchResult != null) { | ||||
|                                         val localManga = smartSearchEngine.networkToLocalManga(searchResult, source.id) | ||||
|                                         val chapters = source.fetchChapterList(localManga).toSingle().await(Schedulers.io()) | ||||
|                                         withContext(Dispatchers.IO) { | ||||
|                                             syncChaptersWithSource(db, chapters, localManga, source) | ||||
|                                         } | ||||
|                                         localManga | ||||
|                                     } else null | ||||
|                                 } catch (e: CancellationException) { | ||||
|                                     // Ignore cancellations | ||||
|                                     throw e | ||||
|                                 } catch (e: Exception) { | ||||
|                                     null | ||||
|                                 } | ||||
|  | ||||
|                                 manga.progress.send(validSources.size to (index + 1)) | ||||
|  | ||||
|                                 if (searchResult != null) return@async searchResult | ||||
|                             } | ||||
|  | ||||
|                             null | ||||
|                         } | ||||
|                     }.await() | ||||
|                 } catch (e: CancellationException) { | ||||
|                     // Ignore canceled migrations | ||||
|                     continue | ||||
|                 } | ||||
|  | ||||
|                 if (result != null && result.thumbnail_url == null) { | ||||
|                     try { | ||||
|                         val newManga = sourceManager.getOrStub(result.source) | ||||
|                                 .fetchMangaDetails(result) | ||||
|                                 .toSingle() | ||||
|                                 .await() | ||||
|                         result.copyFrom(newManga) | ||||
|  | ||||
|                         db.insertManga(result).executeAsBlocking() | ||||
|                     } catch (e: CancellationException) { | ||||
|                         // Ignore cancellations | ||||
|                         throw e | ||||
|                     } catch (e: Exception) { | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 manga.searchResult.initialize(result?.id) | ||||
|             } | ||||
|         }*/ | ||||
|     } | ||||
|  | ||||
|     override fun onDestroy() { | ||||
|         super.onDestroy() | ||||
|  | ||||
|         activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED | ||||
|     } | ||||
|  | ||||
|     companion object { | ||||
|         const val CONFIG_EXTRA = "config_extra" | ||||
|  | ||||
|         fun create(config: MigrationProcedureConfig): MigrationProcedureController { | ||||
|             return MigrationProcedureController(Bundle().apply { | ||||
|                 putParcelable(CONFIG_EXTRA, config) | ||||
|             }) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -19,8 +19,8 @@ import eu.kanade.tachiyomi.util.view.invisible | ||||
| import eu.kanade.tachiyomi.util.view.setVectorCompat | ||||
| import eu.kanade.tachiyomi.util.view.visible | ||||
| import java.text.DecimalFormat | ||||
| import kotlinx.android.synthetic.main.migration_new_manga_card.view.* | ||||
| import kotlinx.android.synthetic.main.migration_new_process_item.* | ||||
| import kotlinx.android.synthetic.main.migration_manga_card.view.* | ||||
| import kotlinx.android.synthetic.main.migration_process_item.* | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| import kotlinx.coroutines.withContext | ||||
| import uy.kohesive.injekt.injectLazy | ||||
| @@ -122,6 +122,7 @@ class MigrationProcessHolder( | ||||
|         manga_chapters.text = "" | ||||
|         manga_chapters.gone() | ||||
|         manga_last_chapter_label.text = "" | ||||
|         migration_manga_card_to.setOnClickListener(null) | ||||
|     } | ||||
|  | ||||
|     private fun View.attachManga(manga: Manga, source: Source) { | ||||
|   | ||||
| @@ -12,7 +12,7 @@ class MigrationProcessItem(val manga: MigratingManga) : | ||||
|  | ||||
|     var holder: MigrationProcessHolder? = null | ||||
|     override fun getLayoutRes(): Int { | ||||
|         return R.layout.migration_new_process_item | ||||
|         return R.layout.migration_process_item | ||||
|     } | ||||
|  | ||||
|     override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): MigrationProcessHolder { | ||||
|   | ||||
| @@ -11,6 +11,6 @@ | ||||
|         android:layout_height="wrap_content" | ||||
|         android:clipToPadding="false" | ||||
|         android:id="@+id/recycler" | ||||
|         tools:listitem="@layout/migration_new_process_item" /> | ||||
|         tools:listitem="@layout/migration_process_item" /> | ||||
|  | ||||
| </FrameLayout> | ||||
| @@ -1,270 +1,124 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" | ||||
| <androidx.constraintlayout.widget.ConstraintLayout 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_width="wrap_content" | ||||
|     android:layout_height="wrap_content" | ||||
|     android:foreground="?android:attr/selectableItemBackground" | ||||
|     android:clickable="true" | ||||
|     android:focusable="true"> | ||||
|     android:background="?selectable_library_drawable"> | ||||
|  | ||||
|     <androidx.constraintlayout.widget.ConstraintLayout | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:clickable="false"> | ||||
|     <FrameLayout | ||||
|         android:id="@+id/card" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="220dp" | ||||
|         android:background="@drawable/card_background" | ||||
|         app:layout_constraintDimensionRatio="0.75" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         app:layout_constraintTop_toTopOf="parent" | ||||
|         app:layout_constraintWidth_min="100dp" | ||||
|         app:layout_constraintHeight_min="100dp"> | ||||
|  | ||||
|         <ImageView | ||||
|             android:id="@+id/manga_cover" | ||||
|             android:layout_width="0dp" | ||||
|             android:layout_height="0dp" | ||||
|             android:layout_marginStart="16dp" | ||||
|             android:layout_marginTop="16dp" | ||||
|             android:contentDescription="@string/description_cover" | ||||
|             app:layout_constraintDimensionRatio="l,2:3" | ||||
|             app:layout_constraintLeft_toLeftOf="parent" | ||||
|             app:layout_constraintRight_toLeftOf="@+id/card_scroll_content" | ||||
|             app:layout_constraintTop_toTopOf="parent" | ||||
|             app:layout_constraintWidth_min="100dp" | ||||
|             tools:background="@color/material_grey_700" /> | ||||
|  | ||||
|         <androidx.constraintlayout.widget.ConstraintLayout | ||||
|             android:id="@+id/card_scroll_content" | ||||
|             android:layout_width="0dp" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_marginLeft="16dp" | ||||
|             android:layout_marginRight="16dp" | ||||
|             android:paddingBottom="16dp" | ||||
|             app:layout_constraintHorizontal_weight="2" | ||||
|             app:layout_constraintLeft_toRightOf="@+id/manga_cover" | ||||
|             app:layout_constraintRight_toRightOf="parent" | ||||
|             app:layout_constraintTop_toTopOf="@+id/manga_cover"> | ||||
|  | ||||
|             <TextView | ||||
|                 android:id="@+id/manga_full_title" | ||||
|                 style="@style/TextAppearance.Medium.Title" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:clickable="false" | ||||
|                 android:maxLines="2" | ||||
|                 android:text="@string/manga_info_full_title_label" | ||||
|                 android:textIsSelectable="false" | ||||
|                 app:autoSizeMaxTextSize="20sp" | ||||
|                 app:autoSizeMinTextSize="12sp" | ||||
|                 app:autoSizeStepGranularity="2sp" | ||||
|                 app:autoSizeTextType="uniform" | ||||
|                 app:layout_constraintLeft_toLeftOf="parent" | ||||
|                 app:layout_constraintTop_toTopOf="parent" /> | ||||
|  | ||||
|             <TextView | ||||
|                 android:id="@+id/manga_author_label" | ||||
|                 style="@style/TextAppearance.Medium.Body2" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:clickable="false" | ||||
|                 android:text="@string/manga_info_author_label" | ||||
|                 android:textIsSelectable="false" | ||||
|                 app:layout_constraintLeft_toLeftOf="parent" | ||||
|                 app:layout_constraintTop_toBottomOf="@+id/manga_full_title" /> | ||||
|  | ||||
|             <TextView | ||||
|                 android:id="@+id/manga_author" | ||||
|                 style="@style/TextAppearance.Regular.Body1.Secondary" | ||||
|                 android:layout_width="0dp" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:layout_marginStart="8dp" | ||||
|                 android:clickable="false" | ||||
|                 android:ellipsize="end" | ||||
|                 android:maxLines="1" | ||||
|                 android:textIsSelectable="false" | ||||
|                 app:layout_constraintBaseline_toBaselineOf="@+id/manga_author_label" | ||||
|                 app:layout_constraintLeft_toRightOf="@+id/manga_author_label" | ||||
|                 app:layout_constraintRight_toRightOf="parent" /> | ||||
|  | ||||
|             <TextView | ||||
|                 android:id="@+id/manga_artist_label" | ||||
|                 style="@style/TextAppearance.Medium.Body2" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:clickable="false" | ||||
|                 android:text="@string/manga_info_artist_label" | ||||
|                 android:textIsSelectable="false" | ||||
|                 app:layout_constraintLeft_toLeftOf="parent" | ||||
|                 app:layout_constraintTop_toBottomOf="@+id/manga_author_label" /> | ||||
|  | ||||
|             <TextView | ||||
|                 android:id="@+id/manga_artist" | ||||
|                 style="@style/TextAppearance.Regular.Body1.Secondary" | ||||
|                 android:layout_width="0dp" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:layout_marginStart="8dp" | ||||
|                 android:clickable="false" | ||||
|                 android:ellipsize="end" | ||||
|                 android:maxLines="1" | ||||
|                 android:textIsSelectable="false" | ||||
|                 app:layout_constraintBaseline_toBaselineOf="@+id/manga_artist_label" | ||||
|                 app:layout_constraintLeft_toRightOf="@+id/manga_artist_label" | ||||
|                 app:layout_constraintRight_toRightOf="parent" /> | ||||
|  | ||||
|             <TextView | ||||
|                 android:id="@+id/manga_status_label" | ||||
|                 style="@style/TextAppearance.Medium.Body2" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:clickable="false" | ||||
|                 android:text="@string/manga_info_status_label" | ||||
|                 android:textIsSelectable="false" | ||||
|                 app:layout_constraintLeft_toLeftOf="parent" | ||||
|                 app:layout_constraintTop_toBottomOf="@+id/manga_artist_label" /> | ||||
|  | ||||
|             <TextView | ||||
|                 android:id="@+id/manga_status" | ||||
|                 style="@style/TextAppearance.Regular.Body1.Secondary" | ||||
|                 android:layout_width="0dp" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:layout_marginStart="8dp" | ||||
|                 android:clickable="false" | ||||
|                 android:ellipsize="end" | ||||
|                 android:maxLines="1" | ||||
|                 android:textIsSelectable="false" | ||||
|                 app:layout_constraintBaseline_toBaselineOf="@+id/manga_status_label" | ||||
|                 app:layout_constraintLeft_toRightOf="@+id/manga_status_label" | ||||
|                 app:layout_constraintRight_toRightOf="parent" /> | ||||
|  | ||||
|             <TextView | ||||
|                 android:id="@+id/manga_chapters_label" | ||||
|                 style="@style/TextAppearance.Medium.Body2" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:clickable="false" | ||||
|                 android:text="@string/manga_info_chapters_label" | ||||
|                 android:textIsSelectable="false" | ||||
|                 app:layout_constraintLeft_toLeftOf="parent" | ||||
|                 app:layout_constraintTop_toBottomOf="@+id/manga_status_label" /> | ||||
|  | ||||
|             <TextView | ||||
|                 android:id="@+id/manga_chapters" | ||||
|                 style="@style/TextAppearance.Regular.Body1.Secondary" | ||||
|                 android:layout_width="0dp" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:layout_marginStart="8dp" | ||||
|                 android:clickable="false" | ||||
|                 android:textIsSelectable="false" | ||||
|                 app:layout_constraintLeft_toRightOf="@+id/manga_chapters_label" | ||||
|                 app:layout_constraintRight_toRightOf="parent" | ||||
|                 app:layout_constraintTop_toBottomOf="@+id/manga_status_label" /> | ||||
|  | ||||
|             <TextView | ||||
|                 android:id="@+id/manga_last_chapter_label" | ||||
|                 style="@style/TextAppearance.Medium.Body2" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:clickable="false" | ||||
|                 android:text="@string/manga_info_last_chapter_label" | ||||
|                 android:textIsSelectable="false" | ||||
|                 app:layout_constraintLeft_toLeftOf="parent" | ||||
|                 app:layout_constraintTop_toBottomOf="@+id/manga_chapters_label" /> | ||||
|  | ||||
|             <TextView | ||||
|                 android:id="@+id/manga_last_chapter" | ||||
|                 style="@style/TextAppearance.Regular.Body1.Secondary" | ||||
|                 android:layout_width="0dp" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:layout_marginStart="8dp" | ||||
|                 android:clickable="false" | ||||
|                 android:textIsSelectable="false" | ||||
|                 app:layout_constraintLeft_toRightOf="@+id/manga_last_chapter_label" | ||||
|                 app:layout_constraintRight_toRightOf="parent" | ||||
|                 app:layout_constraintTop_toBottomOf="@+id/manga_chapters_label" /> | ||||
|  | ||||
|             <TextView | ||||
|                 android:id="@+id/manga_last_update_label" | ||||
|                 style="@style/TextAppearance.Medium.Body2" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:clickable="false" | ||||
|                 android:text="@string/manga_info_latest_data_label" | ||||
|                 android:textIsSelectable="false" | ||||
|                 app:layout_constraintLeft_toLeftOf="parent" | ||||
|                 app:layout_constraintTop_toBottomOf="@+id/manga_last_chapter_label" /> | ||||
|  | ||||
|             <TextView | ||||
|                 android:id="@+id/manga_last_update" | ||||
|                 style="@style/TextAppearance.Regular.Body1.Secondary" | ||||
|                 android:layout_width="0dp" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:layout_marginStart="8dp" | ||||
|                 android:clickable="false" | ||||
|                 android:textIsSelectable="false" | ||||
|                 app:layout_constraintLeft_toRightOf="@+id/manga_last_update_label" | ||||
|                 app:layout_constraintRight_toRightOf="parent" | ||||
|                 app:layout_constraintTop_toBottomOf="@+id/manga_last_chapter_label" /> | ||||
|  | ||||
|             <TextView | ||||
|                 android:id="@+id/manga_source_label" | ||||
|                 style="@style/TextAppearance.Medium.Body2" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:clickable="false" | ||||
|                 android:text="@string/manga_info_source_label" | ||||
|                 android:textIsSelectable="false" | ||||
|                 app:layout_constraintLeft_toLeftOf="parent" | ||||
|                 app:layout_constraintTop_toBottomOf="@+id/manga_last_update_label" /> | ||||
|  | ||||
|             <TextView | ||||
|                 android:id="@+id/manga_source" | ||||
|                 style="@style/TextAppearance.Regular.Body1.Secondary" | ||||
|                 android:layout_width="0dp" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:layout_marginStart="8dp" | ||||
|                 android:clickable="false" | ||||
|                 android:textIsSelectable="false" | ||||
|                 app:layout_constraintLeft_toRightOf="@+id/manga_source_label" | ||||
|                 app:layout_constraintRight_toRightOf="parent" | ||||
|                 app:layout_constraintTop_toBottomOf="@+id/manga_last_update_label" /> | ||||
|  | ||||
|         </androidx.constraintlayout.widget.ConstraintLayout> | ||||
|             android:id="@+id/thumbnail" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="match_parent" | ||||
|             android:background="?android:attr/colorBackground" | ||||
|             tools:background="?android:attr/colorBackground" | ||||
|             tools:ignore="ContentDescription" | ||||
|             tools:src="@mipmap/ic_launcher" /> | ||||
|  | ||||
|         <View | ||||
|             android:id="@+id/card_shim" | ||||
|             android:layout_width="0dp" | ||||
|             android:layout_height="0dp" | ||||
|             android:alpha="0.9" | ||||
|             android:background="?attr/colorSurface" | ||||
|             app:layout_constraintBottom_toBottomOf="parent" | ||||
|             app:layout_constraintEnd_toEndOf="parent" | ||||
|             app:layout_constraintStart_toStartOf="parent" | ||||
|             app:layout_constraintTop_toTopOf="parent" /> | ||||
|  | ||||
|         <TextView | ||||
|             android:id="@+id/search_status" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:id="@+id/gradient" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_marginStart="8dp" | ||||
|             android:layout_marginLeft="8dp" | ||||
|             android:layout_marginTop="8dp" | ||||
|             android:layout_marginEnd="8dp" | ||||
|             android:layout_marginRight="8dp" | ||||
|             android:layout_marginBottom="8dp" | ||||
|             android:text="Searching..." | ||||
|             android:textAppearance="@style/TextAppearance.AppCompat.Large" | ||||
|             app:layout_constraintBottom_toTopOf="@+id/search_progress" | ||||
|             app:layout_constraintEnd_toEndOf="@+id/card_shim" | ||||
|             app:layout_constraintStart_toStartOf="parent" | ||||
|             app:layout_constraintTop_toTopOf="@+id/card_shim" /> | ||||
|             android:layout_gravity="bottom" | ||||
|             android:background="@drawable/gradient_shape" /> | ||||
|  | ||||
|         <ProgressBar | ||||
|             android:id="@+id/search_progress" | ||||
|             style="?android:attr/progressBarStyleHorizontal" | ||||
|             android:layout_width="0dp" | ||||
|             android:layout_height="wrap_content" | ||||
|             app:layout_constraintBottom_toBottomOf="@+id/card_shim" | ||||
|             app:layout_constraintEnd_toEndOf="@+id/card_shim" | ||||
|             app:layout_constraintStart_toStartOf="parent" /> | ||||
|  | ||||
|         <androidx.constraintlayout.widget.Group | ||||
|             android:id="@+id/loading_group" | ||||
|             android:layout_width="56dp" | ||||
|             android:layout_height="56dp" | ||||
|             android:layout_gravity="center" /> | ||||
|  | ||||
|         <TextView | ||||
|             android:id="@+id/manga_chapters" | ||||
|             style="@style/TextAppearance.Regular.Caption.Light" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             app:constraint_referenced_ids="card_shim,search_status,search_progress" /> | ||||
|     </androidx.constraintlayout.widget.ConstraintLayout> | ||||
| </androidx.cardview.widget.CardView> | ||||
|             android:background="@color/md_teal_500" | ||||
|             android:paddingBottom="1dp" | ||||
|             android:paddingLeft="3dp" | ||||
|             android:paddingRight="3dp" | ||||
|             android:paddingTop="1dp" | ||||
|             android:visibility="gone" | ||||
|             tools:visibility="visible" | ||||
|             android:text="101" | ||||
|             android:layout_marginStart="4dp" | ||||
|             app:layout_constraintLeft_toLeftOf="parent" | ||||
|             app:layout_constraintTop_toTopOf="parent" | ||||
|             android:layout_marginTop="4dp"/> | ||||
|  | ||||
|         <eu.kanade.tachiyomi.widget.PTSansTextView | ||||
|             android:id="@+id/title" | ||||
|             style="@style/TextAppearance.Regular.Body1.Light" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_gravity="bottom" | ||||
|             android:ellipsize="end" | ||||
|             android:lineSpacingExtra="-4dp" | ||||
|             android:maxLines="2" | ||||
|             android:padding="8dp" | ||||
|             android:shadowColor="@color/textColorPrimaryLight" | ||||
|             android:shadowDx="0" | ||||
|             android:shadowDy="0" | ||||
|             android:shadowRadius="4" | ||||
|             app:typeface="ptsansNarrowBold" | ||||
|             tools:text="Sample name" /> | ||||
|  | ||||
|         <ProgressBar | ||||
|             android:id="@+id/progress" | ||||
|             style="?android:attr/progressBarStyleSmall" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_gravity="center" | ||||
|             android:visibility="gone" /> | ||||
|  | ||||
|     </FrameLayout> | ||||
|  | ||||
|     <LinearLayout | ||||
|         android:id="@+id/card_scroll_content" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:paddingBottom="20dp" | ||||
|         android:gravity="start" | ||||
|         android:orientation="vertical" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintEnd_toEndOf="@id/card" | ||||
|         app:layout_constraintStart_toStartOf="@id/card" | ||||
|         app:layout_constraintTop_toBottomOf="@id/card"> | ||||
|  | ||||
|  | ||||
|         <TextView | ||||
|             android:id="@+id/manga_source_label" | ||||
|             style="@style/TextAppearance.Medium.Body2" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:clickable="false" | ||||
|             android:textIsSelectable="false" | ||||
|             app:layout_constraintLeft_toLeftOf="parent" | ||||
|             android:ellipsize="end" | ||||
|             android:maxLines="1" | ||||
|             tools:layout_editor_absoluteY="57dp" /> | ||||
|  | ||||
|         <TextView | ||||
|             android:id="@+id/manga_last_chapter_label" | ||||
|             style="@style/TextAppearance.Regular.Body1.Secondary" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:clickable="false" | ||||
|             android:textIsSelectable="false" /> | ||||
|  | ||||
|     </LinearLayout> | ||||
|  | ||||
| </androidx.constraintlayout.widget.ConstraintLayout> | ||||
| @@ -1,123 +0,0 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <androidx.constraintlayout.widget.ConstraintLayout 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="wrap_content" | ||||
|     android:layout_height="wrap_content" | ||||
|     android:background="?selectable_library_drawable"> | ||||
|  | ||||
|     <FrameLayout | ||||
|         android:id="@+id/card" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="220dp" | ||||
|         android:background="?attr/colorSurface" | ||||
|         app:layout_constraintDimensionRatio="0.75" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         app:layout_constraintTop_toTopOf="parent" | ||||
|         app:layout_constraintWidth_min="100dp" | ||||
|         app:layout_constraintHeight_min="100dp"> | ||||
|  | ||||
|         <ImageView | ||||
|             android:id="@+id/thumbnail" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="match_parent" | ||||
|             android:background="?android:attr/colorBackground" | ||||
|             tools:background="?android:attr/colorBackground" | ||||
|             tools:ignore="ContentDescription" | ||||
|             tools:src="@mipmap/ic_launcher" /> | ||||
|  | ||||
|         <View | ||||
|             android:id="@+id/gradient" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_gravity="bottom" | ||||
|             android:background="@drawable/gradient_shape" /> | ||||
|  | ||||
|         <ProgressBar | ||||
|             android:id="@+id/loading_group" | ||||
|             android:layout_width="56dp" | ||||
|             android:layout_height="56dp" | ||||
|             android:layout_gravity="center" /> | ||||
|  | ||||
|         <TextView | ||||
|             android:id="@+id/manga_chapters" | ||||
|             style="@style/TextAppearance.Regular.Caption.Light" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:background="@color/md_teal_500" | ||||
|             android:paddingBottom="1dp" | ||||
|             android:paddingLeft="3dp" | ||||
|             android:paddingRight="3dp" | ||||
|             android:paddingTop="1dp" | ||||
|             android:visibility="gone" | ||||
|             tools:visibility="visible" | ||||
|             android:text="101" | ||||
|             android:layout_marginStart="4dp" | ||||
|             app:layout_constraintLeft_toLeftOf="parent" | ||||
|             app:layout_constraintTop_toTopOf="parent" | ||||
|             android:layout_marginTop="4dp"/> | ||||
|  | ||||
|         <com.google.android.material.textview.MaterialTextView | ||||
|             android:id="@+id/title" | ||||
|             style="@style/TextAppearance.Regular.Body1.Light" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_gravity="bottom" | ||||
|             android:ellipsize="end" | ||||
|             android:lineSpacingExtra="-4dp" | ||||
|             android:maxLines="2" | ||||
|             android:padding="8dp" | ||||
|             android:shadowColor="@color/textColorPrimaryLight" | ||||
|             android:shadowDx="0" | ||||
|             android:shadowDy="0" | ||||
|             android:shadowRadius="4" | ||||
|             tools:text="Sample name" /> | ||||
|  | ||||
|         <ProgressBar | ||||
|             android:id="@+id/progress" | ||||
|             style="?android:attr/progressBarStyleSmall" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_gravity="center" | ||||
|             android:visibility="gone" /> | ||||
|  | ||||
|     </FrameLayout> | ||||
|  | ||||
|     <LinearLayout | ||||
|         android:id="@+id/card_scroll_content" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:paddingBottom="20dp" | ||||
|         android:gravity="start" | ||||
|         android:orientation="vertical" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintEnd_toEndOf="@id/card" | ||||
|         app:layout_constraintStart_toStartOf="@id/card" | ||||
|         app:layout_constraintTop_toBottomOf="@id/card"> | ||||
|  | ||||
|  | ||||
|         <TextView | ||||
|             android:id="@+id/manga_source_label" | ||||
|             style="@style/TextAppearance.Medium.Body2" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:clickable="false" | ||||
|             android:textIsSelectable="false" | ||||
|             app:layout_constraintLeft_toLeftOf="parent" | ||||
|             android:ellipsize="end" | ||||
|             android:maxLines="1" | ||||
|             tools:layout_editor_absoluteY="57dp" /> | ||||
|  | ||||
|         <TextView | ||||
|             android:id="@+id/manga_last_chapter_label" | ||||
|             style="@style/TextAppearance.Regular.Body1.Secondary" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:clickable="false" | ||||
|             android:textIsSelectable="false" /> | ||||
|  | ||||
|     </LinearLayout> | ||||
|  | ||||
| </androidx.constraintlayout.widget.ConstraintLayout> | ||||
| @@ -1,72 +0,0 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <androidx.constraintlayout.widget.ConstraintLayout 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" | ||||
|     android:gravity="center"> | ||||
|  | ||||
|     <include | ||||
|         android:id="@+id/migration_manga_card_from" | ||||
|         layout="@layout/migration_new_manga_card" | ||||
|         android:layout_width="150dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintEnd_toStartOf="@+id/imageView" | ||||
|         app:layout_constraintHorizontal_bias="0.5" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         app:layout_constraintTop_toTopOf="parent" /> | ||||
|  | ||||
|     <ImageView | ||||
|         android:id="@+id/imageView" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="25dp" | ||||
|         android:adjustViewBounds="true" | ||||
|         android:contentDescription="@string/migrating_to" | ||||
|         android:scaleType="center" | ||||
|         android:layout_marginBottom="45dp" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintEnd_toStartOf="@+id/migration_manga_card_to" | ||||
|         app:layout_constraintHorizontal_bias="0.5" | ||||
|         app:layout_constraintStart_toEndOf="@+id/migration_manga_card_from" | ||||
|         app:layout_constraintTop_toTopOf="parent" | ||||
|         app:srcCompat="@drawable/ic_keyboard_arrow_right_black_24dp" /> | ||||
|  | ||||
|     <include | ||||
|         android:id="@+id/migration_manga_card_to" | ||||
|         layout="@layout/migration_new_manga_card" | ||||
|         android:layout_width="150dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintEnd_toStartOf="@+id/migration_menu" | ||||
|         app:layout_constraintHorizontal_bias="0.5" | ||||
|         app:layout_constraintStart_toEndOf="@+id/imageView" | ||||
|         app:layout_constraintTop_toTopOf="parent" /> | ||||
|  | ||||
|     <ImageView | ||||
|         android:id="@+id/migration_menu" | ||||
|         android:layout_width="48dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:contentDescription="@string/description_cover" | ||||
|         android:paddingTop="30dp" | ||||
|         android:paddingBottom="30dp" | ||||
|         android:layout_marginBottom="45dp" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintHorizontal_bias="0.5" | ||||
|         app:layout_constraintStart_toEndOf="@+id/migration_manga_card_to" | ||||
|         app:layout_constraintTop_toTopOf="parent" | ||||
|         app:srcCompat="@drawable/ic_more_vert_24dp" | ||||
|         android:visibility="invisible"/> | ||||
|  | ||||
|  | ||||
|     <ImageView | ||||
|         android:id="@+id/skip_manga" | ||||
|         android:layout_width="48dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         app:layout_constraintBottom_toBottomOf="@+id/migration_menu" | ||||
|         app:layout_constraintEnd_toEndOf="@+id/migration_menu" | ||||
|         app:layout_constraintStart_toStartOf="@+id/migration_menu" | ||||
|         app:layout_constraintTop_toTopOf="@+id/migration_menu" | ||||
|         app:srcCompat="@drawable/ic_close_24dp" /> | ||||
| </androidx.constraintlayout.widget.ConstraintLayout> | ||||
| @@ -1,18 +0,0 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <androidx.constraintlayout.widget.ConstraintLayout | ||||
|     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="match_parent" | ||||
|     android:background="?attr/colorPrimary" > | ||||
|  | ||||
|     <eu.kanade.tachiyomi.ui.migration.manga.process.DeactivatableViewPager | ||||
|         android:id="@+id/pager" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         app:layout_constraintTop_toTopOf="parent" /> | ||||
| </androidx.constraintlayout.widget.ConstraintLayout> | ||||
| @@ -1,108 +1,72 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
| <androidx.constraintlayout.widget.ConstraintLayout 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="match_parent" | ||||
|     android:animateLayoutChanges="true"> | ||||
|     android:layout_height="wrap_content" | ||||
|     android:gravity="center"> | ||||
|  | ||||
|     <androidx.constraintlayout.widget.ConstraintLayout | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent"> | ||||
|     <include | ||||
|         android:id="@+id/migration_manga_card_from" | ||||
|         layout="@layout/migration_manga_card" | ||||
|         android:layout_width="150dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintEnd_toStartOf="@+id/imageView" | ||||
|         app:layout_constraintHorizontal_bias="0.5" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         app:layout_constraintTop_toTopOf="parent" /> | ||||
|  | ||||
|         <include | ||||
|             android:id="@+id/migration_manga_card_from" | ||||
|             layout="@layout/migration_manga_card" | ||||
|             android:layout_width="0dp" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_marginStart="16dp" | ||||
|             android:layout_marginLeft="16dp" | ||||
|             android:layout_marginTop="16dp" | ||||
|             android:layout_marginEnd="16dp" | ||||
|             android:layout_marginRight="16dp" | ||||
|             app:layout_constraintEnd_toEndOf="parent" | ||||
|             app:layout_constraintStart_toStartOf="parent" | ||||
|             app:layout_constraintTop_toTopOf="parent" | ||||
|             app:layout_constraintWidth_max="450dp" /> | ||||
|     <ImageView | ||||
|         android:id="@+id/imageView" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="25dp" | ||||
|         android:adjustViewBounds="true" | ||||
|         android:contentDescription="@string/migrating_to" | ||||
|         android:scaleType="center" | ||||
|         android:layout_marginBottom="45dp" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintEnd_toStartOf="@+id/migration_manga_card_to" | ||||
|         app:layout_constraintHorizontal_bias="0.5" | ||||
|         app:layout_constraintStart_toEndOf="@+id/migration_manga_card_from" | ||||
|         app:layout_constraintTop_toTopOf="parent" | ||||
|         app:srcCompat="@drawable/ic_keyboard_arrow_right_black_24dp" /> | ||||
|  | ||||
|         <ImageView | ||||
|             android:id="@+id/imageView" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="50dp" | ||||
|             android:adjustViewBounds="true" | ||||
|             android:contentDescription="migrating to" | ||||
|             android:scaleType="center" | ||||
|             app:layout_constraintEnd_toEndOf="parent" | ||||
|             app:layout_constraintStart_toStartOf="parent" | ||||
|             app:layout_constraintTop_toBottomOf="@+id/migration_manga_card_from" | ||||
|             app:srcCompat="@drawable/ic_arrow_down_white_32dp" /> | ||||
|     <include | ||||
|         android:id="@+id/migration_manga_card_to" | ||||
|         layout="@layout/migration_manga_card" | ||||
|         android:layout_width="150dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintEnd_toStartOf="@+id/migration_menu" | ||||
|         app:layout_constraintHorizontal_bias="0.5" | ||||
|         app:layout_constraintStart_toEndOf="@+id/imageView" | ||||
|         app:layout_constraintTop_toTopOf="parent" /> | ||||
|  | ||||
|         <include | ||||
|             android:id="@+id/migration_manga_card_to" | ||||
|             layout="@layout/migration_manga_card" | ||||
|             android:layout_width="0dp" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_marginStart="16dp" | ||||
|             android:layout_marginLeft="16dp" | ||||
|             android:layout_marginEnd="16dp" | ||||
|             android:layout_marginRight="16dp" | ||||
|             app:layout_constraintEnd_toEndOf="parent" | ||||
|             app:layout_constraintStart_toStartOf="parent" | ||||
|             app:layout_constraintTop_toBottomOf="@+id/imageView" | ||||
|             app:layout_constraintWidth_max="450dp" /> | ||||
|     <ImageView | ||||
|         android:id="@+id/migration_menu" | ||||
|         android:layout_width="48dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:contentDescription="@string/description_cover" | ||||
|         android:paddingTop="30dp" | ||||
|         android:paddingBottom="30dp" | ||||
|         android:layout_marginBottom="45dp" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintHorizontal_bias="0.5" | ||||
|         app:layout_constraintStart_toEndOf="@+id/migration_manga_card_to" | ||||
|         app:layout_constraintTop_toTopOf="parent" | ||||
|         app:srcCompat="@drawable/ic_more_vert_black_24dp" | ||||
|         android:visibility="invisible"/> | ||||
|  | ||||
|         <Button | ||||
|             android:id="@+id/skip_migration" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_marginEnd="8dp" | ||||
|             android:layout_marginBottom="8dp" | ||||
|             android:drawableStart="@drawable/ic_clear_grey" | ||||
|             android:drawablePadding="6dp" | ||||
|             android:text="Skip manga" | ||||
|             android:textColor="#ffffff" | ||||
|             app:backgroundTint="#E53935" | ||||
|             app:layout_constraintBottom_toBottomOf="parent" | ||||
|             app:layout_constraintEnd_toStartOf="@+id/accept_migration" | ||||
|             app:layout_constraintHorizontal_bias="0.5" | ||||
|             app:layout_constraintStart_toStartOf="parent" /> | ||||
|  | ||||
|         <Button | ||||
|             android:id="@+id/accept_migration" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:alpha="0.5" | ||||
|             android:drawableStart="@drawable/ic_check_box_24dp" | ||||
|             android:drawablePadding="6dp" | ||||
|             android:enabled="false" | ||||
|             android:text="Migrate manga" | ||||
|             android:textColor="#ffffff" | ||||
|             app:backgroundTint="#00C853" | ||||
|             app:layout_constraintBottom_toBottomOf="@+id/skip_migration" | ||||
|             app:layout_constraintEnd_toEndOf="parent" | ||||
|             app:layout_constraintHorizontal_bias="0.5" | ||||
|             app:layout_constraintStart_toEndOf="@+id/skip_migration" /> | ||||
|  | ||||
|     </androidx.constraintlayout.widget.ConstraintLayout> | ||||
|  | ||||
|     <FrameLayout | ||||
|         android:id="@+id/migrating_frame" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" | ||||
|         android:visibility="gone"> | ||||
|  | ||||
|         <View | ||||
|             android:id="@+id/migrating_view" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="match_parent" | ||||
|             android:background="#E6FFFFFF" /> | ||||
|  | ||||
|         <ProgressBar | ||||
|             android:id="@+id/migrating_progress" | ||||
|             style="?android:attr/progressBarStyle" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_gravity="center" /> | ||||
|     </FrameLayout> | ||||
|  | ||||
| </FrameLayout> | ||||
|     <ImageView | ||||
|         android:id="@+id/skip_manga" | ||||
|         android:layout_width="48dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         app:layout_constraintBottom_toBottomOf="@+id/migration_menu" | ||||
|         app:layout_constraintEnd_toEndOf="@+id/migration_menu" | ||||
|         app:layout_constraintStart_toStartOf="@+id/migration_menu" | ||||
|         app:layout_constraintTop_toTopOf="@+id/migration_menu" | ||||
|         app:srcCompat="@drawable/baseline_close_24" /> | ||||
| </androidx.constraintlayout.widget.ConstraintLayout> | ||||
		Reference in New Issue
	
	Block a user