Reader fixes
This commit is contained in:
parent
d77a1e6925
commit
5b1f4f189b
5 changed files with 124 additions and 81 deletions
|
@ -1,71 +1,40 @@
|
|||
package eu.kanade.tachiyomi.ui.reader.viewer.base
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
import android.widget.Button
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.source.model.Page
|
||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||
import kotlinx.android.synthetic.main.page_decode_error.view.*
|
||||
|
||||
class PageDecodeErrorLayout(context: Context) : LinearLayout(context) {
|
||||
|
||||
/**
|
||||
* Text color for black theme.
|
||||
*/
|
||||
private val whiteColor = ContextCompat.getColor(context, R.color.textColorSecondaryDark)
|
||||
|
||||
/**
|
||||
* Text color for white theme.
|
||||
*/
|
||||
private val blackColor = ContextCompat.getColor(context, R.color.textColorSecondaryLight)
|
||||
class PageDecodeErrorLayout(
|
||||
val view: View,
|
||||
val page: Page,
|
||||
val theme: Int,
|
||||
val retryListener: () -> Unit
|
||||
) {
|
||||
|
||||
init {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
gravity = Gravity.CENTER
|
||||
val textColor = if (theme == ReaderActivity.BLACK_THEME)
|
||||
ContextCompat.getColor(view.context, R.color.textColorSecondaryDark)
|
||||
else
|
||||
ContextCompat.getColor(view.context, R.color.textColorSecondaryLight)
|
||||
|
||||
view.decode_error_text.setTextColor(textColor)
|
||||
|
||||
view.decode_retry.setOnClickListener {
|
||||
retryListener()
|
||||
}
|
||||
|
||||
view.decode_open_browser.setOnClickListener {
|
||||
val intent = android.content.Intent(android.content.Intent.ACTION_VIEW, Uri.parse(page.imageUrl))
|
||||
view.context.startActivity(intent)
|
||||
}
|
||||
|
||||
if (page.imageUrl == null) {
|
||||
view.decode_open_browser.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
constructor(context: Context, page: Page, theme: Int, retryListener: () -> Unit) : this(context) {
|
||||
|
||||
// Error message.
|
||||
TextView(context).apply {
|
||||
gravity = Gravity.CENTER
|
||||
setText(R.string.decode_image_error)
|
||||
setTextColor(if (theme == ReaderActivity.BLACK_THEME) whiteColor else blackColor)
|
||||
addView(this)
|
||||
}
|
||||
|
||||
// Retry button.
|
||||
Button(context).apply {
|
||||
layoutParams = ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
|
||||
setText(R.string.action_retry)
|
||||
setOnClickListener {
|
||||
retryListener()
|
||||
}
|
||||
addView(this)
|
||||
}
|
||||
|
||||
// Open in browser button.
|
||||
Button(context).apply {
|
||||
layoutParams = ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
|
||||
setText(R.string.action_open_in_browser)
|
||||
setOnClickListener { v ->
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(page.imageUrl))
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
if (page.imageUrl == null) {
|
||||
visibility = View.GONE
|
||||
}
|
||||
addView(this)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
|||
import eu.kanade.tachiyomi.ui.reader.viewer.base.PageDecodeErrorLayout
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.horizontal.RightToLeftReader
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.vertical.VerticalReader
|
||||
import eu.kanade.tachiyomi.util.inflate
|
||||
import kotlinx.android.synthetic.main.chapter_image.view.*
|
||||
import kotlinx.android.synthetic.main.item_pager_reader.view.*
|
||||
import rx.Observable
|
||||
|
@ -45,7 +46,7 @@ class PageView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
|
|||
/**
|
||||
* Layout of decode error.
|
||||
*/
|
||||
private var decodeErrorLayout: PageDecodeErrorLayout? = null
|
||||
private var decodeErrorLayout: View? = null
|
||||
|
||||
fun initialize(reader: PagerReader, page: Page) {
|
||||
val activity = reader.activity as ReaderActivity
|
||||
|
@ -243,14 +244,20 @@ class PageView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
|
|||
* Called when an image fails to decode.
|
||||
*/
|
||||
private fun onImageDecodeError(reader: PagerReader) {
|
||||
progress_container.visibility = View.GONE
|
||||
|
||||
if (decodeErrorLayout != null || !reader.isAdded) return
|
||||
|
||||
val activity = reader.activity as ReaderActivity
|
||||
|
||||
decodeErrorLayout = PageDecodeErrorLayout(context, page, activity.readerTheme,
|
||||
{ activity.presenter.retryPage(page) })
|
||||
|
||||
addView(decodeErrorLayout)
|
||||
val layout = inflate(R.layout.page_decode_error)
|
||||
PageDecodeErrorLayout(layout, page, activity.readerTheme, {
|
||||
if (reader.isAdded) {
|
||||
activity.presenter.retryPage(page)
|
||||
}
|
||||
})
|
||||
decodeErrorLayout = layout
|
||||
addView(layout)
|
||||
}
|
||||
|
||||
}
|
|
@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.R
|
|||
import eu.kanade.tachiyomi.data.source.model.Page
|
||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.base.PageDecodeErrorLayout
|
||||
import eu.kanade.tachiyomi.util.inflate
|
||||
import kotlinx.android.synthetic.main.chapter_image.view.*
|
||||
import kotlinx.android.synthetic.main.item_webtoon_reader.view.*
|
||||
import rx.Observable
|
||||
|
@ -49,7 +50,7 @@ class WebtoonHolder(private val view: View, private val adapter: WebtoonAdapter)
|
|||
/**
|
||||
* Layout of decode error.
|
||||
*/
|
||||
private var decodeErrorLayout: PageDecodeErrorLayout? = null
|
||||
private var decodeErrorLayout: View? = null
|
||||
|
||||
init {
|
||||
with(view.image_view) {
|
||||
|
@ -74,7 +75,7 @@ class WebtoonHolder(private val view: View, private val adapter: WebtoonAdapter)
|
|||
})
|
||||
}
|
||||
|
||||
view.progress_container.minimumHeight = view.resources.displayMetrics.heightPixels
|
||||
view.progress_container.minimumHeight = view.resources.displayMetrics.heightPixels * 2
|
||||
|
||||
view.setOnTouchListener(adapter.touchListener)
|
||||
view.retry_button.setOnTouchListener { v, event ->
|
||||
|
@ -107,6 +108,7 @@ class WebtoonHolder(private val view: View, private val adapter: WebtoonAdapter)
|
|||
decodeErrorLayout = null
|
||||
}
|
||||
view.image_view.recycle()
|
||||
view.image_view.visibility = View.GONE
|
||||
view.progress_container.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
|
@ -116,24 +118,25 @@ class WebtoonHolder(private val view: View, private val adapter: WebtoonAdapter)
|
|||
* @see processStatus
|
||||
*/
|
||||
private fun observeStatus() {
|
||||
unsubscribeStatus()
|
||||
|
||||
val page = page ?: return
|
||||
|
||||
val statusSubject = SerializedSubject(PublishSubject.create<Int>())
|
||||
page.setStatusSubject(statusSubject)
|
||||
|
||||
statusSubscription?.unsubscribe()
|
||||
statusSubscription = statusSubject.startWith(page.status)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { processStatus(it) }
|
||||
|
||||
webtoonReader.subscriptions.add(statusSubscription)
|
||||
addSubscription(statusSubscription)
|
||||
}
|
||||
|
||||
/**
|
||||
* Observes the progress of the page and updates view.
|
||||
*/
|
||||
private fun observeProgress() {
|
||||
progressSubscription?.unsubscribe()
|
||||
unsubscribeProgress()
|
||||
|
||||
val page = page ?: return
|
||||
|
||||
|
@ -145,6 +148,8 @@ class WebtoonHolder(private val view: View, private val adapter: WebtoonAdapter)
|
|||
.subscribe { progress ->
|
||||
view.progress_text.text = view.context.getString(R.string.download_progress, progress)
|
||||
}
|
||||
|
||||
addSubscription(progressSubscription)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -171,12 +176,27 @@ class WebtoonHolder(private val view: View, private val adapter: WebtoonAdapter)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a subscription to a list of subscriptions that will automatically unsubscribe when the
|
||||
* activity or the reader is destroyed.
|
||||
*/
|
||||
private fun addSubscription(subscription: Subscription?) {
|
||||
webtoonReader.subscriptions.add(subscription)
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a subscription from the list of subscriptions.
|
||||
*/
|
||||
private fun removeSubscription(subscription: Subscription?) {
|
||||
subscription?.let { webtoonReader.subscriptions.remove(it) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribes from the status subscription.
|
||||
*/
|
||||
private fun unsubscribeStatus() {
|
||||
page?.setStatusSubject(null)
|
||||
statusSubscription?.unsubscribe()
|
||||
removeSubscription(statusSubscription)
|
||||
statusSubscription = null
|
||||
}
|
||||
|
||||
|
@ -184,7 +204,7 @@ class WebtoonHolder(private val view: View, private val adapter: WebtoonAdapter)
|
|||
* Unsubscribes from the progress subscription.
|
||||
*/
|
||||
private fun unsubscribeProgress() {
|
||||
progressSubscription?.unsubscribe()
|
||||
removeSubscription(progressSubscription)
|
||||
progressSubscription = null
|
||||
}
|
||||
|
||||
|
@ -194,7 +214,7 @@ class WebtoonHolder(private val view: View, private val adapter: WebtoonAdapter)
|
|||
private fun setQueued() = with(view) {
|
||||
progress_container.visibility = View.VISIBLE
|
||||
progress_text.visibility = View.INVISIBLE
|
||||
retry_button.visibility = View.GONE
|
||||
retry_container.visibility = View.GONE
|
||||
decodeErrorLayout?.let {
|
||||
(view as ViewGroup).removeView(it)
|
||||
decodeErrorLayout = null
|
||||
|
@ -225,6 +245,7 @@ class WebtoonHolder(private val view: View, private val adapter: WebtoonAdapter)
|
|||
val path = page?.imagePath
|
||||
if (path != null && File(path).exists()) {
|
||||
progress_text.visibility = View.INVISIBLE
|
||||
image_view.visibility = View.VISIBLE
|
||||
image_view.setImage(ImageSource.uri(path))
|
||||
} else {
|
||||
page?.status = Page.ERROR
|
||||
|
@ -236,7 +257,7 @@ class WebtoonHolder(private val view: View, private val adapter: WebtoonAdapter)
|
|||
*/
|
||||
private fun setError() = with(view) {
|
||||
progress_container.visibility = View.GONE
|
||||
retry_button.visibility = View.VISIBLE
|
||||
retry_container.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -250,13 +271,19 @@ class WebtoonHolder(private val view: View, private val adapter: WebtoonAdapter)
|
|||
* Called when the image fails to decode.
|
||||
*/
|
||||
private fun onImageDecodeError() {
|
||||
view.progress_container.visibility = View.GONE
|
||||
|
||||
val page = page ?: return
|
||||
if (decodeErrorLayout != null || !webtoonReader.isAdded) return
|
||||
|
||||
decodeErrorLayout = PageDecodeErrorLayout(view.context, page, readerActivity.readerTheme,
|
||||
{ readerActivity.presenter.retryPage(page) })
|
||||
|
||||
(view as ViewGroup).addView(decodeErrorLayout)
|
||||
val layout = (view as ViewGroup).inflate(R.layout.page_decode_error)
|
||||
PageDecodeErrorLayout(layout, page, readerActivity.readerTheme, {
|
||||
if (webtoonReader.isAdded) {
|
||||
readerActivity.presenter.retryPage(page)
|
||||
}
|
||||
})
|
||||
decodeErrorLayout = layout
|
||||
view.addView(layout)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -32,12 +32,20 @@
|
|||
|
||||
<include layout="@layout/chapter_image"/>
|
||||
|
||||
<Button
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/retry_button"
|
||||
android:text="@string/action_retry"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"/>
|
||||
android:layout_height="192dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:id="@+id/retry_container"
|
||||
android:visibility="gone">
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/retry_button"
|
||||
android:text="@string/action_retry"
|
||||
android:layout_gravity="center"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</FrameLayout>
|
32
app/src/main/res/layout/page_decode_error.xml
Normal file
32
app/src/main/res/layout/page_decode_error.xml
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="512dp"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/decode_error_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/decode_image_error"
|
||||
android:layout_margin="8dp"
|
||||
android:gravity="center"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/decode_retry"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:text="@string/action_retry"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/decode_open_browser"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:text="@string/action_open_in_browser"/>
|
||||
|
||||
</LinearLayout>
|
Reference in a new issue