mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-03 23:58:55 +01:00 
			
		
		
		
	@@ -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.Toast
 | 
			
		||||
import androidx.activity.viewModels
 | 
			
		||||
import androidx.compose.runtime.collectAsState
 | 
			
		||||
import androidx.compose.runtime.getValue
 | 
			
		||||
import androidx.core.graphics.ColorUtils
 | 
			
		||||
import androidx.core.net.toUri
 | 
			
		||||
import androidx.core.transition.doOnEnd
 | 
			
		||||
@@ -46,6 +48,7 @@ import com.google.android.material.transition.platform.MaterialContainerTransfor
 | 
			
		||||
import dev.chrisbanes.insetter.applyInsetter
 | 
			
		||||
import eu.kanade.domain.base.BasePreferences
 | 
			
		||||
import eu.kanade.domain.manga.model.orientationType
 | 
			
		||||
import eu.kanade.presentation.reader.PageIndicatorText
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
 | 
			
		||||
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.view.copy
 | 
			
		||||
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.widget.listener.SimpleAnimationListener
 | 
			
		||||
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
 | 
			
		||||
        binding.pageSlider.addOnSliderTouchListener(
 | 
			
		||||
            object : Slider.OnSliderTouchListener {
 | 
			
		||||
@@ -785,7 +798,7 @@ class ReaderActivity : BaseActivity() {
 | 
			
		||||
     * other cases are handled with chapter transitions on the viewers and chapter preloading.
 | 
			
		||||
     */
 | 
			
		||||
    @Suppress("DEPRECATION")
 | 
			
		||||
    fun setProgressDialog(show: Boolean) {
 | 
			
		||||
    private fun setProgressDialog(show: Boolean) {
 | 
			
		||||
        progressDialog?.dismiss()
 | 
			
		||||
        progressDialog = if (show) {
 | 
			
		||||
            ProgressDialog.show(this, null, getString(R.string.loading), true)
 | 
			
		||||
@@ -836,9 +849,6 @@ class ReaderActivity : BaseActivity() {
 | 
			
		||||
        viewModel.onPageSelected(page)
 | 
			
		||||
        val pages = page.chapter.pages ?: return
 | 
			
		||||
 | 
			
		||||
        // Set bottom page number
 | 
			
		||||
        binding.pageNumber.text = "${page.number}/${pages.size}"
 | 
			
		||||
 | 
			
		||||
        // Set page numbers
 | 
			
		||||
        if (viewer !is R2LPagerViewer) {
 | 
			
		||||
            binding.leftPageText.text = "${page.number}"
 | 
			
		||||
 
 | 
			
		||||
@@ -412,6 +412,11 @@ class ReaderViewModel(
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 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
 | 
			
		||||
        val shouldTrack = !incognitoMode || hasTrackers
 | 
			
		||||
        if (selectedChapter.pages?.lastIndex == page.index && shouldTrack) {
 | 
			
		||||
@@ -875,6 +880,7 @@ class ReaderViewModel(
 | 
			
		||||
        val manga: Manga? = null,
 | 
			
		||||
        val viewerChapters: ViewerChapters? = null,
 | 
			
		||||
        val isLoadingAdjacentChapter: Boolean = false,
 | 
			
		||||
        val currentPage: Int = -1,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    sealed class Event {
 | 
			
		||||
 
 | 
			
		||||
@@ -15,9 +15,13 @@ object LocaleHelper {
 | 
			
		||||
     * Sorts by display name, except keeps the "all" (displayed as "Multi") locale at the top.
 | 
			
		||||
     */
 | 
			
		||||
    val comparator = { a: String, b: String ->
 | 
			
		||||
        if (a == "all") -1
 | 
			
		||||
        else if (b == "all") 1
 | 
			
		||||
        else getDisplayName(a).compareTo(getDisplayName(b))
 | 
			
		||||
        if (a == "all") {
 | 
			
		||||
            -1
 | 
			
		||||
        } else if (b == "all") {
 | 
			
		||||
            1
 | 
			
		||||
        } else {
 | 
			
		||||
            getDisplayName(a).compareTo(getDisplayName(b))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user