Formatting, license header
This commit is contained in:
parent
237241baa1
commit
6d8aa8ff47
2 changed files with 429 additions and 319 deletions
|
@ -1,21 +1,53 @@
|
|||
/* Copyright 2017 Andrew Dawson
|
||||
/*
|
||||
* Husky -- A Pleroma client for Android
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
* Copyright (C) 2021 The Husky Developers
|
||||
* Copyright (C) 2017 Alibek "a1batross" Omarov
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.keylesspalace.tusky.network
|
||||
|
||||
import com.keylesspalace.tusky.entity.*
|
||||
import com.keylesspalace.tusky.entity.AccessToken
|
||||
import com.keylesspalace.tusky.entity.Account
|
||||
import com.keylesspalace.tusky.entity.Announcement
|
||||
import com.keylesspalace.tusky.entity.AppCredentials
|
||||
import com.keylesspalace.tusky.entity.Attachment
|
||||
import com.keylesspalace.tusky.entity.Chat
|
||||
import com.keylesspalace.tusky.entity.ChatMessage
|
||||
import com.keylesspalace.tusky.entity.Conversation
|
||||
import com.keylesspalace.tusky.entity.DeletedStatus
|
||||
import com.keylesspalace.tusky.entity.Emoji
|
||||
import com.keylesspalace.tusky.entity.EmojiReaction
|
||||
import com.keylesspalace.tusky.entity.Filter
|
||||
import com.keylesspalace.tusky.entity.IdentityProof
|
||||
import com.keylesspalace.tusky.entity.Instance
|
||||
import com.keylesspalace.tusky.entity.Marker
|
||||
import com.keylesspalace.tusky.entity.MastoList
|
||||
import com.keylesspalace.tusky.entity.NewChatMessage
|
||||
import com.keylesspalace.tusky.entity.NewStatus
|
||||
import com.keylesspalace.tusky.entity.NodeInfo
|
||||
import com.keylesspalace.tusky.entity.NodeInfoLinks
|
||||
import com.keylesspalace.tusky.entity.Notification
|
||||
import com.keylesspalace.tusky.entity.Poll
|
||||
import com.keylesspalace.tusky.entity.Relationship
|
||||
import com.keylesspalace.tusky.entity.ScheduledStatus
|
||||
import com.keylesspalace.tusky.entity.SearchResult
|
||||
import com.keylesspalace.tusky.entity.Status
|
||||
import com.keylesspalace.tusky.entity.StatusContext
|
||||
import com.keylesspalace.tusky.entity.StickerPack
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.Single
|
||||
import okhttp3.MultipartBody
|
||||
|
@ -23,8 +55,21 @@ import okhttp3.RequestBody
|
|||
import okhttp3.ResponseBody
|
||||
import retrofit2.Call
|
||||
import retrofit2.Response
|
||||
import retrofit2.http.*
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.DELETE
|
||||
import retrofit2.http.Field
|
||||
import retrofit2.http.FormUrlEncoded
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.HTTP
|
||||
import retrofit2.http.Header
|
||||
import retrofit2.http.Multipart
|
||||
import retrofit2.http.PATCH
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.PUT
|
||||
import retrofit2.http.Part
|
||||
import retrofit2.http.Path
|
||||
import retrofit2.http.Query
|
||||
import retrofit2.http.Url
|
||||
|
||||
/**
|
||||
* for documentation of the Mastodon REST API see https://docs.joinmastodon.org/api/
|
||||
|
@ -53,66 +98,66 @@ interface MastodonApi {
|
|||
|
||||
@GET("api/v1/timelines/home?with_muted=true")
|
||||
fun homeTimeline(
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?
|
||||
): Call<List<Status>>
|
||||
|
||||
@GET("api/v1/timelines/home?with_muted=true")
|
||||
fun homeTimelineSingle(
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?
|
||||
): Single<List<Status>>
|
||||
|
||||
@GET("api/v1/timelines/public?with_muted=true")
|
||||
fun publicTimeline(
|
||||
@Query("local") local: Boolean?,
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?
|
||||
@Query("local") local: Boolean?,
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?
|
||||
): Call<List<Status>>
|
||||
|
||||
@GET("api/v1/timelines/tag/{hashtag}?with_muted=true")
|
||||
fun hashtagTimeline(
|
||||
@Path("hashtag") hashtag: String,
|
||||
@Query("any[]") any: List<String>?,
|
||||
@Query("local") local: Boolean?,
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?
|
||||
@Path("hashtag") hashtag: String,
|
||||
@Query("any[]") any: List<String>?,
|
||||
@Query("local") local: Boolean?,
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?
|
||||
): Call<List<Status>>
|
||||
|
||||
@GET("api/v1/timelines/list/{listId}?with_muted=true")
|
||||
fun listTimeline(
|
||||
@Path("listId") listId: String,
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?
|
||||
@Path("listId") listId: String,
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?
|
||||
): Call<List<Status>>
|
||||
|
||||
@GET("api/v1/notifications")
|
||||
fun notifications(
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?,
|
||||
@Query("exclude_types[]") excludes: Set<Notification.Type>?,
|
||||
@Query("with_muted") withMuted: Boolean?
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?,
|
||||
@Query("exclude_types[]") excludes: Set<Notification.Type>?,
|
||||
@Query("with_muted") withMuted: Boolean?
|
||||
): Call<List<Notification>>
|
||||
|
||||
@GET("api/v1/markers")
|
||||
fun markersWithAuth(
|
||||
@Header("Authorization") auth: String,
|
||||
@Header(DOMAIN_HEADER) domain: String,
|
||||
@Query("timeline[]") timelines: List<String>
|
||||
@Header("Authorization") auth: String,
|
||||
@Header(DOMAIN_HEADER) domain: String,
|
||||
@Query("timeline[]") timelines: List<String>
|
||||
): Single<Map<String, Marker>>
|
||||
|
||||
@GET("api/v1/notifications?with_muted=true")
|
||||
fun notificationsWithAuth(
|
||||
@Header("Authorization") auth: String,
|
||||
@Header(DOMAIN_HEADER) domain: String,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("include_types[]") includeTypes: List<String>?
|
||||
@Header("Authorization") auth: String,
|
||||
@Header(DOMAIN_HEADER) domain: String,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("include_types[]") includeTypes: List<String>?
|
||||
): Single<List<Notification>>
|
||||
|
||||
@POST("api/v1/notifications/clear")
|
||||
|
@ -120,122 +165,122 @@ interface MastodonApi {
|
|||
|
||||
@GET("api/v1/notifications/{id}")
|
||||
fun notification(
|
||||
@Path("id") notificationId: String
|
||||
@Path("id") notificationId: String
|
||||
): Call<Notification>
|
||||
|
||||
@Multipart
|
||||
@POST("api/v1/media")
|
||||
fun uploadMedia(
|
||||
@Part file: MultipartBody.Part,
|
||||
@Part description: MultipartBody.Part? = null
|
||||
@Part file: MultipartBody.Part,
|
||||
@Part description: MultipartBody.Part? = null
|
||||
): Single<Attachment>
|
||||
|
||||
@FormUrlEncoded
|
||||
@PUT("api/v1/media/{mediaId}")
|
||||
fun updateMedia(
|
||||
@Path("mediaId") mediaId: String,
|
||||
@Field("description") description: String
|
||||
@Path("mediaId") mediaId: String,
|
||||
@Field("description") description: String
|
||||
): Single<Attachment>
|
||||
|
||||
@POST("api/v1/statuses")
|
||||
fun createStatus(
|
||||
@Header("Authorization") auth: String,
|
||||
@Header(DOMAIN_HEADER) domain: String,
|
||||
@Header("Idempotency-Key") idempotencyKey: String,
|
||||
@Body status: NewStatus
|
||||
@Header("Authorization") auth: String,
|
||||
@Header(DOMAIN_HEADER) domain: String,
|
||||
@Header("Idempotency-Key") idempotencyKey: String,
|
||||
@Body status: NewStatus
|
||||
): Call<Status>
|
||||
|
||||
@GET("api/v1/statuses/{id}")
|
||||
fun status(
|
||||
@Path("id") statusId: String
|
||||
@Path("id") statusId: String
|
||||
): Call<Status>
|
||||
|
||||
@GET("api/v1/statuses/{id}")
|
||||
fun statusSingle(
|
||||
@Path("id") statusId: String
|
||||
@Path("id") statusId: String
|
||||
): Single<Status>
|
||||
|
||||
@GET("api/v1/statuses/{id}/context")
|
||||
fun statusContext(
|
||||
@Path("id") statusId: String
|
||||
@Path("id") statusId: String
|
||||
): Call<StatusContext>
|
||||
|
||||
@GET("api/v1/statuses/{id}/reblogged_by")
|
||||
fun statusRebloggedBy(
|
||||
@Path("id") statusId: String,
|
||||
@Query("max_id") maxId: String?
|
||||
@Path("id") statusId: String,
|
||||
@Query("max_id") maxId: String?
|
||||
): Single<Response<List<Account>>>
|
||||
|
||||
@GET("api/v1/statuses/{id}/favourited_by")
|
||||
fun statusFavouritedBy(
|
||||
@Path("id") statusId: String,
|
||||
@Query("max_id") maxId: String?
|
||||
@Path("id") statusId: String,
|
||||
@Query("max_id") maxId: String?
|
||||
): Single<Response<List<Account>>>
|
||||
|
||||
@DELETE("api/v1/statuses/{id}")
|
||||
fun deleteStatus(
|
||||
@Path("id") statusId: String
|
||||
@Path("id") statusId: String
|
||||
): Single<DeletedStatus>
|
||||
|
||||
@POST("api/v1/statuses/{id}/reblog")
|
||||
fun reblogStatus(
|
||||
@Path("id") statusId: String
|
||||
@Path("id") statusId: String
|
||||
): Single<Status>
|
||||
|
||||
@POST("api/v1/statuses/{id}/unreblog")
|
||||
fun unreblogStatus(
|
||||
@Path("id") statusId: String
|
||||
@Path("id") statusId: String
|
||||
): Single<Status>
|
||||
|
||||
@POST("api/v1/statuses/{id}/favourite")
|
||||
fun favouriteStatus(
|
||||
@Path("id") statusId: String
|
||||
@Path("id") statusId: String
|
||||
): Single<Status>
|
||||
|
||||
@POST("api/v1/statuses/{id}/unfavourite")
|
||||
fun unfavouriteStatus(
|
||||
@Path("id") statusId: String
|
||||
@Path("id") statusId: String
|
||||
): Single<Status>
|
||||
|
||||
@POST("api/v1/statuses/{id}/bookmark")
|
||||
fun bookmarkStatus(
|
||||
@Path("id") statusId: String
|
||||
@Path("id") statusId: String
|
||||
): Single<Status>
|
||||
|
||||
@POST("api/v1/statuses/{id}/unbookmark")
|
||||
fun unbookmarkStatus(
|
||||
@Path("id") statusId: String
|
||||
@Path("id") statusId: String
|
||||
): Single<Status>
|
||||
|
||||
@POST("api/v1/statuses/{id}/pin")
|
||||
fun pinStatus(
|
||||
@Path("id") statusId: String
|
||||
@Path("id") statusId: String
|
||||
): Single<Status>
|
||||
|
||||
@POST("api/v1/statuses/{id}/unpin")
|
||||
fun unpinStatus(
|
||||
@Path("id") statusId: String
|
||||
@Path("id") statusId: String
|
||||
): Single<Status>
|
||||
|
||||
|
||||
@POST("api/v1/statuses/{id}/mute")
|
||||
fun muteConversation(
|
||||
@Path("id") statusId: String
|
||||
@Path("id") statusId: String
|
||||
): Single<Status>
|
||||
|
||||
|
||||
@POST("api/v1/statuses/{id}/unmute")
|
||||
fun unmuteConversation(
|
||||
@Path("id") statusId: String
|
||||
@Path("id") statusId: String
|
||||
): Single<Status>
|
||||
|
||||
|
||||
@GET("api/v1/scheduled_statuses")
|
||||
fun scheduledStatuses(
|
||||
@Query("limit") limit: Int? = null,
|
||||
@Query("max_id") maxId: String? = null
|
||||
@Query("limit") limit: Int? = null,
|
||||
@Query("max_id") maxId: String? = null
|
||||
): Single<List<ScheduledStatus>>
|
||||
|
||||
@DELETE("api/v1/scheduled_statuses/{id}")
|
||||
fun deleteScheduledStatus(
|
||||
@Path("id") scheduledStatusId: String
|
||||
@Path("id") scheduledStatusId: String
|
||||
): Single<ResponseBody>
|
||||
|
||||
@GET("api/v1/accounts/verify_credentials")
|
||||
|
@ -244,39 +289,39 @@ interface MastodonApi {
|
|||
@FormUrlEncoded
|
||||
@PATCH("api/v1/accounts/update_credentials")
|
||||
fun accountUpdateSource(
|
||||
@Field("source[privacy]") privacy: String?,
|
||||
@Field("source[sensitive]") sensitive: Boolean?
|
||||
@Field("source[privacy]") privacy: String?,
|
||||
@Field("source[sensitive]") sensitive: Boolean?
|
||||
): Call<Account>
|
||||
|
||||
@Multipart
|
||||
@PATCH("api/v1/accounts/update_credentials")
|
||||
fun accountUpdateCredentials(
|
||||
@Part(value = "display_name") displayName: RequestBody?,
|
||||
@Part(value = "note") note: RequestBody?,
|
||||
@Part(value = "locked") locked: RequestBody?,
|
||||
@Part avatar: MultipartBody.Part?,
|
||||
@Part header: MultipartBody.Part?,
|
||||
@Part(value = "fields_attributes[0][name]") fieldName0: RequestBody?,
|
||||
@Part(value = "fields_attributes[0][value]") fieldValue0: RequestBody?,
|
||||
@Part(value = "fields_attributes[1][name]") fieldName1: RequestBody?,
|
||||
@Part(value = "fields_attributes[1][value]") fieldValue1: RequestBody?,
|
||||
@Part(value = "fields_attributes[2][name]") fieldName2: RequestBody?,
|
||||
@Part(value = "fields_attributes[2][value]") fieldValue2: RequestBody?,
|
||||
@Part(value = "fields_attributes[3][name]") fieldName3: RequestBody?,
|
||||
@Part(value = "fields_attributes[3][value]") fieldValue3: RequestBody?
|
||||
@Part(value = "display_name") displayName: RequestBody?,
|
||||
@Part(value = "note") note: RequestBody?,
|
||||
@Part(value = "locked") locked: RequestBody?,
|
||||
@Part avatar: MultipartBody.Part?,
|
||||
@Part header: MultipartBody.Part?,
|
||||
@Part(value = "fields_attributes[0][name]") fieldName0: RequestBody?,
|
||||
@Part(value = "fields_attributes[0][value]") fieldValue0: RequestBody?,
|
||||
@Part(value = "fields_attributes[1][name]") fieldName1: RequestBody?,
|
||||
@Part(value = "fields_attributes[1][value]") fieldValue1: RequestBody?,
|
||||
@Part(value = "fields_attributes[2][name]") fieldName2: RequestBody?,
|
||||
@Part(value = "fields_attributes[2][value]") fieldValue2: RequestBody?,
|
||||
@Part(value = "fields_attributes[3][name]") fieldName3: RequestBody?,
|
||||
@Part(value = "fields_attributes[3][value]") fieldValue3: RequestBody?
|
||||
): Call<Account>
|
||||
|
||||
@GET("api/v1/accounts/search")
|
||||
fun searchAccounts(
|
||||
@Query("q") query: String,
|
||||
@Query("resolve") resolve: Boolean? = null,
|
||||
@Query("limit") limit: Int? = null,
|
||||
@Query("following") following: Boolean? = null
|
||||
@Query("q") query: String,
|
||||
@Query("resolve") resolve: Boolean? = null,
|
||||
@Query("limit") limit: Int? = null,
|
||||
@Query("following") following: Boolean? = null
|
||||
): Single<List<Account>>
|
||||
|
||||
@GET("api/v1/accounts/{id}")
|
||||
fun account(
|
||||
@Path("id") accountId: String
|
||||
@Path("id") accountId: String
|
||||
): Single<Account>
|
||||
|
||||
/**
|
||||
|
@ -290,78 +335,78 @@ interface MastodonApi {
|
|||
*/
|
||||
@GET("api/v1/accounts/{id}/statuses?with_muted=true")
|
||||
fun accountStatuses(
|
||||
@Path("id") accountId: String,
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?,
|
||||
@Query("exclude_replies") excludeReplies: Boolean?,
|
||||
@Query("only_media") onlyMedia: Boolean?,
|
||||
@Query("pinned") pinned: Boolean?
|
||||
@Path("id") accountId: String,
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?,
|
||||
@Query("exclude_replies") excludeReplies: Boolean?,
|
||||
@Query("only_media") onlyMedia: Boolean?,
|
||||
@Query("pinned") pinned: Boolean?
|
||||
): Call<List<Status>>
|
||||
|
||||
@GET("api/v1/accounts/{id}/followers")
|
||||
fun accountFollowers(
|
||||
@Path("id") accountId: String,
|
||||
@Query("max_id") maxId: String?
|
||||
@Path("id") accountId: String,
|
||||
@Query("max_id") maxId: String?
|
||||
): Single<Response<List<Account>>>
|
||||
|
||||
@GET("api/v1/accounts/{id}/following")
|
||||
fun accountFollowing(
|
||||
@Path("id") accountId: String,
|
||||
@Query("max_id") maxId: String?
|
||||
@Path("id") accountId: String,
|
||||
@Query("max_id") maxId: String?
|
||||
): Single<Response<List<Account>>>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("api/v1/accounts/{id}/follow")
|
||||
fun followAccount(
|
||||
@Path("id") accountId: String,
|
||||
@Field("reblogs") showReblogs: Boolean? = null,
|
||||
@Field("notify") notify: Boolean? = null
|
||||
@Path("id") accountId: String,
|
||||
@Field("reblogs") showReblogs: Boolean? = null,
|
||||
@Field("notify") notify: Boolean? = null
|
||||
): Single<Relationship>
|
||||
|
||||
@POST("api/v1/accounts/{id}/unfollow")
|
||||
fun unfollowAccount(
|
||||
@Path("id") accountId: String
|
||||
@Path("id") accountId: String
|
||||
): Single<Relationship>
|
||||
|
||||
@POST("api/v1/accounts/{id}/block")
|
||||
fun blockAccount(
|
||||
@Path("id") accountId: String
|
||||
@Path("id") accountId: String
|
||||
): Single<Relationship>
|
||||
|
||||
@POST("api/v1/accounts/{id}/unblock")
|
||||
fun unblockAccount(
|
||||
@Path("id") accountId: String
|
||||
@Path("id") accountId: String
|
||||
): Single<Relationship>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("api/v1/accounts/{id}/mute")
|
||||
fun muteAccount(
|
||||
@Path("id") accountId: String,
|
||||
@Field("notifications") notifications: Boolean? = null,
|
||||
@Field("duration") duration: Int? = null
|
||||
@Path("id") accountId: String,
|
||||
@Field("notifications") notifications: Boolean? = null,
|
||||
@Field("duration") duration: Int? = null
|
||||
): Single<Relationship>
|
||||
|
||||
@POST("api/v1/accounts/{id}/unmute")
|
||||
fun unmuteAccount(
|
||||
@Path("id") accountId: String
|
||||
@Path("id") accountId: String
|
||||
): Single<Relationship>
|
||||
|
||||
@GET("api/v1/accounts/relationships")
|
||||
fun relationships(
|
||||
@Query("id[]") accountIds: List<String>
|
||||
@Query("id[]") accountIds: List<String>
|
||||
): Single<List<Relationship>>
|
||||
|
||||
@GET("api/v1/accounts/{id}/identity_proofs")
|
||||
fun identityProofs(
|
||||
@Path("id") accountId: String
|
||||
@Path("id") accountId: String
|
||||
): Single<List<IdentityProof>>
|
||||
|
||||
|
||||
@POST("api/v1/pleroma/accounts/{id}/subscribe")
|
||||
fun subscribeAccount(
|
||||
@Path("id") accountId: String
|
||||
): Single<Relationship>
|
||||
|
||||
|
||||
@POST("api/v1/pleroma/accounts/{id}/unsubscribe")
|
||||
fun unsubscribeAccount(
|
||||
@Path("id") accountId: String
|
||||
|
@ -369,25 +414,25 @@ interface MastodonApi {
|
|||
|
||||
@GET("api/v1/blocks")
|
||||
fun blocks(
|
||||
@Query("max_id") maxId: String?
|
||||
@Query("max_id") maxId: String?
|
||||
): Single<Response<List<Account>>>
|
||||
|
||||
@GET("api/v1/mutes")
|
||||
fun mutes(
|
||||
@Query("max_id") maxId: String?
|
||||
@Query("max_id") maxId: String?
|
||||
): Single<Response<List<Account>>>
|
||||
|
||||
@GET("api/v1/domain_blocks")
|
||||
fun domainBlocks(
|
||||
@Query("max_id") maxId: String? = null,
|
||||
@Query("since_id") sinceId: String? = null,
|
||||
@Query("limit") limit: Int? = null
|
||||
@Query("max_id") maxId: String? = null,
|
||||
@Query("since_id") sinceId: String? = null,
|
||||
@Query("limit") limit: Int? = null
|
||||
): Single<Response<List<String>>>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("api/v1/domain_blocks")
|
||||
fun blockDomain(
|
||||
@Field("domain") domain: String
|
||||
@Field("domain") domain: String
|
||||
): Call<Any>
|
||||
|
||||
@FormUrlEncoded
|
||||
|
@ -397,107 +442,107 @@ interface MastodonApi {
|
|||
|
||||
@GET("api/v1/favourites?with_muted=true")
|
||||
fun favourites(
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?
|
||||
): Call<List<Status>>
|
||||
|
||||
@GET("api/v1/bookmarks?with_muted=true")
|
||||
fun bookmarks(
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?
|
||||
): Call<List<Status>>
|
||||
|
||||
@GET("api/v1/follow_requests")
|
||||
fun followRequests(
|
||||
@Query("max_id") maxId: String?
|
||||
@Query("max_id") maxId: String?
|
||||
): Single<Response<List<Account>>>
|
||||
|
||||
@POST("api/v1/follow_requests/{id}/authorize")
|
||||
fun authorizeFollowRequest(
|
||||
@Path("id") accountId: String
|
||||
@Path("id") accountId: String
|
||||
): Call<Relationship>
|
||||
|
||||
@POST("api/v1/follow_requests/{id}/reject")
|
||||
fun rejectFollowRequest(
|
||||
@Path("id") accountId: String
|
||||
@Path("id") accountId: String
|
||||
): Call<Relationship>
|
||||
|
||||
@POST("api/v1/follow_requests/{id}/authorize")
|
||||
fun authorizeFollowRequestObservable(
|
||||
@Path("id") accountId: String
|
||||
@Path("id") accountId: String
|
||||
): Single<Relationship>
|
||||
|
||||
@POST("api/v1/follow_requests/{id}/reject")
|
||||
fun rejectFollowRequestObservable(
|
||||
@Path("id") accountId: String
|
||||
@Path("id") accountId: String
|
||||
): Single<Relationship>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("api/v1/apps")
|
||||
fun authenticateApp(
|
||||
@Header(DOMAIN_HEADER) domain: String,
|
||||
@Field("client_name") clientName: String,
|
||||
@Field("redirect_uris") redirectUris: String,
|
||||
@Field("scopes") scopes: String,
|
||||
@Field("website") website: String
|
||||
@Header(DOMAIN_HEADER) domain: String,
|
||||
@Field("client_name") clientName: String,
|
||||
@Field("redirect_uris") redirectUris: String,
|
||||
@Field("scopes") scopes: String,
|
||||
@Field("website") website: String
|
||||
): Call<AppCredentials>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("oauth/token")
|
||||
fun fetchOAuthToken(
|
||||
@Header(DOMAIN_HEADER) domain: String,
|
||||
@Field("client_id") clientId: String,
|
||||
@Field("client_secret") clientSecret: String,
|
||||
@Field("redirect_uri") redirectUri: String,
|
||||
@Field("code") code: String,
|
||||
@Field("grant_type") grantType: String
|
||||
@Header(DOMAIN_HEADER) domain: String,
|
||||
@Field("client_id") clientId: String,
|
||||
@Field("client_secret") clientSecret: String,
|
||||
@Field("redirect_uri") redirectUri: String,
|
||||
@Field("code") code: String,
|
||||
@Field("grant_type") grantType: String
|
||||
): Call<AccessToken>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("api/v1/lists")
|
||||
fun createList(
|
||||
@Field("title") title: String
|
||||
@Field("title") title: String
|
||||
): Single<MastoList>
|
||||
|
||||
@FormUrlEncoded
|
||||
@PUT("api/v1/lists/{listId}")
|
||||
fun updateList(
|
||||
@Path("listId") listId: String,
|
||||
@Field("title") title: String
|
||||
@Path("listId") listId: String,
|
||||
@Field("title") title: String
|
||||
): Single<MastoList>
|
||||
|
||||
@DELETE("api/v1/lists/{listId}")
|
||||
fun deleteList(
|
||||
@Path("listId") listId: String
|
||||
@Path("listId") listId: String
|
||||
): Completable
|
||||
|
||||
@GET("api/v1/lists/{listId}/accounts")
|
||||
fun getAccountsInList(
|
||||
@Path("listId") listId: String,
|
||||
@Query("limit") limit: Int
|
||||
@Path("listId") listId: String,
|
||||
@Query("limit") limit: Int
|
||||
): Single<List<Account>>
|
||||
|
||||
@FormUrlEncoded
|
||||
// @DELETE doesn't support fields
|
||||
@HTTP(method = "DELETE", path = "api/v1/lists/{listId}/accounts", hasBody = true)
|
||||
fun deleteAccountFromList(
|
||||
@Path("listId") listId: String,
|
||||
@Field("account_ids[]") accountIds: List<String>
|
||||
@Path("listId") listId: String,
|
||||
@Field("account_ids[]") accountIds: List<String>
|
||||
): Completable
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("api/v1/lists/{listId}/accounts")
|
||||
fun addCountToList(
|
||||
@Path("listId") listId: String,
|
||||
@Field("account_ids[]") accountIds: List<String>
|
||||
@Path("listId") listId: String,
|
||||
@Field("account_ids[]") accountIds: List<String>
|
||||
): Completable
|
||||
|
||||
@GET("/api/v1/conversations")
|
||||
fun getConversations(
|
||||
@Query("max_id") maxId: String? = null,
|
||||
@Query("limit") limit: Int
|
||||
@Query("max_id") maxId: String? = null,
|
||||
@Query("limit") limit: Int
|
||||
): Call<List<Conversation>>
|
||||
|
||||
data class PostFilter(
|
||||
|
@ -513,83 +558,83 @@ interface MastodonApi {
|
|||
|
||||
@PUT("api/v1/filters/{id}")
|
||||
fun updateFilter(
|
||||
@Path("id") id: String,
|
||||
@Body body: PostFilter
|
||||
@Path("id") id: String,
|
||||
@Body body: PostFilter
|
||||
): Call<Filter>
|
||||
|
||||
@DELETE("api/v1/filters/{id}")
|
||||
fun deleteFilter(
|
||||
@Path("id") id: String
|
||||
@Path("id") id: String
|
||||
): Call<ResponseBody>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("api/v1/polls/{id}/votes")
|
||||
fun voteInPoll(
|
||||
@Path("id") id: String,
|
||||
@Field("choices[]") choices: List<Int>
|
||||
@Path("id") id: String,
|
||||
@Field("choices[]") choices: List<Int>
|
||||
): Single<Poll>
|
||||
|
||||
@GET("api/v1/announcements")
|
||||
fun listAnnouncements(
|
||||
@Query("with_dismissed") withDismissed: Boolean = true
|
||||
@Query("with_dismissed") withDismissed: Boolean = true
|
||||
): Single<List<Announcement>>
|
||||
|
||||
@POST("api/v1/announcements/{id}/dismiss")
|
||||
fun dismissAnnouncement(
|
||||
@Path("id") announcementId: String
|
||||
@Path("id") announcementId: String
|
||||
): Single<ResponseBody>
|
||||
|
||||
@PUT("api/v1/announcements/{id}/reactions/{name}")
|
||||
fun addAnnouncementReaction(
|
||||
@Path("id") announcementId: String,
|
||||
@Path("name") name: String
|
||||
@Path("id") announcementId: String,
|
||||
@Path("name") name: String
|
||||
): Single<ResponseBody>
|
||||
|
||||
@DELETE("api/v1/announcements/{id}/reactions/{name}")
|
||||
fun removeAnnouncementReaction(
|
||||
@Path("id") announcementId: String,
|
||||
@Path("name") name: String
|
||||
@Path("id") announcementId: String,
|
||||
@Path("name") name: String
|
||||
): Single<ResponseBody>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("api/v1/reports")
|
||||
fun reportObservable(
|
||||
@Field("account_id") accountId: String,
|
||||
@Field("status_ids[]") statusIds: List<String>,
|
||||
@Field("comment") comment: String,
|
||||
@Field("forward") isNotifyRemote: Boolean?
|
||||
@Field("account_id") accountId: String,
|
||||
@Field("status_ids[]") statusIds: List<String>,
|
||||
@Field("comment") comment: String,
|
||||
@Field("forward") isNotifyRemote: Boolean?
|
||||
): Single<ResponseBody>
|
||||
|
||||
@GET("api/v1/accounts/{id}/statuses?with_muted=true")
|
||||
fun accountStatusesObservable(
|
||||
@Path("id") accountId: String,
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?,
|
||||
@Query("exclude_reblogs") excludeReblogs: Boolean?
|
||||
@Path("id") accountId: String,
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?,
|
||||
@Query("exclude_reblogs") excludeReblogs: Boolean?
|
||||
): Single<List<Status>>
|
||||
|
||||
@GET("api/v1/statuses/{id}")
|
||||
fun statusObservable(
|
||||
@Path("id") statusId: String
|
||||
@Path("id") statusId: String
|
||||
): Single<Status>
|
||||
|
||||
@GET("api/v2/search")
|
||||
fun searchObservable(
|
||||
@Query("q") query: String?,
|
||||
@Query("type") type: String? = null,
|
||||
@Query("resolve") resolve: Boolean? = null,
|
||||
@Query("limit") limit: Int? = null,
|
||||
@Query("offset") offset: Int? = null,
|
||||
@Query("following") following: Boolean? = null
|
||||
@Query("q") query: String?,
|
||||
@Query("type") type: String? = null,
|
||||
@Query("resolve") resolve: Boolean? = null,
|
||||
@Query("limit") limit: Int? = null,
|
||||
@Query("offset") offset: Int? = null,
|
||||
@Query("following") following: Boolean? = null
|
||||
): Single<SearchResult>
|
||||
|
||||
|
||||
@GET(".well-known/nodeinfo")
|
||||
fun getNodeinfoLinks() : Single<NodeInfoLinks>
|
||||
|
||||
fun getNodeinfoLinks(): Single<NodeInfoLinks>
|
||||
|
||||
@GET
|
||||
fun getNodeinfo(@Url url: String) : Single<NodeInfo>
|
||||
|
||||
fun getNodeinfo(@Url url: String): Single<NodeInfo>
|
||||
|
||||
@PUT("api/v1/pleroma/statuses/{id}/reactions/{emoji}")
|
||||
fun reactWithEmoji(
|
||||
@Path("id") statusId: String,
|
||||
|
@ -611,7 +656,7 @@ interface MastodonApi {
|
|||
// NOT AN API CALLS NOT AN API CALLS NOT AN API CALLS NOT AN API CALLS
|
||||
// just for testing and because puniko asked me
|
||||
@GET("static/stickers.json")
|
||||
fun getStickers() : Single<Map<String, String>>
|
||||
fun getStickers(): Single<Map<String, String>>
|
||||
|
||||
@GET
|
||||
fun getStickerPack(
|
||||
|
@ -621,64 +666,64 @@ interface MastodonApi {
|
|||
|
||||
@POST("api/v1/pleroma/chats/{id}/messages/{message_id}/read")
|
||||
fun markChatMessageAsRead(
|
||||
@Path("id") chatId: String,
|
||||
@Path("message_id") messageId: String
|
||||
@Path("id") chatId: String,
|
||||
@Path("message_id") messageId: String
|
||||
): Single<ChatMessage>
|
||||
|
||||
@DELETE("api/v1/pleroma/chats/{id}/messages/{message_id}")
|
||||
fun deleteChatMessage(
|
||||
@Path("id") chatId: String,
|
||||
@Path("message_id") messageId: String
|
||||
@Path("id") chatId: String,
|
||||
@Path("message_id") messageId: String
|
||||
): Single<ChatMessage>
|
||||
|
||||
@GET("api/v2/pleroma/chats")
|
||||
fun getChats(
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("min_id") minId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("offset") offset: Int?,
|
||||
@Query("limit") limit: Int?
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("min_id") minId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("offset") offset: Int?,
|
||||
@Query("limit") limit: Int?
|
||||
): Single<List<Chat>>
|
||||
|
||||
@GET("api/v1/pleroma/chats/{id}/messages")
|
||||
fun getChatMessages(
|
||||
@Path("id") chatId: String,
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("min_id") minId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("offset") offset: Int?,
|
||||
@Query("limit") limit: Int?
|
||||
@Path("id") chatId: String,
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("min_id") minId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("offset") offset: Int?,
|
||||
@Query("limit") limit: Int?
|
||||
): Single<List<ChatMessage>>
|
||||
|
||||
@POST("api/v1/pleroma/chats/{id}/messages")
|
||||
fun createChatMessage(
|
||||
@Header("Authorization") auth: String,
|
||||
@Header(DOMAIN_HEADER) domain: String,
|
||||
@Path("id") chatId: String,
|
||||
@Body chatMessage: NewChatMessage
|
||||
@Header("Authorization") auth: String,
|
||||
@Header(DOMAIN_HEADER) domain: String,
|
||||
@Path("id") chatId: String,
|
||||
@Body chatMessage: NewChatMessage
|
||||
): Call<ChatMessage>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("api/v1/pleroma/chats/{id}/read")
|
||||
fun markChatAsRead(
|
||||
@Path("id") chatId: String,
|
||||
@Field("last_read_id") lastReadId: String? = null
|
||||
@Path("id") chatId: String,
|
||||
@Field("last_read_id") lastReadId: String? = null
|
||||
): Single<Chat>
|
||||
|
||||
@POST("api/v1/pleroma/chats/by-account-id/{id}")
|
||||
fun createChat(
|
||||
@Path("id") accountId: String
|
||||
@Path("id") accountId: String
|
||||
): Single<Chat>
|
||||
|
||||
@GET("api/v1/pleroma/chats/{id}")
|
||||
fun getChat(
|
||||
@Path("id") chatId: String
|
||||
@Path("id") chatId: String
|
||||
): Single<Chat>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("api/v1/accounts/{id}/note")
|
||||
fun updateAccountNote(
|
||||
@Path("id") accountId: String,
|
||||
@Field("comment") note: String
|
||||
@Path("id") accountId: String,
|
||||
@Field("comment") note: String
|
||||
): Single<Relationship>
|
||||
}
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
/*
|
||||
* Husky -- A Pleroma client for Android
|
||||
*
|
||||
* Copyright (C) 2021 The Husky Developers
|
||||
* Copyright (C) 2021 Andrew Dawson
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.keylesspalace.tusky.repository
|
||||
|
||||
import android.text.SpannedString
|
||||
|
@ -5,8 +25,16 @@ import androidx.core.text.parseAsHtml
|
|||
import androidx.core.text.toHtml
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.keylesspalace.tusky.db.*
|
||||
import com.keylesspalace.tusky.entity.*
|
||||
import com.keylesspalace.tusky.db.AccountManager
|
||||
import com.keylesspalace.tusky.db.ChatEntity
|
||||
import com.keylesspalace.tusky.db.ChatEntityWithAccount
|
||||
import com.keylesspalace.tusky.db.ChatMessageEntity
|
||||
import com.keylesspalace.tusky.db.ChatsDao
|
||||
import com.keylesspalace.tusky.entity.Account
|
||||
import com.keylesspalace.tusky.entity.Attachment
|
||||
import com.keylesspalace.tusky.entity.Chat
|
||||
import com.keylesspalace.tusky.entity.ChatMessage
|
||||
import com.keylesspalace.tusky.entity.Emoji
|
||||
import com.keylesspalace.tusky.network.MastodonApi
|
||||
import com.keylesspalace.tusky.repository.TimelineRequestMode.DISK
|
||||
import com.keylesspalace.tusky.repository.TimelineRequestMode.NETWORK
|
||||
|
@ -17,39 +45,56 @@ import com.keylesspalace.tusky.util.trimTrailingWhitespace
|
|||
import io.reactivex.Single
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
import java.util.Date
|
||||
|
||||
typealias ChatStatus = Either<Placeholder, Chat>
|
||||
typealias ChatMesssageOrPlaceholder = Either<Placeholder, ChatMessage>
|
||||
|
||||
interface ChatRepository {
|
||||
fun getChats(maxId: String?, sinceId: String?, sincedIdMinusOne: String?, limit: Int,
|
||||
requestMode: TimelineRequestMode): Single<out List<ChatStatus>>
|
||||
fun getChats(
|
||||
maxId: String?, sinceId: String?, sincedIdMinusOne: String?, limit: Int,
|
||||
requestMode: TimelineRequestMode
|
||||
): Single<out List<ChatStatus>>
|
||||
|
||||
fun getChatMessages(chatId: String, maxId: String?, sinceId: String?, sincedIdMinusOne: String?, limit: Int, requestMode: TimelineRequestMode) : Single<out List<ChatMesssageOrPlaceholder>>
|
||||
fun getChatMessages(
|
||||
chatId: String,
|
||||
maxId: String?,
|
||||
sinceId: String?,
|
||||
sincedIdMinusOne: String?,
|
||||
limit: Int,
|
||||
requestMode: TimelineRequestMode
|
||||
): Single<out List<ChatMesssageOrPlaceholder>>
|
||||
}
|
||||
|
||||
class ChatRepositoryImpl(
|
||||
private val chatsDao: ChatsDao,
|
||||
private val mastodonApi: MastodonApi,
|
||||
private val accountManager: AccountManager,
|
||||
private val gson: Gson
|
||||
private val chatsDao: ChatsDao,
|
||||
private val mastodonApi: MastodonApi,
|
||||
private val accountManager: AccountManager,
|
||||
private val gson: Gson
|
||||
) : ChatRepository {
|
||||
|
||||
override fun getChats(maxId: String?, sinceId: String?, sincedIdMinusOne: String?,
|
||||
limit: Int, requestMode: TimelineRequestMode
|
||||
override fun getChats(
|
||||
maxId: String?, sinceId: String?, sincedIdMinusOne: String?,
|
||||
limit: Int, requestMode: TimelineRequestMode
|
||||
): Single<out List<ChatStatus>> {
|
||||
val acc = accountManager.activeAccount ?: throw IllegalStateException()
|
||||
val accountId = acc.id
|
||||
|
||||
return if (requestMode == DISK) {
|
||||
return if(requestMode == DISK) {
|
||||
this.getChatsFromDb(accountId, maxId, sinceId, limit)
|
||||
} else {
|
||||
getChatsFromNetwork(maxId, sinceId, sincedIdMinusOne, limit, accountId, requestMode)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getChatMessages(chatId: String, maxId: String?, sinceId: String?, sincedIdMinusOne: String?, limit: Int, requestMode: TimelineRequestMode) : Single<out List<ChatMesssageOrPlaceholder>> {
|
||||
override fun getChatMessages(
|
||||
chatId: String,
|
||||
maxId: String?,
|
||||
sinceId: String?,
|
||||
sincedIdMinusOne: String?,
|
||||
limit: Int,
|
||||
requestMode: TimelineRequestMode
|
||||
): Single<out List<ChatMesssageOrPlaceholder>> {
|
||||
val acc = accountManager.activeAccount ?: throw IllegalStateException()
|
||||
val accountId = acc.id
|
||||
|
||||
|
@ -62,9 +107,10 @@ class ChatRepositoryImpl(
|
|||
return getChatMessagesFromNetwork(chatId, maxId, null, null, limit, accountId, requestMode)
|
||||
}
|
||||
|
||||
private fun getChatsFromNetwork(maxId: String?, sinceId: String?,
|
||||
sinceIdMinusOne: String?, limit: Int,
|
||||
accountId: Long, requestMode: TimelineRequestMode
|
||||
private fun getChatsFromNetwork(
|
||||
maxId: String?, sinceId: String?,
|
||||
sinceIdMinusOne: String?, limit: Int,
|
||||
accountId: Long, requestMode: TimelineRequestMode
|
||||
): Single<out List<ChatStatus>> {
|
||||
return mastodonApi.getChats(null, null, sinceIdMinusOne, 0, limit + 1)
|
||||
.map { chats ->
|
||||
|
@ -74,17 +120,18 @@ class ChatRepositoryImpl(
|
|||
this.addFromDbIfNeeded(accountId, chats, maxId, sinceId, limit, requestMode)
|
||||
}
|
||||
.onErrorResumeNext { error ->
|
||||
if (error is IOException && requestMode != NETWORK) {
|
||||
if(error is IOException && requestMode != NETWORK) {
|
||||
this.getChatsFromDb(accountId, maxId, sinceId, limit)
|
||||
} else {
|
||||
Single.error(error)
|
||||
}
|
||||
Single.error(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getChatMessagesFromNetwork(chatId: String, maxId: String?, sinceId: String?,
|
||||
sinceIdMinusOne: String?, limit: Int,
|
||||
accountId: Long, requestMode: TimelineRequestMode
|
||||
private fun getChatMessagesFromNetwork(
|
||||
chatId: String, maxId: String?, sinceId: String?,
|
||||
sinceIdMinusOne: String?, limit: Int,
|
||||
accountId: Long, requestMode: TimelineRequestMode
|
||||
): Single<out List<ChatMesssageOrPlaceholder>> {
|
||||
return mastodonApi.getChatMessages(chatId, maxId, null, sinceIdMinusOne, 0, limit + 1).map {
|
||||
it.mapTo(mutableListOf(), ChatMessage::lift)
|
||||
|
@ -92,62 +139,66 @@ class ChatRepositoryImpl(
|
|||
}
|
||||
|
||||
|
||||
private fun addFromDbIfNeeded(accountId: Long, chats: List<ChatStatus>,
|
||||
maxId: String?, sinceId: String?, limit: Int,
|
||||
requestMode: TimelineRequestMode
|
||||
private fun addFromDbIfNeeded(
|
||||
accountId: Long, chats: List<ChatStatus>,
|
||||
maxId: String?, sinceId: String?, limit: Int,
|
||||
requestMode: TimelineRequestMode
|
||||
): Single<List<ChatStatus>> {
|
||||
return if (requestMode != NETWORK && chats.size < 2) {
|
||||
val newMaxID = if (chats.isEmpty()) {
|
||||
return if(requestMode != NETWORK && chats.size < 2) {
|
||||
val newMaxID = if(chats.isEmpty()) {
|
||||
maxId
|
||||
} else {
|
||||
chats.last { it.isRight() }.asRight().id
|
||||
}
|
||||
this.getChatsFromDb(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() }) {
|
||||
chats
|
||||
} else {
|
||||
chats + 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() }) {
|
||||
chats
|
||||
} else {
|
||||
chats + fromDb
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Single.just(chats)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getChatsFromDb(accountId: Long, maxId: String?, sinceId: String?,
|
||||
limit: Int): Single<out List<ChatStatus>> {
|
||||
private fun getChatsFromDb(
|
||||
accountId: Long, maxId: String?, sinceId: String?,
|
||||
limit: Int
|
||||
): Single<out List<ChatStatus>> {
|
||||
return chatsDao.getChatsForAccount(accountId, maxId, sinceId, limit)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.map { chats ->
|
||||
chats.map { it.toChat(gson) }
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.map { chats ->
|
||||
chats.map { it.toChat(gson) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun saveChatsToDb(accountId: Long, chats: List<Chat>,
|
||||
maxId: String?, sinceId: String?
|
||||
private fun saveChatsToDb(
|
||||
accountId: Long, chats: List<Chat>,
|
||||
maxId: String?, sinceId: String?
|
||||
): List<ChatStatus> {
|
||||
var placeholderToInsert: Placeholder? = null
|
||||
|
||||
// Look for overlap
|
||||
val resultChats = if (chats.isNotEmpty() && sinceId != null) {
|
||||
val resultChats = if(chats.isNotEmpty() && sinceId != null) {
|
||||
val indexOfSince = chats.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())
|
||||
chats.mapTo(mutableListOf(), Chat::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.
|
||||
chats.mapTo(mutableListOf(), Chat::lift)
|
||||
.apply {
|
||||
subList(indexOfSince, size).clear()
|
||||
}
|
||||
.apply {
|
||||
subList(indexOfSince, size).clear()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Just a normal case.
|
||||
|
@ -160,13 +211,13 @@ class ChatRepositoryImpl(
|
|||
chatsDao.deleteRange(accountId, chats.last().id, chats.first().id)
|
||||
}
|
||||
|
||||
for (chat in chats) {
|
||||
for(chat in chats) {
|
||||
val pair = chat.toEntity(accountId, gson)
|
||||
|
||||
chatsDao.insertInTransaction(
|
||||
pair.first,
|
||||
pair.second,
|
||||
chat.account.toEntity(accountId, gson)
|
||||
pair.first,
|
||||
pair.second,
|
||||
chat.account.toEntity(accountId, gson)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -176,21 +227,24 @@ class ChatRepositoryImpl(
|
|||
|
||||
// If we're loading in the bottom insert placeholder after every load
|
||||
// (for requests on next launches) but not return it.
|
||||
if (sinceId == null && chats.isNotEmpty()) {
|
||||
if(sinceId == null && chats.isNotEmpty()) {
|
||||
chatsDao.insertChatIfNotThere(
|
||||
Placeholder(chats.last().id.dec()).toChatEntity(accountId))
|
||||
Placeholder(chats.last().id.dec()).toChatEntity(accountId)
|
||||
)
|
||||
}
|
||||
|
||||
// There may be placeholders which we thought could be from our TL but they are not
|
||||
if (chats.size > 2) {
|
||||
chatsDao.removeAllPlaceholdersBetween(accountId, chats.first().id,
|
||||
chats.last().id)
|
||||
} else if (placeholderToInsert == null && maxId != null && sinceId != null) {
|
||||
if(chats.size > 2) {
|
||||
chatsDao.removeAllPlaceholdersBetween(
|
||||
accountId, chats.first().id,
|
||||
chats.last().id
|
||||
)
|
||||
} else if(placeholderToInsert == null && maxId != null && sinceId != null) {
|
||||
chatsDao.removeAllPlaceholdersBetween(accountId, maxId, sinceId)
|
||||
}
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe()
|
||||
|
||||
return resultChats
|
||||
}
|
||||
|
@ -200,62 +254,73 @@ private val emojisListTypeToken = object : TypeToken<List<Emoji>>() {}
|
|||
|
||||
fun Placeholder.toChatEntity(timelineUserId: Long): ChatEntity {
|
||||
return ChatEntity(
|
||||
localId = timelineUserId,
|
||||
chatId = this.id,
|
||||
accountId = "",
|
||||
unread = 0L,
|
||||
updatedAt = 0L,
|
||||
lastMessageId = null
|
||||
localId = timelineUserId,
|
||||
chatId = this.id,
|
||||
accountId = "",
|
||||
unread = 0L,
|
||||
updatedAt = 0L,
|
||||
lastMessageId = null
|
||||
)
|
||||
}
|
||||
|
||||
fun ChatMessage.toEntity(timelineUserId: Long, gson: Gson) : ChatMessageEntity {
|
||||
fun ChatMessage.toEntity(timelineUserId: Long, gson: Gson): ChatMessageEntity {
|
||||
return ChatMessageEntity(
|
||||
localId = timelineUserId,
|
||||
messageId = this.id,
|
||||
content = this.content?.toHtml(),
|
||||
chatId = this.chatId,
|
||||
accountId = this.accountId,
|
||||
createdAt = this.createdAt.time,
|
||||
attachment = this.attachment?.let { gson.toJson(it, Attachment::class.java) },
|
||||
emojis = gson.toJson(this.emojis)
|
||||
localId = timelineUserId,
|
||||
messageId = this.id,
|
||||
content = this.content?.toHtml(),
|
||||
chatId = this.chatId,
|
||||
accountId = this.accountId,
|
||||
createdAt = this.createdAt.time,
|
||||
attachment = this.attachment?.let { gson.toJson(it, Attachment::class.java) },
|
||||
emojis = gson.toJson(this.emojis)
|
||||
)
|
||||
}
|
||||
|
||||
fun Chat.toEntity(timelineUserId: Long, gson: Gson): Pair<ChatEntity, ChatMessageEntity?> {
|
||||
return Pair(ChatEntity(
|
||||
return Pair(
|
||||
ChatEntity(
|
||||
localId = timelineUserId,
|
||||
chatId = this.id,
|
||||
accountId = this.account.id,
|
||||
unread = this.unread,
|
||||
updatedAt = this.updatedAt.time,
|
||||
lastMessageId = this.lastMessage?.id
|
||||
), this.lastMessage?.toEntity(timelineUserId, gson))
|
||||
}
|
||||
|
||||
fun ChatMessageEntity.toChatMessage(gson: Gson) : ChatMessage {
|
||||
return ChatMessage(
|
||||
id = this.messageId,
|
||||
content = this.content?.let { it.parseAsHtml().trimTrailingWhitespace() },
|
||||
chatId = this.chatId,
|
||||
accountId = this.accountId,
|
||||
createdAt = Date(this.createdAt),
|
||||
attachment = this.attachment?.let { gson.fromJson(it, Attachment::class.java) },
|
||||
emojis = gson.fromJson(this.emojis, object : TypeToken<List<Emoji>>() {}.type ),
|
||||
card = null /* don't care about card */
|
||||
), this.lastMessage?.toEntity(timelineUserId, gson)
|
||||
)
|
||||
}
|
||||
|
||||
fun ChatEntityWithAccount.toChat(gson: Gson) : ChatStatus {
|
||||
fun ChatMessageEntity.toChatMessage(gson: Gson): ChatMessage {
|
||||
return ChatMessage(
|
||||
id = this.messageId,
|
||||
content = this.content?.let { it.parseAsHtml().trimTrailingWhitespace() },
|
||||
chatId = this.chatId,
|
||||
accountId = this.accountId,
|
||||
createdAt = Date(this.createdAt),
|
||||
attachment = this.attachment?.let { gson.fromJson(it, Attachment::class.java) },
|
||||
emojis = gson.fromJson(this.emojis, object : TypeToken<List<Emoji>>() {}.type),
|
||||
card = null /* don't care about card */
|
||||
)
|
||||
}
|
||||
|
||||
fun ChatEntityWithAccount.toChat(gson: Gson): ChatStatus {
|
||||
if(account == null || chat.accountId.isEmpty() || chat.updatedAt == 0L)
|
||||
return Either.Left(Placeholder(chat.chatId))
|
||||
|
||||
return Chat(
|
||||
account = this.account?.toAccount(gson) ?: Account("", "", "", "", SpannedString(""), "", "", "" ),
|
||||
id = this.chat.chatId,
|
||||
unread = this.chat.unread,
|
||||
updatedAt = Date(this.chat.updatedAt),
|
||||
lastMessage = this.lastMessage?.toChatMessage(gson)
|
||||
account = this.account?.toAccount(gson) ?: Account(
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
SpannedString(""),
|
||||
"",
|
||||
"",
|
||||
""
|
||||
),
|
||||
id = this.chat.chatId,
|
||||
unread = this.chat.unread,
|
||||
updatedAt = Date(this.chat.updatedAt),
|
||||
lastMessage = this.lastMessage?.toChatMessage(gson)
|
||||
).lift()
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue