support for articles; ui & ux & logic fixes for 2fa and captcha screens; fix mentions;

This commit is contained in:
2024-07-13 01:37:24 +03:00
parent 25acc6505b
commit ce1867c22c
38 changed files with 449 additions and 218 deletions
@@ -40,12 +40,15 @@ class OAuthRepositoryImpl(
requireNotNull(result.error)
}
else -> throw IllegalStateException("Unknown result")
is ApiResult.Failure.ApiFailure -> TODO()
// is ApiResult.Failure.ApiFailure -> TODO()
// is ApiResult.Failure.HttpFailure -> TODO()
// is ApiResult.Failure.NetworkFailure -> TODO()
// is ApiResult.Failure.UnknownFailure -> TODO()
is ApiResult.Failure.NetworkFailure -> {
// TODO: 13/07/2024, Danil Nikolaev: implement showing network error
TODO()
}
is ApiResult.Failure.UnknownFailure -> TODO()
else -> throw IllegalStateException("Unknown result")
}
}
}
@@ -104,6 +104,7 @@
<string name="message_attachments_audio_playlist">Playlist</string>
<string name="message_attachments_podcast">Podcast</string>
<string name="message_attachments_narrative">Narrative</string>
<string name="message_attachments_article">Article</string>
<string name="chat_interaction_uploading_file">Uploading file</string>
<string name="chat_interaction_uploading_photo">Uploading photo</string>
+3
View File
@@ -32,6 +32,9 @@ dependencies {
implementation(libs.moshi.kotlin)
ksp(libs.moshi.kotlin.codegen)
implementation(platform(libs.compose.bom))
implementation(libs.bundles.compose)
implementation(libs.room.ktx)
implementation(libs.room.runtime)
ksp(libs.room.compiler)
@@ -1,5 +1,9 @@
package com.meloda.app.fast.model
import androidx.compose.runtime.Immutable
@Immutable
sealed class BaseError {
data object SessionExpired : BaseError()
}
@@ -26,7 +26,8 @@ enum class AttachmentType(var value: String) {
ARTIST("artist"),
AUDIO_PLAYLIST("audio_playlist"),
PODCAST("podcast"),
NARRATIVE("narrative");
NARRATIVE("narrative"),
ARTICLE("article");
fun isMultiple(): Boolean = this in listOf(PHOTO, VIDEO, AUDIO, FILE)
@@ -0,0 +1,15 @@
package com.meloda.app.fast.model.api.data
import com.meloda.app.fast.model.api.domain.VkArticleDomain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VkArticleData(
@Json(name = "id") val id: Int
) : VkAttachmentData {
fun toDomain(): VkArticleDomain = VkArticleDomain(
id = id
)
}
@@ -31,7 +31,8 @@ data class VkAttachmentItemData(
@Json(name = "audios") val audios: List<VkAudioData>?,
@Json(name = "audio_playlist") val audioPlaylist: VkAudioPlaylistData?,
@Json(name = "podcast") val podcast: VkPodcastData?,
@Json(name = "narrative") val narrative: VkNarrativeData?
@Json(name = "narrative") val narrative: VkNarrativeData?,
@Json(name = "article") val article: VkArticleData?
) {
fun toDomain(): VkAttachment = when (AttachmentType.parse(type)) {
AttachmentType.UNKNOWN -> VkUnknownAttachment
@@ -58,5 +59,6 @@ data class VkAttachmentItemData(
AttachmentType.AUDIO_PLAYLIST -> audioPlaylist?.toDomain()
AttachmentType.PODCAST -> podcast?.toDomain()
AttachmentType.NARRATIVE -> narrative?.toDomain()
AttachmentType.ARTICLE -> article?.toDomain()
} ?: VkUnknownAttachment
}
@@ -10,11 +10,11 @@ data class VkGroupData(
@Json(name = "id") val id: Int,
@Json(name = "name") val name: String,
@Json(name = "screen_name") val screenName: String,
@Json(name = "is_closed") val isClosed: Int,
@Json(name = "is_closed") val isClosed: Int?,
@Json(name = "type") val type: String,
@Json(name = "is_admin") val isAdmin: Int,
@Json(name = "is_member") val isMember: Int,
@Json(name = "is_advertiser") val isAdvertiser: Int,
@Json(name = "is_admin") val isAdmin: Int?,
@Json(name = "is_member") val isMember: Int?,
@Json(name = "is_advertiser") val isAdvertiser: Int?,
@Json(name = "photo_50") val photo50: String?,
@Json(name = "photo_100") val photo100: String?,
@Json(name = "photo_200") val photo200: String?,
@@ -0,0 +1,10 @@
package com.meloda.app.fast.model.api.domain
import com.meloda.app.fast.model.api.data.AttachmentType
data class VkArticleDomain(
val id: Int
) : VkAttachment {
override val type: AttachmentType = AttachmentType.ARTICLE
}
@@ -75,7 +75,7 @@ data class InvalidCredentialsError(
)
@JsonClass(generateAdapter = true)
data class WrongTwoFaCode(
data class WrongTwoFaCodeError(
@Json(name = "error") override val error: String, // "invalid_request"
@Json(name = "error_description") override val errorDescription: String,
@Json(name = "error_type") override val errorType: String // "wrong_otp"
@@ -86,7 +86,7 @@ data class WrongTwoFaCode(
)
@JsonClass(generateAdapter = true)
data class WrongTwoFaCodeFormat(
data class WrongTwoFaCodeFormatError(
@Json(name = "error") override val error: String, // "invalid_request"
@Json(name = "error_description") override val errorDescription: String,
@Json(name = "error_type") override val errorType: String // "otp_format_is_incorrect"
@@ -96,6 +96,17 @@ data class WrongTwoFaCodeFormat(
errorType = errorType
)
@JsonClass(generateAdapter = true)
data class TooManyTriesError(
@Json(name = "error") override val error: String, // "9;Flood control"
@Json(name = "error_description") override val errorDescription: String,
@Json(name = "error_type") override val errorType: String // "password_bruteforce_attempt"
) : OAuthError(
error = error,
errorDescription = errorDescription,
errorType = errorType
)
fun OAuthError.toDomain(): OAuthErrorDomain? = when (this) {
is ValidationRequiredError -> {
OAuthErrorDomain.ValidationRequiredError(
@@ -129,13 +140,17 @@ fun OAuthError.toDomain(): OAuthErrorDomain? = when (this) {
OAuthErrorDomain.InvalidCredentialsError
}
is WrongTwoFaCode -> {
is WrongTwoFaCodeError -> {
OAuthErrorDomain.WrongTwoFaCode
}
is WrongTwoFaCodeFormat -> {
is WrongTwoFaCodeFormatError -> {
OAuthErrorDomain.WrongTwoFaCodeFormat
}
is TooManyTriesError -> {
OAuthErrorDomain.TooManyTriesError
}
else -> null
}
@@ -27,5 +27,7 @@ sealed class OAuthErrorDomain {
data object InvalidCredentialsError : OAuthErrorDomain()
data object WrongTwoFaCode : OAuthErrorDomain()
data object WrongTwoFaCodeFormat : OAuthErrorDomain()
data object TooManyTriesError: OAuthErrorDomain()
data object UnknownError : OAuthErrorDomain()
}
@@ -110,6 +110,11 @@ internal class ResultCall<R : Any, E : OAuthError>(
.fromJson(errorBodyString.orEmpty()) ?: return
val error: OAuthError? = when (baseError.error) {
"9;Flood control" -> {
moshi.adapter(TooManyTriesError::class.java)
.fromJson(errorBodyString.orEmpty())
}
"invalid_client" -> {
moshi.adapter(InvalidCredentialsError::class.java)
.fromJson(errorBodyString.orEmpty())
@@ -123,12 +128,12 @@ internal class ResultCall<R : Any, E : OAuthError>(
"invalid_request" -> {
when (val type = baseError.errorType) {
"wrong_otp" -> {
moshi.adapter(WrongTwoFaCode::class.java)
moshi.adapter(WrongTwoFaCodeError::class.java)
.fromJson(errorBodyString.orEmpty())
}
"otp_format_is_incorrect" -> {
moshi.adapter(WrongTwoFaCodeFormat::class.java)
moshi.adapter(WrongTwoFaCodeFormatError::class.java)
.fromJson(errorBodyString.orEmpty())
}
@@ -51,10 +51,12 @@ object VkOAuthErrors {
const val NEED_CAPTCHA = "need_captcha"
const val INVALID_CLIENT = "invalid_client"
const val INVALID_REQUEST = "invalid_request"
const val FLOOD_CONTROL = "9;Flood control"
}
object VkErrorTypes {
const val WRONG_OTP_FORMAT = "otp_format_is_incorrect"
const val WRONG_OTP = "wrong_otp"
const val PASSWORD_BRUTEFORCE_ATTEMPT = "password_bruteforce_attempt"
}