mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-09 19:55:11 +01:00
Added new Manga controller to library
This commit is contained in:
parent
2d66185a02
commit
c2b1c3f63f
@ -119,6 +119,7 @@ dependencies {
|
||||
implementation 'androidx.annotation:annotation:1.1.0'
|
||||
implementation 'androidx.browser:browser:1.2.0'
|
||||
implementation 'androidx.biometric:biometric:1.0.1'
|
||||
implementation 'androidx.palette:palette:1.0.0'
|
||||
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
|
||||
|
@ -0,0 +1,77 @@
|
||||
package eu.kanade.tachiyomi.ui.download
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.util.AttributeSet
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import eu.kanade.tachiyomi.util.view.gone
|
||||
import eu.kanade.tachiyomi.util.view.visible
|
||||
import kotlinx.android.synthetic.main.download_button.view.*
|
||||
|
||||
class DownloadButton @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
|
||||
: FrameLayout(context, attrs) {
|
||||
|
||||
private val activeColor = context.getResourceColor(R.attr.colorAccent)
|
||||
private val disabledColor = ContextCompat.getColor(context,
|
||||
R.color.material_on_surface_disabled)
|
||||
private val downloadedColor = ContextCompat.getColor(context,
|
||||
R.color.material_green_800)
|
||||
private val errorColor = ContextCompat.getColor(context,
|
||||
R.color.red_error)
|
||||
private val filledCircle = ContextCompat.getDrawable(context,
|
||||
R.drawable.filled_circle)?.mutate()
|
||||
private val borderCircle = ContextCompat.getDrawable(context,
|
||||
R.drawable.border_circle)?.mutate()
|
||||
|
||||
|
||||
fun setDownoadStatus(state: Int, progress: Int = 0) {
|
||||
when (state) {
|
||||
Download.NOT_DOWNLOADED -> {
|
||||
download_border.visible()
|
||||
download_progress.gone()
|
||||
download_progress_indeterminate.gone()
|
||||
download_border.setImageDrawable(borderCircle)
|
||||
download_border.drawable.setTint(activeColor)
|
||||
download_icon.drawable.setTint(activeColor)
|
||||
}
|
||||
Download.QUEUE -> {
|
||||
download_border.gone()
|
||||
download_progress.gone()
|
||||
download_progress_indeterminate.visible()
|
||||
download_progress.isIndeterminate = true
|
||||
download_icon.drawable.setTint(disabledColor)
|
||||
}
|
||||
Download.DOWNLOADING -> {
|
||||
download_border.visible()
|
||||
download_progress.visible()
|
||||
download_progress_indeterminate.gone()
|
||||
download_border.setImageDrawable(borderCircle)
|
||||
download_progress.isIndeterminate = false
|
||||
download_progress.progress = progress
|
||||
download_border.drawable.setTint(disabledColor)
|
||||
download_progress.progressDrawable?.setTint(downloadedColor)
|
||||
download_icon.drawable.setTint(disabledColor)
|
||||
}
|
||||
Download.DOWNLOADED -> {
|
||||
download_progress.gone()
|
||||
download_border.visible()
|
||||
download_progress_indeterminate.gone()
|
||||
download_border.setImageDrawable(filledCircle)
|
||||
download_border.drawable.setTint(downloadedColor)
|
||||
download_icon.drawable.setTint(Color.WHITE)
|
||||
}
|
||||
Download.ERROR -> {
|
||||
download_progress.gone()
|
||||
download_border.visible()
|
||||
download_progress_indeterminate.gone()
|
||||
download_border.setImageDrawable(borderCircle)
|
||||
download_border.drawable.setTint(errorColor)
|
||||
download_icon.drawable.setTint(errorColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -43,7 +43,7 @@ import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.ui.download.DownloadController
|
||||
import eu.kanade.tachiyomi.ui.library.filter.SortFilterBottomSheet
|
||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaChaptersController
|
||||
import eu.kanade.tachiyomi.ui.migration.MigrationInterface
|
||||
import eu.kanade.tachiyomi.ui.migration.manga.design.PreMigrationController
|
||||
import eu.kanade.tachiyomi.ui.migration.manga.process.MigrationListController
|
||||
@ -628,7 +628,8 @@ open class LibraryController(
|
||||
}
|
||||
|
||||
fun openManga(manga: Manga, startY: Float?) {
|
||||
router.pushController(MangaController(manga, startY).withFadeTransaction())
|
||||
router.pushController(MangaChaptersController(manga).withFadeTransaction())
|
||||
// router.pushController(MangaController(manga, startY).withFadeTransaction())
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,20 @@
|
||||
package eu.kanade.tachiyomi.ui.manga
|
||||
|
||||
import android.view.View
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersAdapter
|
||||
|
||||
abstract class MangaChapterHolder(
|
||||
private val view: View,
|
||||
private val adapter: ChaptersAdapter
|
||||
) : BaseFlexibleViewHolder(view, adapter) {
|
||||
/**
|
||||
* Method called from [ChaptersAdapter.onBindViewHolder]. It updates the data for this
|
||||
* holder with the given manga.
|
||||
*
|
||||
* @param item the manga item to bind.
|
||||
*/
|
||||
abstract fun bind(item: ChapterItem, manga: Manga)
|
||||
}
|
@ -0,0 +1,363 @@
|
||||
package eu.kanade.tachiyomi.ui.manga
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.view.ActionMode
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.palette.graphics.Palette
|
||||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.vectordrawable.graphics.drawable.ArgbEvaluator
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.ControllerChangeType
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.request.target.CustomTarget
|
||||
import com.bumptech.glide.request.transition.Transition
|
||||
import com.bumptech.glide.signature.ObjectKey
|
||||
import com.google.android.material.snackbar.BaseTransientBottomBar
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.database.models.MangaImpl
|
||||
import eu.kanade.tachiyomi.data.glide.GlideApp
|
||||
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.ui.base.controller.BaseController
|
||||
import eu.kanade.tachiyomi.ui.catalogue.CatalogueController
|
||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||
import eu.kanade.tachiyomi.ui.main.SearchActivity
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersAdapter
|
||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import eu.kanade.tachiyomi.util.view.getText
|
||||
import eu.kanade.tachiyomi.util.view.snack
|
||||
import kotlinx.android.synthetic.main.big_manga_controller.*
|
||||
import kotlinx.android.synthetic.main.main_activity.*
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class MangaChaptersController : BaseController,
|
||||
ActionMode.Callback,
|
||||
FlexibleAdapter.OnItemClickListener,
|
||||
ChaptersAdapter.MangaHeaderInterface {
|
||||
|
||||
constructor(manga: Manga?,
|
||||
fromCatalogue: Boolean = false,
|
||||
smartSearchConfig: CatalogueController.SmartSearchConfig? = null,
|
||||
update: Boolean = false) : super(Bundle().apply {
|
||||
putLong(MangaController.MANGA_EXTRA, manga?.id ?: 0)
|
||||
putBoolean(MangaController.FROM_CATALOGUE_EXTRA, fromCatalogue)
|
||||
putParcelable(MangaController.SMART_SEARCH_CONFIG_EXTRA, smartSearchConfig)
|
||||
putBoolean(MangaController.UPDATE_EXTRA, update)
|
||||
}) {
|
||||
this.manga = manga
|
||||
if (manga != null) {
|
||||
source = Injekt.get<SourceManager>().getOrStub(manga.source)
|
||||
}
|
||||
}
|
||||
|
||||
constructor(mangaId: Long) : this(
|
||||
Injekt.get<DatabaseHelper>().getManga(mangaId).executeAsBlocking())
|
||||
|
||||
constructor(bundle: Bundle) : this(bundle.getLong(MangaController.MANGA_EXTRA)) {
|
||||
val notificationId = bundle.getInt("notificationId", -1)
|
||||
val context = applicationContext ?: return
|
||||
if (notificationId > -1) NotificationReceiver.dismissNotification(
|
||||
context, notificationId, bundle.getInt("groupId", 0)
|
||||
)
|
||||
}
|
||||
|
||||
private var manga: Manga? = null
|
||||
private var source: Source? = null
|
||||
var colorAnimator:ValueAnimator? = null
|
||||
lateinit var presenter:MangaPresenter
|
||||
var coverColor:Int? = null
|
||||
var toolbarIsColored = false
|
||||
private var snack: Snackbar? = null
|
||||
|
||||
/**
|
||||
* Adapter containing a list of chapters.
|
||||
*/
|
||||
private var adapter: ChaptersAdapter? = null
|
||||
|
||||
init {
|
||||
setHasOptionsMenu(true)
|
||||
}
|
||||
|
||||
override fun getTitle(): String? {
|
||||
return if (toolbarIsColored) manga?.currentTitle() else null
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
coverColor = null
|
||||
if (!::presenter.isInitialized) presenter = MangaPresenter(this, manga!!, source!!)
|
||||
|
||||
// Init RecyclerView and adapter
|
||||
adapter = ChaptersAdapter(this, view.context)
|
||||
//setReadingDrawable()
|
||||
|
||||
recycler.adapter = adapter
|
||||
recycler.layoutManager = LinearLayoutManager(view.context)
|
||||
recycler.addItemDecoration(
|
||||
DividerItemDecoration(
|
||||
view.context,
|
||||
DividerItemDecoration.VERTICAL
|
||||
)
|
||||
)
|
||||
recycler.setHasFixedSize(true)
|
||||
|
||||
presenter.onCreate()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
recycler.setOnScrollChangeListener { v, scrollX, scrollY, oldScrollX, oldScrollY ->
|
||||
val atTop =
|
||||
((recycler.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition() == 0)
|
||||
if ((!atTop && !toolbarIsColored) || (atTop && toolbarIsColored)) {
|
||||
toolbarIsColored = !atTop
|
||||
colorAnimator?.cancel()
|
||||
val color =
|
||||
coverColor ?: activity!!.getResourceColor(android.R.attr.colorPrimary)
|
||||
val colorFrom = ColorUtils.setAlphaComponent(
|
||||
color, if (toolbarIsColored) 0 else 255
|
||||
)
|
||||
val colorTo = ColorUtils.setAlphaComponent(
|
||||
color, if (toolbarIsColored) 255 else 0
|
||||
)
|
||||
colorAnimator = ValueAnimator.ofObject(
|
||||
ArgbEvaluator(), colorFrom, colorTo
|
||||
)
|
||||
colorAnimator?.duration = 250 // milliseconds
|
||||
//colorAnimation.startDelay = 150
|
||||
colorAnimator?.addUpdateListener { animator ->
|
||||
(activity as MainActivity).toolbar.setBackgroundColor(animator.animatedValue as Int)
|
||||
//activity?.window?.statusBarColor = (animator.animatedValue as Int)
|
||||
}
|
||||
colorAnimator?.start()
|
||||
val isCurrentController = router?.backstack?.lastOrNull()?.controller() == this
|
||||
if (isCurrentController) setTitle()
|
||||
}
|
||||
}
|
||||
}
|
||||
GlideApp.with(view.context).load(manga)
|
||||
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
|
||||
.signature(ObjectKey(MangaImpl.getLastCoverFetch(manga!!.id!!).toString()))
|
||||
.into(object : CustomTarget<Drawable>() {
|
||||
override fun onResourceReady(resource: Drawable,
|
||||
transition: Transition<in Drawable>?
|
||||
) {
|
||||
Palette.from(
|
||||
(resource as BitmapDrawable).bitmap).generate {
|
||||
if (recycler == null) return@generate
|
||||
val currentNightMode =
|
||||
recycler.resources!!.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
|
||||
val colorBack = view.context.getResourceColor(
|
||||
android.R.attr.colorBackground
|
||||
)
|
||||
val backDropColor =
|
||||
(if (currentNightMode == Configuration.UI_MODE_NIGHT_NO) it?.getLightMutedColor(
|
||||
colorBack
|
||||
)
|
||||
else it?.getDarkMutedColor(colorBack)) ?: colorBack
|
||||
onCoverLoaded(backDropColor)
|
||||
(recycler.findViewHolderForItemId(-1) as? MangaHeaderHolder)
|
||||
?.setBackDrop(backDropColor)
|
||||
if (toolbarIsColored)
|
||||
(activity as MainActivity).toolbar.setBackgroundColor(backDropColor)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLoadCleared(placeholder: Drawable?) { }
|
||||
})
|
||||
//adapter?.fastScroller = fast_scroller
|
||||
}
|
||||
|
||||
override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) {
|
||||
super.onChangeStarted(handler, type)
|
||||
if (type == ControllerChangeType.PUSH_ENTER || type == ControllerChangeType.POP_ENTER) {
|
||||
(activity as MainActivity).appbar.setBackgroundColor(Color.TRANSPARENT)
|
||||
(activity as MainActivity).toolbar.setBackgroundColor(Color.TRANSPARENT)
|
||||
/* val colorFrom = ((activity as MainActivity).toolbar.background as ColorDrawable).color
|
||||
val colorTo = Color.TRANSPARENT
|
||||
colorAnimator = ValueAnimator.ofObject(
|
||||
ArgbEvaluator(), colorFrom, colorTo)
|
||||
colorAnimator?.duration = 250 // milliseconds
|
||||
//colorAnimation.startDelay = 150
|
||||
colorAnimator?.addUpdateListener { animator ->
|
||||
(activity as MainActivity).toolbar.setBackgroundColor(animator.animatedValue as Int)
|
||||
//activity?.window?.statusBarColor = (animator.animatedValue as Int)
|
||||
}
|
||||
colorAnimator?.start()*/
|
||||
|
||||
/*activity!!.window.setFlags(
|
||||
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
|
||||
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
val insetTop = activity!!.window.decorView.rootWindowInsets.systemWindowInsetTop
|
||||
val insetBottom = activity!!.window.decorView.rootWindowInsets.stableInsetBottom
|
||||
(activity)?.appbar?.updateLayoutParams<ConstraintLayout.LayoutParams> {
|
||||
topMargin = insetTop
|
||||
}
|
||||
|
||||
(activity)?.navigationView?.updateLayoutParams<ConstraintLayout.LayoutParams> {
|
||||
bottomMargin = insetBottom
|
||||
}
|
||||
}*/
|
||||
|
||||
//
|
||||
//(activity as MainActivity).toolbar.setBackgroundColor(Color.TRANSPARENT)
|
||||
//(activity as MainActivity).appbar.gone()
|
||||
}
|
||||
else if (type == ControllerChangeType.PUSH_EXIT || type == ControllerChangeType.POP_EXIT) {
|
||||
colorAnimator?.cancel()
|
||||
|
||||
(activity as MainActivity).toolbar.setBackgroundColor(activity?.getResourceColor(
|
||||
android.R.attr.colorPrimary
|
||||
) ?: Color.BLACK)
|
||||
|
||||
// activity!!.window.clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
|
||||
|
||||
activity?.window?.statusBarColor = activity?.getResourceColor(
|
||||
android.R.attr.colorPrimary
|
||||
) ?: Color.BLACK
|
||||
/*(activity as MainActivity).appbar.updateLayoutParams<ConstraintLayout.LayoutParams> {
|
||||
topMargin = 0
|
||||
}
|
||||
(activity as MainActivity).navigationView.updateLayoutParams<ConstraintLayout
|
||||
.LayoutParams> {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
bottomMargin = 0
|
||||
}
|
||||
}*/
|
||||
//(activity as MainActivity).appbar.background = null
|
||||
// (activity as AppCompatActivity).supportActionBar?.show()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun updateChapters(chapters: List<ChapterItem>) {
|
||||
if (presenter.chapters.isEmpty()) {
|
||||
//initialFetchChapters()
|
||||
}
|
||||
adapter?.updateDataSet(listOf(ChapterItem(Chapter.create(), manga!!)) + chapters)
|
||||
}
|
||||
|
||||
override fun onItemClick(view: View?, position: Int): Boolean {
|
||||
val adapter = adapter ?: return false
|
||||
val chapter = adapter.getItem(position)?.chapter ?: return false
|
||||
if (!chapter.isRecognizedNumber) return false
|
||||
/*if (actionMode != null && adapter.mode == SelectableAdapter.Mode.MULTI) {
|
||||
lastClickPosition = position
|
||||
toggleSelection(position)
|
||||
return true
|
||||
} else {*/
|
||||
openChapter(chapter)
|
||||
return false
|
||||
//}
|
||||
}
|
||||
|
||||
fun openChapter(chapter: Chapter, hasAnimation: Boolean = false) {
|
||||
val activity = activity ?: return
|
||||
val intent = ReaderActivity.newIntent(activity, manga!!, chapter)
|
||||
if (hasAnimation) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
|
||||
}
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
fun getStatusBarHeight(): Int {
|
||||
var result = 0
|
||||
val resourceId = resources!!.getIdentifier("status_bar_height", "dimen", "android")
|
||||
if (resourceId > 0) {
|
||||
result = resources!!.getDimensionPixelSize(resourceId)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
inflater.inflate(R.menu.chapters, menu)
|
||||
}
|
||||
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||
return inflater.inflate(R.layout.big_manga_controller, container, false)
|
||||
}
|
||||
|
||||
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
override fun onDestroyActionMode(mode: ActionMode?) {
|
||||
|
||||
}
|
||||
|
||||
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean {
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
fun onCoverLoaded(color: Int) {
|
||||
if (view == null) return
|
||||
coverColor = color
|
||||
activity?.window?.statusBarColor = color
|
||||
}
|
||||
|
||||
override fun coverColor(): Int? = coverColor
|
||||
|
||||
override fun nextChapter(): Chapter? {
|
||||
return presenter.getNextUnreadChapter()
|
||||
}
|
||||
|
||||
override fun readNextChapter() {
|
||||
if (activity is SearchActivity && presenter.isLockedFromSearch) {
|
||||
SecureActivityDelegate.promptLockIfNeeded(activity)
|
||||
return
|
||||
}
|
||||
val item = presenter.getNextUnreadChapter()
|
||||
if (item != null) {
|
||||
openChapter(item.chapter)
|
||||
} else if (snack == null || snack?.getText() != view?.context?.getString(
|
||||
R.string.no_next_chapter)) {
|
||||
snack = view?.snack(R.string.no_next_chapter, Snackbar.LENGTH_LONG) {
|
||||
addCallback(object : BaseTransientBottomBar.BaseCallback<Snackbar>() {
|
||||
override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
|
||||
super.onDismissed(transientBottomBar, event)
|
||||
if (snack == transientBottomBar) snack = null
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun downloadChapter(position: Int) {
|
||||
val adapter = adapter ?: return
|
||||
val chapter = adapter.getItem(position) ?: return
|
||||
if (!chapter.isRecognizedNumber) return
|
||||
if (chapter.isDownloaded) {
|
||||
presenter.deleteChapters(listOf(chapter))
|
||||
}
|
||||
else presenter.downloadChapters(listOf(chapter))
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package eu.kanade.tachiyomi.ui.manga
|
||||
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.ColorUtils
|
||||
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.Manga
|
||||
import eu.kanade.tachiyomi.data.database.models.MangaImpl
|
||||
import eu.kanade.tachiyomi.data.glide.GlideApp
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersAdapter
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import eu.kanade.tachiyomi.util.view.visibleIf
|
||||
import kotlinx.android.synthetic.main.manga_header_item.*
|
||||
|
||||
class MangaHeaderHolder(
|
||||
private val view: View,
|
||||
private val adapter: ChaptersAdapter
|
||||
) : MangaChapterHolder(view, adapter) {
|
||||
|
||||
init {
|
||||
start_reading_button.setOnClickListener { adapter.coverListener?.readNextChapter() }
|
||||
}
|
||||
|
||||
override fun bind(item: ChapterItem, manga: Manga) {
|
||||
manga_title.text = manga.currentTitle()
|
||||
if (manga.currentAuthor() == manga.currentArtist() ||
|
||||
manga.currentArtist().isNullOrBlank())
|
||||
manga_author.text = manga.currentAuthor()
|
||||
else {
|
||||
manga_author.text = "${manga.currentAuthor()?.trim()}, ${manga.currentArtist()}"
|
||||
}
|
||||
manga_summary.text = manga.currentDesc()
|
||||
manga_summary_label.text = "About this ${if (manga.mangaType() == Manga.TYPE_MANGA) "Manga"
|
||||
else "Manhwa"}"
|
||||
with(favorite_button) {
|
||||
icon = ContextCompat.getDrawable(
|
||||
itemView.context, when {
|
||||
item.isLocked -> R.drawable.ic_lock_white_24dp
|
||||
manga.favorite -> R.drawable.ic_bookmark_white_24dp
|
||||
else -> R.drawable.ic_add_to_library_24dp
|
||||
}
|
||||
)
|
||||
text = itemView.resources.getString(
|
||||
when {
|
||||
item.isLocked -> R.string.unlock
|
||||
manga.favorite -> R.string.in_library
|
||||
else -> R.string.add_to_library
|
||||
}
|
||||
)
|
||||
backgroundTintList =
|
||||
ContextCompat.getColorStateList(context, android.R.color.transparent)
|
||||
if (!item.isLocked && manga.favorite) {
|
||||
backgroundTintList =
|
||||
ColorStateList.valueOf(
|
||||
ColorUtils.setAlphaComponent(
|
||||
context.getResourceColor(R.attr.colorAccent), 75))
|
||||
strokeColor = ColorStateList.valueOf(Color.TRANSPARENT)
|
||||
}
|
||||
}
|
||||
true_backdrop.setBackgroundColor(adapter.coverListener?.coverColor() ?:
|
||||
itemView.context.getResourceColor(android.R.attr.colorBackground))
|
||||
|
||||
with(start_reading_button) {
|
||||
val nextChapter = adapter.coverListener?.nextChapter()
|
||||
visibleIf(nextChapter != null && !item.isLocked)
|
||||
if (nextChapter != null) {
|
||||
val number = adapter.decimalFormat.format(nextChapter.chapter_number.toDouble())
|
||||
text = resources.getString(if (nextChapter.last_page_read > 0)
|
||||
R.string.continue_reader_chapter
|
||||
else R.string.start_reader_chapter, number)
|
||||
}
|
||||
}
|
||||
|
||||
GlideApp.with(view.context).load(manga)
|
||||
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
|
||||
.signature(ObjectKey(MangaImpl.getLastCoverFetch(manga.id!!).toString()))
|
||||
.into(manga_cover)
|
||||
GlideApp.with(view.context).load(manga)
|
||||
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
|
||||
.signature(ObjectKey(MangaImpl.getLastCoverFetch(manga.id!!).toString()))
|
||||
.centerCrop()
|
||||
.into(backdrop)
|
||||
}
|
||||
|
||||
fun setBackDrop(color: Int) {
|
||||
true_backdrop.setBackgroundColor(color)
|
||||
}
|
||||
}
|
258
app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt
Normal file
258
app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt
Normal file
@ -0,0 +1,258 @@
|
||||
package eu.kanade.tachiyomi.ui.manga
|
||||
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.source.LocalSource
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
|
||||
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class MangaPresenter(private val controller: MangaChaptersController,
|
||||
val manga: Manga,
|
||||
val source: Source,
|
||||
val preferences: PreferencesHelper = Injekt.get(),
|
||||
private val db: DatabaseHelper = Injekt.get(),
|
||||
private val downloadManager: DownloadManager = Injekt.get()) {
|
||||
|
||||
|
||||
var isLockedFromSearch = false
|
||||
|
||||
var chapters:List<ChapterItem> = emptyList()
|
||||
private set
|
||||
fun onCreate() {
|
||||
isLockedFromSearch = SecureActivityDelegate.shouldBeLocked()
|
||||
|
||||
val chapters = db.getChapters(manga).executeAsBlocking().map { it.toModel() }
|
||||
|
||||
|
||||
// Store the last emission
|
||||
this.chapters = applyChapterFilters(chapters)
|
||||
|
||||
// Find downloaded chapters
|
||||
setDownloadedChapters(chapters)
|
||||
|
||||
controller.updateChapters(this.chapters)
|
||||
|
||||
// Listen for download status changes
|
||||
//observeDownloads()
|
||||
|
||||
// Emit the number of chapters to the info tab.
|
||||
//chapterCountRelay.call(chapters.maxBy { it.chapter_number }?.chapter_number ?: 0f)
|
||||
|
||||
// Emit the upload date of the most recent chapter
|
||||
/*lastUpdateRelay.call(
|
||||
Date(chapters.maxBy { it.date_upload }?.date_upload ?: 0)
|
||||
)*/
|
||||
|
||||
/* // Prepare the relay.
|
||||
chaptersRelay.flatMap { applyChapterFilters(it) }
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeLatestCache(
|
||||
ChaptersController::onNextChapters
|
||||
) { _, error -> Timber.e(error) }
|
||||
|
||||
// Add the subscription that retrieves the chapters from the database, keeps subscribed to
|
||||
// changes, and sends the list of chapters to the relay.
|
||||
add(db.getChapters(manga).asRxObservable()
|
||||
.map { chapters ->
|
||||
// Convert every chapter to a model.
|
||||
chapters.map { it.toModel() }
|
||||
}
|
||||
.doOnNext { chapters ->
|
||||
// Find downloaded chapters
|
||||
setDownloadedChapters(chapters)
|
||||
|
||||
// Store the last emission
|
||||
this.chapters = chapters
|
||||
|
||||
// Listen for download status changes
|
||||
observeDownloads()
|
||||
|
||||
// Emit the number of chapters to the info tab.
|
||||
chapterCountRelay.call(chapters.maxBy { it.chapter_number }?.chapter_number
|
||||
?: 0f)
|
||||
|
||||
// Emit the upload date of the most recent chapter
|
||||
lastUpdateRelay.call(
|
||||
Date(chapters.maxBy { it.date_upload }?.date_upload
|
||||
?: 0)
|
||||
)
|
||||
|
||||
}
|
||||
.subscribe { chaptersRelay.call(it) })*/
|
||||
}
|
||||
|
||||
/*private fun observeDownloads() {
|
||||
observeDownloadsSubscription?.let { remove(it) }
|
||||
observeDownloadsSubscription = downloadManager.queue.getStatusObservable()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.filter { download -> download.manga.id == manga.id }
|
||||
.doOnNext { onDownloadStatusChange(it) }
|
||||
.subscribeLatestCache(ChaptersController::onChapterStatusChange) {
|
||||
_, error -> Timber.e(error)
|
||||
}
|
||||
}*/
|
||||
/**
|
||||
* Finds and assigns the list of downloaded chapters.
|
||||
*
|
||||
* @param chapters the list of chapter from the database.
|
||||
*/
|
||||
private fun setDownloadedChapters(chapters: List<ChapterItem>) {
|
||||
for (chapter in chapters) {
|
||||
if (downloadManager.isChapterDownloaded(chapter, manga)) {
|
||||
chapter.status = Download.DOWNLOADED
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Converts a chapter from the database to an extended model, allowing to store new fields.
|
||||
*/
|
||||
private fun Chapter.toModel(): ChapterItem {
|
||||
// Create the model object.
|
||||
val model = ChapterItem(this, manga)
|
||||
model.isLocked = isLockedFromSearch
|
||||
|
||||
// Find an active download for this chapter.
|
||||
val download = downloadManager.queue.find { it.chapter.id == id }
|
||||
|
||||
if (download != null) {
|
||||
// If there's an active download, assign it.
|
||||
model.download = download
|
||||
}
|
||||
return model
|
||||
}
|
||||
/**
|
||||
* Sets the active display mode.
|
||||
* @param mode the mode to set.
|
||||
*/
|
||||
fun setDisplayMode(mode: Int) {
|
||||
manga.displayMode = mode
|
||||
db.updateFlags(manga).executeAsBlocking()
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sorting method and requests an UI update.
|
||||
* @param sort the sorting mode.
|
||||
*/
|
||||
fun setSorting(sort: Int) {
|
||||
manga.sorting = sort
|
||||
db.updateFlags(manga).executeAsBlocking()
|
||||
// refreshChapters()
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the display only downloaded filter is enabled.
|
||||
*/
|
||||
fun onlyDownloaded(): Boolean {
|
||||
return manga.downloadedFilter == Manga.SHOW_DOWNLOADED
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the display only downloaded filter is enabled.
|
||||
*/
|
||||
fun onlyBookmarked(): Boolean {
|
||||
return manga.bookmarkedFilter == Manga.SHOW_BOOKMARKED
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the display only unread filter is enabled.
|
||||
*/
|
||||
fun onlyUnread(): Boolean {
|
||||
return manga.readFilter == Manga.SHOW_UNREAD
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the display only read filter is enabled.
|
||||
*/
|
||||
fun onlyRead(): Boolean {
|
||||
return manga.readFilter == Manga.SHOW_READ
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the sorting method is descending or ascending.
|
||||
*/
|
||||
fun sortDescending(): Boolean {
|
||||
return manga.sortDescending()
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the view filters to the list of chapters obtained from the database.
|
||||
* @param chapterList the list of chapters from the database
|
||||
* @return an observable of the list of chapters filtered and sorted.
|
||||
*/
|
||||
private fun applyChapterFilters(chapterList: List<ChapterItem>): List<ChapterItem> {
|
||||
var chapters = chapterList
|
||||
if (onlyUnread()) {
|
||||
chapters = chapters.filter { !it.read }
|
||||
} else if (onlyRead()) {
|
||||
chapters = chapters.filter { it.read }
|
||||
}
|
||||
if (onlyDownloaded()) {
|
||||
chapters = chapters.filter { it.isDownloaded || it.manga.source == LocalSource.ID }
|
||||
}
|
||||
if (onlyBookmarked()) {
|
||||
chapters = chapters.filter { it.bookmark }
|
||||
}
|
||||
val sortFunction: (Chapter, Chapter) -> Int = when (manga.sorting) {
|
||||
Manga.SORTING_SOURCE -> when (sortDescending()) {
|
||||
true -> { c1, c2 -> c1.source_order.compareTo(c2.source_order) }
|
||||
false -> { c1, c2 -> c2.source_order.compareTo(c1.source_order) }
|
||||
}
|
||||
Manga.SORTING_NUMBER -> when (sortDescending()) {
|
||||
true -> { c1, c2 -> c2.chapter_number.compareTo(c1.chapter_number) }
|
||||
false -> { c1, c2 -> c1.chapter_number.compareTo(c2.chapter_number) }
|
||||
}
|
||||
else -> throw NotImplementedError("Unimplemented sorting method")
|
||||
}
|
||||
chapters = chapters.sortedWith(Comparator(sortFunction))
|
||||
//if (sortDescending())
|
||||
// chapters = chapters.reversed()
|
||||
return chapters
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next unread chapter or null if everything is read.
|
||||
*/
|
||||
fun getNextUnreadChapter(): ChapterItem? {
|
||||
return chapters.sortedByDescending { it.source_order }.find { !it.read }
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads the given list of chapters with the manager.
|
||||
* @param chapters the list of chapters to download.
|
||||
*/
|
||||
fun downloadChapters(chapters: List<ChapterItem>) {
|
||||
downloadManager.downloadChapters(manga, chapters)
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the given list of chapter.
|
||||
* @param chapters the list of chapters to delete.
|
||||
*/
|
||||
fun deleteChapters(chapters: List<ChapterItem>) {
|
||||
deleteChaptersInternal(chapters)
|
||||
|
||||
setDownloadedChapters(chapters)
|
||||
|
||||
controller.updateChapters(this.chapters)
|
||||
// if (onlyDownloaded()) refreshChapters() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a list of chapters from disk. This method is called in a background thread.
|
||||
* @param chapters the chapters to delete.
|
||||
*/
|
||||
private fun deleteChaptersInternal(chapters: List<ChapterItem>) {
|
||||
downloadManager.deleteChapters(chapters, manga, source)
|
||||
chapters.forEach {
|
||||
it.status = Download.NOT_DOWNLOADED
|
||||
it.download = null
|
||||
}
|
||||
}
|
||||
}
|
@ -27,7 +27,7 @@ class ChapterHolder(
|
||||
}
|
||||
|
||||
fun bind(item: ChapterItem, manga: Manga) {
|
||||
val chapter = item.chapter
|
||||
val chapter = item.chapter ?: return
|
||||
val isLocked = item.isLocked
|
||||
chapter_title.text = when (manga.displayMode) {
|
||||
Manga.DISPLAY_NUMBER -> {
|
||||
@ -90,6 +90,7 @@ class ChapterHolder(
|
||||
|
||||
private fun showPopupMenu(view: View) {
|
||||
val item = adapter.getItem(adapterPosition) ?: return
|
||||
val chapter = item.chapter ?: return
|
||||
|
||||
if (item.isLocked) {
|
||||
adapter.unlock()
|
||||
@ -101,7 +102,6 @@ class ChapterHolder(
|
||||
// Inflate our menu resource into the PopupMenu's Menu
|
||||
popup.menuInflater.inflate(R.menu.chapter_single, popup.menu)
|
||||
|
||||
val chapter = item.chapter
|
||||
|
||||
// Hide download and show delete if the chapter is downloaded
|
||||
if (item.isDownloaded) {
|
||||
@ -125,7 +125,7 @@ class ChapterHolder(
|
||||
|
||||
// Set a listener so we are notified if a menu item is clicked
|
||||
popup.setOnMenuItemClickListener { menuItem ->
|
||||
adapter.menuItemListener.onMenuItemClick(adapterPosition, menuItem)
|
||||
adapter.menuItemListener?.onMenuItemClick(adapterPosition, menuItem)
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -9,11 +9,21 @@ import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaChapterHolder
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaHeaderHolder
|
||||
|
||||
class ChapterItem(val chapter: Chapter, val manga: Manga) : AbstractFlexibleItem<ChapterHolder>(),
|
||||
Chapter by chapter {
|
||||
class ChapterItem(val chapter: Chapter, val manga: Manga) :
|
||||
AbstractFlexibleItem<MangaChapterHolder>(),
|
||||
Chapter by chapter {
|
||||
|
||||
private var _status: Int = 0
|
||||
|
||||
val progress: Int
|
||||
get() {
|
||||
val pages = download?.pages ?: return 0
|
||||
return pages.map(Page::progress).average().toInt()
|
||||
}
|
||||
var isLocked = false
|
||||
|
||||
var status: Int
|
||||
@ -26,31 +36,36 @@ class ChapterItem(val chapter: Chapter, val manga: Manga) : AbstractFlexibleItem
|
||||
get() = status == Download.DOWNLOADED
|
||||
|
||||
override fun getLayoutRes(): Int {
|
||||
return R.layout.chapters_item
|
||||
return if (!chapter.isRecognizedNumber) R.layout.manga_header_item
|
||||
else R.layout.chapters_mat_item
|
||||
}
|
||||
|
||||
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): ChapterHolder {
|
||||
return ChapterHolder(view, adapter as ChaptersAdapter)
|
||||
override fun isSelectable(): Boolean {
|
||||
return chapter.isRecognizedNumber
|
||||
}
|
||||
|
||||
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): MangaChapterHolder {
|
||||
return if (!chapter.isRecognizedNumber) MangaHeaderHolder(view, adapter as ChaptersAdapter)
|
||||
else ChapterMatHolder(view, adapter as ChaptersAdapter)
|
||||
}
|
||||
|
||||
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>,
|
||||
holder: ChapterHolder,
|
||||
holder: MangaChapterHolder,
|
||||
position: Int,
|
||||
payloads: MutableList<Any?>?) {
|
||||
|
||||
holder.bind(this, manga)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other is ChapterItem) {
|
||||
return chapter.id!! == other.chapter.id!!
|
||||
return chapter.id ?: -1 == other.chapter.id ?: -1
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return chapter.id!!.hashCode()
|
||||
return chapter.id?.hashCode() ?: -1
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,116 @@
|
||||
package eu.kanade.tachiyomi.ui.manga.chapter
|
||||
|
||||
import android.view.View
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaChapterHolder
|
||||
import eu.kanade.tachiyomi.util.view.gone
|
||||
import eu.kanade.tachiyomi.util.view.invisible
|
||||
import eu.kanade.tachiyomi.util.view.visible
|
||||
import kotlinx.android.synthetic.main.chapters_mat_item.*
|
||||
import kotlinx.android.synthetic.main.download_button.*
|
||||
|
||||
class ChapterMatHolder(
|
||||
private val view: View,
|
||||
private val adapter: ChaptersAdapter
|
||||
) : MangaChapterHolder(view, adapter) {
|
||||
|
||||
init {
|
||||
// We need to post a Runnable to show the popup to make sure that the PopupMenu is
|
||||
// correctly positioned. The reason being that the view may change position before the
|
||||
// PopupMenu is shown.
|
||||
//chapter_menu.setOnClickListener { it.post { showPopupMenu(it) } }
|
||||
download_button.setOnClickListener { downloadOrRemoveMenu() }
|
||||
}
|
||||
|
||||
private fun downloadOrRemoveMenu() {
|
||||
val chapter = adapter.getItem(adapterPosition) ?: return
|
||||
if (chapter.status != Download.NOT_DOWNLOADED) {
|
||||
download_button.post {
|
||||
// Create a PopupMenu, giving it the clicked view for an anchor
|
||||
val popup = PopupMenu(download_button.context, download_button)
|
||||
|
||||
// Inflate our menu resource into the PopupMenu's Menu
|
||||
popup.menuInflater.inflate(R.menu.chapter_download, popup.menu)
|
||||
|
||||
// Hide download and show delete if the chapter is downloaded
|
||||
if (chapter.status != Download.DOWNLOADED) popup.menu.findItem(R.id.action_delete)
|
||||
.title = download_button.context.getString(
|
||||
R.string.action_cancel
|
||||
)
|
||||
|
||||
// Set a listener so we are notified if a menu item is clicked
|
||||
popup.setOnMenuItemClickListener { _ ->
|
||||
adapter.coverListener?.downloadChapter(adapterPosition)
|
||||
true
|
||||
}
|
||||
|
||||
// Finally show the PopupMenu
|
||||
popup.show()
|
||||
}
|
||||
}
|
||||
else {
|
||||
adapter.coverListener?.downloadChapter(adapterPosition)
|
||||
}
|
||||
}
|
||||
|
||||
override fun bind(item: ChapterItem, manga: Manga) {
|
||||
val chapter = item.chapter
|
||||
val isLocked = item.isLocked
|
||||
chapter_title.text = when (manga.displayMode) {
|
||||
Manga.DISPLAY_NUMBER -> {
|
||||
val number = adapter.decimalFormat.format(chapter.chapter_number.toDouble())
|
||||
itemView.context.getString(R.string.display_mode_chapter, number)
|
||||
}
|
||||
else -> chapter.name
|
||||
}
|
||||
|
||||
//chapter_menu.visible()
|
||||
// Set the correct drawable for dropdown and update the tint to match theme.
|
||||
//chapter_menu.setVectorCompat(R.drawable.ic_more_vert_black_24dp, view.context
|
||||
// .getResourceColor(R.attr.icon_color))
|
||||
|
||||
if (isLocked) download_button.invisible()
|
||||
|
||||
// Set correct text color
|
||||
chapter_title.setTextColor(if (chapter.read && !isLocked)
|
||||
adapter.readColor else adapter.unreadColor)
|
||||
if (chapter.bookmark && !isLocked) chapter_title.setTextColor(adapter.bookmarkedColor)
|
||||
|
||||
/*if (chapter.date_upload > 0) {
|
||||
chapter_date.text = adapter.dateFormat.format(Date(chapter.date_upload))
|
||||
chapter_date.setTextColor(if (chapter.read) adapter.readColor else adapter.unreadColor)
|
||||
} else {
|
||||
chapter_date.text = ""
|
||||
}*/
|
||||
|
||||
//add scanlator if exists
|
||||
chapter_scanlator.text = chapter.scanlator ?: " "
|
||||
//allow longer titles if there is no scanlator (most sources)
|
||||
/*if (chapter_scanlator.text.isNullOrBlank()) {
|
||||
chapter_title.maxLines = 2
|
||||
//chapter_scanlator.gone()
|
||||
} else {
|
||||
chapter_title.maxLines = 1
|
||||
}*/
|
||||
|
||||
/* chapter_pages.text = if (!chapter.read && chapter.last_page_read > 0 && !isLocked) {
|
||||
itemView.context.getString(R.string.chapter_progress, chapter.last_page_read + 1)
|
||||
} else {
|
||||
""
|
||||
}*/
|
||||
|
||||
notifyStatus(item.status, item.isLocked, item.progress)
|
||||
}
|
||||
|
||||
fun notifyStatus(status: Int, locked: Boolean, progress: Int) = with(download_button) {
|
||||
if (locked) {
|
||||
gone()
|
||||
return
|
||||
}
|
||||
visible()
|
||||
setDownoadStatus(status, progress)
|
||||
}
|
||||
}
|
@ -5,8 +5,10 @@ import android.view.MenuItem
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||
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.security.SecureActivityDelegate
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
@ -15,7 +17,7 @@ import java.text.DecimalFormat
|
||||
import java.text.DecimalFormatSymbols
|
||||
|
||||
class ChaptersAdapter(
|
||||
val controller: ChaptersController,
|
||||
val controller: BaseController,
|
||||
context: Context
|
||||
) : FlexibleAdapter<ChapterItem>(null, controller, true) {
|
||||
|
||||
@ -23,7 +25,8 @@ class ChaptersAdapter(
|
||||
|
||||
var items: List<ChapterItem> = emptyList()
|
||||
|
||||
val menuItemListener: OnMenuItemClickListener = controller
|
||||
val menuItemListener: OnMenuItemClickListener? = controller as? OnMenuItemClickListener
|
||||
val coverListener: MangaHeaderInterface? = controller as? MangaHeaderInterface
|
||||
|
||||
val readColor = context.getResourceColor(android.R.attr.textColorHint)
|
||||
|
||||
@ -53,4 +56,11 @@ class ChaptersAdapter(
|
||||
interface OnMenuItemClickListener {
|
||||
fun onMenuItemClick(position: Int, item: MenuItem)
|
||||
}
|
||||
|
||||
interface MangaHeaderInterface {
|
||||
fun coverColor(): Int?
|
||||
fun nextChapter(): Chapter?
|
||||
fun readNextChapter()
|
||||
fun downloadChapter(position: Int)
|
||||
}
|
||||
}
|
||||
|
@ -2,22 +2,22 @@ package eu.kanade.tachiyomi.ui.setting
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.preference.PreferenceController
|
||||
import androidx.preference.PreferenceScreen
|
||||
import android.util.TypedValue
|
||||
import android.view.ContextThemeWrapper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.preference.PreferenceController
|
||||
import androidx.preference.PreferenceScreen
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.ControllerChangeType
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.ui.base.controller.BaseController
|
||||
import eu.kanade.tachiyomi.util.view.RecyclerWindowInsetsListener
|
||||
import eu.kanade.tachiyomi.util.view.doOnApplyWindowInsets
|
||||
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
|
||||
import eu.kanade.tachiyomi.util.view.updateLayoutParams
|
||||
import rx.Observable
|
||||
import rx.Subscription
|
||||
import rx.subscriptions.CompositeSubscription
|
||||
@ -36,6 +36,12 @@ abstract class SettingsController : PreferenceController() {
|
||||
untilDestroySubscriptions = CompositeSubscription()
|
||||
}
|
||||
val view = super.onCreateView(inflater, container, savedInstanceState)
|
||||
view.updateLayoutParams<FrameLayout.LayoutParams> {
|
||||
val attrsArray = intArrayOf(android.R.attr.actionBarSize)
|
||||
val array = view.context.obtainStyledAttributes(attrsArray)
|
||||
topMargin = array.getDimensionPixelSize(0, 0)
|
||||
array.recycle()
|
||||
}
|
||||
listView.setOnApplyWindowInsetsListener(RecyclerWindowInsetsListener)
|
||||
return view
|
||||
}
|
||||
|
13
app/src/main/res/drawable/border_circle.xml
Normal file
13
app/src/main/res/drawable/border_circle.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
android:shape="oval"
|
||||
android:thicknessRatio="2">
|
||||
<solid android:color="@android:color/transparent" />
|
||||
<size
|
||||
android:height="25dp"
|
||||
android:width="25dp" />
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="?colorAccent" />
|
||||
</shape>
|
20
app/src/main/res/drawable/circle_progress.xml
Normal file
20
app/src/main/res/drawable/circle_progress.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item android:id="@android:id/progress">
|
||||
<rotate
|
||||
android:fromDegrees="270"
|
||||
android:toDegrees="270"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="50%" >
|
||||
<shape
|
||||
android:shape="ring"
|
||||
android:thickness="2dp">
|
||||
<gradient
|
||||
android:centerColor="@color/gray_button"
|
||||
android:endColor="@color/gray_button"
|
||||
android:startColor="@color/gray_button"
|
||||
android:type="sweep" />
|
||||
</shape>
|
||||
</rotate>
|
||||
</item>
|
||||
</layer-list>
|
13
app/src/main/res/drawable/filled_circle.xml
Normal file
13
app/src/main/res/drawable/filled_circle.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
android:shape="oval"
|
||||
android:thicknessRatio="2">
|
||||
<solid android:color="?colorAccent" />
|
||||
<size
|
||||
android:height="25dp"
|
||||
android:width="25dp" />
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="?colorAccent" />
|
||||
</shape>
|
@ -4,7 +4,7 @@
|
||||
|
||||
<gradient
|
||||
android:angle="90"
|
||||
android:startColor="#cc000000"
|
||||
android:startColor="#ff000000"
|
||||
android:centerColor="#00000000"
|
||||
android:endColor="#00ffffff"/>
|
||||
|
||||
|
@ -0,0 +1,9 @@
|
||||
<!-- drawable/earth.xml -->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?actionBarTintColor">
|
||||
<path android:fillColor="#000" android:pathData="M17.9,17.39C17.64,16.59 16.89,16 16,16H15V13A1,1 0 0,0 14,12H8V10H10A1,1 0 0,0 11,9V7H13A2,2 0 0,0 15,5V4.59C17.93,5.77 20,8.64 20,12C20,14.08 19.2,15.97 17.9,17.39M11,19.93C7.05,19.44 4,16.08 4,12C4,11.38 4.08,10.78 4.21,10.21L9,15V16A2,2 0 0,0 11,18M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" />
|
||||
</vector>
|
@ -3,7 +3,7 @@
|
||||
android:color="@color/gray_button">
|
||||
<item android:id="@android:id/mask">
|
||||
<shape android:shape="oval">
|
||||
<solid android:color="@color/gray_button" />
|
||||
<solid android:color="@color/fullRippleColor" />
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
@ -1,320 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout 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/manga_info_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@id/swipe_refresh"
|
||||
android:layout_width="match_parent"
|
||||
android:background="?android:colorBackground"
|
||||
android:fitsSystemWindows="true"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="eu.kanade.tachiyomi.ui.catalogue.browse.BrowseCatalogueController">
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/manga_info_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<View
|
||||
android:id="@+id/guideline"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="32dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/backdrop" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/guideline2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_percent="0.35" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/backdrop"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:alpha="0.2"
|
||||
android:translationY="-40dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/manga_cover"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:background="@color/material_red_400" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:alpha="0.25"
|
||||
android:background="@drawable/gradient_shape"
|
||||
android:backgroundTint="@color/material_red_400"
|
||||
android:scaleY="-1"
|
||||
android:translationY="-40dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/backdrop" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/manga_cover"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@string/description_cover"
|
||||
android:src="@mipmap/ic_launcher"
|
||||
app:layout_constraintBottom_toBottomOf="@id/guideline"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:background="@color/material_grey_700" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_full_title"
|
||||
style="@style/TextAppearance.MaterialComponents.Headline5"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="50dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:maxLines="2"
|
||||
android:text="@string/manga_info_full_title_label"
|
||||
android:textIsSelectable="false"
|
||||
android:textSize="20sp"
|
||||
app:autoSizeTextType="uniform"
|
||||
app:layout_constraintStart_toEndOf="@id/manga_cover"
|
||||
app:layout_constraintTop_toTopOf="@id/manga_cover"
|
||||
tools:text="Title Example" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_author_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_author_label"
|
||||
android:textIsSelectable="false"
|
||||
|
||||
app:layout_constraintStart_toStartOf="@id/manga_full_title"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_full_title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_author"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_author_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_author_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_last_update_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_latest_data_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="@id/manga_full_title"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_author_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_last_update"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_last_update_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_last_update_label" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/manga_status_source"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/manga_full_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/manga_last_update_label"
|
||||
tools:text="Completed • Mangadex (EN)" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/button_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="14dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/manga_cover"
|
||||
app:layout_constraintBottom_toTopOf="@id/start_reading_button">
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:tint="@color/gray_button"
|
||||
android:src="@drawable/ic_add_to_library_24dp"/>
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_gravity="center"
|
||||
android:background="@color/gray_button"/>
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:tint="@color/gray_button"
|
||||
android:src="@drawable/ic_add_to_library_24dp"/>
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_gravity="center"
|
||||
android:background="@color/gray_button"/>
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:tint="@color/gray_button"
|
||||
android:src="@drawable/ic_sync_black_24dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/start_reading_button"
|
||||
android:layout_width="0dp"
|
||||
app:backgroundTint="?colorAccent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAllCaps="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/button_layout"
|
||||
app:layout_constraintBottom_toTopOf="@id/manga_summary_label"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="Start Reading"/>
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/manga_summary_label"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@string/description"
|
||||
android:textIsSelectable="false"
|
||||
style="@style/TextAppearance.MaterialComponents.Headline6"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:textSize="17sp"
|
||||
tools:text="About this manga"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/start_reading_button" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_summary"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="55dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBottom_toTopOf="@id/manga_genres_tags"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/manga_summary_label"
|
||||
tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." />
|
||||
|
||||
<View
|
||||
android:layout_width="75dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginEnd="30dp"
|
||||
android:background="@drawable/full_gradient"
|
||||
android:backgroundTint="@color/md_white_1000"
|
||||
app:layout_constraintBottom_toBottomOf="@id/manga_summary"
|
||||
app:layout_constraintEnd_toEndOf="@id/more_button" />
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="20dp"
|
||||
android:background="@color/md_white_1000"
|
||||
android:layout_marginStart="20dp"
|
||||
app:layout_constraintStart_toStartOf="@id/more_button"
|
||||
app:layout_constraintBottom_toBottomOf="@id/manga_summary"
|
||||
app:layout_constraintEnd_toEndOf="@id/more_button" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/more_button"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20sp"
|
||||
android:text="More"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?colorAccent"
|
||||
app:layout_constraintEnd_toEndOf="@id/manga_summary"
|
||||
app:layout_constraintTop_toTopOf="@id/manga_summary"
|
||||
app:rippleColor="@color/gray_button" />
|
||||
|
||||
|
||||
<me.gujun.android.taggroup.TagGroup
|
||||
android:id="@+id/manga_genres_tags"
|
||||
style="@style/TagGroup"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:atg_backgroundColor="@android:color/transparent"
|
||||
app:atg_borderColor="@color/md_blue_A400"
|
||||
app:atg_borderStrokeWidth="1dp"
|
||||
app:atg_textColor="@color/md_blue_A400"
|
||||
app:layout_constrainedHeight="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/manga_summary" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/chapters_title"
|
||||
style="@style/TextAppearance.MaterialComponents.Headline6"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:text="@string/chapters"
|
||||
android:textSize="17sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/recycler"
|
||||
app:layout_constraintStart_toStartOf="@id/manga_summary_label"
|
||||
app:layout_constraintTop_toBottomOf="@id/manga_genres_tags" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/show_all_button"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Show All"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?colorAccent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/chapters_title"
|
||||
app:layout_constraintBottom_toBottomOf="@id/chapters_title"
|
||||
app:rippleColor="@color/gray_button" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:clipToPadding="false"
|
||||
android:descendantFocusability="blocksDescendants"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/chapters_title"
|
||||
tools:listitem="@layout/chapters_item">
|
||||
|
||||
</androidx.recyclerview.widget.RecyclerView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:descendantFocusability="blocksDescendants"
|
||||
android:nestedScrollingEnabled="false"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/chapters_title"
|
||||
tools:listitem="@layout/chapters_mat_item">
|
||||
</androidx.recyclerview.widget.RecyclerView>
|
||||
|
||||
<View
|
||||
android:id="@+id/full_backdrop"
|
||||
@ -337,6 +49,5 @@
|
||||
android:layout_marginBottom="16dp"
|
||||
android:contentDescription="@string/description_cover"
|
||||
android:visibility="invisible" />
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
@ -4,6 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/catalouge_layout"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
|
@ -2,6 +2,7 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
|
@ -76,6 +76,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="150dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:alpha="0.75"
|
||||
android:background="@drawable/gradient_shape" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
|
@ -3,6 +3,7 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
|
@ -1,11 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<eu.kanade.tachiyomi.widget.AutofitRecyclerView
|
||||
android:id="@+id/catalogue_recycler"
|
||||
<eu.kanade.tachiyomi.widget.AutofitRecyclerView android:id="@+id/catalogue_recycler"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
style="@style/Theme.Widget.GridView.Catalogue"
|
||||
android:layout_width="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
android:layout_height="match_parent"
|
||||
android:columnWidth="120dp"
|
||||
android:clipToPadding="false"
|
||||
tools:listitem="@layout/catalogue_grid_item" />
|
||||
tools:listitem="@layout/catalogue_grid_item"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto" />
|
@ -4,6 +4,7 @@
|
||||
android:id="@+id/cat_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
44
app/src/main/res/layout/chapters_mat_item.xml
Normal file
44
app/src/main/res/layout/chapters_mat_item.xml
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectable_list_drawable">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/chapter_title"
|
||||
style="@style/TextAppearance.Regular.Body1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
app:layout_constraintBottom_toTopOf="@id/chapter_scanlator"
|
||||
app:layout_constraintEnd_toStartOf="@id/download_button"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Chapter 123 - The Real One" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/chapter_scanlator"
|
||||
style="@style/TextAppearance.Regular.Caption.Hint"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:maxLines="1"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/download_button"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/chapter_title"
|
||||
tools:text="3 days ago • On page 45 • Scanlator" />
|
||||
|
||||
<include layout="@layout/download_button"
|
||||
android:layout_height="0dp"
|
||||
android:layout_width="50dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
49
app/src/main/res/layout/download_button.xml
Normal file
49
app/src/main/res/layout/download_button.xml
Normal file
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<eu.kanade.tachiyomi.ui.download.DownloadButton xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/download_button"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/download_border"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/border_circle"
|
||||
android:padding="3dp"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/download_progress_indeterminate"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:visibility="gone"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true"
|
||||
android:indeterminateTint="@color/material_on_surface_disabled"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/download_progress"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:progressDrawable="@drawable/circle_progress"
|
||||
android:layout_gravity="center"
|
||||
android:progressTint="@color/material_green_800"
|
||||
android:progressBackgroundTint="@color/material_on_surface_disabled"/>
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/download_icon"
|
||||
android:tint="?colorAccent"
|
||||
android:layout_gravity="center"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:background="@drawable/round_ripple"
|
||||
android:padding="5dp"
|
||||
android:src="@drawable/ic_arrow_down_white_24dp" />
|
||||
</eu.kanade.tachiyomi.ui.download.DownloadButton>
|
@ -3,6 +3,7 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
|
@ -4,6 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:id="@+id/ext_swipe_refresh">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
|
@ -3,6 +3,7 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
|
@ -4,6 +4,7 @@
|
||||
android:layout_width="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/library_layout"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:layout_height="match_parent">
|
||||
<FrameLayout
|
||||
android:id="@+id/recycler_layout"
|
||||
|
@ -29,8 +29,10 @@
|
||||
<eu.kanade.tachiyomi.widget.ElevationAppBarLayout
|
||||
android:id="@+id/appbar"
|
||||
android:layout_width="match_parent"
|
||||
android:translationZ="0.1dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
android:stateListAnimator="@null"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
@ -65,7 +67,7 @@
|
||||
app:layout_constraintBottom_toTopOf="@+id/navigationView"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/appbar">
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
</com.bluelinelabs.conductor.ChangeHandlerFrameLayout>
|
||||
|
||||
@ -85,7 +87,6 @@
|
||||
app:tabBackground="@color/rippleColor"
|
||||
app:tabRippleColor="@color/rippleColor"
|
||||
app:tabTextColor="?attr/tabBarIconColor" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.drawerlayout.widget.DrawerLayout>
|
||||
|
348
app/src/main/res/layout/manga_header_item.xml
Normal file
348
app/src/main/res/layout/manga_header_item.xml
Normal file
@ -0,0 +1,348 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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/manga_header_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<View
|
||||
android:id="@+id/guideline"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="52dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/true_backdrop" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/guideline2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_percent="0.35" />
|
||||
|
||||
<View
|
||||
android:id="@+id/true_backdrop"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="200dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:background="@color/material_red_400" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/backdrop"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="200dp"
|
||||
android:alpha="0.1"
|
||||
android:scaleType="centerCrop"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@mipmap/ic_launcher" />
|
||||
|
||||
<View
|
||||
android:id="@+id/backdrop_gradient"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="300dp"
|
||||
android:background="@drawable/gradient_shape"
|
||||
android:backgroundTint="?android:attr/colorBackground"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/true_backdrop" />
|
||||
|
||||
<View
|
||||
android:id="@+id/top_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="30dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/top_line"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/top_line"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:barrierDirection="top"
|
||||
app:constraint_referenced_ids="cover_card,manga_layout" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/manga_layout"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/guideline"
|
||||
app:layout_constraintDimensionRatio="h,7:10"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/top_line">
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/cover_card"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/manga_layout"
|
||||
app:layout_constraintEnd_toEndOf="@id/manga_layout"
|
||||
app:layout_constraintStart_toStartOf="@id/manga_layout"
|
||||
app:layout_constraintTop_toTopOf="@id/top_line"
|
||||
app:layout_constraintVertical_bias="1.0">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/manga_cover"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@string/description_cover"
|
||||
android:maxHeight="300dp"
|
||||
tools:background="@color/material_grey_700"
|
||||
tools:src="@mipmap/ic_launcher" />
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_title"
|
||||
style="@style/TextAppearance.MaterialComponents.Headline5"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="4"
|
||||
android:text="@string/manga_info_full_title_label"
|
||||
android:textIsSelectable="false"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/manga_layout"
|
||||
app:layout_constraintTop_toTopOf="@id/cover_card"
|
||||
tools:text="Title Example" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_author"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/manga_info_author_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/manga_title"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_last_update_label"
|
||||
style="@style/TextAppearance.Medium.Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/manga_info_latest_data_label"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toStartOf="@id/manga_title"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_author" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_last_update"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBaseline_toBaselineOf="@+id/manga_last_update_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/manga_last_update_label" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/manga_status_source"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/manga_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/manga_last_update_label"
|
||||
tools:text="Completed • Mangadex (EN)" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/bottom_line"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="6dp"
|
||||
android:orientation="horizontal"
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="manga_status_source,manga_layout" />
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/button_layout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="14dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/manga_summary_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/bottom_line">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
style="@style/Theme.Widget.Button.RounededOutline"
|
||||
android:id="@+id/favorite_button"
|
||||
android:text="@string/add_to_library"
|
||||
app:icon="@drawable/ic_add_to_library_24dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
style="@style/Theme.Widget.Button.RounededOutline"
|
||||
android:layout_marginStart="6dp"
|
||||
android:id="@+id/track_button"
|
||||
android:text="@string/manga_tracking_tab"
|
||||
app:icon="@drawable/ic_sync_black_24dp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/download_button"
|
||||
style="@style/Theme.Widget.CustomImageButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="6dp"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:padding="5dp"
|
||||
android:src="@drawable/ic_edit_white_24dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/chapters_title"
|
||||
app:layout_constraintEnd_toStartOf="@id/sort_button" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/manga_summary_label"
|
||||
style="@style/TextAppearance.MaterialComponents.Headline6"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@string/description"
|
||||
android:textIsSelectable="false"
|
||||
android:textSize="17sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/button_layout"
|
||||
tools:text="About this manga" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_summary"
|
||||
style="@style/TextAppearance.Regular.Body1.Secondary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:maxLines="3"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBottom_toTopOf="@id/start_reading_button"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/manga_summary_label"
|
||||
tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." />
|
||||
|
||||
<View
|
||||
android:layout_width="75dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginEnd="30dp"
|
||||
android:background="@drawable/full_gradient"
|
||||
android:backgroundTint="?android:attr/colorBackground"
|
||||
app:layout_constraintBottom_toBottomOf="@id/manga_summary"
|
||||
app:layout_constraintEnd_toEndOf="@id/more_button" />
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:background="?android:attr/colorBackground"
|
||||
app:layout_constraintBottom_toBottomOf="@id/manga_summary"
|
||||
app:layout_constraintEnd_toEndOf="@id/more_button"
|
||||
app:layout_constraintStart_toStartOf="@id/more_button" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/more_button"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20sp"
|
||||
android:text="More"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?colorAccent"
|
||||
app:layout_constraintEnd_toEndOf="@id/manga_summary"
|
||||
app:layout_constraintTop_toTopOf="@id/manga_summary"
|
||||
app:rippleColor="@color/gray_button" />
|
||||
|
||||
<me.gujun.android.taggroup.TagGroup
|
||||
android:id="@+id/manga_genres_tags"
|
||||
style="@style/TagGroup"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:visibility="gone"
|
||||
app:atg_backgroundColor="@android:color/transparent"
|
||||
app:atg_borderColor="@color/md_blue_A400"
|
||||
app:atg_borderStrokeWidth="1dp"
|
||||
app:atg_textColor="@color/md_blue_A400"
|
||||
app:layout_constrainedHeight="true"
|
||||
app:layout_constraintBottom_toTopOf="@id/start_reading_button"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/manga_summary" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/start_reading_button"
|
||||
style="@style/Theme.Widget.Button.Primary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@string/start_reading"
|
||||
app:layout_constraintBottom_toTopOf="@id/chapters_title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_genres_tags"
|
||||
tools:text="Continue Reading Chapter 17.1" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/chapters_title"
|
||||
style="@style/TextAppearance.MaterialComponents.Headline6"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="18dp"
|
||||
android:text="@string/chapters"
|
||||
android:textSize="17sp"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/manga_summary_label"
|
||||
app:layout_constraintTop_toBottomOf="@id/start_reading_button" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/sort_button"
|
||||
style="@style/Theme.Widget.CustomImageButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:padding="5dp"
|
||||
android:src="@drawable/ic_swap_vert_white_24dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/chapters_title"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/filter_button"
|
||||
style="@style/Theme.Widget.CustomImageButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:padding="5dp"
|
||||
android:src="@drawable/ic_filter_list_white_24dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/chapters_title"
|
||||
app:layout_constraintEnd_toStartOf="@id/sort_button" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -87,7 +87,7 @@
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_full_title"
|
||||
android:id="@+id/manga_title"
|
||||
style="@style/TextAppearance.Medium.Title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
@ -110,7 +110,7 @@
|
||||
android:textIsSelectable="false"
|
||||
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_full_title" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/manga_title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_author"
|
||||
|
@ -4,4 +4,5 @@
|
||||
android:id="@+id/migration_recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:clipToPadding="false"/>
|
||||
|
@ -4,6 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:animateLayoutChanges="true">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
|
@ -4,6 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:animateLayoutChanges="true">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
|
@ -5,6 +5,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:orientation="vertical">
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipe_refresh"
|
||||
|
@ -4,6 +4,7 @@
|
||||
android:id="@+id/frame_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
|
6
app/src/main/res/menu/chapter_download.xml
Normal file
6
app/src/main/res/menu/chapter_download.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@+id/action_delete"
|
||||
android:title="@string/action_remove_download"
|
||||
android:icon="@drawable/ic_delete_white_24dp"/>
|
||||
</menu>
|
@ -23,6 +23,7 @@
|
||||
<string name="label_extensions">Extensions</string>
|
||||
<string name="label_extension_info">Extension info</string>
|
||||
<string name="label_help">Help</string>
|
||||
<string name="unlock">Unlock</string>
|
||||
<string name="unlock_library">Unlock to access Library</string>
|
||||
<plurals name="extensions_updates_available">
|
||||
<item quantity="one">Update available</item>
|
||||
@ -71,6 +72,7 @@
|
||||
<string name="action_bookmark">Bookmark</string>
|
||||
<string name="action_remove_bookmark">Remove bookmark</string>
|
||||
<string name="action_delete">Delete</string>
|
||||
<string name="action_remove_download">Remove download</string>
|
||||
<string name="action_update_library">Update library</string>
|
||||
<string name="action_edit">Edit</string>
|
||||
<string name="action_add">Add</string>
|
||||
@ -476,6 +478,7 @@
|
||||
<string name="licensed">Licensed</string>
|
||||
<string name="manga_info_full_title_label">Title</string>
|
||||
<string name="manga_added_library">Added to library</string>
|
||||
<string name="add_to_library">Add to Library</string>
|
||||
<string name="manga_removed_library">Removed from library</string>
|
||||
<string name="manga_info_author_label">Author</string>
|
||||
<string name="manga_info_artist_label">Artist</string>
|
||||
@ -494,6 +497,8 @@
|
||||
<string name="source_not_installed">Source not installed: %1$s</string>
|
||||
|
||||
<!-- Manga chapters fragment -->
|
||||
<string name="start_reader_chapter">Start Reading Chapter %1$s</string>
|
||||
<string name="continue_reader_chapter">Continue Reading Chapter %1$s</string>
|
||||
<string name="manga_chapters_tab">Chapters</string>
|
||||
<string name="display_mode_chapter">Chapter %1$s</string>
|
||||
<string name="chapter_downloaded">Downloaded</string>
|
||||
|
@ -234,6 +234,31 @@
|
||||
<item name="android:minWidth">48dip</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Widget.Button.RounededOutline" parent="Widget.MaterialComponents.Button.OutlinedButton">
|
||||
<item name="android:layout_width">wrap_content</item>
|
||||
<item name="android:textAllCaps">false</item>
|
||||
<item name="android:letterSpacing">0.0</item>
|
||||
<item name="android:layout_height">40dp</item>
|
||||
<item name="iconTint">?colorAccent</item>
|
||||
<item name="rippleColor">@color/fullRippleColor</item>
|
||||
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||
<item name="cornerRadius">15dp</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Widget.Button.Primary" parent="Widget.MaterialComponents.Button">
|
||||
<item name="android:textAllCaps">false</item>
|
||||
<item name="backgroundTint">?colorAccent</item>
|
||||
<item name="android:textColor">@android:color/white</item>
|
||||
<item name="android:letterSpacing">0.0</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Widget.CustomImageButton">
|
||||
<item name="android:background">@drawable/round_ripple</item>
|
||||
<item name="android:clickable">true</item>
|
||||
<item name="android:focusable">true</item>
|
||||
<item name="android:tint">?colorAccent</item>
|
||||
</style>
|
||||
|
||||
<!--===-->
|
||||
<!--OLD-->
|
||||
<!--===-->
|
||||
|
Loading…
Reference in New Issue
Block a user