Refactoring Library and Filter Bottom Sheet

Library controller is no longer rx
Library presenter is no longer rx
This commit is contained in:
Jay 2020-02-08 18:59:51 -08:00
parent 05cb2c0b6b
commit d4153a9f41
11 changed files with 166 additions and 411 deletions

View File

@ -27,8 +27,6 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.snackbar.BaseTransientBottomBar
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.tabs.TabLayout
import com.jakewharton.rxbinding.support.v4.view.pageSelections
import com.jakewharton.rxbinding.support.v7.widget.queryTextChanges
import com.jakewharton.rxrelay.BehaviorRelay
import com.jakewharton.rxrelay.PublishRelay
import eu.kanade.tachiyomi.R
@ -41,13 +39,13 @@ import eu.kanade.tachiyomi.data.library.LibraryServiceListener
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.ui.base.controller.BaseController
import eu.kanade.tachiyomi.ui.base.controller.SecondaryDrawerController
import eu.kanade.tachiyomi.ui.base.controller.TabbedController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.ui.category.CategoryController
import eu.kanade.tachiyomi.ui.download.DownloadController
import eu.kanade.tachiyomi.ui.library.filter.FilterBottomSheet
import eu.kanade.tachiyomi.ui.library.filter.SortFilterBottomSheet
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.ui.migration.MigrationController
@ -75,7 +73,7 @@ import uy.kohesive.injekt.api.get
class LibraryController(
bundle: Bundle? = null,
private val preferences: PreferencesHelper = Injekt.get()
) : NucleusController<LibraryPresenter>(bundle),
) : BaseController(bundle),
TabbedController,
SecondaryDrawerController,
ActionMode.Callback,
@ -154,18 +152,16 @@ class LibraryController(
/**
* Drawer listener to allow swipe only for closing the drawer.
*/
private var drawerListener: DrawerLayout.DrawerListener? = null
private var tabsVisibilityRelay: BehaviorRelay<Boolean> = BehaviorRelay.create(false)
private var tabsVisibilitySubscription: Subscription? = null
private var searchViewSubscription: Subscription? = null
var snack: Snackbar? = null
private var reorderMenuItem:MenuItem? = null
private var presenter = LibraryPresenter(this)
init {
setHasOptionsMenu(true)
retainViewMode = RetainViewMode.RETAIN_DETACH
@ -174,11 +170,6 @@ class LibraryController(
override fun getTitle(): String? {
return resources?.getString(R.string.label_library)
}
override fun createPresenter(): LibraryPresenter {
return LibraryPresenter()
}
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.library_controller, container, false)
}
@ -188,10 +179,20 @@ class LibraryController(
adapter = LibraryAdapter(this)
library_pager.adapter = adapter
library_pager.pageSelections().skip(1).subscribeUntilDestroy {
preferences.lastUsedCategory().set(it)
activeCategory = it
}
library_pager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageSelected(position: Int) {
preferences.lastUsedCategory().set(position)
activeCategory = position
}
override fun onPageScrollStateChanged(state: Int) { }
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) { }
})
library_pager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageSelected(position: Int) {
@ -209,11 +210,7 @@ class LibraryController(
override fun onPageScrollStateChanged(state: Int) { }
})
getColumnsPreferenceForCurrentOrientation().asObservable()
.doOnNext { mangaPerRow = it }
.skip(1)
// Set again the adapter to recalculate the covers height
.subscribeUntilDestroy { reattachAdapter() }
mangaPerRow = getColumnsPreferenceForCurrentOrientation().getOrDefault()
if (selectedMangas.isNotEmpty()) {
createActionModeIfNeeded()
@ -224,14 +221,14 @@ class LibraryController(
bottom_sheet.onGroupClicked = {
when (it) {
FilterBottomSheet.ACTION_REFRESH -> onRefresh()
FilterBottomSheet.ACTION_FILTER -> onFilterChanged()
FilterBottomSheet.ACTION_SORT -> onSortChanged()
FilterBottomSheet.ACTION_DISPLAY -> reattachAdapter()
FilterBottomSheet.ACTION_DOWNLOAD_BADGE ->
SortFilterBottomSheet.ACTION_REFRESH -> onRefresh()
SortFilterBottomSheet.ACTION_FILTER -> onFilterChanged()
SortFilterBottomSheet.ACTION_SORT -> onSortChanged()
SortFilterBottomSheet.ACTION_DISPLAY -> reattachAdapter()
SortFilterBottomSheet.ACTION_DOWNLOAD_BADGE ->
presenter.requestDownloadBadgesUpdate()
FilterBottomSheet.ACTION_UNREAD_BADGE -> presenter.requestUnreadBadgesUpdate()
FilterBottomSheet.ACTION_CAT_SORT -> onCatSortChanged()
SortFilterBottomSheet.ACTION_UNREAD_BADGE -> presenter.requestUnreadBadgesUpdate()
SortFilterBottomSheet.ACTION_CAT_SORT -> onCatSortChanged()
}
}
@ -528,15 +525,19 @@ class LibraryController(
// Mutate the filter icon because it needs to be tinted and the resource is shared.
menu.findItem(R.id.action_library_filter).icon.mutate()
searchViewSubscription?.unsubscribe()
searchViewSubscription = searchView.queryTextChanges()
// Ignore events if this controller isn't at the top
.filter { router.backstack.lastOrNull()?.controller() == this }
.subscribeUntilDestroy {
query = it.toString()
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextChange(newText: String?): Boolean {
if (router.backstack.lastOrNull()?.controller() == this@LibraryController) {
query = newText ?: ""
searchRelay.call(query)
}
return true
}
override fun onQueryTextSubmit(query: String?): Boolean {
return true
}
})
searchItem.fixExpand(onExpand = { invalidateMenuOnExpand() })
}
@ -712,9 +713,6 @@ class LibraryController(
}
fun openManga(manga: Manga, startY: Float?) {
// Notify the presenter a manga is being opened.
presenter.onOpenManga()
router.pushController(MangaController(manga, startY).withFadeTransaction())
}

View File

@ -55,12 +55,13 @@ private typealias LibraryMap = Map<Int, List<LibraryItem>>
* Presenter of [LibraryController].
*/
class LibraryPresenter(
private val view: LibraryController,
private val db: DatabaseHelper = Injekt.get(),
private val preferences: PreferencesHelper = Injekt.get(),
private val coverCache: CoverCache = Injekt.get(),
private val sourceManager: SourceManager = Injekt.get(),
private val downloadManager: DownloadManager = Injekt.get()
) : BasePresenter<LibraryController>() {
) {
private val context = preferences.context
@ -80,33 +81,6 @@ class LibraryPresenter(
private var currentMangaMap:LibraryMap? = null
override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState)
getLibrary()
}
/**
* Subscribes to library if needed.
*/
/* fun subscribeLibrary() {
if (librarySubscription.isNullOrUnsubscribed()) {
librarySubscription = getLibraryObservable()
.combineLatest(downloadTriggerRelay.observeOn(Schedulers.io())) {
lib, _ -> lib.apply { setDownloadCount(mangaMap) }
}
.combineLatest(filterTriggerRelay.observeOn(Schedulers.io())) {
lib, _ -> lib.copy(mangaMap = applyFilters(lib.mangaMap))
}
.combineLatest(sortTriggerRelay.observeOn(Schedulers.io())) {
lib, _ -> lib.copy(mangaMap = applySort(lib.mangaMap))
}
.observeOn(AndroidSchedulers.mainThread())
.subscribeLatestCache({ view, (categories, mangaMap) ->
view.onNextLibraryUpdate(categories, mangaMap)
})
}
}*/
fun getLibrary() {
launchUI {
val mangaMap = withContext(Dispatchers.IO) {
@ -119,7 +93,7 @@ class LibraryPresenter(
mangaMap
}
currentMangaMap = mangaMap
view?.onNextLibraryUpdate(categories, mangaMap)
view.onNextLibraryUpdate(categories, mangaMap)
}
}
@ -428,25 +402,6 @@ class LibraryPresenter(
return Library(this.categories, libraryMap)
}
/**
* Get the categories and all its manga from the database.
*
* @return an observable of the categories and its manga.
*/
/*private fun getLibraryObservable(): Observable<Library> {
return Observable.combineLatest(getCategoriesObservable(), getLibraryMangasObservable()) { dbCategories, libraryManga ->
val categories = if (libraryManga.containsKey(0))
arrayListOf(createDefaultCategory()) + dbCategories
else dbCategories
this.allCategories = categories
this.categories = if (preferences.hideCategories().getOrDefault())
arrayListOf(createDefaultCategory())
else categories
Library(this.categories, libraryManga)
}
}*/
private fun createDefaultCategory(): Category {
val default = Category.createDefault(context)
val defOrder = preferences.defaultMangaOrder().getOrDefault()
@ -454,36 +409,7 @@ class LibraryPresenter(
else default.mangaOrder = defOrder.split("/").mapNotNull { it.toLongOrNull() }
return default
}
/*
/**
* Get the categories from the database.
*
* @return an observable of the categories.
*/
private fun getCategoriesObservable(): Observable<List<Category>> {
return db.getCategories().asRxObservable()
}
/**
* Get the manga grouped by categories.
*
* @return an observable containing a map with the category id as key and a list of manga as the
* value.
*/
private fun getLibraryMangasObservable(): Observable<LibraryMap> {
val libraryAsList = preferences.libraryAsList()
return db.getLibraryMangas().asRxObservable()
.map { list ->
if (!preferences.hideCategories().getOrDefault()) {
list.map { LibraryItem(it, libraryAsList) }.groupBy { it.manga.category }
}
else {
list.distinctBy { it.id }.map { LibraryItem(it, libraryAsList)}.groupBy {
0 }
}
}
}
*/
/**
* Requests the library to be filtered.
*/
@ -493,7 +419,7 @@ class LibraryPresenter(
mangaMap = withContext(Dispatchers.IO) { applyFilters(mangaMap) }
mangaMap = withContext(Dispatchers.IO) { applySort(mangaMap) }
currentMangaMap = mangaMap
view?.onNextLibraryUpdate(categories, mangaMap)
view.onNextLibraryUpdate(categories, mangaMap)
}
}
@ -501,7 +427,6 @@ class LibraryPresenter(
* Requests the library to have download badges added/removed.
*/
fun requestDownloadBadgesUpdate() {
//getLibrary()
launchUI {
val mangaMap = rawMangaMap ?: return@launchUI
withContext(Dispatchers.IO) { setDownloadCount(mangaMap) }
@ -509,7 +434,7 @@ class LibraryPresenter(
val current = currentMangaMap ?: return@launchUI
withContext(Dispatchers.IO) { setDownloadCount(current) }
currentMangaMap = current
view?.onNextLibraryUpdate(categories, current)
view.onNextLibraryUpdate(categories, current)
}
}
@ -525,7 +450,7 @@ class LibraryPresenter(
val current = currentMangaMap ?: return@launchUI
withContext(Dispatchers.IO) { setUnreadBadge(current) }
currentMangaMap = current
view?.onNextLibraryUpdate(categories, current)
view.onNextLibraryUpdate(categories, current)
}
}
@ -537,7 +462,7 @@ class LibraryPresenter(
var mangaMap = currentMangaMap ?: return@launchUI
mangaMap = withContext(Dispatchers.IO) { applySort(mangaMap) }
currentMangaMap = mangaMap
view?.onNextLibraryUpdate(categories, mangaMap)
view.onNextLibraryUpdate(categories, mangaMap)
}
}
@ -546,23 +471,14 @@ class LibraryPresenter(
var mangaMap = currentMangaMap ?: return@launchUI
mangaMap = withContext(Dispatchers.IO) { applyCatSort(mangaMap, catId) }
currentMangaMap = mangaMap
view?.onNextLibraryUpdate(categories, mangaMap)
view.onNextLibraryUpdate(categories, mangaMap)
}
}
fun requestFullUpdate() {
//librarySubscription?.unsubscribe()
getLibrary()
}
/**
* Called when a manga is opened.
*/
fun onOpenManga() {
// Avoid further db updates for the library when it's not needed
//librarySubscription?.let { remove(it) }
}
/**
* Returns the common categories for the given list of manga.
*

View File

@ -1,168 +0,0 @@
package eu.kanade.tachiyomi.ui.library.filter
import android.app.Activity
import android.content.res.Configuration
import android.graphics.Color
import android.graphics.drawable.GradientDrawable
import android.os.Build
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.CompoundButton
import android.widget.LinearLayout
import android.widget.RadioButton
import android.widget.RadioGroup
import android.widget.Toast
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.graphics.ColorUtils
import com.bluelinelabs.conductor.Controller
import com.f2prateek.rx.preferences.Preference
import com.google.android.material.bottomsheet.BottomSheetDialog
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.ui.migration.MigrationFlags
import eu.kanade.tachiyomi.util.view.gone
import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.marginBottom
import eu.kanade.tachiyomi.util.view.updateLayoutParams
import eu.kanade.tachiyomi.util.view.visible
import kotlinx.android.synthetic.main.migration_bottom_sheet.*
import kotlinx.android.synthetic.main.migration_bottom_sheet.extra_search_param
import kotlinx.android.synthetic.main.migration_bottom_sheet.extra_search_param_text
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_tracking
import uy.kohesive.injekt.injectLazy
class SortBottomSheet(private val activity: Activity, theme: Int, private val listener:
SortBottomSheetListener) :
BottomSheetDialog(activity,
theme) {
/**
* Preferences helper.
*/
private val preferences by injectLazy<PreferencesHelper>()
init {
// Use activity theme for this layout
val view = activity.layoutInflater.inflate(R.layout.migration_bottom_sheet, null)
//val scroll = NestedScrollView(context)
// scroll.addView(view)
setContentView(view)
if (activity.resources.configuration?.orientation == Configuration.ORIENTATION_LANDSCAPE)
sourceGroup.orientation = LinearLayout.HORIZONTAL
window?.setBackgroundDrawable(null)
val currentNightMode = activity.resources.configuration.uiMode and Configuration
.UI_MODE_NIGHT_MASK
if (currentNightMode == Configuration.UI_MODE_NIGHT_NO)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
window?.decorView?.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val nView = View(context)
val height = activity.window.decorView.rootWindowInsets.systemWindowInsetBottom
val params = ConstraintLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, height
)
params.bottomToBottom = constraintLayout.id
params.startToStart = constraintLayout.id
params.endToEnd = constraintLayout.id
nView.layoutParams = params
nView.background = GradientDrawable(
GradientDrawable.Orientation.BOTTOM_TOP, intArrayOf(
ColorUtils.setAlphaComponent(Color.BLACK, 179), Color.TRANSPARENT
)
)
constraintLayout.addView(nView)
}
}
/**
* Called when the sheet is created. It initializes the listeners and values of the preferences.
*/
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
initPreferences()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
window?.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
val marginB = skip_step.marginBottom
skip_step.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = marginB +
activity.window.decorView.rootWindowInsets.systemWindowInsetBottom
}
}
}
/**
* Init general reader preferences.
*/
private fun initPreferences() {
val flags = preferences.migrateFlags().getOrDefault()
mig_chapters.isChecked = MigrationFlags.hasChapters(flags)
mig_categories.isChecked = MigrationFlags.hasCategories(flags)
mig_tracking.isChecked = MigrationFlags.hasTracks(flags)
mig_chapters.setOnCheckedChangeListener { _, _ -> setFlags() }
mig_categories.setOnCheckedChangeListener { _, _ -> setFlags() }
mig_tracking.setOnCheckedChangeListener { _, _ -> setFlags() }
extra_search_param_text.gone()
extra_search_param.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
extra_search_param_text.visible()
} else {
extra_search_param_text.gone()
}
}
sourceGroup.bindToPreference(preferences.useSourceWithMost())
skip_step.isChecked = preferences.skipPreMigration().getOrDefault()
skip_step.setOnCheckedChangeListener { _, isChecked ->
if (isChecked)
(listener as? Controller)?.activity?.toast(R.string.pre_migration_skip_toast,
Toast.LENGTH_LONG)
}
}
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_tracking.isChecked) flags = flags or MigrationFlags.TRACK
preferences.migrateFlags().set(flags)
}
/**
* Binds a checkbox or switch view with a boolean preference.
*/
private fun CompoundButton.bindToPreference(pref: Preference<Boolean>) {
isChecked = pref.getOrDefault()
setOnCheckedChangeListener { _, isChecked -> pref.set(isChecked) }
}
/**
* Binds a radio group with a boolean preference.
*/
private fun RadioGroup.bindToPreference(pref: Preference<Boolean>) {
(getChildAt(pref.getOrDefault().toInt()) as RadioButton).isChecked = true
setOnCheckedChangeListener { _, value ->
val index = indexOfChild(findViewById(value))
pref.set(index == 1)
}
}
private fun Boolean.toInt() = if (this) 1 else 0
}
interface SortBottomSheetListener {
fun onApplySort()
}

