From 69f27b92e5e60fae85cd1f315f73bc7926e5ee69 Mon Sep 17 00:00:00 2001 From: Adolfo Santiago Date: Sun, 3 Apr 2022 10:24:46 +0200 Subject: [PATCH] Format TimelineRepository.kt --- .../tusky/repository/TimelineRepository.kt | 464 +++++++++--------- 1 file changed, 242 insertions(+), 222 deletions(-) diff --git a/husky/app/src/main/java/com/keylesspalace/tusky/repository/TimelineRepository.kt b/husky/app/src/main/java/com/keylesspalace/tusky/repository/TimelineRepository.kt index 58233f3..b90a0da 100644 --- a/husky/app/src/main/java/com/keylesspalace/tusky/repository/TimelineRepository.kt +++ b/husky/app/src/main/java/com/keylesspalace/tusky/repository/TimelineRepository.kt @@ -19,7 +19,6 @@ import io.reactivex.schedulers.Schedulers import java.io.IOException import java.util.* import java.util.concurrent.TimeUnit -import kotlin.collections.ArrayList data class Placeholder(val id: String) @@ -30,8 +29,10 @@ enum class TimelineRequestMode { } interface TimelineRepository { - fun getStatuses(maxId: String?, sinceId: String?, sincedIdMinusOne: String?, limit: Int, - requestMode: TimelineRequestMode): Single> + fun getStatuses( + maxId: String?, sinceId: String?, sincedIdMinusOne: String?, limit: Int, + requestMode: TimelineRequestMode + ): Single> companion object { val CLEANUP_INTERVAL = TimeUnit.DAYS.toMillis(14) @@ -39,104 +40,110 @@ interface TimelineRepository { } class TimelineRepositoryImpl( - private val timelineDao: TimelineDao, - private val mastodonApi: MastodonApi, - private val accountManager: AccountManager, - private val gson: Gson + private val timelineDao: TimelineDao, + private val mastodonApi: MastodonApi, + private val accountManager: AccountManager, + private val gson: Gson ) : TimelineRepository { init { this.cleanup() } - override fun getStatuses(maxId: String?, sinceId: String?, sincedIdMinusOne: String?, - limit: Int, requestMode: TimelineRequestMode + override fun getStatuses( + maxId: String?, sinceId: String?, sincedIdMinusOne: String?, + limit: Int, requestMode: TimelineRequestMode ): Single> { val acc = accountManager.activeAccount ?: throw IllegalStateException() val accountId = acc.id - return if (requestMode == DISK) { + return if(requestMode == DISK) { this.getStatusesFromDb(accountId, maxId, sinceId, limit) } else { getStatusesFromNetwork(maxId, sinceId, sincedIdMinusOne, limit, accountId, requestMode) } } - private fun getStatusesFromNetwork(maxId: String?, sinceId: String?, - sinceIdMinusOne: String?, limit: Int, - accountId: Long, requestMode: TimelineRequestMode + private fun getStatusesFromNetwork( + maxId: String?, sinceId: String?, + sinceIdMinusOne: String?, limit: Int, + accountId: Long, requestMode: TimelineRequestMode ): Single> { return mastodonApi.homeTimelineSingle(maxId, sinceIdMinusOne, limit + 1) - .map { statuses -> - this.saveStatusesToDb(accountId, statuses, maxId, sinceId) - } - .flatMap { statuses -> - this.addFromDbIfNeeded(accountId, statuses, maxId, sinceId, limit, requestMode) - } - .onErrorResumeNext { error -> - if (error is IOException && requestMode != NETWORK) { - this.getStatusesFromDb(accountId, maxId, sinceId, limit) - } else { - Single.error(error) - } + .map { statuses -> + this.saveStatusesToDb(accountId, statuses, maxId, sinceId) + } + .flatMap { statuses -> + this.addFromDbIfNeeded(accountId, statuses, maxId, sinceId, limit, requestMode) + } + .onErrorResumeNext { error -> + if(error is IOException && requestMode != NETWORK) { + this.getStatusesFromDb(accountId, maxId, sinceId, limit) + } else { + Single.error(error) } + } } - private fun addFromDbIfNeeded(accountId: Long, statuses: List>, - maxId: String?, sinceId: String?, limit: Int, - requestMode: TimelineRequestMode + private fun addFromDbIfNeeded( + accountId: Long, statuses: List>, + maxId: String?, sinceId: String?, limit: Int, + requestMode: TimelineRequestMode ): Single>? { - return if (requestMode != NETWORK && statuses.size < 2) { - val newMaxID = if (statuses.isEmpty()) { + return if(requestMode != NETWORK && statuses.size < 2) { + val newMaxID = if(statuses.isEmpty()) { maxId } else { statuses.last { it.isRight() }.asRight().id } this.getStatusesFromDb(accountId, newMaxID, sinceId, limit) - .map { fromDb -> - // If it's just placeholders and less than limit (so we exhausted both - // db and server at this point) - if (fromDb.size < limit && fromDb.all { !it.isRight() }) { - statuses - } else { - statuses + fromDb - } + .map { fromDb -> + // If it's just placeholders and less than limit (so we exhausted both + // db and server at this point) + if(fromDb.size < limit && fromDb.all { !it.isRight() }) { + statuses + } else { + statuses + fromDb } + } } else { Single.just(statuses) } } - private fun getStatusesFromDb(accountId: Long, maxId: String?, sinceId: String?, - limit: Int): Single> { + private fun getStatusesFromDb( + accountId: Long, maxId: String?, sinceId: String?, + limit: Int + ): Single> { return timelineDao.getStatusesForAccount(accountId, maxId, sinceId, limit) - .subscribeOn(Schedulers.io()) - .map { statuses -> - statuses.map { it.toStatus() } - } + .subscribeOn(Schedulers.io()) + .map { statuses -> + statuses.map { it.toStatus() } + } } - private fun saveStatusesToDb(accountId: Long, statuses: List, - maxId: String?, sinceId: String? + private fun saveStatusesToDb( + accountId: Long, statuses: List, + maxId: String?, sinceId: String? ): List> { var placeholderToInsert: Placeholder? = null // Look for overlap - val resultStatuses = if (statuses.isNotEmpty() && sinceId != null) { + val resultStatuses = if(statuses.isNotEmpty() && sinceId != null) { val indexOfSince = statuses.indexOfLast { it.id == sinceId } - if (indexOfSince == -1) { + if(indexOfSince == -1) { // We didn't find the status which must be there. Add a placeholder placeholderToInsert = Placeholder(sinceId.inc()) statuses.mapTo(mutableListOf(), Status::lift) - .apply { - add(Either.Left(placeholderToInsert)) - } + .apply { + add(Either.Left(placeholderToInsert)) + } } else { // There was an overlap. Remove all overlapped statuses. No need for a placeholder. statuses.mapTo(mutableListOf(), Status::lift) - .apply { - subList(indexOfSince, size).clear() - } + .apply { + subList(indexOfSince, size).clear() + } } } else { // Just a normal case. @@ -149,11 +156,11 @@ class TimelineRepositoryImpl( timelineDao.deleteRange(accountId, statuses.last().id, statuses.first().id) } - for (status in statuses) { + for(status in statuses) { timelineDao.insertInTransaction( - status.toEntity(accountId, gson), - status.account.toEntity(accountId, gson), - status.reblog?.account?.toEntity(accountId, gson) + status.toEntity(accountId, gson), + status.account.toEntity(accountId, gson), + status.reblog?.account?.toEntity(accountId, gson) ) } @@ -163,21 +170,24 @@ class TimelineRepositoryImpl( // If we're loading in the bottom insert placeholder after every load // (for requests on next launches) but not return it. - if (sinceId == null && statuses.isNotEmpty()) { + if(sinceId == null && statuses.isNotEmpty()) { timelineDao.insertStatusIfNotThere( - Placeholder(statuses.last().id.dec()).toEntity(accountId)) + Placeholder(statuses.last().id.dec()).toEntity(accountId) + ) } // There may be placeholders which we thought could be from our TL but they are not - if (statuses.size > 2) { - timelineDao.removeAllPlaceholdersBetween(accountId, statuses.first().id, - statuses.last().id) - } else if (placeholderToInsert == null && maxId != null && sinceId != null) { + if(statuses.size > 2) { + timelineDao.removeAllPlaceholdersBetween( + accountId, statuses.first().id, + statuses.last().id + ) + } else if(placeholderToInsert == null && maxId != null && sinceId != null) { timelineDao.removeAllPlaceholdersBetween(accountId, maxId, sinceId) } } - .subscribeOn(Schedulers.io()) - .subscribe() + .subscribeOn(Schedulers.io()) + .subscribe() return resultStatuses } @@ -190,101 +200,109 @@ class TimelineRepositoryImpl( } private fun TimelineStatusWithAccount.toStatus(): TimelineStatus { - if (this.status.authorServerId == null) { + if(this.status.authorServerId == null) { return Either.Left(Placeholder(this.status.serverId)) } - val attachments: ArrayList = gson.fromJson(status.attachments, - object : TypeToken>() {}.type) ?: ArrayList() - val mentions: Array = gson.fromJson(status.mentions, - Array::class.java) ?: arrayOf() + val attachments: ArrayList = gson.fromJson( + status.attachments, + object : TypeToken>() {}.type + ) ?: ArrayList() + val mentions: Array = gson.fromJson( + status.mentions, + Array::class.java + ) ?: arrayOf() val application = gson.fromJson(status.application, Status.Application::class.java) - val emojis: List = gson.fromJson(status.emojis, - object : TypeToken>() {}.type) ?: listOf() + val emojis: List = gson.fromJson( + status.emojis, + object : TypeToken>() {}.type + ) ?: listOf() val poll: Poll? = gson.fromJson(status.poll, Poll::class.java) val pleroma = gson.fromJson(status.pleroma, Status.PleromaStatus::class.java) val reblog = status.reblogServerId?.let { id -> Status( - id = id, - url = status.url, - account = account.toAccount(gson), - inReplyToId = status.inReplyToId, - inReplyToAccountId = status.inReplyToAccountId, - reblog = null, - content = status.content?.parseAsHtml()?.trimTrailingWhitespace() ?: SpannedString(""), - createdAt = Date(status.createdAt), - emojis = emojis, - reblogsCount = status.reblogsCount, - favouritesCount = status.favouritesCount, - reblogged = status.reblogged, - favourited = status.favourited, - bookmarked = status.bookmarked, - sensitive = status.sensitive, - spoilerText = status.spoilerText!!, - visibility = status.visibility!!, - attachments = attachments, - mentions = mentions, - application = application, - pinned = false, - poll = poll, - card = null, - pleroma = pleroma + id = id, + url = status.url, + account = account.toAccount(gson), + inReplyToId = status.inReplyToId, + inReplyToAccountId = status.inReplyToAccountId, + reblog = null, + content = status.content?.parseAsHtml()?.trimTrailingWhitespace() + ?: SpannedString(""), + createdAt = Date(status.createdAt), + emojis = emojis, + reblogsCount = status.reblogsCount, + favouritesCount = status.favouritesCount, + reblogged = status.reblogged, + favourited = status.favourited, + bookmarked = status.bookmarked, + sensitive = status.sensitive, + spoilerText = status.spoilerText!!, + visibility = status.visibility!!, + attachments = attachments, + mentions = mentions, + application = application, + pinned = false, + poll = poll, + card = null, + pleroma = pleroma ) } - val status = if (reblog != null) { + val status = if(reblog != null) { Status( - id = status.serverId, - url = null, // no url for reblogs - account = this.reblogAccount!!.toAccount(gson), - inReplyToId = null, - inReplyToAccountId = null, - reblog = reblog, - content = SpannedString(""), - createdAt = Date(status.createdAt), // lie but whatever? - emojis = listOf(), - reblogsCount = 0, - favouritesCount = 0, - reblogged = false, - favourited = false, - bookmarked = false, - sensitive = false, - spoilerText = "", - visibility = status.visibility!!, - attachments = ArrayList(), - mentions = arrayOf(), - application = null, - pinned = false, - poll = null, - card = null, - pleroma = null + id = status.serverId, + url = null, // no url for reblogs + account = this.reblogAccount!!.toAccount(gson), + inReplyToId = null, + inReplyToAccountId = null, + reblog = reblog, + content = SpannedString(""), + createdAt = Date(status.createdAt), // lie but whatever? + emojis = listOf(), + reblogsCount = 0, + favouritesCount = 0, + reblogged = false, + favourited = false, + bookmarked = false, + sensitive = false, + spoilerText = "", + visibility = status.visibility!!, + attachments = ArrayList(), + mentions = arrayOf(), + application = null, + pinned = false, + poll = null, + card = null, + pleroma = null ) } else { Status( - id = status.serverId, - url = status.url, - account = account.toAccount(gson), - inReplyToId = status.inReplyToId, - inReplyToAccountId = status.inReplyToAccountId, - reblog = null, - content = status.content?.parseAsHtml()?.trimTrailingWhitespace() ?: SpannedString(""), - createdAt = Date(status.createdAt), - emojis = emojis, - reblogsCount = status.reblogsCount, - favouritesCount = status.favouritesCount, - reblogged = status.reblogged, - favourited = status.favourited, - bookmarked = status.bookmarked, - sensitive = status.sensitive, - spoilerText = status.spoilerText!!, - visibility = status.visibility!!, - attachments = attachments, - mentions = mentions, - application = application, - pinned = false, - poll = poll, - card = null, - pleroma = pleroma + id = status.serverId, + url = status.url, + account = account.toAccount(gson), + inReplyToId = status.inReplyToId, + inReplyToAccountId = status.inReplyToAccountId, + reblog = null, + content = status.content?.parseAsHtml()?.trimTrailingWhitespace() + ?: SpannedString(""), + createdAt = Date(status.createdAt), + emojis = emojis, + reblogsCount = status.reblogsCount, + favouritesCount = status.favouritesCount, + reblogged = status.reblogged, + favourited = status.favourited, + bookmarked = status.bookmarked, + sensitive = status.sensitive, + spoilerText = status.spoilerText!!, + visibility = status.visibility!!, + attachments = attachments, + mentions = mentions, + application = application, + pinned = false, + poll = poll, + card = null, + pleroma = pleroma ) } return Either.Right(status) @@ -295,98 +313,100 @@ private val emojisListTypeToken = object : TypeToken>() {} fun Account.toEntity(accountId: Long, gson: Gson): TimelineAccountEntity { return TimelineAccountEntity( - serverId = id, - timelineUserId = accountId, - localUsername = localUsername, - username = username, - displayName = displayName.orEmpty(), - url = url, - avatar = avatar, - emojis = gson.toJson(emojis), - bot = bot + serverId = id, + timelineUserId = accountId, + localUsername = localUsername, + username = username, + displayName = displayName.orEmpty(), + url = url, + avatar = avatar, + emojis = gson.toJson(emojis), + bot = bot ) } fun TimelineAccountEntity.toAccount(gson: Gson): Account { return Account( - id = serverId, - localUsername = localUsername, - username = username, - displayName = displayName, - note = SpannedString(""), - url = url, - avatar = avatar, - header = "", - locked = false, - followingCount = 0, - followersCount = 0, - statusesCount = 0, - source = null, - bot = bot, - emojis = gson.fromJson(this.emojis, emojisListTypeToken.type), - fields = null, - moved = null + id = serverId, + localUsername = localUsername, + username = username, + displayName = displayName, + note = SpannedString(""), + url = url, + avatar = avatar, + header = "", + locked = false, + followingCount = 0, + followersCount = 0, + statusesCount = 0, + source = null, + bot = bot, + emojis = gson.fromJson(this.emojis, emojisListTypeToken.type), + fields = null, + moved = null ) } fun Placeholder.toEntity(timelineUserId: Long): TimelineStatusEntity { return TimelineStatusEntity( - serverId = this.id, - url = null, - timelineUserId = timelineUserId, - authorServerId = null, - inReplyToId = null, - inReplyToAccountId = null, - content = null, - createdAt = 0L, - emojis = null, - reblogsCount = 0, - favouritesCount = 0, - reblogged = false, - favourited = false, - bookmarked = false, - sensitive = false, - spoilerText = null, - visibility = null, - attachments = null, - mentions = null, - application = null, - reblogServerId = null, - reblogAccountId = null, - poll = null, - pleroma = null + serverId = this.id, + url = null, + timelineUserId = timelineUserId, + authorServerId = null, + inReplyToId = null, + inReplyToAccountId = null, + content = null, + createdAt = 0L, + emojis = null, + reblogsCount = 0, + favouritesCount = 0, + reblogged = false, + favourited = false, + bookmarked = false, + sensitive = false, + spoilerText = null, + visibility = null, + attachments = null, + mentions = null, + application = null, + reblogServerId = null, + reblogAccountId = null, + poll = null, + pleroma = null ) } -fun Status.toEntity(timelineUserId: Long, - gson: Gson): TimelineStatusEntity { +fun Status.toEntity( + timelineUserId: Long, + gson: Gson +): TimelineStatusEntity { val actionable = actionableStatus return TimelineStatusEntity( - serverId = this.id, - url = actionable.url!!, - timelineUserId = timelineUserId, - authorServerId = actionable.account.id, - inReplyToId = actionable.inReplyToId, - inReplyToAccountId = actionable.inReplyToAccountId, - content = actionable.content.toHtml(), - createdAt = actionable.createdAt.time, - emojis = actionable.emojis.let(gson::toJson), - reblogsCount = actionable.reblogsCount, - favouritesCount = actionable.favouritesCount, - reblogged = actionable.reblogged, - favourited = actionable.favourited, - bookmarked = actionable.bookmarked, - sensitive = actionable.sensitive, - spoilerText = actionable.spoilerText, - visibility = actionable.visibility, - attachments = actionable.attachments.let(gson::toJson), - mentions = actionable.mentions.let(gson::toJson), - application = actionable.application.let(gson::toJson), - reblogServerId = reblog?.id, - reblogAccountId = reblog?.let { this.account.id }, - poll = actionable.poll.let(gson::toJson), - pleroma = actionable.pleroma.let(gson::toJson) + serverId = this.id, + url = actionable.url!!, + timelineUserId = timelineUserId, + authorServerId = actionable.account.id, + inReplyToId = actionable.inReplyToId, + inReplyToAccountId = actionable.inReplyToAccountId, + content = actionable.content.toHtml(), + createdAt = actionable.createdAt.time, + emojis = actionable.emojis.let(gson::toJson), + reblogsCount = actionable.reblogsCount, + favouritesCount = actionable.favouritesCount, + reblogged = actionable.reblogged, + favourited = actionable.favourited, + bookmarked = actionable.bookmarked, + sensitive = actionable.sensitive, + spoilerText = actionable.spoilerText, + visibility = actionable.visibility, + attachments = actionable.attachments.let(gson::toJson), + mentions = actionable.mentions.let(gson::toJson), + application = actionable.application.let(gson::toJson), + reblogServerId = reblog?.id, + reblogAccountId = reblog?.let { this.account.id }, + poll = actionable.poll.let(gson::toJson), + pleroma = actionable.pleroma.let(gson::toJson) ) }