Merge branch 'develop' into feature/fga/csam_preferences_server

This commit is contained in:
ganfra 2025-06-30 21:42:06 +02:00
commit 773fa1657a
623 changed files with 4661 additions and 2049 deletions

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_analytics_settings_help_us_improve">"Del anonyme brugsdata for at hjælpe os med at identificere problemer."</string>
<string name="screen_analytics_settings_read_terms">"Du kan læse alle vores vilkår %1$s."</string>
<string name="screen_analytics_settings_read_terms_content_link">"her"</string>
<string name="screen_analytics_settings_share_data">"Del analysedata"</string>
</resources>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_analytics_prompt_data_usage">"Vi vil ikke registrere eller profilere nogen personlige data"</string>
<string name="screen_analytics_prompt_help_us_improve">"Del anonyme brugsdata for at hjælpe os med at identificere problemer."</string>
<string name="screen_analytics_prompt_read_terms">"Du kan læse alle vores vilkår %1$s."</string>
<string name="screen_analytics_prompt_read_terms_content_link">"her"</string>
<string name="screen_analytics_prompt_settings">"Du kan slå dette fra når som helst"</string>
<string name="screen_analytics_prompt_third_party_sharing">"Vi deler ikke dine data med tredjeparter"</string>
<string name="screen_analytics_prompt_title">"Hjælp med at forbedre %1$s"</string>
</resources>

View file

