Added sorting/display options to bottom sheet

Edge to edge on the pre migration bottom sheet
This commit is contained in:
Jay 2020-02-07 03:27:57 -08:00
parent 7f1f2b7863
commit 0cc96ef585
24 changed files with 1056 additions and 411 deletions

View File

@ -1,317 +0,0 @@
package eu.kanade.tachiyomi.ui.library
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.widget.LinearLayout
import com.google.android.material.bottomsheet.BottomSheetBehavior
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.LibraryManga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.launchUI
import eu.kanade.tachiyomi.util.view.inflate
import kotlinx.android.synthetic.main.filter_bottom_sheet.view.*
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import kotlin.math.roundToInt
class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
: LinearLayout(context, attrs),
FilterTagGroupListener {
/**
* Preferences helper.
*/
private val preferences: PreferencesHelper by injectLazy()
private lateinit var downloaded:FilterTagGroup
private lateinit var unread:FilterTagGroup
private lateinit var completed:FilterTagGroup
private lateinit var tracked:FilterTagGroup
private lateinit var categories:FilterTagGroup
private var mangaType:FilterTagGroup? = null
var lastCategory:Category? = null
private val filterItems:MutableList<FilterTagGroup> by lazy {
val list = mutableListOf<FilterTagGroup>()
if (Injekt.get<DatabaseHelper>().getCategories().executeAsBlocking().isNotEmpty())
list.add(categories)
list.add(downloaded)
list.add(unread)
list.add(completed)
if (Injekt.get<TrackManager>().hasLoggedServices())
list.add(tracked)
list
}
var onGroupClicked: (Int) -> Unit = { _ -> }
val recycler = androidx.recyclerview.widget.RecyclerView(context)
var pager:View? = null
fun onCreate(pagerView:View) {
val sheetBehavior = BottomSheetBehavior.from(this)
topbar.setOnClickListener {
if (sheetBehavior.state != BottomSheetBehavior.STATE_EXPANDED) {
sheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
} else {
sheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
}
}
line.alpha = 0f
sortText.alpha = if (sheetBehavior.state != BottomSheetBehavior.STATE_EXPANDED) 1f else 0f
title.alpha = if (sheetBehavior.state == BottomSheetBehavior.STATE_EXPANDED) 1f else 0f
pager = pagerView
pager?.setPadding(0, 0, 0, topbar.height)
updateTitle()
sheetBehavior.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(bottomSheet: View, progress: Float) {
updateRootPadding(progress)
sortText.alpha = 1 - progress
title.alpha = progress
}
override fun onStateChanged(p0: View, state: Int) {
if (state == BottomSheetBehavior.STATE_COLLAPSED) {
reSortViews()
}
}
})
topbar.viewTreeObserver.addOnGlobalLayoutListener {
sheetBehavior.peekHeight = topbar.height
if (sheetBehavior.state == BottomSheetBehavior.STATE_COLLAPSED) {
pager?.setPadding(0, 0, 0, topbar.height)
sortText.alpha = 1f
title.alpha = 0f
}
else {
updateRootPadding()
}
}
createTags()
}
fun updateTitle() {
val filters = getFilters().toMutableList()
if (filters.isEmpty()) {
sortText.text = context.getString(
R.string.sorting_by_, context.getString(
when (sorting()) {
LibrarySort.LAST_UPDATED -> R.string.action_sort_last_updated
LibrarySort.DRAG_AND_DROP -> R.string.action_sort_drag_and_drop
LibrarySort.TOTAL -> R.string.action_sort_total
LibrarySort.UNREAD -> R.string.action_filter_unread
LibrarySort.LAST_READ -> R.string.action_sort_last_read
else -> R.string.title
}
)
)
}
else {
filters.add(0, when (sorting()) {
LibrarySort.LAST_UPDATED -> R.string.action_sort_last_updated
LibrarySort.DRAG_AND_DROP -> R.string.action_sort_drag_and_drop
LibrarySort.TOTAL -> R.string.action_sort_total
LibrarySort.UNREAD -> R.string.action_filter_unread
LibrarySort.LAST_READ -> R.string.action_sort_last_read
else -> R.string.action_sort_alpha
})
sortText.text = filters.joinToString(", ") { context.getString(it) }
}
}
fun adjustTitleMargin(downloading: Boolean) {
val params = sortText.layoutParams as? MarginLayoutParams ?: return
params.rightMargin = (if (downloading) 80 else 8).dpToPx
sortText.layoutParams = params
}
fun updateRootPadding(progress: Float? = null) {
val sheetBehavior = BottomSheetBehavior.from(this)
val minHeight = sheetBehavior.peekHeight
val maxHeight = height
val trueProgress = progress ?: if (sheetBehavior.state == BottomSheetBehavior.STATE_EXPANDED) 1f else 0f
val percent = (trueProgress * 100).roundToInt()
val value = (percent * (maxHeight - minHeight) / 100) + minHeight
pager?.setPadding(0, 0, 0, value)
}
fun sorting(): Int {
val sortingMode = preferences.librarySortingMode().getOrDefault()
return if (sortingMode == LibrarySort.DRAG_AND_DROP &&
lastCategory != null &&
preferences.showCategories().getOrDefault()) {
when (lastCategory?.mangaSort) {
'a', 'b' -> LibrarySort.ALPHA
'c', 'd' -> LibrarySort.LAST_UPDATED
'e', 'f' -> LibrarySort.UNREAD
'g', 'h' -> LibrarySort.LAST_READ
else -> LibrarySort.DRAG_AND_DROP
}
}
else {
preferences.librarySortingMode().getOrDefault()
}
}
private fun getFilters(): List<Int> {
val filters = mutableListOf<Int>()
val categoriesOn = preferences.showCategories().getOrDefault()
if (!categoriesOn) {
filters.add(R.string.hiding_categories)
}
var filter = preferences.filterDownloaded().getOrDefault()
if (filter > 0) {
filters.add(if (filter == 1) R.string.action_filter_downloaded else R.string
.action_filter_not_downloaded)
}
filter = preferences.filterUnread().getOrDefault()
if (filter > 0) {
filters.add(when (filter) {
3 -> R.string.action_filter_read
2 -> R.string.action_filter_in_progress
else -> R.string.action_filter_not_started
})
}
filter = preferences.filterCompleted().getOrDefault()
if (filter > 0) {
filters.add(if (filter == 1) R.string.completed else R.string
.ongoing)
}
filter = preferences.filterTracked().getOrDefault()
if (filter > 0) {
filters.add(if (filter == 1) R.string.action_filter_tracked else R.string
.action_filter_not_tracked)
}
filter = preferences.filterMangaType().getOrDefault()
if (filter > 0) {
filters.add(if (filter == 1) R.string.manga_only else R.string.manwha_only)
}
return filters
}
fun createTags() {
categories = inflate(R.layout.filter_buttons) as FilterTagGroup
categories.setup(this, R.string.hide_categories)
downloaded = inflate(R.layout.filter_buttons) as FilterTagGroup
downloaded.setup(this, R.string.action_filter_downloaded, R.string.action_filter_not_downloaded)
completed = inflate(R.layout.filter_buttons) as FilterTagGroup
completed.setup(this, R.string.completed, R.string.ongoing)
unread = inflate(R.layout.filter_buttons) as FilterTagGroup
unread.setup(this, R.string.action_filter_not_started, R.string.action_filter_in_progress,
R.string.action_filter_read)
tracked = inflate(R.layout.filter_buttons) as FilterTagGroup
tracked.setup(this, R.string.action_filter_tracked, R.string.action_filter_not_tracked)
filterItems.forEach {
filterLayout.addView(it)
}
checkForManwha()
}
private fun checkForManwha() {
GlobalScope.launch(Dispatchers.IO, CoroutineStart.DEFAULT) {
val db:DatabaseHelper by injectLazy()
val librryManga = db.getLibraryMangas().executeAsBlocking()
if (librryManga.any { it.mangaType() == LibraryManga.MANWHA }) {
launchUI {
val mangaType = inflate(R.layout.filter_buttons) as FilterTagGroup
mangaType.setup(
this@FilterBottomSheet,
R.string.manga,
R.string.manwha
)
this@FilterBottomSheet.mangaType = mangaType
filterLayout.addView(mangaType)
filterItems.add(mangaType)
}
}
launchUI {
categories.setState(!preferences.showCategories().getOrDefault())
downloaded.setState(preferences.filterDownloaded())
completed.setState(preferences.filterCompleted())
unread.setState(preferences.filterUnread())
tracked.setState(preferences.filterTracked())
mangaType?.setState(preferences.filterMangaType())
reSortViews()
}
}
}
override fun onFilterClicked(view: FilterTagGroup, index: Int, updatePreference:Boolean) {
if (updatePreference) {
when (view) {
categories -> {
preferences.showCategories().set(index != 0)
onGroupClicked(ACTION_REFRESH)
}
downloaded -> {
preferences.filterDownloaded().set(index + 1)
onGroupClicked(ACTION_FILTER)
}
unread -> {
preferences.filterUnread().set(index + 1)
onGroupClicked(ACTION_FILTER)
}
completed -> {
preferences.filterCompleted().set(index + 1)
onGroupClicked(ACTION_FILTER)
}
tracked -> {
preferences.filterTracked().set(index + 1)
onGroupClicked(ACTION_FILTER)
}
mangaType -> {
preferences.filterMangaType().set(index + 1)
onGroupClicked(ACTION_FILTER)
}
}
updateTitle()
}
}
fun reSortViews() {
filterLayout.removeAllViews()
filterItems.filter { it.isActivated }.forEach {
filterLayout.addView(it)
}
filterItems.filterNot { it.isActivated }.forEach {
filterLayout.addView(it)
}
filterScrollView.scrollTo(0, 0)
}
companion object {
const val ACTION_REFRESH = 0
const val ACTION_SORT = 1
const val ACTION_FILTER = 2
const val ACTION_DISPLAY = 3
const val ACTION_BADGE = 4
}
}

