mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-09 19:55:11 +01:00
Made chapters swipeable to change read/bookmark status
This commit is contained in:
parent
87e86f81cf
commit
b331e12fde
@ -40,7 +40,7 @@ class Download(val source: HttpSource, val manga: Manga, val chapter: Chapter) {
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val CHECKED = -1
|
||||
const val NOT_DOWNLOADED = 0
|
||||
const val QUEUE = 1
|
||||
const val DOWNLOADING = 2
|
||||
|
@ -29,6 +29,10 @@ class DownloadButton @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||
R.drawable.filled_circle)?.mutate()
|
||||
private val borderCircle = ContextCompat.getDrawable(context,
|
||||
R.drawable.border_circle)?.mutate()
|
||||
private val downloadDrawable = ContextCompat.getDrawable(context,
|
||||
R.drawable.ic_arrow_down_white_24dp)?.mutate()
|
||||
private val checkDrawable = ContextCompat.getDrawable(context,
|
||||
R.drawable.ic_check_white_24dp)?.mutate()
|
||||
private var isAnimating = false
|
||||
private var iconAnimation: ObjectAnimator? = null
|
||||
|
||||
@ -38,7 +42,17 @@ class DownloadButton @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||
download_icon.alpha = 1f
|
||||
isAnimating = false
|
||||
}
|
||||
download_icon.setImageDrawable(if (state == Download.CHECKED)
|
||||
checkDrawable else downloadDrawable)
|
||||
when (state) {
|
||||
Download.CHECKED -> {
|
||||
download_progress.gone()
|
||||
download_border.visible()
|
||||
download_progress_indeterminate.gone()
|
||||
download_border.setImageDrawable(filledCircle)
|
||||
download_border.drawable.setTint(activeColor)
|
||||
download_icon.drawable.setTint(Color.WHITE)
|
||||
}
|
||||
Download.NOT_DOWNLOADED -> {
|
||||
download_border.visible()
|
||||
download_progress.gone()
|
||||
|
@ -441,7 +441,7 @@ open class LibraryController(
|
||||
|
||||
val searchItem = menu.findItem(R.id.action_search)
|
||||
val searchView = searchItem.actionView as SearchView
|
||||
searchView.queryHint = resources?.getString(R.string.search_hint)
|
||||
searchView.queryHint = resources?.getString(R.string.library_search_hint)
|
||||
|
||||
searchItem.collapseActionView()
|
||||
if (query.isNotEmpty()) {
|
||||
|
@ -59,10 +59,8 @@ import eu.kanade.tachiyomi.ui.setting.SettingsController
|
||||
import eu.kanade.tachiyomi.ui.setting.SettingsMainController
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import eu.kanade.tachiyomi.util.system.launchUI
|
||||
import eu.kanade.tachiyomi.util.view.gone
|
||||
import eu.kanade.tachiyomi.util.view.updateLayoutParams
|
||||
import eu.kanade.tachiyomi.util.view.updatePadding
|
||||
import eu.kanade.tachiyomi.util.view.visible
|
||||
import java.util.Date
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.math.abs
|
||||
@ -197,19 +195,6 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
|
||||
container.systemUiVisibility =
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
updateRecentsIcon()
|
||||
content.viewTreeObserver.addOnGlobalLayoutListener {
|
||||
val heightDiff: Int = content.rootView.height - content.height
|
||||
if (heightDiff > 200 && window.attributes.softInputMode == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) {
|
||||
// keyboard is open, hide layout
|
||||
bottom_nav.gone()
|
||||
} else if (bottom_nav.visibility == View.GONE && window.attributes.softInputMode == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) {
|
||||
// keyboard is hidden, show layout
|
||||
// use coroutine to delay so the bottom bar doesn't flash on top of the keyboard
|
||||
launchUI {
|
||||
bottom_nav.visible()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
supportActionBar?.setDisplayShowCustomEnabled(true)
|
||||
|
||||
|
@ -19,7 +19,6 @@ import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
@ -31,12 +30,14 @@ import android.view.inputmethod.InputMethodManager
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.view.ActionMode
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.core.content.pm.ShortcutInfoCompat
|
||||
import androidx.core.content.pm.ShortcutManagerCompat
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.graphics.drawable.IconCompat
|
||||
import androidx.palette.graphics.Palette
|
||||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.transition.ChangeBounds
|
||||
@ -95,6 +96,7 @@ import eu.kanade.tachiyomi.util.system.launchUI
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import eu.kanade.tachiyomi.util.view.doOnApplyWindowInsets
|
||||
import eu.kanade.tachiyomi.util.view.getText
|
||||
import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener
|
||||
import eu.kanade.tachiyomi.util.view.snack
|
||||
import eu.kanade.tachiyomi.util.view.updateLayoutParams
|
||||
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
|
||||
@ -114,6 +116,7 @@ class MangaDetailsController : BaseController,
|
||||
FlexibleAdapter.OnItemLongClickListener,
|
||||
ActionMode.Callback,
|
||||
ChaptersAdapter.MangaHeaderInterface,
|
||||
FlexibleAdapter.OnItemMoveListener,
|
||||
ChangeMangaCategoriesDialog.Listener {
|
||||
|
||||
constructor(
|
||||
@ -159,6 +162,11 @@ class MangaDetailsController : BaseController,
|
||||
private var editMangaDialog: EditMangaDialog? = null
|
||||
var refreshTracker: Int? = null
|
||||
|
||||
/**
|
||||
* Library search query.
|
||||
*/
|
||||
private var query = ""
|
||||
|
||||
/**
|
||||
* Adapter containing a list of chapters.
|
||||
*/
|
||||
@ -190,6 +198,7 @@ class MangaDetailsController : BaseController,
|
||||
adapter = ChaptersAdapter(this, view.context)
|
||||
|
||||
recycler.adapter = adapter
|
||||
adapter?.isSwipeEnabled = true
|
||||
recycler.layoutManager = LinearLayoutManager(view.context)
|
||||
recycler.addItemDecoration(
|
||||
DividerItemDecoration(
|
||||
@ -369,6 +378,13 @@ class MangaDetailsController : BaseController,
|
||||
presenter.preferences.theme()
|
||||
)
|
||||
) {
|
||||
if (forThis)
|
||||
(activity as MainActivity).appbar.context.setTheme(R.style
|
||||
.ThemeOverlay_AppCompat_DayNight_ActionBar)
|
||||
else
|
||||
(activity as MainActivity).appbar.context.setTheme(R.style
|
||||
.Theme_ActionBar_Dark_DayNight)
|
||||
|
||||
val iconPrimary = view?.context?.getResourceColor(
|
||||
if (forThis) android.R.attr.textColorPrimary
|
||||
else R.attr.actionBarTintColor
|
||||
@ -418,6 +434,8 @@ class MangaDetailsController : BaseController,
|
||||
adapter?.addSelection(position)
|
||||
(recycler.findViewHolderForAdapterPosition(position) as? BaseFlexibleViewHolder)
|
||||
?.toggleActivation()
|
||||
(recycler.findViewHolderForAdapterPosition(position) as? ChapterMatHolder)
|
||||
?.notifyStatus(Download.CHECKED, false, 0)
|
||||
startingDLChapterPos = position
|
||||
actionMode?.invalidate()
|
||||
} else {
|
||||
@ -446,24 +464,24 @@ class MangaDetailsController : BaseController,
|
||||
val adapter = adapter ?: return
|
||||
val item = (adapter.getItem(position) as? ChapterItem) ?: return
|
||||
val itemView = getHolder(item)?.itemView ?: return
|
||||
val popup = PopupMenu(itemView.context, itemView, Gravity.END)
|
||||
val popup = PopupMenu(itemView.context, itemView)
|
||||
|
||||
// Inflate our menu resource into the PopupMenu's Menu
|
||||
popup.menuInflater.inflate(R.menu.chapters_mat_single, popup.menu)
|
||||
|
||||
// Hide bookmark if bookmark
|
||||
popup.menu.findItem(R.id.action_bookmark).isVisible = !item.bookmark
|
||||
popup.menu.findItem(R.id.action_remove_bookmark).isVisible = item.bookmark
|
||||
popup.menu.findItem(R.id.action_bookmark).isVisible = false // !item.bookmark
|
||||
popup.menu.findItem(R.id.action_remove_bookmark).isVisible = false // item.bookmark
|
||||
|
||||
// Hide mark as unread when the chapter is unread
|
||||
if (!item.read && item.last_page_read == 0) {
|
||||
// if (!item.read && item.last_page_read == 0) {
|
||||
popup.menu.findItem(R.id.action_mark_as_unread).isVisible = false
|
||||
}
|
||||
// }
|
||||
|
||||
// Hide mark as read when the chapter is read
|
||||
if (item.read) {
|
||||
// if (item.read) {
|
||||
popup.menu.findItem(R.id.action_mark_as_read).isVisible = false
|
||||
}
|
||||
// }
|
||||
|
||||
// Set a listener so we are notified if a menu item is clicked
|
||||
popup.setOnMenuItemClickListener { menuItem ->
|
||||
@ -491,19 +509,30 @@ class MangaDetailsController : BaseController,
|
||||
}
|
||||
}
|
||||
|
||||
fun bookmarkChapter(position: Int) {
|
||||
val item = adapter?.getItem(position) as? ChapterItem ?: return
|
||||
bookmarkChapters(listOf(item), !item.bookmark)
|
||||
}
|
||||
|
||||
fun toggleReadChapter(position: Int) {
|
||||
val item = adapter?.getItem(position) as? ChapterItem ?: return
|
||||
if (!item.read) markAsRead(listOf(item), false)
|
||||
else markAsUnread(listOf(item), false)
|
||||
}
|
||||
|
||||
private fun bookmarkChapters(chapters: List<ChapterItem>, bookmarked: Boolean) {
|
||||
presenter.bookmarkChapters(chapters, bookmarked)
|
||||
}
|
||||
|
||||
private fun markAsRead(chapters: List<ChapterItem>) {
|
||||
presenter.markChaptersRead(chapters, true)
|
||||
private fun markAsRead(chapters: List<ChapterItem>, refresh: Boolean = true) {
|
||||
presenter.markChaptersRead(chapters, read = true)
|
||||
if (presenter.preferences.removeAfterMarkedAsRead()) {
|
||||
presenter.deleteChapters(chapters)
|
||||
}
|
||||
}
|
||||
|
||||
private fun markAsUnread(chapters: List<ChapterItem>) {
|
||||
presenter.markChaptersRead(chapters, false)
|
||||
private fun markAsUnread(chapters: List<ChapterItem>, refresh: Boolean = true) {
|
||||
presenter.markChaptersRead(chapters, read = false)
|
||||
}
|
||||
|
||||
private fun openChapter(chapter: Chapter) {
|
||||
@ -535,6 +564,25 @@ class MangaDetailsController : BaseController,
|
||||
?: Color.BLACK
|
||||
menu.findItem(R.id.action_download).icon?.mutate()?.setTint(iconPrimary)
|
||||
editItem.icon?.mutate()?.setTint(iconPrimary)
|
||||
|
||||
val searchItem = menu.findItem(R.id.action_search)
|
||||
val searchView = searchItem.actionView as SearchView
|
||||
searchView.queryHint = resources?.getString(R.string.chapter_search_hint)
|
||||
searchItem.icon?.mutate()?.setTint(iconPrimary)
|
||||
searchItem.collapseActionView()
|
||||
if (query.isNotEmpty()) {
|
||||
searchItem.expandActionView()
|
||||
searchView.setQuery(query, true)
|
||||
searchView.clearFocus()
|
||||
}
|
||||
|
||||
setOnQueryTextChangeListener(searchView) {
|
||||
query = it ?: ""
|
||||
adapter?.setFilter(query)
|
||||
adapter?.performFilter()
|
||||
true
|
||||
}
|
||||
searchItem.fixExpand(onExpand = { invalidateMenuOnExpand() })
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
@ -1033,6 +1081,12 @@ class MangaDetailsController : BaseController,
|
||||
override fun onDestroyActionMode(mode: ActionMode?) {
|
||||
actionMode = null
|
||||
setStatusBarAndToolbar()
|
||||
if (startingDLChapterPos != null) {
|
||||
val item = adapter?.getItem(startingDLChapterPos!!) as? ChapterItem
|
||||
(recycler.findViewHolderForAdapterPosition(startingDLChapterPos!!) as? ChapterMatHolder)?.notifyStatus(
|
||||
item?.status ?: Download.NOT_DOWNLOADED, false, 0
|
||||
)
|
||||
}
|
||||
startingDLChapterPos = null
|
||||
adapter?.mode = SelectableAdapter.Mode.IDLE
|
||||
adapter?.clearSelection()
|
||||
@ -1096,6 +1150,17 @@ class MangaDetailsController : BaseController,
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActionStateChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
|
||||
swipe_refresh.isEnabled = actionState != ItemTouchHelper.ACTION_STATE_SWIPE
|
||||
}
|
||||
|
||||
override fun onItemMove(fromPosition: Int, toPosition: Int) {
|
||||
}
|
||||
|
||||
override fun shouldMoveItem(fromPosition: Int, toPosition: Int): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun zoomImageFromThumb(thumbView: View) {
|
||||
// If there's an animation in progress, cancel it immediately and proceed with this one.
|
||||
currentAnimator?.cancel()
|
||||
|
@ -22,6 +22,10 @@ class MangaHeaderItem(val manga: Manga, private val startExpanded: Boolean) :
|
||||
return false
|
||||
}
|
||||
|
||||
override fun isSwipeable(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): MangaHeaderHolder {
|
||||
return MangaHeaderHolder(view, adapter as ChaptersAdapter, startExpanded)
|
||||
}
|
||||
|
@ -41,6 +41,10 @@ class ChapterItem(val chapter: Chapter, val manga: Manga) :
|
||||
return true
|
||||
}
|
||||
|
||||
override fun isSwipeable(): Boolean {
|
||||
return !isLocked
|
||||
}
|
||||
|
||||
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): ChapterMatHolder {
|
||||
return ChapterMatHolder(view, adapter as ChaptersAdapter)
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
package eu.kanade.tachiyomi.ui.manga.chapter
|
||||
|
||||
import android.animation.Animator
|
||||
import android.text.format.DateUtils
|
||||
import android.view.View
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.core.content.ContextCompat
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
@ -10,9 +12,9 @@ import eu.kanade.tachiyomi.source.LocalSource
|
||||
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
|
||||
import eu.kanade.tachiyomi.util.view.gone
|
||||
import eu.kanade.tachiyomi.util.view.visibleIf
|
||||
import java.util.Date
|
||||
import kotlinx.android.synthetic.main.chapters_mat_item.*
|
||||
import kotlinx.android.synthetic.main.download_button.*
|
||||
import java.util.Date
|
||||
|
||||
class ChapterMatHolder(
|
||||
private val view: View,
|
||||
@ -74,32 +76,93 @@ class ChapterMatHolder(
|
||||
if (isLocked) download_button.gone()
|
||||
|
||||
// Set correct text color
|
||||
chapter_title.setTextColor(if (chapter.read && !isLocked)
|
||||
adapter.readColor else adapter.unreadColor)
|
||||
chapter_title.setTextColor(
|
||||
if (chapter.read && !isLocked) adapter.readColor else adapter.unreadColor
|
||||
)
|
||||
if (chapter.bookmark && !isLocked) chapter_title.setTextColor(adapter.bookmarkedColor)
|
||||
|
||||
val statuses = mutableListOf<String>()
|
||||
|
||||
if (chapter.date_upload > 0) {
|
||||
statuses.add(DateUtils.getRelativeTimeSpanString(chapter.date_upload,
|
||||
Date().time, DateUtils.HOUR_IN_MILLIS).toString())
|
||||
statuses.add(
|
||||
DateUtils.getRelativeTimeSpanString(
|
||||
chapter.date_upload, Date().time, DateUtils.HOUR_IN_MILLIS
|
||||
).toString()
|
||||
)
|
||||
}
|
||||
|
||||
if (!chapter.read && chapter.last_page_read > 0 && chapter.pages_left > 0 && !isLocked) {
|
||||
statuses.add(itemView.resources.getQuantityString(R.plurals.pages_left, chapter
|
||||
.pages_left, chapter.pages_left))
|
||||
statuses.add(
|
||||
itemView.resources.getQuantityString(
|
||||
R.plurals.pages_left, chapter.pages_left, chapter.pages_left
|
||||
)
|
||||
)
|
||||
} else if (!chapter.read && chapter.last_page_read > 0 && !isLocked) {
|
||||
statuses.add(itemView.context.getString(R.string.chapter_progress, chapter
|
||||
.last_page_read + 1))
|
||||
statuses.add(
|
||||
itemView.context.getString(
|
||||
R.string.chapter_progress, chapter.last_page_read + 1
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (!chapter.scanlator.isNullOrBlank()) {
|
||||
statuses.add(chapter.scanlator!!)
|
||||
}
|
||||
|
||||
read.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
read.context, if (item.read) R.drawable.eye_off
|
||||
else R.drawable.eye
|
||||
)
|
||||
)
|
||||
bookmark.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
read.context, if (item.bookmark) R.drawable.star_off
|
||||
else R.drawable.star
|
||||
)
|
||||
)
|
||||
|
||||
chapter_scanlator.setTextColor(if (chapter.read) adapter.readColor else adapter.unreadColor)
|
||||
chapter_scanlator.text = statuses.joinToString(" • ")
|
||||
notifyStatus(item.status, item.isLocked, item.progress)
|
||||
notifyStatus(
|
||||
if (adapter.isSelected(adapterPosition)) Download.CHECKED else item.status,
|
||||
item.isLocked,
|
||||
item.progress
|
||||
)
|
||||
resetFrontView()
|
||||
}
|
||||
|
||||
override fun getFrontView(): View {
|
||||
return front_view
|
||||
}
|
||||
|
||||
override fun getRearRightView(): View {
|
||||
return right_view
|
||||
}
|
||||
|
||||
override fun getRearLeftView(): View {
|
||||
return left_view
|
||||
}
|
||||
|
||||
private fun resetFrontView() {
|
||||
if (front_view.translationX == 0f) return
|
||||
itemView.post {
|
||||
adapter.recyclerView.itemAnimator?.changeDuration = 0
|
||||
val anim = front_view.animate().translationX(0f).setDuration(250)
|
||||
anim.setListener(object : Animator.AnimatorListener {
|
||||
override fun onAnimationEnd(animation: Animator?) {
|
||||
adapter.itemTouchHelper.startSwipe(this@ChapterMatHolder)
|
||||
adapter.notifyItemChanged(adapterPosition)
|
||||
}
|
||||
|
||||
override fun onAnimationCancel(animation: Animator?) {}
|
||||
|
||||
override fun onAnimationRepeat(animation: Animator?) {}
|
||||
|
||||
override fun onAnimationStart(animation: Animator?) {}
|
||||
})
|
||||
anim.start()
|
||||
}
|
||||
}
|
||||
|
||||
fun notifyStatus(status: Int, locked: Boolean, progress: Int) = with(download_button) {
|
||||
|
@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.manga.chapter
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.tachiyomi.R
|
||||
@ -37,7 +38,7 @@ class ChaptersAdapter(
|
||||
|
||||
fun setChapters(items: List<ChapterItem>?) {
|
||||
this.items = items ?: emptyList()
|
||||
super.updateDataSet(items)
|
||||
performFilter()
|
||||
}
|
||||
|
||||
fun indexOf(item: ChapterItem): Int {
|
||||
@ -49,6 +50,24 @@ class ChaptersAdapter(
|
||||
SecureActivityDelegate.promptLockIfNeeded(activity)
|
||||
}
|
||||
|
||||
fun performFilter() {
|
||||
val s = getFilter(String::class.java)
|
||||
if (s.isNullOrBlank()) {
|
||||
updateDataSet(items)
|
||||
} else {
|
||||
updateDataSet(items.filter { it.name.contains(s, true) ||
|
||||
it.scanlator?.contains(s, true) == true })
|
||||
}
|
||||
}
|
||||
|
||||
override fun onItemSwiped(position: Int, direction: Int) {
|
||||
super.onItemSwiped(position, direction)
|
||||
when (direction) {
|
||||
ItemTouchHelper.RIGHT -> controller.bookmarkChapter(position)
|
||||
ItemTouchHelper.LEFT -> controller.toggleReadChapter(position)
|
||||
}
|
||||
}
|
||||
|
||||
interface MangaHeaderInterface {
|
||||
fun coverColor(): Int?
|
||||
fun mangaPresenter(): MangaDetailsPresenter
|
||||
|
@ -36,6 +36,8 @@ class TrackHolder(view: View, adapter: TrackAdapter) : BaseViewHolder(view) {
|
||||
track_title.text = track.title
|
||||
with(track_chapters) {
|
||||
text = when {
|
||||
track.total_chapters > 0 && track.last_chapter_read == track.total_chapters ->
|
||||
context.getString(R.string.all_chapters_read)
|
||||
track.total_chapters > 0 -> context.getString(
|
||||
R.string.chapter_x_of_y, track.last_chapter_read, track.total_chapters
|
||||
)
|
||||
|
@ -36,7 +36,7 @@ class SettingsMainController : SettingsController() {
|
||||
onClick { navigateTo(SettingsLibraryController()) }
|
||||
}
|
||||
preference {
|
||||
iconRes = R.drawable.ic_chrome_reader_mode_black_24dp
|
||||
iconRes = R.drawable.ic_read_24dp
|
||||
iconTint = tintColor
|
||||
titleRes = R.string.pref_category_reader
|
||||
onClick { navigateTo(SettingsReaderController()) }
|
||||
|
@ -14,6 +14,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewTreeObserver
|
||||
import android.view.WindowInsets
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.Button
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
@ -310,6 +311,10 @@ fun Controller.setOnQueryTextChangeListener(
|
||||
|
||||
override fun onQueryTextSubmit(query: String?): Boolean {
|
||||
if (router.backstack.lastOrNull()?.controller() == this@setOnQueryTextChangeListener) {
|
||||
val imm =
|
||||
activity?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
|
||||
?: return f(query)
|
||||
imm.hideSoftInputFromWindow(searchView.windowToken, 0)
|
||||
return f(query)
|
||||
}
|
||||
return true
|
||||
@ -320,6 +325,7 @@ fun Controller.setOnQueryTextChangeListener(
|
||||
fun Controller.scrollViewWith(
|
||||
recycler: RecyclerView,
|
||||
padBottom: Boolean = false,
|
||||
customPadding: Boolean = false,
|
||||
swipeRefreshLayout: SwipeRefreshLayout? = null,
|
||||
afterInsets: ((WindowInsets) -> Unit)? = null
|
||||
) {
|
||||
@ -331,7 +337,7 @@ fun Controller.scrollViewWith(
|
||||
array.recycle()
|
||||
recycler.doOnApplyWindowInsets { view, insets, _ ->
|
||||
val headerHeight = insets.systemWindowInsetTop + appBarHeight
|
||||
view.updatePaddingRelative(
|
||||
if (!customPadding) view.updatePaddingRelative(
|
||||
top = headerHeight,
|
||||
bottom = if (padBottom) insets.systemWindowInsetBottom else view.paddingBottom
|
||||
)
|
||||
@ -365,8 +371,10 @@ fun Controller.scrollViewWith(
|
||||
android.R.integer.config_shortAnimTime
|
||||
) ?: 0
|
||||
val closerToTop = abs(activity!!.appbar.y) - halfWay > 0
|
||||
val atTop =
|
||||
(recycler.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition() < 2
|
||||
val atTop = (!customPadding &&
|
||||
(recycler.layoutManager as LinearLayoutManager)
|
||||
.findFirstVisibleItemPosition() < 2) ||
|
||||
!recycler.canScrollVertically(-1)
|
||||
activity!!.appbar.animate().y(
|
||||
if (closerToTop && !atTop) (-activity!!.appbar.height.toFloat())
|
||||
else 0f
|
||||
|
8
app/src/main/res/drawable/eye.xml
Normal file
8
app/src/main/res/drawable/eye.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<!-- drawable/eye.xml -->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="#000" android:pathData="M12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15A3,3 0 0,0 15,12A3,3 0 0,0 12,9M12,17A5,5 0 0,1 7,12A5,5 0 0,1 12,7A5,5 0 0,1 17,12A5,5 0 0,1 12,17M12,4.5C7,4.5 2.73,7.61 1,12C2.73,16.39 7,19.5 12,19.5C17,19.5 21.27,16.39 23,12C21.27,7.61 17,4.5 12,4.5Z" />
|
||||
</vector>
|
8
app/src/main/res/drawable/eye_off.xml
Normal file
8
app/src/main/res/drawable/eye_off.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<!-- drawable/eye_off.xml -->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="#000" android:pathData="M11.83,9L15,12.16C15,12.11 15,12.05 15,12A3,3 0 0,0 12,9C11.94,9 11.89,9 11.83,9M7.53,9.8L9.08,11.35C9.03,11.56 9,11.77 9,12A3,3 0 0,0 12,15C12.22,15 12.44,14.97 12.65,14.92L14.2,16.47C13.53,16.8 12.79,17 12,17A5,5 0 0,1 7,12C7,11.21 7.2,10.47 7.53,9.8M2,4.27L4.28,6.55L4.73,7C3.08,8.3 1.78,10 1,12C2.73,16.39 7,19.5 12,19.5C13.55,19.5 15.03,19.2 16.38,18.66L16.81,19.08L19.73,22L21,20.73L3.27,3M12,7A5,5 0 0,1 17,12C17,12.64 16.87,13.26 16.64,13.82L19.57,16.75C21.07,15.5 22.27,13.86 23,12C21.27,7.61 17,4.5 12,4.5C10.6,4.5 9.26,4.75 8,5.2L10.17,7.35C10.74,7.13 11.35,7 12,7Z" />
|
||||
</vector>
|
8
app/src/main/res/drawable/star.xml
Normal file
8
app/src/main/res/drawable/star.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<!-- drawable/star.xml -->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="#000" android:pathData="M12,17.27L18.18,21L16.54,13.97L22,9.24L14.81,8.62L12,2L9.19,8.62L2,9.24L7.45,13.97L5.82,21L12,17.27Z" />
|
||||
</vector>
|
8
app/src/main/res/drawable/star_off.xml
Normal file
8
app/src/main/res/drawable/star_off.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<!-- drawable/star_off.xml -->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="#000" android:pathData="M2,5.27L3.28,4L20,20.72L18.73,22L17.05,20.31L12,17.27L5.82,21L7.45,13.97L2,9.24L5.66,8.93L2,5.27M12,2L14.81,8.62L22,9.24L16.54,13.97L16.77,14.95L9.56,7.74L12,2Z" />
|
||||
</vector>
|
@ -1,48 +1,103 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/chapter_layout"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectable_list_drawable">
|
||||
android:background="?android:attr/colorBackground">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/chapter_title"
|
||||
style="@style/TextAppearance.MaterialComponents.Body2"
|
||||
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.MaterialComponents.Caption"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:ellipsize="end"
|
||||
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_width="50dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
<FrameLayout
|
||||
android:id="@+id/right_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
android:background="@color/material_green_800"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/read"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:tint="@color/md_white_1000"
|
||||
android:layout_gravity="end|center"
|
||||
android:layout_marginEnd="21dp"
|
||||
android:src="@drawable/ic_read_24dp" />
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/left_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
android:background="@color/colorAccent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bookmark"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="start|center"
|
||||
android:layout_marginStart="21dp"
|
||||
android:tint="@color/md_white_1000"
|
||||
android:src="@drawable/ic_bookmark_white_24dp" />
|
||||
</FrameLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/front_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:background="?attr/selectable_list_drawable"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/chapter_title"
|
||||
style="@style/TextAppearance.MaterialComponents.Body2"
|
||||
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.MaterialComponents.Caption"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:ellipsize="end"
|
||||
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_width="50dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</FrameLayout>
|
@ -3,10 +3,11 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_edit"
|
||||
android:icon="@drawable/ic_edit_white_24dp"
|
||||
android:title="@string/action_edit"
|
||||
app:showAsAction="ifRoom" />
|
||||
android:id="@+id/action_search"
|
||||
android:icon="@drawable/ic_search_white_24dp"
|
||||
android:title="@string/action_search"
|
||||
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
||||
app:showAsAction="collapseActionView|ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_download"
|
||||
@ -44,6 +45,12 @@
|
||||
android:title="@string/action_mark_all_as_unread"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_edit"
|
||||
android:icon="@drawable/ic_edit_white_24dp"
|
||||
android:title="@string/action_edit"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_add_to_home_screen"
|
||||
android:title="@string/action_add_to_home_screen"
|
||||
|
@ -41,6 +41,9 @@
|
||||
</style>
|
||||
|
||||
<style name="Theme.Splash" parent="Theme.Tachiyomi">
|
||||
<item name="android:windowBackground">@drawable/splash_background</item>
|
||||
<item name="android:statusBarColor">@color/splashBackground</item>
|
||||
<item name="android:navigationBarColor">@color/splashBackground</item>
|
||||
<item name="android:windowLightStatusBar">false</item>
|
||||
</style>
|
||||
</resources>
|
@ -183,7 +183,7 @@
|
||||
<item quantity="many">Po %1$s minutach</item>
|
||||
<item quantity="other">Po %1$s minutach</item>
|
||||
</plurals>
|
||||
<string name="search_hint">Szukaj tytułu, tagów, źródła…</string>
|
||||
<string name="library_search_hint">Szukaj tytułu, tagów, źródła…</string>
|
||||
<string name="pref_refresh_covers_too">Automatycznie odśwież okładki</string>
|
||||
<string name="pref_refresh_covers_too_summary">Odśwież okładki w bibliotece podczas odświeżania biblioteki (nadpisuje lokalne okładki)</string>
|
||||
|
||||
|
@ -520,7 +520,7 @@
|
||||
|
||||
<string name="score">Оценка</string>
|
||||
|
||||
<string name="search_hint">Название, теги, источник</string>
|
||||
<string name="library_search_hint">Название, теги, источник</string>
|
||||
<string name="search_parameter">Параметр поиска (например: language:english)</string>
|
||||
|
||||
<string name="second_to_last">Предпоследняя</string>
|
||||
|
@ -244,7 +244,7 @@
|
||||
<item quantity="one">After %1$s minute</item>
|
||||
<item quantity="other">After %1$s minutes</item>
|
||||
</plurals>
|
||||
<string name="search_hint">Search title, tags, source</string>
|
||||
<string name="library_search_hint">Search title, tags, source</string>
|
||||
<string name="pref_refresh_covers_too">Automatically refresh covers</string>
|
||||
<string name="pref_refresh_covers_too_summary">Refresh covers in library as well
|
||||
when updating library (overwrites local covers)</string>
|
||||
@ -531,6 +531,7 @@
|
||||
<string name="remove_from_library">Remove from library</string>
|
||||
<string name="select_start_chapter">Select starting chapter</string>
|
||||
<string name="select_end_chapter">Select ending chapter</string>
|
||||
<string name="chapter_search_hint">Search chapters</string>
|
||||
|
||||
<!-- Manga chapters fragment -->
|
||||
<string name="start_reading">Start reading</string>
|
||||
|
Loading…
Reference in New Issue
Block a user