@ -7,16 +7,6 @@
package io.element.android.features.call.impl.pip
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
open class PictureInPictureStateProvider : PreviewParameterProvider<PictureInPictureState> {
override val values: Sequence<PictureInPictureState>
get() = sequenceOf(
aPictureInPictureState(supportPip = true),
aPictureInPictureState(supportPip = true, isInPictureInPicture = true),
)
}
fun aPictureInPictureState(
supportPip: Boolean = false,
isInPictureInPicture: Boolean = false,

View file

@ -11,6 +11,7 @@ import android.annotation.SuppressLint
import android.util.Log
import android.view.ViewGroup
import android.webkit.ConsoleMessage
import android.webkit.JavascriptInterface
import android.webkit.PermissionRequest
import android.webkit.WebChromeClient
import android.webkit.WebView
@ -19,7 +20,6 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@ -32,11 +32,9 @@ import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.viewinterop.AndroidView
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.features.call.impl.R
import io.element.android.features.call.impl.pip.PictureInPictureEvents
import io.element.android.features.call.impl.pip.PictureInPictureState
import io.element.android.features.call.impl.pip.PictureInPictureStateProvider
import io.element.android.features.call.impl.pip.aPictureInPictureState
import io.element.android.features.call.impl.utils.InvalidAudioDeviceReason
import io.element.android.features.call.impl.utils.WebViewAudioManager
@ -44,13 +42,11 @@ import io.element.android.features.call.impl.utils.WebViewPipController
import io.element.android.features.call.impl.utils.WebViewWidgetMessageInterceptor
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.ui.strings.CommonStrings
import timber.log.Timber
@ -60,7 +56,6 @@ interface CallScreenNavigator {
fun close()
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun CallScreenView(
state: CallScreenState,
@ -78,19 +73,6 @@ internal fun CallScreenView(
Scaffold(
modifier = modifier,
topBar = {
if (!pipState.isInPictureInPicture) {
TopAppBar(
title = { Text(stringResource(R.string.element_call)) },
navigationIcon = {
BackButton(
imageVector = if (pipState.supportPip) CompoundIcons.ArrowLeft() else CompoundIcons.Close(),
onClick = ::handleBack,
)
}
)
}
}
) { padding ->
BackHandler {
handleBack()
@ -127,9 +109,11 @@ internal fun CallScreenView(
requestPermissions(androidPermissions.toTypedArray(), callback)
},
onCreateWebView = { webView ->
webView.addBackHandler(onBackPressed = ::handleBack)
val interceptor = WebViewWidgetMessageInterceptor(
webView = webView,
onUrlLoaded = { url ->
webView.evaluateJavascript("controls.onBackButtonPressed = () => { backHandler.onBackPressed() }", null)
if (webViewAudioManager?.isInCallMode?.get() == false) {
Timber.d("URL $url is loaded, starting in-call audio mode")
webViewAudioManager?.onCallStarted()
@ -282,6 +266,17 @@ private fun WebView.setup(
}
}
private fun WebView.addBackHandler(onBackPressed: () -> Unit) {
addJavascriptInterface(
object {
@Suppress("unused")
@JavascriptInterface
fun onBackPressed() = onBackPressed()
},
"backHandler"
)
}
@PreviewsDayNight
@Composable
internal fun CallScreenViewPreview(
@ -294,18 +289,6 @@ internal fun CallScreenViewPreview(
)
}
@PreviewsDayNight
@Composable
internal fun CallScreenPipViewPreview(
@PreviewParameter(PictureInPictureStateProvider::class) state: PictureInPictureState,
) = ElementPreview {
CallScreenView(
state = aCallScreenState(),
pipState = state,
requestPermissions = { _, _ -> },
)
}
@PreviewsDayNight
@Composable
internal fun InvalidAudioDeviceDialogPreview() = ElementPreview {

View file

@ -3,5 +3,6 @@
<string name="call_foreground_service_channel_title_android">"Probíhající hovor"</string>
<string name="call_foreground_service_message_android">"Klepněte pro návrat k hovoru"</string>
<string name="call_foreground_service_title_android">"☎️ Probíhá hovor"</string>
<string name="call_invalid_audio_device_bluetooth_devices_disabled">"Element Call nepodporuje používání Bluetooth zvukových zařízení v této verzi systému Android. Vyberte jiné zvukové zařízení."</string>
<string name="screen_incoming_call_subtitle_android">"Příchozí Element Call"</string>
</resources>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="call_foreground_service_channel_title_android">"Igangværende opkald"</string>
<string name="call_foreground_service_message_android">"Tryk for at vende tilbage til opkaldet"</string>
<string name="call_foreground_service_title_android">"☎️ Opkald i gang"</string>
<string name="call_invalid_audio_device_bluetooth_devices_disabled">"Element Call understøtter desværre ikke brug af Bluetooth-lydenheder i denne Android-version. Vælg venligst en anden lydenhed."</string>
<string name="screen_incoming_call_subtitle_android">"Indgående Element opkald"</string>
</resources>

View file

@ -3,5 +3,6 @@
<string name="call_foreground_service_channel_title_android">"Συνεχής κλήση"</string>
<string name="call_foreground_service_message_android">"Πάτα για να επιστρέψεις στην κλήση"</string>
<string name="call_foreground_service_title_android">"☎️ Κλήση σε εξέλιξη"</string>
<string name="call_invalid_audio_device_bluetooth_devices_disabled">"Το Element Call δεν υποστηρίζει τη χρήση συσκευών ήχου Bluetooth σε αυτήν την έκδοση Android. Επέλεξε μια διαφορετική συσκευή ήχου."</string>
<string name="screen_incoming_call_subtitle_android">"Εισερχόμενη κλήση Element"</string>
</resources>

View file

@ -3,5 +3,6 @@
<string name="call_foreground_service_channel_title_android">"Käimasolev kõne"</string>
<string name="call_foreground_service_message_android">"Kõne juurde naasmiseks klõpsa"</string>
<string name="call_foreground_service_title_android">"☎️ Kõne on pooleli"</string>
<string name="call_invalid_audio_device_bluetooth_devices_disabled">"Element Call ei võimalda selles Androidi versioonis Bluetoothi heliseadmete kasutamist. Palun vali mõni muu heliseade."</string>
<string name="screen_incoming_call_subtitle_android">"Sissetulev Element Calli kõne"</string>
</resources>

View file

@ -3,5 +3,6 @@
<string name="call_foreground_service_channel_title_android">"Folyamatban lévő hívás"</string>
<string name="call_foreground_service_message_android">"Koppintson a híváshoz való visszatéréshez"</string>
<string name="call_foreground_service_title_android">"☎️ Hívás folyamatban"</string>
<string name="call_invalid_audio_device_bluetooth_devices_disabled">"Az Element Call nem támogatja a Bluetooth hangeszközök használatát ebben az Android-verzióban. Válasszon másik hangeszközt."</string>
<string name="screen_incoming_call_subtitle_android">"Bejövő Element hívás"</string>
</resources>

View file

@ -3,5 +3,6 @@
<string name="call_foreground_service_channel_title_android">"Chamada em curso"</string>
<string name="call_foreground_service_message_android">"Toca para voltar à chamada"</string>
<string name="call_foreground_service_title_android">"☎️ Chamada em curso"</string>
<string name="call_invalid_audio_device_bluetooth_devices_disabled">"As chamadas do Element não permitem o uso de dispositivos de áudio Bluetooth nesta versão do Android. Por favor, seleciona outro dispositivo."</string>
<string name="screen_incoming_call_subtitle_android">"A receber chamada da Element"</string>
</resources>

View file

@ -3,5 +3,6 @@
<string name="call_foreground_service_channel_title_android">"Prebiehajúci hovor"</string>
<string name="call_foreground_service_message_android">"Ťuknutím sa vrátite k hovoru"</string>
<string name="call_foreground_service_title_android">"☎️ Prebieha hovor"</string>
<string name="call_invalid_audio_device_bluetooth_devices_disabled">"Element Call nepodporuje používanie zvukových zariadení Bluetooth v tejto verzii systému Android. Vyberte iné zvukové zariadenie."</string>
<string name="screen_incoming_call_subtitle_android">"Prichádzajúci hovor Element Call"</string>
</resources>

View file

@ -3,5 +3,6 @@
<string name="call_foreground_service_channel_title_android">"Поточний виклик"</string>
<string name="call_foreground_service_message_android">"Торкніться, щоб повернутися до виклику"</string>
<string name="call_foreground_service_title_android">"☎️ Триває виклик"</string>
<string name="call_invalid_audio_device_bluetooth_devices_disabled">"Element Call не підтримує використання аудіопристроїв Bluetooth у цій версії Android. Виберіть інший аудіопристрій."</string>
<string name="screen_incoming_call_subtitle_android">"Вхідний виклик Element"</string>
</resources>

View file

@ -1,83 +0,0 @@
/*
* Copyright 2024 New Vector 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.call.impl.ui
import androidx.activity.ComponentActivity
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.element.android.features.call.impl.pip.PictureInPictureEvents
import io.element.android.features.call.impl.pip.PictureInPictureState
import io.element.android.features.call.impl.pip.aPictureInPictureState
import io.element.android.tests.testutils.EventsRecorder
import io.element.android.tests.testutils.pressBack
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class CallScreenViewTest {
@get:Rule val rule = createAndroidComposeRule<ComponentActivity>()
@Test
fun `clicking on back when pip is not supported hangs up`() {
val eventsRecorder = EventsRecorder<CallScreenEvents>()
val pipEventsRecorder = EventsRecorder<PictureInPictureEvents>()
rule.setCallScreenView(
aCallScreenState(
eventSink = eventsRecorder
),
aPictureInPictureState(
supportPip = false,
eventSink = pipEventsRecorder,
),
)
rule.pressBack()
eventsRecorder.assertSize(2)
eventsRecorder.assertTrue(0) { it is CallScreenEvents.SetupMessageChannels }
eventsRecorder.assertTrue(1) { it == CallScreenEvents.Hangup }
pipEventsRecorder.assertSize(1)
pipEventsRecorder.assertTrue(0) { it is PictureInPictureEvents.SetPipController }
}
@Test
fun `clicking on back when pip is supported enables PiP`() {
val eventsRecorder = EventsRecorder<CallScreenEvents>()
val pipEventsRecorder = EventsRecorder<PictureInPictureEvents>()
rule.setCallScreenView(
aCallScreenState(
eventSink = eventsRecorder
),
aPictureInPictureState(
supportPip = true,
eventSink = pipEventsRecorder,
),
)
rule.pressBack()
eventsRecorder.assertSize(1)
eventsRecorder.assertTrue(0) { it is CallScreenEvents.SetupMessageChannels }
pipEventsRecorder.assertSize(2)
pipEventsRecorder.assertTrue(0) { it is PictureInPictureEvents.SetPipController }
pipEventsRecorder.assertTrue(1) { it == PictureInPictureEvents.EnterPictureInPicture }
}
}
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setCallScreenView(
state: CallScreenState,
pipState: PictureInPictureState,
requestPermissions: (Array<String>, RequestPermissionCallback) -> Unit = { _, _ -> },
) {
setContent {
CallScreenView(
state = state,
pipState = pipState,
requestPermissions = requestPermissions,
)
}
}

View file

@ -3,10 +3,21 @@
<string name="screen_create_room_action_create_room">"Нова стая"</string>
<string name="screen_create_room_add_people_title">"Поканване на хора"</string>
<string name="screen_create_room_error_creating_room">"Възникна грешка при създаването на стаята"</string>
<string name="screen_create_room_private_option_description">"Съобщенията в тази стая са шифровани. Шифроването не може да бъде изключено впоследствие."</string>
<string name="screen_create_room_private_option_title">"Частна стая (само с покана)"</string>
<string name="screen_create_room_public_option_description">"Съобщенията не са шифровани и всеки може да ги прочете. Можете да активирате шифроването на по-късна дата."</string>
<string name="screen_create_room_private_option_description">"Само поканени хора имат достъп до тази стая. Всички съобщения са шифровани от край до край."</string>
<string name="screen_create_room_private_option_title">"Частна стая"</string>
<string name="screen_create_room_public_option_description">"Всеки може да намери тази стая.
Можете да промените това по всяко време в настройките на стаята."</string>
<string name="screen_create_room_public_option_title">"Общодостъпна стая"</string>
<string name="screen_create_room_room_access_section_anyone_option_description">"Всеки може да се присъедини към тази стая"</string>
<string name="screen_create_room_room_access_section_anyone_option_title">"Всеки"</string>
<string name="screen_create_room_room_address_section_footer">"За да бъде тази стая видима в директорията на общодостъпните стаи, ще ви е необходим адрес на стаята."</string>
<string name="screen_create_room_room_name_label">"Име на стаята"</string>
<string name="screen_create_room_room_visibility_section_title">"Видимост на стаята"</string>
<string name="screen_create_room_title">"Създаване на стая"</string>
<string name="screen_create_room_topic_label">"Тема за разговор (незадължително)"</string>
<string name="screen_start_chat_join_room_by_address_action">"Присъединяване към стая по адрес"</string>
<string name="screen_start_chat_join_room_by_address_invalid_address">"Не е валиден адрес"</string>
<string name="screen_start_chat_join_room_by_address_placeholder">"Въведете…"</string>
<string name="screen_start_chat_join_room_by_address_room_not_found">"Стаята не е намерена"</string>
<string name="screen_start_chat_join_room_by_address_supporting_text">"напр. #room-name:matrix.org"</string>
</resources>

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_create_room_action_create_room">"Nyt rum"</string>
<string name="screen_create_room_add_people_title">"Invitér folk"</string>
<string name="screen_create_room_error_creating_room">"Der opstod en fejl ved oprettelsen af rummet"</string>
<string name="screen_create_room_private_option_description">"Kun inviterede personer kan få adgang til dette rum. Alle meddelelser er ende-til-ende krypteret."</string>
<string name="screen_create_room_private_option_title">"Privat rum"</string>
<string name="screen_create_room_public_option_description">"Alle kan finde dette rum.
Du kan ændre dette når som helst i rummets indstillinger."</string>
<string name="screen_create_room_public_option_title">"Offentligt rum"</string>
<string name="screen_create_room_room_access_section_anyone_option_description">"Alle kan deltage i dette rum"</string>
<string name="screen_create_room_room_access_section_anyone_option_title">"Enhver"</string>
<string name="screen_create_room_room_access_section_header">"Adgang til rummet"</string>
<string name="screen_create_room_room_access_section_knocking_option_description">"Alle kan bede om at deltage i rummet, men en administrator eller en moderator skal acceptere anmodningen"</string>
<string name="screen_create_room_room_access_section_knocking_option_title">"Spørg om at deltage"</string>
<string name="screen_create_room_room_address_section_footer">"Hvis dette rum skal være synligt i det offentlige register, skal du bruge en rum-adresse."</string>
<string name="screen_create_room_room_address_section_title">"Rummets adresse"</string>
<string name="screen_create_room_room_name_label">"Navn på rum"</string>
<string name="screen_create_room_room_visibility_section_title">"Rummets synlighed"</string>
<string name="screen_create_room_title">"Opret et rum"</string>
<string name="screen_create_room_topic_label">"Emne (valgfrit)"</string>
<string name="screen_room_directory_search_title">"Register over rum"</string>
<string name="screen_start_chat_error_starting_chat">"Der opstod en fejl under forsøget på at starte en samtale"</string>
<string name="screen_start_chat_join_room_by_address_action">"Tilslut dig rummet med adressen"</string>
<string name="screen_start_chat_join_room_by_address_invalid_address">"Ikke en gyldig adresse"</string>
<string name="screen_start_chat_join_room_by_address_placeholder">"Indtast…"</string>
<string name="screen_start_chat_join_room_by_address_room_found">"Matchende rum fundet"</string>
<string name="screen_start_chat_join_room_by_address_room_not_found">"Rum ikke fundet"</string>
<string name="screen_start_chat_join_room_by_address_supporting_text">"f.eks. #rummets-navn:matrix.org"</string>
</resources>

View file

@ -1,30 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_create_room_action_create_room">"Νέο δωμάτιο"</string>
<string name="screen_create_room_action_create_room">"Νέα αίθουσα"</string>
<string name="screen_create_room_add_people_title">"Πρόσκληση ατόμων"</string>
<string name="screen_create_room_error_creating_room">αρουσιάστηκε σφάλμα κατά τη δημιουργία του δωματίου"</string>
<string name="screen_create_room_private_option_description">"Μόνο άτομα που έχουν προσκληθεί μπορούν να έχουν πρόσβαση σε αυτό το δωμάτιο. Όλα τα μηνύματα είναι κρυπτογραφημένα από άκρο σε άκρο."</string>
<string name="screen_create_room_private_option_title">"Ιδιωτικό δωμάτιο"</string>
<string name="screen_create_room_public_option_description">"Ο καθένας μπορεί να βρει αυτό το δωμάτιο.
Μπορείς να το αλλάξεις ανά πάσα στιγμή στις ρυθμίσεις δωματίου."</string>
<string name="screen_create_room_public_option_title">"Δημόσιο δωμάτιο"</string>
<string name="screen_create_room_room_access_section_anyone_option_description">"Οποιοσδήποτε μπορεί να συμμετάσχει σε αυτό το δωμάτιο"</string>
<string name="screen_create_room_error_creating_room">ροέκυψε σφάλμα κατά τη δημιουργία της αίθουσας"</string>
<string name="screen_create_room_private_option_description">"Μόνο τα άτομα που έχουν προσκληθεί μπορούν να έχουν πρόσβαση σε αυτή την αίθουσα. Όλα τα μηνύματα είναι κρυπτογραφημένα από άκρο σε άκρο."</string>
<string name="screen_create_room_private_option_title">"Ιδιωτική αίθουσα"</string>
<string name="screen_create_room_public_option_description">"Ο καθένας μπορεί να βρει αυτή την αίθουσα.
Αυτό μπορείτε να το αλλάξετε ανά πάσα στιγμή στις ρυθμίσεις της αίθουσας."</string>
<string name="screen_create_room_public_option_title">"Δημόσια αίθουσα"</string>
<string name="screen_create_room_room_access_section_anyone_option_description">"Οποιοσδήποτε μπορεί να συμμετάσχει σε αυτή την αίθουσα"</string>
<string name="screen_create_room_room_access_section_anyone_option_title">"Οποιοσδήποτε"</string>
<string name="screen_create_room_room_access_section_header">"Πρόσβαση Δωματίου"</string>
<string name="screen_create_room_room_access_section_knocking_option_description">"Οποιοσδήποτε μπορεί να ζητήσει να συμμετάσχει στο δωμάτιο, αλλά ένας διαχειριστής ή συντονιστής θα πρέπει να αποδεχθεί το αίτημα"</string>
<string name="screen_create_room_room_access_section_header">"Πρόσβαση στην Αίθουσα"</string>
<string name="screen_create_room_room_access_section_knocking_option_description">"Οποιοσδήποτε μπορεί να ζητήσει να συμμετάσχει στην αίθουσα, αλλά ένας διαχειριστής ή ένας συντονιστής θα πρέπει να αποδεχτεί το αίτημα"</string>
<string name="screen_create_room_room_access_section_knocking_option_title">"Αίτημα συμμετοχής"</string>
<string name="screen_create_room_room_address_section_footer">"Για να είναι ορατό αυτό το δωμάτιο στον κατάλογο των δημόσιων δωματίων, θα χρειαστείς μια διεύθυνση δωματίου."</string>
<string name="screen_create_room_room_address_section_title">"Διεύθυνση δωματίου"</string>
<string name="screen_create_room_room_name_label">"Όνομα δωματίου"</string>
<string name="screen_create_room_room_visibility_section_title">"Ορατότητα δωματίου"</string>
<string name="screen_create_room_title">"Δημιούργησε ένα δωμάτιο"</string>
<string name="screen_create_room_room_address_section_footer">"Για να είναι ορατή αυτή η αίθουσα στον δημόσιο κατάλογο αιθουσών, θα χρειαστείτε μια διεύθυνση αίθουσας."</string>
<string name="screen_create_room_room_address_section_title">"Διεύθυνση αίθουσας"</string>
<string name="screen_create_room_room_name_label">"Όνομα αίθουσας"</string>
<string name="screen_create_room_room_visibility_section_title">"Ορατότητα αίθουσας"</string>
<string name="screen_create_room_title">"Δημιουργία αίθουσας"</string>
<string name="screen_create_room_topic_label">"Θέμα (προαιρετικό)"</string>
<string name="screen_room_directory_search_title">"Κατάλογος δωματίων"</string>
<string name="screen_room_directory_search_title">"Κατάλογος αιθουσών"</string>
<string name="screen_start_chat_error_starting_chat">"Παρουσιάστηκε σφάλμα κατά την προσπάθεια έναρξης μιας συνομιλίας"</string>
<string name="screen_start_chat_join_room_by_address_action">"Συμμετοχή σε δωμάτιο μέσω διεύθυνσης"</string>
<string name="screen_start_chat_join_room_by_address_action">"Συμμετοχή σε αίθουσα μέσω διεύθυνσης"</string>
<string name="screen_start_chat_join_room_by_address_invalid_address">"Μη έγκυρη διεύθυνση"</string>
<string name="screen_start_chat_join_room_by_address_placeholder">"Εισάγετε…"</string>
<string name="screen_start_chat_join_room_by_address_room_found">"Βρέθηκε το αντίστοιχο δωμάτιο"</string>
<string name="screen_start_chat_join_room_by_address_room_not_found">"Το δωμάτιο δε βρέθηκε"</string>
<string name="screen_start_chat_join_room_by_address_supporting_text">"π.χ. #όνομα-δωματίου:matrix.org"</string>
<string name="screen_start_chat_join_room_by_address_room_found">"Βρέθηκε η αντίστοιχη αίθουσα"</string>
<string name="screen_start_chat_join_room_by_address_room_not_found">"Η αίθουσα δεν βρέθηκε"</string>
<string name="screen_start_chat_join_room_by_address_supporting_text">"π.χ. #όνομα-αίθουσας:matrix.org"</string>
</resources>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_deactivate_account_confirmation_dialog_content">"Моля, потвърдете, че искате да деактивирате акаунта си. Това действие не може да бъде отменено."</string>
<string name="screen_deactivate_account_title">"Деактивиране на акаунта"</string>
</resources>

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_deactivate_account_confirmation_dialog_content">"Bekræft venligst, at du vil deaktivere din konto. Denne handling kan ikke fortrydes."</string>
<string name="screen_deactivate_account_delete_all_messages">"Slet alle mine beskeder"</string>
<string name="screen_deactivate_account_delete_all_messages_notice">"Advarsel: Fremtidige brugere kan muligvis se ufuldstændige samtaler."</string>
<string name="screen_deactivate_account_description">"Deaktivering af din konto er %1$s, det vil:"</string>
<string name="screen_deactivate_account_description_bold_part">"irreversibel"</string>
<string name="screen_deactivate_account_list_item_1">"%1$s din konto (du kan ikke logge ind igen, og dit ID kan ikke genbruges)."</string>
<string name="screen_deactivate_account_list_item_1_bold_part">"Deaktiver permanent"</string>
<string name="screen_deactivate_account_list_item_2">"Fjern dig fra alle samtalerum"</string>
<string name="screen_deactivate_account_list_item_3">"Slette dine kontooplysninger fra vores identitetsserver."</string>
<string name="screen_deactivate_account_list_item_4">"Dine beskeder vil stadig være synlige for registrerede brugere, men vil ikke være tilgængelige for nye eller uregistrerede brugere, hvis du vælger at slette dem."</string>
<string name="screen_deactivate_account_title">"Deaktiver konto"</string>
</resources>

View file

@ -7,7 +7,7 @@
<string name="screen_deactivate_account_description_bold_part">"μη αναστρέψιμο"</string>
<string name="screen_deactivate_account_list_item_1">"%1$s τον λογαριασμό σου (δεν μπορείς να συνδεθείς ξανά και το αναγνωριστικό σου δεν μπορεί να επαναχρησιμοποιηθεί)."</string>
<string name="screen_deactivate_account_list_item_1_bold_part">"Μόνιμη απενεργοποίηση"</string>
<string name="screen_deactivate_account_list_item_2">"Σε αφαιρέσει από όλα τα δωμάτια συνομιλίας."</string>
<string name="screen_deactivate_account_list_item_2">"Αποχώρησή σας από όλες τις αίθουσες συνομιλίας."</string>
<string name="screen_deactivate_account_list_item_3">"Διαγράψει τα στοιχεία του λογαριασμού σου από τον διακομιστή ταυτότητάς μας."</string>
<string name="screen_deactivate_account_list_item_4">"Τα μηνύματά σου θα εξακολουθούν να είναι ορατά στους εγγεγραμμένους χρήστες, αλλά δεν θα είναι διαθέσιμα σε νέους ή μη εγγεγραμμένους χρήστες εάν επιλέξεις να τα διαγράψεις."</string>
<string name="screen_deactivate_account_title">"Απενεργοποίηση λογαριασμού"</string>

View file

@ -1,5 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_identity_confirmation_cannot_confirm">"Не можете да потвърдите?"</string>
<string name="screen_identity_confirmation_subtitle">"Потвърдете това устройство, за да настроите защитени съобщения."</string>
<string name="screen_identity_confirmation_title">"Потвърдете самоличността си"</string>
<string name="screen_identity_confirmation_use_another_device">"Използване на друго устройство"</string>
<string name="screen_identity_confirmation_use_recovery_key">"Използване на ключ за възстановяване"</string>
<string name="screen_identity_confirmed_title">"Устройството е потвърдено"</string>
<string name="screen_identity_use_another_device">"Използване на друго устройство"</string>
<string name="screen_notification_optin_subtitle">"Можете да промените настройките си по-късно."</string>
<string name="screen_notification_optin_title">"Разрешете известията и никога не пропускайте съобщение"</string>
<string name="screen_session_verification_enter_recovery_key">"Въвеждане на ключ за възстановяване"</string>

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_identity_confirmation_cannot_confirm">"Kan ikke bekræfte?"</string>
<string name="screen_identity_confirmation_create_new_recovery_key">"Opret en ny gendannelsesnøgle"</string>
<string name="screen_identity_confirmation_subtitle">"Verificér denne enhed for at konfigurere sikre meddelelser."</string>
<string name="screen_identity_confirmation_title">"Bekræft din identitet"</string>
<string name="screen_identity_confirmation_use_another_device">"Brug en anden enhed"</string>
<string name="screen_identity_confirmation_use_recovery_key">"Brug gendannelsesnøgle"</string>
<string name="screen_identity_confirmed_subtitle">"Nu kan du læse eller sende beskeder sikkert, og enhver du samtaler med kan også stole på denne enhed."</string>
<string name="screen_identity_confirmed_title">"Enhed verificeret"</string>
<string name="screen_identity_use_another_device">"Brug en anden enhed"</string>
<string name="screen_identity_waiting_on_other_device">"Venter på en anden enhed…"</string>
<string name="screen_notification_optin_subtitle">"Du kan ændre dine indstillinger senere."</string>
<string name="screen_notification_optin_title">"Tillad notifikationer, og gå aldrig glip af en besked"</string>
<string name="screen_session_verification_enter_recovery_key">"Indtast gendannelsesnøgle"</string>
<string name="screen_welcome_bullet_1">"Opkald, afstemninger, søgninger og mere vil blive tilføjet senere på året."</string>
<string name="screen_welcome_bullet_2">"Beskedhistorik for krypterede rum er ikke tilgængelig endnu."</string>
<string name="screen_welcome_bullet_3">"Vi vil meget gerne høre fra dig. Fortæl os din mening via indstillingssiden."</string>
<string name="screen_welcome_button">"Lad os komme i gang!"</string>
<string name="screen_welcome_subtitle">"Her er, hvad du har brug for at vide:"</string>
<string name="screen_welcome_title">"Velkommen til %1$s!"</string>
</resources>

View file

@ -14,7 +14,7 @@
<string name="screen_notification_optin_title">"Επέτρεψε τις ειδοποιήσεις και μην χάσεις ούτε ένα μήνυμα"</string>
<string name="screen_session_verification_enter_recovery_key">"Εισαγωγή κλειδιού ανάκτησης"</string>
<string name="screen_welcome_bullet_1">"Κλήσεις, δημοσκοπήσεις, αναζήτηση και άλλα, θα προστεθούν αργότερα φέτος."</string>
<string name="screen_welcome_bullet_2">"Το ιστορικό μηνυμάτων για κρυπτογραφημένα δωμάτια δεν είναι ακόμα διαθέσιμο."</string>
<string name="screen_welcome_bullet_2">"Το ιστορικό μηνυμάτων για κρυπτογραφημένες αίθουσες δεν είναι ακόμη διαθέσιμο."</string>
<string name="screen_welcome_bullet_3">"Θα θέλαμε να ακούσουμε τη γνώμη σου, πες μας τη γνώμη σου μέσω της σελίδας ρυθμίσεων."</string>
<string name="screen_welcome_button">"Πάμε!"</string>
<string name="screen_welcome_subtitle">"Να τί πρέπει να ξέρεις:"</string>

View file

@ -9,7 +9,7 @@ plugins {
}
android {
namespace = "io.element.android.features.roomlist.api"
namespace = "io.element.android.features.home.api"
}
dependencies {

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.api
package io.element.android.features.home.api
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
@ -13,7 +13,7 @@ import com.bumble.appyx.core.plugin.Plugin
import io.element.android.libraries.architecture.FeatureEntryPoint
import io.element.android.libraries.matrix.api.core.RoomId
interface RoomListEntryPoint : FeatureEntryPoint {
interface HomeEntryPoint : FeatureEntryPoint {
fun nodeBuilder(parentNode: Node, buildContext: BuildContext): NodeBuilder
interface NodeBuilder {
fun callback(callback: Callback): NodeBuilder

View file

@ -13,7 +13,7 @@ plugins {
}
android {
namespace = "io.element.android.features.roomlist.impl"
namespace = "io.element.android.features.home.impl"
testOptions {
unitTests {
@ -52,7 +52,7 @@ dependencies {
implementation(projects.services.analytics.api)
implementation(libs.androidx.datastore.preferences)
implementation(projects.features.reportroom.api)
api(projects.features.roomlist.api)
api(projects.features.home.api)
testImplementation(libs.androidx.compose.ui.test.junit)
testReleaseImplementation(libs.androidx.compose.ui.test.manifest)

View file

@ -5,30 +5,30 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl
package io.element.android.features.home.impl
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.roomlist.api.RoomListEntryPoint
import io.element.android.features.home.api.HomeEntryPoint
import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.di.AppScope
import javax.inject.Inject
@ContributesBinding(AppScope::class)
class DefaultRoomListEntryPoint @Inject constructor() : RoomListEntryPoint {
override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): RoomListEntryPoint.NodeBuilder {
class DefaultHomeEntryPoint @Inject constructor() : HomeEntryPoint {
override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): HomeEntryPoint.NodeBuilder {
val plugins = ArrayList<Plugin>()
return object : RoomListEntryPoint.NodeBuilder {
override fun callback(callback: RoomListEntryPoint.Callback): RoomListEntryPoint.NodeBuilder {
return object : HomeEntryPoint.NodeBuilder {
override fun callback(callback: HomeEntryPoint.Callback): HomeEntryPoint.NodeBuilder {
plugins += callback
return this
}
override fun build(): Node {
return parentNode.createNode<RoomListFlowNode>(buildContext, plugins)
return parentNode.createNode<HomeFlowNode>(buildContext, plugins)
}
}
}

View file

@ -0,0 +1,10 @@
/*
* Copyright 2025 New Vector 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.home.impl
sealed interface HomeEvents

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl
package io.element.android.features.home.impl
import android.app.Activity
import android.os.Parcelable
@ -24,14 +24,14 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import im.vector.app.features.analytics.plan.MobileScreen
import io.element.android.anvilannotations.ContributesNode
import io.element.android.features.home.api.HomeEntryPoint
import io.element.android.features.home.impl.components.RoomListMenuAction
import io.element.android.features.home.impl.model.RoomListRoomSummary
import io.element.android.features.invite.api.InviteData
import io.element.android.features.invite.api.acceptdecline.AcceptDeclineInviteView
import io.element.android.features.invite.api.declineandblock.DeclineInviteAndBlockEntryPoint
import io.element.android.features.logout.api.direct.DirectLogoutView
import io.element.android.features.reportroom.api.ReportRoomEntryPoint
import io.element.android.features.roomlist.api.RoomListEntryPoint
import io.element.android.features.roomlist.impl.components.RoomListMenuAction
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.libraries.architecture.BackstackView
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.deeplink.usecase.InviteFriendsUseCase
@ -41,17 +41,17 @@ import io.element.android.services.analytics.api.AnalyticsService
import kotlinx.parcelize.Parcelize
@ContributesNode(SessionScope::class)
class RoomListFlowNode @AssistedInject constructor(
class HomeFlowNode @AssistedInject constructor(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
private val presenter: RoomListPresenter,
private val presenter: HomePresenter,
private val inviteFriendsUseCase: InviteFriendsUseCase,
private val analyticsService: AnalyticsService,
private val acceptDeclineInviteView: AcceptDeclineInviteView,
private val directLogoutView: DirectLogoutView,
private val reportRoomEntryPoint: ReportRoomEntryPoint,
private val declineInviteAndBlockUserEntryPoint: DeclineInviteAndBlockEntryPoint,
) : BaseFlowNode<RoomListFlowNode.NavTarget>(
) : BaseFlowNode<HomeFlowNode.NavTarget>(
backstack = BackStack(
initialElement = NavTarget.Root,
savedStateMap = buildContext.savedStateMap,
@ -79,27 +79,27 @@ class RoomListFlowNode @AssistedInject constructor(
}
private fun onRoomClick(roomId: RoomId) {
plugins<RoomListEntryPoint.Callback>().forEach { it.onRoomClick(roomId) }
plugins<HomeEntryPoint.Callback>().forEach { it.onRoomClick(roomId) }
}
private fun onOpenSettings() {
plugins<RoomListEntryPoint.Callback>().forEach { it.onSettingsClick() }
plugins<HomeEntryPoint.Callback>().forEach { it.onSettingsClick() }
}
private fun onCreateRoomClick() {
plugins<RoomListEntryPoint.Callback>().forEach { it.onCreateRoomClick() }
plugins<HomeEntryPoint.Callback>().forEach { it.onCreateRoomClick() }
}
private fun onSetUpRecoveryClick() {
plugins<RoomListEntryPoint.Callback>().forEach { it.onSetUpRecoveryClick() }
plugins<HomeEntryPoint.Callback>().forEach { it.onSetUpRecoveryClick() }
}
private fun onSessionConfirmRecoveryKeyClick() {
plugins<RoomListEntryPoint.Callback>().forEach { it.onSessionConfirmRecoveryKeyClick() }
plugins<HomeEntryPoint.Callback>().forEach { it.onSessionConfirmRecoveryKeyClick() }
}
private fun onRoomSettingsClick(roomId: RoomId) {
plugins<RoomListEntryPoint.Callback>().forEach { it.onRoomSettingsClick(roomId) }
plugins<HomeEntryPoint.Callback>().forEach { it.onRoomSettingsClick(roomId) }
}
private fun onReportRoomClick(roomId: RoomId) {
@ -116,7 +116,7 @@ class RoomListFlowNode @AssistedInject constructor(
inviteFriendsUseCase.execute(activity)
}
RoomListMenuAction.ReportBug -> {
plugins<RoomListEntryPoint.Callback>().forEach { it.onReportBugClick() }
plugins<HomeEntryPoint.Callback>().forEach { it.onReportBugClick() }
}
}
}
@ -126,8 +126,8 @@ class RoomListFlowNode @AssistedInject constructor(
val state = presenter.present()
val activity = requireNotNull(LocalActivity.current)
RoomListView(
state = state,
HomeView(
homeState = state,
onRoomClick = this::onRoomClick,
onSettingsClick = this::onOpenSettings,
onCreateRoomClick = this::onCreateRoomClick,
@ -140,7 +140,7 @@ class RoomListFlowNode @AssistedInject constructor(
modifier = modifier,
) {
acceptDeclineInviteView.Render(
state = state.acceptDeclineInviteState,
state = state.roomListState.acceptDeclineInviteState,
onAcceptInviteSuccess = this::onRoomClick,
onDeclineInviteSuccess = { },
modifier = Modifier

View file

@ -0,0 +1,69 @@
/*
* Copyright 2025 New Vector 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.home.impl
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import io.element.android.features.home.impl.roomlist.RoomListState
import io.element.android.features.logout.api.direct.DirectLogoutState
import io.element.android.features.rageshake.api.RageshakeFeatureAvailability
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState
import io.element.android.libraries.indicator.api.IndicatorService
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.sync.SyncService
import javax.inject.Inject
class HomePresenter @Inject constructor(
private val client: MatrixClient,
private val syncService: SyncService,
private val snackbarDispatcher: SnackbarDispatcher,
private val indicatorService: IndicatorService,
private val roomListPresenter: Presenter<RoomListState>,
private val logoutPresenter: Presenter<DirectLogoutState>,
private val rageshakeFeatureAvailability: RageshakeFeatureAvailability,
) : Presenter<HomeState> {
@Composable
override fun present(): HomeState {
val matrixUser = client.userProfile.collectAsState()
val isOnline by syncService.isOnline.collectAsState()
val canReportBug = remember { rageshakeFeatureAvailability.isAvailable() }
val roomListState = roomListPresenter.present()
LaunchedEffect(Unit) {
// Force a refresh of the profile
client.getUserProfile()
}
// Avatar indicator
val showAvatarIndicator by indicatorService.showRoomListTopBarIndicator()
val directLogoutState = logoutPresenter.present()
fun handleEvents(event: HomeEvents) {
// TODO
}
val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState()
return HomeState(
matrixUser = matrixUser.value,
showAvatarIndicator = showAvatarIndicator,
hasNetworkConnection = isOnline,
roomListState = roomListState,
snackbarMessage = snackbarMessage,
canReportBug = canReportBug,
directLogoutState = directLogoutState,
eventSink = ::handleEvents,
)
}
}

View file

@ -0,0 +1,28 @@
/*
* Copyright 2023, 2024 New Vector 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.home.impl
import androidx.compose.runtime.Immutable
import io.element.android.features.home.impl.roomlist.RoomListState
import io.element.android.features.logout.api.direct.DirectLogoutState
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.matrix.api.user.MatrixUser
@Immutable
data class HomeState(
val matrixUser: MatrixUser,
val showAvatarIndicator: Boolean,
val hasNetworkConnection: Boolean,
val roomListState: RoomListState,
val snackbarMessage: SnackbarMessage?,
val canReportBug: Boolean,
val directLogoutState: DirectLogoutState,
val eventSink: (HomeEvents) -> Unit,
) {
val displayActions = true
}

View file

@ -0,0 +1,50 @@
/*
* Copyright 2025 New Vector 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.home.impl
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.home.impl.roomlist.RoomListState
import io.element.android.features.home.impl.roomlist.RoomListStateProvider
import io.element.android.features.home.impl.roomlist.aRoomListState
import io.element.android.features.logout.api.direct.DirectLogoutState
import io.element.android.features.logout.api.direct.aDirectLogoutState
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.ui.strings.CommonStrings
open class HomeStateProvider : PreviewParameterProvider<HomeState> {
override val values: Sequence<HomeState>
get() = sequenceOf(
aHomeState(),
aHomeState(hasNetworkConnection = false),
aHomeState(snackbarMessage = SnackbarMessage(CommonStrings.common_verification_complete)),
) + RoomListStateProvider().values.map {
aHomeState(roomListState = it)
}
}
internal fun aHomeState(
matrixUser: MatrixUser = MatrixUser(userId = UserId("@id:domain"), displayName = "User#1"),
showAvatarIndicator: Boolean = false,
hasNetworkConnection: Boolean = true,
snackbarMessage: SnackbarMessage? = null,
roomListState: RoomListState = aRoomListState(),
canReportBug: Boolean = true,
directLogoutState: DirectLogoutState = aDirectLogoutState(),
eventSink: (HomeEvents) -> Unit = {}
) = HomeState(
matrixUser = matrixUser,
showAvatarIndicator = showAvatarIndicator,
hasNetworkConnection = hasNetworkConnection,
snackbarMessage = snackbarMessage,
canReportBug = canReportBug,
directLogoutState = directLogoutState,
roomListState = roomListState,
eventSink = eventSink,
)

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl
package io.element.android.features.home.impl
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
@ -25,13 +25,17 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.features.home.impl.components.RoomListContentView
import io.element.android.features.home.impl.components.RoomListMenuAction
import io.element.android.features.home.impl.components.RoomListTopBar
import io.element.android.features.home.impl.model.RoomListRoomSummary
import io.element.android.features.home.impl.roomlist.RoomListContextMenu
import io.element.android.features.home.impl.roomlist.RoomListDeclineInviteMenu
import io.element.android.features.home.impl.roomlist.RoomListEvents
import io.element.android.features.home.impl.roomlist.RoomListState
import io.element.android.features.home.impl.search.RoomListSearchView
import io.element.android.features.leaveroom.api.LeaveRoomView
import io.element.android.features.networkmonitor.api.ui.ConnectivityIndicatorContainer
import io.element.android.features.roomlist.impl.components.RoomListContentView
import io.element.android.features.roomlist.impl.components.RoomListMenuAction
import io.element.android.features.roomlist.impl.components.RoomListTopBar
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.features.roomlist.impl.search.RoomListSearchView
import io.element.android.libraries.androidutils.throttler.FirstThrottler
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
@ -43,8 +47,8 @@ import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbar
import io.element.android.libraries.matrix.api.core.RoomId
@Composable
fun RoomListView(
state: RoomListState,
fun HomeView(
homeState: HomeState,
onRoomClick: (RoomId) -> Unit,
onSettingsClick: () -> Unit,
onSetUpRecoveryClick: () -> Unit,
@ -57,12 +61,13 @@ fun RoomListView(
modifier: Modifier = Modifier,
acceptDeclineInviteView: @Composable () -> Unit,
) {
val state: RoomListState = homeState.roomListState
val coroutineScope = rememberCoroutineScope()
val firstThrottler = remember { FirstThrottler(300, coroutineScope) }
ConnectivityIndicatorContainer(
modifier = modifier,
isOnline = state.hasNetworkConnection,
isOnline = homeState.hasNetworkConnection,
) { topPadding ->
Box {
if (state.contextMenu is RoomListState.ContextMenu.Shown) {
@ -85,8 +90,8 @@ fun RoomListView(
LeaveRoomView(state = state.leaveRoomState)
RoomListScaffold(
state = state,
HomeScaffold(
state = homeState,
onSetUpRecoveryClick = onSetUpRecoveryClick,
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
onRoomClick = { if (firstThrottler.canHandle()) onRoomClick(it) },
@ -114,8 +119,8 @@ fun RoomListView(
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun RoomListScaffold(
state: RoomListState,
private fun HomeScaffold(
state: HomeState,
onSetUpRecoveryClick: () -> Unit,
onConfirmRecoveryKeyClick: () -> Unit,
onRoomClick: (RoomId) -> Unit,
@ -131,6 +136,7 @@ private fun RoomListScaffold(
val appBarState = rememberTopAppBarState()
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(appBarState)
val snackbarHostState = rememberSnackbarHostState(snackbarMessage = state.snackbarMessage)
val roomListState: RoomListState = state.roomListState
Scaffold(
modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
@ -138,23 +144,23 @@ private fun RoomListScaffold(
RoomListTopBar(
matrixUser = state.matrixUser,
showAvatarIndicator = state.showAvatarIndicator,
areSearchResultsDisplayed = state.searchState.isSearchActive,
onToggleSearch = { state.eventSink(RoomListEvents.ToggleSearchResults) },
areSearchResultsDisplayed = roomListState.searchState.isSearchActive,
onToggleSearch = { roomListState.eventSink(RoomListEvents.ToggleSearchResults) },
onMenuActionClick = onMenuActionClick,
onOpenSettings = onOpenSettings,
scrollBehavior = scrollBehavior,
displayMenuItems = state.displayActions,
displayFilters = state.displayFilters,
filtersState = state.filtersState,
displayFilters = roomListState.displayFilters,
filtersState = roomListState.filtersState,
canReportBug = state.canReportBug,
)
},
content = { padding ->
RoomListContentView(
contentState = state.contentState,
filtersState = state.filtersState,
hideInvitesAvatars = state.hideInvitesAvatars,
eventSink = state.eventSink,
contentState = roomListState.contentState,
filtersState = roomListState.filtersState,
hideInvitesAvatars = roomListState.hideInvitesAvatars,
eventSink = roomListState.eventSink,
onSetUpRecoveryClick = onSetUpRecoveryClick,
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
onRoomClick = ::onRoomClick,
@ -186,9 +192,9 @@ internal fun RoomListRoomSummary.contentType() = displayType.ordinal
@PreviewsDayNight
@Composable
internal fun RoomListViewPreview(@PreviewParameter(RoomListStateProvider::class) state: RoomListState) = ElementPreview {
RoomListView(
state = state,
internal fun HomeViewPreview(@PreviewParameter(HomeStateProvider::class) state: HomeState) = ElementPreview {
HomeView(
homeState = state,
onRoomClick = {},
onSettingsClick = {},
onSetUpRecoveryClick = {},

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.components
package io.element.android.features.home.impl.components
import androidx.compose.foundation.layout.padding
import androidx.compose.ui.Modifier

View file

@ -5,12 +5,12 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.components
package io.element.android.features.home.impl.components
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import io.element.android.features.roomlist.impl.R
import io.element.android.features.home.impl.R
import io.element.android.libraries.designsystem.components.Announcement
import io.element.android.libraries.designsystem.components.AnnouncementType
import io.element.android.libraries.designsystem.preview.ElementPreview

View file

@ -5,12 +5,12 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.components
package io.element.android.features.home.impl.components
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import io.element.android.features.roomlist.impl.R
import io.element.android.features.home.impl.R
import io.element.android.libraries.designsystem.components.Announcement
import io.element.android.libraries.designsystem.components.AnnouncementType
import io.element.android.libraries.designsystem.preview.ElementPreview

View file

@ -5,12 +5,12 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.components
package io.element.android.features.home.impl.components
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import io.element.android.features.roomlist.impl.R
import io.element.android.features.home.impl.R
import io.element.android.libraries.designsystem.components.Announcement
import io.element.android.libraries.designsystem.components.AnnouncementType
import io.element.android.libraries.designsystem.preview.ElementPreview

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.components
package io.element.android.features.home.impl.components
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Arrangement
@ -34,19 +34,19 @@ 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.roomlist.impl.R
import io.element.android.features.roomlist.impl.RoomListContentState
import io.element.android.features.roomlist.impl.RoomListContentStateProvider
import io.element.android.features.roomlist.impl.RoomListEvents
import io.element.android.features.roomlist.impl.SecurityBannerState
import io.element.android.features.roomlist.impl.contentType
import io.element.android.features.roomlist.impl.filters.RoomListFilter
import io.element.android.features.roomlist.impl.filters.RoomListFiltersEmptyStateResources
import io.element.android.features.roomlist.impl.filters.RoomListFiltersState
import io.element.android.features.roomlist.impl.filters.aRoomListFiltersState
import io.element.android.features.roomlist.impl.filters.selection.FilterSelectionState
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.features.roomlist.impl.model.RoomSummaryDisplayType
import io.element.android.features.home.impl.R
import io.element.android.features.home.impl.contentType
import io.element.android.features.home.impl.filters.RoomListFilter
import io.element.android.features.home.impl.filters.RoomListFiltersEmptyStateResources
import io.element.android.features.home.impl.filters.RoomListFiltersState
import io.element.android.features.home.impl.filters.aRoomListFiltersState
import io.element.android.features.home.impl.filters.selection.FilterSelectionState
import io.element.android.features.home.impl.model.RoomListRoomSummary
import io.element.android.features.home.impl.model.RoomSummaryDisplayType
import io.element.android.features.home.impl.roomlist.RoomListContentState
import io.element.android.features.home.impl.roomlist.RoomListContentStateProvider
import io.element.android.features.home.impl.roomlist.RoomListEvents
import io.element.android.features.home.impl.roomlist.SecurityBannerState
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Button
@ -311,7 +311,12 @@ internal fun RoomListContentViewPreview(@PreviewParameter(RoomListContentStatePr
RoomListContentView(
contentState = state,
filtersState = aRoomListFiltersState(
filterSelectionStates = RoomListFilter.entries.map { FilterSelectionState(it, isSelected = true) }
filterSelectionStates = RoomListFilter.entries.map {
FilterSelectionState(
filter = it,
isSelected = true
)
}
),
hideInvitesAvatars = false,
eventSink = {},

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.components
package io.element.android.features.home.impl.components
enum class RoomListMenuAction {
InviteFriends,

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.components
package io.element.android.features.home.impl.components
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@ -40,10 +40,10 @@ import androidx.compose.ui.unit.dp
import io.element.android.appconfig.RoomListConfig
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.features.roomlist.impl.R
import io.element.android.features.roomlist.impl.filters.RoomListFiltersState
import io.element.android.features.roomlist.impl.filters.RoomListFiltersView
import io.element.android.features.roomlist.impl.filters.aRoomListFiltersState
import io.element.android.features.home.impl.R
import io.element.android.features.home.impl.filters.RoomListFiltersState
import io.element.android.features.home.impl.filters.RoomListFiltersView
import io.element.android.features.home.impl.filters.aRoomListFiltersState
import io.element.android.libraries.designsystem.atomic.atoms.RedIndicatorAtom
import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarData

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.components
package io.element.android.features.home.impl.components
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.components
package io.element.android.features.home.impl.components
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.interaction.MutableInteractionSource
@ -37,11 +37,11 @@ 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.roomlist.impl.R
import io.element.android.features.roomlist.impl.RoomListEvents
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.features.roomlist.impl.model.RoomListRoomSummaryProvider
import io.element.android.features.roomlist.impl.model.RoomSummaryDisplayType
import io.element.android.features.home.impl.R
import io.element.android.features.home.impl.model.RoomListRoomSummary
import io.element.android.features.home.impl.model.RoomListRoomSummaryProvider
import io.element.android.features.home.impl.model.RoomSummaryDisplayType
import io.element.android.features.home.impl.roomlist.RoomListEvents
import io.element.android.libraries.core.extensions.orEmpty
import io.element.android.libraries.designsystem.atomic.atoms.UnreadIndicatorAtom
import io.element.android.libraries.designsystem.components.avatar.Avatar

View file

@ -5,12 +5,12 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.components
package io.element.android.features.home.impl.components
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import io.element.android.features.roomlist.impl.R
import io.element.android.features.home.impl.R
import io.element.android.libraries.designsystem.components.Announcement
import io.element.android.libraries.designsystem.components.AnnouncementType
import io.element.android.libraries.designsystem.preview.ElementPreview

View file

@ -5,9 +5,9 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.datasource
package io.element.android.features.home.impl.datasource
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.features.home.impl.model.RoomListRoomSummary
import io.element.android.libraries.androidutils.diff.DiffCacheUpdater
import io.element.android.libraries.androidutils.diff.MutableListDiffCache
import io.element.android.libraries.androidutils.system.DateTimeObserver

View file

@ -5,10 +5,10 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.datasource
package io.element.android.features.home.impl.datasource
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.features.roomlist.impl.model.RoomSummaryDisplayType
import io.element.android.features.home.impl.model.RoomListRoomSummary
import io.element.android.features.home.impl.model.RoomSummaryDisplayType
import io.element.android.libraries.core.extensions.orEmpty
import io.element.android.libraries.dateformatter.api.DateFormatter
import io.element.android.libraries.dateformatter.api.DateFormatterMode

View file

@ -5,21 +5,26 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.di
package io.element.android.features.home.impl.di
import com.squareup.anvil.annotations.ContributesTo
import dagger.Binds
import dagger.Module
import io.element.android.features.roomlist.impl.filters.RoomListFiltersPresenter
import io.element.android.features.roomlist.impl.filters.RoomListFiltersState
import io.element.android.features.roomlist.impl.search.RoomListSearchPresenter
import io.element.android.features.roomlist.impl.search.RoomListSearchState
import io.element.android.features.home.impl.filters.RoomListFiltersPresenter
import io.element.android.features.home.impl.filters.RoomListFiltersState
import io.element.android.features.home.impl.roomlist.RoomListPresenter
import io.element.android.features.home.impl.roomlist.RoomListState
import io.element.android.features.home.impl.search.RoomListSearchPresenter
import io.element.android.features.home.impl.search.RoomListSearchState
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.di.SessionScope
@ContributesTo(SessionScope::class)
@Module
interface RoomListModule {
@Binds
fun bindRoomListPresenter(presenter: RoomListPresenter): Presenter<RoomListState>
@Binds
fun bindSearchPresenter(presenter: RoomListSearchPresenter): Presenter<RoomListSearchState>

View file

@ -5,9 +5,9 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.filters
package io.element.android.features.home.impl.filters
import io.element.android.features.roomlist.impl.R
import io.element.android.features.home.impl.R
/**
* Enum class representing the different filters that can be applied to the room list.

View file

@ -5,10 +5,10 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.filters
package io.element.android.features.home.impl.filters
import androidx.annotation.StringRes
import io.element.android.features.roomlist.impl.R
import io.element.android.features.home.impl.R
/**
* Holds the resources for the empty state when filters are applied to the room list.

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.filters
package io.element.android.features.home.impl.filters
sealed interface RoomListFiltersEvents {
data class ToggleFilter(val filter: RoomListFilter) : RoomListFiltersEvents

View file

@ -5,12 +5,12 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.filters
package io.element.android.features.home.impl.filters
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
import io.element.android.features.roomlist.impl.filters.selection.FilterSelectionStrategy
import io.element.android.features.home.impl.filters.selection.FilterSelectionStrategy
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import kotlinx.collections.immutable.toPersistentList

View file

@ -5,9 +5,9 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.filters
package io.element.android.features.home.impl.filters
import io.element.android.features.roomlist.impl.filters.selection.FilterSelectionState
import io.element.android.features.home.impl.filters.selection.FilterSelectionState
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList

View file

@ -5,10 +5,10 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.filters
package io.element.android.features.home.impl.filters
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.roomlist.impl.filters.selection.FilterSelectionState
import io.element.android.features.home.impl.filters.selection.FilterSelectionState
import kotlinx.collections.immutable.toImmutableList
class RoomListFiltersStateProvider : PreviewParameterProvider<RoomListFiltersState> {

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.filters
package io.element.android.features.home.impl.filters
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.Spring
@ -40,6 +40,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.features.home.impl.R
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
@ -147,7 +148,7 @@ private fun RoomListClearFiltersButton(
modifier = Modifier.align(Alignment.Center),
imageVector = CompoundIcons.Close(),
tint = ElementTheme.colors.iconOnSolidPrimary,
contentDescription = stringResource(id = io.element.android.libraries.ui.strings.R.string.action_clear),
contentDescription = stringResource(id = R.string.screen_roomlist_clear_filters),
)
}
}

View file

@ -5,10 +5,10 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.filters.selection
package io.element.android.features.home.impl.filters.selection
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.roomlist.impl.filters.RoomListFilter
import io.element.android.features.home.impl.filters.RoomListFilter
import io.element.android.libraries.di.SessionScope
import kotlinx.coroutines.flow.MutableStateFlow
import javax.inject.Inject

View file

@ -5,9 +5,9 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.filters.selection
package io.element.android.features.home.impl.filters.selection
import io.element.android.features.roomlist.impl.filters.RoomListFilter
import io.element.android.features.home.impl.filters.RoomListFilter
data class FilterSelectionState(
val filter: RoomListFilter,

View file

@ -5,9 +5,9 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.filters.selection
package io.element.android.features.home.impl.filters.selection
import io.element.android.features.roomlist.impl.filters.RoomListFilter
import io.element.android.features.home.impl.filters.RoomListFilter
import kotlinx.coroutines.flow.StateFlow
interface FilterSelectionStrategy {

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.model
package io.element.android.features.home.impl.model
import androidx.compose.runtime.Immutable
import io.element.android.features.invite.api.InviteData

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.model
package io.element.android.features.home.impl.model
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.designsystem.components.avatar.AvatarData

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.model
package io.element.android.features.home.impl.model
/**
* Represents the type of display for a room list item.

View file

@ -5,10 +5,10 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl
package io.element.android.features.home.impl.roomlist
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.features.home.impl.model.RoomListRoomSummary
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
import io.element.android.libraries.fullscreenintent.api.aFullScreenIntentPermissionsState
import io.element.android.libraries.matrix.api.core.RoomId

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl
package io.element.android.features.home.impl.roomlist
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
@ -19,6 +19,7 @@ import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.tooling.preview.PreviewParameter
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.features.home.impl.R
import io.element.android.libraries.designsystem.components.list.ListItemContent
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl
package io.element.android.features.home.impl.roomlist
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
@ -20,7 +20,8 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.features.home.impl.R
import io.element.android.features.home.impl.model.RoomListRoomSummary
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Button

View file

@ -5,9 +5,9 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl
package io.element.android.features.home.impl.roomlist
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.features.home.impl.model.RoomListRoomSummary
import io.element.android.libraries.matrix.api.core.RoomId
sealed interface RoomListEvents {

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl
package io.element.android.features.home.impl.roomlist
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@ -23,18 +23,16 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import im.vector.app.features.analytics.plan.Interaction
import io.element.android.features.home.impl.datasource.RoomListDataSource
import io.element.android.features.home.impl.filters.RoomListFiltersState
import io.element.android.features.home.impl.search.RoomListSearchEvents
import io.element.android.features.home.impl.search.RoomListSearchState
import io.element.android.features.invite.api.SeenInvitesStore
import io.element.android.features.invite.api.acceptdecline.AcceptDeclineInviteEvents.AcceptInvite
import io.element.android.features.invite.api.acceptdecline.AcceptDeclineInviteEvents.DeclineInvite
import io.element.android.features.invite.api.acceptdecline.AcceptDeclineInviteState
import io.element.android.features.leaveroom.api.LeaveRoomEvent.ShowConfirmation
import io.element.android.features.leaveroom.api.LeaveRoomState
import io.element.android.features.logout.api.direct.DirectLogoutState
import io.element.android.features.rageshake.api.RageshakeFeatureAvailability
import io.element.android.features.roomlist.impl.datasource.RoomListDataSource
import io.element.android.features.roomlist.impl.filters.RoomListFiltersState
import io.element.android.features.roomlist.impl.search.RoomListSearchEvents
import io.element.android.features.roomlist.impl.search.RoomListSearchState
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.coroutine.mapState
@ -43,13 +41,11 @@ import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarM
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
import io.element.android.libraries.indicator.api.IndicatorService
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.encryption.RecoveryState
import io.element.android.libraries.matrix.api.roomlist.RoomList
import io.element.android.libraries.matrix.api.sync.SyncService
import io.element.android.libraries.matrix.api.timeline.ReceiptType
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import io.element.android.libraries.preferences.api.store.SessionPreferencesStore
@ -78,12 +74,9 @@ private const val SUBSCRIBE_TO_VISIBLE_ROOMS_DEBOUNCE_IN_MILLIS = 300L
class RoomListPresenter @Inject constructor(
private val client: MatrixClient,
private val syncService: SyncService,
private val snackbarDispatcher: SnackbarDispatcher,
private val leaveRoomPresenter: Presenter<LeaveRoomState>,
private val roomListDataSource: RoomListDataSource,
private val featureFlagService: FeatureFlagService,
private val indicatorService: IndicatorService,
private val filtersPresenter: Presenter<RoomListFiltersState>,
private val searchPresenter: Presenter<RoomListSearchState>,
private val sessionPreferencesStore: SessionPreferencesStore,
@ -92,9 +85,7 @@ class RoomListPresenter @Inject constructor(
private val fullScreenIntentPermissionsPresenter: Presenter<FullScreenIntentPermissionsState>,
private val batteryOptimizationPresenter: Presenter<BatteryOptimizationState>,
private val notificationCleaner: NotificationCleaner,
private val logoutPresenter: Presenter<DirectLogoutState>,
private val appPreferencesStore: AppPreferencesStore,
private val rageshakeFeatureAvailability: RageshakeFeatureAvailability,
private val seenInvitesStore: SeenInvitesStore,
) : Presenter<RoomListState> {
private val encryptionService: EncryptionService = client.encryptionService()
@ -103,23 +94,17 @@ class RoomListPresenter @Inject constructor(
override fun present(): RoomListState {
val coroutineScope = rememberCoroutineScope()
val leaveRoomState = leaveRoomPresenter.present()
val matrixUser = client.userProfile.collectAsState()
val isOnline by syncService.isOnline.collectAsState()
val filtersState = filtersPresenter.present()
val searchState = searchPresenter.present()
val acceptDeclineInviteState = acceptDeclineInvitePresenter.present()
val canReportBug = remember { rageshakeFeatureAvailability.isAvailable() }
LaunchedEffect(Unit) {
roomListDataSource.launchIn(this)
// Force a refresh of the profile
client.getUserProfile()
}
var securityBannerDismissed by rememberSaveable { mutableStateOf(false) }
// Avatar indicator
val showAvatarIndicator by indicatorService.showRoomListTopBarIndicator()
val hideInvitesAvatar by remember {
client
.mediaPreviewService()
@ -130,8 +115,6 @@ class RoomListPresenter @Inject constructor(
val contextMenu = remember { mutableStateOf<RoomListState.ContextMenu>(RoomListState.ContextMenu.Hidden) }
val declineInviteMenu = remember { mutableStateOf<RoomListState.DeclineInviteMenu>(RoomListState.DeclineInviteMenu.Hidden) }
val directLogoutState = logoutPresenter.present()
fun handleEvents(event: RoomListEvents) {
when (event) {
is RoomListEvents.UpdateVisibleRange -> coroutineScope.launch {
@ -166,26 +149,18 @@ class RoomListPresenter @Inject constructor(
}
}
val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState()
val contentState = roomListContentState(securityBannerDismissed)
val canReportRoom by produceState(false) { value = client.canReportRoom() }
return RoomListState(
matrixUser = matrixUser.value,
showAvatarIndicator = showAvatarIndicator,
snackbarMessage = snackbarMessage,
hasNetworkConnection = isOnline,
contextMenu = contextMenu.value,
declineInviteMenu = declineInviteMenu.value,
leaveRoomState = leaveRoomState,
filtersState = filtersState,
canReportBug = canReportBug,
searchState = searchState,
contentState = contentState,
acceptDeclineInviteState = acceptDeclineInviteState,
directLogoutState = directLogoutState,
hideInvitesAvatars = hideInvitesAvatar,
canReportRoom = canReportRoom,
eventSink = ::handleEvents,

View file

@ -5,44 +5,34 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl
package io.element.android.features.home.impl.roomlist
import androidx.compose.runtime.Immutable
import io.element.android.features.home.impl.filters.RoomListFiltersState
import io.element.android.features.home.impl.model.RoomListRoomSummary
import io.element.android.features.home.impl.search.RoomListSearchState
import io.element.android.features.invite.api.acceptdecline.AcceptDeclineInviteState
import io.element.android.features.leaveroom.api.LeaveRoomState
import io.element.android.features.logout.api.direct.DirectLogoutState
import io.element.android.features.roomlist.impl.filters.RoomListFiltersState
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.features.roomlist.impl.search.RoomListSearchState
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.push.api.battery.BatteryOptimizationState
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.ImmutableSet
@Immutable
data class RoomListState(
val matrixUser: MatrixUser,
val showAvatarIndicator: Boolean,
val hasNetworkConnection: Boolean,
val snackbarMessage: SnackbarMessage?,
val contextMenu: ContextMenu,
val declineInviteMenu: DeclineInviteMenu,
val leaveRoomState: LeaveRoomState,
val filtersState: RoomListFiltersState,
val canReportBug: Boolean,
val searchState: RoomListSearchState,
val contentState: RoomListContentState,
val acceptDeclineInviteState: AcceptDeclineInviteState,
val directLogoutState: DirectLogoutState,
val hideInvitesAvatars: Boolean,
val canReportRoom: Boolean,
val eventSink: (RoomListEvents) -> Unit,
) {
val displayFilters = contentState is RoomListContentState.Rooms
val displayActions = true
sealed interface ContextMenu {
data object Hidden : ContextMenu

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl
package io.element.android.features.home.impl.roomlist
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.matrix.api.core.RoomId

View file

@ -5,32 +5,26 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl
package io.element.android.features.home.impl.roomlist
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.home.impl.filters.RoomListFiltersState
import io.element.android.features.home.impl.filters.aRoomListFiltersState
import io.element.android.features.home.impl.model.RoomListRoomSummary
import io.element.android.features.home.impl.model.RoomSummaryDisplayType
import io.element.android.features.home.impl.model.aRoomListRoomSummary
import io.element.android.features.home.impl.model.anInviteSender
import io.element.android.features.home.impl.search.RoomListSearchState
import io.element.android.features.home.impl.search.aRoomListSearchState
import io.element.android.features.invite.api.acceptdecline.AcceptDeclineInviteEvents
import io.element.android.features.invite.api.acceptdecline.AcceptDeclineInviteState
import io.element.android.features.leaveroom.api.LeaveRoomState
import io.element.android.features.leaveroom.api.aLeaveRoomState
import io.element.android.features.logout.api.direct.DirectLogoutState
import io.element.android.features.logout.api.direct.aDirectLogoutState
import io.element.android.features.roomlist.impl.filters.RoomListFiltersState
import io.element.android.features.roomlist.impl.filters.aRoomListFiltersState
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.features.roomlist.impl.model.RoomSummaryDisplayType
import io.element.android.features.roomlist.impl.model.aRoomListRoomSummary
import io.element.android.features.roomlist.impl.model.anInviteSender
import io.element.android.features.roomlist.impl.search.RoomListSearchState
import io.element.android.features.roomlist.impl.search.aRoomListSearchState
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.push.api.battery.aBatteryOptimizationState
import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
@ -38,8 +32,6 @@ open class RoomListStateProvider : PreviewParameterProvider<RoomListState> {
override val values: Sequence<RoomListState>
get() = sequenceOf(
aRoomListState(),
aRoomListState(snackbarMessage = SnackbarMessage(CommonStrings.common_verification_complete)),
aRoomListState(hasNetworkConnection = false),
aRoomListState(contextMenu = aContextMenuShown(roomName = null)),
aRoomListState(contextMenu = aContextMenuShown(roomName = "A nice room name")),
aRoomListState(contextMenu = aContextMenuShown(isFavorite = true)),
@ -53,36 +45,24 @@ open class RoomListStateProvider : PreviewParameterProvider<RoomListState> {
}
internal fun aRoomListState(
matrixUser: MatrixUser = MatrixUser(userId = UserId("@id:domain"), displayName = "User#1"),
showAvatarIndicator: Boolean = false,
hasNetworkConnection: Boolean = true,
snackbarMessage: SnackbarMessage? = null,
contextMenu: RoomListState.ContextMenu = RoomListState.ContextMenu.Hidden,
declineInviteMenu: RoomListState.DeclineInviteMenu = RoomListState.DeclineInviteMenu.Hidden,
leaveRoomState: LeaveRoomState = aLeaveRoomState(),
searchState: RoomListSearchState = aRoomListSearchState(),
filtersState: RoomListFiltersState = aRoomListFiltersState(),
canReportBug: Boolean = true,
contentState: RoomListContentState = aRoomsContentState(),
acceptDeclineInviteState: AcceptDeclineInviteState = anAcceptDeclineInviteState(),
directLogoutState: DirectLogoutState = aDirectLogoutState(),
hideInvitesAvatars: Boolean = false,
canReportRoom: Boolean = true,
eventSink: (RoomListEvents) -> Unit = {}
) = RoomListState(
matrixUser = matrixUser,
showAvatarIndicator = showAvatarIndicator,
hasNetworkConnection = hasNetworkConnection,
snackbarMessage = snackbarMessage,
contextMenu = contextMenu,
declineInviteMenu = declineInviteMenu,
leaveRoomState = leaveRoomState,
filtersState = filtersState,
canReportBug = canReportBug,
searchState = searchState,
contentState = contentState,
acceptDeclineInviteState = acceptDeclineInviteState,
directLogoutState = directLogoutState,
hideInvitesAvatars = hideInvitesAvatars,
canReportRoom = canReportRoom,
eventSink = eventSink,

View file

@ -5,10 +5,10 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.search
package io.element.android.features.home.impl.search
import io.element.android.features.roomlist.impl.datasource.RoomListRoomSummaryFactory
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.features.home.impl.datasource.RoomListRoomSummaryFactory
import io.element.android.features.home.impl.model.RoomListRoomSummary
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.matrix.api.roomlist.RoomList
import io.element.android.libraries.matrix.api.roomlist.RoomListFilter

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.search
package io.element.android.features.home.impl.search
sealed interface RoomListSearchEvents {
data object ToggleSearchVisibility : RoomListSearchEvents

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.search
package io.element.android.features.home.impl.search
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect

View file

@ -5,9 +5,9 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.search
package io.element.android.features.home.impl.search
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.features.home.impl.model.RoomListRoomSummary
import kotlinx.collections.immutable.ImmutableList
data class RoomListSearchState(

View file

@ -5,11 +5,11 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.search
package io.element.android.features.home.impl.search
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.roomlist.impl.aRoomListRoomSummaryList
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.features.home.impl.model.RoomListRoomSummary
import io.element.android.features.home.impl.roomlist.aRoomListRoomSummaryList
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf

View file

@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.search
package io.element.android.features.home.impl.search
import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedVisibility
@ -34,10 +34,10 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.features.roomlist.impl.RoomListEvents
import io.element.android.features.roomlist.impl.components.RoomSummaryRow
import io.element.android.features.roomlist.impl.contentType
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.features.home.impl.components.RoomSummaryRow
import io.element.android.features.home.impl.contentType
import io.element.android.features.home.impl.model.RoomListRoomSummary
import io.element.android.features.home.impl.roomlist.RoomListEvents
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.modifiers.applyIf
import io.element.android.libraries.designsystem.preview.ElementPreview

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="confirm_recovery_key_banner_message">"Потвърдете ключа си за възстановяване, за да запазите достъп до хранилището за ключове и историята на съобщенията си."</string>
<string name="confirm_recovery_key_banner_primary_button_title">"Въведете ключа си за възстановяване"</string>
<string name="confirm_recovery_key_banner_title">"Хранилището ви за ключове не е синхронизирано"</string>
<string name="screen_invites_decline_chat_message">"Сигурни ли сте, че искате да отхвърлите поканата за присъединяване в %1$s?"</string>
<string name="screen_invites_decline_chat_title">"Отказване на покана"</string>
<string name="screen_invites_empty_list">"Няма покани"</string>
<string name="screen_invites_invited_you">"%1$s (%2$s) ви покани"</string>
<string name="screen_roomlist_a11y_create_message">"Създаване на нов разговор или стая"</string>
<string name="screen_roomlist_empty_message">"Започнете, като изпратите съобщение на някого."</string>
<string name="screen_roomlist_empty_title">"Все още няма чатове."</string>
<string name="screen_roomlist_filter_favourites">"Любими"</string>
<string name="screen_roomlist_filter_favourites_empty_state_subtitle">"Можете да добавите чат към фаворизираните си в настройките на чата.
Засега можете да премахнете избора на филтрите, за да видите другите си чатове."</string>
<string name="screen_roomlist_filter_favourites_empty_state_title">"Все още нямате фаворизирани чатове"</string>
<string name="screen_roomlist_filter_invites">"Покани"</string>
<string name="screen_roomlist_filter_invites_empty_state_title">"Нямате чакащи покани."</string>
<string name="screen_roomlist_filter_low_priority">"Нисък приоритет"</string>
<string name="screen_roomlist_filter_mixed_empty_state_subtitle">"Можете да премахнете избора на филтрите, за да видите другите си чатове"</string>
<string name="screen_roomlist_filter_people">"Хора"</string>
<string name="screen_roomlist_filter_people_empty_state_title">"Все още нямате директни съобщения"</string>
<string name="screen_roomlist_filter_rooms">"Стаи"</string>
<string name="screen_roomlist_filter_rooms_empty_state_title">"Все още не сте в никоя стая"</string>
<string name="screen_roomlist_filter_unreads">"Непрочетени"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Поздравления!
Нямате непрочетени съобщения!"</string>
<string name="screen_roomlist_main_space_title">"Всички чатове"</string>
<string name="screen_roomlist_mark_as_read">"Отбелязване като прочетено"</string>
<string name="screen_roomlist_mark_as_unread">"Отбелязване като непрочетено"</string>
<string name="session_verification_banner_message">"Изглежда, че използвате ново устройство. Потвърдете с друго устройство за достъп до вашите шифровани съобщения."</string>
<string name="session_verification_banner_title">"Потвърдете, че сте вие"</string>
</resources>

View file

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="banner_battery_optimization_content_android">"Zakažte optimalizaci baterie pro tuto aplikaci, abyste měli jistotu, že budou přijata všechna oznámení."</string>
<string name="banner_battery_optimization_submit_android">"Zakázat optimalizaci"</string>
<string name="banner_battery_optimization_title_android">"Nepřicházejí vám oznámení?"</string>
<string name="banner_set_up_recovery_content">"Vygenerujte nový klíč pro obnovení, který lze použít k obnovení historie šifrovaných zpráv v případě, že ztratíte přístup ke svým zařízením."</string>
<string name="banner_set_up_recovery_submit">"Nastavení obnovy"</string>
<string name="banner_set_up_recovery_title">"Nastavení obnovy"</string>

View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="banner_battery_optimization_content_android">"Deaktiver batterioptimering for denne app for at sikre, at alle notifikationer dukker op."</string>
<string name="banner_battery_optimization_submit_android">"Deaktivér optimering"</string>
<string name="banner_battery_optimization_title_android">"Modtager du ikke notifikationer?"</string>
<string name="banner_set_up_recovery_content">"Gendan din kryptografiske identitet og meddelelseshistorik med en gendannelsesnøgle, hvis du har mistet alle dine eksisterende enheder."</string>
<string name="banner_set_up_recovery_submit">"Opsæt gendannelse"</string>
<string name="banner_set_up_recovery_title">"Konfigurer gendannelse for at beskytte din konto"</string>
<string name="confirm_recovery_key_banner_message">"Bekræft din gendannelsesnøgle for at bevare adgangen til nøglelager og meddelelseshistorik."</string>
<string name="confirm_recovery_key_banner_primary_button_title">"Indtast din gendannelsesnøgle"</string>
<string name="confirm_recovery_key_banner_secondary_button_title">"Har du glemt din gendannelsesnøgle?"</string>
<string name="confirm_recovery_key_banner_title">"Dit nøglelager er ikke synkroniseret"</string>
<string name="full_screen_intent_banner_message">"For at sikre, at du aldrig går glip af et vigtigt opkald, skal du ændre dine indstillinger til at tillade underretninger i fuld skærm, når din telefon er låst."</string>
<string name="full_screen_intent_banner_title">"Gør din opkaldsoplevelse bedre"</string>
<string name="screen_invites_decline_chat_message">"Er du sikker på, at du vil afvise invitationen til at deltage i %1$s?"</string>
<string name="screen_invites_decline_chat_title">"Afvis invitation"</string>
<string name="screen_invites_decline_direct_chat_message">"Er du sikker på, at du vil afvise denne private samtale med %1$s?"</string>
<string name="screen_invites_decline_direct_chat_title">"Afvis samtale"</string>
<string name="screen_invites_empty_list">"Ingen invitationer"</string>
<string name="screen_invites_invited_you">"%1$s(%2$s ) inviterede dig"</string>
<string name="screen_migration_message">"Dette er en engangsproces, tak for din tålmodighed."</string>
<string name="screen_migration_title">"Sætter din konto op."</string>
<string name="screen_roomlist_a11y_create_message">"Opret en ny samtale eller et nyt rum"</string>
<string name="screen_roomlist_empty_message">"Kom i gang ved at sende en besked til nogen."</string>
<string name="screen_roomlist_empty_title">"Ingen samtaler endnu."</string>
<string name="screen_roomlist_filter_favourites">"Favoritter"</string>
<string name="screen_roomlist_filter_favourites_empty_state_subtitle">"Du kan tilføje en samtale til dine favoritter i samtaleindstillingerne.
For nu kan du fravælge filtre for at se dine andre samtaler"</string>
<string name="screen_roomlist_filter_favourites_empty_state_title">"Du har endnu ingen foretrukne samtaler"</string>
<string name="screen_roomlist_filter_invites">"Invitationer"</string>
<string name="screen_roomlist_filter_invites_empty_state_title">"Du har ingen afventende invitationer."</string>
<string name="screen_roomlist_filter_low_priority">"Lav prioritet"</string>
<string name="screen_roomlist_filter_mixed_empty_state_subtitle">"Du kan fravælge filtre for at se dine andre samtaler"</string>
<string name="screen_roomlist_filter_mixed_empty_state_title">"Du har ingen samtaler til dette valg"</string>
<string name="screen_roomlist_filter_people">"Mennesker"</string>
<string name="screen_roomlist_filter_people_empty_state_title">"Du har ingen DM\'er endnu"</string>
<string name="screen_roomlist_filter_rooms">"Rum"</string>
<string name="screen_roomlist_filter_rooms_empty_state_title">"Du er ikke i noget rum endnu"</string>
<string name="screen_roomlist_filter_unreads">"Ulæste"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Tillykke!
Du har ingen ulæste beskeder!"</string>
<string name="screen_roomlist_knock_event_sent_description">"Anmodning om at deltage sendt"</string>
<string name="screen_roomlist_main_space_title">"Samtaler"</string>
<string name="screen_roomlist_mark_as_read">"Marker som læst"</string>
<string name="screen_roomlist_mark_as_unread">"Marker som ulæst"</string>
<string name="screen_roomlist_tombstoned_room_description">"Dette rum er blevet opgraderet"</string>
<string name="session_verification_banner_message">"Det ser ud til, at du bruger en ny enhed. Bekræft med en anden enhed for at få adgang til dine krypterede meddelelser."</string>
<string name="session_verification_banner_title">"Bekræft, at det er dig"</string>
</resources>

View file

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="banner_battery_optimization_content_android">"Απενεργοποίησε τη βελτιστοποίηση μπαταρίας για αυτήν την εφαρμογή, για να βεβαιωθείς ότι λαμβάνονται όλες οι ειδοποιήσεις."</string>
<string name="banner_battery_optimization_submit_android">"Απενεργοποίηση βελτιστοποίησης"</string>
<string name="banner_battery_optimization_title_android">"Δεν φτάνουν οι ειδοποιήσεις;"</string>
<string name="banner_set_up_recovery_content">"Δημιούργησε ένα νέο κλειδί ανάκτησης που μπορεί να χρησιμοποιηθεί για την επαναφορά του ιστορικού των κρυπτογραφημένων μηνυμάτων σου σε περίπτωση που χάσεις την πρόσβαση στις συσκευές σου."</string>
<string name="banner_set_up_recovery_submit">"Ρύθμιση ανάκτησης"</string>
<string name="banner_set_up_recovery_title">"Ρύθμιση ανάκτησης"</string>
@ -7,7 +10,7 @@
<string name="confirm_recovery_key_banner_primary_button_title">"Εισήγαγε το κλειδί ανάκτησης"</string>
<string name="confirm_recovery_key_banner_secondary_button_title">"Ξέχασες το κλειδί ανάκτησης;"</string>
<string name="confirm_recovery_key_banner_title">"Ο χώρος αποθήκευσης κλειδιών σου δεν είναι συγχρονισμένος"</string>
<string name="full_screen_intent_banner_message">"Για να διασφαλίσεις ότι δεν θα χάσεις ποτέ μια σημαντική κλήση, άλλαξε τις ρυθμίσεις σου για να επιτρέψεις τις ειδοποιήσεις πλήρους οθόνης όταν το τηλέφωνό σου είναι κλειδωμένο."</string>
<string name="full_screen_intent_banner_message">"Για να διασφαλίσετε ότι δεν θα χάσετε ποτέ μια σημαντική κλήση, αλλάξτε τις ρυθμίσεις σας ώστε να επιτρέπονται οι ειδοποιήσεις πλήρους οθόνης όταν το τηλέφωνό σας είναι κλειδωμένο."</string>
<string name="full_screen_intent_banner_title">"Βελτίωσε την εμπειρία κλήσεων"</string>
<string name="screen_invites_decline_chat_message">"Σίγουρα θες να απορρίψεις την πρόσκληση συμμετοχής στο %1$s;"</string>
<string name="screen_invites_decline_chat_title">"Απόρριψη πρόσκλησης"</string>
@ -17,7 +20,7 @@
<string name="screen_invites_invited_you">"%1$s (%2$s) σέ προσκάλεσε"</string>
<string name="screen_migration_message">"Αυτή είναι μια εφάπαξ διαδικασία, ευχαριστώ που περίμενες."</string>
<string name="screen_migration_title">"Ρύθμιση του λογαριασμού σου."</string>
<string name="screen_roomlist_a11y_create_message">"Δημιουργία νέας συνομιλίας ή δωματίου"</string>
<string name="screen_roomlist_a11y_create_message">"Δημιουργία νέας συνομιλίας ή αίθουσας"</string>
<string name="screen_roomlist_empty_message">"Ξεκίνησε στέλνοντας μηνύματα σε κάποιον."</string>
<string name="screen_roomlist_empty_title">"Δεν υπάρχουν συνομιλίες ακόμα."</string>
<string name="screen_roomlist_filter_favourites">"Αγαπημένα"</string>
@ -31,8 +34,8 @@
<string name="screen_roomlist_filter_mixed_empty_state_title">"Δεν έχεις συνομιλίες για αυτήν την επιλογή"</string>
<string name="screen_roomlist_filter_people">"Άτομα"</string>
<string name="screen_roomlist_filter_people_empty_state_title">"Δεν έχεις ακόμα ΠΜ"</string>
<string name="screen_roomlist_filter_rooms">"Δωμάτια"</string>
<string name="screen_roomlist_filter_rooms_empty_state_title">"Δεν είσαι ακόμα σε κανένα δωμάτιο"</string>
<string name="screen_roomlist_filter_rooms">"Αίθουσες"</string>
<string name="screen_roomlist_filter_rooms_empty_state_title">"Δεν είστε ακόμα σε κάποια αίθουσα"</string>
<string name="screen_roomlist_filter_unreads">"Μη αναγνωσμένα"</string>
<string name="screen_roomlist_filter_unreads_empty_state_title">"Συγχαρητήρια!
Δεν έχεις μη αναγνωσμένα μηνύματα!"</string>
@ -40,6 +43,7 @@
<string name="screen_roomlist_main_space_title">"Συνομιλίες"</string>
<string name="screen_roomlist_mark_as_read">"Επισήμανση ως αναγνωσμένου"</string>
<string name="screen_roomlist_mark_as_unread">"Επισήμανση ως μη αναγνωσμένου"</string>
<string name="screen_roomlist_tombstoned_room_description">"Αυτή η αίθουσα έχει αναβαθμιστεί"</string>
<string name="session_verification_banner_message">"Φαίνεται ότι χρησιμοποιείς μια νέα συσκευή. Επαλήθευσε με άλλη συσκευή για πρόσβαση στα κρυπτογραφημένα σου μηνύματα."</string>
<string name="session_verification_banner_title">"Επαλήθευσε ότι είσαι εσύ"</string>
</resources>

View file

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="banner_battery_optimization_content_android">"Kui tahad olla kindel, et näed õigel ajal kõiki teavitusi, siis palun lülita akukasutuse optimeerimine välja."</string>
<string name="banner_battery_optimization_submit_android">"Lülita akukasutuse optimeerimine välja"</string>
<string name="banner_battery_optimization_title_android">"Sa ei näe kõiki teavitusi?"</string>
<string name="banner_set_up_recovery_content">"Loo uus taastevõti, mida saad kasutada oma krüptitud sõnumite ajaloo taastamisel olukorras, kus kaotad ligipääsu oma seadmetele."</string>
<string name="banner_set_up_recovery_submit">"Seadista andmete taastamine"</string>
<string name="banner_set_up_recovery_title">"Seadista taastamine"</string>
@ -18,6 +21,7 @@
<string name="screen_migration_message">"Tänud, et ootad - seda toimingut on vaja teha vaid üks kord."</string>
<string name="screen_migration_title">"Seadistame sinu kasutajakontot."</string>
<string name="screen_roomlist_a11y_create_message">"Loo uus vestlus või jututuba"</string>
<string name="screen_roomlist_clear_filters">"Tühjenda filtrid"</string>
<string name="screen_roomlist_empty_message">"Alustamiseks saada kellelegi sõnum."</string>
<string name="screen_roomlist_empty_title">"Veel pole vestlusi."</string>
<string name="screen_roomlist_filter_favourites">"Lemmikud"</string>
@ -40,6 +44,7 @@ Sul pole ühtegi lugemata sõnumit!"</string>
<string name="screen_roomlist_main_space_title">"Vestlused"</string>
<string name="screen_roomlist_mark_as_read">"Märgi loetuks"</string>
<string name="screen_roomlist_mark_as_unread">"Märgi mitteloetuks"</string>
<string name="screen_roomlist_tombstoned_room_description">"See jututuba on uuendatud"</string>
<string name="session_verification_banner_message">"Tundub, et kasutad uut seadet. Oma krüptitud sõnumite lugemiseks verifitseeri ta mõne muu oma seadmega."</string>
<string name="session_verification_banner_title">"Verifitseeri, et see oled sina"</string>
</resources>

View file

@ -40,6 +40,7 @@ Sinulla ei ole lukemattomia viestejä!"</string>
<string name="screen_roomlist_main_space_title">"Keskustelut"</string>
<string name="screen_roomlist_mark_as_read">"Merkitse luetuksi"</string>
<string name="screen_roomlist_mark_as_unread">"Merkitse lukemattomaksi"</string>
<string name="screen_roomlist_tombstoned_room_description">"Tämä huone on päivitetty"</string>
<string name="session_verification_banner_message">"Vaikuttaisi siltä, että käytät uutta laitetta. Vahvista toisella laitteella nähdäksesi salatut viestit."</string>
<string name="session_verification_banner_title">"Vahvista, että se olet sinä"</string>
</resources>

View file

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="banner_battery_optimization_content_android">"Désactivez loptimisation de la batterie pour cette application afin de vous assurer que toutes les notifications sont reçues."</string>
<string name="banner_battery_optimization_submit_android">"Désactiver loptimisation"</string>
<string name="banner_battery_optimization_title_android">"Ils vous manque des notifications?"</string>
<string name="banner_set_up_recovery_content">"Générez une nouvelle clé de récupération qui peut être utilisée pour restaurer lhistorique de vos messages chiffrés au cas où vous perdriez laccès à vos appareils."</string>
<string name="banner_set_up_recovery_submit">"Configurer la sauvegarde"</string>
<string name="banner_set_up_recovery_title">"Configurer la récupération"</string>
@ -18,6 +21,7 @@
<string name="screen_migration_message">"Il sagit dune opération ponctuelle, merci dattendre quelques instants."</string>
<string name="screen_migration_title">"Configuration de votre compte."</string>
<string name="screen_roomlist_a11y_create_message">"Créer une nouvelle discussion ou un nouveau salon"</string>
<string name="screen_roomlist_clear_filters">"Supprimer les filtres"</string>
<string name="screen_roomlist_empty_message">"Commencez par envoyer un message à quelquun."</string>
<string name="screen_roomlist_empty_title">"Aucune discussion pour le moment."</string>
<string name="screen_roomlist_filter_favourites">"Favoris"</string>
@ -40,6 +44,7 @@ Vous navez plus de messages non-lus !"</string>
<string name="screen_roomlist_main_space_title">"Conversations"</string>
<string name="screen_roomlist_mark_as_read">"Marquer comme lu"</string>
<string name="screen_roomlist_mark_as_unread">"Marquer comme non lu"</string>
<string name="screen_roomlist_tombstoned_room_description">"Ce salon a été mis à niveau."</string>
<string name="session_verification_banner_message">"Il semblerait que vous utilisiez un nouvel appareil. Vérifiez la session avec un autre de vos appareils pour accéder à vos messages chiffrés."</string>
<string name="session_verification_banner_title">"Vérifier que cest bien vous"</string>
</resources>

View file

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="banner_battery_optimization_content_android">"Kapcsolja ki az alkalmazás akkumulátor-optimalizálását, hogy biztosan megkapja az összes értesítést."</string>
<string name="banner_battery_optimization_submit_android">"Optimalizálás letiltása"</string>
<string name="banner_battery_optimization_title_android">"Nem érkeznek meg az értesítések?"</string>
<string name="banner_set_up_recovery_content">"Hozzon létre egy új helyreállítási kulcsot, amellyel visszaállíthatja a titkosított üzenetek előzményeit, ha elveszíti az eszközökhöz való hozzáférést."</string>
<string name="banner_set_up_recovery_submit">"Helyreállítás beállítása"</string>
<string name="banner_set_up_recovery_title">"Helyreállítás beállítása a fiókja védelméhez"</string>
@ -18,6 +21,7 @@
<string name="screen_migration_message">"Ez egy egyszeri folyamat, köszönjük a türelmét."</string>
<string name="screen_migration_title">"A fiók beállítása."</string>
<string name="screen_roomlist_a11y_create_message">"Új beszélgetés vagy szoba létrehozása"</string>
<string name="screen_roomlist_clear_filters">"Szűrők törlése"</string>
<string name="screen_roomlist_empty_message">"Kezdje azzal, hogy üzenetet küld valakinek."</string>
<string name="screen_roomlist_empty_title">"Még nincsenek csevegések."</string>
<string name="screen_roomlist_filter_favourites">"Kedvencek"</string>
@ -40,6 +44,7 @@ Nincs olvasatlan üzenete!"</string>
<string name="screen_roomlist_main_space_title">"Összes csevegés"</string>
<string name="screen_roomlist_mark_as_read">"Megjelölés olvasottként"</string>
<string name="screen_roomlist_mark_as_unread">"Megjelölés olvasatlanként"</string>
<string name="screen_roomlist_tombstoned_room_description">"A szoba verzióját frissítették"</string>
<string name="session_verification_banner_message">"Úgy tűnik, hogy új eszközt használ. Ellenőrizze egy másik eszközzel, hogy a továbbiakban elérje a titkosított üzeneteket."</string>
<string name="session_verification_banner_title">"Ellenőrizze, hogy Ön az"</string>
</resources>

View file

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="banner_battery_optimization_content_android">"Deaktiver batterioptimalisering for denne appen for å sikre at alle varsler mottas."</string>
<string name="banner_battery_optimization_submit_android">"Deaktiver optimalisering"</string>
<string name="banner_battery_optimization_title_android">"Kommer ikke varslene frem?"</string>
<string name="banner_set_up_recovery_content">"Gjenopprett din kryptografiske identitet og meldingshistorikk med en gjenopprettingsnøkkel hvis du har mistet alle dine brukte enheter."</string>
<string name="banner_set_up_recovery_submit">"Konfigurer gjenoppretting"</string>
<string name="banner_set_up_recovery_title">"Konfigurer gjenoppretting for å beskytte kontoen din"</string>
@ -40,6 +43,7 @@ Du har ingen uleste meldinger!"</string>
<string name="screen_roomlist_main_space_title">"Chatter"</string>
<string name="screen_roomlist_mark_as_read">"Marker som lest"</string>
<string name="screen_roomlist_mark_as_unread">"Merk som ulest"</string>
<string name="screen_roomlist_tombstoned_room_description">"Dette rommet har blitt oppgradert"</string>
<string name="session_verification_banner_message">"Det ser ut til at du bruker en ny enhet. Bekreft med en annen enhet for å få tilgang til de krypterte meldingene dine."</string>
<string name="session_verification_banner_title">"Bekreft at det er deg"</string>
</resources>

View file

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="banner_battery_optimization_content_android">"Desativa as otimizações de bateria para esta aplicação, de modo a garantir que todas as notificações chegam."</string>
<string name="banner_battery_optimization_submit_android">"Desativar otimizações"</string>
<string name="banner_battery_optimization_title_android">"As notificações não chegam?"</string>
<string name="banner_set_up_recovery_content">"Recupera a tua identidade criptográfica e o histórico de mensagens com uma chave de recuperação se tiveres perdido todos os teus dispositivos existentes."</string>
<string name="banner_set_up_recovery_submit">"Configurar recuperação"</string>
<string name="banner_set_up_recovery_title">"Configurar a recuperação"</string>
@ -18,6 +21,7 @@
<string name="screen_migration_message">"Este processo só acontece uma única vez, obrigado por esperares."</string>
<string name="screen_migration_title">"A configurar a tua conta…"</string>
<string name="screen_roomlist_a11y_create_message">"Criar uma nova conversa ou sala"</string>
<string name="screen_roomlist_clear_filters">"Limpar filtros"</string>
<string name="screen_roomlist_empty_message">"Começa por enviar uma mensagem a alguém."</string>
<string name="screen_roomlist_empty_title">"Ainda não tens conversas."</string>
<string name="screen_roomlist_filter_favourites">"Favoritas"</string>
@ -40,6 +44,7 @@ Não tens nenhuma mensagem por ler!"</string>
<string name="screen_roomlist_main_space_title">"Conversas"</string>
<string name="screen_roomlist_mark_as_read">"Marcar como lida"</string>
<string name="screen_roomlist_mark_as_unread">"Marcar como não lida"</string>
<string name="screen_roomlist_tombstoned_room_description">"Esta sala foi atualizada"</string>
<string name="session_verification_banner_message">"Parece que estás a utilizar um novo dispositivo. Verifica-o com um outro para poderes aceder às tuas mensagens cifradas."</string>
<string name="session_verification_banner_title">"Verifica que és tu"</string>
</resources>

View file

@ -40,6 +40,7 @@
<string name="screen_roomlist_main_space_title">"Все чаты"</string>
<string name="screen_roomlist_mark_as_read">"Пометить как прочитанное"</string>
<string name="screen_roomlist_mark_as_unread">"Отметить как непрочитанное"</string>
<string name="screen_roomlist_tombstoned_room_description">"Эта комната была обновлена"</string>
<string name="session_verification_banner_message">"Похоже, вы используете новое устройство. Чтобы получить доступ к зашифрованным сообщениям пройдите подтверждение с другим устройством."</string>
<string name="session_verification_banner_title">"Подтвердите, что это вы"</string>
</resources>

View file

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="banner_battery_optimization_content_android">"Vypnite optimalizáciu batérie pre túto aplikáciu, aby ste sa uistili, že sú prijaté všetky upozornenia."</string>
<string name="banner_battery_optimization_submit_android">"Zakázať optimalizáciu"</string>
<string name="banner_battery_optimization_title_android">"Oznámenia neprichádzajú?"</string>
<string name="banner_set_up_recovery_content">"Vytvorte nový kľúč na obnovenie, ktorý môžete použiť na obnovenie vašej histórie šifrovaných správ v prípade straty prístupu k vašim zariadeniam."</string>
<string name="banner_set_up_recovery_submit">"Nastaviť obnovenie"</string>
<string name="banner_set_up_recovery_title">"Nastaviť obnovenie"</string>
@ -18,6 +21,7 @@
<string name="screen_migration_message">"Ide o jednorazový proces, ďakujeme za trpezlivosť."</string>
<string name="screen_migration_title">"Nastavenie vášho účtu."</string>
<string name="screen_roomlist_a11y_create_message">"Vytvorte novú konverzáciu alebo miestnosť"</string>
<string name="screen_roomlist_clear_filters">"Vyčistiť filtre"</string>
<string name="screen_roomlist_empty_message">"Začnite tým, že niekomu pošlete správu."</string>
<string name="screen_roomlist_empty_title">"Zatiaľ žiadne konverzácie."</string>
<string name="screen_roomlist_filter_favourites">"Obľúbené"</string>
@ -40,6 +44,7 @@ Nemáte žiadne neprečítané správy!"</string>
<string name="screen_roomlist_main_space_title">"Všetky konverzácie"</string>
<string name="screen_roomlist_mark_as_read">"Označiť ako prečítané"</string>
<string name="screen_roomlist_mark_as_unread">"Označiť ako neprečítané"</string>
<string name="screen_roomlist_tombstoned_room_description">"Táto miestnosť bola aktualizovaná"</string>
<string name="session_verification_banner_message">"Vyzerá to tak, že používate nové zariadenie. Overte svoj prístup k zašifrovaným správam pomocou vášho druhého zariadenia."</string>
<string name="session_verification_banner_title">"Overte, že ste to vy"</string>
</resources>

View file

@ -40,6 +40,7 @@ Du har inga olästa meddelanden!"</string>
<string name="screen_roomlist_main_space_title">"Alla chattar"</string>
<string name="screen_roomlist_mark_as_read">"Markera som läst"</string>
<string name="screen_roomlist_mark_as_unread">"Markera som oläst"</string>
<string name="screen_roomlist_tombstoned_room_description">"Det här rummet har uppgraderats"</string>
<string name="session_verification_banner_message">"Det verkar som om du använder en ny enhet. Verifiera med en annan enhet för att komma åt dina krypterade meddelanden."</string>
<string name="session_verification_banner_title">"Verifiera att det är du"</string>
</resources>

Some files were not shown because too many files have changed in this diff Show more