View File

@ -44,7 +44,7 @@ import uy.kohesive.injekt.injectLazy
import kotlin.math.min
import kotlin.math.roundToInt
class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
class SortFilterBottomSheet @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
: LinearLayout(context, attrs),
FilterTagGroupListener {
@ -88,8 +88,8 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
fun onCreate(pagerView:View) {
if (isLandscape() || isTablet()) {
sideLayout.orientation = HORIZONTAL
sortingLayout.updateLayoutParams<MarginLayoutParams> {
side_layout.orientation = HORIZONTAL
sorting_layout.updateLayoutParams<MarginLayoutParams> {
bottomMargin = 0
topMargin = 0
}
@ -98,10 +98,10 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
top = 0
)
}
clearButton = pendingClearButton
filterLayout.removeView(clearButton)
clearButton = clear_button
filter_layout.removeView(clearButton)
sheetBehavior = BottomSheetBehavior.from(this)
topbar.setOnClickListener {
top_bar.setOnClickListener {
if (sheetBehavior?.state != BottomSheetBehavior.STATE_EXPANDED) {
sheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED
//topbar.animate().alpha(0f).setDuration(100).start()
@ -117,7 +117,7 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
val coordLayout:View = (pagerView.parent as ViewGroup).findViewById(R.id.snackbar_layout)
sheetBehavior?.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(bottomSheet: View, progress: Float) {
topbar.alpha = 1 - progress
top_bar.alpha = 1 - progress
shadow2.alpha = (1 - progress) * 0.25f
updateRootPadding(progress)
}
@ -126,12 +126,12 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
if (state == BottomSheetBehavior.STATE_COLLAPSED) reSortViews()
else setMainSortText()
if (state == BottomSheetBehavior.STATE_EXPANDED)
topbar.alpha = 0f
topbar.isClickable = state == BottomSheetBehavior.STATE_COLLAPSED
topbar.isFocusable = state == BottomSheetBehavior.STATE_COLLAPSED
top_bar.alpha = 0f
top_bar.isClickable = state == BottomSheetBehavior.STATE_COLLAPSED
top_bar.isFocusable = state == BottomSheetBehavior.STATE_COLLAPSED
}
})
topbar.viewTreeObserver.addOnGlobalLayoutListener {
top_bar.viewTreeObserver.addOnGlobalLayoutListener {
val phoneLandscape = (isLandscape() && !isTablet())
sheetBehavior?.peekHeight = if (phoneLandscape) {
if (shadow2.visibility != View.GONE) {
@ -140,15 +140,15 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
}
0
}
else if (!sortText.text.isNullOrBlank()) {
topbar.height
else if (!title.text.isNullOrBlank()) {
top_bar.height
}
else 0
if (sheetBehavior?.state == BottomSheetBehavior.STATE_COLLAPSED) {
val height = context.resources.getDimensionPixelSize(R.dimen.rounder_radius)
pager?.setPadding(0, 0, 0, if (phoneLandscape) 0 else
(topbar.height - height))
coordLayout.setPadding(0, 0, 0, topbar.height)
(top_bar.height - height))
coordLayout.setPadding(0, 0, 0, top_bar.height)
}
else {
updateRootPadding()
@ -156,11 +156,11 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
}
createTags()
mainSortTextView.setOnClickListener { showMainSortOptions() }
catSortTextView.setOnClickListener { showCatSortOptions() }
library_sort_text.setOnClickListener { showMainSortOptions() }
category_sort_text.setOnClickListener { showCatSortOptions() }
clearButton.setOnClickListener { clearFilters() }
downloadCheckbox.isChecked = preferences.downloadBadge().getOrDefault()
downloadCheckbox.setOnCheckedChangeListener { _, isChecked ->
download_checkbox.isChecked = preferences.downloadBadge().getOrDefault()
download_checkbox.setOnCheckedChangeListener { _, isChecked ->
preferences.downloadBadge().set(isChecked)
onGroupClicked(ACTION_DOWNLOAD_BADGE)
}
@ -169,7 +169,7 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
showUnreadMenu()
}
displayGroup.bindToPreference(preferences.libraryAsList())
display_group.bindToPreference(preferences.libraryAsList())
}
private fun isLandscape(): Boolean {
@ -212,17 +212,17 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
filters.joinToString(", ") { context.getString(it) }
}
}
sortText.text = text
title.text = text
setMainSortText()
}
}
fun adjustTitleMargin(downloading: Boolean) {
val params = sortText.layoutParams as? MarginLayoutParams ?: return
val params = title.layoutParams as? MarginLayoutParams ?: return
params.rightMargin = (if (downloading) 80 else 8).dpToPx
sortText.layoutParams = params
title.layoutParams = params
filterScrollView.updatePaddingRelative(end = (if (downloading) 80 else 20).dpToPx)
filter_scroll.updatePaddingRelative(end = (if (downloading) 80 else 20).dpToPx)
}
fun updateRootPadding(progress: Float? = null) {
@ -309,7 +309,7 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
tracked.setup(this, R.string.action_filter_tracked, R.string.action_filter_not_tracked)
filterItems.forEach {
filterLayout.addView(it)
filter_layout.addView(it)
}
checkForManwha()
@ -323,12 +323,12 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
launchUI {
val mangaType = inflate(R.layout.filter_buttons) as FilterTagGroup
mangaType.setup(
this@FilterBottomSheet,
this@SortFilterBottomSheet,
R.string.manga,
R.string.manwha
)
this@FilterBottomSheet.mangaType = mangaType
filterLayout.addView(mangaType)
this@SortFilterBottomSheet.mangaType = mangaType
filter_layout.addView(mangaType)
filterItems.add(mangaType)
}
}
@ -347,7 +347,7 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
private fun showMainSortOptions() {
// Create a PopupMenu, giving it the clicked view for an anchor
val popup = PopupMenu(context, mainSortTextView)
val popup = PopupMenu(context, library_sort_text)
// Inflate our menu resource into the PopupMenu's Menu
popup.menuInflater.inflate(R.menu.main_sort, popup.menu)
@ -390,7 +390,7 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
private fun showCatSortOptions() {
val category = lastCategory ?: return
// Create a PopupMenu, giving it the clicked view for an anchor
val popup = PopupMenu(context, catSortTextView)
val popup = PopupMenu(context, category_sort_text)
// Inflate our menu resource into the PopupMenu's Menu
popup.menuInflater.inflate(R.menu.cat_sort, popup.menu)
@ -504,7 +504,7 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
}
)
}
mainSortTextView.text = withContext(Dispatchers.IO) {
library_sort_text.text = withContext(Dispatchers.IO) {
context.getString(
if (sortId == LibrarySort.DRAG_AND_DROP) R.string.sort_library_by_
else R.string.sort_by_, context.getString(
@ -519,7 +519,7 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
)
)
}
mainSortTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(
library_sort_text.setCompoundDrawablesRelativeWithIntrinsicBounds(
drawableL, null, null, null
)
setCatSortText()
@ -540,7 +540,7 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
}
)
}
catSortTextView.text = withContext(Dispatchers.IO) {
category_sort_text.text = withContext(Dispatchers.IO) {
context.getString(
R.string.sort_category_by_, context.getString(
when (sortId) {
@ -554,11 +554,11 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
)
)
}
catSortTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(
category_sort_text.setCompoundDrawablesRelativeWithIntrinsicBounds(
drawableL, null, null, null
)
if (catSortTextView.visibility != View.VISIBLE) catSortTextView.visible()
} else if (catSortTextView.visibility == View.VISIBLE) catSortTextView.gone()
if (category_sort_text.visibility != View.VISIBLE) category_sort_text.visible()
} else if (category_sort_text.visibility == View.VISIBLE) category_sort_text.gone()
}
}
@ -603,9 +603,9 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
}
val filters = getFilters().size
if (filters > 0 && clearButton.parent == null)
filterLayout.addView(clearButton, 0)
filter_layout.addView(clearButton, 0)
else if (filters == 0 && clearButton.parent != null)
filterLayout.removeView(clearButton)
filter_layout.removeView(clearButton)
}
private fun clearFilters() {
@ -621,7 +621,7 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
val transition = androidx.transition.AutoTransition()
transition.duration = 150
androidx.transition.TransitionManager.beginDelayedTransition(filterLayout, transition)
androidx.transition.TransitionManager.beginDelayedTransition(filter_layout, transition)
filterItems.forEach {
it.reset()
}
@ -630,16 +630,16 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
}
fun reSortViews() {
filterLayout.removeAllViews()
filter_layout.removeAllViews()
if (filterItems.any { it.isActivated })
filterLayout.addView(clearButton)
filter_layout.addView(clearButton)
filterItems.filter { it.isActivated }.forEach {
filterLayout.addView(it)
filter_layout.addView(it)
}
filterItems.filterNot { it.isActivated }.forEach {
filterLayout.addView(it)
filter_layout.addView(it)
}
filterScrollView.scrollTo(0, 0)
filter_scroll.scrollTo(0, 0)
}
private fun showUnreadMenu() {

View File

@ -111,13 +111,15 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
lateinit var tabAnimator: TabsAnimator
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Create a webview before extensions do or else they will break night mode theme
// https://stackoverflow.com/questions/54191883
Timber.d("Manually instantiating WebView to avoid night mode issue.")
try {
WebView(applicationContext)
} catch (e: Exception) {
Timber.e(e, "Exception when creating webview at start")
}
super.onCreate(savedInstanceState)
if (trulyGoBack) return
// Do not let the launcher create a new activity http://stackoverflow.com/questions/16283079
@ -480,7 +482,7 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
} else if (!bottomNav && backstackSize == 1 && router.getControllerWithTag
("$startScreenId") == null) {
setSelectedDrawerItem(startScreenId)
} else if (!router.handleBack()) {
} else if (!router.handleBack()) {
unlocked = false
super.onBackPressed()
}
@ -488,7 +490,10 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
private fun setSelectedDrawerItem(itemId: Int) {
if (!isFinishing) {
if (bottomNav) navigationView.selectedItemId = itemId
if (bottomNav) {
if (itemId == R.id.nav_drawer_library || itemId == R.id.nav_drawer_settings)
navigationView.selectedItemId = itemId
}
else nav_view.setCheckedItem(itemId)
jumpToController(itemId)
}
@ -499,21 +504,17 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
val currentRoot = router.backstack.firstOrNull()
if (currentRoot?.tag()?.toIntOrNull() != id) {
when (id) {
R.id.nav_drawer_library -> setRoot(LibraryController(), id)
R.id.nav_drawer_library -> if (!bottomNav) setRoot(LibraryController(), id)
R.id.nav_drawer_recent_updates -> {
if (bottomNav)
navigationView.selectedItemId = R.id.nav_drawer_recents
setRoot(RecentChaptersController(), if (bottomNav) R.id.nav_drawer_recents
else id)
preferences.showRecentUpdates().set(true)
if (bottomNav) navigationView.selectedItemId = R.id.nav_drawer_recents
else setRoot(RecentChaptersController(), id)
updateRecentsIcon()
}
R.id.nav_drawer_recently_read -> {
if (bottomNav)
navigationView.selectedItemId = R.id.nav_drawer_recents
setRoot(RecentlyReadController(), if (bottomNav) R.id.nav_drawer_recents
else id)
preferences.showRecentUpdates().set(false)
if (bottomNav) navigationView.selectedItemId = R.id.nav_drawer_recents
else setRoot(RecentlyReadController(), id)
updateRecentsIcon()
}
R.id.nav_drawer_catalogues -> setRoot(CatalogueController(), id)
@ -549,7 +550,8 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
}
R.id.nav_drawer_settings -> {
setRoot(SettingsMainController(), id)
if (!bottomNav)
setRoot(SettingsMainController(), id)
}
}
}

