feat: add channel message support and refactor UI components

- Implement `VkChannelMessage` domain and data models for channel message attachments
- Add `CHANNEL_MESSAGE` to `AttachmentType` and map it to relevant UI resources and strings
- Refactor `Sticker` and `Gift` composables to accept URL strings instead of domain objects for better decoupling
- Simplify `AppTheme` by removing redundant color animations and passing the color scheme directly to `MaterialExpressiveTheme`
- Update `LoginScreen` to include a theme toggle (classic vs. light) and improve back-button behavior by resetting error states
- Bump VK API version from 5.238 to 5.263
- Adjust layout and padding for sticker and gift attachment previews
This commit is contained in:
2026-05-19 22:54:44 +03:00
parent b31c0f30c5
commit 574b230b26
13 changed files with 125 additions and 46 deletions
@@ -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() {
@@ -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,
@@ -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 -> {
@@ -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(
@@ -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()
)
}
}