parent
f5ad95d78a
commit
3c79777e66
6 changed files with 73 additions and 65 deletions
|
@ -0,0 +1,44 @@
|
||||||
|
package eu.kanade.presentation.reader
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||||
|
import androidx.compose.ui.text.ExperimentalTextApi
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
|
||||||
|
@OptIn(ExperimentalTextApi::class)
|
||||||
|
@Composable
|
||||||
|
fun PageIndicatorText(
|
||||||
|
currentPage: Int,
|
||||||
|
totalPages: Int,
|
||||||
|
) {
|
||||||
|
if (currentPage <= 0 || totalPages <= 0) return
|
||||||
|
|
||||||
|
val text = "$currentPage / $totalPages"
|
||||||
|
|
||||||
|
Box {
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
color = Color(45, 45, 45),
|
||||||
|
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
letterSpacing = 1.sp,
|
||||||
|
style = TextStyle.Default.copy(
|
||||||
|
drawStyle = Stroke(width = 4f),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
color = Color(235, 235, 235),
|
||||||
|
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
letterSpacing = 1.sp,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,52 +0,0 @@
|
||||||
package eu.kanade.tachiyomi.ui.reader
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.text.Spannable
|
|
||||||
import android.text.SpannableString
|
|
||||||
import android.text.style.ScaleXSpan
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import androidx.appcompat.widget.AppCompatTextView
|
|
||||||
import eu.kanade.tachiyomi.widget.OutlineSpan
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Page indicator found at the bottom of the reader
|
|
||||||
*/
|
|
||||||
class PageIndicatorTextView(
|
|
||||||
context: Context,
|
|
||||||
attrs: AttributeSet? = null,
|
|
||||||
) : AppCompatTextView(context, attrs) {
|
|
||||||
|
|
||||||
init {
|
|
||||||
setTextColor(fillColor)
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
override fun setText(text: CharSequence?, type: BufferType?) {
|
|
||||||
// Add spaces at the start & end of the text, otherwise the stroke is cut-off because it's
|
|
||||||
// not taken into account when measuring the text (view's padding doesn't help).
|
|
||||||
val currText = " $text "
|
|
||||||
|
|
||||||
// Also add a bit of spacing between each character, as the stroke overlaps them
|
|
||||||
val finalText = SpannableString(currText.asIterable().joinToString("\u00A0")).apply {
|
|
||||||
// Apply text outline
|
|
||||||
setSpan(spanOutline, 1, length - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
||||||
|
|
||||||
for (i in 1..lastIndex step 2) {
|
|
||||||
setSpan(ScaleXSpan(0.2f), i, i + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
super.setText(finalText, BufferType.SPANNABLE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val fillColor = Color.rgb(235, 235, 235)
|
|
||||||
private val strokeColor = Color.rgb(45, 45, 45)
|
|
||||||
|
|
||||||
// A span object with text outlining properties
|
|
||||||
private val spanOutline = OutlineSpan(
|
|
||||||
strokeColor = strokeColor,
|
|
||||||
strokeWidth = 4f,
|
|
||||||
)
|
|
|
@ -29,6 +29,8 @@ import android.view.animation.AnimationUtils
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.core.graphics.ColorUtils
|
import androidx.core.graphics.ColorUtils
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.core.transition.doOnEnd
|
import androidx.core.transition.doOnEnd
|
||||||
|
@ -46,6 +48,7 @@ import com.google.android.material.transition.platform.MaterialContainerTransfor
|
||||||
import dev.chrisbanes.insetter.applyInsetter
|
import dev.chrisbanes.insetter.applyInsetter
|
||||||
import eu.kanade.domain.base.BasePreferences
|
import eu.kanade.domain.base.BasePreferences
|
||||||
import eu.kanade.domain.manga.model.orientationType
|
import eu.kanade.domain.manga.model.orientationType
|
||||||
|
import eu.kanade.presentation.reader.PageIndicatorText
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
||||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||||
|
@ -77,6 +80,7 @@ import eu.kanade.tachiyomi.util.system.toShareIntent
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import eu.kanade.tachiyomi.util.view.copy
|
import eu.kanade.tachiyomi.util.view.copy
|
||||||
import eu.kanade.tachiyomi.util.view.popupMenu
|
import eu.kanade.tachiyomi.util.view.popupMenu
|
||||||
|
import eu.kanade.tachiyomi.util.view.setComposeContent
|
||||||
import eu.kanade.tachiyomi.util.view.setTooltip
|
import eu.kanade.tachiyomi.util.view.setTooltip
|
||||||
import eu.kanade.tachiyomi.widget.listener.SimpleAnimationListener
|
import eu.kanade.tachiyomi.widget.listener.SimpleAnimationListener
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
@ -407,6 +411,15 @@ class ReaderActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.pageNumber.setComposeContent {
|
||||||
|
val state by viewModel.state.collectAsState()
|
||||||
|
|
||||||
|
PageIndicatorText(
|
||||||
|
currentPage = state.currentPage,
|
||||||
|
totalPages = state.viewerChapters?.currChapter?.pages?.size ?: -1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Init listeners on bottom menu
|
// Init listeners on bottom menu
|
||||||
binding.pageSlider.addOnSliderTouchListener(
|
binding.pageSlider.addOnSliderTouchListener(
|
||||||
object : Slider.OnSliderTouchListener {
|
object : Slider.OnSliderTouchListener {
|
||||||
|
@ -785,7 +798,7 @@ class ReaderActivity : BaseActivity() {
|
||||||
* other cases are handled with chapter transitions on the viewers and chapter preloading.
|
* other cases are handled with chapter transitions on the viewers and chapter preloading.
|
||||||
*/
|
*/
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
fun setProgressDialog(show: Boolean) {
|
private fun setProgressDialog(show: Boolean) {
|
||||||
progressDialog?.dismiss()
|
progressDialog?.dismiss()
|
||||||
progressDialog = if (show) {
|
progressDialog = if (show) {
|
||||||
ProgressDialog.show(this, null, getString(R.string.loading), true)
|
ProgressDialog.show(this, null, getString(R.string.loading), true)
|
||||||
|
@ -836,9 +849,6 @@ class ReaderActivity : BaseActivity() {
|
||||||
viewModel.onPageSelected(page)
|
viewModel.onPageSelected(page)
|
||||||
val pages = page.chapter.pages ?: return
|
val pages = page.chapter.pages ?: return
|
||||||
|
|
||||||
// Set bottom page number
|
|
||||||
binding.pageNumber.text = "${page.number}/${pages.size}"
|
|
||||||
|
|
||||||
// Set page numbers
|
// Set page numbers
|
||||||
if (viewer !is R2LPagerViewer) {
|
if (viewer !is R2LPagerViewer) {
|
||||||
binding.leftPageText.text = "${page.number}"
|
binding.leftPageText.text = "${page.number}"
|
||||||
|
|
|
@ -412,6 +412,11 @@ class ReaderViewModel(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save last page read and mark as read if needed
|
// Save last page read and mark as read if needed
|
||||||
|
mutableState.update {
|
||||||
|
it.copy(
|
||||||
|
currentPage = page.index + 1,
|
||||||
|
)
|
||||||
|
}
|
||||||
selectedChapter.chapter.last_page_read = page.index
|
selectedChapter.chapter.last_page_read = page.index
|
||||||
val shouldTrack = !incognitoMode || hasTrackers
|
val shouldTrack = !incognitoMode || hasTrackers
|
||||||
if (selectedChapter.pages?.lastIndex == page.index && shouldTrack) {
|
if (selectedChapter.pages?.lastIndex == page.index && shouldTrack) {
|
||||||
|
@ -875,6 +880,7 @@ class ReaderViewModel(
|
||||||
val manga: Manga? = null,
|
val manga: Manga? = null,
|
||||||
val viewerChapters: ViewerChapters? = null,
|
val viewerChapters: ViewerChapters? = null,
|
||||||
val isLoadingAdjacentChapter: Boolean = false,
|
val isLoadingAdjacentChapter: Boolean = false,
|
||||||
|
val currentPage: Int = -1,
|
||||||
)
|
)
|
||||||
|
|
||||||
sealed class Event {
|
sealed class Event {
|
||||||
|
|
|
@ -15,9 +15,13 @@ object LocaleHelper {
|
||||||
* Sorts by display name, except keeps the "all" (displayed as "Multi") locale at the top.
|
* Sorts by display name, except keeps the "all" (displayed as "Multi") locale at the top.
|
||||||
*/
|
*/
|
||||||
val comparator = { a: String, b: String ->
|
val comparator = { a: String, b: String ->
|
||||||
if (a == "all") -1
|
if (a == "all") {
|
||||||
else if (b == "all") 1
|
-1
|
||||||
else getDisplayName(a).compareTo(getDisplayName(b))
|
} else if (b == "all") {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
getDisplayName(a).compareTo(getDisplayName(b))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -16,15 +16,11 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:descendantFocusability="blocksDescendants" />
|
android:descendantFocusability="blocksDescendants" />
|
||||||
|
|
||||||
<eu.kanade.tachiyomi.ui.reader.PageIndicatorTextView
|
<androidx.compose.ui.platform.ComposeView
|
||||||
android:id="@+id/page_number"
|
android:id="@+id/page_number"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom|center_horizontal"
|
android:layout_gravity="bottom|center_horizontal" />
|
||||||
android:padding="4dp"
|
|
||||||
android:textAppearance="?attr/textAppearanceBodySmall"
|
|
||||||
android:textDirection="ltr"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
|
Reference in a new issue