mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2025-01-22 23:01:16 +01:00
Download queue moved to recents
We're at 7 bottom sheets now Using vibrant color for manga cover background
This commit is contained in:
parent
9a4894ba95
commit
1ce426d1c9
@ -8,6 +8,8 @@ import eu.kanade.tachiyomi.data.database.mappers.MangaGetResolver
|
|||||||
import eu.kanade.tachiyomi.data.database.models.ChapterImpl
|
import eu.kanade.tachiyomi.data.database.models.ChapterImpl
|
||||||
import eu.kanade.tachiyomi.data.database.models.HistoryImpl
|
import eu.kanade.tachiyomi.data.database.models.HistoryImpl
|
||||||
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
|
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
|
||||||
|
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
|
||||||
|
import eu.kanade.tachiyomi.data.database.tables.HistoryTable
|
||||||
|
|
||||||
class MangaChapterHistoryGetResolver : DefaultGetResolver<MangaChapterHistory>() {
|
class MangaChapterHistoryGetResolver : DefaultGetResolver<MangaChapterHistory>() {
|
||||||
companion object {
|
companion object {
|
||||||
@ -37,19 +39,24 @@ class MangaChapterHistoryGetResolver : DefaultGetResolver<MangaChapterHistory>()
|
|||||||
val manga = mangaGetResolver.mapFromCursor(cursor)
|
val manga = mangaGetResolver.mapFromCursor(cursor)
|
||||||
|
|
||||||
// Get chapter object
|
// Get chapter object
|
||||||
val chapter = try { chapterResolver.mapFromCursor(cursor) } catch (e: Exception) {
|
val chapter =
|
||||||
ChapterImpl() }
|
if (!cursor.isNull(cursor.getColumnIndex(ChapterTable.COL_MANGA_ID))) chapterResolver
|
||||||
|
.mapFromCursor(
|
||||||
|
cursor
|
||||||
|
) else ChapterImpl()
|
||||||
|
|
||||||
// Get history object
|
// Get history object
|
||||||
val history = try { historyGetResolver.mapFromCursor(cursor) } catch (e: Exception) { HistoryImpl() }
|
val history =
|
||||||
|
if (!cursor.isNull(cursor.getColumnIndex(HistoryTable.COL_ID))) historyGetResolver.mapFromCursor(
|
||||||
|
cursor
|
||||||
|
) else HistoryImpl()
|
||||||
|
|
||||||
// Make certain column conflicts are dealt with
|
// Make certain column conflicts are dealt with
|
||||||
if (chapter.id != null) {
|
if (chapter.id != null) {
|
||||||
manga.id = chapter.manga_id
|
manga.id = chapter.manga_id
|
||||||
manga.url = cursor.getString(cursor.getColumnIndex("mangaUrl"))
|
manga.url = cursor.getString(cursor.getColumnIndex("mangaUrl"))
|
||||||
}
|
}
|
||||||
if (history.id != null)
|
if (history.id != null) chapter.id = history.chapter_id
|
||||||
chapter.id = history.chapter_id
|
|
||||||
|
|
||||||
// Return result
|
// Return result
|
||||||
return MangaChapterHistory(manga, chapter, history)
|
return MangaChapterHistory(manga, chapter, history)
|
||||||
|
@ -239,6 +239,9 @@ class DownloadManager(val context: Context) {
|
|||||||
downloader.start()
|
downloader.start()
|
||||||
} else if (downloader.queue.isEmpty() && DownloadService.isRunning(context)) {
|
} else if (downloader.queue.isEmpty() && DownloadService.isRunning(context)) {
|
||||||
DownloadService.stop(context)
|
DownloadService.stop(context)
|
||||||
|
} else if (downloader.queue.isEmpty()) {
|
||||||
|
DownloadService.callListeners(false)
|
||||||
|
downloader.stop()
|
||||||
}
|
}
|
||||||
queue.remove(chapters)
|
queue.remove(chapters)
|
||||||
val chapterDirs = provider.findChapterDirs(chapters, manga, source) + provider.findTempChapterDirs(chapters, manga, source)
|
val chapterDirs = provider.findChapterDirs(chapters, manga, source) + provider.findTempChapterDirs(chapters, manga, source)
|
||||||
|
@ -5,6 +5,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga
|
|||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import rx.subjects.PublishSubject
|
import rx.subjects.PublishSubject
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class Download(val source: HttpSource, val manga: Manga, val chapter: Chapter) {
|
class Download(val source: HttpSource, val manga: Manga, val chapter: Chapter) {
|
||||||
|
|
||||||
@ -25,10 +26,16 @@ class Download(val source: HttpSource, val manga: Manga, val chapter: Chapter) {
|
|||||||
|
|
||||||
@Transient private var statusCallback: ((Download) -> Unit)? = null
|
@Transient private var statusCallback: ((Download) -> Unit)? = null
|
||||||
|
|
||||||
|
val pageProgress: Int
|
||||||
|
get() {
|
||||||
|
val pages = pages ?: return 0
|
||||||
|
return pages.map(Page::progress).sum()
|
||||||
|
}
|
||||||
|
|
||||||
val progress: Int
|
val progress: Int
|
||||||
get() {
|
get() {
|
||||||
val pages = pages ?: return 0
|
val pages = pages ?: return 0
|
||||||
return pages.map(Page::progress).average().toInt()
|
return pages.map(Page::progress).average().roundToInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setStatusSubject(subject: PublishSubject<Download>?) {
|
fun setStatusSubject(subject: PublishSubject<Download>?) {
|
||||||
|
@ -28,6 +28,7 @@ import eu.kanade.tachiyomi.ui.catalogue.browse.BrowseCatalogueController
|
|||||||
import eu.kanade.tachiyomi.ui.catalogue.global_search.CatalogueSearchController
|
import eu.kanade.tachiyomi.ui.catalogue.global_search.CatalogueSearchController
|
||||||
import eu.kanade.tachiyomi.ui.catalogue.latest.LatestUpdatesController
|
import eu.kanade.tachiyomi.ui.catalogue.latest.LatestUpdatesController
|
||||||
import eu.kanade.tachiyomi.ui.extension.SettingsExtensionsController
|
import eu.kanade.tachiyomi.ui.extension.SettingsExtensionsController
|
||||||
|
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||||
import eu.kanade.tachiyomi.ui.main.RootSearchInterface
|
import eu.kanade.tachiyomi.ui.main.RootSearchInterface
|
||||||
import eu.kanade.tachiyomi.ui.setting.SettingsSourcesController
|
import eu.kanade.tachiyomi.ui.setting.SettingsSourcesController
|
||||||
import eu.kanade.tachiyomi.util.view.applyWindowInsetsForRootController
|
import eu.kanade.tachiyomi.util.view.applyWindowInsetsForRootController
|
||||||
@ -269,6 +270,12 @@ class CatalogueController : NucleusController<CataloguePresenter>(),
|
|||||||
router.pushController(controller.withFadeTransaction())
|
router.pushController(controller.withFadeTransaction())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun expandSearch() {
|
||||||
|
if (showingExtenions)
|
||||||
|
ext_bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_COLLAPSED
|
||||||
|
else activity?.toolbar?.menu?.findItem(R.id.action_search)?.expandActionView()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds items to the options menu.
|
* Adds items to the options menu.
|
||||||
*
|
*
|
||||||
@ -276,6 +283,7 @@ class CatalogueController : NucleusController<CataloguePresenter>(),
|
|||||||
* @param inflater used to load the menu xml.
|
* @param inflater used to load the menu xml.
|
||||||
*/
|
*/
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
|
(activity as? MainActivity)?.setDismissIcon(showingExtenions)
|
||||||
if (showingExtenions) {
|
if (showingExtenions) {
|
||||||
// Inflate menu
|
// Inflate menu
|
||||||
inflater.inflate(R.menu.extension_main, menu)
|
inflater.inflate(R.menu.extension_main, menu)
|
||||||
@ -336,9 +344,6 @@ class CatalogueController : NucleusController<CataloguePresenter>(),
|
|||||||
).pushChangeHandler(FadeChangeHandler())
|
).pushChangeHandler(FadeChangeHandler())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
R.id.action_dismiss -> {
|
|
||||||
ext_bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_COLLAPSED
|
|
||||||
}
|
|
||||||
else -> return super.onOptionsItemSelected(item)
|
else -> return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -8,7 +8,7 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
|
|||||||
*
|
*
|
||||||
* @param context the context of the fragment containing this adapter.
|
* @param context the context of the fragment containing this adapter.
|
||||||
*/
|
*/
|
||||||
class DownloadAdapter(controller: DownloadController) : FlexibleAdapter<DownloadItem>(null, controller,
|
class DownloadAdapter(controller: DownloadItemListener) : FlexibleAdapter<DownloadItem>(null, controller,
|
||||||
true) {
|
true) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,6 +21,12 @@ class DownloadAdapter(controller: DownloadController) : FlexibleAdapter<Download
|
|||||||
* Called when an item of the list is released.
|
* Called when an item of the list is released.
|
||||||
*/
|
*/
|
||||||
fun onItemReleased(position: Int)
|
fun onItemReleased(position: Int)
|
||||||
|
fun onItemRemoved(position: Int)
|
||||||
fun onMenuItemClick(position: Int, menuItem: MenuItem)
|
fun onMenuItemClick(position: Int, menuItem: MenuItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onItemSwiped(position: Int, direction: Int) {
|
||||||
|
super.onItemSwiped(position, direction)
|
||||||
|
downloadItemListener.onItemRemoved(position)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
package eu.kanade.tachiyomi.ui.download
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
|
import eu.kanade.tachiyomi.data.download.model.Download
|
||||||
|
import eu.kanade.tachiyomi.data.download.model.DownloadQueue
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Presenter of [DownloadBottomSheet].
|
||||||
|
*/
|
||||||
|
class DownloadBottomPresenter(val sheet: DownloadBottomSheet) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download manager.
|
||||||
|
*/
|
||||||
|
val downloadManager: DownloadManager by injectLazy()
|
||||||
|
var items = listOf<DownloadItem>()
|
||||||
|
|
||||||
|
private var scope = CoroutineScope(Job() + Dispatchers.Default)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property to get the queue from the download manager.
|
||||||
|
*/
|
||||||
|
val downloadQueue: DownloadQueue
|
||||||
|
get() = downloadManager.queue
|
||||||
|
|
||||||
|
fun getItems() {
|
||||||
|
scope.launch {
|
||||||
|
val items = downloadQueue.map(::DownloadItem)
|
||||||
|
val hasChanged = if (this@DownloadBottomPresenter.items.size != items.size) true
|
||||||
|
else {
|
||||||
|
val oldItemsIds = this@DownloadBottomPresenter.items.mapNotNull {
|
||||||
|
it.download.chapter.id
|
||||||
|
}.toLongArray()
|
||||||
|
val newItemsIds = items.mapNotNull { it.download.chapter.id }.toLongArray()
|
||||||
|
!oldItemsIds.contentEquals(newItemsIds)
|
||||||
|
}
|
||||||
|
this@DownloadBottomPresenter.items = items
|
||||||
|
if (hasChanged) {
|
||||||
|
withContext(Dispatchers.Main) { sheet.onNextDownloads(items) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pauses the download queue.
|
||||||
|
*/
|
||||||
|
fun pauseDownloads() {
|
||||||
|
downloadManager.pauseDownloads()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the download queue.
|
||||||
|
*/
|
||||||
|
fun clearQueue() {
|
||||||
|
downloadManager.clearQueue()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reorder(downloads: List<Download>) {
|
||||||
|
downloadManager.reorderQueue(downloads)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun cancelDownload(download: Download) {
|
||||||
|
downloadManager.deletePendingDownloads(download)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,272 @@
|
|||||||
|
package eu.kanade.tachiyomi.ui.download
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.data.download.DownloadService
|
||||||
|
import eu.kanade.tachiyomi.data.download.model.Download
|
||||||
|
import eu.kanade.tachiyomi.ui.extension.ExtensionDividerItemDecoration
|
||||||
|
import eu.kanade.tachiyomi.ui.recents.RecentsController
|
||||||
|
import eu.kanade.tachiyomi.util.view.RecyclerWindowInsetsListener
|
||||||
|
import eu.kanade.tachiyomi.util.view.doOnApplyWindowInsets
|
||||||
|
import eu.kanade.tachiyomi.util.view.updateLayoutParams
|
||||||
|
import kotlinx.android.synthetic.main.download_bottom_sheet.view.*
|
||||||
|
|
||||||
|
class DownloadBottomSheet @JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? =
|
||||||
|
null
|
||||||
|
) : LinearLayout(context, attrs),
|
||||||
|
DownloadAdapter.DownloadItemListener {
|
||||||
|
lateinit var controller: RecentsController
|
||||||
|
var sheetBehavior: BottomSheetBehavior<*>? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapter containing the active downloads.
|
||||||
|
*/
|
||||||
|
private var adapter: DownloadAdapter? = null
|
||||||
|
|
||||||
|
private val presenter = DownloadBottomPresenter(this)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the download queue is running or not.
|
||||||
|
*/
|
||||||
|
private var isRunning: Boolean = false
|
||||||
|
private var activity: Activity? = null
|
||||||
|
|
||||||
|
fun onCreate(controller: RecentsController) {
|
||||||
|
// Initialize adapter, scroll listener and recycler views
|
||||||
|
adapter = DownloadAdapter(this)
|
||||||
|
sheetBehavior = BottomSheetBehavior.from(this)
|
||||||
|
activity = controller.activity
|
||||||
|
// Create recycler and set adapter.
|
||||||
|
dl_recycler.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(context)
|
||||||
|
dl_recycler.adapter = adapter
|
||||||
|
adapter?.isHandleDragEnabled = true
|
||||||
|
adapter?.isSwipeEnabled = true
|
||||||
|
dl_recycler.setHasFixedSize(true)
|
||||||
|
dl_recycler.addItemDecoration(ExtensionDividerItemDecoration(context))
|
||||||
|
dl_recycler.setOnApplyWindowInsetsListener(RecyclerWindowInsetsListener)
|
||||||
|
this.controller = controller
|
||||||
|
updateDLTitle()
|
||||||
|
|
||||||
|
val attrsArray = intArrayOf(android.R.attr.actionBarSize)
|
||||||
|
val array = context.obtainStyledAttributes(attrsArray)
|
||||||
|
val headerHeight = array.getDimensionPixelSize(0, 0)
|
||||||
|
array.recycle()
|
||||||
|
dl_recycler.doOnApplyWindowInsets { _, windowInsets, _ ->
|
||||||
|
dl_recycler.updateLayoutParams<MarginLayoutParams> {
|
||||||
|
topMargin = windowInsets.systemWindowInsetTop + headerHeight - sheet_layout.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sheet_layout.setOnClickListener {
|
||||||
|
if (sheetBehavior?.state != BottomSheetBehavior.STATE_EXPANDED) {
|
||||||
|
sheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
} else {
|
||||||
|
sheetBehavior?.state = BottomSheetBehavior.STATE_COLLAPSED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update()
|
||||||
|
setBottomSheet()
|
||||||
|
|
||||||
|
if (sheetBehavior?.state != BottomSheetBehavior.STATE_EXPANDED && sheetBehavior?.isHideable == true) sheetBehavior?.state =
|
||||||
|
BottomSheetBehavior.STATE_HIDDEN
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update() {
|
||||||
|
presenter.getItems()
|
||||||
|
onQueueStatusChange(!presenter.downloadManager.isPaused())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateDLTitle() {
|
||||||
|
val extCount = presenter.downloadQueue.firstOrNull()
|
||||||
|
title_text.text = if (extCount != null) resources.getString(
|
||||||
|
R.string.downloading_x, extCount.chapter.name
|
||||||
|
)
|
||||||
|
else ""
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the queue's status has changed. Updates the visibility of the buttons.
|
||||||
|
*
|
||||||
|
* @param running whether the queue is now running or not.
|
||||||
|
*/
|
||||||
|
private fun onQueueStatusChange(running: Boolean) {
|
||||||
|
val oldRunning = isRunning
|
||||||
|
isRunning = running
|
||||||
|
if (oldRunning != running) {
|
||||||
|
activity?.invalidateOptionsMenu()
|
||||||
|
|
||||||
|
// Check if download queue is empty and update information accordingly.
|
||||||
|
setInformationView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from the presenter to assign the downloads for the adapter.
|
||||||
|
*
|
||||||
|
* @param downloads the downloads from the queue.
|
||||||
|
*/
|
||||||
|
fun onNextDownloads(downloads: List<DownloadItem>) {
|
||||||
|
activity?.invalidateOptionsMenu()
|
||||||
|
setInformationView()
|
||||||
|
adapter?.updateDataSet(downloads)
|
||||||
|
setBottomSheet()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the progress of a download changes.
|
||||||
|
*
|
||||||
|
* @param download the download whose progress has changed.
|
||||||
|
*/
|
||||||
|
fun onUpdateProgress(download: Download) {
|
||||||
|
getHolder(download)?.notifyProgress()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a page of a download is downloaded.
|
||||||
|
*
|
||||||
|
* @param download the download whose page has been downloaded.
|
||||||
|
*/
|
||||||
|
fun onUpdateDownloadedPages(download: Download) {
|
||||||
|
getHolder(download)?.notifyDownloadedPages()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the holder for the given download.
|
||||||
|
*
|
||||||
|
* @param download the download to find.
|
||||||
|
* @return the holder of the download or null if it's not bound.
|
||||||
|
*/
|
||||||
|
private fun getHolder(download: Download): DownloadHolder? {
|
||||||
|
return dl_recycler?.findViewHolderForItemId(download.chapter.id!!) as? DownloadHolder
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set information view when queue is empty
|
||||||
|
*/
|
||||||
|
private fun setInformationView() {
|
||||||
|
updateDLTitle()
|
||||||
|
setBottomSheet()
|
||||||
|
if (presenter.downloadQueue.isEmpty()) {
|
||||||
|
empty_view?.show(
|
||||||
|
R.drawable.ic_file_download_black_128dp,
|
||||||
|
R.string.nothing_downloading)
|
||||||
|
} else {
|
||||||
|
empty_view?.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun prepareMenu(menu: Menu) {
|
||||||
|
// Set start button visibility.
|
||||||
|
menu.findItem(R.id.start_queue)?.isVisible = !isRunning && !presenter.downloadQueue.isEmpty()
|
||||||
|
|
||||||
|
// Set pause button visibility.
|
||||||
|
menu.findItem(R.id.pause_queue)?.isVisible = isRunning && !presenter.downloadQueue.isEmpty()
|
||||||
|
|
||||||
|
// Set clear button visibility.
|
||||||
|
menu.findItem(R.id.clear_queue)?.isVisible = !presenter.downloadQueue.isEmpty()
|
||||||
|
|
||||||
|
// Set reorder button visibility.
|
||||||
|
menu.findItem(R.id.reorder)?.isVisible = !presenter.downloadQueue.isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
val context = activity ?: return false
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.start_queue -> DownloadService.start(context)
|
||||||
|
R.id.pause_queue -> {
|
||||||
|
DownloadService.stop(context)
|
||||||
|
presenter.pauseDownloads()
|
||||||
|
}
|
||||||
|
R.id.clear_queue -> {
|
||||||
|
DownloadService.stop(context)
|
||||||
|
presenter.clearQueue()
|
||||||
|
}
|
||||||
|
R.id.newest, R.id.oldest -> {
|
||||||
|
val adapter = adapter ?: return false
|
||||||
|
val items = adapter.currentItems.sortedBy { it.download.chapter.date_upload }
|
||||||
|
.toMutableList()
|
||||||
|
if (item.itemId == R.id.newest)
|
||||||
|
items.reverse()
|
||||||
|
adapter.updateDataSet(items)
|
||||||
|
val downloads = items.mapNotNull { it.download }
|
||||||
|
presenter.reorder(downloads)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dismiss() {
|
||||||
|
if (sheetBehavior?.isHideable == true) {
|
||||||
|
sheetBehavior?.state = BottomSheetBehavior.STATE_HIDDEN
|
||||||
|
} else {
|
||||||
|
sheetBehavior?.state = BottomSheetBehavior.STATE_COLLAPSED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setBottomSheet() {
|
||||||
|
val hasQueue = presenter.downloadQueue.isNotEmpty()
|
||||||
|
if (hasQueue) {
|
||||||
|
sheetBehavior?.skipCollapsed = !hasQueue
|
||||||
|
if (sheetBehavior?.state == BottomSheetBehavior.STATE_HIDDEN) sheetBehavior?.state =
|
||||||
|
BottomSheetBehavior.STATE_COLLAPSED
|
||||||
|
sheetBehavior?.isHideable = !hasQueue
|
||||||
|
} else {
|
||||||
|
sheetBehavior?.isHideable = !hasQueue
|
||||||
|
sheetBehavior?.skipCollapsed = !hasQueue
|
||||||
|
if (sheetBehavior?.state == BottomSheetBehavior.STATE_COLLAPSED) sheetBehavior?.state =
|
||||||
|
BottomSheetBehavior.STATE_HIDDEN
|
||||||
|
}
|
||||||
|
controller.setPadding(!hasQueue)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when an item is released from a drag.
|
||||||
|
*
|
||||||
|
* @param position The position of the released item.
|
||||||
|
*/
|
||||||
|
override fun onItemReleased(position: Int) {
|
||||||
|
val adapter = adapter ?: return
|
||||||
|
val downloads = (0 until adapter.itemCount).mapNotNull { adapter.getItem(it)?.download }
|
||||||
|
presenter.reorder(downloads)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemRemoved(position: Int) {
|
||||||
|
val download = adapter?.getItem(position)?.download ?: return
|
||||||
|
presenter.cancelDownload(download)
|
||||||
|
|
||||||
|
adapter?.removeItem(position)
|
||||||
|
val adapter = adapter ?: return
|
||||||
|
val downloads = (0 until adapter.itemCount).mapNotNull { adapter.getItem(it)?.download }
|
||||||
|
presenter.reorder(downloads)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the menu item of a download is pressed
|
||||||
|
*
|
||||||
|
* @param position The position of the item
|
||||||
|
* @param menuItem The menu Item pressed
|
||||||
|
*/
|
||||||
|
override fun onMenuItemClick(position: Int, menuItem: MenuItem) {
|
||||||
|
when (menuItem.itemId) {
|
||||||
|
R.id.move_to_top, R.id.move_to_bottom -> {
|
||||||
|
val items = adapter?.currentItems?.toMutableList() ?: return
|
||||||
|
val item = items[position]
|
||||||
|
items.remove(item)
|
||||||
|
if (menuItem.itemId == R.id.move_to_top)
|
||||||
|
items.add(0, item)
|
||||||
|
else
|
||||||
|
items.add(item)
|
||||||
|
adapter?.updateDataSet(items)
|
||||||
|
val downloads = items.mapNotNull { it.download }
|
||||||
|
presenter.reorder(downloads)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -299,15 +299,9 @@ class DownloadController : NucleusController<DownloadPresenter>(),
|
|||||||
val downloads = items.mapNotNull { it.download }
|
val downloads = items.mapNotNull { it.download }
|
||||||
presenter.reorder(downloads)
|
presenter.reorder(downloads)
|
||||||
}
|
}
|
||||||
R.id.cancel_download -> {
|
|
||||||
val download = adapter?.getItem(position)?.download ?: return
|
|
||||||
presenter.cancelDownload(download)
|
|
||||||
|
|
||||||
adapter?.removeItem(position)
|
|
||||||
val adapter = adapter ?: return
|
|
||||||
val downloads = (0 until adapter.itemCount).mapNotNull { adapter.getItem(it)?.download }
|
|
||||||
presenter.reorder(downloads)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onItemRemoved(position: Int) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ class DownloadHolder(private val view: View, val adapter: DownloadAdapter) :
|
|||||||
if (download_progress.max == 1) {
|
if (download_progress.max == 1) {
|
||||||
download_progress.max = pages.size * 100
|
download_progress.max = pages.size * 100
|
||||||
}
|
}
|
||||||
download_progress.progress = download.totalProgress
|
download_progress.progress = download.pageProgress
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,4 +104,16 @@ class DownloadHolder(private val view: View, val adapter: DownloadAdapter) :
|
|||||||
// Finally show the PopupMenu
|
// Finally show the PopupMenu
|
||||||
popup.show()
|
popup.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getFrontView(): View {
|
||||||
|
return front_view
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getRearRightView(): View {
|
||||||
|
return right_view
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getRearLeftView(): View {
|
||||||
|
return left_view
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ ExtensionAdapter.OnButtonClickListener,
|
|||||||
var shouldCallApi = false
|
var shouldCallApi = false
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapter containing the list of manga from the catalogue.
|
* Adapter containing the list of extensions
|
||||||
*/
|
*/
|
||||||
private var adapter: FlexibleAdapter<IFlexible<*>>? = null
|
private var adapter: FlexibleAdapter<IFlexible<*>>? = null
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ import com.google.android.material.snackbar.Snackbar
|
|||||||
import eu.kanade.tachiyomi.BuildConfig
|
import eu.kanade.tachiyomi.BuildConfig
|
||||||
import eu.kanade.tachiyomi.Migrations
|
import eu.kanade.tachiyomi.Migrations
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadService
|
import eu.kanade.tachiyomi.data.download.DownloadService
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadServiceListener
|
import eu.kanade.tachiyomi.data.download.DownloadServiceListener
|
||||||
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
||||||
@ -67,6 +68,8 @@ import kotlinx.coroutines.GlobalScope
|
|||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import uy.kohesive.injekt.Injekt
|
||||||
|
import uy.kohesive.injekt.api.get
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
@ -79,6 +82,7 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
|
|||||||
var drawerArrow: DrawerArrowDrawable? = null
|
var drawerArrow: DrawerArrowDrawable? = null
|
||||||
private set
|
private set
|
||||||
private var searchDrawable: Drawable? = null
|
private var searchDrawable: Drawable? = null
|
||||||
|
private var dismissDrawable: Drawable? = null
|
||||||
private var currentGestureDelegate: SwipeGestureInterface? = null
|
private var currentGestureDelegate: SwipeGestureInterface? = null
|
||||||
private lateinit var gestureDetector: GestureDetectorCompat
|
private lateinit var gestureDetector: GestureDetectorCompat
|
||||||
|
|
||||||
@ -129,6 +133,9 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
|
|||||||
searchDrawable = ContextCompat.getDrawable(
|
searchDrawable = ContextCompat.getDrawable(
|
||||||
this, R.drawable.ic_search_white_24dp
|
this, R.drawable.ic_search_white_24dp
|
||||||
)
|
)
|
||||||
|
dismissDrawable = ContextCompat.getDrawable(
|
||||||
|
this, R.drawable.ic_close_white_24dp
|
||||||
|
)
|
||||||
|
|
||||||
var continueSwitchingTabs = false
|
var continueSwitchingTabs = false
|
||||||
bottom_nav.setOnNavigationItemSelectedListener { item ->
|
bottom_nav.setOnNavigationItemSelectedListener { item ->
|
||||||
@ -152,12 +159,11 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
|
|||||||
} else if (currentRoot.tag()?.toIntOrNull() == id) {
|
} else if (currentRoot.tag()?.toIntOrNull() == id) {
|
||||||
if (router.backstackSize == 1) {
|
if (router.backstackSize == 1) {
|
||||||
when (id) {
|
when (id) {
|
||||||
/*R.id.nav_recents -> {
|
R.id.nav_recents -> {
|
||||||
val showRecents = preferences.showRecentUpdates().getOrDefault()
|
val controller =
|
||||||
if (!showRecents) setRoot(RecentChaptersController(), id)
|
router.getControllerWithTag(id.toString()) as? RecentsController
|
||||||
else setRoot(RecentlyReadController(), id)
|
controller?.toggleDownloads()
|
||||||
preferences.showRecentUpdates().set(!showRecents)
|
}
|
||||||
}*/
|
|
||||||
R.id.nav_library -> {
|
R.id.nav_library -> {
|
||||||
val controller =
|
val controller =
|
||||||
router.getControllerWithTag(id.toString()) as? LibraryController
|
router.getControllerWithTag(id.toString()) as? LibraryController
|
||||||
@ -215,7 +221,7 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
|
|||||||
toolbar.setNavigationOnClickListener {
|
toolbar.setNavigationOnClickListener {
|
||||||
val rootSearchController = router.backstack.lastOrNull()?.controller()
|
val rootSearchController = router.backstack.lastOrNull()?.controller()
|
||||||
if (rootSearchController is RootSearchInterface) {
|
if (rootSearchController is RootSearchInterface) {
|
||||||
toolbar.menu.findItem(R.id.action_search)?.expandActionView()
|
rootSearchController.expandSearch()
|
||||||
} else onBackPressed()
|
} else onBackPressed()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,6 +273,10 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
|
|||||||
setExtensionsBadge()
|
setExtensionsBadge()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setDismissIcon(enabled: Boolean) {
|
||||||
|
toolbar.navigationIcon = if (enabled) dismissDrawable else searchDrawable
|
||||||
|
}
|
||||||
|
|
||||||
private fun setNavBarColor(insets: WindowInsets?) {
|
private fun setNavBarColor(insets: WindowInsets?) {
|
||||||
if (insets == null) return
|
if (insets == null) return
|
||||||
window.navigationBarColor = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) {
|
window.navigationBarColor = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) {
|
||||||
@ -309,8 +319,8 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
|
|||||||
delay(100)
|
delay(100)
|
||||||
if (Color.alpha(window?.statusBarColor ?: Color.BLACK) >= 255) window?.statusBarColor =
|
if (Color.alpha(window?.statusBarColor ?: Color.BLACK) >= 255) window?.statusBarColor =
|
||||||
getResourceColor(
|
getResourceColor(
|
||||||
android.R.attr.statusBarColor
|
android.R.attr.statusBarColor
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
super.onSupportActionModeFinished(mode)
|
super.onSupportActionModeFinished(mode)
|
||||||
}
|
}
|
||||||
@ -554,17 +564,15 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun downloadStatusChanged(downloading: Boolean) {
|
override fun downloadStatusChanged(downloading: Boolean) {
|
||||||
/*val downloadManager = Injekt.get<DownloadManager>()
|
val downloadManager = Injekt.get<DownloadManager>()
|
||||||
val hasQueue = downloading || downloadManager.hasQueue()
|
val hasQueue = downloading || downloadManager.hasQueue()
|
||||||
launchUI {
|
launchUI {
|
||||||
if (hasQueue) {
|
if (hasQueue) {
|
||||||
val badge = navigationView?.getOrCreateBadge(R.id.nav_library) ?: return@launchUI
|
bottom_nav?.getOrCreateBadge(R.id.nav_recents)
|
||||||
badge.clearNumber()
|
|
||||||
badge.backgroundColor = getResourceColor(R.attr.badgeColor)
|
|
||||||
} else {
|
} else {
|
||||||
navigationView?.removeBadge(R.id.nav_library)
|
bottom_nav?.removeBadge(R.id.nav_recents)
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class GestureListener : GestureDetector.SimpleOnGestureListener() {
|
private inner class GestureListener : GestureDetector.SimpleOnGestureListener() {
|
||||||
@ -638,7 +646,12 @@ interface BottomNavBarInterface {
|
|||||||
fun canChangeTabs(block: () -> Unit): Boolean
|
fun canChangeTabs(block: () -> Unit): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RootSearchInterface
|
interface RootSearchInterface {
|
||||||
|
fun expandSearch() {
|
||||||
|
if (this is Controller) activity?.toolbar?.menu?.findItem(R.id.action_search)?.expandActionView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface SpinnerTitleInterface
|
interface SpinnerTitleInterface
|
||||||
|
|
||||||
interface OnTouchEventInterface {
|
interface OnTouchEventInterface {
|
||||||
|
@ -16,6 +16,7 @@ class SearchActivity : MainActivity() {
|
|||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
toolbar.navigationIcon = drawerArrow
|
||||||
toolbar.setNavigationOnClickListener {
|
toolbar.setNavigationOnClickListener {
|
||||||
popToRoot()
|
popToRoot()
|
||||||
}
|
}
|
||||||
|
@ -347,10 +347,10 @@ class MangaDetailsController : BaseController,
|
|||||||
android.R.attr.colorBackground
|
android.R.attr.colorBackground
|
||||||
)
|
)
|
||||||
val backDropColor =
|
val backDropColor =
|
||||||
(if (currentNightMode == Configuration.UI_MODE_NIGHT_NO) it?.getLightMutedColor(
|
(if (currentNightMode == Configuration.UI_MODE_NIGHT_NO) it?.getLightVibrantColor(
|
||||||
colorBack
|
colorBack
|
||||||
)
|
)
|
||||||
else it?.getDarkMutedColor(colorBack)) ?: colorBack
|
else it?.getDarkVibrantColor(colorBack)) ?: colorBack
|
||||||
coverColor = backDropColor
|
coverColor = backDropColor
|
||||||
(recycler.findViewHolderForAdapterPosition(0) as? MangaHeaderHolder)
|
(recycler.findViewHolderForAdapterPosition(0) as? MangaHeaderHolder)
|
||||||
?.setBackDrop(backDropColor)
|
?.setBackDrop(backDropColor)
|
||||||
|
@ -14,6 +14,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|||||||
import com.bluelinelabs.conductor.Controller
|
import com.bluelinelabs.conductor.Controller
|
||||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||||
import com.bluelinelabs.conductor.ControllerChangeType
|
import com.bluelinelabs.conductor.ControllerChangeType
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.snackbar.BaseTransientBottomBar
|
import com.google.android.material.snackbar.BaseTransientBottomBar
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
@ -29,12 +30,18 @@ import eu.kanade.tachiyomi.ui.manga.MangaDetailsController
|
|||||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||||
import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersController
|
import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersController
|
||||||
import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadController
|
import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadController
|
||||||
|
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||||
import eu.kanade.tachiyomi.util.view.applyWindowInsetsForRootController
|
import eu.kanade.tachiyomi.util.view.applyWindowInsetsForRootController
|
||||||
import eu.kanade.tachiyomi.util.view.scrollViewWith
|
import eu.kanade.tachiyomi.util.view.scrollViewWith
|
||||||
import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener
|
import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener
|
||||||
import eu.kanade.tachiyomi.util.view.snack
|
import eu.kanade.tachiyomi.util.view.snack
|
||||||
|
import eu.kanade.tachiyomi.util.view.updateLayoutParams
|
||||||
|
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
|
||||||
|
import kotlinx.android.synthetic.main.download_bottom_sheet.*
|
||||||
import kotlinx.android.synthetic.main.main_activity.*
|
import kotlinx.android.synthetic.main.main_activity.*
|
||||||
import kotlinx.android.synthetic.main.recently_read_controller.*
|
import kotlinx.android.synthetic.main.recents_controller.*
|
||||||
|
import kotlin.math.abs
|
||||||
|
import kotlin.math.max
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fragment that shows recently read manga.
|
* Fragment that shows recently read manga.
|
||||||
@ -59,13 +66,17 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
private var recentItems: List<RecentMangaItem>? = null
|
private var recentItems: List<RecentMangaItem>? = null
|
||||||
private var snack: Snackbar? = null
|
private var snack: Snackbar? = null
|
||||||
private var lastChapterId: Long? = null
|
private var lastChapterId: Long? = null
|
||||||
|
private var showingDownloads = false
|
||||||
|
var headerHeight = 0
|
||||||
|
|
||||||
override fun getTitle(): String? {
|
override fun getTitle(): String? {
|
||||||
return resources?.getString(R.string.short_recents)
|
return if (showingDownloads)
|
||||||
|
resources?.getString(R.string.label_download_queue)
|
||||||
|
else resources?.getString(R.string.short_recents)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||||
return inflater.inflate(R.layout.recently_read_controller, container, false)
|
return inflater.inflate(R.layout.recents_controller, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -86,16 +97,90 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
adapter.itemTouchHelperCallback.setSwipeFlags(
|
adapter.itemTouchHelperCallback.setSwipeFlags(
|
||||||
ItemTouchHelper.LEFT
|
ItemTouchHelper.LEFT
|
||||||
)
|
)
|
||||||
scrollViewWith(recycler, skipFirstSnap = true)
|
val attrsArray = intArrayOf(android.R.attr.actionBarSize)
|
||||||
|
val array = view.context.obtainStyledAttributes(attrsArray)
|
||||||
|
val appBarHeight = array.getDimensionPixelSize(0, 0)
|
||||||
|
array.recycle()
|
||||||
|
scrollViewWith(recycler, skipFirstSnap = true) {
|
||||||
|
headerHeight = it.systemWindowInsetTop + appBarHeight
|
||||||
|
}
|
||||||
|
|
||||||
if (recentItems != null) adapter.updateDataSet(recentItems!!.toList())
|
if (recentItems != null) adapter.updateDataSet(recentItems!!.toList())
|
||||||
presenter.onCreate()
|
presenter.onCreate()
|
||||||
|
|
||||||
|
dl_bottom_sheet.onCreate(this)
|
||||||
|
|
||||||
|
shadow2.alpha =
|
||||||
|
if (dl_bottom_sheet.sheetBehavior?.state == BottomSheetBehavior.STATE_COLLAPSED) 0.25f else 0f
|
||||||
|
shadow.alpha =
|
||||||
|
if (dl_bottom_sheet.sheetBehavior?.state == BottomSheetBehavior.STATE_COLLAPSED) 0.5f else 0f
|
||||||
|
|
||||||
|
dl_bottom_sheet.sheetBehavior?.addBottomSheetCallback(object :
|
||||||
|
BottomSheetBehavior.BottomSheetCallback() {
|
||||||
|
override fun onSlide(bottomSheet: View, progress: Float) {
|
||||||
|
shadow2.alpha = (1 - abs(progress)) * 0.25f
|
||||||
|
shadow.alpha = (1 - abs(progress)) * 0.5f
|
||||||
|
sheet_layout.alpha = 1 - progress
|
||||||
|
activity?.appbar?.y = max(activity!!.appbar.y, -headerHeight * (1 - progress))
|
||||||
|
val oldShow = showingDownloads
|
||||||
|
showingDownloads = progress > 0.92f
|
||||||
|
if (oldShow != showingDownloads) {
|
||||||
|
setTitle()
|
||||||
|
activity?.invalidateOptionsMenu()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStateChanged(p0: View, state: Int) {
|
||||||
|
if (this@RecentsController.view == null) return
|
||||||
|
if (state == BottomSheetBehavior.STATE_EXPANDED) activity?.appbar?.y = 0f
|
||||||
|
if (state == BottomSheetBehavior.STATE_EXPANDED || state == BottomSheetBehavior.STATE_COLLAPSED) {
|
||||||
|
sheet_layout.alpha =
|
||||||
|
if (state == BottomSheetBehavior.STATE_COLLAPSED) 1f else 0f
|
||||||
|
showingDownloads = state == BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
setTitle()
|
||||||
|
activity?.invalidateOptionsMenu()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == BottomSheetBehavior.STATE_HIDDEN || state == BottomSheetBehavior.STATE_COLLAPSED) {
|
||||||
|
shadow2.alpha = if (state == BottomSheetBehavior.STATE_COLLAPSED) 0.25f else 0f
|
||||||
|
shadow.alpha = if (state == BottomSheetBehavior.STATE_COLLAPSED) 0.5f else 0f
|
||||||
|
}
|
||||||
|
|
||||||
|
retainViewMode =
|
||||||
|
if (state == BottomSheetBehavior.STATE_EXPANDED) RetainViewMode.RETAIN_DETACH else RetainViewMode.RELEASE_DETACH
|
||||||
|
sheet_layout?.isClickable = state == BottomSheetBehavior.STATE_COLLAPSED
|
||||||
|
sheet_layout?.isFocusable = state == BottomSheetBehavior.STATE_COLLAPSED
|
||||||
|
setPadding(dl_bottom_sheet.sheetBehavior?.isHideable == true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (showingDownloads) {
|
||||||
|
dl_bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
}
|
||||||
|
setPadding(dl_bottom_sheet.sheetBehavior?.isHideable == true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handleRootBack(): Boolean {
|
||||||
|
if (dl_bottom_sheet.sheetBehavior?.state == BottomSheetBehavior.STATE_EXPANDED) {
|
||||||
|
dl_bottom_sheet.dismiss()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setPadding(sheetIsHidden: Boolean) {
|
||||||
|
recycler.updatePaddingRelative(bottom = if (sheetIsHidden) 0 else 20.dpToPx)
|
||||||
|
recycler.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||||
|
bottomMargin = if (sheetIsHidden) 0 else 30.dpToPx
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityResumed(activity: Activity) {
|
override fun onActivityResumed(activity: Activity) {
|
||||||
super.onActivityResumed(activity)
|
super.onActivityResumed(activity)
|
||||||
if (view != null)
|
if (view != null) {
|
||||||
refresh()
|
refresh()
|
||||||
|
dl_bottom_sheet?.update()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
@ -118,6 +203,9 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
|
|
||||||
fun updateChapterDownload(download: Download) {
|
fun updateChapterDownload(download: Download) {
|
||||||
if (view == null) return
|
if (view == null) return
|
||||||
|
dl_bottom_sheet.update()
|
||||||
|
dl_bottom_sheet.onUpdateProgress(download)
|
||||||
|
dl_bottom_sheet.onUpdateDownloadedPages(download)
|
||||||
val id = download.chapter.id ?: return
|
val id = download.chapter.id ?: return
|
||||||
val holder = recycler.findViewHolderForItemId(id) as? RecentMangaHolder ?: return
|
val holder = recycler.findViewHolderForItemId(id) as? RecentMangaHolder ?: return
|
||||||
holder.notifyStatus(download.status, download.progress)
|
holder.notifyStatus(download.status, download.progress)
|
||||||
@ -204,30 +292,38 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
override fun isSearching() = presenter.query.isNotEmpty()
|
override fun isSearching() = presenter.query.isNotEmpty()
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
inflater.inflate(R.menu.recents, menu)
|
(activity as? MainActivity)?.setDismissIcon(showingDownloads)
|
||||||
val searchItem = menu.findItem(R.id.action_search)
|
if (showingDownloads) {
|
||||||
val searchView = searchItem.actionView as SearchView
|
inflater.inflate(R.menu.download_queue, menu)
|
||||||
searchView.queryHint = view?.context?.getString(R.string.search_recents)
|
} else {
|
||||||
if (presenter.query.isNotEmpty()) {
|
inflater.inflate(R.menu.recents, menu)
|
||||||
searchItem.expandActionView()
|
val searchItem = menu.findItem(R.id.action_search)
|
||||||
searchView.setQuery(presenter.query, true)
|
val searchView = searchItem.actionView as SearchView
|
||||||
searchView.clearFocus()
|
searchView.queryHint = view?.context?.getString(R.string.search_recents)
|
||||||
}
|
if (presenter.query.isNotEmpty()) {
|
||||||
setOnQueryTextChangeListener(searchView) {
|
searchItem.expandActionView()
|
||||||
if (presenter.query != it) {
|
searchView.setQuery(presenter.query, true)
|
||||||
presenter.query = it ?: return@setOnQueryTextChangeListener false
|
searchView.clearFocus()
|
||||||
refresh()
|
}
|
||||||
|
setOnQueryTextChangeListener(searchView) {
|
||||||
|
if (presenter.query != it) {
|
||||||
|
presenter.query = it ?: return@setOnQueryTextChangeListener false
|
||||||
|
refresh()
|
||||||
|
}
|
||||||
|
true
|
||||||
}
|
}
|
||||||
true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||||
|
super.onPrepareOptionsMenu(menu)
|
||||||
|
if (showingDownloads) dl_bottom_sheet.prepareMenu(menu)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) {
|
override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) {
|
||||||
super.onChangeStarted(handler, type)
|
super.onChangeStarted(handler, type)
|
||||||
if (type.isEnter) {
|
if (type.isEnter) {
|
||||||
if (type == ControllerChangeType.POP_EXIT) {
|
if (type == ControllerChangeType.POP_EXIT) presenter.onCreate()
|
||||||
presenter.onCreate()
|
|
||||||
}
|
|
||||||
setHasOptionsMenu(true)
|
setHasOptionsMenu(true)
|
||||||
} else {
|
} else {
|
||||||
snack?.dismiss()
|
snack?.dismiss()
|
||||||
@ -235,7 +331,23 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun toggleDownloads() {
|
||||||
|
if (dl_bottom_sheet.sheetBehavior?.isHideable == false) {
|
||||||
|
if (showingDownloads) dl_bottom_sheet.dismiss()
|
||||||
|
else dl_bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun expandSearch() {
|
||||||
|
if (showingDownloads) {
|
||||||
|
dl_bottom_sheet.dismiss()
|
||||||
|
} else
|
||||||
|
activity?.toolbar?.menu?.findItem(R.id.action_search)?.expandActionView()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
if (showingDownloads)
|
||||||
|
return dl_bottom_sheet.onOptionsItemSelected(item)
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.action_refresh -> {
|
R.id.action_refresh -> {
|
||||||
if (!LibraryUpdateService.isRunning()) {
|
if (!LibraryUpdateService.isRunning()) {
|
||||||
|
@ -4,6 +4,7 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
|||||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||||
import eu.kanade.tachiyomi.data.database.models.LibraryManga
|
import eu.kanade.tachiyomi.data.database.models.LibraryManga
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
import eu.kanade.tachiyomi.data.download.model.Download
|
import eu.kanade.tachiyomi.data.download.model.Download
|
||||||
import eu.kanade.tachiyomi.data.download.model.DownloadQueue
|
import eu.kanade.tachiyomi.data.download.model.DownloadQueue
|
||||||
@ -22,6 +23,8 @@ import uy.kohesive.injekt.Injekt
|
|||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
class RecentsPresenter(
|
class RecentsPresenter(
|
||||||
val controller: RecentsController,
|
val controller: RecentsController,
|
||||||
@ -87,7 +90,13 @@ class RecentsPresenter(
|
|||||||
if (query.isEmpty()) {
|
if (query.isEmpty()) {
|
||||||
val nChaptersItems =
|
val nChaptersItems =
|
||||||
pairs.filter { it.first.history.id == null && it.first.chapter.id != null }
|
pairs.filter { it.first.history.id == null && it.first.chapter.id != null }
|
||||||
.sortedByDescending { it.second.date_upload }
|
.sortedWith(Comparator<Pair<MangaChapterHistory, Chapter>> { f1, f2 ->
|
||||||
|
if (abs(f1.second.date_fetch - f2.second.date_fetch) <=
|
||||||
|
TimeUnit.HOURS.toMillis(2))
|
||||||
|
f2.second.date_upload.compareTo(f1.second.date_upload)
|
||||||
|
else
|
||||||
|
f2.second.date_fetch.compareTo(f1.second.date_fetch)
|
||||||
|
})
|
||||||
.take(4).map {
|
.take(4).map {
|
||||||
RecentMangaItem(
|
RecentMangaItem(
|
||||||
it.first,
|
it.first,
|
||||||
|
@ -17,8 +17,6 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
|||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
|
||||||
import eu.kanade.tachiyomi.ui.download.DownloadController
|
|
||||||
import eu.kanade.tachiyomi.util.system.getFilePicker
|
import eu.kanade.tachiyomi.util.system.getFilePicker
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
@ -33,13 +31,6 @@ class SettingsDownloadController : SettingsController() {
|
|||||||
override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) {
|
override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) {
|
||||||
titleRes = R.string.pref_category_downloads
|
titleRes = R.string.pref_category_downloads
|
||||||
|
|
||||||
preference {
|
|
||||||
titleRes = R.string.label_download_queue
|
|
||||||
onClick {
|
|
||||||
router.pushController(DownloadController().withFadeTransaction())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
preference {
|
preference {
|
||||||
key = Keys.downloadsDirectory
|
key = Keys.downloadsDirectory
|
||||||
titleRes = R.string.pref_download_directory
|
titleRes = R.string.pref_download_directory
|
||||||
|
78
app/src/main/res/layout/download_bottom_sheet.xml
Normal file
78
app/src/main/res/layout/download_bottom_sheet.xml
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<eu.kanade.tachiyomi.ui.download.DownloadBottomSheet 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/dl_bottom_sheet"
|
||||||
|
style="@style/BottomSheetDialogTheme"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@drawable/bg_bottom_sheet_dialog_fragment"
|
||||||
|
android:backgroundTint="?android:attr/colorBackground"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:behavior_peekHeight="48sp"
|
||||||
|
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/sheet_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:background="@drawable/bg_bottom_sheet_dialog_fragment"
|
||||||
|
android:backgroundTint="?attr/colorPrimaryVariant"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/pill"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:alpha="0.25"
|
||||||
|
android:contentDescription="@string/drag_handle"
|
||||||
|
android:src="@drawable/draggable_pill"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/title_text"
|
||||||
|
style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
|
android:layout_marginTop="6dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:gravity="center"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textColor="?actionBarTintColor"
|
||||||
|
android:textSize="18sp"
|
||||||
|
tools:text="Downloads" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:background="?android:attr/colorBackground"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/dl_recycler"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
tools:listitem="@layout/download_item"/>
|
||||||
|
|
||||||
|
<eu.kanade.tachiyomi.widget.EmptyView
|
||||||
|
android:id="@+id/empty_view"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
</FrameLayout>
|
||||||
|
</eu.kanade.tachiyomi.ui.download.DownloadBottomSheet>
|
@ -1,88 +1,127 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout 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:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingStart="0dp"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:paddingTop="@dimen/material_component_lists_padding_above_list">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<ImageView
|
<FrameLayout
|
||||||
android:id="@+id/reorder"
|
android:id="@+id/right_view"
|
||||||
android:layout_width="@dimen/material_component_lists_single_line_with_avatar_height"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="match_parent"
|
||||||
android:layout_alignParentStart="true"
|
android:visibility="gone"
|
||||||
android:layout_gravity="start"
|
android:background="@color/red_error">
|
||||||
android:contentDescription="@string/action_reorganize_by"
|
|
||||||
android:scaleType="center"
|
|
||||||
android:tint="?android:attr/textColorPrimary"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:srcCompat="@drawable/ic_reorder_grey_24dp" />
|
|
||||||
|
|
||||||
<TextView
|
<ImageView
|
||||||
android:id="@+id/manga_full_title"
|
android:id="@+id/close_right"
|
||||||
android:layout_width="0dp"
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:tint="@color/md_white_1000"
|
||||||
|
android:layout_gravity="end|center"
|
||||||
|
android:layout_marginEnd="21dp"
|
||||||
|
android:src="@drawable/ic_close_white_24dp" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/left_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:background="@color/red_error">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/close_left"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_gravity="start|center"
|
||||||
|
android:layout_marginStart="21dp"
|
||||||
|
android:tint="@color/md_white_1000"
|
||||||
|
android:src="@drawable/ic_close_white_24dp" />
|
||||||
|
</FrameLayout>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:id="@+id/front_view"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="8dp"
|
android:background="?android:attr/colorBackground"
|
||||||
android:layout_toEndOf="@id/reorder"
|
android:paddingTop="@dimen/material_component_lists_padding_above_list">
|
||||||
android:ellipsize="end"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:textAppearance="@style/TextAppearance.Regular.Body1"
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/download_progress_text"
|
|
||||||
app:layout_constraintStart_toEndOf="@+id/reorder"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:text="Manga title" />
|
|
||||||
|
|
||||||
<TextView
|
<ImageView
|
||||||
android:id="@+id/chapter_title"
|
android:id="@+id/reorder"
|
||||||
android:layout_width="0dp"
|
android:layout_width="@dimen/material_component_lists_single_line_with_avatar_height"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="0dp"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_toEndOf="@id/reorder"
|
android:layout_gravity="start"
|
||||||
android:ellipsize="end"
|
android:contentDescription="@string/action_reorganize_by"
|
||||||
android:maxLines="1"
|
android:scaleType="center"
|
||||||
android:textAppearance="@style/TextAppearance.Regular.Caption"
|
android:tint="?android:attr/textColorPrimary"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/migration_menu"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="@+id/manga_full_title"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/manga_full_title"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:text="Chapter Title" />
|
app:srcCompat="@drawable/ic_reorder_grey_24dp" />
|
||||||
|
|
||||||
<ProgressBar
|
<TextView
|
||||||
android:id="@+id/download_progress"
|
android:id="@+id/manga_full_title"
|
||||||
style="?android:attr/progressBarStyleHorizontal"
|
android:layout_width="0dp"
|
||||||
android:layout_width="0dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_toEndOf="@id/reorder"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
android:ellipsize="end"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/migration_menu"
|
android:maxLines="1"
|
||||||
app:layout_constraintStart_toEndOf="@+id/reorder"
|
android:textAppearance="@style/TextAppearance.Regular.Body1"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/chapter_title" />
|
app:layout_constraintEnd_toStartOf="@+id/download_progress_text"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/reorder"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="Manga title" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/download_progress_text"
|
android:id="@+id/chapter_title"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_toEndOf="@id/manga_full_title"
|
android:layout_marginTop="4dp"
|
||||||
android:maxLines="1"
|
android:layout_toEndOf="@id/reorder"
|
||||||
android:textAppearance="@style/TextAppearance.Regular.Caption.Hint"
|
android:ellipsize="end"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/manga_full_title"
|
android:maxLines="1"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/migration_menu"
|
android:textAppearance="@style/TextAppearance.Regular.Caption"
|
||||||
app:layout_constraintTop_toTopOf="@+id/manga_full_title"
|
app:layout_constraintEnd_toStartOf="@+id/migration_menu"
|
||||||
tools:text="(0/10)" />
|
app:layout_constraintStart_toStartOf="@+id/manga_full_title"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/manga_full_title"
|
||||||
|
tools:text="Chapter Title" />
|
||||||
|
|
||||||
<ImageView
|
<ProgressBar
|
||||||
android:id="@+id/migration_menu"
|
android:id="@+id/download_progress"
|
||||||
android:layout_width="44dp"
|
style="?android:attr/progressBarStyleHorizontal"
|
||||||
android:paddingStart="10dp"
|
android:layout_width="0dp"
|
||||||
android:paddingEnd="10dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="@dimen/material_component_lists_single_line_with_avatar_height"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_toEndOf="@id/download_progress_text"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
android:contentDescription="@string/description_cover"
|
app:layout_constraintEnd_toStartOf="@+id/migration_menu"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintStart_toEndOf="@+id/reorder"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintTop_toBottomOf="@+id/chapter_title" />
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:srcCompat="@drawable/ic_more_vert_black_24dp" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
<TextView
|
||||||
|
android:id="@+id/download_progress_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_toEndOf="@id/manga_full_title"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textAppearance="@style/TextAppearance.Regular.Caption.Hint"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/manga_full_title"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/migration_menu"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/manga_full_title"
|
||||||
|
tools:text="(0/10)" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/migration_menu"
|
||||||
|
android:layout_width="44dp"
|
||||||
|
android:layout_height="@dimen/material_component_lists_single_line_with_avatar_height"
|
||||||
|
android:layout_toEndOf="@id/download_progress_text"
|
||||||
|
android:contentDescription="@string/description_cover"
|
||||||
|
android:paddingStart="10dp"
|
||||||
|
android:paddingEnd="10dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:srcCompat="@drawable/ic_more_vert_black_24dp" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</FrameLayout>
|
43
app/src/main/res/layout/recents_controller.xml
Normal file
43
app/src/main/res/layout/recents_controller.xml
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/recents_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/frame_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="?android:attr/colorBackground">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recycler"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
tools:listitem="@layout/catalogue_main_controller_card" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/shadow"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:alpha="0.5"
|
||||||
|
android:background="@drawable/shape_gradient_top_shadow"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
|
app:layout_anchorGravity="top"
|
||||||
|
app:layout_anchor="@id/dl_bottom_sheet" />
|
||||||
|
<!-- Adding bottom sheet after main content -->
|
||||||
|
<include layout="@layout/download_bottom_sheet"/>
|
||||||
|
|
||||||
|
<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" />
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
@ -15,6 +15,7 @@
|
|||||||
android:layout_marginTop="6dp"
|
android:layout_marginTop="6dp"
|
||||||
android:layout_marginBottom="12dp"
|
android:layout_marginBottom="12dp"
|
||||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
|
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
|
||||||
|
android:fontFamily="sans-serif-medium"
|
||||||
app:layout_constraintStart_toEndOf="@id/arrow"
|
app:layout_constraintStart_toEndOf="@id/arrow"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
android:textColor="?colorAccent"
|
android:textColor="?colorAccent"
|
||||||
|
@ -5,7 +5,4 @@
|
|||||||
|
|
||||||
<item android:id="@+id/move_to_bottom"
|
<item android:id="@+id/move_to_bottom"
|
||||||
android:title="@string/action_move_to_bottom" />
|
android:title="@string/action_move_to_bottom" />
|
||||||
|
|
||||||
<item android:id="@+id/cancel_download"
|
|
||||||
android:title="@string/action_cancel" />
|
|
||||||
</menu>
|
</menu>
|
@ -4,7 +4,6 @@
|
|||||||
<item
|
<item
|
||||||
android:id="@+id/action_search"
|
android:id="@+id/action_search"
|
||||||
android:icon="@drawable/ic_search_white_24dp"
|
android:icon="@drawable/ic_search_white_24dp"
|
||||||
android:visible="false"
|
|
||||||
android:title="@string/action_search"
|
android:title="@string/action_search"
|
||||||
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
||||||
app:showAsAction="collapseActionView|ifRoom" />
|
app:showAsAction="collapseActionView|ifRoom" />
|
||||||
@ -22,11 +21,4 @@
|
|||||||
android:visible="false"
|
android:visible="false"
|
||||||
android:checkable="true"
|
android:checkable="true"
|
||||||
app:showAsAction="never"/>
|
app:showAsAction="never"/>
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_dismiss"
|
|
||||||
android:title="@string/action_dismiss"
|
|
||||||
android:icon="@drawable/ic_close_white_24dp"
|
|
||||||
app:showAsAction="always"/>
|
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
<item quantity="one">Extension update available</item>
|
<item quantity="one">Extension update available</item>
|
||||||
<item quantity="other">%d extension updates available</item>
|
<item quantity="other">%d extension updates available</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<string name="downloading_x">Downloading: %1$s</string>
|
||||||
<plurals name="downloads_pending">
|
<plurals name="downloads_pending">
|
||||||
<item quantity="one">1 in queue</item>
|
<item quantity="one">1 in queue</item>
|
||||||
<item quantity="other">%d in queue</item>
|
<item quantity="other">%d in queue</item>
|
||||||
@ -708,6 +709,7 @@
|
|||||||
|
|
||||||
<!-- Information Text -->
|
<!-- Information Text -->
|
||||||
<string name="information_no_downloads">No downloads</string>
|
<string name="information_no_downloads">No downloads</string>
|
||||||
|
<string name="nothing_downloading">Nothing currently downloading</string>
|
||||||
<string name="information_no_recent">No recent chapters</string>
|
<string name="information_no_recent">No recent chapters</string>
|
||||||
<string name="information_no_recent_manga">No recently read manga</string>
|
<string name="information_no_recent_manga">No recently read manga</string>
|
||||||
<string name="information_empty_library">Your library is empty, add series to your library from the catalogues.</string>
|
<string name="information_empty_library">Your library is empty, add series to your library from the catalogues.</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user