Merge branch 'develop' into feature/bma/dataObject

This commit is contained in:
Benoit Marty 2023-08-28 10:56:02 +02:00 committed by GitHub
commit 55255735d7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
129 changed files with 2140 additions and 487 deletions

View file

@ -16,6 +16,7 @@
package io.element.android.features.messages.impl.timeline.components
import android.annotation.SuppressLint
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@ -68,9 +69,11 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItemGrou
import io.element.android.features.messages.impl.timeline.model.bubble.BubbleState
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent
import io.element.android.libraries.designsystem.components.EqualWidthColumn
import io.element.android.libraries.designsystem.components.avatar.Avatar
@ -357,11 +360,15 @@ private fun MessageEventBubbleContent(
onMessageLongClick: () -> Unit,
inReplyToClick: () -> Unit,
onTimestampClicked: () -> Unit,
modifier: Modifier = Modifier
@SuppressLint("ModifierParameter") bubbleModifier: Modifier = Modifier, // need to rename this modifier to distinguish it from the following ones
) {
val isMediaItem = event.content is TimelineItemImageContent
|| event.content is TimelineItemVideoContent
|| event.content is TimelineItemLocationContent
val timestampPosition = when (event.content) {
is TimelineItemImageContent,
is TimelineItemVideoContent,
is TimelineItemLocationContent -> TimestampPosition.Overlay
is TimelineItemPollContent -> TimestampPosition.Below
else -> TimestampPosition.Default
}
val replyToDetails = event.inReplyTo as? InReplyTo.Ready
// Long clicks are not not automatically propagated from a `clickable`
@ -384,96 +391,97 @@ private fun MessageEventBubbleContent(
@Composable
fun ContentAndTimestampView(
overlayTimestamp: Boolean,
timestampPosition: TimestampPosition,
modifier: Modifier = Modifier,
contentModifier: Modifier = Modifier,
timestampModifier: Modifier = Modifier,
) {
if (overlayTimestamp) {
Box(modifier) {
ContentView(modifier = contentModifier)
TimelineEventTimestampView(
event = event,
onClick = onTimestampClicked,
onLongClick = ::onTimestampLongClick,
modifier = timestampModifier
.padding(horizontal = 4.dp, vertical = 4.dp) // Outer padding
.background(ElementTheme.colors.bgSubtleSecondary, RoundedCornerShape(10.0.dp))
.align(Alignment.BottomEnd)
.padding(horizontal = 4.dp, vertical = 2.dp) // Inner padding
)
}
} else {
Box(modifier) {
ContentView(modifier = contentModifier)
TimelineEventTimestampView(
event = event,
onClick = onTimestampClicked,
onLongClick = ::onTimestampLongClick,
modifier = timestampModifier
.align(Alignment.BottomEnd)
.padding(horizontal = 8.dp, vertical = 4.dp)
)
}
when (timestampPosition) {
TimestampPosition.Overlay ->
Box(modifier) {
ContentView(modifier = contentModifier)
TimelineEventTimestampView(
event = event,
onClick = onTimestampClicked,
onLongClick = ::onTimestampLongClick,
modifier = timestampModifier
.padding(horizontal = 4.dp, vertical = 4.dp) // Outer padding
.background(ElementTheme.colors.bgSubtleSecondary, RoundedCornerShape(10.0.dp))
.align(Alignment.BottomEnd)
.padding(horizontal = 4.dp, vertical = 2.dp) // Inner padding
)
}
TimestampPosition.Aligned ->
Box(modifier) {
ContentView(modifier = contentModifier)
TimelineEventTimestampView(
event = event,
onClick = onTimestampClicked,
onLongClick = ::onTimestampLongClick,
modifier = timestampModifier
.align(Alignment.BottomEnd)
.padding(horizontal = 8.dp, vertical = 4.dp)
)
}
TimestampPosition.Below ->
Column(modifier) {
ContentView(modifier = contentModifier)
TimelineEventTimestampView(
event = event,
onClick = onTimestampClicked,
onLongClick = ::onTimestampLongClick,
modifier = timestampModifier
.align(Alignment.End)
.padding(horizontal = 8.dp, vertical = 4.dp)
)
}
}
}
/** Used only for media items, with no reply to metadata. It displays the contents with no paddings. */
@Composable
fun SimpleMediaItemLayout(modifier: Modifier = Modifier) {
ContentAndTimestampView(overlayTimestamp = true, modifier = modifier)
}
/** Used for every other type of message, groups the different components in a Column with some space between them. */
/** Groups the different components in a Column with some space between them. */
@Composable
fun CommonLayout(
inReplyToDetails: InReplyTo.Ready?,
modifier: Modifier = Modifier
) {
var modifierWithPadding: Modifier = Modifier
var contentModifier: Modifier = Modifier
EqualWidthColumn(modifier = modifier, spacing = 8.dp) {
if (inReplyToDetails != null) {
val senderName = inReplyToDetails.senderDisplayName ?: inReplyToDetails.senderId.value
val attachmentThumbnailInfo = attachmentThumbnailInfoForInReplyTo(inReplyToDetails)
val text = textForInReplyTo(inReplyToDetails)
ReplyToContent(
senderName = senderName,
text = text,
attachmentThumbnailInfo = attachmentThumbnailInfo,
modifier = Modifier
.padding(top = 8.dp, start = 8.dp, end = 8.dp)
.clip(RoundedCornerShape(6.dp))
.clickable(enabled = true, onClick = inReplyToClick),
)
}
val modifierWithPadding = if (isMediaItem) {
Modifier.padding(start = 8.dp, end = 8.dp, bottom = 8.dp)
} else {
Modifier
}
val contentModifier = if (isMediaItem) {
Modifier.clip(RoundedCornerShape(12.dp))
} else {
if (inReplyToDetails != null) {
Modifier.padding(start = 12.dp, end = 12.dp, top = 0.dp, bottom = 8.dp)
} else {
Modifier.padding(start = 12.dp, end = 12.dp, top = 8.dp, bottom = 8.dp)
when {
inReplyToDetails != null -> {
val senderName = inReplyToDetails.senderDisplayName ?: inReplyToDetails.senderId.value
val attachmentThumbnailInfo = attachmentThumbnailInfoForInReplyTo(inReplyToDetails)
val text = textForInReplyTo(inReplyToDetails)
ReplyToContent(
senderName = senderName,
text = text,
attachmentThumbnailInfo = attachmentThumbnailInfo,
modifier = Modifier
.padding(top = 8.dp, start = 8.dp, end = 8.dp)
.clip(RoundedCornerShape(6.dp))
.clickable(enabled = true, onClick = inReplyToClick),
)
if (timestampPosition == TimestampPosition.Overlay) {
modifierWithPadding = Modifier.padding(start = 8.dp, end = 8.dp, bottom = 8.dp)
contentModifier = Modifier.clip(RoundedCornerShape(12.dp))
} else {
contentModifier = Modifier.padding(start = 12.dp, end = 12.dp, top = 0.dp, bottom = 8.dp)
}
}
timestampPosition != TimestampPosition.Overlay -> {
contentModifier = Modifier.padding(start = 12.dp, end = 12.dp, top = 8.dp, bottom = 8.dp)
}
}
ContentAndTimestampView(
overlayTimestamp = isMediaItem,
timestampPosition = timestampPosition,
contentModifier = contentModifier,
modifier = modifierWithPadding,
)
}
}
if (isMediaItem && replyToDetails == null) {
SimpleMediaItemLayout()
} else {
CommonLayout(inReplyToDetails = replyToDetails, modifier = modifier)
}
CommonLayout(inReplyToDetails = replyToDetails, modifier = bubbleModifier)
}
@Composable
@ -810,3 +818,23 @@ internal fun TimelineItemEventRowLongSenderNamePreview() = ElementPreviewLight {
onTimestampClicked = {},
)
}
// Note: no need for light/dark variant for this preview, we only look at the timestamp position
@Preview
@Composable
internal fun TimelineItemEventTimestampBelowPreview() = ElementPreviewLight {
TimelineItemEventRow(
event = aTimelineItemEvent(content = aTimelineItemPollContent()),
isHighlighted = false,
canReply = true,
onClick = {},
onLongClick = {},
onUserDataClick = {},
inReplyToClick = {},
onReactionClick = { _, _ -> },
onReactionLongClick = { _, _ -> },
onMoreReactionsClick = {},
onSwipeToReply = {},
onTimestampClicked = {},
)
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.messages.impl.timeline.components
enum class TimestampPosition {
/**
* Timestamp should overlay the timeline event content (eg. image).
*/
Overlay,
/**
* Timestamp should be aligned with the timeline event content if this is possible (eg. text).
*/
Aligned,
/**
* Timestamp should always be rendered below the timeline event content (eg. poll).
*/
Below;
companion object {
/**
* Default timestamp position for timeline event contents.
*/
val Default: TimestampPosition = Aligned
}
}

View file

@ -21,7 +21,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.PreviewParameter
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContentProvider
import io.element.android.features.poll.api.ActivePollContentView
import io.element.android.features.poll.api.PollContentView
import io.element.android.libraries.designsystem.preview.DayNightPreviews
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.matrix.api.poll.PollAnswer
@ -33,10 +33,11 @@ fun TimelineItemPollView(
onAnswerSelected: (PollAnswer) -> Unit,
modifier: Modifier = Modifier,
) {
ActivePollContentView(
PollContentView(
question = content.question,
answerItems = content.answerItems.toImmutableList(),
pollKind = content.pollKind,
isPollEnded = content.isEnded,
onAnswerSelected = onAnswerSelected,
modifier = modifier,
)

View file

@ -23,7 +23,7 @@ import io.element.android.features.poll.api.PollAnswerItem
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.poll.PollKind
import io.element.android.libraries.matrix.api.poll.isDisclosed
import io.element.android.libraries.matrix.api.timeline.item.event.PollContent
import javax.inject.Inject
@ -36,18 +36,33 @@ class TimelineItemContentPollFactory @Inject constructor(
if (!featureFlagService.isFeatureEnabled(FeatureFlags.Polls)) return TimelineItemUnknownContent
// Todo Move this computation to the matrix rust sdk
val showResults = content.kind == PollKind.Disclosed && matrixClient.sessionId in content.votes.flatMap { it.value }
val pollVotesCount = content.votes.flatMap { it.value }.size
val userVotes = content.votes.filter { matrixClient.sessionId in it.value }.keys
val totalVoteCount = content.votes.flatMap { it.value }.size
val myVotes = content.votes.filter { matrixClient.sessionId in it.value }.keys
val isEndedPoll = content.endTime != null
val winnerIds = if (!isEndedPoll) {
emptyList()
} else {
content.answers
.map { answer -> answer.id }
.groupBy { answerId -> content.votes[answerId]?.size ?: 0 } // Group by votes count
.maxByOrNull { (votes, _) -> votes } // Keep max voted answers
?.takeIf { (votes, _) -> votes > 0 } // Ignore if no option has been voted
?.value
.orEmpty()
}
val answerItems = content.answers.map { answer ->
val votesCount = content.votes[answer.id]?.size ?: 0
val progress = if (pollVotesCount > 0) votesCount.toFloat() / pollVotesCount.toFloat() else 0f
val answerVoteCount = content.votes[answer.id]?.size ?: 0
val isSelected = answer.id in myVotes
val isWinner = answer.id in winnerIds
val percentage = if (totalVoteCount > 0) answerVoteCount.toFloat() / totalVoteCount.toFloat() else 0f
PollAnswerItem(
answer = answer,
isSelected = answer.id in userVotes,
isDisclosed = showResults,
votesCount = votesCount,
progress = progress,
isSelected = isSelected,
isEnabled = !isEndedPoll,
isWinner = isWinner,
isDisclosed = content.kind.isDisclosed || isEndedPoll,
votesCount = answerVoteCount,
percentage = percentage,
)
}
@ -56,7 +71,7 @@ class TimelineItemContentPollFactory @Inject constructor(
answerItems = answerItems,
votes = content.votes,
pollKind = content.kind,
isDisclosed = showResults
isEnded = isEndedPoll,
)
}
}

View file

@ -25,7 +25,7 @@ data class TimelineItemPollContent(
val answerItems: List<PollAnswerItem>,
val votes: Map<String, List<UserId>>,
val pollKind: PollKind,
val isDisclosed: Boolean,
val isEnded: Boolean,
) : TimelineItemEventContent {
override val type: String = "TimelineItemPollContent"
}

View file

@ -24,16 +24,16 @@ open class TimelineItemPollContentProvider : PreviewParameterProvider<TimelineIt
override val values: Sequence<TimelineItemPollContent>
get() = sequenceOf(
aTimelineItemPollContent(),
aTimelineItemPollContent().copy(isDisclosed = true),
aTimelineItemPollContent().copy(pollKind = PollKind.Undisclosed),
)
}
fun aTimelineItemPollContent(): TimelineItemPollContent {
return TimelineItemPollContent(
pollKind = PollKind.Disclosed,
isDisclosed = false,
question = "What type of food should we have at the party?",
answerItems = aPollAnswerItemList(),
isEnded = false,
votes = emptyMap(),
)
}

View file

@ -5,19 +5,43 @@
<item quantity="few">"%1$d změny místnosti"</item>
<item quantity="other">"%1$d změn místnosti"</item>
</plurals>
<plurals name="screen_room_timeline_more_reactions">
<item quantity="one">"%1$d další"</item>
<item quantity="few">"%1$d další"</item>
<item quantity="other">"%1$d dalších"</item>
</plurals>
<string name="screen_room_attachment_source_camera">"Fotoaparát"</string>
<string name="screen_room_attachment_source_camera_photo">"Vyfotit"</string>
<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_poll">"Hlasování"</string>
<string name="screen_room_encrypted_history_banner">"Historie zpráv je momentálně v této místnosti nedostupná"</string>
<string name="screen_room_error_failed_retrieving_user_details">"Nepodařilo se načíst údaje o uživateli"</string>
<string name="screen_room_invite_again_alert_message">"Chtěli byste je pozvat zpět?"</string>
<string name="screen_room_invite_again_alert_title">"V tomto chatu jste sami"</string>
<string name="screen_room_message_copied">"Zpráva zkopírována"</string>
<string name="screen_room_no_permission_to_post">"Nemáte oprávnění zveřejňovat příspěvky v této místnosti"</string>
<string name="screen_room_notification_settings_allow_custom">"Povolit vlastní nastavení"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Zapnutím této funkce přepíšete výchozí nastavení"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Upozornit mě v tomto chatu na"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Můžete změnit ve vašem %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"globální nastavení"</string>
<string name="screen_room_notification_settings_default_setting_title">"Výchozí nastavení"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Odebrat vlastní nastavení"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Při načítání nastavení oznámení došlo k chybě."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Obnovení výchozího režimu se nezdařilo, zkuste to prosím znovu."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Nastavení režimu se nezdařilo, zkuste to prosím znovu."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Všechny zprávy"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Pouze zmínky a klíčová slova"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"V této místnosti mě upozornit na"</string>
<string name="screen_room_reactions_show_less">"Zobrazit méně"</string>
<string name="screen_room_reactions_show_more">"Zobrazit více"</string>
<string name="screen_room_retry_send_menu_send_again_action">"Odeslat znovu"</string>
<string name="screen_room_retry_send_menu_title">"Vaši zprávu se nepodařilo odeslat"</string>
<string name="screen_room_timeline_add_reaction">"Přidat emoji"</string>
<string name="screen_room_timeline_less_reactions">"Zobrazit méně"</string>
<string name="screen_room_error_failed_processing_media">"Nahrání média se nezdařilo, zkuste to prosím znovu."</string>
<string name="screen_room_retry_send_menu_remove_action">"Odstranit"</string>
</resources>

View file

@ -10,16 +10,32 @@
<string name="screen_room_attachment_source_files">"Anhang"</string>
<string name="screen_room_attachment_source_gallery">"Foto- &amp; Video-Bibliothek"</string>
<string name="screen_room_attachment_source_location">"Standort"</string>
<string name="screen_room_attachment_source_poll">"Umfrage"</string>
<string name="screen_room_encrypted_history_banner">"Der Nachrichtenverlauf ist in diesem Raum derzeit nicht verfügbar"</string>
<string name="screen_room_error_failed_retrieving_user_details">"Benutzerdetails konnten nicht abgerufen werden"</string>
<string name="screen_room_invite_again_alert_message">"Möchtest du sie wieder einladen?"</string>
<string name="screen_room_invite_again_alert_title">"Du bist allein in diesem Chat"</string>
<string name="screen_room_message_copied">"Nachricht kopiert"</string>
<string name="screen_room_no_permission_to_post">"Du bist keine Berechtigung, um in diesem Raum zu posten"</string>
<string name="screen_room_notification_settings_allow_custom">"Benutzerdefinierte Einstellung zulassen"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Das Aktivieren dieser Option wird die Standardeinstellungen überschreiben."</string>
<string name="screen_room_notification_settings_custom_settings_title">"Benachrichtige mich in diesem Chat für"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Du kannst es in deinem %1$s ändern."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"Globale Einstellungen"</string>
<string name="screen_room_notification_settings_default_setting_title">"Standardeinstellung"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Benutzerdefinierte Einstellung entfernen"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Beim Laden der Benachrichtigungseinstellungen ist ein Fehler aufgetreten."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Wiederherstellung des Standardmodus fehlgeschlagen. Bitte versuche es erneut."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Fehler beim Einstellen des Modus. Bitte versuche es erneut."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Alle Nachrichten"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Nur Erwähnungen und Schlüsselwörter"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"In diesem Raum, benachrichtige mich für"</string>
<string name="screen_room_reactions_show_less">"Weniger anzeigen"</string>
<string name="screen_room_reactions_show_more">"Mehr anzeigen"</string>
<string name="screen_room_retry_send_menu_send_again_action">"Erneut senden"</string>
<string name="screen_room_retry_send_menu_title">"Ihre Nachricht konnte nicht gesendet werden"</string>
<string name="screen_room_timeline_add_reaction">"Emoji hinzufügen"</string>
<string name="screen_room_timeline_less_reactions">"Weniger anzeigen"</string>
<string name="screen_room_error_failed_processing_media">"Fehler bei der Verarbeitung von Medien zum Hochladen, bitte versuche es erneut."</string>
<string name="screen_room_retry_send_menu_remove_action">"Entfernen"</string>
</resources>

View file

@ -5,6 +5,11 @@
<item quantity="few">"%1$d изменения в комнате"</item>
<item quantity="many">"%1$d изменений в комнате"</item>
</plurals>
<plurals name="screen_room_timeline_more_reactions">
<item quantity="one">"И ещё %1$d"</item>
<item quantity="few">"И ещё %1$d"</item>
<item quantity="many">"И ещё %1$d"</item>
</plurals>
<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>
@ -24,11 +29,13 @@
<string name="screen_room_notification_settings_default_setting_footnote">"Вы можете изменить его в своем %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"Основные Настройки"</string>
<string name="screen_room_notification_settings_default_setting_title">"Настройка по умолчанию"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Удалить пользовательскую настройку"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Произошла ошибка при загрузке настроек уведомлений."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Не удалось восстановить режим по умолчанию, попробуйте еще раз."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Не удалось настроить режим, попробуйте еще раз."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Все сообщения"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Только упоминания и ключевые слова"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"В этой комнате уведомить меня о"</string>
<string name="screen_room_reactions_show_less">"Показать меньше"</string>
<string name="screen_room_reactions_show_more">"Показать больше"</string>
<string name="screen_room_retry_send_menu_send_again_action">"Отправить снова"</string>

View file

@ -16,6 +16,7 @@
<string name="screen_room_attachment_source_files">"Príloha"</string>
<string name="screen_room_attachment_source_gallery">"Knižnica fotografií a videí"</string>
<string name="screen_room_attachment_source_location">"Poloha"</string>
<string name="screen_room_attachment_source_poll">"Anketa"</string>
<string name="screen_room_encrypted_history_banner">"História správ v tejto miestnosti nie je momentálne k dispozícii"</string>
<string name="screen_room_error_failed_retrieving_user_details">"Nepodarilo sa získať údaje o používateľovi"</string>
<string name="screen_room_invite_again_alert_message">"Chceli by ste ich pozvať späť?"</string>
@ -28,11 +29,13 @@
<string name="screen_room_notification_settings_default_setting_footnote">"Môžete to zmeniť vo svojich %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"všeobecných nastaveniach"</string>
<string name="screen_room_notification_settings_default_setting_title">"Predvolené nastavenie"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Odstrániť vlastné nastavenie"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Pri načítavaní nastavení oznámení došlo k chybe."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Nepodarilo sa obnoviť predvolený režim, skúste to prosím znova."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Nepodarilo sa nastaviť režim, skúste to prosím znova."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Všetky správy"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Iba zmienky a kľúčové slová"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"V tejto miestnosti ma upozorniť na"</string>
<string name="screen_room_reactions_show_less">"Zobraziť menej"</string>
<string name="screen_room_reactions_show_more">"Zobraziť viac"</string>
<string name="screen_room_retry_send_menu_send_again_action">"Odoslať znova"</string>