feat(app): redesigned interface, polls, drafts, forwarding and mentions
A new look across the app and a set of everyday messaging features. Interface - Home screen with Chats, Contacts and Settings tabs, a large title, search across chats and message text (diacritics-insensitive), filters and pinned chats. - Conversation view with a translucent header and composer, grouped bubbles, author avatars and colours in groups, swipe to reply, an "N new messages" marker, a jump-to-latest button and in-chat search. - Contact and group profiles: verification, shared photos, groups in common, disappearing messages, mute, block; members, admin badges, adding people, rename and leave for groups. - Full-screen photo viewer that pages through the whole conversation. - A stable avatar colour per person and a clearly visible read state. Messaging - Polls in chats and groups, single or multiple choice, with votes that can be changed or withdrawn; older clients see them as text. - Drafts survive leaving a chat and show in the chat list. - Forwarding of messages, photos, files and voice messages. - Notes to self: a local-only, encrypted chat that never reaches the relay. - @mentions in groups that notify even when the group is muted. - Typing indicators sent as ephemeral messages, opt-in and mutual like read receipts. - Delivery and read times per message and per group member. - Profile photos, cropped, resized and stripped of metadata, delivered encrypted to contacts. - Voice message playback at 1.5x and 2x. - Call buttons in 1:1 chats and call log entries. Fixes - Muted groups no longer notify: muting was checked against the author's chat instead of the group. - A blocked contact could unblock itself by changing its delivery address. - Read receipts no longer regress to delivered when a late delivery receipt arrives. - A message marked as failed corrects itself once it is delivered. - Double ticks in groups now mean delivered to every member.
This commit is contained in:
+128
-7
@@ -18,9 +18,23 @@
|
||||
"groupsRename": "Переименовать группу",
|
||||
"groupsLeave": "Покинуть группу",
|
||||
"groupsLeftBanner": "Вы больше не в группе. История сохранится, но новые сообщения приходить не будут.",
|
||||
"groupsMembersWithCount": "Участники ({count})",
|
||||
"groupsYou": "Вы",
|
||||
"groupsFounder": "Создатель",
|
||||
"groupsAdmin": "Администратор",
|
||||
"groupsMakeAdmin": "Сделать администратором",
|
||||
"groupsDismissAdmin": "Снять роль администратора",
|
||||
"groupsRemoveMember": "Удалить из группы",
|
||||
"groupsRemoveMemberConfirmTitle": "Удалить {name} из группы?",
|
||||
"groupsRemoveMemberConfirmBody": "Новые сообщения группы перестанут приходить. Прежняя история сохранится.",
|
||||
"groupsRemoveAction": "Удалить",
|
||||
"groupsViewContact": "Открыть контакт",
|
||||
"groupsAdminOnlyHint": "Название, участников и администраторов группы меняют только администраторы.",
|
||||
"groupsAdminOnlyCompatHint": "Переименовать группу и менять администраторов могут только администраторы. Добавлять людей пока может любой, потому что у кого-то в группе старая версия Šepot.",
|
||||
"groupsAdminActionFailed": "Не удалось внести изменение: {error}",
|
||||
"groupsResyncNotice": "Группа сверяется с администратором. Изменения состава могут появиться с задержкой.",
|
||||
"groupsRejectedChangeNotice": "Кто-то без прав попытался изменить группу. Изменение не применено.",
|
||||
"errorGroupNotAdmin": "Это может сделать только администратор группы.",
|
||||
"errorGroupLastAdmin": "Вы единственный администратор. Сначала назначьте администратором кого-то ещё.",
|
||||
"groupsNameHint": "Название группы",
|
||||
"commonCancel": "Отмена",
|
||||
"commonSave": "Сохранить",
|
||||
@@ -51,6 +65,12 @@
|
||||
"chatEditingMessage": "Редактирование сообщения",
|
||||
"chatReply": "Ответ",
|
||||
"chatActionReply": "Ответить",
|
||||
"chatActionForward": "Переслать",
|
||||
"forwardTitle": "Переслать в…",
|
||||
"forwardSearchHint": "Найти контакт или группу",
|
||||
"forwardEmpty": "Ничего не найдено",
|
||||
"forwardDone": "Переслано: {name}",
|
||||
"forwardFailed": "Не удалось переслать: {error}",
|
||||
"commonCopy": "Копировать",
|
||||
"commonEdit": "Изменить",
|
||||
"chatDeleteForMe": "Удалить у меня",
|
||||
@@ -68,6 +88,9 @@
|
||||
"attachmentTakePhoto": "Сделать фото",
|
||||
"attachmentDocument": "Документ",
|
||||
"attachmentTooLarge": "Файл слишком большой (макс. {maxMb} МБ)",
|
||||
"attachmentKeepsMetadataTitle": "Фото будет с геолокацией",
|
||||
"attachmentKeepsMetadataBody": "Из этого формата фото (например, HEIC) я не могу удалить метаданные. Оно будет отправлено в оригинале, включая место съёмки и данные о телефоне. Безопаснее отправить его через Галерею — там метаданные удаляются.",
|
||||
"attachmentSendOriginal": "Отправить оригинал",
|
||||
"attachmentPickFailed": "Не удалось выбрать вложение: {error}",
|
||||
"attachmentSendFailed": "Не удалось отправить вложение: {error}",
|
||||
"chatSendFailed": "Не удалось отправить: {error}",
|
||||
@@ -79,6 +102,7 @@
|
||||
"errorContactLinkIncomplete": "Ссылка неполная — собеседник создал её до подключения. Попросите у него новую ссылку sepot://.",
|
||||
"errorAttachmentTooLarge": "Вложение слишком большое (макс. {maxMb} МБ)",
|
||||
"errorGroupNeedsMember": "В группе должен быть хотя бы 1 участник",
|
||||
"errorAttachmentUnavailable": "Вложения больше нет на этом телефоне",
|
||||
"errorGroupMaxMembers": "Максимальное число участников группы — {maxMembers}",
|
||||
"errorMemberNoDeliveryAddress": "У контакта {displayName} нет адреса доставки — запросите новую ссылку",
|
||||
"errorContactNoDeliveryAddress": "У контакта нет адреса доставки — попросите у него новую ссылку sepot://",
|
||||
@@ -163,9 +187,36 @@
|
||||
"attachmentOpenFailed": "Не удалось открыть вложение: {error}",
|
||||
"commonFile": "Файл",
|
||||
"chatListNewConversation": "Новый чат",
|
||||
"chatListPhotoWithCaptionPreview": "📷 {caption}",
|
||||
"chatListFilePreview": "📎 {fileName}",
|
||||
"chatListReadReceiptPreview": "Прочитано",
|
||||
"chatListDraft": "Черновик",
|
||||
"notesTitle": "Заметки для себя",
|
||||
"notesSubtitle": "Только на этом телефоне, в зашифрованном виде",
|
||||
"callVoice": "Позвонить",
|
||||
"callVideo": "Видеозвонок",
|
||||
"callStatusRinging": "Вызов…",
|
||||
"callIncomingVoice": "Входящий звонок",
|
||||
"callIncomingVideo": "Входящий видеозвонок",
|
||||
"callStatusConnecting": "Соединение…",
|
||||
"callEnded": "Звонок завершён",
|
||||
"callEndedBusy": "Занято",
|
||||
"callEndedRejected": "Звонок отклонён",
|
||||
"callEndedUnanswered": "Нет ответа",
|
||||
"callEndedFailed": "Не удалось соединиться",
|
||||
"callEncrypted": "Сквозное шифрование",
|
||||
"callAccept": "Принять",
|
||||
"callReject": "Отклонить",
|
||||
"callMute": "Выключить микрофон",
|
||||
"callSpeaker": "Динамик",
|
||||
"callCamera": "Выключить камеру",
|
||||
"callSwitchCamera": "Сменить камеру",
|
||||
"callHangUp": "Завершить",
|
||||
"callLogMissed": "Пропущенный звонок",
|
||||
"callLogUnanswered": "Звонок без ответа",
|
||||
"callLogRejected": "Отклонённый звонок",
|
||||
"callLogBusy": "Занято",
|
||||
"callLogFailed": "Звонок не удался",
|
||||
"callLogVoice": "Звонок · {duration}",
|
||||
"callLogVideo": "Видеозвонок · {duration}",
|
||||
"chatListTimeNow": "сейчас",
|
||||
"chatListTimeMinutes": "{minutes} мин",
|
||||
"qrScanTitle": "Сканировать QR-код",
|
||||
@@ -266,9 +317,9 @@
|
||||
"pinUnlockError": "Ошибка разблокировки",
|
||||
"pushTitle": "Push-уведомления",
|
||||
"pushModeOffDesc": "Сообщения загрузятся только после открытия приложения.",
|
||||
"pushModeUp": "UnifiedPush (рекомендуется)",
|
||||
"pushModeUp": "UnifiedPush (без Google)",
|
||||
"pushModeUpDesc": "Без сервисов Google — требуется приложение ntfy (F-Droid/Play).",
|
||||
"pushModeFcm": "Google (FCM)",
|
||||
"pushModeFcm": "Google (FCM, по умолчанию)",
|
||||
"pushModeFcmDesc": "Надёжно и без дополнительных приложений. Push-токен устройства передаётся Google; содержимое сообщений — никогда.",
|
||||
"pushSetupFailed": "Не удалось настроить push: {error}",
|
||||
"pushHintOff": "Сообщения придут, только когда откроешь Šepot — сигналы не настроены.",
|
||||
@@ -280,7 +331,7 @@
|
||||
"pushPickDistributorTitle": "Выберите дистрибьютора",
|
||||
"pushSubtitleUnifiedPush": "UnifiedPush · {distributor}",
|
||||
"pushNoDistributorFallback": "без дистрибьютора",
|
||||
"pushSubtitleFcm": "Google (FCM) — быстро, только по вашему выбору",
|
||||
"pushSubtitleFcm": "Google (FCM)",
|
||||
"restoreErrorNameRequired": "Введите отображаемое имя.",
|
||||
"restoreErrorWordCount": "{wordCount, plural, one{Во фразе {wordCount} слово, а нужно {requiredWords}.} few{Во фразе {wordCount} слова, а нужно {requiredWords}.} many{Во фразе {wordCount} слов, а нужно {requiredWords}.} other{Во фразе {wordCount} слова, а нужно {requiredWords}.}}",
|
||||
"restoreErrorInvalidPhrase": "Фраза недействительна — проверьте слова и их порядок.",
|
||||
@@ -364,5 +415,75 @@
|
||||
"photoPreviewSend": "Отправить",
|
||||
"photoPreviewTextDialogTitle": "Текст на фото",
|
||||
"photoPreviewRemoveText": "Удалить",
|
||||
"photoPreviewDecodeFailed": "Не удалось загрузить фото"
|
||||
"photoPreviewDecodeFailed": "Не удалось загрузить фото",
|
||||
"chatActionInfo": "Сведения о сообщении",
|
||||
"messageInfoSent": "Отправлено",
|
||||
"messageInfoDelivered": "Доставлено",
|
||||
"messageInfoRead": "Прочитано",
|
||||
"messageInfoPending": "ещё нет",
|
||||
"messageInfoReadReceiptsOff": "Время прочтения видно, только если вы сами делитесь отчётами о прочтении (Настройки).",
|
||||
"chatStatusReadAt": "Прочитано {time}",
|
||||
"chatStatusDeliveredAt": "Доставлено {time}",
|
||||
"groupsAddMembers": "Добавить участников",
|
||||
"groupsAddMembersAction": "Добавить",
|
||||
"groupsAddMembersFailed": "Не удалось добавить: {error}",
|
||||
"groupsNoContactsToAdd": "Все ваши контакты уже в группе. Сначала добавьте нового человека в контакты по QR-коду.",
|
||||
"navChats": "Чаты",
|
||||
"chatListNewChat": "Новый чат",
|
||||
"chatListSearchHint": "Поиск по чатам и сообщениям",
|
||||
"chatFilterAll": "Все",
|
||||
"chatFilterUnread": "Непрочитанные",
|
||||
"chatFilterGroups": "Группы",
|
||||
"chatFilterArchive": "Архив",
|
||||
"chatListNoResults": "Ничего не найдено.",
|
||||
"chatListFilterEmpty": "Здесь пока ничего нет.",
|
||||
"chatListPin": "Закрепить",
|
||||
"chatListUnpin": "Открепить",
|
||||
"chatOpenProfile": "Открыть профиль",
|
||||
"groupsProfile": "Информация о группе",
|
||||
"chatSearchHint": "Поиск в чате",
|
||||
"chatSearchNoMatches": "Нет",
|
||||
"chatSearchCounter": "{current} из {total}",
|
||||
"chatSearchOlder": "Предыдущее совпадение",
|
||||
"chatSearchNewer": "Следующее совпадение",
|
||||
"chatUnreadDivider": "{count, plural, one{{count} новое сообщение} few{{count} новых сообщения} other{{count} новых сообщений}}",
|
||||
"chatJumpToLatest": "К последним сообщениям",
|
||||
"chatAttach": "Прикрепить",
|
||||
"chatSend": "Отправить",
|
||||
"chatRecordVoice": "Записать голосовое",
|
||||
"profileSharedMedia": "Общие медиа",
|
||||
"profileMessage": "Написать",
|
||||
"profileSearch": "Поиск",
|
||||
"profileUnmute": "Включить звук",
|
||||
"profileDisappearing": "Исчезание",
|
||||
"profileCommonGroups": "Общие группы",
|
||||
"profileSafetyNumber": "Код безопасности",
|
||||
"profileSafetyNumberHint": "Сравните лично или по QR-коду",
|
||||
"profileVerifiedInPerson": "Проверено лично",
|
||||
"profileVerifyNow": "Проверить контакт",
|
||||
"profileAdd": "Добавить",
|
||||
"profileGroupSubtitle": "Группа · {members} · создана {date}",
|
||||
"profileMembersOfMax": "{count} из {max}",
|
||||
"chatTyping": "печатает…",
|
||||
"chatTypingNamed": "{name} печатает…",
|
||||
"chatTypingSeveral": "Несколько человек печатают…",
|
||||
"settingsTypingTitle": "Индикатор набора",
|
||||
"settingsTypingSubtitle": "Взаимно — не делитесь, не видите (по умолчанию выкл.)",
|
||||
"pollAttach": "Опрос",
|
||||
"pollCreateTitle": "Новый опрос",
|
||||
"pollQuestion": "Вопрос",
|
||||
"pollOptionHint": "Вариант {number}",
|
||||
"pollAddOption": "Добавить вариант",
|
||||
"pollRemoveOption": "Удалить вариант",
|
||||
"pollAllowMultiple": "Разрешить несколько ответов",
|
||||
"pollSingle": "Опрос",
|
||||
"pollMulti": "Опрос, несколько ответов",
|
||||
"pollVoters": "{count, plural, =0{пока нет голосов} one{{count} голос} few{{count} голоса} other{{count} голосов}}",
|
||||
"pollFallback": "Опрос: {question}",
|
||||
"pollFallbackUpdate": "Обновите Šepot, чтобы голосовать.",
|
||||
"profilePhotoEdit": "Изменить фото профиля",
|
||||
"profilePhotoPick": "Выбрать фото",
|
||||
"profilePhotoRemove": "Удалить фото",
|
||||
"profilePhotoHint": "Фото увидят только ваши собеседники — зашифровано, как и сообщения. Геоданные и метаданные не отправляются.",
|
||||
"profilePhotoFailed": "Не удалось установить фото: {error}"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user