2019-02-12 19:22:37 +01:00
|
|
|
package com.keylesspalace.tusky.components.conversation
|
|
|
|
|
|
|
|
import androidx.annotation.MainThread
|
|
|
|
import androidx.lifecycle.LiveData
|
|
|
|
import androidx.lifecycle.MutableLiveData
|
|
|
|
import androidx.lifecycle.Transformations
|
|
|
|
import androidx.paging.Config
|
|
|
|
import androidx.paging.toLiveData
|
|
|
|
import com.keylesspalace.tusky.db.AppDatabase
|
|
|
|
import com.keylesspalace.tusky.entity.Conversation
|
|
|
|
import com.keylesspalace.tusky.network.MastodonApi
|
|
|
|
import com.keylesspalace.tusky.util.Listing
|
|
|
|
import com.keylesspalace.tusky.util.NetworkState
|
2019-02-13 19:21:04 +01:00
|
|
|
import io.reactivex.Single
|
|
|
|
import io.reactivex.schedulers.Schedulers
|
2019-02-12 19:22:37 +01:00
|
|
|
import retrofit2.Call
|
|
|
|
import retrofit2.Callback
|
|
|
|
import retrofit2.Response
|
|
|
|
import java.util.concurrent.Executors
|
|
|
|
import javax.inject.Inject
|
|
|
|
import javax.inject.Singleton
|
|
|
|
|
|
|
|
@Singleton
|
|
|
|
class ConversationsRepository @Inject constructor(val mastodonApi: MastodonApi, val db: AppDatabase) {
|
|
|
|
|
|
|
|
private val ioExecutor = Executors.newSingleThreadExecutor()
|
|
|
|
|
|
|
|
companion object {
|
|
|
|
private const val DEFAULT_PAGE_SIZE = 20
|
|
|
|
}
|
|
|
|
|
|
|
|
@MainThread
|
|
|
|
fun refresh(accountId: Long, showLoadingIndicator: Boolean): LiveData<NetworkState> {
|
|
|
|
val networkState = MutableLiveData<NetworkState>()
|
|
|
|
if(showLoadingIndicator) {
|
|
|
|
networkState.value = NetworkState.LOADING
|
|
|
|
}
|
|
|
|
|
2019-09-22 08:18:44 +02:00
|
|
|
mastodonApi.getConversations(limit = DEFAULT_PAGE_SIZE).enqueue(
|
2019-02-12 19:22:37 +01:00
|
|
|
object : Callback<List<Conversation>> {
|
|
|
|
override fun onFailure(call: Call<List<Conversation>>, t: Throwable) {
|
|
|
|
// retrofit calls this on main thread so safe to call set value
|
|
|
|
networkState.value = NetworkState.error(t.message)
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onResponse(call: Call<List<Conversation>>, response: Response<List<Conversation>>) {
|
|
|
|
ioExecutor.execute {
|
|
|
|
db.runInTransaction {
|
|
|
|
db.conversationDao().deleteForAccount(accountId)
|
|
|
|
insertResultIntoDb(accountId, response.body())
|
|
|
|
}
|
|
|
|
// since we are in bg thread now, post the result.
|
|
|
|
networkState.postValue(NetworkState.LOADED)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
return networkState
|
|
|
|
}
|
|
|
|
|
|
|
|
@MainThread
|
|
|
|
fun conversations(accountId: Long): Listing<ConversationEntity> {
|
|
|
|
// create a boundary callback which will observe when the user reaches to the edges of
|
|
|
|
// the list and update the database with extra data.
|
|
|
|
val boundaryCallback = ConversationsBoundaryCallback(
|
|
|
|
accountId = accountId,
|
|
|
|
mastodonApi = mastodonApi,
|
|
|
|
handleResponse = this::insertResultIntoDb,
|
|
|
|
ioExecutor = ioExecutor,
|
|
|
|
networkPageSize = DEFAULT_PAGE_SIZE)
|
|
|
|
// we are using a mutable live data to trigger refresh requests which eventually calls
|
|
|
|
// refresh method and gets a new live data. Each refresh request by the user becomes a newly
|
|
|
|
// dispatched data in refreshTrigger
|
|
|
|
val refreshTrigger = MutableLiveData<Unit>()
|
|
|
|
val refreshState = Transformations.switchMap(refreshTrigger) {
|
|
|
|
refresh(accountId, true)
|
|
|
|
}
|
|
|
|
|
|
|
|
// We use toLiveData Kotlin extension function here, you could also use LivePagedListBuilder
|
|
|
|
val livePagedList = db.conversationDao().conversationsForAccount(accountId).toLiveData(
|
|
|
|
config = Config(pageSize = DEFAULT_PAGE_SIZE, prefetchDistance = DEFAULT_PAGE_SIZE / 2, enablePlaceholders = false),
|
|
|
|
boundaryCallback = boundaryCallback
|
|
|
|
)
|
|
|
|
|
|
|
|
return Listing(
|
|
|
|
pagedList = livePagedList,
|
|
|
|
networkState = boundaryCallback.networkState,
|
|
|
|
retry = {
|
|
|
|
boundaryCallback.helper.retryAllFailed()
|
|
|
|
},
|
|
|
|
refresh = {
|
|
|
|
refreshTrigger.value = null
|
|
|
|
},
|
|
|
|
refreshState = refreshState
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-02-13 19:21:04 +01:00
|
|
|
fun deleteCacheForAccount(accountId: Long) {
|
|
|
|
Single.fromCallable {
|
|
|
|
db.conversationDao().deleteForAccount(accountId)
|
|
|
|
}.subscribeOn(Schedulers.io())
|
|
|
|
.subscribe()
|
|
|
|
}
|
|
|
|
|
2019-02-12 19:22:37 +01:00
|
|
|
private fun insertResultIntoDb(accountId: Long, result: List<Conversation>?) {
|
2019-02-13 21:14:12 +01:00
|
|
|
result?.filter { it.lastStatus != null }
|
|
|
|
?.map{ it.toEntity(accountId) }
|
|
|
|
?.let { db.conversationDao().insert(it) }
|
|
|
|
|
2019-02-12 19:22:37 +01:00
|
|
|
}
|
|
|
|
}
|