mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-09-10 20:53:14 +02:00
Fixes to the fast scroller for this fork + remove keyword searching
This commit is contained in:
parent
d8f385cc63
commit
b668cc9abc
@ -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)
|
||||||
|
@ -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 ')',
|
||||||
|
@ -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) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,15 +67,59 @@ class LibraryCategoryAdapter(view: LibraryCategoryView) :
|
|||||||
updateDataSet(mangas.filter { it.filter(s) })
|
updateDataSet(mangas.filter { it.filter(s) })
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateBubbleText(position: Int): String {
|
override fun onCreateBubbleText(position: Int):String {
|
||||||
return if (position < scrollableHeaders.size) {
|
return if (position < scrollableHeaders.size) {
|
||||||
"Top"
|
"Top"
|
||||||
} else if (position >= itemCount - scrollableFooters.size) {
|
} else if (position >= itemCount - scrollableFooters.size) {
|
||||||
"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)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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)
|
||||||
|
@ -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"
|
||||||
|
Loading…
Reference in New Issue
Block a user