diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt index 5a53c7f96d..9ae7a1221b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt @@ -113,6 +113,8 @@ object PreferenceKeys { const val libraryLayout = "pref_display_library_layout" + const val libraryUsingPager = "library_using_pager" + const val lang = "app_language" const val dateFormat = "app_date_format" diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt index 8f7b6eb0e3..81195bd611 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -11,9 +11,9 @@ import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.track.TrackService import eu.kanade.tachiyomi.source.Source import java.io.File -import java.util.Locale import java.text.DateFormat import java.text.SimpleDateFormat +import java.util.Locale import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys fun Preference.getOrDefault(): T = get() ?: defaultValue()!! @@ -173,6 +173,8 @@ class PreferencesHelper(val context: Context) { fun libraryLayout() = rxPrefs.getInteger(Keys.libraryLayout, 1) + fun libraryUsingPager() = rxPrefs.getBoolean(Keys.libraryUsingPager, false) + fun downloadBadge() = rxPrefs.getBoolean(Keys.downloadBadge, false) fun filterDownloaded() = rxPrefs.getInteger(Keys.filterDownloaded, 0) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt index 4a5bae8933..f89f091017 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt @@ -6,11 +6,10 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.getOrDefault -import eu.kanade.tachiyomi.ui.category.CategoryAdapter import eu.kanade.tachiyomi.util.lang.chop import eu.kanade.tachiyomi.util.lang.removeArticles -import eu.kanade.tachiyomi.util.system.launchUI -import kotlinx.coroutines.delay +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy import java.text.SimpleDateFormat import java.util.Calendar @@ -22,19 +21,18 @@ import java.util.Locale * * @param view the fragment containing this adapter. */ -class LibraryCategoryAdapter(val view: LibraryCategoryView) : - FlexibleAdapter(null, view, true) { +class LibraryCategoryAdapter(val libraryListener: LibraryListener) : + FlexibleAdapter>(null, libraryListener, true) { + init { + setDisplayHeadersAtStartUp(!Injekt.get().libraryUsingPager() + .getOrDefault()) + } /** * The list of manga in this category. */ private var mangas: List = emptyList() - /** - * Listener called when an item of the list press start reading. - */ - val libraryListener: LibraryListener = view - /** * Sets a list of manga in the adapter. * @@ -47,13 +45,26 @@ class LibraryCategoryAdapter(val view: LibraryCategoryView) : performFilter() } + /** + * Returns the position in the adapter for the given manga. + * + * @param manga the manga to find. + */ + fun indexOf(categoryOrder: Int): Int { + return currentItems.indexOfFirst { + if (it is LibraryHeaderItem) it.category.order == categoryOrder + else false } + } + /** * Returns the position in the adapter for the given manga. * * @param manga the manga to find. */ fun indexOf(manga: Manga): Int { - return currentItems.indexOfFirst { it.manga.id == manga.id } + return currentItems.indexOfFirst { + if (it is LibraryItem) it.manga.id == manga.id + else false } } fun performFilter() { @@ -64,7 +75,7 @@ class LibraryCategoryAdapter(val view: LibraryCategoryView) : else { updateDataSet(mangas.filter { it.filter(s) }) } - isLongPressDragEnabled = view.canDrag() && s.isNullOrBlank() + isLongPressDragEnabled = libraryListener.canDrag() && s.isNullOrBlank() } override fun onCreateBubbleText(position: Int):String { @@ -74,6 +85,13 @@ class LibraryCategoryAdapter(val view: LibraryCategoryView) : "Bottom" } else { // Get and show the first character val iFlexible: IFlexible<*>? = getItem(position) + return if (iFlexible is LibraryHeaderItem) { + iFlexible.category.name + } else { + val db:DatabaseHelper by injectLazy() + val category = db.getCategoriesForManga((iFlexible as LibraryItem).manga).executeAsBlocking().firstOrNull()?.name + category?.chop(10) ?: "Default" + } val preferences:PreferencesHelper by injectLazy() when (preferences.librarySortingMode().getOrDefault()) { LibrarySort.DRAG_AND_DROP -> { @@ -145,5 +163,6 @@ class LibraryCategoryAdapter(val view: LibraryCategoryView) : */ fun startReading(position: Int) fun onItemReleased(position: Int) + fun canDrag(): Boolean } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt index 517e2faabe..5c862f86a4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt @@ -79,6 +79,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att fun onCreate(controller: LibraryController) { this.controller = controller + adapter = LibraryCategoryAdapter(this) recycler = if (preferences.libraryLayout().getOrDefault() == 0) { (swipe_refresh.inflate(R.layout.library_list_recycler) as RecyclerView).apply { layoutManager = LinearLayoutManager(context) @@ -89,7 +90,6 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att } } - adapter = LibraryCategoryAdapter(this) recycler.setHasFixedSize(true) recycler.adapter = adapter @@ -155,7 +155,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att .subscribe { if (it == category.id) { adapter.currentItems.forEach { item -> - controller.setSelection(item.manga, true) + controller.setSelection((item as LibraryItem).manga, true) } controller.invalidateActionMode() } @@ -167,11 +167,12 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att if (it.second in -2..-1) { val items = adapter.currentItems.toMutableList() val mangas = controller.selectedMangas - val selectedManga = items.filter { item -> item.manga in mangas } + val selectedManga = items.filter { item -> (item as LibraryItem).manga in + mangas } items.removeAll(selectedManga) if (it.second == -1) items.addAll(0, selectedManga) else items.addAll(selectedManga) - adapter.setItems(items) + adapter.setItems(items.filterIsInstance()) adapter.notifyDataSetChanged() saveDragSort() } @@ -179,7 +180,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att } } - fun canDrag(): Boolean { + override fun canDrag(): Boolean { val sortingMode = preferences.librarySortingMode().getOrDefault() val filterOff = preferences.filterCompleted().getOrDefault() + preferences.filterTracked().getOrDefault() + @@ -212,6 +213,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att val mangaForCategory = event.getMangaForCategory(category).orEmpty() adapter.setItems(mangaForCategory) + adapter.hideAllHeaders() swipe_refresh.isEnabled = !preferences.hideCategories().getOrDefault() @@ -283,7 +285,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att */ override fun onItemClick(view: View?, position: Int): Boolean { // If the action mode is created and the position is valid, toggle the selection. - val item = adapter.getItem(position) ?: return false + val item = adapter.getItem(position) as? LibraryItem ?: return false return if (adapter.mode == SelectableAdapter.Mode.MULTI) { lastClickPosition = position toggleSelection(position) @@ -328,13 +330,13 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att } override fun startReading(position: Int) { - val manga = adapter.getItem(position)?.manga ?: return + val manga = (adapter.getItem(position) as? LibraryItem)?.manga ?: return if (adapter.mode == SelectableAdapter.Mode.MULTI) toggleSelection(position) else controller.startReading(manga) } private fun saveDragSort() { - val mangaIds = adapter.currentItems.mapNotNull { it.manga.id } + val mangaIds = adapter.currentItems.mapNotNull { (it as? LibraryItem)?.manga?.id } category.mangaSort = null category.mangaOrder = mangaIds if (category.id == 0) @@ -373,7 +375,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att private fun toggleSelection(position: Int) { val item = adapter.getItem(position) ?: return - controller.setSelection(item.manga, !adapter.isSelected(position)) + controller.setSelection((item as LibraryItem).manga, !adapter.isSelected(position)) controller.invalidateActionMode() } @@ -386,7 +388,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att private fun setSelection(position: Int) { val item = adapter.getItem(position) ?: return - controller.setSelection(item.manga, true) + controller.setSelection((item as LibraryItem).manga, true) controller.invalidateActionMode() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt index f7dd6e7c2c..5f196fef2d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt @@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.ui.library import android.app.Activity import android.content.Context -import android.content.Intent import android.content.res.Configuration import android.graphics.Color import android.os.Bundle @@ -14,10 +13,18 @@ import android.view.View import android.view.ViewGroup import android.view.WindowInsets import android.view.inputmethod.InputMethodManager +import android.widget.ArrayAdapter +import android.widget.Spinner +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.view.ActionMode +import androidx.appcompat.widget.AppCompatSpinner import androidx.appcompat.widget.SearchView +import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.graphics.drawable.DrawableCompat +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import androidx.viewpager.widget.ViewPager import com.afollestad.materialdialogs.MaterialDialog import com.bluelinelabs.conductor.ControllerChangeHandler @@ -26,9 +33,10 @@ import com.f2prateek.rx.preferences.Preference 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.rxrelay.BehaviorRelay import com.jakewharton.rxrelay.PublishRelay +import eu.davidea.flexibleadapter.FlexibleAdapter +import eu.davidea.flexibleadapter.SelectableAdapter import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.LibraryManga @@ -40,7 +48,6 @@ 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.BaseController -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 @@ -53,14 +60,20 @@ import eu.kanade.tachiyomi.ui.migration.manga.design.PreMigrationController import eu.kanade.tachiyomi.ui.migration.manga.process.MigrationListController import eu.kanade.tachiyomi.ui.migration.manga.process.MigrationProcedureConfig import eu.kanade.tachiyomi.ui.reader.ReaderActivity +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.setOnQueryTextChangeListener 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.view.visible +import eu.kanade.tachiyomi.widget.AutofitRecyclerView +import eu.kanade.tachiyomi.widget.IgnoreFirstSpinnerListener import kotlinx.android.synthetic.main.filter_bottom_sheet.* import kotlinx.android.synthetic.main.library_controller.* -import kotlinx.android.synthetic.main.main_activity.* -import rx.Subscription import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -68,12 +81,16 @@ class LibraryController( bundle: Bundle? = null, private val preferences: PreferencesHelper = Injekt.get() ) : BaseController(bundle), - TabbedController, + //TabbedController, ActionMode.Callback, ChangeMangaCategoriesDialog.Listener, MigrationInterface, DownloadServiceListener, - LibraryServiceListener { + LibraryServiceListener, + FlexibleAdapter.OnItemClickListener, + FlexibleAdapter.OnItemLongClickListener, + FlexibleAdapter.OnItemMoveListener, + LibraryCategoryAdapter.LibraryListener{ /** * Position of the active category. @@ -135,14 +152,19 @@ class LibraryController( /** * Adapter of the view pager. */ - private var adapter: LibraryAdapter? = null + private var pagerAdapter: LibraryAdapter? = null + private lateinit var adapter: LibraryCategoryAdapter + + private lateinit var spinner: Spinner + + private var lastClickPosition = -1 /** * Drawer listener to allow swipe only for closing the drawer. */ - private var tabsVisibilityRelay: BehaviorRelay = BehaviorRelay.create(false) + // private var tabsVisibilityRelay: BehaviorRelay = BehaviorRelay.create(false) - private var tabsVisibilitySubscription: Subscription? = null + // private var tabsVisibilitySubscription: Subscription? = null private var observeLater:Boolean = false @@ -153,47 +175,131 @@ class LibraryController( private var justStarted = true + private var updateScroll = true + + private var spinnerAdapter: SpinnerAdapter? = null + + var scrollLister = object : RecyclerView.OnScrollListener () { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + super.onScrolled(recyclerView, dx, dy) + val position = + (recycler.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition() + val order = when (val item = adapter.getItem(position)) { + is LibraryHeaderItem -> item.category.order + is LibraryItem -> presenter.categories.find { it.id == item.manga.category }?.order + else -> null + } + if (order != null && order != activeCategory) { + preferences.lastUsedCategory().set(order) + activeCategory = order + val category = presenter.categories.find { it.order == order } + + bottom_sheet.lastCategory = category + if (preferences.librarySortingMode().getOrDefault() == LibrarySort.DRAG_AND_DROP) + bottom_sheet.updateTitle() + // spinner.onItemSelectedListener = null + spinnerAdapter?.setCustomText(category?.name) + //spinner.view + //spinner.post { spinner.onItemSelectedListener = listener } + } + } + } + + /** + * Recycler view of the list of manga. + */ + private lateinit var recycler: RecyclerView + + var usePager = preferences.libraryUsingPager().getOrDefault() + init { setHasOptionsMenu(true) retainViewMode = RetainViewMode.RETAIN_DETACH } override fun getTitle(): String? { - return resources?.getString(R.string.label_library) + return null//if (title != null) null else resources?.getString(R.string.label_library) } + + private var title: String? = null + set(value) { + field = value + setTitle() + } + override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { return inflater.inflate(R.layout.library_controller, container, false) } override fun onViewCreated(view: View) { super.onViewCreated(view) + mangaPerRow = getColumnsPreferenceForCurrentOrientation().getOrDefault() - adapter = LibraryAdapter(this) - library_pager.adapter = adapter + if (usePager) { + pager_layout.visible() + fast_scroller.gone() + pagerAdapter = LibraryAdapter(this) + library_pager.adapter = pagerAdapter + library_pager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { + override fun onPageSelected(position: Int) { + preferences.lastUsedCategory().set(position) + activeCategory = position + bottom_sheet.lastCategory = pagerAdapter?.categories?.getOrNull(position) + if (preferences.librarySortingMode().getOrDefault() == LibrarySort.DRAG_AND_DROP) bottom_sheet.updateTitle() + } - library_pager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { - override fun onPageSelected(position: Int) { - preferences.lastUsedCategory().set(position) - activeCategory = position - bottom_sheet.lastCategory = adapter?.categories?.getOrNull(position) - if (preferences.librarySortingMode().getOrDefault() == LibrarySort.DRAG_AND_DROP) bottom_sheet.updateTitle() - } + override fun onPageScrolled( + position: Int, positionOffset: Float, positionOffsetPixels: Int + ) { + } - override fun onPageScrolled( - position: Int, positionOffset: Float, positionOffsetPixels: Int - ) { + override fun onPageScrollStateChanged(state: Int) {} + }) + } + else { + adapter = LibraryCategoryAdapter(this) + recycler = if (preferences.libraryLayout().getOrDefault() == 0) { + (swipe_refresh.inflate(R.layout.library_list_recycler) as RecyclerView).apply { + layoutManager = LinearLayoutManager(context) + } + } else { + (swipe_refresh.inflate(R.layout.library_grid_recycler) as AutofitRecyclerView).apply { + spanCount = mangaPerRow + manager.spanSizeLookup = (object : GridLayoutManager.SpanSizeLookup() { + override fun getSpanSize(position: Int): Int { + val item = this@LibraryController.adapter.getItem(position) + return if (item is LibraryHeaderItem) + manager.spanCount else 1 + } + }) + } } - override fun onPageScrollStateChanged(state: Int) {} - }) + recycler.setHasFixedSize(true) + recycler.adapter = adapter + //adapter.setStickyHeaders(true) + recycler_layout.addView(recycler) + adapter.fastScroller = fast_scroller + recycler.addOnScrollListener(scrollLister) + + spinner = swipe_refresh.inflate(R.layout.library_spinner) as AppCompatSpinner + (activity as MainActivity).supportActionBar?.setDisplayShowCustomEnabled(true) + (activity as MainActivity).supportActionBar?.customView = spinner + spinnerAdapter = SpinnerAdapter(view.context, R.layout.library_spinner_textview, + arrayOf(resources!!.getString(R.string.label_library))) + spinner.adapter = spinnerAdapter + + spinnerAdapter?.setCustomText(resources?.getString(R.string.label_library)) + } - mangaPerRow = getColumnsPreferenceForCurrentOrientation().getOrDefault() if (selectedMangas.isNotEmpty()) { createActionModeIfNeeded() } - bottom_sheet.onCreate(pager_layout) + + //bottom_sheet.onCreate(pager_layout) + bottom_sheet.onCreate(if (usePager) pager_layout else swipe_refresh) bottom_sheet.onGroupClicked = { when (it) { @@ -211,6 +317,28 @@ class LibraryController( router.pushController(DownloadController().withFadeTransaction()) } + + // spinner.onItemSelectedListener = listener + /*spinner.onItemSelectedListener = IgnoreFirstSpinnerListener { position -> + if (!updateScroll) return@IgnoreFirstSpinnerListener + val headerPosition = adapter.indexOf(position) + 1 + if (headerPosition > -1) (recycler.layoutManager as LinearLayoutManager) + .scrollToPositionWithOffset(position, 0) + }*/ + + val config = resources?.configuration + val phoneLandscape = (config?.orientation == Configuration.ORIENTATION_LANDSCAPE && + (config.screenLayout.and(Configuration.SCREENLAYOUT_SIZE_MASK)) < + Configuration.SCREENLAYOUT_SIZE_LARGE) + // pad the recycler if the filter bottom sheet is visible + if (!usePager && !phoneLandscape) { + val height = view.context.resources.getDimensionPixelSize(R.dimen.rounder_radius) + 5.dpToPx + recycler.updatePaddingRelative(bottom = height) + fast_scroller.updateLayoutParams { + bottomMargin = height + } + } + if (presenter.isDownloading()) { fab.scaleY = 1f fab.scaleX = 1f @@ -219,9 +347,10 @@ class LibraryController( } presenter.onRestore() val library = presenter.getAllManga() - if (library != null) onNextLibraryUpdate(presenter.categories, library) + if (library != null) presenter.updateViewBlocking() //onNextLibraryUpdate(presenter.categories, library) else { library_pager.alpha = 0f + swipe_refresh.alpha = 0f presenter.getLibraryBlocking() } } @@ -229,12 +358,17 @@ class LibraryController( override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) { super.onChangeStarted(handler, type) if (type.isEnter) { - activity?.tabs?.setupWithViewPager(library_pager) + if (usePager) + (activity as MainActivity).supportActionBar?.setDisplayShowCustomEnabled(true) + //activity?.tabs?.setupWithViewPager(library_pager) presenter.getLibrary() DownloadService.addListener(this) DownloadService.callListeners() LibraryUpdateService.setListener(this) } + else if (type == ControllerChangeType.PUSH_EXIT) { + (activity as MainActivity).supportActionBar?.setDisplayShowCustomEnabled(false) + } } override fun onActivityResumed(activity: Activity) { @@ -251,18 +385,19 @@ class LibraryController( } override fun onDestroy() { + (activity as MainActivity).supportActionBar?.setDisplayShowCustomEnabled(false) presenter.onDestroy() super.onDestroy() } override fun onDestroyView(view: View) { - adapter?.onDestroy() + //adapter.onDestroy() DownloadService.removeListener(this) LibraryUpdateService.removeListener() - adapter = null + //adapter = null actionMode = null - tabsVisibilitySubscription?.unsubscribe() - tabsVisibilitySubscription = null + //tabsVisibilitySubscription?.unsubscribe() + //tabsVisibilitySubscription = null super.onDestroyView(view) } @@ -288,7 +423,7 @@ class LibraryController( super.onDetach(view) } - override fun configureTabs(tabs: TabLayout) { + /*override fun configureTabs(tabs: TabLayout) { with(tabs) { tabGravity = TabLayout.GRAVITY_CENTER tabMode = TabLayout.MODE_SCROLLABLE @@ -307,12 +442,53 @@ class LibraryController( override fun cleanupTabs(tabs: TabLayout) { tabsVisibilitySubscription?.unsubscribe() tabsVisibilitySubscription = null + }*/ + + fun onNextLibraryUpdate(mangaMap: List, freshStart: Boolean = false) { + if (mangaMap.isNotEmpty()) { + empty_view.hide() + } else { + empty_view.show(R.drawable.ic_book_black_128dp, R.string.information_empty_library) + } + adapter.setItems(mangaMap) + + val position = if (freshStart) adapter.indexOf(activeCategory) + 1 else null + + spinner.onItemSelectedListener = null + spinnerAdapter = SpinnerAdapter(view!!.context, R.layout.library_spinner_textview, + presenter.categories.map { it.name }.toTypedArray()) + spinner.adapter = spinnerAdapter + + + spinnerAdapter?.setCustomText(presenter.categories.find { it.order == activeCategory + }?.name ?: resources?.getString(R.string.label_library)) + if (!freshStart) { + spinnerAdapter?.setCustomText(presenter.categories.find { it.order == activeCategory + }?.name ?: resources?.getString(R.string.label_library)) + justStarted = false + if (swipe_refresh.alpha == 0f) + swipe_refresh.animate().alpha(1f).setDuration(500).start() + + + }else { + if (position != null) + (recycler.layoutManager as LinearLayoutManager) + .scrollToPositionWithOffset(position, 0) + } + spinner.onItemSelectedListener = IgnoreFirstSpinnerListener { pos -> + val headerPosition = adapter.indexOf(pos - 1) + 1 + if (headerPosition > -1) { + (recycler.layoutManager as LinearLayoutManager).scrollToPositionWithOffset( + headerPosition, 0 + ) + } + } } fun onNextLibraryUpdate(categories: List, mangaMap: Map>, freshStart: Boolean = false) { val view = view ?: return - val adapter = adapter ?: return + val adapter = pagerAdapter ?: return // Show empty view if needed if (mangaMap.isNotEmpty()) { @@ -342,13 +518,13 @@ class LibraryController( bottom_sheet.lastCategory = adapter.categories.getOrNull(activeCat) bottom_sheet.updateTitle() - tabsVisibilityRelay.call(categories.size > 1) + //tabsVisibilityRelay.call(categories.size > 1) if (freshStart || !justStarted) { // Delay the scroll position to allow the view to be properly measured. view.post { if (isAttached) { - activity?.tabs?.setScrollPosition(library_pager.currentItem, 0f, true) + //activity?.tabs?.setScrollPosition(library_pager.currentItem, 0f, true) } } @@ -398,22 +574,50 @@ class LibraryController( } fun onCatSortChanged(id: Int? = null) { - val catId = id ?: adapter?.categories?.getOrNull(library_pager.currentItem)?.id ?: return - presenter.requestCatSortUpdate(catId) + val catId = id ?: presenter.categories.find { it.order == activeCategory }?.id ?: return + presenter.requestCatSortUpdate(catId) + //val catId = id ?: adapter?.categories?.getOrNull(library_pager.currentItem)?.id ?: return + // presenter.requestCatSortUpdate(catId) } /** * Reattaches the adapter to the view pager to recreate fragments */ private fun reattachAdapter() { - val adapter = adapter ?: return + val position = (recycler.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition() + if (recycler is AutofitRecyclerView && preferences.libraryLayout().getOrDefault() == 0 || + recycler !is AutofitRecyclerView && preferences.libraryLayout().getOrDefault() > 0) { + recycler_layout.removeView(recycler) + recycler = if (preferences.libraryLayout().getOrDefault() == 0) { + (swipe_refresh.inflate(R.layout.library_list_recycler) as RecyclerView).apply { + layoutManager = LinearLayoutManager(context) + } + } else { + (swipe_refresh.inflate(R.layout.library_grid_recycler) as AutofitRecyclerView).apply { + spanCount = mangaPerRow + manager.spanSizeLookup = (object : GridLayoutManager.SpanSizeLookup() { + override fun getSpanSize(position: Int): Int { + val item = this@LibraryController.adapter.getItem(position) + return if (item is LibraryHeaderItem) + manager.spanCount else 1 + } + }) + } + } + recycler.setHasFixedSize(true) + recycler.addOnScrollListener(scrollLister) + recycler_layout.addView(recycler) + } + recycler.adapter = adapter + (recycler.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(position, 0) + //val adapter = adapter ?: return - val position = library_pager.currentItem + /*val position = library_pager.currentItem adapter.recycle = false library_pager.adapter = adapter library_pager.currentItem = position - adapter.recycle = true + adapter.recycle = true*/ } /** @@ -533,8 +737,8 @@ class LibraryController( mode.title = resources?.getString(R.string.label_selected, count) if (preferences.librarySortingMode().getOrDefault() == LibrarySort.DRAG_AND_DROP) { val catId = (selectedMangas.first() as? LibraryManga)?.category - val sameCat = (adapter?.categories?.getOrNull(library_pager.currentItem)?.id - == catId) && selectedMangas.all { (it as? LibraryManga)?.category == catId } + val sameCat = /*(adapter?.categories?.getOrNull(library_pager.currentItem)?.id + == catId) &&*/ selectedMangas.all { (it as? LibraryManga)?.category == catId } menu.findItem(R.id.action_move_manga).isVisible = sameCat } else menu.findItem(R.id.action_move_manga).isVisible = false @@ -554,11 +758,11 @@ class LibraryController( .negativeButton(android.R.string.no) .show() } - R.id.action_select_all -> { + /*R.id.action_select_all -> { adapter?.categories?.getOrNull(library_pager.currentItem)?.id?.let { selectAllRelay.call(it) } - } + }*/ R.id.action_migrate -> { router.pushController( if (preferences.skipPreMigration().getOrDefault()) { @@ -573,12 +777,12 @@ class LibraryController( .withFadeTransaction()) destroyActionModeIfNeeded() } - R.id.action_to_top, R.id.action_to_bottom -> { + /*R.id.action_to_top, R.id.action_to_bottom -> { adapter?.categories?.getOrNull(library_pager.currentItem)?.id?.let { reorganizeRelay.call(it to if (item.itemId == R.id.action_to_top) -1 else -2) } destroyActionModeIfNeeded() - } + }*/ else -> return false } return true @@ -669,6 +873,19 @@ class LibraryController( destroyActionModeIfNeeded() } + override fun startReading(position: Int) { + val activity = activity ?: return + val manga = (adapter.getItem(position) as? LibraryItem)?.manga ?: return + val chapter = presenter.getFirstUnread(manga) ?: return + val intent = ReaderActivity.newIntent(activity, manga, chapter) + destroyActionModeIfNeeded() + startActivity(intent) + } + + override fun onItemReleased(position: Int) { + + } + fun startReading(manga: Manga) { val activity = activity ?: return val chapter = presenter.getFirstUnread(manga) ?: return @@ -676,6 +893,94 @@ class LibraryController( destroyActionModeIfNeeded() startActivity(intent) } + + override fun canDrag(): Boolean { + val sortingMode = preferences.librarySortingMode().getOrDefault() + val filterOff = preferences.filterCompleted().getOrDefault() + + preferences.filterTracked().getOrDefault() + + preferences.filterUnread().getOrDefault() + + preferences.filterCompleted().getOrDefault() == 0 && + !preferences.hideCategories().getOrDefault() + return sortingMode == LibrarySort.DRAG_AND_DROP && filterOff && + adapter.mode != SelectableAdapter.Mode.MULTI + } + + /** + * Called when a manga is clicked. + * + * @param position the position of the element clicked. + * @return true if the item should be selected, false otherwise. + */ + override fun onItemClick(view: View?, position: Int): Boolean { + // If the action mode is created and the position is valid, toggle the selection. + val item = adapter.getItem(position) as? LibraryItem ?: return false + return if (adapter.mode == SelectableAdapter.Mode.MULTI) { + lastClickPosition = position + toggleSelection(position) + true + } else { + openManga(item.manga, 0f) + false + } + } + + /** + * Called when a manga is long clicked. + * + * @param position the position of the element clicked. + */ + override fun onItemLongClick(position: Int) { + createActionModeIfNeeded() + when { + lastClickPosition == -1 -> setSelection(position) + lastClickPosition > position -> for (i in position until lastClickPosition) + setSelection(i) + lastClickPosition < position -> for (i in lastClickPosition + 1..position) + setSelection(i) + else -> setSelection(position) + } + lastClickPosition = position + } + + override fun onActionStateChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) { + val position = viewHolder?.adapterPosition ?: return + if (actionState == 2) onItemLongClick(position) + } + + /** + * Tells the presenter to toggle the selection for the given position. + * + * @param position the position to toggle. + */ + private fun toggleSelection(position: Int) { + val item = adapter.getItem(position) ?: return + + setSelection((item as LibraryItem).manga, !adapter.isSelected(position)) + invalidateActionMode() + } + + + /** + * Tells the presenter to set the selection for the given position. + * + * @param position the position to toggle. + */ + private fun setSelection(position: Int) { + val item = adapter.getItem(position) ?: return + + setSelection((item as LibraryItem).manga, true) + invalidateActionMode() + } + + override fun onItemMove(fromPosition: Int, toPosition: Int) { } + + override fun shouldMoveItem(fromPosition: Int, toPosition: Int): Boolean { + if (adapter.selectedItemCount > 1) + return false + if (adapter.isSelected(fromPosition)) + toggleSelection(fromPosition) + return true + } } object HeightTopWindowInsetsListener : View.OnApplyWindowInsetsListener { @@ -688,4 +993,30 @@ object HeightTopWindowInsetsListener : View.OnApplyWindowInsetsListener { } return insets } +} + +class SpinnerAdapter(context: Context, layoutId: Int, val array: Array) : + ArrayAdapter + (context, layoutId, array) { + private var mCustomText = "" + + override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { + val view = super.getView(position, convertView, parent) + val tv: TextView = view as TextView + tv.text = mCustomText + return view + } + + fun setCustomText(customText: String?) { + // Call to set the text that must be shown in the spinner for the custom option. + val text = customText ?: return + mCustomText = text + notifyDataSetChanged() + } + + override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View { + val view = parent.inflate(R.layout.library_spinner_entry_text) as TextView + view.text = array[position] + return view + } } \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGridHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGridHolder.kt index 4f4d9407cc..ed7bfdc141 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGridHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGridHolder.kt @@ -7,13 +7,11 @@ import android.widget.FrameLayout import androidx.constraintlayout.widget.ConstraintLayout import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.signature.ObjectKey -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.MangaImpl import eu.kanade.tachiyomi.data.glide.GlideApp import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.view.gone -import eu.kanade.tachiyomi.util.view.updatePaddingRelative import eu.kanade.tachiyomi.util.view.visible import kotlinx.android.synthetic.main.catalogue_grid_item.* import kotlinx.android.synthetic.main.unread_download_badge.* diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHeaderItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHeaderItem.kt new file mode 100644 index 0000000000..3b531756ba --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHeaderItem.kt @@ -0,0 +1,64 @@ +package eu.kanade.tachiyomi.ui.library + +import android.view.View +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import eu.davidea.flexibleadapter.FlexibleAdapter +import eu.davidea.flexibleadapter.items.AbstractHeaderItem +import eu.davidea.flexibleadapter.items.IFlexible +import eu.davidea.viewholders.FlexibleViewHolder +import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.database.models.Category + +class LibraryHeaderItem(val category: Category) : AbstractHeaderItem() { + + override fun getLayoutRes(): Int { + return R.layout.library_category_header_item + } + + override fun createViewHolder( + view: View, + adapter: FlexibleAdapter> + ): Holder { + return Holder(view, adapter) + } + + override fun bindViewHolder( + adapter: FlexibleAdapter>, + holder: Holder, + position: Int, + payloads: MutableList? + ) { + holder.bind(this) + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other is LibraryHeaderItem) { + return category.id == other.category.id + } + return false + } + + override fun isDraggable(): Boolean { + return false + } + + override fun isSelectable(): Boolean { + return false + } + + override fun hashCode(): Int { + return category.id!! + } + + class Holder(view: View, adapter: FlexibleAdapter>) : + FlexibleViewHolder(view, adapter, true) { + + private val sectionText: TextView = view.findViewById(R.id.category_title) + + fun bind(item: LibraryHeaderItem) { + sectionText.text = item.category.name + } + } +} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt index d2fa4c1f0e..be317101dc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt @@ -37,8 +37,4 @@ abstract class LibraryHolder( super.onItemReleased(position) (adapter as? LibraryCategoryAdapter)?.libraryListener?.onItemReleased(position) } - - protected fun convertColor(color: Int):String { - return Integer.toHexString(color and 0x00ffffff) - } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt index 3b648b8f78..c87e4c8fc8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt @@ -9,7 +9,7 @@ import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView import com.f2prateek.rx.preferences.Preference import eu.davidea.flexibleadapter.FlexibleAdapter -import eu.davidea.flexibleadapter.items.AbstractFlexibleItem +import eu.davidea.flexibleadapter.items.AbstractSectionableItem import eu.davidea.flexibleadapter.items.IFilterable import eu.davidea.flexibleadapter.items.IFlexible import eu.kanade.tachiyomi.R @@ -21,8 +21,10 @@ import eu.kanade.tachiyomi.widget.AutofitRecyclerView import kotlinx.android.synthetic.main.catalogue_grid_item.view.* import uy.kohesive.injekt.injectLazy -class LibraryItem(val manga: LibraryManga, private val libraryLayout: Preference) : - AbstractFlexibleItem(), IFilterable { +class LibraryItem(val manga: LibraryManga, + private val libraryLayout: Preference, + header: LibraryHeaderItem) : + AbstractSectionableItem(header), IFilterable { var downloadCount = -1 var unreadType = 1 @@ -51,7 +53,8 @@ class LibraryItem(val manga: LibraryManga, private val libraryLayout: Preference cover_thumbnail.maxHeight = Integer.MAX_VALUE constraint_layout.minHeight = 0 cover_thumbnail.adjustViewBounds = false - cover_thumbnail.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, coverHeight) + cover_thumbnail.layoutParams = + FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, coverHeight) } else { constraint_layout.minHeight = coverHeight diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt index 34b2c11f5c..3a99be68e4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt @@ -17,7 +17,6 @@ import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.online.HttpSource -import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem import eu.kanade.tachiyomi.ui.migration.MigrationFlags import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource import eu.kanade.tachiyomi.util.lang.removeArticles @@ -29,20 +28,16 @@ import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Comp import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import rx.Observable -import rx.Subscription import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.util.ArrayList -import java.util.Calendar import java.util.Collections import java.util.Comparator -import java.util.Date /** * Class containing library information. @@ -109,7 +104,7 @@ class LibraryPresenter( mangaMap } currentMangaMap = mangaMap - view.onNextLibraryUpdate(categories, mangaMap) + updateView(categories, mangaMap) } } @@ -124,7 +119,9 @@ class LibraryPresenter( mangaMap }() currentMangaMap = mangaMap - view.onNextLibraryUpdate(categories, mangaMap, true) + launchUI { + updateView(categories, mangaMap, true) + } } fun getAllManga(): LibraryMap? { @@ -314,7 +311,6 @@ class LibraryPresenter( } val catListing by lazy { val default = createDefaultCategory() - default.order = -1 listOf(default) + db.getCategories().executeAsBlocking() } @@ -423,11 +419,38 @@ class LibraryPresenter( var libraryManga = db.getLibraryMangas().executeAsBlocking() if (!showCategories) libraryManga = libraryManga.distinctBy { it.id } - val libraryMap = libraryManga.map { manga -> + /*val libraryMap = libraryManga.map { manga -> LibraryItem(manga, libraryLayout).apply { unreadType = unreadBadgeType } }.groupBy { if (showCategories) it.manga.category else 0 - } + }*/ + val catItemMain = LibraryHeaderItem(categories.firstOrNull() ?: createDefaultCategory()) + val libraryMap = + if (preferences.libraryUsingPager().getOrDefault()) { + libraryManga.map { manga -> + LibraryItem(manga, libraryLayout, catItemMain).apply { unreadType = unreadBadgeType } + }.groupBy { + if (showCategories) it.manga.category else 0 + } + } + else { + libraryManga.groupBy { manga -> + if (showCategories) manga.category else 0 + //LibraryItem(manga, libraryLayout).apply { unreadType = unreadBadgeType } + }.map { entry -> + val categoryItem = LibraryHeaderItem(categories.find { entry.key == it.id } + ?: createDefaultCategory()) + entry.value.map { + LibraryItem( + it, libraryLayout, categoryItem + ).apply { unreadType = unreadBadgeType } + } + }.map { + val cat = if (showCategories) it.firstOrNull()?.manga?.category ?: 0 else 0 + cat to it + //LibraryItem(manga, libraryLayout).apply { unreadType = unreadBadgeType } + }.toMap() + } if (libraryMap.containsKey(0)) categories.add(0, createDefaultCategory()) @@ -441,6 +464,7 @@ class LibraryPresenter( private fun createDefaultCategory(): Category { val default = Category.createDefault(context) + default.order = -1 val defOrder = preferences.defaultMangaOrder().getOrDefault() if (defOrder.firstOrNull()?.isLetter() == true) default.mangaSort = defOrder.first() else default.mangaOrder = defOrder.split("/").mapNotNull { it.toLongOrNull() } @@ -456,8 +480,59 @@ class LibraryPresenter( mangaMap = withContext(Dispatchers.IO) { applyFilters(mangaMap) } mangaMap = withContext(Dispatchers.IO) { applySort(mangaMap) } currentMangaMap = mangaMap - view.onNextLibraryUpdate(categories, mangaMap) + updateView(categories, mangaMap) + } + } + + suspend fun updateView(categories: List, mangaMap: LibraryMap, freshStart:Boolean + = false) { + /* val list = withContext(Dispatchers.IO) { + val showCategories = !preferences.hideCategories().getOrDefault() + val current = mangaMap.values.first() + current.groupBy { + if (showCategories) it.manga.category else 0 + }.flatMap { it.value } + }*/ + if (preferences.libraryUsingPager().getOrDefault()) { + view.onNextLibraryUpdate(categories, mangaMap, true) } + else { + val mangaList = withContext(Dispatchers.IO) { + val list = mutableListOf() + val many = categories.size > 1 + for (element in mangaMap.toSortedMap(compareBy { entry -> + categories.find { it.id == entry }?.order ?: -1 + })) { + list.addAll(element.value) + } + list + } + view.onNextLibraryUpdate(mangaList, freshStart) + } + } + + fun updateViewBlocking() { + /* val list = withContext(Dispatchers.IO) { + val showCategories = !preferences.hideCategories().getOrDefault() + val current = mangaMap.values.first() + current.groupBy { + if (showCategories) it.manga.category else 0 + }.flatMap { it.value } + }*/ + val mangaMap = currentMangaMap ?: return + if (preferences.libraryUsingPager().getOrDefault()) { + view.onNextLibraryUpdate(categories, mangaMap, true) + } + else { + val list = mutableListOf() + for (element in mangaMap?.toSortedMap(compareBy { entry -> + categories.find { it.id == entry }?.order ?: -1 + })) { + list.addAll(element.value) + } + view.onNextLibraryUpdate(list, true) + } + } /** @@ -471,7 +546,7 @@ class LibraryPresenter( val current = currentMangaMap ?: return@launchUI withContext(Dispatchers.IO) { setDownloadCount(current) } currentMangaMap = current - view.onNextLibraryUpdate(categories, current) + updateView(categories, current) } } @@ -487,7 +562,7 @@ class LibraryPresenter( val current = currentMangaMap ?: return@launchUI withContext(Dispatchers.IO) { setUnreadBadge(current) } currentMangaMap = current - view.onNextLibraryUpdate(categories, current) + updateView(categories, current) } } @@ -499,7 +574,7 @@ class LibraryPresenter( var mangaMap = currentMangaMap ?: return@launchUI mangaMap = withContext(Dispatchers.IO) { applySort(mangaMap) } currentMangaMap = mangaMap - view.onNextLibraryUpdate(categories, mangaMap) + updateView(categories, mangaMap) } } @@ -508,7 +583,7 @@ class LibraryPresenter( var mangaMap = currentMangaMap ?: return@launchUI mangaMap = withContext(Dispatchers.IO) { applyCatSort(mangaMap, catId) } currentMangaMap = mangaMap - view.onNextLibraryUpdate(categories, mangaMap) + updateView(categories, mangaMap) } } @@ -698,5 +773,6 @@ class LibraryPresenter( private companion object { var currentLibrary:Library? = null + var currentList:List? = null } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index 34a41b57a1..a16e6fe042 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -1,7 +1,6 @@ package eu.kanade.tachiyomi.ui.main import android.app.SearchManager -import android.content.ComponentCallbacks2 import android.content.Intent import android.content.res.Configuration import android.graphics.Color @@ -48,7 +47,6 @@ import eu.kanade.tachiyomi.ui.catalogue.global_search.CatalogueSearchController import eu.kanade.tachiyomi.ui.download.DownloadController import eu.kanade.tachiyomi.ui.extension.ExtensionController import eu.kanade.tachiyomi.ui.library.LibraryController -import eu.kanade.tachiyomi.ui.library.LibraryPresenter import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersController import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadController @@ -58,7 +56,6 @@ import eu.kanade.tachiyomi.util.system.launchUI import eu.kanade.tachiyomi.util.view.gone import eu.kanade.tachiyomi.util.view.updateLayoutParams import eu.kanade.tachiyomi.util.view.updatePadding -import eu.kanade.tachiyomi.util.view.updatePaddingRelative import eu.kanade.tachiyomi.util.view.visible import kotlinx.android.synthetic.main.main_activity.* import kotlinx.coroutines.Dispatchers @@ -186,6 +183,8 @@ open class MainActivity : BaseActivity(), DownloadServiceListener { } } + supportActionBar?.setDisplayShowCustomEnabled(true) + content.setOnApplyWindowInsetsListener { v, insets -> // if device doesn't support light nav bar if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { @@ -279,6 +278,10 @@ open class MainActivity : BaseActivity(), DownloadServiceListener { }) + if (router.backstackSize <= 1) { + tabAnimator.hide() + } + syncActivityViewWithController(router.backstack.lastOrNull()?.controller()) if (savedInstanceState == null) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/TabsAnimator.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/TabsAnimator.kt index a4014beeda..35edd4d084 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/TabsAnimator.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/TabsAnimator.kt @@ -1,9 +1,9 @@ package eu.kanade.tachiyomi.ui.main import android.animation.ObjectAnimator -import com.google.android.material.tabs.TabLayout import android.view.ViewTreeObserver import android.view.animation.DecelerateInterpolator +import com.google.android.material.tabs.TabLayout class TabsAnimator(val tabs: TabLayout) { @@ -97,6 +97,11 @@ class TabsAnimator(val tabs: TabLayout) { isLastStateShown = false } + fun hide() { + setHeight(0) + isLastStateShown = false + } + /** * Returns whether the tab layout has a known height. */ diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt index 657fa022d8..ca49dddcc0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt @@ -52,6 +52,13 @@ class SettingsLibraryController : SettingsController() { } } + switchPreference { + key = Keys.libraryUsingPager + titleRes = R.string.pref_remove_articles + summaryRes = R.string.pref_remove_articles_summary + defaultValue = false + } + switchPreference { key = Keys.removeArticles titleRes = R.string.pref_remove_articles diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/AutofitRecyclerView.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/AutofitRecyclerView.kt index 53b062b6af..8d001a631b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/AutofitRecyclerView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/AutofitRecyclerView.kt @@ -3,13 +3,12 @@ package eu.kanade.tachiyomi.widget import android.content.Context import android.util.AttributeSet import androidx.recyclerview.widget.GridLayoutManager -import androidx.recyclerview.widget.RecyclerView import kotlin.math.max class AutofitRecyclerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : androidx.recyclerview.widget.RecyclerView(context, attrs) { - private val manager = GridLayoutManager(context, 1) + val manager = GridLayoutManager(context, 1) private var columnWidth = -1 diff --git a/app/src/main/res/layout/catalogue_grid_item.xml b/app/src/main/res/layout/catalogue_grid_item.xml index 38d41f2155..13810dad96 100644 --- a/app/src/main/res/layout/catalogue_grid_item.xml +++ b/app/src/main/res/layout/catalogue_grid_item.xml @@ -1,153 +1,154 @@ - + + + android:layout_marginStart="8dp" + android:layout_marginTop="10dp" + android:layout_marginEnd="8dp" + app:layout_constraintBottom_toTopOf="@+id/title" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="1.0"> + - + tools:background="?android:attr/colorBackground" + tools:ignore="ContentDescription" + tools:src="@mipmap/ic_launcher" /> + - - - - - - - - - - + android:layout_marginTop="6dp" + android:layout_marginEnd="6dp" + android:layout_marginBottom="6dp" + android:background="@drawable/round_play_background" + android:contentDescription="@string/start_reading" + android:padding="6dp" + android:src="@drawable/ic_start_reading_white_24dp" + android:tint="@android:color/white" /> - - - + - - + android:layout_height="150dp" + android:layout_gravity="bottom" + android:background="@drawable/gradient_shape" /> - + app:layout_constraintTop_toTopOf="parent" /> + + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/library_category_header_item.xml b/app/src/main/res/layout/library_category_header_item.xml new file mode 100644 index 0000000000..ac6a50c740 --- /dev/null +++ b/app/src/main/res/layout/library_category_header_item.xml @@ -0,0 +1,27 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/library_controller.xml b/app/src/main/res/layout/library_controller.xml index a43a3b25b3..5703f91381 100644 --- a/app/src/main/res/layout/library_controller.xml +++ b/app/src/main/res/layout/library_controller.xml @@ -2,11 +2,24 @@ + + + + + @@ -16,6 +29,14 @@ android:layout_height="match_parent" /> + + + \ No newline at end of file diff --git a/app/src/main/res/layout/library_spinner_entry_text.xml b/app/src/main/res/layout/library_spinner_entry_text.xml new file mode 100644 index 0000000000..0cfd835f2d --- /dev/null +++ b/app/src/main/res/layout/library_spinner_entry_text.xml @@ -0,0 +1,13 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/library_spinner_textview.xml b/app/src/main/res/layout/library_spinner_textview.xml new file mode 100644 index 0000000000..b93f486b5e --- /dev/null +++ b/app/src/main/res/layout/library_spinner_textview.xml @@ -0,0 +1,11 @@ + + \ No newline at end of file