diff --git a/core/common/src/main/kotlin/dev/meloda/fast/common/AppConstants.kt b/core/common/src/main/kotlin/dev/meloda/fast/common/AppConstants.kt index 333ce1c5..5f5f2602 100644 --- a/core/common/src/main/kotlin/dev/meloda/fast/common/AppConstants.kt +++ b/core/common/src/main/kotlin/dev/meloda/fast/common/AppConstants.kt @@ -4,7 +4,7 @@ object AppConstants { const val INSTALL_APP_MIME_TYPE = "application/vnd.android.package-archive" - const val API_VERSION = "5.238" + const val API_VERSION = "5.263" const val URL_OAUTH = "https://oauth.vk.ru" const val URL_API = "https://api.vk.ru/method" diff --git a/core/domain/src/main/kotlin/dev/meloda/fast/domain/util/ConvoMapper.kt b/core/domain/src/main/kotlin/dev/meloda/fast/domain/util/ConvoMapper.kt index 2d55cfed..84f043d1 100644 --- a/core/domain/src/main/kotlin/dev/meloda/fast/domain/util/ConvoMapper.kt +++ b/core/domain/src/main/kotlin/dev/meloda/fast/domain/util/ConvoMapper.kt @@ -598,6 +598,7 @@ private fun getAttachmentIconByType(attachmentType: AttachmentType): UiImage? { AttachmentType.VIDEO_MESSAGE -> null AttachmentType.GROUP_CHAT_STICKER -> R.drawable.ic_sticker_fill_round_24 AttachmentType.STICKER_PACK_PREVIEW -> null + AttachmentType.CHANNEL_MESSAGE -> null }?.let(UiImage::Resource) } @@ -687,6 +688,7 @@ fun getAttachmentUiText( AttachmentType.VIDEO_MESSAGE -> R.string.message_attachments_video_message AttachmentType.GROUP_CHAT_STICKER -> R.string.message_attachments_group_sticker AttachmentType.STICKER_PACK_PREVIEW -> R.string.message_attachments_sticker_pack_preview + AttachmentType.CHANNEL_MESSAGE -> R.string.message_attachments_channel_message }.let(UiText::Resource) } diff --git a/core/model/src/main/kotlin/dev/meloda/fast/model/api/data/AttachmentType.kt b/core/model/src/main/kotlin/dev/meloda/fast/model/api/data/AttachmentType.kt index ced68273..3527fb60 100644 --- a/core/model/src/main/kotlin/dev/meloda/fast/model/api/data/AttachmentType.kt +++ b/core/model/src/main/kotlin/dev/meloda/fast/model/api/data/AttachmentType.kt @@ -30,7 +30,8 @@ enum class AttachmentType(var value: String) { ARTICLE("article"), VIDEO_MESSAGE("video_message"), GROUP_CHAT_STICKER("ugc_sticker"), - STICKER_PACK_PREVIEW("sticker_pack_preview") + STICKER_PACK_PREVIEW("sticker_pack_preview"), + CHANNEL_MESSAGE("channel_message") ; fun isMultiple(): Boolean = this in listOf(PHOTO, VIDEO, AUDIO, FILE) diff --git a/core/model/src/main/kotlin/dev/meloda/fast/model/api/data/VkAttachmentItemData.kt b/core/model/src/main/kotlin/dev/meloda/fast/model/api/data/VkAttachmentItemData.kt index 47db4f55..9282f01b 100644 --- a/core/model/src/main/kotlin/dev/meloda/fast/model/api/data/VkAttachmentItemData.kt +++ b/core/model/src/main/kotlin/dev/meloda/fast/model/api/data/VkAttachmentItemData.kt @@ -35,7 +35,8 @@ data class VkAttachmentItemData( @Json(name = "article") val article: VkArticleData?, @Json(name = "video_message") val videoMessage: VkVideoMessageData?, @Json(name = "ugc_sticker") val groupSticker: VkGroupStickerData?, - @Json(name = "sticker_pack_preview") val stickerPackPreview: VkStickerPackPreviewData? + @Json(name = "sticker_pack_preview") val stickerPackPreview: VkStickerPackPreviewData?, + @Json(name = "channel_message") val channelMessageData: VkChannelMessageData? ) { fun toDomain(): VkAttachment = when (AttachmentType.parse(type)) { AttachmentType.UNKNOWN -> VkUnknownAttachment @@ -66,5 +67,6 @@ data class VkAttachmentItemData( AttachmentType.VIDEO_MESSAGE -> videoMessage?.toDomain() AttachmentType.GROUP_CHAT_STICKER -> groupSticker?.toDomain() AttachmentType.STICKER_PACK_PREVIEW -> stickerPackPreview?.toDomain() + AttachmentType.CHANNEL_MESSAGE -> channelMessageData?.toDomain() } ?: VkUnknownAttachment } diff --git a/core/model/src/main/kotlin/dev/meloda/fast/model/api/data/VkChannelMessageData.kt b/core/model/src/main/kotlin/dev/meloda/fast/model/api/data/VkChannelMessageData.kt new file mode 100644 index 00000000..5897dddb --- /dev/null +++ b/core/model/src/main/kotlin/dev/meloda/fast/model/api/data/VkChannelMessageData.kt @@ -0,0 +1,40 @@ +package dev.meloda.fast.model.api.data + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass +import dev.meloda.fast.model.api.domain.VkChannelMessage + +@JsonClass(generateAdapter = true) +data class VkChannelMessageData( + @Json(name = "channel_id") val channelId: Long, + @Json(name = "cmid") val cmId: Long, + @Json(name = "author_id") val authorId: Long, + @Json(name = "channel_info") val channelInfo: ChannelInfo, + @Json(name = "channel_type") val channelType: String, + @Json(name = "guid") val guid: String, + @Json(name = "text") val text: String?, + @Json(name = "time") val time: Long, + @Json(name = "attachments") val attachments: List = emptyList(), +) : VkAttachmentData { + + @JsonClass(generateAdapter = true) + data class ChannelInfo( + @Json(name = "photo_base") val photoBase: String?, + @Json(name = "title") val title: String + ) + + fun toDomain(): VkChannelMessage = VkChannelMessage( + channelId = channelId, + cmId = cmId, + authorId = authorId, + channelInfo = VkChannelMessage.ChannelInfo( + title = channelInfo.title, + photoBase = channelInfo.photoBase + ), + channelType = channelType, + guid = guid, + text = text, + time = time, + attachments = attachments.map(VkAttachmentItemData::toDomain), + ) +} diff --git a/core/model/src/main/kotlin/dev/meloda/fast/model/api/domain/VkChannelMessage.kt b/core/model/src/main/kotlin/dev/meloda/fast/model/api/domain/VkChannelMessage.kt new file mode 100644 index 00000000..46d0ae89 --- /dev/null +++ b/core/model/src/main/kotlin/dev/meloda/fast/model/api/domain/VkChannelMessage.kt @@ -0,0 +1,23 @@ +package dev.meloda.fast.model.api.domain + +import dev.meloda.fast.model.api.data.AttachmentType + +data class VkChannelMessage( + val channelId: Long, + val cmId: Long, + val authorId: Long, + val channelInfo: ChannelInfo, + val channelType: String, + val guid: String, + val text: String?, + val time: Long, + val attachments: List?, +) : VkAttachment { + + data class ChannelInfo( + val title: String, + val photoBase: String? + ) + + override val type: AttachmentType = AttachmentType.CHANNEL_MESSAGE +} diff --git a/core/ui/src/main/kotlin/dev/meloda/fast/ui/theme/AppTheme.kt b/core/ui/src/main/kotlin/dev/meloda/fast/ui/theme/AppTheme.kt index f2830ee8..1af0133b 100644 --- a/core/ui/src/main/kotlin/dev/meloda/fast/ui/theme/AppTheme.kt +++ b/core/ui/src/main/kotlin/dev/meloda/fast/ui/theme/AppTheme.kt @@ -58,7 +58,7 @@ fun AppTheme( ) { val context = LocalContext.current - val colorScheme: ColorScheme = when { + val colorScheme: ColorScheme = predefinedColorScheme ?: when { useDynamicColors && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { if (useDarkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) @@ -82,10 +82,6 @@ fun AppTheme( } } - val colorPrimary by animateColorAsState(colorScheme.primary) - val colorSurface by animateColorAsState(colorScheme.surface) - val colorBackground by animateColorAsState(colorScheme.background) - val typography = if (useSystemFont) { MaterialTheme.typography } else { @@ -118,12 +114,7 @@ fun AppTheme( } MaterialExpressiveTheme( - colorScheme = (predefinedColorScheme ?: colorScheme) - .copy( - primary = colorPrimary, - background = colorBackground, - surface = colorSurface - ), + colorScheme = colorScheme, typography = typography, content = content ) diff --git a/core/ui/src/main/res/values/strings.xml b/core/ui/src/main/res/values/strings.xml index fa25f3d9..f86ae261 100644 --- a/core/ui/src/main/res/values/strings.xml +++ b/core/ui/src/main/res/values/strings.xml @@ -88,6 +88,7 @@ Video message Group sticker Sticker pack preview + Channel message Uploading file Uploading photo diff --git a/feature/auth/src/main/kotlin/dev/meloda/fast/auth/login/LoginViewModel.kt b/feature/auth/src/main/kotlin/dev/meloda/fast/auth/login/LoginViewModel.kt index b1c15789..96896659 100644 --- a/feature/auth/src/main/kotlin/dev/meloda/fast/auth/login/LoginViewModel.kt +++ b/feature/auth/src/main/kotlin/dev/meloda/fast/auth/login/LoginViewModel.kt @@ -100,7 +100,13 @@ class LoginViewModel( } fun onBackPressed() { - _screenState.setValue { old -> old.copy(showLogo = true) } + _screenState.setValue { old -> + old.copy( + showLogo = true, + loginError = false, + passwordError = false + ) + } } fun onPasswordVisibilityButtonClicked() { diff --git a/feature/auth/src/main/kotlin/dev/meloda/fast/auth/login/presentation/LoginScreen.kt b/feature/auth/src/main/kotlin/dev/meloda/fast/auth/login/presentation/LoginScreen.kt index df3725ca..7015ece5 100644 --- a/feature/auth/src/main/kotlin/dev/meloda/fast/auth/login/presentation/LoginScreen.kt +++ b/feature/auth/src/main/kotlin/dev/meloda/fast/auth/login/presentation/LoginScreen.kt @@ -31,9 +31,13 @@ import androidx.compose.material3.ScaffoldDefaults import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TextField +import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.autofill.ContentType @@ -58,7 +62,6 @@ import androidx.compose.ui.unit.dp import androidx.core.net.toUri import androidx.lifecycle.compose.collectAsStateWithLifecycle import dev.meloda.fast.auth.login.LoginViewModel -import dev.meloda.fast.auth.login.model.CaptchaArguments import dev.meloda.fast.auth.login.model.LoginDialog import dev.meloda.fast.auth.login.model.LoginScreenState import dev.meloda.fast.auth.login.model.LoginUserBannedArguments @@ -67,6 +70,8 @@ import dev.meloda.fast.ui.R import dev.meloda.fast.ui.common.LocalSizeConfig import dev.meloda.fast.ui.components.MaterialDialog import dev.meloda.fast.ui.components.TextFieldErrorText +import dev.meloda.fast.ui.theme.AppTheme +import dev.meloda.fast.ui.theme.ClassicColorScheme import dev.meloda.fast.ui.util.handleEnterKey import dev.meloda.fast.ui.util.handleTabKey import org.koin.androidx.compose.koinViewModel @@ -114,17 +119,27 @@ fun LoginRoute( viewModel.onValidationCodeReceived(validationCode) } - LoginScreen( - screenState = screenState, - onLoginInputChanged = viewModel::onLoginInputChanged, - onPasswordInputChanged = viewModel::onPasswordInputChanged, - onPasswordFieldEnterKeyClicked = viewModel::onSignInButtonClicked, - onPasswordVisibilityButtonClicked = viewModel::onPasswordVisibilityButtonClicked, - onPasswordFieldGoAction = viewModel::onSignInButtonClicked, - onSignInButtonClicked = viewModel::onSignInButtonClicked, - onLogoClicked = viewModel::onLogoClicked, - onLogoLongClicked = onNavigateToSettings - ) + var useClassic by rememberSaveable { mutableStateOf(true) } + + AppTheme( + predefinedColorScheme = if (useClassic) ClassicColorScheme.lightScheme + else lightColorScheme(), + ) { + LoginScreen( + screenState = screenState, + onLoginInputChanged = viewModel::onLoginInputChanged, + onPasswordInputChanged = viewModel::onPasswordInputChanged, + onPasswordFieldEnterKeyClicked = viewModel::onSignInButtonClicked, + onPasswordVisibilityButtonClicked = viewModel::onPasswordVisibilityButtonClicked, + onPasswordFieldGoAction = viewModel::onSignInButtonClicked, + onSignInButtonClicked = viewModel::onSignInButtonClicked, + onLogoClicked = { + viewModel.onLogoClicked() + useClassic = !useClassic + }, + onLogoLongClicked = onNavigateToSettings + ) + } HandleDialogs( loginDialog = loginDialog, diff --git a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Attachments.kt b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Attachments.kt index cdc47fef..0c321768 100644 --- a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Attachments.kt +++ b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Attachments.kt @@ -119,12 +119,15 @@ fun Attachments( AttachmentType.STICKER -> { Sticker( - item = attachment as VkStickerDomain + url = (attachment as VkStickerDomain).getUrl( + width = 256, + withBackground = false + ) ) } AttachmentType.GIFT -> { - Gift(item = attachment as VkGiftDomain) + Gift(url = (attachment as VkGiftDomain).getDefaultThumbSizeOrLess()) } AttachmentType.VIDEO_MESSAGE -> { diff --git a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Gift.kt b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Gift.kt index a1d1819d..9508dc01 100644 --- a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Gift.kt +++ b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Gift.kt @@ -21,25 +21,24 @@ import androidx.compose.ui.res.vectorResource import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import coil.compose.AsyncImage -import dev.meloda.fast.model.api.domain.VkGiftDomain import dev.meloda.fast.ui.R @Composable fun Gift( modifier: Modifier = Modifier, - item: VkGiftDomain + url: String ) { Column( - modifier = modifier.width(192.dp), + modifier = modifier + .width(208.dp) + .padding(8.dp), verticalArrangement = Arrangement.spacedBy(4.dp) ) { AsyncImage( - model = item.getDefaultThumbSizeOrLess(), + model = url, contentDescription = null, contentScale = ContentScale.Crop, - modifier = Modifier - .padding(8.dp) - .fillMaxWidth() + modifier = Modifier.size(192.dp) ) Row( diff --git a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Sticker.kt b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Sticker.kt index ed091d52..e69a2d07 100644 --- a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Sticker.kt +++ b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Sticker.kt @@ -10,27 +10,23 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.unit.dp import coil.compose.AsyncImage -import dev.meloda.fast.model.api.domain.VkStickerDomain @Composable fun Sticker( modifier: Modifier = Modifier, - item: VkStickerDomain + url: String? ) { Box( - modifier = modifier.size(192.dp), + modifier = modifier + .size(208.dp) + .padding(8.dp), contentAlignment = Alignment.Center ) { AsyncImage( - model = item.getUrl( - width = 256, - withBackground = false - ), + model = url, contentDescription = null, contentScale = ContentScale.Crop, - modifier = Modifier - .padding(8.dp) - .fillMaxSize() + modifier = Modifier.fillMaxSize() ) } }