View File

@ -19,6 +19,7 @@ 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.category.CategoryAdapter
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.util.system.launchUI
import eu.kanade.tachiyomi.util.view.doOnApplyWindowInsets
import eu.kanade.tachiyomi.util.view.inflate
@ -26,6 +27,7 @@ import eu.kanade.tachiyomi.util.view.snack
import eu.kanade.tachiyomi.util.view.updateLayoutParams
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
import eu.kanade.tachiyomi.util.lang.plusAssign
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
import kotlinx.android.synthetic.main.library_category.view.*
import kotlinx.coroutines.delay
@ -98,14 +100,26 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
swipe_refresh.addView(recycler)
adapter.fastScroller = fast_scroller
fast_scroller.addOnScrollStateChangeListener {
controller.lockFilterBar(it)
}
recycler.doOnApplyWindowInsets { v, insets, padding ->
v.updatePaddingRelative(bottom = padding.bottom + insets.systemWindowInsetBottom)
fast_scroller?.updateLayoutParams<MarginLayoutParams> {
bottomMargin = insets.systemWindowInsetBottom
if (!MainActivity.bottomNav) {
fast_scroller.addOnScrollStateChangeListener {
controller.lockFilterBar(it)
}
}
else {
fast_scroller.setIgnoreTouchesOutsideHandle(false)
}
if (MainActivity.bottomNav) {
val height = context.resources.getDimensionPixelSize(R.dimen.rounder_radius) + 5.dpToPx
recycler.updatePaddingRelative(bottom = height)
}
else {
recycler.doOnApplyWindowInsets { v, insets, padding ->
v.updatePaddingRelative(bottom = padding.bottom + insets.systemWindowInsetBottom)
fast_scroller?.updateLayoutParams<MarginLayoutParams> {
bottomMargin = insets.systemWindowInsetBottom
}
}
}

View File

@ -23,8 +23,6 @@ import com.afollestad.materialdialogs.MaterialDialog
import com.bluelinelabs.conductor.ControllerChangeHandler
import com.bluelinelabs.conductor.ControllerChangeType
import com.f2prateek.rx.preferences.Preference
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.snackbar.BaseTransientBottomBar
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.tabs.TabLayout
@ -46,6 +44,7 @@ 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.main.MainActivity
import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.ui.migration.MigrationController
@ -217,7 +216,7 @@ class LibraryController(
}
if (MainActivity.bottomNav) {
bottom_sheet.onCreate(library_pager)
bottom_sheet.onCreate(pager_layout)
bottom_sheet?.onGroupClicked = {
when (it) {
@ -241,11 +240,13 @@ class LibraryController(
}
fun enableReorderItems(category: Category) {
if (MainActivity.bottomNav) return
adapter?.categories?.getOrNull(library_pager.currentItem)?.mangaSort = category.mangaSort
enableReorderItems(sortType = category.mangaSort)
}
private fun enableReorderItems(position: Int? = null, sortType: Char? = null) {
if (MainActivity.bottomNav) return
val pos = position ?: library_pager.currentItem
val orderOfCat = sortType ?: adapter?.categories?.getOrNull(pos)?.mangaSort
if (reorderMenuItem?.isVisible != true) return
@ -302,7 +303,8 @@ class LibraryController(
super.onDetach(view)
}
override fun createSecondaryDrawer(drawer: DrawerLayout): ViewGroup {
override fun createSecondaryDrawer(drawer: DrawerLayout): ViewGroup? {
if (MainActivity.bottomNav) return null
val view = drawer.inflate(R.layout.library_drawer) as LibraryNavigationView
navView = view
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, GravityCompat.END)
@ -384,6 +386,7 @@ class LibraryController(
bottom_sheet.lastCategory = adapter.categories.getOrNull(activeCat)
bottom_sheet.updateTitle()
bottom_sheet.setMainSortText()
tabsVisibilityRelay.call(categories.size > 1)
@ -481,8 +484,10 @@ class LibraryController(
val reorganizeItem = menu.findItem(R.id.action_reorganize)
reorganizeItem.isVisible =
!MainActivity.bottomNav
preferences.librarySortingMode().getOrDefault() == LibrarySort.DRAG_AND_DROP &&
!preferences.hideCategories().getOrDefault()
menu.findItem(R.id.action_filter).isVisible = !MainActivity.bottomNav
reorderMenuItem = reorganizeItem
enableReorderItems()
@ -726,7 +731,8 @@ class LibraryController(
presenter.removeMangaFromLibrary(mangas)
destroyActionModeIfNeeded()
snack?.dismiss()
snack = view?.snack(activity?.getString(R.string.manga_removed_library) ?: "", Snackbar.LENGTH_INDEFINITE) {
snack = pager_layout?.snack(activity?.getString(R.string.manga_removed_library) ?: "", Snackbar
.LENGTH_INDEFINITE) {
var undoing = false
setAction(R.string.action_undo) {
presenter.addMangas(mangas)

View File

@ -0,0 +1,519 @@
package eu.kanade.tachiyomi.ui.library.filter
import android.content.Context
import android.content.res.Configuration
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.RadioButton
import android.widget.RadioGroup
import androidx.appcompat.widget.PopupMenu
import androidx.core.content.ContextCompat
import com.f2prateek.rx.preferences.Preference
import com.google.android.material.bottomsheet.BottomSheetBehavior
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.LibraryManga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.ui.library.LibrarySort
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.system.launchUI
import eu.kanade.tachiyomi.util.view.gone
import eu.kanade.tachiyomi.util.view.inflate
import eu.kanade.tachiyomi.util.view.marginBottom
import eu.kanade.tachiyomi.util.view.marginTop
import eu.kanade.tachiyomi.util.view.updateLayoutParams
import eu.kanade.tachiyomi.util.view.updatePadding
import eu.kanade.tachiyomi.util.view.visible
import kotlinx.android.synthetic.main.filter_bottom_sheet.view.*
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import kotlin.math.roundToInt
class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
: LinearLayout(context, attrs),
FilterTagGroupListener {
/**
* Preferences helper.
*/
private val preferences: PreferencesHelper by injectLazy()
private lateinit var downloaded: FilterTagGroup
private lateinit var unread: FilterTagGroup
private lateinit var completed: FilterTagGroup
private lateinit var tracked: FilterTagGroup
private lateinit var categories: FilterTagGroup
private var mangaType: FilterTagGroup? = null
var lastCategory:Category? = null
var sheetBehavior:BottomSheetBehavior<View>? = null
private val filterItems:MutableList<FilterTagGroup> by lazy {
val list = mutableListOf<FilterTagGroup>()
if (Injekt.get<DatabaseHelper>().getCategories().executeAsBlocking().isNotEmpty())
list.add(categories)
list.add(downloaded)
list.add(unread)
list.add(completed)
if (Injekt.get<TrackManager>().hasLoggedServices())
list.add(tracked)
list
}
var onGroupClicked: (Int) -> Unit = { _ -> }
val recycler = androidx.recyclerview.widget.RecyclerView(context)
var pager:View? = null
fun onCreate(pagerView:View) {
if (context.resources.configuration?.orientation == Configuration.ORIENTATION_LANDSCAPE) {
sortLayout.orientation = HORIZONTAL
val marginValue = 10.dpToPx
arrayListOf(mainSortTextView, catSortTextView, displayLayout).forEach {
it.updateLayoutParams<MarginLayoutParams> {
bottomMargin = 0
topMargin = 0
}
}
sortScrollView.updatePadding(
bottom = marginValue,
top = 0
)
}
sheetBehavior = BottomSheetBehavior.from(this)
topbar.setOnClickListener {
if (sheetBehavior?.state != BottomSheetBehavior.STATE_EXPANDED) {
sheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED
} else {
sheetBehavior?.state = BottomSheetBehavior.STATE_COLLAPSED
}
}
sortText.alpha = if (sheetBehavior?.state != BottomSheetBehavior.STATE_EXPANDED) 1f else 0f
title.alpha = if (sheetBehavior?.state == BottomSheetBehavior.STATE_EXPANDED) 1f else 0f
pager = pagerView
pager?.setPadding(0, 0, 0, topbar.height)
updateTitle()
sheetBehavior?.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(bottomSheet: View, progress: Float) {
updateRootPadding(progress)
val newProg = when {
progress > 0.9f -> 1f
progress < 0.1f -> 0f
else -> progress
}
sortText.alpha = 1 - newProg
title.alpha = newProg
}
override fun onStateChanged(p0: View, state: Int) {
if (state == BottomSheetBehavior.STATE_COLLAPSED) reSortViews()
else setMainSortText()
}
})
topbar.viewTreeObserver.addOnGlobalLayoutListener {
sheetBehavior?.peekHeight = topbar.height
if (sheetBehavior?.state == BottomSheetBehavior.STATE_COLLAPSED) {
val height = context.resources.getDimensionPixelSize(R.dimen.rounder_radius)
pager?.setPadding(0, 0, 0, topbar.height - height)
sortText.alpha = 1f
title.alpha = 0f
}
else {
updateRootPadding()
}
}
createTags()
mainSortTextView.setOnClickListener { showMainSortOptions() }
catSortTextView.setOnClickListener { showCatSortOptions() }
displayGroup.bindToPreference(preferences.libraryAsList())
}
fun updateTitle() {
launchUI {
val text = withContext(Dispatchers.IO) {
val filters = getFilters().toMutableList()
if (filters.isEmpty()) {
context.getString(
R.string.sorting_by_, context.getString(
when (sorting()) {
LibrarySort.LAST_UPDATED -> R.string.action_sort_last_updated
LibrarySort.DRAG_AND_DROP -> R.string.action_sort_drag_and_drop
LibrarySort.TOTAL -> R.string.action_sort_total
LibrarySort.UNREAD -> R.string.action_filter_unread
LibrarySort.LAST_READ -> R.string.action_sort_last_read
else -> R.string.title
}
)
)
} else {
filters.add(
0, when (sorting()) {
LibrarySort.LAST_UPDATED -> R.string.action_sort_last_updated
LibrarySort.DRAG_AND_DROP -> R.string.action_sort_drag_and_drop
LibrarySort.TOTAL -> R.string.action_sort_total
LibrarySort.UNREAD -> R.string.action_filter_unread
LibrarySort.LAST_READ -> R.string.action_sort_last_read
else -> R.string.action_sort_alpha
}
)
filters.joinToString(", ") { context.getString(it) }
}
}
sortText.text = text
setMainSortText()
}
}
fun adjustTitleMargin(downloading: Boolean) {
val params = sortText.layoutParams as? MarginLayoutParams ?: return
params.rightMargin = (if (downloading) 80 else 8).dpToPx
sortText.layoutParams = params
}
fun updateRootPadding(progress: Float? = null) {
val minHeight = sheetBehavior?.peekHeight ?: 0
val maxHeight = height
val trueProgress = progress ?:
if (sheetBehavior?.state == BottomSheetBehavior.STATE_EXPANDED) 1f else 0f
val percent = (trueProgress * 100).roundToInt()
val value = (percent * (maxHeight - minHeight) / 100) + minHeight
val height = context.resources.getDimensionPixelSize(R.dimen.rounder_radius)
pager?.setPadding(0, 0, 0, value - height)
}
fun sorting(trueSort:Boolean = false): Int {
val sortingMode = preferences.librarySortingMode().getOrDefault()
return if (!trueSort && sortingMode == LibrarySort.DRAG_AND_DROP &&
lastCategory != null &&
preferences.showCategories().getOrDefault()) {
when (lastCategory?.mangaSort) {
'a', 'b' -> LibrarySort.ALPHA
'c', 'd' -> LibrarySort.LAST_UPDATED
'e', 'f' -> LibrarySort.UNREAD
'g', 'h' -> LibrarySort.LAST_READ
else -> LibrarySort.DRAG_AND_DROP
}
}
else {
sortingMode
}
}
private fun getFilters(): List<Int> {
val filters = mutableListOf<Int>()
val categoriesOn = preferences.showCategories().getOrDefault()
if (!categoriesOn) {
filters.add(R.string.hiding_categories)
}
var filter = preferences.filterDownloaded().getOrDefault()
if (filter > 0) {
filters.add(if (filter == 1) R.string.action_filter_downloaded else R.string
.action_filter_not_downloaded)
}
filter = preferences.filterUnread().getOrDefault()
if (filter > 0) {
filters.add(when (filter) {
3 -> R.string.action_filter_read
2 -> R.string.action_filter_in_progress
else -> R.string.action_filter_not_started
})
}
filter = preferences.filterCompleted().getOrDefault()
if (filter > 0) {
filters.add(if (filter == 1) R.string.completed else R.string
.ongoing)
}
filter = preferences.filterTracked().getOrDefault()
if (filter > 0) {
filters.add(if (filter == 1) R.string.action_filter_tracked else R.string
.action_filter_not_tracked)
}
filter = preferences.filterMangaType().getOrDefault()
if (filter > 0) {
filters.add(if (filter == 1) R.string.manga_only else R.string.manwha_only)
}
return filters
}
fun createTags() {
categories = inflate(R.layout.filter_buttons) as FilterTagGroup
categories.setup(this, R.string.hide_categories)
downloaded = inflate(R.layout.filter_buttons) as FilterTagGroup
downloaded.setup(this, R.string.action_filter_downloaded, R.string.action_filter_not_downloaded)
completed = inflate(R.layout.filter_buttons) as FilterTagGroup
completed.setup(this, R.string.completed, R.string.ongoing)
unread = inflate(R.layout.filter_buttons) as FilterTagGroup
unread.setup(this, R.string.action_filter_not_started, R.string.action_filter_in_progress,
R.string.action_filter_read)
tracked = inflate(R.layout.filter_buttons) as FilterTagGroup
tracked.setup(this, R.string.action_filter_tracked, R.string.action_filter_not_tracked)
filterItems.forEach {
filterLayout.addView(it)
}
checkForManwha()
}
private fun checkForManwha() {
GlobalScope.launch(Dispatchers.IO, CoroutineStart.DEFAULT) {
val db:DatabaseHelper by injectLazy()
val librryManga = db.getLibraryMangas().executeAsBlocking()
if (librryManga.any { it.mangaType() == LibraryManga.MANWHA }) {
launchUI {
val mangaType = inflate(R.layout.filter_buttons) as FilterTagGroup
mangaType.setup(
this@FilterBottomSheet,
R.string.manga,
R.string.manwha
)
this@FilterBottomSheet.mangaType = mangaType
filterLayout.addView(mangaType)
filterItems.add(mangaType)
}
}
launchUI {
categories.setState(!preferences.showCategories().getOrDefault())
downloaded.setState(preferences.filterDownloaded())
completed.setState(preferences.filterCompleted())
unread.setState(preferences.filterUnread())
tracked.setState(preferences.filterTracked())
mangaType?.setState(preferences.filterMangaType())
reSortViews()
}
}
}
private fun showMainSortOptions() {
// Create a PopupMenu, giving it the clicked view for an anchor
val popup = PopupMenu(context, mainSortTextView)
// Inflate our menu resource into the PopupMenu's Menu
popup.menuInflater.inflate(R.menu.main_sort, popup.menu)
// Set a listener so we are notified if a menu item is clicked
popup.setOnMenuItemClickListener { menuItem ->
onMainSortClicked(menuItem)
true
}
popup.menu.findItem(R.id.action_reverse).isVisible =
preferences.librarySortingMode().getOrDefault() != LibrarySort.DRAG_AND_DROP
// Finally show the PopupMenu
popup.show()
}
private fun showCatSortOptions() {
// Create a PopupMenu, giving it the clicked view for an anchor
val popup = PopupMenu(context, catSortTextView)
// Inflate our menu resource into the PopupMenu's Menu
popup.menuInflater.inflate(R.menu.cat_sort, popup.menu)
// Set a listener so we are notified if a menu item is clicked
/* popup.setOnMenuItemClickListener { menuItem ->
onMainSortClicked(menuItem)
true
}*/
popup.menu.findItem(R.id.action_reverse).isVisible = lastCategory?.mangaSort != null
// Finally show the PopupMenu
popup.show()
}
private fun onMainSortClicked(menu: MenuItem) {
if (menu.itemId == R.id.action_reverse) {
preferences.librarySortingAscending().set(
!preferences.librarySortingAscending().getOrDefault())
}
else {
preferences.librarySortingMode().set(
when (menu.itemId) {
R.id.action_update -> LibrarySort.LAST_UPDATED
R.id.action_unread -> LibrarySort.UNREAD
R.id.action_total_chaps -> LibrarySort.TOTAL
R.id.action_last_read -> LibrarySort.LAST_READ
R.id.action_drag_and_drop -> LibrarySort.DRAG_AND_DROP
else -> LibrarySort.ALPHA
}
)
preferences.librarySortingAscending().set(true)
}
setMainSortText()
onGroupClicked(ACTION_SORT)
}
fun setMainSortText() {
if (sheetBehavior?.state == BottomSheetBehavior.STATE_COLLAPSED) return
launchUI {
val sortId = withContext(Dispatchers.IO) { sorting(true) }
val drawable = withContext(Dispatchers.IO) {
tintVector(
when {
sortId == LibrarySort.DRAG_AND_DROP -> R.drawable.ic_sort_white_24dp
preferences.librarySortingAscending().getOrDefault() -> R.drawable
.ic_arrow_up_white_24dp
else -> R.drawable.ic_arrow_down_white_24dp
}
)
}
mainSortTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(
drawable, null, null, null
)
mainSortTextView.text = withContext(Dispatchers.IO) {
context.getString(
if (sortId == LibrarySort.DRAG_AND_DROP) R.string.sort_library_by_
else R.string.sort_by_
, context.getString(
when (sortId) {
LibrarySort.LAST_UPDATED -> R.string.action_sort_last_updated
LibrarySort.DRAG_AND_DROP -> R.string.action_sort_drag_and_drop
LibrarySort.TOTAL -> R.string.action_sort_total
LibrarySort.UNREAD -> R.string.action_filter_unread
LibrarySort.LAST_READ -> R.string.action_sort_last_read
else -> R.string.title
}
)
)
}
setCatSortText()
}
}
private fun setCatSortText() {
launchUI {
if (preferences.librarySortingMode().getOrDefault() == LibrarySort.DRAG_AND_DROP && preferences.showCategories().getOrDefault() && lastCategory != null) {
val sortId = withContext(Dispatchers.IO) { sorting() }
val drawable = withContext(Dispatchers.IO) {
tintVector(
when {
sortId == LibrarySort.DRAG_AND_DROP -> R.drawable.ic_sort_white_24dp
preferences.librarySortingAscending().getOrDefault() -> R.drawable
.ic_arrow_up_white_24dp
else -> R.drawable.ic_arrow_down_white_24dp
}
)
}
catSortTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(
drawable, null, null, null
)
catSortTextView.text = withContext(Dispatchers.IO) {
context.getString(
R.string.sort_category_by_, context.getString(
when (sortId) {
LibrarySort.LAST_UPDATED -> R.string.action_sort_last_updated
LibrarySort.DRAG_AND_DROP -> R.string.action_sort_drag_and_drop
LibrarySort.TOTAL -> R.string.action_sort_total
LibrarySort.UNREAD -> R.string.action_filter_unread
LibrarySort.LAST_READ -> R.string.action_sort_last_read
else -> R.string.title
}
)
)
}
if (catSortTextView.visibility != View.VISIBLE) catSortTextView.visible()
} else if (catSortTextView.visibility == View.VISIBLE) catSortTextView.gone()
}
}
/**
* 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)
onGroupClicked(ACTION_DISPLAY)
}
}
private fun Boolean.toInt() = if (this) 1 else 0
private fun tintVector(resId: Int): Drawable? {
return ContextCompat.getDrawable(context, resId)?.mutate()?.apply {
setTint(context.getResourceColor(R.attr.actionBarTintColor))
}
}
override fun onFilterClicked(view: FilterTagGroup, index: Int, updatePreference:Boolean) {
if (updatePreference) {
when (view) {
categories -> {
preferences.showCategories().set(index != 0)
onGroupClicked(ACTION_REFRESH)
}
downloaded -> {
preferences.filterDownloaded().set(index + 1)
onGroupClicked(ACTION_FILTER)
}
unread -> {
preferences.filterUnread().set(index + 1)
onGroupClicked(ACTION_FILTER)
}
completed -> {
preferences.filterCompleted().set(index + 1)
onGroupClicked(ACTION_FILTER)
}
tracked -> {
preferences.filterTracked().set(index + 1)
onGroupClicked(ACTION_FILTER)
}
mangaType -> {
preferences.filterMangaType().set(index + 1)
onGroupClicked(ACTION_FILTER)
}
}
updateTitle()
}
}
fun reSortViews() {
filterLayout.removeAllViews()
filterItems.filter { it.isActivated }.forEach {
filterLayout.addView(it)
}
filterItems.filterNot { it.isActivated }.forEach {
filterLayout.addView(it)
}
filterScrollView.scrollTo(0, 0)
}
companion object {
const val ACTION_REFRESH = 0
const val ACTION_SORT = 1
const val ACTION_FILTER = 2
const val ACTION_DISPLAY = 3
const val ACTION_BADGE = 4
}
}

View File

@ -1,12 +1,9 @@
package eu.kanade.tachiyomi.ui.library
package eu.kanade.tachiyomi.ui.library.filter
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.widget.HorizontalScrollView
import android.widget.LinearLayout
import androidx.transition.Transition
import com.f2prateek.rx.preferences.Preference
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.util.system.dpToPx
@ -17,7 +14,7 @@ import kotlinx.android.synthetic.main.filter_buttons.view.*
class FilterTagGroup@JvmOverloads constructor(context: Context, attrs: AttributeSet? = null): LinearLayout
(context, attrs) {
private var listener:FilterTagGroupListener? = null
private var listener: FilterTagGroupListener? = null
var itemCount = 0
private set

View File

@ -0,0 +1,168 @@
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

@ -2,12 +2,22 @@ package eu.kanade.tachiyomi.ui.migration.manga.design
import android.app.Activity
import android.content.res.Configuration
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.GradientDrawable
import android.os.Build
import android.os.Bundle
import android.view.Gravity
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
@ -17,6 +27,8 @@ 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
@ -24,9 +36,10 @@ 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_chapters
import kotlinx.android.synthetic.main.migration_bottom_sheet.mig_tracking
import kotlinx.android.synthetic.main.migration_bottom_sheet.view.*
import uy.kohesive.injekt.injectLazy
class MigrationBottomSheetDialog(activity: Activity, theme: Int, private val listener:
class MigrationBottomSheetDialog(private val activity: Activity, theme: Int, private val listener:
StartMigrationListener) :
BottomSheetDialog(activity,
theme) {
@ -45,6 +58,28 @@ StartMigrationListener) :
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)
}
}
/**
@ -55,6 +90,16 @@ StartMigrationListener) :
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
}
}
fab.setOnClickListener {
preferences.skipPreMigration().set(skip_step.isChecked)
listener.startMigration(

View File

@ -72,7 +72,8 @@ class PreMigrationController(bundle: Bundle? = null) : BaseController(bundle), F
fab.setOnClickListener {
if (dialog?.isShowing != true) {
dialog = MigrationBottomSheetDialog(activity!!, R.style.SheetDialog, this)
dialog = MigrationBottomSheetDialog(activity!!, R.style.BottomSheetDialogTheme,
this)
dialog?.show()
val bottomSheet = dialog?.findViewById<FrameLayout>(
com.google.android.material.R.id.design_bottom_sheet

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:topLeftRadius="14dp"
android:topRightRadius="14dp" />
<solid android:color="?android:attr/colorBackground" />
</shape>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
android:tint="?attr/actionBarTintColor">
<path
android:fillColor="#FFFFFF"
android:pathData="M11,4H13V16L18.5,10.5L19.92,11.92L12,19.84L4.08,11.92L5.5,10.5L11,16V4Z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="#FFFFFF"
android:pathData="M13,20H11V8L5.5,13.5L4.08,12.08L12,4.16L19.92,12.08L18.5,13.5L13,8V20Z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="?attr/actionBarTintColor"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M17.63,5.84C17.27,5.33 16.67,5 16,5L5,5.01C3.9,5.01 3,5.9 3,7v10c0,1.1 0.9,1.99 2,1.99L16,19c0.67,0 1.27,-0.33 1.63,-0.84L22,12l-4.37,-6.16zM16,17H5V7h11l3.55,5L16,17z"/>
</vector>

View File

@ -1,21 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<eu.kanade.tachiyomi.ui.library.FilterBottomSheet xmlns:android="http://schemas.android.com/apk/res/android"
<eu.kanade.tachiyomi.ui.library.filter.FilterBottomSheet 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:id="@+id/bottom_sheet"
android:layout_width="match_parent"
style="@style/BottomSheetDialogTheme"
android:background="@drawable/bg_bottom_sheet_dialog_fragment"
android:layout_height="wrap_content"
android:background="?android:attr/colorBackground"
android:orientation="vertical"
android:clickable="true"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
android:focusable="true">
android:focusable="true"
android:orientation="vertical"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/topbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/topbar"
android:background="?android:attr/colorPrimary">
android:backgroundTint="?android:attr/colorPrimary"
android:background="@drawable/bg_bottom_sheet_dialog_fragment">
<ImageView
@ -33,39 +35,30 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginTop="15dp"
android:textColor="?attr/actionBarTintColor"
android:text="Filter &amp; Sort"
android:layout_marginBottom="15dp"
android:layout_marginEnd="8dp"
android:text="@string/filter_and_sort"
android:textAlignment="textStart"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
app:layout_constraintStart_toEndOf="@+id/imageView2"
android:textColor="?attr/actionBarTintColor"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView2"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textColor="?attr/actionBarTintColor"
android:text="Filter &amp; Sort"
android:textAlignment="textStart"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
app:layout_constraintTop_toTopOf="@+id/sortText"
android:textColor="?attr/actionBarTintColor"
app:layout_constraintBottom_toBottomOf="@+id/sortText"
app:layout_constraintEnd_toEndOf="@+id/sortText"
app:layout_constraintStart_toStartOf="@+id/sortText" />
<View
android:id="@+id/line"
android:layout_width="wrap_content"
android:layout_height="1dp"
android:layout_marginTop="15dp"
android:background="?attr/actionBarTintColor"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sortText" />
app:layout_constraintStart_toStartOf="@+id/sortText"
app:layout_constraintTop_toTopOf="@+id/sortText" />
</androidx.constraintlayout.widget.ConstraintLayout>
@ -73,38 +66,134 @@
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<HorizontalScrollView
android:layout_marginTop="6dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:id="@+id/filterScrollView"
android:layout_width="wrap_content"
android:scrollbars="none"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:clipToPadding="false"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/filterLayout"
android:gravity="center_vertical"
android:orientation="horizontal">
</LinearLayout>
</HorizontalScrollView>
<HorizontalScrollView
android:id="@+id/filterScrollView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:clipToPadding="false"
android:paddingStart="20dp"
android:paddingTop="10dp"
android:paddingEnd="20dp"
android:paddingBottom="10dp"
android:scrollbars="none">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:drawablePadding="16dp"
android:text="For sorting later" />
<LinearLayout
android:id="@+id/filterLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
</LinearLayout>
</HorizontalScrollView>
<HorizontalScrollView
android:id="@+id/sortScrollView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:clipToPadding="false"
android:paddingStart="30dp"
android:paddingTop="10dp"
android:paddingEnd="20dp"
android:paddingBottom="10dp"
android:scrollbars="none">
<LinearLayout
android:id="@+id/sortLayout"
android:layout_width="wrap_content"
android:baselineAligned="true"
android:layout_height="wrap_content"
android:gravity="center|start"
android:orientation="vertical">
<TextView
android:id="@+id/mainSortTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:layout_weight="1"
android:layout_marginBottom="20dp"
android:clickable="true"
android:drawablePadding="16dp"
android:focusable="true"
android:gravity="center"
android:text="srgdg"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textColor="?android:attr/textColorPrimary"
android:textSize="15sp"
android:textStyle="normal" />
<TextView
android:id="@+id/catSortTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:layout_weight="1"
android:layout_marginBottom="20dp"
android:clickable="true"
android:drawablePadding="16dp"
android:gravity="center"
android:focusable="true"
android:text="srgdg"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textColor="?android:attr/textColorPrimary"
android:textSize="15sp"
android:textStyle="normal" />
<LinearLayout
android:id="@+id/displayLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center|start"
android:layout_weight="1"
android:baselineAligned="false"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:layout_marginEnd="14dp"
android:focusable="true"
android:text="@string/display_as"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textColor="?android:attr/textColorPrimary"
android:textSize="15sp"
android:textStyle="normal" />
<RadioGroup
android:id="@+id/displayGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="0dp"
android:paddingEnd="8dp"
android:text="@string/action_display_grid" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:text="@string/action_display_list" />
</RadioGroup>
</LinearLayout>
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</eu.kanade.tachiyomi.ui.library.FilterBottomSheet>
</eu.kanade.tachiyomi.ui.library.filter.FilterBottomSheet>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<eu.kanade.tachiyomi.ui.library.FilterTagGroup xmlns:android="http://schemas.android.com/apk/res/android"
<eu.kanade.tachiyomi.ui.library.filter.FilterTagGroup xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="wrap_content"
android:background="@drawable/round_textview_border"
android:layout_marginStart="5dp"
@ -64,4 +64,4 @@
android:text="112"
android:paddingStart="20dp"
android:paddingEnd="20dp"/>
</eu.kanade.tachiyomi.ui.library.FilterTagGroup>
</eu.kanade.tachiyomi.ui.library.filter.FilterTagGroup>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<eu.kanade.tachiyomi.ui.library.FilterTagGroup xmlns:android="http://schemas.android.com/apk/res/android"
<eu.kanade.tachiyomi.ui.library.filter.FilterTagGroup xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"

View File

@ -1,48 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
android:layout_height="match_parent">
<androidx.viewpager.widget.ViewPager
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/pager_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/library_pager"/>
android:layout_height="match_parent">
<androidx.viewpager.widget.ViewPager
android:id="@+id/library_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<eu.kanade.tachiyomi.widget.EmptyView
android:id="@+id/empty_view"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_height="wrap_content"/>
android:visibility="gone" />
<View
android:id="@+id/shadow"
android:layout_width="match_parent"
android:layout_height="16dp"
android:backgroundTint="@color/md_black_1000_54"
android:layout_height="20dp"
android:background="@drawable/shape_gradient_top_shadow"
android:backgroundTint="@color/md_black_1000_54"
android:paddingBottom="10dp"
app:layout_anchorGravity="top"
app:layout_anchor="@id/bottom_sheet" />
<!-- Adding bottom sheet after main content -->
<include layout="@layout/filter_bottom_sheet" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:scaleX="0"
android:scaleY="0"
style="@style/Theme.Widget.FABFixed"
android:layout_gravity="center"
android:clickable="false"
android:focusable="false"
android:scaleX="0"
android:scaleY="0"
app:layout_anchor="@id/bottom_sheet"
style="@style/Theme.Widget.FABFixed"
app:layout_anchorGravity="end|top"
android:layout_gravity="center"
app:srcCompat="@drawable/ic_file_download_white_24dp"/>
app:srcCompat="@drawable/ic_file_download_white_24dp" />
<View
android:id="@+id/shadow2"
android:layout_width="match_parent"
android:layout_height="8dp"
android:layout_gravity="bottom"
android:alpha="0.25"
android:background="@drawable/shape_gradient_top_shadow"
android:layout_gravity="bottom" />
android:background="@drawable/shape_gradient_top_shadow" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -6,6 +6,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
android:fitsSystemWindows="true"
android:orientation="vertical">
@ -13,7 +14,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:background="@drawable/dialog_rounded_background"
android:background="@drawable/bg_bottom_sheet_dialog_fragment"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<group android:id="@+id/reorder_group"
android:checkableBehavior="single">
<item
android:id="@+id/action_alpha"
android:title="@string/title"/>
<item
android:id="@+id/action_last_read"
android:title="@string/action_sort_last_read"/>
<item
android:id="@+id/action_update"
android:title="@string/action_sort_last_updated"/>
<item
android:id="@+id/action_unread"
android:title="@string/action_filter_unread"/>
</group>
<item
android:id="@+id/action_reverse"
android:title="@string/action_reverse_order"/>
</menu>

View File

@ -19,18 +19,21 @@
<item
android:id="@+id/action_edit_categories"
android:icon="@drawable/ic_label_outline_white_24dp"
android:title="@string/action_edit_categories"
app:showAsAction="never"/>
app:showAsAction="ifRoom"/>
<item
android:id="@+id/action_source_migration"
android:icon="@drawable/ic_swap_calls_white_24dp"
android:title="@string/label_migration"
app:showAsAction="never"/>
<item
android:id="@+id/action_reorganize"
android:icon="@drawable/ic_swap_vert_white_24dp"
android:title="@string/action_sort_by"
app:showAsAction="never">
app:showAsAction="ifRoom">
<menu>
<group android:id="@+id/reorder_group"
android:checkableBehavior="single">

View File

@ -24,8 +24,6 @@
android:title="@string/label_migration"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_move_manga"
android:icon="@drawable/ic_swap_vert_white_24dp"

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<group android:id="@+id/reorder_group"
android:checkableBehavior="single">
<item
android:id="@+id/action_alpha"
android:title="@string/title"/>
<item
android:id="@+id/action_last_read"
android:title="@string/action_sort_last_read"/>
<item
android:id="@+id/action_update"
android:title="@string/action_sort_last_updated"/>
<item
android:id="@+id/action_unread"
android:title="@string/action_filter_unread"/>
<item
android:id="@+id/action_total_chaps"
android:title="@string/action_sort_total"/>
<item
android:id="@+id/action_drag_and_drop"
android:title="@string/action_sort_drag_and_drop"/>
</group>
<item
android:id="@+id/action_reverse"
android:title="@string/action_reverse_order"/>
</menu>

View File

@ -1,6 +1,7 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="space_between_cards">4dp</dimen>
<dimen name="rounder_radius">14dp</dimen>
<dimen name="fab_size">56dp</dimen>
<dimen name="fab_margin">16dp</dimen>

View File

@ -50,6 +50,9 @@
<string name="manwha_only">Manwha only</string>
<string name="sorting_by_">Sorting by %1$s</string>
<string name="sort_by_">Sort by: %1$s</string>
<string name="sort_library_by_">Sort library by: %1$s</string>
<string name="sort_category_by_">Sort category by: %1$s</string>
<string name="action_filter_empty">Remove filter</string>
<string name="action_sort_alpha">Alphabetically</string>
<string name="action_sort_enabled">Enabled</string>
@ -628,5 +631,7 @@
<string name="skip_this_step_next_time">Skip this step next time</string>
<string name="pre_migration_skip_toast">To show this screen again, go to Settings -> Library.</string>
<string name="reset_tags">Reset Tags</string>
<string name="filter_and_sort"><![CDATA[Filter & Sort]]></string>
<string name="display_as">Display as:</string>
</resources>

View File

@ -191,6 +191,19 @@
<item name="android:background">?attr/selectable_list_drawable</item>
</style>
<!-- set the rounded drawable as background to your bottom sheet -->
<style name="BottomSheet" parent="@style/Widget.Design.BottomSheet.Modal">
<item name="android:background">@drawable/bg_bottom_sheet_dialog_fragment</item>
</style>
<style name="RoundedBottomSheetDialogTheme" parent="@style/Theme.MaterialComponents.BottomSheetDialog">
<item name="android:background">@android:color/transparent</item>
</style>
<style name="BottomSheetDialogTheme" parent="@style/Theme.MaterialComponents.BottomSheetDialog">
<item name="android:colorBackground">@android:color/transparent</item>
</style>
<!--==============-->
<!--Widgets.Button-->
<!--==============-->