View File

@ -131,7 +131,7 @@ class RecentlyReadController(bundle: Bundle? = null) : BaseController(bundle),
if (size > 0) {
empty_view?.hide()
} else {
empty_view.show(R.drawable.ic_glasses_black_128dp, R.string.information_no_recent_manga)
empty_view.show(R.drawable.ic_history_white_128dp, R.string.information_no_recent_manga)
}
}

View File

@ -1,5 +1,6 @@
package eu.kanade.tachiyomi.ui.setting
import androidx.appcompat.app.AppCompatDelegate
import androidx.biometric.BiometricManager
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.BuildConfig

View File

@ -0,0 +1,6 @@
<vector android:height="128dp"
android:tint="?attr/actionBarTintColor"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="128dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M13,3c-4.97,0 -9,4.03 -9,9L1,12l3.89,3.89 0.07,0.14L9,12L6,12c0,-3.87 3.13,-7 7,-7s7,3.13 7,7 -3.13,7 -7,7c-1.93,0 -3.68,-0.79 -4.94,-2.06l-1.42,1.42C8.27,19.99 10.51,21 13,21c4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9zM12,8v5l4.28,2.54 0.72,-1.21 -3.5,-2.08L13.5,8L12,8z"/>
</vector>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<eu.kanade.tachiyomi.ui.library.filter.FilterBottomSheet xmlns:android="http://schemas.android.com/apk/res/android"
<eu.kanade.tachiyomi.ui.library.filter.SortFilterBottomSheet xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/bottom_sheet"
style="@style/BottomSheetDialogTheme"
@ -24,7 +24,7 @@
android:orientation="vertical">
<HorizontalScrollView
android:id="@+id/filterScrollView"
android:id="@+id/filter_scroll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
@ -35,14 +35,14 @@
android:scrollbars="none">
<LinearLayout
android:id="@+id/filterLayout"
android:id="@+id/filter_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/pendingClearButton"
android:id="@+id/clear_button"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginStart="10dp"
@ -69,7 +69,7 @@
android:scrollbars="none">
<LinearLayout
android:id="@+id/sideLayout"
android:id="@+id/side_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:baselineAligned="true"
@ -77,7 +77,7 @@
android:orientation="horizontal">
<LinearLayout
android:id="@+id/sortingLayout"
android:id="@+id/sorting_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
@ -87,7 +87,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/mainSortTextView"
android:id="@+id/library_sort_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
@ -104,7 +104,7 @@
android:textStyle="normal" />
<TextView
android:id="@+id/catSortTextView"
android:id="@+id/category_sort_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/square_ripple"
@ -123,7 +123,7 @@
</LinearLayout>
<LinearLayout
android:id="@+id/displayLayout"
android:id="@+id/display_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="7dp"
@ -146,7 +146,7 @@
<RadioGroup
android:id="@+id/displayGroup"
android:id="@+id/display_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
@ -175,7 +175,7 @@
>
<CheckBox
android:id="@+id/downloadCheckbox"
android:id="@+id/download_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
@ -204,7 +204,7 @@
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/topbar"
android:id="@+id/top_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_bottom_sheet_primary"
@ -214,17 +214,17 @@
<ImageView
android:id="@+id/imageView2"
android:id="@+id/title_icon"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginStart="24dp"
android:src="@drawable/ic_sort_white_24dp"
app:layout_constraintBottom_toBottomOf="@+id/sortText"
app:layout_constraintBottom_toBottomOf="@+id/title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/sortText" />
app:layout_constraintTop_toTopOf="@+id/title" />
<TextView
android:id="@+id/sortText"
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
@ -236,8 +236,8 @@
android:textColor="?attr/actionBarTintColor"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView2"
app:layout_constraintStart_toEndOf="@+id/title_icon"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</eu.kanade.tachiyomi.ui.library.filter.FilterBottomSheet>
</eu.kanade.tachiyomi.ui.library.filter.SortFilterBottomSheet>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<eu.kanade.tachiyomi.ui.library.filter.FilterBottomSheet xmlns:android="http://schemas.android.com/apk/res/android"
<eu.kanade.tachiyomi.ui.library.filter.SortFilterBottomSheet xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/bottom_sheet"
style="@style/BottomSheetDialogTheme"
@ -24,7 +24,7 @@
android:orientation="vertical">
<HorizontalScrollView
android:id="@+id/filterScrollView"
android:id="@+id/filter_scroll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
@ -35,14 +35,14 @@
android:scrollbars="none">
<LinearLayout
android:id="@+id/filterLayout"
android:id="@+id/filter_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/pendingClearButton"
android:id="@+id/clear_button"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginStart="10dp"
@ -69,7 +69,7 @@
android:scrollbars="none">
<LinearLayout
android:id="@+id/sideLayout"
android:id="@+id/side_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:baselineAligned="true"
@ -77,7 +77,7 @@
android:orientation="horizontal">
<LinearLayout
android:id="@+id/sortingLayout"
android:id="@+id/sorting_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
@ -87,7 +87,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/mainSortTextView"
android:id="@+id/library_sort_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
@ -104,7 +104,7 @@
android:textStyle="normal" />
<TextView
android:id="@+id/catSortTextView"
android:id="@+id/category_sort_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/square_ripple"
@ -123,7 +123,7 @@
</LinearLayout>
<LinearLayout
android:id="@+id/displayLayout"
android:id="@+id/display_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="7dp"
@ -146,7 +146,7 @@
<RadioGroup
android:id="@+id/displayGroup"
android:id="@+id/display_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
@ -175,7 +175,7 @@
>
<CheckBox
android:id="@+id/downloadCheckbox"
android:id="@+id/download_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
@ -204,7 +204,7 @@
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/topbar"
android:id="@+id/top_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_bottom_sheet_primary"
@ -214,17 +214,17 @@
<ImageView
android:id="@+id/imageView2"
android:id="@+id/title_icon"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginStart="24dp"
android:src="@drawable/ic_sort_white_24dp"
app:layout_constraintBottom_toBottomOf="@+id/sortText"
app:layout_constraintBottom_toBottomOf="@+id/title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/sortText" />
app:layout_constraintTop_toTopOf="@+id/title" />
<TextView
android:id="@+id/sortText"
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
@ -236,8 +236,8 @@
android:textColor="?attr/actionBarTintColor"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView2"
app:layout_constraintStart_toEndOf="@+id/title_icon"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</eu.kanade.tachiyomi.ui.library.filter.FilterBottomSheet>
</eu.kanade.tachiyomi.ui.library.filter.SortFilterBottomSheet>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<eu.kanade.tachiyomi.ui.library.filter.FilterBottomSheet xmlns:android="http://schemas.android.com/apk/res/android"
<eu.kanade.tachiyomi.ui.library.filter.SortFilterBottomSheet xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/bottom_sheet"
style="@style/BottomSheetDialogTheme"
@ -24,7 +24,7 @@
android:orientation="vertical">
<HorizontalScrollView
android:id="@+id/filterScrollView"
android:id="@+id/filter_scroll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
@ -35,14 +35,14 @@
android:scrollbars="none">
<LinearLayout
android:id="@+id/filterLayout"
android:id="@+id/filter_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/pendingClearButton"
android:id="@+id/clear_button"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginStart="10dp"
@ -59,7 +59,7 @@
</HorizontalScrollView>
<LinearLayout
android:id="@+id/sideLayout"
android:id="@+id/side_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
@ -70,7 +70,7 @@
android:orientation="vertical">
<LinearLayout
android:id="@+id/sortingLayout"
android:id="@+id/sorting_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
@ -80,7 +80,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/mainSortTextView"
android:id="@+id/library_sort_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
@ -98,7 +98,7 @@
android:textStyle="normal" />
<TextView
android:id="@+id/catSortTextView"
android:id="@+id/category_sort_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@drawable/square_ripple"
@ -119,7 +119,7 @@
</LinearLayout>
<LinearLayout
android:id="@+id/displayLayout"
android:id="@+id/display_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="7dp"
@ -142,7 +142,7 @@
<RadioGroup
android:id="@+id/displayGroup"
android:id="@+id/display_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
@ -171,7 +171,7 @@
>
<CheckBox
android:id="@+id/downloadCheckbox"
android:id="@+id/download_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
@ -199,7 +199,7 @@
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/topbar"
android:id="@+id/top_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_bottom_sheet_primary"
@ -209,17 +209,17 @@
<ImageView
android:id="@+id/imageView2"
android:id="@+id/title_icon"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginStart="24dp"
android:src="@drawable/ic_sort_white_24dp"
app:layout_constraintBottom_toBottomOf="@+id/sortText"
app:layout_constraintBottom_toBottomOf="@+id/title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/sortText" />
app:layout_constraintTop_toTopOf="@+id/title" />
<TextView
android:id="@+id/sortText"
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
@ -231,8 +231,8 @@
android:textColor="?attr/actionBarTintColor"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView2"
app:layout_constraintStart_toEndOf="@+id/title_icon"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</eu.kanade.tachiyomi.ui.library.filter.FilterBottomSheet>
</eu.kanade.tachiyomi.ui.library.filter.SortFilterBottomSheet>