Merge branch 'develop' into feature/fga/live_location_sharing_setup

This commit is contained in:
ganfra 2026-03-24 10:17:24 +01:00
commit 9a984e1423
632 changed files with 4530 additions and 3107 deletions

View file

@ -706,14 +706,14 @@ class MessageComposerPresenter(
val draft = createDraftFromState(markdownTextEditorState, richTextEditorState)
updateDraft(draft, isVolatile = true).join()
}
setText(newComposerMode.content, markdownTextEditorState, richTextEditorState)
setText(newComposerMode.content, markdownTextEditorState, richTextEditorState, requestFocus = true)
}
is MessageComposerMode.EditCaption -> {
if (currentComposerMode.isEditing.not()) {
val draft = createDraftFromState(markdownTextEditorState, richTextEditorState)
updateDraft(draft, isVolatile = true).join()
}
setText(newComposerMode.content, markdownTextEditorState, richTextEditorState)
setText(newComposerMode.content, markdownTextEditorState, richTextEditorState, requestFocus = true)
}
else -> {
// When coming from edit, just clear the composer as it'd be weird to reset a volatile draft in this scenario.

View file

@ -43,6 +43,9 @@ import io.element.android.features.messages.impl.timeline.TimelinePresenter
import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPresenterFactories
import io.element.android.features.messages.impl.timeline.di.TimelineItemPresenterFactories
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.roommembermoderation.api.ModerationAction
import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents
import io.element.android.features.roommembermoderation.api.RoomMemberModerationRenderer
import io.element.android.libraries.androidutils.browser.openUrlInChromeCustomTab
import io.element.android.libraries.androidutils.system.openUrlInExternalApp
import io.element.android.libraries.architecture.NodeInputs
@ -86,6 +89,7 @@ class ThreadedMessagesNode(
private val mediaPlayer: MediaPlayer,
private val permalinkParser: PermalinkParser,
private val appNavigationStateService: AppNavigationStateService,
private val roomMemberModerationRenderer: RoomMemberModerationRenderer,
) : Node(buildContext, plugins = plugins), MessagesNavigator {
data class Inputs(
val threadRootEventId: ThreadId,
@ -289,6 +293,17 @@ class ThreadedMessagesNode(
knockRequestsBannerView = {},
)
roomMemberModerationRenderer.Render(
state = state.roomMemberModerationState,
onSelectAction = { action, target ->
when (action) {
is ModerationAction.DisplayProfile -> callback.navigateToRoomMemberDetails(target.userId)
else -> state.roomMemberModerationState.eventSink(RoomMemberModerationEvents.ProcessAction(action, target))
}
},
modifier = Modifier,
)
var focusedEventId by rememberSaveable {
mutableStateOf(inputs.focusedEventId)
}

View file

@ -22,14 +22,12 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.draw.drawWithCache
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.CompositingStrategy
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.graphics.layer.CompositingStrategy
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
@ -49,6 +47,7 @@ import io.element.android.libraries.designsystem.theme.messageFromMeBackground
import io.element.android.libraries.designsystem.theme.messageFromOtherBackground
import io.element.android.libraries.testtags.TestTags
import io.element.android.libraries.testtags.testTag
import io.element.android.libraries.ui.utils.graphics.drawInLayer
import io.element.android.libraries.ui.utils.time.isTalkbackActive
private val BUBBLE_RADIUS = 12.dp
@ -78,32 +77,45 @@ fun MessageEventBubble(
.onKeyboardContextMenuAction(onLongClick)
}
val cutTopStart = state.cutTopStart
// Ignore state.isHighlighted for now, we need a design decision on it.
val backgroundBubbleColor = MessageEventBubbleDefaults.backgroundBubbleColor(state.isMine)
val bubbleShape = remember(state) { MessageEventBubbleDefaults.shape(state.cutTopStart, state.groupPosition, state.isMine) }
val radiusPx = (avatarRadius + SENDER_AVATAR_BORDER_WIDTH).toPx()
val yOffsetPx = -(NEGATIVE_MARGIN_FOR_BUBBLE + avatarRadius).toPx()
val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl
BoxWithConstraints(
modifier = modifier
.graphicsLayer {
shape = bubbleShape
clip = true
compositingStrategy = CompositingStrategy.Offscreen
}
.drawWithContent {
drawRect(backgroundBubbleColor)
drawContent()
if (state.cutTopStart) {
drawCircle(
color = Color.Black,
center = Offset(
x = if (isRtl) size.width else 0f,
y = yOffsetPx,
),
radius = radiusPx,
blendMode = BlendMode.Clear,
)
.drawWithCache {
// Calculate the outline of the background and cache it
val outline = bubbleShape.createOutline(size, layoutDirection, this)
onDrawWithContent {
// Draw the contents in a layer to be able to clip them with the same outline
// For some reason, doing this clipping outside a layer messes up with the touch events
drawInLayer(
composingStrategy = CompositingStrategy.Offscreen,
outline = outline,
clip = true,
) {
// Draw the background first, so that it's behind the content
drawRect(backgroundBubbleColor)
// Then draw the content on top of it
drawContent()
// And then clip the top start corner if needed to make room for the avatar
if (cutTopStart) {
drawCircle(
color = Color.Black,
center = Offset(
x = if (layoutDirection == LayoutDirection.Rtl) size.width else 0f,
y = yOffsetPx,
),
radius = radiusPx,
blendMode = BlendMode.Clear,
)
}
}
}
},
// Need to set the contentAlignment again (it's already set in TimelineItemEventRow), for the case

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2026 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.messages.impl.timeline.components.event
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.messageFromMeBackground
@Composable
internal fun ElementTimelineItemPreview(
content: @Composable BoxScope.() -> Unit,
) = ElementPreview {
Box(
modifier = Modifier
.background(ElementTheme.colors.messageFromMeBackground)
.padding(4.dp),
content = content,
)
}

View file

@ -9,18 +9,16 @@
package io.element.android.features.messages.impl.timeline.components.event
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
@ -73,17 +71,17 @@ private fun TimelineItemAttachmentHeaderView(
val spacing = 8.dp
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(spacing),
) {
Box(
modifier = Modifier
.size(iconSize)
.clip(CircleShape)
.background(ElementTheme.colors.bgCanvasDefault),
.background(ElementTheme.colors.bgCanvasDefault, RoundedCornerShape(4.dp)),
contentAlignment = Alignment.Center,
) {
icon()
}
Spacer(Modifier.width(spacing))
Column {
Text(
text = filename,

View file

@ -18,7 +18,6 @@ import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayoutData
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContentProvider
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Icon
@ -49,7 +48,7 @@ fun TimelineItemAudioView(
@PreviewsDayNight
@Composable
internal fun TimelineItemAudioViewPreview(@PreviewParameter(TimelineItemAudioContentProvider::class) content: TimelineItemAudioContent) =
ElementPreview {
ElementTimelineItemPreview {
TimelineItemAudioView(
content,
onContentLayoutChange = {},

View file

@ -11,20 +11,21 @@ package io.element.android.features.messages.impl.timeline.components.event
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayoutData
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContentProvider
import io.element.android.libraries.designsystem.icons.CompoundDrawables
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.ui.strings.CommonStrings
/**
* https://www.figma.com/design/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?node-id=2019-6477&t=2yr7kvVEdtsP4p26-4
*/
@Composable
fun TimelineItemFileView(
content: TimelineItemFileContent,
@ -39,12 +40,11 @@ fun TimelineItemFileView(
modifier = modifier,
icon = {
Icon(
resourceId = CompoundDrawables.ic_compound_attachment,
imageVector = CompoundIcons.Attachment(),
contentDescription = stringResource(CommonStrings.common_file),
tint = ElementTheme.colors.iconPrimary,
modifier = Modifier
.size(16.dp)
.rotate(-45f),
.size(16.dp),
)
}
)
@ -52,9 +52,11 @@ fun TimelineItemFileView(
@PreviewsDayNight
@Composable
internal fun TimelineItemFileViewPreview(@PreviewParameter(TimelineItemFileContentProvider::class) content: TimelineItemFileContent) = ElementPreview {
TimelineItemFileView(
content,
onContentLayoutChange = {},
)
internal fun TimelineItemFileViewPreview(@PreviewParameter(TimelineItemFileContentProvider::class) content: TimelineItemFileContent) {
ElementTimelineItemPreview {
TimelineItemFileView(
content,
onContentLayoutChange = {},
)
}
}

View file

@ -35,7 +35,7 @@
<string name="screen_room_attachment_source_camera_video">"Natočit video"</string>
<string name="screen_room_attachment_source_files">"Příloha"</string>
<string name="screen_room_attachment_source_gallery">"Knihovna fotografií a videí"</string>
<string name="screen_room_attachment_source_location">"Poloha"</string>
<string name="screen_room_attachment_source_location">"Sdílejte polohu"</string>
<string name="screen_room_attachment_source_poll">"Hlasování"</string>
<string name="screen_room_attachment_text_formatting">"Formátování textu"</string>
<string name="screen_room_encrypted_history_banner">"Historie zpráv je momentálně v této místnosti nedostupná"</string>

View file

@ -35,7 +35,7 @@
<string name="screen_room_attachment_source_camera_video">"Optag video"</string>
<string name="screen_room_attachment_source_files">"Vedhæftning"</string>
<string name="screen_room_attachment_source_gallery">"Foto- og videobibliotek"</string>
<string name="screen_room_attachment_source_location">"Lokation"</string>
<string name="screen_room_attachment_source_location">"Del lokation"</string>
<string name="screen_room_attachment_source_poll">"Afstemning"</string>
<string name="screen_room_attachment_text_formatting">"Tekstformatering"</string>
<string name="screen_room_encrypted_history_banner">"Beskedhistorikken er i øjeblikket ikke tilgængelig."</string>

View file

@ -35,7 +35,7 @@
<string name="screen_room_attachment_source_camera_video">"Εγγραφή βίντεο"</string>
<string name="screen_room_attachment_source_files">"Επισύναψη"</string>
<string name="screen_room_attachment_source_gallery">"Βιβλιοθήκη Φωτογραφιών &amp; Βίντεο"</string>
<string name="screen_room_attachment_source_location">"Τοποθεσία"</string>
<string name="screen_room_attachment_source_location">"Κοινή χρήση τοποθεσίας"</string>
<string name="screen_room_attachment_source_poll">"Δημοσκόπηση"</string>
<string name="screen_room_attachment_text_formatting">"Μορφοποίηση Κειμένου"</string>
<string name="screen_room_encrypted_history_banner">"Το ιστορικό μηνυμάτων δεν είναι διαθέσιμο προς το παρόν."</string>

View file

@ -35,7 +35,7 @@
<string name="screen_room_attachment_source_camera_video">"Nauhoita video"</string>
<string name="screen_room_attachment_source_files">"Liite"</string>
<string name="screen_room_attachment_source_gallery">"Kuva- ja videokirjasto"</string>
<string name="screen_room_attachment_source_location">"Sijainti"</string>
<string name="screen_room_attachment_source_location">"Jaa sijainti"</string>
<string name="screen_room_attachment_source_poll">"Kysely"</string>
<string name="screen_room_attachment_text_formatting">"Tekstin muotoilu"</string>
<string name="screen_room_encrypted_history_banner">"Viestihistoria ei ole tällä hetkellä saatavilla"</string>

View file

@ -35,7 +35,7 @@
<string name="screen_room_attachment_source_camera_video">"Enregistrer une vidéo"</string>
<string name="screen_room_attachment_source_files">"Pièce jointe"</string>
<string name="screen_room_attachment_source_gallery">"Galerie Photo et Vidéo"</string>
<string name="screen_room_attachment_source_location">"Position"</string>
<string name="screen_room_attachment_source_location">"Partager votre position"</string>
<string name="screen_room_attachment_source_poll">"Sondage"</string>
<string name="screen_room_attachment_text_formatting">"Formatage du texte"</string>
<string name="screen_room_encrypted_history_banner">"Lhistorique des messages nest actuellement pas disponible dans ce salon"</string>

View file

@ -35,7 +35,7 @@
<string name="screen_room_attachment_source_camera_video">"Videó rögzítése"</string>
<string name="screen_room_attachment_source_files">"Melléklet"</string>
<string name="screen_room_attachment_source_gallery">"Fénykép- és videótár"</string>
<string name="screen_room_attachment_source_location">"Hely"</string>
<string name="screen_room_attachment_source_location">"Hely megosztása"</string>
<string name="screen_room_attachment_source_poll">"Szavazás"</string>
<string name="screen_room_attachment_text_formatting">"Szövegformázás"</string>
<string name="screen_room_encrypted_history_banner">"Az üzenetelőzmények jelenleg nem érhetők el."</string>

View file

@ -14,10 +14,17 @@
<string name="emoji_picker_category_objects">"Objek"</string>
<string name="emoji_picker_category_people">"Senyuman &amp; Orang"</string>
<string name="emoji_picker_category_places">"Wisata &amp; Tempat"</string>
<string name="emoji_picker_category_recent">"Emojis Sebelumnya"</string>
<string name="emoji_picker_category_symbols">"Simbol"</string>
<string name="screen_media_upload_preview_caption_warning">"Keterangan mungkin tidak terlihat oleh orang yang menggunakan aplikasi lama."</string>
<string name="screen_media_upload_preview_change_video_quality_prompt">"Ketuk untuk mengubah kualitas unggahan video"</string>
<string name="screen_media_upload_preview_error_could_not_be_uploaded">"Dokumen tidak dapat diunggah."</string>
<string name="screen_media_upload_preview_error_failed_processing">"Gagal memproses media untuk diunggah, silakan coba lagi."</string>
<string name="screen_media_upload_preview_error_failed_sending">"Gagal mengunggah media, silakan coba lagi."</string>
<string name="screen_media_upload_preview_error_too_large_message">"Ukuran file maksimum yang diizinkan adalah%1$s ."</string>
<string name="screen_media_upload_preview_error_too_large_title">"Ukuran file terlalu besar untuk diunggah."</string>
<string name="screen_media_upload_preview_optimize_image_quality_title">"Optimalkan kualitas gambar"</string>
<string name="screen_media_upload_preview_processing">"Memproses…"</string>
<string name="screen_report_content_block_user">"Blokir pengguna"</string>
<string name="screen_report_content_block_user_hint">"Centang jika Anda ingin menyembunyikan semua pesan saat ini dan yang akan datang dari pengguna ini"</string>
<string name="screen_report_content_explanation">"Pesan ini akan dilaporkan ke administrator homeserver Anda. Mereka tidak akan dapat membaca pesan terenkripsi apa pun."</string>

View file

@ -14,6 +14,7 @@
<string name="emoji_picker_category_objects">"사물"</string>
<string name="emoji_picker_category_people">"표정 &amp; 사람"</string>
<string name="emoji_picker_category_places">"여행 &amp; 장소"</string>
<string name="emoji_picker_category_recent">"최근 이모지"</string>
<string name="emoji_picker_category_symbols">"상징"</string>
<string name="screen_media_upload_preview_caption_warning">"캡션은 오래된 앱을 사용하는 사용자에게 표시되지 않을 수 있습니다."</string>
<string name="screen_media_upload_preview_change_video_quality_prompt">"비디오 업로드 품질을 변경하려면 탭하세요"</string>
@ -22,6 +23,7 @@
<string name="screen_media_upload_preview_error_failed_sending">"미디어 파일 업로드에 실패했습니다. 다시 시도해 주세요."</string>
<string name="screen_media_upload_preview_error_too_large_message">"허용되는 최대 파일 크기는 %1$s 입니다."</string>
<string name="screen_media_upload_preview_error_too_large_title">"파일 크기가 너무 커서 업로드할 수 없습니다."</string>
<string name="screen_media_upload_preview_item_count">"전체 %2$d개 중 %1$d번째 파일"</string>
<string name="screen_media_upload_preview_optimize_image_quality_title">"이미지 품질 최적화"</string>
<string name="screen_media_upload_preview_processing">"처리 중…"</string>
<string name="screen_report_content_block_user">"사용자 차단하기"</string>
@ -33,7 +35,7 @@
<string name="screen_room_attachment_source_camera_video">"동영상 녹화"</string>
<string name="screen_room_attachment_source_files">"첨부 파일"</string>
<string name="screen_room_attachment_source_gallery">"사진 &amp; 동영상 라이브러리"</string>
<string name="screen_room_attachment_source_location">"위치"</string>
<string name="screen_room_attachment_source_location">"위치 공유"</string>
<string name="screen_room_attachment_source_poll">"투표"</string>
<string name="screen_room_attachment_text_formatting">"텍스트 서식"</string>
<string name="screen_room_encrypted_history_banner">"메시지 기록은 현재 사용할 수 없습니다."</string>

View file

@ -19,13 +19,20 @@
<string name="screen_room_attachment_source_camera_video">"Įrašyti vaizdo įrašą"</string>
<string name="screen_room_attachment_source_files">"Priedas"</string>
<string name="screen_room_attachment_source_gallery">"Nuotraukų ir vaizdo įrašų biblioteka"</string>
<string name="screen_room_attachment_source_location">"Bendrinti vietą"</string>
<string name="screen_room_encrypted_history_banner">"Šiuo metu žinučių istorija nepasiekiama."</string>
<string name="screen_room_invite_again_alert_message">"Ar norėtumėte juos pakviesti atgal?"</string>
<string name="screen_room_invite_again_alert_title">"Šiame pokalbyje esate vieni."</string>
<string name="screen_room_retry_send_menu_send_again_action">"Siųsti vėl"</string>
<string name="screen_room_retry_send_menu_title">"Jūsų žinutė nepavyko išsiųsti."</string>
<string name="screen_room_timeline_add_reaction">"Pridėti reakciją"</string>
<string name="screen_room_timeline_beginning_of_room">"Tai yra %1$s pradžia."</string>
<string name="screen_room_timeline_beginning_of_room_no_name">"Tai yra šio pokalbio pradžia."</string>
<string name="screen_room_timeline_less_reactions">"Rodyti mažiau"</string>
<string name="screen_room_timeline_message_copied">"Žinutė nukopijuota"</string>
<string name="screen_room_timeline_no_permission_to_post">"Neturite leidimą skelbti šiame kambaryje."</string>
<string name="screen_room_timeline_reactions_show_less">"Rodyti mažiau"</string>
<string name="screen_room_timeline_reactions_show_more">"Rodyti daugiau"</string>
<string name="screen_room_timeline_read_marker_title">"Naujų"</string>
<plurals name="screen_room_timeline_state_changes">
<item quantity="one">"%1$d kambario pakeitimas"</item>

View file

@ -35,7 +35,7 @@
<string name="screen_room_attachment_source_camera_video">"Ta opp video"</string>
<string name="screen_room_attachment_source_files">"Vedlegg"</string>
<string name="screen_room_attachment_source_gallery">"Foto- og videobibliotek"</string>
<string name="screen_room_attachment_source_location">"Posisjon"</string>
<string name="screen_room_attachment_source_location">"Del posisjon"</string>
<string name="screen_room_attachment_source_poll">"Avstemning"</string>
<string name="screen_room_attachment_text_formatting">"Tekstformatering"</string>
<string name="screen_room_encrypted_history_banner">"Meldingshistorikken er for øyeblikket ikke tilgjengelig."</string>

View file

@ -7,12 +7,12 @@
<string name="crypto_event_authenticity_unknown_device">"Зашифровано неизвестным или удаленным устройством."</string>
<string name="crypto_event_authenticity_unsigned_device">"Зашифровано устройством, не проверенным его владельцем."</string>
<string name="crypto_event_authenticity_unverified_identity">"Зашифровано непроверенным пользователем."</string>
<string name="emoji_picker_category_activity">"Деятельность"</string>
<string name="emoji_picker_category_activity">"Активности"</string>
<string name="emoji_picker_category_flags">"Флаги"</string>
<string name="emoji_picker_category_foods">"Еда и напитки"</string>
<string name="emoji_picker_category_nature">"Животные и природа"</string>
<string name="emoji_picker_category_objects">"Объекты"</string>
<string name="emoji_picker_category_people">"Улыбки и люди"</string>
<string name="emoji_picker_category_people">"Эмодзи и люди"</string>
<string name="emoji_picker_category_places">"Путешествия и места"</string>
<string name="emoji_picker_category_recent">"Недавние эмодзи"</string>
<string name="emoji_picker_category_symbols">"Символы"</string>
@ -23,19 +23,19 @@
<string name="screen_media_upload_preview_error_failed_sending">"Не удалось загрузить медиафайлы, попробуйте еще раз."</string>
<string name="screen_media_upload_preview_error_too_large_message">"Максимальный размер файла: %1$s."</string>
<string name="screen_media_upload_preview_error_too_large_title">"Файл слишком большой для загрузки."</string>
<string name="screen_media_upload_preview_item_count">"Элемент %1$d из %2$d"</string>
<string name="screen_media_upload_preview_item_count">"%1$d из %2$d"</string>
<string name="screen_media_upload_preview_optimize_image_quality_title">"Оптимизировать качество изображения"</string>
<string name="screen_media_upload_preview_processing">"Обработка…"</string>
<string name="screen_report_content_block_user">"Заблокировать пользователя"</string>
<string name="screen_report_content_block_user_hint">"Отметьте, хотите ли вы скрыть все текущие и будущие сообщения от этого пользователя"</string>
<string name="screen_report_content_explanation">"Это сообщение будет передано администратору вашего домашнего сервера. Они не смогут прочитать зашифрованные сообщения."</string>
<string name="screen_report_content_hint">"Причина, по которой вы пожаловались на этот контент"</string>
<string name="screen_report_content_hint">"Причина жалобы"</string>
<string name="screen_room_attachment_source_camera">"Камера"</string>
<string name="screen_room_attachment_source_camera_photo">"Сделать фото"</string>
<string name="screen_room_attachment_source_camera_video">"Записать видео"</string>
<string name="screen_room_attachment_source_files">"Вложение"</string>
<string name="screen_room_attachment_source_gallery">"Фото и видео"</string>
<string name="screen_room_attachment_source_location">"Местоположение"</string>
<string name="screen_room_attachment_source_location">"Поделиться местоположением"</string>
<string name="screen_room_attachment_source_poll">"Опрос"</string>
<string name="screen_room_attachment_text_formatting">"Форматирование текста"</string>
<string name="screen_room_encrypted_history_banner">"В настоящее время история сообщений недоступна в этой комнате."</string>
@ -46,13 +46,13 @@
<string name="screen_room_mentions_at_room_title">"Все"</string>
<string name="screen_room_retry_send_menu_send_again_action">"Отправить снова"</string>
<string name="screen_room_retry_send_menu_title">"Не удалось отправить ваше сообщение"</string>
<string name="screen_room_timeline_add_reaction">"Добавить эмодзи"</string>
<string name="screen_room_timeline_add_reaction">"Добавить реакцию"</string>
<string name="screen_room_timeline_beginning_of_room">"Это начало %1$s."</string>
<string name="screen_room_timeline_beginning_of_room_no_name">"Это начало разговора."</string>
<string name="screen_room_timeline_legacy_call">"Неподдерживаемый вызов. уточните, может ли звонящий использовать новое приложение Element X."</string>
<string name="screen_room_timeline_beginning_of_room_no_name">"Это начало беседы."</string>
<string name="screen_room_timeline_legacy_call">"Звонок не поддерживается. Собеседник должен использовать новое приложение Element X."</string>
<string name="screen_room_timeline_less_reactions">"Показать меньше"</string>
<string name="screen_room_timeline_message_copied">"Сообщение скопировано"</string>
<string name="screen_room_timeline_no_permission_to_post">"У вас нет разрешения публиковать сообщения в этой комнате"</string>
<string name="screen_room_timeline_no_permission_to_post">"Вы не можете писать сообщения в этой комнате"</string>
<plurals name="screen_room_timeline_reaction_a11y">
<item quantity="one">"%1$d участник отреагировал %2$s"</item>
<item quantity="few">"%1$d участника отреагировало %2$s"</item>
@ -63,11 +63,11 @@
<item quantity="few">"Вы и %1$d участника отреагировали %2$s"</item>
<item quantity="many">"Вы и %1$d участников отреагировали %2$s"</item>
</plurals>
<string name="screen_room_timeline_reaction_you_a11y">"Вы отреагировали %1$s"</string>
<string name="screen_room_timeline_reaction_you_a11y">"Вы отреагировали: %1$s"</string>
<string name="screen_room_timeline_reactions_show_less">"Показать меньше"</string>
<string name="screen_room_timeline_reactions_show_more">"Показать больше"</string>
<string name="screen_room_timeline_reactions_show_reactions_summary">"Показать сводку реакций"</string>
<string name="screen_room_timeline_read_marker_title">"Новый"</string>
<string name="screen_room_timeline_read_marker_title">"Новое"</string>
<plurals name="screen_room_timeline_state_changes">
<item quantity="one">"%1$d изменение в комнате"</item>
<item quantity="few">"%1$d изменения в комнате"</item>
@ -75,7 +75,7 @@
</plurals>
<string name="screen_room_timeline_tombstoned_room_action">"Перейти в новую комнату"</string>
<string name="screen_room_timeline_tombstoned_room_message">"Эта комната была заменена и больше не активна"</string>
<string name="screen_room_timeline_upgraded_room_action">"Посмотреть старые сообщения"</string>
<string name="screen_room_timeline_upgraded_room_action">росмотреть старые сообщения"</string>
<string name="screen_room_timeline_upgraded_room_message">"Эта комната является продолжением другой комнаты"</string>
<plurals name="screen_room_typing_many_members">
<item quantity="one">"%1$s, %2$s и %3$d"</item>
@ -83,9 +83,9 @@
<item quantity="many">"%1$s, %2$s и другие %3$d"</item>
</plurals>
<plurals name="screen_room_typing_notification">
<item quantity="one">"%1$s набирает сообщение"</item>
<item quantity="few">"%1$s набирают сообщения"</item>
<item quantity="many">"%1$s набирают сообщения"</item>
<item quantity="one">"%1$s печатает"</item>
<item quantity="few">"%1$s печатают"</item>
<item quantity="many">"%1$s печатают"</item>
</plurals>
<string name="screen_room_typing_two_members">"%1$s и %2$s"</string>
</resources>

View file

@ -14,6 +14,7 @@
<string name="emoji_picker_category_objects">"Об\'єкти"</string>
<string name="emoji_picker_category_people">"Смайлики та люди"</string>
<string name="emoji_picker_category_places">"Подорожі та місця"</string>
<string name="emoji_picker_category_recent">"Нещодавні емодзі"</string>
<string name="emoji_picker_category_symbols">"Символи"</string>
<string name="screen_media_upload_preview_caption_warning">"Користувачі старих застосунків можуть не бачити підписи."</string>
<string name="screen_media_upload_preview_change_video_quality_prompt">"Натисніть, щоб змінити якість вивантажуваного відео"</string>
@ -22,6 +23,7 @@
<string name="screen_media_upload_preview_error_failed_sending">"Не вдалося завантажити медіафайл, спробуйте ще раз."</string>
<string name="screen_media_upload_preview_error_too_large_message">"Максимально дозволений розмір файлу — %1$s."</string>
<string name="screen_media_upload_preview_error_too_large_title">"Файл завеликий для вивантаження"</string>
<string name="screen_media_upload_preview_item_count">"Елемент %1$d з %2$d"</string>
<string name="screen_media_upload_preview_optimize_image_quality_title">"Оптимізувати якість зображення"</string>
<string name="screen_media_upload_preview_processing">"Обробка…"</string>
<string name="screen_report_content_block_user">"Заблокувати користувача"</string>