Handle offline mode in shelf
parent
9b54ed6bc7
commit
74717e2b93
@ -0,0 +1,64 @@
|
|||||||
|
package org.koitharu.kotatsu.core.os
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.ConnectivityManager.NetworkCallback
|
||||||
|
import android.net.Network
|
||||||
|
import android.net.NetworkRequest
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
import kotlinx.coroutines.channels.ProducerScope
|
||||||
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
|
import kotlinx.coroutines.channels.trySendBlocking
|
||||||
|
import kotlinx.coroutines.flow.FlowCollector
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.callbackFlow
|
||||||
|
import org.koitharu.kotatsu.utils.ext.connectivityManager
|
||||||
|
import org.koitharu.kotatsu.utils.ext.isNetworkAvailable
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class NetworkStateObserver @Inject constructor(
|
||||||
|
@ApplicationContext context: Context,
|
||||||
|
) : StateFlow<Boolean> {
|
||||||
|
|
||||||
|
private val connectivityManager = context.connectivityManager
|
||||||
|
|
||||||
|
override val replayCache: List<Boolean>
|
||||||
|
get() = listOf(value)
|
||||||
|
|
||||||
|
override var value: Boolean = connectivityManager.isNetworkAvailable
|
||||||
|
|
||||||
|
override suspend fun collect(collector: FlowCollector<Boolean>): Nothing {
|
||||||
|
collector.emit(value)
|
||||||
|
while (true) {
|
||||||
|
observeImpl().collect(collector)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun observeImpl() = callbackFlow<Boolean> {
|
||||||
|
val request = NetworkRequest.Builder().build()
|
||||||
|
val callback = FlowNetworkCallback(this)
|
||||||
|
connectivityManager.registerNetworkCallback(request, callback)
|
||||||
|
awaitClose {
|
||||||
|
connectivityManager.unregisterNetworkCallback(callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class FlowNetworkCallback(
|
||||||
|
private val producerScope: ProducerScope<Boolean>,
|
||||||
|
) : NetworkCallback() {
|
||||||
|
override fun onAvailable(network: Network) = update()
|
||||||
|
|
||||||
|
override fun onLost(network: Network) = update()
|
||||||
|
|
||||||
|
override fun onUnavailable() = update()
|
||||||
|
|
||||||
|
private fun update() {
|
||||||
|
val newValue = connectivityManager.isNetworkAvailable
|
||||||
|
if (value != newValue) {
|
||||||
|
value = newValue
|
||||||
|
producerScope.trySendBlocking(newValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
package org.koitharu.kotatsu.list.ui.adapter
|
||||||
|
|
||||||
|
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
||||||
|
import org.koitharu.kotatsu.databinding.ItemEmptyCardBinding
|
||||||
|
import org.koitharu.kotatsu.list.ui.model.EmptyHint
|
||||||
|
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||||
|
import org.koitharu.kotatsu.utils.ext.setTextAndVisible
|
||||||
|
|
||||||
|
fun emptyHintAD(
|
||||||
|
listener: ListStateHolderListener,
|
||||||
|
) = adapterDelegateViewBinding<EmptyHint, ListModel, ItemEmptyCardBinding>(
|
||||||
|
{ inflater, parent -> ItemEmptyCardBinding.inflate(inflater, parent, false) },
|
||||||
|
) {
|
||||||
|
|
||||||
|
binding.buttonRetry.setOnClickListener { listener.onEmptyActionClick() }
|
||||||
|
|
||||||
|
bind {
|
||||||
|
binding.icon.setImageResource(item.icon)
|
||||||
|
binding.textPrimary.setText(item.textPrimary)
|
||||||
|
binding.textSecondary.setTextAndVisible(item.textSecondary)
|
||||||
|
binding.buttonRetry.setTextAndVisible(item.actionStringRes)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package org.koitharu.kotatsu.list.ui.model
|
||||||
|
|
||||||
|
import androidx.annotation.DrawableRes
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
|
||||||
|
class EmptyHint(
|
||||||
|
@DrawableRes icon: Int,
|
||||||
|
@StringRes textPrimary: Int,
|
||||||
|
@StringRes textSecondary: Int,
|
||||||
|
@StringRes actionStringRes: Int,
|
||||||
|
) : EmptyState(icon, textPrimary, textSecondary, actionStringRes) {
|
||||||
|
|
||||||
|
fun toState() = EmptyState(icon, textPrimary, textSecondary, actionStringRes)
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue