Simple chat & small fixes

This commit is contained in:
2021-09-12 23:35:23 +03:00
parent f098a9ff12
commit 400ff118b5
51 changed files with 1610 additions and 203 deletions
@@ -12,6 +12,7 @@ object VKConstants {
const val VK_APP_ID = "2274003"
const val VK_SECRET = "hHbZxrka2uZ6jB1inYsH"
const val FAST_GROUP_ID = -119516304
object Auth {
const val SCOPE = "notify," +
@@ -1,106 +0,0 @@
package com.meloda.fast.api
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.meloda.fast.api.datasource.AuthDataSource
import com.meloda.fast.api.datasource.ConversationsDataSource
import com.meloda.fast.api.datasource.MessagesDataSource
import com.meloda.fast.api.datasource.UsersDataSource
import com.meloda.fast.api.network.AuthInterceptor
import com.meloda.fast.api.network.ResultCallFactory
import com.meloda.fast.api.network.repo.AuthRepo
import com.meloda.fast.api.network.repo.ConversationsRepo
import com.meloda.fast.api.network.repo.MessagesRepo
import com.meloda.fast.api.network.repo.UsersRepo
import com.meloda.fast.database.dao.ConversationsDao
import com.meloda.fast.database.dao.MessagesDao
import com.meloda.fast.database.dao.UsersDao
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
import javax.inject.Singleton
@InstallIn(SingletonComponent::class)
@Module
class VKModules {
@Singleton
@Provides
fun provideOkHttpClient(authInterceptor: AuthInterceptor): OkHttpClient = OkHttpClient.Builder()
.connectTimeout(20, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.addInterceptor(authInterceptor)
.followRedirects(true)
.followSslRedirects(true)
.addInterceptor(HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}).build()
@Singleton
@Provides
fun provideGson(): Gson = GsonBuilder()
.setLenient()
.create()
@Singleton
@Provides
fun provideRetrofit(
client: OkHttpClient,
gson: Gson
): Retrofit = Retrofit.Builder()
.baseUrl("https://api.vk.com/")
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(ResultCallFactory())
.client(client)
.build()
@Provides
@Singleton
fun provideAuthInterceptor(): AuthInterceptor = AuthInterceptor()
@Provides
fun provideAuthRepo(retrofit: Retrofit): AuthRepo =
retrofit.create(AuthRepo::class.java)
@Provides
fun provideConversationsRepo(retrofit: Retrofit): ConversationsRepo =
retrofit.create(ConversationsRepo::class.java)
@Provides
fun provideUsersRepo(retrofit: Retrofit): UsersRepo =
retrofit.create(UsersRepo::class.java)
@Provides
@Singleton
fun provideAuthDataSource(
repo: AuthRepo
): AuthDataSource = AuthDataSource(repo)
@Provides
@Singleton
fun provideUsersDataSource(
repo: UsersRepo,
dao: UsersDao
): UsersDataSource = UsersDataSource(repo, dao)
@Provides
@Singleton
fun provideConversationsDataSource(
repo: ConversationsRepo,
dao: ConversationsDao
): ConversationsDataSource = ConversationsDataSource(repo, dao)
@Provides
@Singleton
fun provideMessagesDataSource(
repo: MessagesRepo,
dao: MessagesDao
): MessagesDataSource = MessagesDataSource(repo, dao)
}
@@ -5,7 +5,6 @@ import android.graphics.drawable.Drawable
import androidx.core.content.ContextCompat
import com.meloda.fast.R
import com.meloda.fast.api.model.VkGroup
import com.meloda.fast.api.model.VkGroupCall
import com.meloda.fast.api.model.VkMessage
import com.meloda.fast.api.model.VkUser
import com.meloda.fast.api.model.attachments.*
@@ -25,6 +24,12 @@ object VkUtils {
return throwable.error == VKErrors.NEED_CAPTCHA
}
fun prepareMessageText(text: String): String {
return text
.replace("\n", " ")
.replace("&amp", "&")
}
fun parseForwards(baseForwards: List<BaseVkMessage>?): List<VkMessage>? {
if (baseForwards.isNullOrEmpty()) return null
@@ -1,6 +1,8 @@
package com.meloda.fast.api.datasource
import com.meloda.fast.api.network.repo.MessagesRepo
import com.meloda.fast.api.network.request.MessagesGetHistoryRequest
import com.meloda.fast.api.network.request.MessagesSendRequest
import com.meloda.fast.database.dao.MessagesDao
import javax.inject.Inject
@@ -9,4 +11,8 @@ class MessagesDataSource @Inject constructor(
private val dao: MessagesDao
) {
suspend fun getHistory(params: MessagesGetHistoryRequest) = repo.getHistory(params.map)
suspend fun send(params: MessagesSendRequest) = repo.send(params.map)
}
@@ -1,10 +1,13 @@
package com.meloda.fast.api.model
import android.os.Parcelable
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
import kotlinx.parcelize.Parcelize
@Entity(tableName = "conversations")
@Parcelize
data class VkConversation(
@PrimaryKey(autoGenerate = false)
val id: Int,
@@ -18,8 +21,9 @@ data class VkConversation(
val outRead: Int,
val isMarkedUnread: Boolean,
val lastMessageId: Int,
val unreadCount: Int?
) {
val unreadCount: Int?,
val membersCount: Int?
) : Parcelable {
@Ignore
var lastMessage: VkMessage? = null
@@ -1,16 +1,19 @@
package com.meloda.fast.api.model
import android.os.Parcelable
import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.parcelize.Parcelize
@Entity(tableName = "groups")
@Parcelize
data class VkGroup(
@PrimaryKey(autoGenerate = false)
val id: Int,
val name: String,
val screenName: String,
val photo200: String?
) {
): Parcelable {
override fun toString() = name.trim()
@@ -1,7 +0,0 @@
package com.meloda.fast.api.model
import com.meloda.fast.api.model.attachments.VkAttachment
data class VkGroupCall(
val initiatorId: Int
) : VkAttachment()
@@ -1,41 +1,69 @@
package com.meloda.fast.api.model
import android.os.Parcelable
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
import com.meloda.fast.api.model.attachments.VkAttachment
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
@Entity(tableName = "messages")
@Parcelize
data class VkMessage(
@PrimaryKey(autoGenerate = false)
val id: Int,
val text: String?,
val text: String? = null,
val isOut: Boolean,
val peerId: Int,
val fromId: Int,
val date: Int,
val action: String?,
val actionMemberId: Int?,
val actionText: String?,
val actionConversationMessageId: Int?,
val actionMessage: String?,
val geoType: String?
) {
val randomId: Int,
val action: String? = null,
val actionMemberId: Int? = null,
val actionText: String? = null,
val actionConversationMessageId: Int? = null,
val actionMessage: String? = null,
val geoType: String? = null
) : Parcelable {
@IgnoredOnParcel
@Ignore
var forwards: List<VkMessage>? = null
@IgnoredOnParcel
@Ignore
var attachments: List<VkAttachment>? = null
fun isPeerChat() = peerId > 2_000_000_000
fun isUser() = fromId > 0
fun isGroup() = fromId < 0
fun isRead(conversation: VkConversation) = conversation.outRead < id
fun getPreparedAction(): Action? {
if (action == null) return null
return Action.parse(action)
}
fun changeId(id: Int) = VkMessage(
id = id,
text = text,
isOut = isOut,
peerId = peerId,
fromId = fromId,
date = date,
randomId = randomId,
action = action,
actionMemberId = actionMemberId,
actionText = actionText,
actionConversationMessageId = actionConversationMessageId,
actionMessage = actionMessage,
geoType = geoType
)
enum class Action(val value: String) {
CHAT_CREATE("chat_create"),
CHAT_PHOTO_UPDATE("chat_photo_update"),
@@ -1,9 +1,12 @@
package com.meloda.fast.api.model
import android.os.Parcelable
import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.parcelize.Parcelize
@Entity(tableName = "users")
@Parcelize
data class VkUser(
@PrimaryKey(autoGenerate = false)
val id: Int,
@@ -11,7 +14,7 @@ data class VkUser(
val lastName: String,
val online: Boolean,
val photo200: String?
) {
) : Parcelable {
override fun toString() = "$firstName $lastName".trim()
@@ -0,0 +1,5 @@
package com.meloda.fast.api.model.attachments
data class VkGroupCall(
val initiatorId: Int
) : VkAttachment()
@@ -50,7 +50,8 @@ data class BaseVkConversation(
outRead = outRead,
isMarkedUnread = isMarkedUnread,
lastMessageId = lastMessageId,
unreadCount = unreadCount
unreadCount = unreadCount,
membersCount = chatSettings?.membersCount
).apply { this.lastMessage = lastMessage }
@Parcelize
@@ -40,6 +40,7 @@ data class BaseVkMessage(
peerId = peerId,
fromId = fromId,
date = date,
randomId = randomId,
action = action?.type,
actionMemberId = action?.memberId,
actionText = action?.text,
@@ -6,16 +6,21 @@ object VKUrls {
const val API = "https://api.vk.com/method"
object Auth {
const val directAuth = "$OAUTH/token"
const val sendSms = "$API/auth.validatePhone"
const val DirectAuth = "$OAUTH/token"
const val SendSms = "$API/auth.validatePhone"
}
object Conversations {
const val get = "$API/messages.getConversations"
const val Get = "$API/messages.getConversations"
}
object Users {
const val getById = "$API/users.get"
const val GetById = "$API/users.get"
}
object Messages {
const val GetHistory = "$API/messages.getHistory"
const val Send = "$API/messages.send"
}
@@ -8,10 +8,10 @@ import retrofit2.http.*
interface AuthRepo {
@GET(VKUrls.Auth.directAuth)
@GET(VKUrls.Auth.DirectAuth)
suspend fun auth(@QueryMap param: Map<String, String?>): Answer<ResponseAuthDirect>
@GET(VKUrls.Auth.sendSms)
@GET(VKUrls.Auth.SendSms)
suspend fun sendSms(@Query("sid") validationSid: String): Answer<ResponseSendSms>
}
@@ -11,7 +11,7 @@ import retrofit2.http.POST
interface ConversationsRepo {
@FormUrlEncoded
@POST(VKUrls.Conversations.get)
@POST(VKUrls.Conversations.Get)
suspend fun getAllChats(@FieldMap params: Map<String, String>): Answer<ApiResponse<ConversationsGetResponse>>
}
@@ -1,4 +1,21 @@
package com.meloda.fast.api.network.repo
import com.meloda.fast.api.base.ApiResponse
import com.meloda.fast.api.network.Answer
import com.meloda.fast.api.network.VKUrls
import com.meloda.fast.api.network.response.MessagesGetHistoryResponse
import retrofit2.http.FieldMap
import retrofit2.http.FormUrlEncoded
import retrofit2.http.POST
interface MessagesRepo {
@FormUrlEncoded
@POST(VKUrls.Messages.GetHistory)
suspend fun getHistory(@FieldMap params: Map<String, String>): Answer<ApiResponse<MessagesGetHistoryResponse>>
@FormUrlEncoded
@POST(VKUrls.Messages.Send)
suspend fun send(@FieldMap params: Map<String, String>): Answer<ApiResponse<Int>>
}
@@ -11,7 +11,7 @@ import retrofit2.http.POST
interface UsersRepo {
@FormUrlEncoded
@POST(VKUrls.Users.getById)
@POST(VKUrls.Users.GetById)
suspend fun getById(
@FieldMap params: Map<String, String>?
): Answer<ApiResponse<List<BaseVkUser>>>
@@ -1,7 +1,6 @@
package com.meloda.fast.api.network.request
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
import kotlinx.parcelize.Parcelize
@Parcelize
@@ -11,7 +10,6 @@ data class ConversationsGetRequest(
val fields: String = "",
val filter: String = "all",
val extended: Boolean? = true,
@SerializedName("start_message_id")
val startMessageId: Int? = null
) : Parcelable {
@@ -0,0 +1,58 @@
package com.meloda.fast.api.network.request
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
data class MessagesGetHistoryRequest(
val count: Int? = null,
val offset: Int? = null,
val peerId: Int,
val extended: Boolean? = null,
val startMessageId: Int? = null,
val rev: Boolean? = null,
val fields: String? = null,
) : Parcelable {
val map
get() = mutableMapOf(
"peer_id" to peerId.toString()
).apply {
count?.let { this["count"] = it.toString() }
offset?.let { this["offset"] = it.toString() }
extended?.let { this["extended"] = (if (it) 1 else 0).toString() }
startMessageId?.let { this["start_message_id"] = it.toString() }
rev?.let { this["rev"] = (if (it) 1 else 0).toString() }
fields?.let { this["fields"] = it }
}
}
@Parcelize
data class MessagesSendRequest(
val peerId: Int,
val randomId: Int = 0,
val message: String? = null,
val lat: Int? = null,
val lon: Int? = null,
val replyTo: Int? = null,
val stickerId: Int? = null,
val disableMentions: Boolean? = null,
val dontParseLinks: Boolean? = null
) : Parcelable {
val map
get() = mutableMapOf(
"peer_id" to peerId.toString(),
"random_id" to randomId.toString()
).apply {
message?.let { this["message"] = it }
lat?.let { this["lat"] = it.toString() }
lon?.let { this["lon"] = it.toString() }
replyTo?.let { this["reply_to"] = it.toString() }
stickerId?.let { this["sticker_id"] = it.toString() }
disableMentions?.let { this["disable_mentions"] = (if (it) 1 else 0).toString() }
dontParseLinks?.let { this["dont_parse_links"] = (if (it) 1 else 0).toString() }
}
}
@@ -0,0 +1,17 @@
package com.meloda.fast.api.network.response
import android.os.Parcelable
import com.meloda.fast.api.model.base.BaseVkConversation
import com.meloda.fast.api.model.base.BaseVkGroup
import com.meloda.fast.api.model.base.BaseVkMessage
import com.meloda.fast.api.model.base.BaseVkUser
import kotlinx.parcelize.Parcelize
@Parcelize
data class MessagesGetHistoryResponse(
val count: Int,
val items: List<BaseVkMessage> = listOf(),
val conversations: List<BaseVkConversation>?,
val profiles: List<BaseVkUser>?,
val groups: List<BaseVkGroup>?
) : Parcelable