Fixes to the fast scroller for this fork + remove keyword searching

This commit is contained in:
Jay 2020-01-06 02:28:15 -08:00
parent d8f385cc63
commit b668cc9abc
7 changed files with 82 additions and 82 deletions

View File

@ -193,8 +193,6 @@ class PreferencesHelper(val context: Context) {
fun migrationSources() = rxPrefs.getString("migrate_sources", "") fun migrationSources() = rxPrefs.getString("migrate_sources", "")
fun smartMigration() = rxPrefs.getBoolean("smart_migrate", false)
fun useSourceWithMost() = rxPrefs.getBoolean("use_source_with_most", false) fun useSourceWithMost() = rxPrefs.getBoolean("use_source_with_most", false)
fun skipPreMigration() = rxPrefs.getBoolean(Keys.skipPreMigration, false) fun skipPreMigration() = rxPrefs.getBoolean(Keys.skipPreMigration, false)

View File

@ -25,7 +25,7 @@ class SmartSearchEngine(parentContext: CoroutineContext,
private val normalizedLevenshtein = NormalizedLevenshtein() private val normalizedLevenshtein = NormalizedLevenshtein()
suspend fun smartSearch(source: CatalogueSource, title: String): SManga? { /*suspend fun smartSearch(source: CatalogueSource, title: String): SManga? {
val cleanedTitle = cleanSmartSearchTitle(title) val cleanedTitle = cleanSmartSearchTitle(title)
val queries = getSmartSearchQueries(cleanedTitle) val queries = getSmartSearchQueries(cleanedTitle)
@ -52,7 +52,7 @@ class SmartSearchEngine(parentContext: CoroutineContext,
} }
return eligibleManga.maxBy { it.dist }?.manga return eligibleManga.maxBy { it.dist }?.manga
} }*/
suspend fun normalSearch(source: CatalogueSource, title: String): SManga? { suspend fun normalSearch(source: CatalogueSource, title: String): SManga? {
val eligibleManga = supervisorScope { val eligibleManga = supervisorScope {
@ -74,52 +74,6 @@ class SmartSearchEngine(parentContext: CoroutineContext,
return eligibleManga.maxBy { it.dist }?.manga return eligibleManga.maxBy { it.dist }?.manga
} }
private fun getSmartSearchQueries(cleanedTitle: String): List<String> {
val splitCleanedTitle = cleanedTitle.split(" ")
val splitSortedByLargest = splitCleanedTitle.sortedByDescending { it.length }
if(splitCleanedTitle.isEmpty()) {
return emptyList()
}
// Search cleaned title
// Search two largest words
// Search largest word
// Search first two words
// Search first word
val searchQueries = listOf(
listOf(cleanedTitle),
splitSortedByLargest.take(2),
splitSortedByLargest.take(1),
splitCleanedTitle.take(2),
splitCleanedTitle.take(1)
)
return searchQueries.map {
it.joinToString(" ").trim()
}.distinct()
}
private fun cleanSmartSearchTitle(title: String): String {
val preTitle = title.toLowerCase()
// Remove text in brackets
var cleanedTitle = removeTextInBrackets(preTitle, true)
if(cleanedTitle.length <= 5) { // Title is suspiciously short, try parsing it backwards
cleanedTitle = removeTextInBrackets(preTitle, false)
}
// Strip non-special characters
cleanedTitle = cleanedTitle.replace(titleRegex, " ")
// Strip splitters and consecutive spaces
cleanedTitle = cleanedTitle.trim().replace(" - ", " ").replace(consecutiveSpacesRegex, " ").trim()
return cleanedTitle
}
private fun removeTextInBrackets(text: String, readForward: Boolean): String { private fun removeTextInBrackets(text: String, readForward: Boolean): String {
val bracketPairs = listOf( val bracketPairs = listOf(
'(' to ')', '(' to ')',

View File

@ -1,9 +1,25 @@
package eu.kanade.tachiyomi.ui.library package eu.kanade.tachiyomi.ui.library
import android.graphics.Color
import android.text.format.DateUtils
import androidx.core.content.ContextCompat
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.IFlexible import eu.davidea.flexibleadapter.items.IFlexible
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.database.models.Manga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.ui.category.CategoryAdapter import eu.kanade.tachiyomi.ui.category.CategoryAdapter
import eu.kanade.tachiyomi.util.getResourceColor
import eu.kanade.tachiyomi.util.removeArticles
import uy.kohesive.injekt.injectLazy
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.Year
import java.util.* import java.util.*
@ -12,7 +28,7 @@ import java.util.*
* *
* @param view the fragment containing this adapter. * @param view the fragment containing this adapter.
*/ */
class LibraryCategoryAdapter(view: LibraryCategoryView) : class LibraryCategoryAdapter(val view: LibraryCategoryView) :
FlexibleAdapter<LibraryItem>(null, view, true) { FlexibleAdapter<LibraryItem>(null, view, true) {
/** /**
@ -58,8 +74,52 @@ class LibraryCategoryAdapter(view: LibraryCategoryView) :
"Bottom" "Bottom"
} else { // Get and show the first character } else { // Get and show the first character
val iFlexible: IFlexible<*>? = getItem(position) val iFlexible: IFlexible<*>? = getItem(position)
(iFlexible as LibraryItem).manga.title.substring(0, 1).toUpperCase(Locale.US) val preferences:PreferencesHelper by injectLazy()
when (preferences.librarySortingMode().getOrDefault()) {
LibrarySort.LAST_READ -> {
val db:DatabaseHelper by injectLazy()
val id = (iFlexible as LibraryItem).manga.id ?: return ""
val history = db.getHistoryByMangaId(id).executeAsBlocking()
if (history.firstOrNull() != null)
getShortDate(Date(history.first().last_read))
else
"Never Read"
}
LibrarySort.LAST_UPDATED -> {
val lastUpdate = (iFlexible as LibraryItem).manga.last_update
if (lastUpdate > 0)
getShortDate(Date(lastUpdate))
else
"N/A"
}
LibrarySort.SOURCE -> {
val sourceId = (iFlexible as LibraryItem).manga.source
val sourceManager:SourceManager by injectLazy()
sourceManager.getOrStub(sourceId).name.substring(0, 1).toUpperCase(Locale.US)
}
else -> {
val title = (iFlexible as LibraryItem).manga.title
if (preferences.removeArticles().getOrDefault())
title.removeArticles().substring(0, 1).toUpperCase(Locale.US)
else title.substring(0, 1).toUpperCase(Locale.US)
}
}
} }
} }
private fun getShortDate(date:Date):String {
val cal = Calendar.getInstance()
cal.time = Date()
val yearNow = cal.get(Calendar.YEAR)
val cal2 = Calendar.getInstance()
cal2.time = date
val yearThen = cal2.get(Calendar.YEAR)
return if (yearNow == yearThen)
SimpleDateFormat("MMM").format(date)
else
SimpleDateFormat("yyyy").format(date)
}
} }

View File

@ -6,6 +6,7 @@ import androidx.recyclerview.widget.RecyclerView
import android.util.AttributeSet import android.util.AttributeSet
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout import android.widget.FrameLayout
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.SelectableAdapter import eu.davidea.flexibleadapter.SelectableAdapter
@ -19,6 +20,7 @@ import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.ui.category.CategoryAdapter import eu.kanade.tachiyomi.ui.category.CategoryAdapter
import eu.kanade.tachiyomi.util.* import eu.kanade.tachiyomi.util.*
import eu.kanade.tachiyomi.widget.AutofitRecyclerView import eu.kanade.tachiyomi.widget.AutofitRecyclerView
import kotlinx.android.synthetic.main.chapters_controller.*
import kotlinx.android.synthetic.main.library_category.view.* import kotlinx.android.synthetic.main.library_category.view.*
import rx.subscriptions.CompositeSubscription import rx.subscriptions.CompositeSubscription
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -91,13 +93,17 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
recycler.addOnScrollListener(object : RecyclerView.OnScrollListener() { recycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recycler: RecyclerView, newState: Int) { override fun onScrollStateChanged(recycler: RecyclerView, newState: Int) {
// Disable swipe refresh when view is not at the top // Disable swipe refresh when view is not at the top
val firstPos = (recycler.layoutManager as androidx.recyclerview.widget.LinearLayoutManager) val firstPos = (recycler.layoutManager as LinearLayoutManager)
.findFirstCompletelyVisibleItemPosition() .findFirstCompletelyVisibleItemPosition()
swipe_refresh.isEnabled = firstPos <= 0 swipe_refresh.isEnabled = firstPos <= 0
} }
}) })
recycler.doOnApplyWindowInsets { v, insets, padding -> recycler.doOnApplyWindowInsets { v, insets, padding ->
v.updatePaddingRelative(bottom = padding.bottom + insets.systemWindowInsetBottom) v.updatePaddingRelative(bottom = padding.bottom + insets.systemWindowInsetBottom)
fast_scroller?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = insets.systemWindowInsetBottom
}
} }
// Double the distance required to trigger sync // Double the distance required to trigger sync

View File

@ -24,7 +24,6 @@ import kotlinx.android.synthetic.main.migration_bottom_sheet.extra_search_param_
import kotlinx.android.synthetic.main.migration_bottom_sheet.mig_categories import kotlinx.android.synthetic.main.migration_bottom_sheet.mig_categories
import kotlinx.android.synthetic.main.migration_bottom_sheet.mig_chapters import kotlinx.android.synthetic.main.migration_bottom_sheet.mig_chapters
import kotlinx.android.synthetic.main.migration_bottom_sheet.mig_tracking import kotlinx.android.synthetic.main.migration_bottom_sheet.mig_tracking
import kotlinx.android.synthetic.main.migration_bottom_sheet.use_smart_search
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
class MigrationBottomSheetDialog(activity: Activity, theme: Int, private val listener: class MigrationBottomSheetDialog(activity: Activity, theme: Int, private val listener:
@ -59,7 +58,7 @@ StartMigrationListener) :
fab.setOnClickListener { fab.setOnClickListener {
preferences.skipPreMigration().set(skip_step.isChecked) preferences.skipPreMigration().set(skip_step.isChecked)
listener.startMigration( listener.startMigration(
if (use_smart_search.isChecked && extra_search_param_text.text.isNotBlank()) if (extra_search_param.isChecked && extra_search_param_text.text.isNotBlank())
extra_search_param_text.text.toString() else null) extra_search_param_text.text.toString() else null)
dismiss() dismiss()
} }
@ -79,7 +78,6 @@ StartMigrationListener) :
mig_categories.setOnCheckedChangeListener { _, _ -> setFlags() } mig_categories.setOnCheckedChangeListener { _, _ -> setFlags() }
mig_tracking.setOnCheckedChangeListener { _, _ -> setFlags() } mig_tracking.setOnCheckedChangeListener { _, _ -> setFlags() }
use_smart_search.bindToPreference(preferences.smartMigration())
extra_search_param_text.gone() extra_search_param_text.gone()
extra_search_param.setOnCheckedChangeListener { _, isChecked -> extra_search_param.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) { if (isChecked) {

View File

@ -122,7 +122,6 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
suspend fun runMigrations(mangas: List<MigratingManga>) { suspend fun runMigrations(mangas: List<MigratingManga>) {
val useSourceWithMost = preferences.useSourceWithMost().getOrDefault() val useSourceWithMost = preferences.useSourceWithMost().getOrDefault()
val useSmartSearch = preferences.smartMigration().getOrDefault()
val sources = preferences.migrationSources().getOrDefault().split("/").mapNotNull { val sources = preferences.migrationSources().getOrDefault().split("/").mapNotNull {
val value = it.toLongOrNull() ?: return val value = it.toLongOrNull() ?: return
@ -152,11 +151,10 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
async { async {
sourceSemaphore.withPermit { sourceSemaphore.withPermit {
try { try {
val searchResult = if (useSmartSearch) { /* val searchResult = if (useSmartSearch) {
smartSearchEngine.smartSearch(source, mangaObj.title) smartSearchEngine.smartSearch(source, mangaObj.title)
} else { } else {*/
smartSearchEngine.normalSearch(source, mangaObj.title) val searchResult = smartSearchEngine.normalSearch(source, mangaObj.title)
}
if(searchResult != null) { if(searchResult != null) {
val localManga = smartSearchEngine.networkToLocalManga(searchResult, source.id) val localManga = smartSearchEngine.networkToLocalManga(searchResult, source.id)
@ -185,11 +183,8 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle),
} else { } else {
validSources.forEachIndexed { index, source -> validSources.forEachIndexed { index, source ->
val searchResult = try { val searchResult = try {
val searchResult = if (useSmartSearch) { val searchResult = smartSearchEngine.normalSearch(source,
smartSearchEngine.smartSearch(source, mangaObj.title) mangaObj.title)
} else {
smartSearchEngine.normalSearch(source, mangaObj.title)
}
if (searchResult != null) { if (searchResult != null) {
val localManga = smartSearchEngine.networkToLocalManga(searchResult, source.id) val localManga = smartSearchEngine.networkToLocalManga(searchResult, source.id)

View File

@ -101,26 +101,15 @@
android:text="@string/use_most_chapters" /> android:text="@string/use_most_chapters" />
</RadioGroup> </RadioGroup>
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/use_smart_search"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginTop="16dp"
android:text="@string/use_intelligent_search"
app:layout_constraintEnd_toEndOf="@+id/sourceGroup"
app:layout_constraintStart_toStartOf="@+id/sourceGroup"
app:layout_constraintTop_toBottomOf="@+id/sourceGroup" />
<androidx.appcompat.widget.SwitchCompat <androidx.appcompat.widget.SwitchCompat
android:id="@+id/extra_search_param" android:id="@+id/extra_search_param"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="16dp"
android:text="@string/include_extra_search_parameter" android:text="@string/include_extra_search_parameter"
app:layout_constraintEnd_toEndOf="@+id/use_smart_search" app:layout_constraintEnd_toEndOf="@+id/sourceGroup"
app:layout_constraintStart_toStartOf="@+id/use_smart_search" app:layout_constraintStart_toStartOf="@+id/sourceGroup"
app:layout_constraintTop_toBottomOf="@+id/use_smart_search" /> app:layout_constraintTop_toBottomOf="@+id/sourceGroup" />
<EditText <EditText
android:id="@+id/extra_search_param_text" android:id="@+id/extra_search_param_text"