Improve pages preview on details screen
This commit is contained in:
@@ -82,7 +82,7 @@ afterEvaluate {
|
||||
}
|
||||
dependencies {
|
||||
//noinspection GradleDependency
|
||||
implementation('com.github.KotatsuApp:kotatsu-parsers:7c89f53988') {
|
||||
implementation('com.github.KotatsuApp:kotatsu-parsers:3feb84ac9e') {
|
||||
exclude group: 'org.json', module: 'json'
|
||||
}
|
||||
|
||||
|
||||
@@ -204,6 +204,9 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
||||
val isUnstableUpdatesAllowed: Boolean
|
||||
get() = prefs.getBoolean(KEY_UPDATES_UNSTABLE, false)
|
||||
|
||||
val defaultDetailsTab: Int
|
||||
get() = prefs.getString(KEY_DETAILS_TAB, null)?.toIntOrNull()?.coerceIn(0, 1) ?: 0
|
||||
|
||||
val isContentPrefetchEnabled: Boolean
|
||||
get() {
|
||||
if (isBackgroundNetworkRestricted()) {
|
||||
@@ -559,6 +562,7 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
||||
const val KEY_CF_INVERTED = "cf_inverted"
|
||||
const val KEY_CF_GRAYSCALE = "cf_grayscale"
|
||||
const val KEY_IGNORE_DOZE = "ignore_dose"
|
||||
const val KEY_DETAILS_TAB = "details_tab"
|
||||
|
||||
// About
|
||||
const val KEY_APP_UPDATE = "app_update"
|
||||
|
||||
@@ -38,4 +38,12 @@ abstract class BoundsScrollListener(
|
||||
firstVisibleItemPosition: Int,
|
||||
visibleItemCount: Int
|
||||
) = Unit
|
||||
|
||||
fun invalidate(recyclerView: RecyclerView) {
|
||||
onScrolled(recyclerView, 0, 0)
|
||||
}
|
||||
|
||||
fun postInvalidate(recyclerView: RecyclerView) = recyclerView.post {
|
||||
invalidate(recyclerView)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.koitharu.kotatsu.details.ui
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
@@ -57,9 +56,6 @@ class ChaptersFragment :
|
||||
checkNotNull(selectionController).attachToRecyclerView(this)
|
||||
setHasFixedSize(true)
|
||||
adapter = chaptersAdapter
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
scrollIndicators = if (resources.getBoolean(R.bool.is_tablet)) 0 else View.SCROLL_INDICATOR_TOP
|
||||
}
|
||||
}
|
||||
viewModel.isLoading.observe(viewLifecycleOwner, this::onLoadingStateChanged)
|
||||
viewModel.chapters.observe(viewLifecycleOwner, this::onChaptersChanged)
|
||||
|
||||
@@ -27,7 +27,6 @@ import androidx.core.view.isVisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.core.view.updatePadding
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.snackbar.BaseTransientBottomBar
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
@@ -38,8 +37,10 @@ import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
|
||||
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
|
||||
import org.koitharu.kotatsu.core.os.AppShortcutManager
|
||||
import org.koitharu.kotatsu.core.parser.MangaIntent
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.ui.BaseActivity
|
||||
import org.koitharu.kotatsu.core.ui.util.MenuInvalidator
|
||||
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
|
||||
import org.koitharu.kotatsu.core.util.ext.doOnExpansionsChanged
|
||||
import org.koitharu.kotatsu.core.util.ext.getAnimationDuration
|
||||
import org.koitharu.kotatsu.core.util.ext.getThemeColor
|
||||
@@ -77,6 +78,9 @@ class DetailsActivity :
|
||||
@Inject
|
||||
lateinit var appShortcutManager: AppShortcutManager
|
||||
|
||||
@Inject
|
||||
lateinit var settings: AppSettings
|
||||
|
||||
private var buttonTip: WeakReference<ButtonTip>? = null
|
||||
|
||||
private val viewModel: DetailsViewModel by viewModels()
|
||||
@@ -129,19 +133,16 @@ class DetailsActivity :
|
||||
},
|
||||
),
|
||||
)
|
||||
viewModel.onShowToast.observeEvent(this) {
|
||||
makeSnackbar(getString(it), Snackbar.LENGTH_SHORT).show()
|
||||
}
|
||||
viewModel.onActionDone.observeEvent(this, ReversibleActionObserver(viewBinding.containerDetails))
|
||||
viewModel.onShowTip.observeEvent(this) { showTip() }
|
||||
viewModel.historyInfo.observe(this, ::onHistoryChanged)
|
||||
viewModel.selectedBranch.observe(this) {
|
||||
viewBinding.toolbarChapters?.subtitle = it
|
||||
viewBinding.textViewSubtitle?.textAndVisible = it
|
||||
}
|
||||
viewModel.isChaptersReversed.observe(
|
||||
this,
|
||||
MenuInvalidator(viewBinding.toolbarChapters ?: this),
|
||||
)
|
||||
val chaptersMenuInvalidator = MenuInvalidator(viewBinding.toolbarChapters ?: this)
|
||||
viewModel.isChaptersReversed.observe(this, chaptersMenuInvalidator)
|
||||
viewModel.isChaptersEmpty.observe(this, chaptersMenuInvalidator)
|
||||
val menuInvalidator = MenuInvalidator(this)
|
||||
viewModel.favouriteCategories.observe(this, menuInvalidator)
|
||||
viewModel.remoteManga.observe(this, menuInvalidator)
|
||||
@@ -304,7 +305,7 @@ class DetailsActivity :
|
||||
tab.removeBadge()
|
||||
} else {
|
||||
val badge = tab.orCreateBadge
|
||||
badge.horizontalOffset = resources.getDimensionPixelOffset(R.dimen.margin_small)
|
||||
badge.horizontalOffsetWithText = -resources.getDimensionPixelOffset(R.dimen.margin_small)
|
||||
badge.number = count
|
||||
badge.isVisible = true
|
||||
}
|
||||
@@ -343,9 +344,8 @@ class DetailsActivity :
|
||||
val manga = viewModel.manga.value ?: return
|
||||
val chapterId = viewModel.historyInfo.value.history?.chapterId
|
||||
if (chapterId != null && manga.chapters?.none { x -> x.id == chapterId } == true) {
|
||||
val snackbar =
|
||||
makeSnackbar(getString(R.string.chapter_is_missing), Snackbar.LENGTH_SHORT)
|
||||
snackbar.show()
|
||||
Snackbar.make(viewBinding.containerDetails, R.string.chapter_is_missing, Snackbar.LENGTH_SHORT)
|
||||
.show()
|
||||
} else {
|
||||
startActivity(
|
||||
IntentBuilder(this)
|
||||
@@ -365,6 +365,7 @@ class DetailsActivity :
|
||||
val adapter = DetailsPagerAdapter(this)
|
||||
viewBinding.pager.adapter = adapter
|
||||
TabLayoutMediator(viewBinding.tabs, viewBinding.pager, adapter).attach()
|
||||
viewBinding.pager.setCurrentItem(settings.defaultDetailsTab, false)
|
||||
}
|
||||
|
||||
private fun showBottomSheet(isVisible: Boolean) {
|
||||
@@ -377,17 +378,6 @@ class DetailsActivity :
|
||||
view.isVisible = isVisible
|
||||
}
|
||||
|
||||
private fun makeSnackbar(
|
||||
text: CharSequence,
|
||||
@BaseTransientBottomBar.Duration duration: Int,
|
||||
): Snackbar {
|
||||
val sb = Snackbar.make(viewBinding.containerDetails, text, duration)
|
||||
if (viewBinding.layoutBottom?.isVisible == true) {
|
||||
sb.anchorView = viewBinding.toolbarChapters
|
||||
}
|
||||
return sb
|
||||
}
|
||||
|
||||
private class PrefetchObserver(
|
||||
private val context: Context,
|
||||
) : FlowCollector<List<ChapterListItem>?> {
|
||||
|
||||
@@ -10,8 +10,6 @@ import android.widget.Toast
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.Insets
|
||||
import androidx.core.text.buildSpannedString
|
||||
import androidx.core.text.color
|
||||
import androidx.core.text.method.LinkMovementMethodCompat
|
||||
import androidx.core.view.isGone
|
||||
import androidx.core.view.isVisible
|
||||
@@ -23,7 +21,6 @@ import coil.request.SuccessResult
|
||||
import coil.util.CoilUtils
|
||||
import com.google.android.material.chip.Chip
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.bookmarks.domain.Bookmark
|
||||
@@ -42,7 +39,6 @@ import org.koitharu.kotatsu.core.util.FileSize
|
||||
import org.koitharu.kotatsu.core.util.ext.crossfade
|
||||
import org.koitharu.kotatsu.core.util.ext.drawableTop
|
||||
import org.koitharu.kotatsu.core.util.ext.enqueueWith
|
||||
import org.koitharu.kotatsu.core.util.ext.getThemeColor
|
||||
import org.koitharu.kotatsu.core.util.ext.ifNullOrEmpty
|
||||
import org.koitharu.kotatsu.core.util.ext.isTextTruncated
|
||||
import org.koitharu.kotatsu.core.util.ext.observe
|
||||
@@ -75,7 +71,6 @@ import org.koitharu.kotatsu.scrobbling.common.ui.selector.ScrobblingSelectorShee
|
||||
import org.koitharu.kotatsu.search.ui.MangaListActivity
|
||||
import org.koitharu.kotatsu.search.ui.SearchActivity
|
||||
import javax.inject.Inject
|
||||
import com.google.android.material.R as materialR
|
||||
|
||||
@AndroidEntryPoint
|
||||
class DetailsFragment :
|
||||
@@ -122,7 +117,7 @@ class DetailsFragment :
|
||||
viewModel.description.observe(viewLifecycleOwner, ::onDescriptionChanged)
|
||||
viewModel.localSize.observe(viewLifecycleOwner, ::onLocalSizeChanged)
|
||||
viewModel.relatedManga.observe(viewLifecycleOwner, ::onRelatedMangaChanged)
|
||||
combine(viewModel.chapters, viewModel.newChaptersCount, ::Pair).observe(viewLifecycleOwner, ::onChaptersChanged)
|
||||
viewModel.chapters.observe(viewLifecycleOwner, ::onChaptersChanged)
|
||||
}
|
||||
|
||||
override fun onItemClick(item: Bookmark, view: View) {
|
||||
@@ -204,8 +199,7 @@ class DetailsFragment :
|
||||
}
|
||||
}
|
||||
|
||||
private fun onChaptersChanged(data: Pair<List<ChapterListItem>?, Int>) {
|
||||
val (chapters, newChapters) = data
|
||||
private fun onChaptersChanged(chapters: List<ChapterListItem>?) {
|
||||
val infoLayout = requireViewBinding().infoLayout
|
||||
if (chapters.isNullOrEmpty()) {
|
||||
infoLayout.textViewChapters.isVisible = false
|
||||
@@ -213,19 +207,7 @@ class DetailsFragment :
|
||||
val count = chapters.countChaptersByBranch()
|
||||
infoLayout.textViewChapters.isVisible = true
|
||||
val chaptersText = resources.getQuantityString(R.plurals.chapters, count, count)
|
||||
infoLayout.textViewChapters.text = if (newChapters == 0) {
|
||||
chaptersText
|
||||
} else {
|
||||
buildSpannedString {
|
||||
append(chaptersText)
|
||||
append(' ')
|
||||
color(infoLayout.textViewChapters.context.getThemeColor(materialR.attr.colorError)) {
|
||||
append("(+")
|
||||
append(newChapters.toString())
|
||||
append(')')
|
||||
}
|
||||
}
|
||||
}
|
||||
infoLayout.textViewChapters.text = chaptersText
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import kotlinx.coroutines.flow.mapLatest
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.plus
|
||||
import okio.FileNotFoundException
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.bookmarks.domain.Bookmark
|
||||
import org.koitharu.kotatsu.bookmarks.domain.BookmarksRepository
|
||||
@@ -30,6 +31,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.prefs.ListMode
|
||||
import org.koitharu.kotatsu.core.prefs.observeAsStateFlow
|
||||
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.core.ui.util.ReversibleAction
|
||||
import org.koitharu.kotatsu.core.util.ext.MutableEventFlow
|
||||
import org.koitharu.kotatsu.core.util.ext.call
|
||||
import org.koitharu.kotatsu.core.util.ext.computeSize
|
||||
@@ -80,7 +82,7 @@ class DetailsViewModel @Inject constructor(
|
||||
private val mangaId = intent.mangaId
|
||||
private var loadingJob: Job
|
||||
|
||||
val onShowToast = MutableEventFlow<Int>()
|
||||
val onActionDone = MutableEventFlow<ReversibleAction>()
|
||||
val onShowTip = MutableEventFlow<Unit>()
|
||||
val onSelectChapter = MutableEventFlow<Long>()
|
||||
val onDownloadStarted = MutableEventFlow<Unit>()
|
||||
@@ -234,7 +236,7 @@ class DetailsViewModel @Inject constructor(
|
||||
fun deleteLocal() {
|
||||
val m = details.value?.local?.manga
|
||||
if (m == null) {
|
||||
onShowToast.call(R.string.file_not_found)
|
||||
errorEvent.call(FileNotFoundException())
|
||||
return
|
||||
}
|
||||
launchLoadingJob(Dispatchers.Default) {
|
||||
@@ -246,7 +248,7 @@ class DetailsViewModel @Inject constructor(
|
||||
fun removeBookmark(bookmark: Bookmark) {
|
||||
launchJob(Dispatchers.Default) {
|
||||
bookmarksRepository.removeBookmark(bookmark)
|
||||
onShowToast.call(R.string.bookmark_removed)
|
||||
onActionDone.call(ReversibleAction(R.string.bookmark_removed, null))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.graphics.Insets
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
@@ -21,7 +23,6 @@ import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
|
||||
import org.koitharu.kotatsu.core.util.RecyclerViewScrollCallback
|
||||
import org.koitharu.kotatsu.core.util.ext.observe
|
||||
import org.koitharu.kotatsu.core.util.ext.observeEvent
|
||||
import org.koitharu.kotatsu.core.util.ext.plus
|
||||
import org.koitharu.kotatsu.core.util.ext.showOrHide
|
||||
import org.koitharu.kotatsu.databinding.FragmentPagesBinding
|
||||
import org.koitharu.kotatsu.details.ui.DetailsViewModel
|
||||
@@ -55,9 +56,6 @@ class PagesFragment :
|
||||
private var scrollListener: ScrollListener? = null
|
||||
|
||||
private val spanSizeLookup = SpanSizeLookup()
|
||||
private val listCommitCallback = Runnable {
|
||||
spanSizeLookup.invalidateCache()
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -66,7 +64,7 @@ class PagesFragment :
|
||||
detailsViewModel.history,
|
||||
detailsViewModel.selectedBranch,
|
||||
) { details, history, branch ->
|
||||
if (details?.isLoaded == true) {
|
||||
if (details != null && (details.isLoaded || details.chapters.isNotEmpty())) {
|
||||
PagesViewModel.State(details, history, branch)
|
||||
} else {
|
||||
null
|
||||
@@ -89,6 +87,7 @@ class PagesFragment :
|
||||
with(binding.recyclerView) {
|
||||
addItemDecoration(TypedListSpacingDecoration(context, false))
|
||||
adapter = thumbnailsAdapter
|
||||
setHasFixedSize(true)
|
||||
addOnLayoutChangeListener(spanResolver)
|
||||
spanResolver?.setGridSize(settings.gridSize / 100f, this)
|
||||
addOnScrollListener(ScrollListener().also { scrollListener = it })
|
||||
@@ -97,6 +96,7 @@ class PagesFragment :
|
||||
it.spanCount = checkNotNull(spanResolver).spanCount
|
||||
}
|
||||
}
|
||||
detailsViewModel.isChaptersEmpty.observe(viewLifecycleOwner, ::onNoChaptersChanged)
|
||||
viewModel.thumbnails.observe(viewLifecycleOwner, ::onThumbnailsChanged)
|
||||
viewModel.onError.observeEvent(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this))
|
||||
viewModel.isLoading.observe(viewLifecycleOwner) { binding.progressBar.showOrHide(it) }
|
||||
@@ -121,7 +121,7 @@ class PagesFragment :
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
private fun onThumbnailsChanged(list: List<ListModel>) {
|
||||
private suspend fun onThumbnailsChanged(list: List<ListModel>) {
|
||||
val adapter = thumbnailsAdapter ?: return
|
||||
if (adapter.itemCount == 0) {
|
||||
var position = list.indexOfFirst { it is PageThumbnail && it.isCurrent }
|
||||
@@ -134,12 +134,24 @@ class PagesFragment :
|
||||
0
|
||||
}
|
||||
val scrollCallback = RecyclerViewScrollCallback(requireViewBinding().recyclerView, position, offset)
|
||||
adapter.setItems(list, listCommitCallback + scrollCallback)
|
||||
adapter.emit(list)
|
||||
scrollCallback.run()
|
||||
} else {
|
||||
adapter.setItems(list, listCommitCallback)
|
||||
adapter.emit(list)
|
||||
}
|
||||
} else {
|
||||
adapter.setItems(list, listCommitCallback)
|
||||
adapter.emit(list)
|
||||
}
|
||||
spanSizeLookup.invalidateCache()
|
||||
viewBinding?.recyclerView?.let {
|
||||
scrollListener?.postInvalidate(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onNoChaptersChanged(isNoChapters: Boolean) {
|
||||
with(viewBinding ?: return) {
|
||||
textViewHolder.isVisible = isNoChapters
|
||||
recyclerView.isInvisible = isNoChapters
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,9 @@ class PagesViewModel @Inject constructor(
|
||||
private suspend fun doInit(state: State) {
|
||||
chaptersLoader.init(state.details)
|
||||
val initialChapterId = state.history?.chapterId ?: state.details.allChapters.firstOrNull()?.id ?: return
|
||||
chaptersLoader.loadSingleChapter(initialChapterId)
|
||||
if (!chaptersLoader.hasPages(initialChapterId)) {
|
||||
chaptersLoader.loadSingleChapter(initialChapterId)
|
||||
}
|
||||
updateList(state.history)
|
||||
}
|
||||
|
||||
|
||||
@@ -171,6 +171,9 @@ abstract class MangaListFragment :
|
||||
private suspend fun onListChanged(list: List<ListModel>) {
|
||||
listAdapter?.emit(list)
|
||||
spanSizeLookup.invalidateCache()
|
||||
viewBinding?.recyclerView?.let {
|
||||
paginationListener?.postInvalidate(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveException(e: Throwable) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.koitharu.kotatsu.reader.domain
|
||||
|
||||
import androidx.collection.LongSparseArray
|
||||
import androidx.collection.contains
|
||||
import org.koitharu.kotatsu.reader.ui.pager.ReaderPage
|
||||
|
||||
class ChapterPages private constructor(private val pages: ArrayDeque<ReaderPage>) : List<ReaderPage> by pages {
|
||||
@@ -57,6 +58,8 @@ class ChapterPages private constructor(private val pages: ArrayDeque<ReaderPage>
|
||||
return pages.subList(range.first, range.last + 1)
|
||||
}
|
||||
|
||||
operator fun contains(chapterId: Long) = indices.contains(chapterId)
|
||||
|
||||
private fun shiftIndices(delta: Int) {
|
||||
for (i in 0 until indices.size()) {
|
||||
val range = indices.valueAt(i)
|
||||
|
||||
@@ -67,6 +67,10 @@ class ChaptersLoader @Inject constructor(
|
||||
|
||||
fun peekChapter(chapterId: Long): MangaChapter? = chapters[chapterId]
|
||||
|
||||
fun hasPages(chapterId: Long): Boolean {
|
||||
return chapterId in chapterPages
|
||||
}
|
||||
|
||||
fun getPages(chapterId: Long): List<ReaderPage> {
|
||||
return chapterPages.subList(chapterId)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
android:scrollIndicators="top"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:listitem="@layout/item_chapter" />
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
android:scrollIndicators="top"
|
||||
app:bubbleSize="small"
|
||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||
tools:listitem="@layout/item_page_thumb"
|
||||
|
||||
@@ -17,13 +17,10 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView_state"
|
||||
style="@style/Widget.Kotatsu.TextView.Indicator.Vertical"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:drawablePadding="4dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:padding="4dp"
|
||||
android:textSize="12sp"
|
||||
android:visibility="gone"
|
||||
tools:drawableTopCompat="@drawable/ic_state_finished"
|
||||
tools:text="Completed"
|
||||
@@ -31,13 +28,10 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView_chapters"
|
||||
style="@style/Widget.Kotatsu.TextView.Indicator.Vertical"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:drawablePadding="4dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:padding="4dp"
|
||||
android:textSize="12sp"
|
||||
android:visibility="gone"
|
||||
app:drawableTopCompat="@drawable/ic_book_page"
|
||||
tools:text="52 chapters"
|
||||
@@ -45,28 +39,22 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView_nsfw"
|
||||
style="@style/Widget.Kotatsu.TextView.Indicator.Vertical"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:drawablePadding="4dp"
|
||||
android:gravity="center"
|
||||
android:padding="4dp"
|
||||
android:text="@string/nsfw"
|
||||
android:textSize="12sp"
|
||||
android:visibility="gone"
|
||||
app:drawableTopCompat="@drawable/ic_alert_outline"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView_source"
|
||||
style="@style/Widget.Kotatsu.TextView.Indicator.Vertical"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:drawablePadding="4dp"
|
||||
android:gravity="center"
|
||||
android:padding="4dp"
|
||||
android:textSize="12sp"
|
||||
android:visibility="gone"
|
||||
app:drawableTopCompat="@drawable/ic_web"
|
||||
tools:text="Source"
|
||||
@@ -74,13 +62,10 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView_size"
|
||||
style="@style/Widget.Kotatsu.TextView.Indicator.Vertical"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:drawablePadding="4dp"
|
||||
android:gravity="center"
|
||||
android:padding="4dp"
|
||||
android:textSize="12sp"
|
||||
android:visibility="gone"
|
||||
app:drawableTopCompat="@drawable/ic_storage"
|
||||
tools:text="1.8 GiB"
|
||||
|
||||
@@ -81,4 +81,8 @@
|
||||
<item>@string/frequency_twice_per_month</item>
|
||||
<item>@string/frequency_once_per_month</item>
|
||||
</string-array>
|
||||
<string-array name="details_tabs" translatable="false">
|
||||
<item>@string/chapters</item>
|
||||
<item>@string/pages</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
|
||||
@@ -70,4 +70,8 @@
|
||||
<item>14</item>
|
||||
<item>30</item>
|
||||
</string-array>
|
||||
<string-array name="details_tabs_values" translatable="false">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
|
||||
@@ -555,4 +555,5 @@
|
||||
<string name="rating_safe">Safe</string>
|
||||
<string name="rating_suggestive">Suggestive</string>
|
||||
<string name="rating_adult">Adult</string>
|
||||
<string name="default_tab">Default tab</string>
|
||||
</resources>
|
||||
|
||||
@@ -220,6 +220,16 @@
|
||||
<item name="android:textAppearance">?textAppearanceLabelMedium</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Kotatsu.TextView.Indicator.Vertical" parent="Widget.MaterialComponents.TextView">
|
||||
<item name="android:drawablePadding">4dp</item>
|
||||
<item name="android:gravity">center</item>
|
||||
<item name="android:textAlignment">center</item>
|
||||
<item name="android:padding">4dp</item>
|
||||
<item name="android:singleLine">true</item>
|
||||
<item name="android:textSize">12sp</item>
|
||||
<item name="android:elegantTextHeight">false</item>
|
||||
</style>
|
||||
|
||||
<style name="ThemeOverlay.Kotatsu.MainToolbar" parent="">
|
||||
<item name="colorControlHighlight">@color/selector_overlay</item>
|
||||
</style>
|
||||
|
||||
@@ -46,6 +46,19 @@
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="@string/details">
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="0"
|
||||
android:entries="@array/details_tabs"
|
||||
android:entryValues="@array/details_tabs_values"
|
||||
android:key="details_tab"
|
||||
android:title="@string/default_tab"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceScreen
|
||||
android:fragment="org.koitharu.kotatsu.settings.nav.NavConfigFragment"
|
||||
android:key="nav_main"
|
||||
|
||||
Reference in New Issue
Block a user