Закрыты задачи бэклога по неочевидному поведению UI при ошибках отправки сообщений и блокировках со стороны Message-safety + добалено ограничение на размер сообщения

This commit is contained in:
mi
2026-07-29 16:45:19 +03:00
parent 41e19005fb
commit bda3ff39d7
36 changed files with 486 additions and 141 deletions
@@ -1,6 +1,7 @@
import { Feather } from "@expo/vector-icons";
import React, { useState } from "react";
import { Pressable, StyleSheet, Text, TextInput, View } from "react-native";
import { messageFitsLimit } from "../message-text";
import { colors, radii, spacing } from "../theme";
type Props = {
@@ -13,6 +14,7 @@ type Props = {
placeholder?: string;
hint?: string;
inputLabel?: string;
maxLength?: number;
};
export function ChatInputBar({
@@ -25,9 +27,12 @@ export function ChatInputBar({
placeholder = "Напишите ваш вопрос...",
hint = "Напишите сообщение или прикрепите документ",
inputLabel = "Сообщение",
maxLength,
}: Props) {
const [focused, setFocused] = useState(false);
const canSend = Boolean(value.trim()) && !disabled && !sending;
const withinLimit = maxLength === undefined || messageFitsLimit(value, maxLength);
const canSend = Boolean(value.trim()) && withinLimit && !disabled && !sending;
const nearLimit = maxLength !== undefined && value.length >= maxLength * 0.9;
return (
<View style={styles.wrapper}>
@@ -78,6 +83,18 @@ export function ChatInputBar({
</Pressable>
</View>
</View>
{maxLength !== undefined ? (
<Text
accessibilityLiveRegion={withinLimit ? "none" : "polite"}
style={[
styles.counter,
nearLimit && styles.counterWarning,
!withinLimit && styles.counterError,
]}
>
{value.length}/{maxLength}
</Text>
) : null}
{hint ? <Text style={styles.hint}>{hint}</Text> : null}
</View>
);
@@ -111,6 +128,9 @@ const styles = StyleSheet.create({
iconButton: { width: 36, height: 36, borderRadius: radii.full, alignItems: "center", justifyContent: "center" },
sendButton: { width: 36, height: 36, borderRadius: radii.full, backgroundColor: colors.primary, alignItems: "center", justifyContent: "center" },
sendButtonDisabled: { opacity: 0.4 },
counter: { fontSize: 12, color: colors.mutedForeground, textAlign: "right", marginTop: spacing.xs },
counterWarning: { color: colors.warning },
counterError: { color: colors.destructive },
hint: { fontSize: 12, color: colors.mutedForeground, textAlign: "center", marginTop: spacing.sm },
pressed: { opacity: 0.7 },
});