Caching toots (#809)

* Initial timeline cache implementation

* Fix build/DI errors for caching

* Rename timeline entities tables. Add migration. Add DB scheme file.

* Fix uniqueness problem, change offline strategy, improve mapping

* Try to merge in new statuses, fix bottom loading, fix saving spans.

* Fix reblogs IDs, fix inserting elements from top

* Send one more request to get latest timeline statuses

* Give Timeline placeholders string id. Rewrite Either in Kotlin

* Initial placeholder implementation for caching

* Fix crash on removing overlap statuses

* Migrate counters to long

* Remove unused counters. Add minimal TimelineDAOTest

* Fix bug with placeholder ID

* Update cache in response to events. Refactor TimelineCases

* Fix crash, reduce number of placeholders

* Fix crash, fix filtering, improve placeholder handling

* Fix migration, add 8-9 migration test

* Fix initial timeline update, remove more placeholders

* Add cleanup for old statuses

* Fix cleanup

* Delete ExampleInstrumentedTest

* Improve timeline UX regarding caching

* Fix typos

* Fix initial timeline update

* Cleanup/fix initial timeline update

* Workaround for weird behavior of first post on initial tl update.

* Change counter types back to int

* Clear timeline cache on logout

* Fix loading when timeline is completely empty

* Fix androidx migration issues

* Fix tests

* Apply caching feedback

* Save account emojis to cache

* Fix warnings and bugs
This commit is contained in:
Ivan Kupalov 2019-01-14 22:05:08 +01:00 committed by Konrad Pozniak
commit 3ab78a19bc
29 changed files with 1950 additions and 497 deletions

View file

@ -66,6 +66,12 @@ public interface MastodonApi {
@Query("since_id") String sinceId,
@Query("limit") Integer limit);
@GET("api/v1/timelines/home")
Single<List<Status>> homeTimelineSingle(
@Query("max_id") String maxId,
@Query("since_id") String sinceId,
@Query("limit") Integer limit);
@GET("api/v1/timelines/public")
Call<List<Status>> publicTimeline(
@Query("local") Boolean local,
@ -146,16 +152,16 @@ public interface MastodonApi {
Call<ResponseBody> deleteStatus(@Path("id") String statusId);
@POST("api/v1/statuses/{id}/reblog")
Call<Status> reblogStatus(@Path("id") String statusId);
Single<Status> reblogStatus(@Path("id") String statusId);
@POST("api/v1/statuses/{id}/unreblog")
Call<Status> unreblogStatus(@Path("id") String statusId);
Single<Status> unreblogStatus(@Path("id") String statusId);
@POST("api/v1/statuses/{id}/favourite")
Call<Status> favouriteStatus(@Path("id") String statusId);
Single<Status> favouriteStatus(@Path("id") String statusId);
@POST("api/v1/statuses/{id}/unfavourite")
Call<Status> unfavouriteStatus(@Path("id") String statusId);
Single<Status> unfavouriteStatus(@Path("id") String statusId);
@POST("api/v1/statuses/{id}/pin")
Single<Status> pinStatus(@Path("id") String statusId);

View file

@ -15,12 +15,10 @@
package com.keylesspalace.tusky.network
import com.keylesspalace.tusky.appstore.BlockEvent
import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.MuteEvent
import com.keylesspalace.tusky.appstore.StatusDeletedEvent
import com.keylesspalace.tusky.appstore.*
import com.keylesspalace.tusky.entity.Relationship
import com.keylesspalace.tusky.entity.Status
import io.reactivex.Single
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.addTo
import okhttp3.ResponseBody
@ -33,8 +31,8 @@ import retrofit2.Response
*/
interface TimelineCases {
fun reblogWithCallback(status: Status, reblog: Boolean, callback: Callback<Status>)
fun favouriteWithCallback(status: Status, favourite: Boolean, callback: Callback<Status>)
fun reblog(status: Status, reblog: Boolean): Single<Status>
fun favourite(status: Status, favourite: Boolean): Single<Status>
fun mute(id: String)
fun block(id: String)
fun delete(id: String)
@ -52,7 +50,7 @@ class TimelineCasesImpl(
*/
private val cancelDisposable = CompositeDisposable()
override fun reblogWithCallback(status: Status, reblog: Boolean, callback: Callback<Status>) {
override fun reblog(status: Status, reblog: Boolean): Single<Status> {
val id = status.actionableId
val call = if (reblog) {
@ -60,10 +58,12 @@ class TimelineCasesImpl(
} else {
mastodonApi.unreblogStatus(id)
}
call.enqueue(callback)
return call.doAfterSuccess {
eventHub.dispatch(ReblogEvent(status.id, reblog))
}
}
override fun favouriteWithCallback(status: Status, favourite: Boolean, callback: Callback<Status>) {
override fun favourite(status: Status, favourite: Boolean): Single<Status> {
val id = status.actionableId
val call = if (favourite) {
@ -71,7 +71,9 @@ class TimelineCasesImpl(
} else {
mastodonApi.unfavouriteStatus(id)
}
call.enqueue(callback)
return call.doAfterSuccess {
eventHub.dispatch(FavoriteEvent(status.id, favourite))
}
}
override fun mute(id: String) {