Reader fixes

This commit is contained in:
len 2016-10-24 22:16:50 +02:00
parent d77a1e6925
commit 5b1f4f189b
5 changed files with 124 additions and 81 deletions

View file

@ -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)
}
}
}

View file

@ -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)
}
}

View file

@ -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)
}
/**

View file

@ -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>

View 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>