First Commit

This commit is contained in:
2025-12-18 16:28:50 +07:00
commit 8c3e4f491f
9974 changed files with 396488 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
import extension.setupDependencyInjection
import extension.testCommonDependencies
/*
* Copyright (c) 2025 Element Creations Ltd.
* 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.
*/
plugins {
id("io.element.android-compose-library")
id("kotlin-parcelize")
}
android {
namespace = "io.element.android.features.signedout.impl"
}
setupDependencyInjection()
dependencies {
api(projects.features.signedout.api)
implementation(projects.libraries.core)
implementation(projects.libraries.architecture)
implementation(projects.libraries.matrix.api)
implementation(projects.libraries.matrixui)
implementation(projects.libraries.designsystem)
implementation(projects.libraries.uiStrings)
testCommonDependencies(libs)
testImplementation(projects.libraries.matrix.test)
testImplementation(projects.libraries.sessionStorage.test)
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.signedout.impl
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding
import io.element.android.features.signedout.api.SignedOutEntryPoint
import io.element.android.libraries.architecture.createNode
@ContributesBinding(AppScope::class)
class DefaultSignedOutEntryPoint : SignedOutEntryPoint {
override fun createNode(
parentNode: Node,
buildContext: BuildContext,
params: SignedOutEntryPoint.Params,
): Node {
return parentNode.createNode<SignedOutNode>(
buildContext = buildContext,
plugins = listOf(SignedOutNode.Inputs(params.sessionId))
)
}
}

View File

@@ -0,0 +1,13 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.signedout.impl
sealed interface SignedOutEvents {
data object SignInAgain : SignedOutEvents
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.signedout.impl
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.AssistedInject
import io.element.android.annotations.ContributesNode
import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.matrix.api.core.SessionId
@ContributesNode(AppScope::class)
@AssistedInject
class SignedOutNode(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
presenterFactory: SignedOutPresenter.Factory,
) : Node(buildContext, plugins = plugins) {
data class Inputs(
val sessionId: SessionId,
) : NodeInputs
private val inputs: Inputs = inputs()
private val presenter = presenterFactory.create(inputs.sessionId)
@Composable
override fun View(modifier: Modifier) {
val state = presenter.present()
SignedOutView(
state = state,
modifier = modifier
)
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.signedout.impl
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.AssistedFactory
import dev.zacsweers.metro.AssistedInject
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.sessionstorage.api.SessionStore
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
@AssistedInject
class SignedOutPresenter(
@Assisted private val sessionId: SessionId,
private val sessionStore: SessionStore,
private val buildMeta: BuildMeta,
) : Presenter<SignedOutState> {
@AssistedFactory
fun interface Factory {
fun create(sessionId: SessionId): SignedOutPresenter
}
@Composable
override fun present(): SignedOutState {
val signedOutSession by remember {
sessionStore.sessionsFlow().map { sessions ->
sessions.firstOrNull { it.userId == sessionId.value }
}
}.collectAsState(initial = null)
val coroutineScope = rememberCoroutineScope()
fun handleEvent(event: SignedOutEvents) {
when (event) {
SignedOutEvents.SignInAgain -> coroutineScope.launch {
sessionStore.removeSession(sessionId.value)
}
}
}
return SignedOutState(
appName = buildMeta.applicationName,
signedOutSession = signedOutSession,
eventSink = ::handleEvent,
)
}
}

View File

@@ -0,0 +1,17 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.signedout.impl
import io.element.android.libraries.sessionstorage.api.SessionData
data class SignedOutState(
val appName: String,
val signedOutSession: SessionData?,
val eventSink: (SignedOutEvents) -> Unit,
)

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.signedout.impl
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.sessionstorage.api.LoginType
import io.element.android.libraries.sessionstorage.api.SessionData
open class SignedOutStateProvider : PreviewParameterProvider<SignedOutState> {
override val values: Sequence<SignedOutState>
get() = sequenceOf(
aSignedOutState(),
// Add other states here
)
}
private fun aSignedOutState() = SignedOutState(
appName = "AppName",
signedOutSession = aSessionData(),
eventSink = {},
)
private fun aSessionData(
sessionId: String = "@alice:server.org",
isTokenValid: Boolean = false,
): SessionData {
return SessionData(
userId = sessionId,
deviceId = "aDeviceId",
accessToken = "anAccessToken",
refreshToken = "aRefreshToken",
homeserverUrl = "aHomeserverUrl",
oidcData = null,
loginTimestamp = null,
isTokenValid = isTokenValid,
loginType = LoginType.UNKNOWN,
passphrase = null,
sessionPath = "/a/path/to/a/session",
cachePath = "/a/path/to/a/cache",
position = 0,
lastUsageIndex = 0,
userDisplayName = null,
userAvatarUrl = null,
)
}

View File

@@ -0,0 +1,120 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.signedout.impl
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.runtime.Composable
import androidx.compose.ui.BiasAlignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule
import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
import io.element.android.libraries.designsystem.atomic.organisms.InfoListItem
import io.element.android.libraries.designsystem.atomic.organisms.InfoListOrganism
import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
import io.element.android.libraries.designsystem.components.BigIcon
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
import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.collections.immutable.persistentListOf
@Composable
fun SignedOutView(
state: SignedOutState,
modifier: Modifier = Modifier,
) {
BackHandler(onBack = { state.eventSink(SignedOutEvents.SignInAgain) })
HeaderFooterPage(
modifier = modifier
.fillMaxSize()
.systemBarsPadding()
.imePadding(),
header = { SignedOutHeader(state) },
content = { SignedOutContent() },
footer = {
SignedOutFooter(
onSignInAgain = { state.eventSink(SignedOutEvents.SignInAgain) },
)
}
)
}
@Composable
private fun SignedOutHeader(state: SignedOutState) {
IconTitleSubtitleMolecule(
modifier = Modifier.padding(top = 60.dp, bottom = 12.dp),
title = stringResource(id = R.string.screen_signed_out_title),
subTitle = stringResource(id = R.string.screen_signed_out_subtitle, state.appName),
iconStyle = BigIcon.Style.Default(CompoundIcons.UserProfileSolid()),
)
}
@Composable
private fun SignedOutContent() {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = BiasAlignment(
horizontalBias = 0f,
verticalBias = -0.4f
)
) {
InfoListOrganism(
items = persistentListOf(
InfoListItem(
message = stringResource(id = R.string.screen_signed_out_reason_1),
iconVector = CompoundIcons.Lock(),
),
InfoListItem(
message = stringResource(id = R.string.screen_signed_out_reason_2),
iconVector = CompoundIcons.Devices(),
),
InfoListItem(
message = stringResource(id = R.string.screen_signed_out_reason_3),
iconVector = CompoundIcons.Block(),
),
),
textStyle = ElementTheme.typography.fontBodyMdMedium,
iconTint = ElementTheme.colors.iconSecondary,
)
}
}
@Composable
private fun SignedOutFooter(
onSignInAgain: () -> Unit,
) {
ButtonColumnMolecule {
Button(
text = stringResource(id = CommonStrings.action_sign_in_again),
onClick = onSignInAgain,
modifier = Modifier.fillMaxWidth(),
)
}
}
@PreviewsDayNight
@Composable
internal fun SignedOutViewPreview(
@PreviewParameter(SignedOutStateProvider::class) state: SignedOutState,
) = ElementPreview {
SignedOutView(
state = state,
)
}

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="screen_signed_out_reason_1">"Вы змянілі свой пароль у іншым сеансе"</string>
<string name="screen_signed_out_reason_2">"Вы выдалілі сеанс з іншага сеансу"</string>
<string name="screen_signed_out_reason_3">"Адміністратар вашага сервера ануляваў ваш доступ"</string>
<string name="screen_signed_out_subtitle">"Магчыма, вы выйшлі з сістэмы па адной з прычын, пералічаных ніжэй. Калі ласка, увайдзіце яшчэ раз, каб працягнуць выкарыстанне %s."</string>
<string name="screen_signed_out_title">"Вы выйшлі з сістэмы"</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_signed_out_reason_1">"Променили сте паролата си в друга сесия"</string>
<string name="screen_signed_out_title">"Излезли сте"</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="screen_signed_out_reason_1">"Změnili jste heslo v jiné relaci"</string>
<string name="screen_signed_out_reason_2">"Odstranili jste relaci z jiné relace"</string>
<string name="screen_signed_out_reason_3">"Správce vašeho serveru zrušil váš přístup"</string>
<string name="screen_signed_out_subtitle">"Je možné, že jste byli odhlášeni z některého z níže uvedených důvodů. Chcete-li pokračovat v používání %s, přihlaste se znovu."</string>
<string name="screen_signed_out_title">"Jste odhlášeni"</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="screen_signed_out_reason_1">"Rydych chi wedi newid eich cyfrinair yn ystod sesiwn arall"</string>
<string name="screen_signed_out_reason_2">"Rydych chi wedi dileu\'r sesiwn o sesiwn arall"</string>
<string name="screen_signed_out_reason_3">"Mae gweinyddwr eich gweinydd wedi annilysu eich mynediad"</string>
<string name="screen_signed_out_subtitle">"Efallai eich bod wedi cael eich allgofnodi am un o\'r rhesymau sy\'n cael eu rhestru isod. Mewngofnodwch eto i barhau i ddefnyddio %s."</string>
<string name="screen_signed_out_title">"Rydych wedi\'ch allgofnodi"</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="screen_signed_out_reason_1">"Du har ændret din adgangskode på en anden session"</string>
<string name="screen_signed_out_reason_2">"Du har slettet sessionen fra en anden session"</string>
<string name="screen_signed_out_reason_3">"Din serveradministrator har lukket for din adgang"</string>
<string name="screen_signed_out_subtitle">"Du er muligvis blevet logget ud på grund af en af nedenstående årsager. Log ind igen for at fortsætte med at bruge%s."</string>
<string name="screen_signed_out_title">"Du er logget ud"</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="screen_signed_out_reason_1">"Du hast dein Passwort in einer anderen Sitzung geändert"</string>
<string name="screen_signed_out_reason_2">"Du hast diese Sitzung aus einer anderen Sitzung gelöscht"</string>
<string name="screen_signed_out_reason_3">"Der Administrator deines Servers hat deinen Zugang ungültig gemacht"</string>
<string name="screen_signed_out_subtitle">"Möglicherweise wurdest du aus einem der folgenden Gründe abgemeldet. Bitte melde dich erneut an, um %s weiter zu nutzen."</string>
<string name="screen_signed_out_title">"Du bist abgemeldet"</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="screen_signed_out_reason_1">"Άλλαξες τον κωδικό πρόσβασής σου σε άλλη συνεδρία"</string>
<string name="screen_signed_out_reason_2">"Έχεις διαγράψει τη συνεδρία από άλλη συνεδρία"</string>
<string name="screen_signed_out_reason_3">"Ο διαχειριστής του διακομιστή σου έχει ακυρώσει την πρόσβασή σου"</string>
<string name="screen_signed_out_subtitle">"Μπορεί να έχεις αποσυνδεθεί για έναν από τους λόγους που αναφέρονται παρακάτω. Συνδέσου ξανά για να συνεχίσεις να χρησιμοποιείς %s."</string>
<string name="screen_signed_out_title">"Έχεις αποσυνδεθεί"</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="screen_signed_out_reason_1">"Has cambiado tu contraseña en otra sesión"</string>
<string name="screen_signed_out_reason_2">"Has eliminado la sesión desde otra sesión"</string>
<string name="screen_signed_out_reason_3">"El administrador de tu servidor ha invalidado su acceso"</string>
<string name="screen_signed_out_subtitle">"Es posible que haya cerrado sesión por uno de los motivos que se enumeran a continuación. Por favor inicia sesión nuevamente para continuar usando %s."</string>
<string name="screen_signed_out_title">"Has cerrado sesión"</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="screen_signed_out_reason_1">"Sa oled muutnud oma salasõna ühes teises sessioonis"</string>
<string name="screen_signed_out_reason_2">"Sa oled kustutanud selle sessiooni ühest teisest oma sessioonist"</string>
<string name="screen_signed_out_reason_3">"Sinu koduserveri haldaja on sinu ligipääsu keelanud"</string>
<string name="screen_signed_out_subtitle">"Sa oled välja logitud ühel alltoodud põhjusel. Teenuse %s kasutamiseks palun logi uuesti sisse."</string>
<string name="screen_signed_out_title">"Sa oled välja loginud"</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="screen_signed_out_reason_1">"Pasahitza beste saio batean aldatu duzu"</string>
<string name="screen_signed_out_reason_2">"Saioa beste saio batetik ezabatu duzu"</string>
<string name="screen_signed_out_reason_3">"Zerbitzariaren administratzaileak zure sarbidea baliogabetu du"</string>
<string name="screen_signed_out_subtitle">"Litekeena da saioa amaitu izana ondorengo arrazoietako bat dela eta. Hasi saioa berriro %s erabiltzen jarraitzeko."</string>
<string name="screen_signed_out_title">"Saioa amaitu duzu"</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="screen_signed_out_reason_1">"گذرواژه‌تان را در نشستی دیگر تغییر داده‌اید"</string>
<string name="screen_signed_out_reason_2">"این نشست را از نشستی دیگر حذف کرده‌اید"</string>
<string name="screen_signed_out_reason_3">"مدیر کارسازتان دسترسیتان را نامعتبر کرده است"</string>
<string name="screen_signed_out_subtitle">"ممکن است به یکی از دلایل ذکر شده در زیر از سیستم خارج شده باشید. لطفا برای ادامه استفاده از %s دوباره وارد شوید."</string>
<string name="screen_signed_out_title">"خارج شده‌اید"</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="screen_signed_out_reason_1">"Olet vaihtanut salasanasi toisessa istunnossa"</string>
<string name="screen_signed_out_reason_2">"Olet poistanut istunnon toisesta istunnosta"</string>
<string name="screen_signed_out_reason_3">"Palvelimesi ylläpitäjä on mitätöinyt käyttöoikeutesi"</string>
<string name="screen_signed_out_subtitle">"Sinut on saatettu kirjata ulos jostakin alla luetellusta syystä. Kirjaudu uudelleen sisään jatkaaksesi %s -sovelluksen käyttöä."</string>
<string name="screen_signed_out_title">"Sinut on kirjattu ulos"</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="screen_signed_out_reason_1">"Le mot de passe de votre compte a été modifié sur un autre appareil"</string>
<string name="screen_signed_out_reason_2">"Cette session a été supprimée depuis un autre appareil"</string>
<string name="screen_signed_out_reason_3">"Ladministrateur de votre serveur a révoqué votre accès."</string>
<string name="screen_signed_out_subtitle">"La déconnexion peut être due à une des raisons ci-dessous. Veuillez vous connecter à nouveau pour continuer à utiliser %s."</string>
<string name="screen_signed_out_title">"Vous avez été déconnecté"</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="screen_signed_out_reason_1">"Megváltoztatta a jelszavát egy másik munkamenetben"</string>
<string name="screen_signed_out_reason_2">"Törölte a munkamenetet egy másik munkamenetből"</string>
<string name="screen_signed_out_reason_3">"A kiszolgáló adminisztrátora érvénytelenítette a hozzáférését"</string>
<string name="screen_signed_out_subtitle">"Előfordulhat, hogy az alábbiakban felsorolt okok valamelyike miatt került kijelentkeztetésre. Jelentkezzen be újra, hogy folytatni tudja az %s használatát."</string>
<string name="screen_signed_out_title">"Kijelentkezett"</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="screen_signed_out_reason_1">"Anda telah mengubah kata sandi Anda di sesi yang lain"</string>
<string name="screen_signed_out_reason_2">"Anda telah menghapus sesi dari sesi lain"</string>
<string name="screen_signed_out_reason_3">"Administrator homeserver Anda telah membatalkan akses Anda"</string>
<string name="screen_signed_out_subtitle">"Anda mungkin dikeluarkan karena alasan berikut. Silakan masuk lagi untuk melanjutkan menggunakan %s."</string>
<string name="screen_signed_out_title">"Anda telah keluar"</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="screen_signed_out_reason_1">"Hai cambiato la password in un\'altra sessione"</string>
<string name="screen_signed_out_reason_2">"Hai eliminato la sessione da un\'altra"</string>
<string name="screen_signed_out_reason_3">"L\'amministratore del tuo server ha invalidato il tuo accesso"</string>
<string name="screen_signed_out_subtitle">"Potresti essere stato disconnesso per uno dei motivi elencati di seguito. Accedi di nuovo per continuare a usare %s."</string>
<string name="screen_signed_out_title">"Sei disconnesso"</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="screen_signed_out_reason_1">"თქვენ პაროლი შეცვალეთ სხვა სესიაში"</string>
<string name="screen_signed_out_reason_2">"თქვენ სესია წაშალეთ სხვა სესიიდან"</string>
<string name="screen_signed_out_reason_3">"თქვენი სერვერის ადმინისტრატორმა გააუქმა თქვენი წვდომა"</string>
<string name="screen_signed_out_subtitle">"ალბათ, თქვენ გამოხვედით ქვემოთ ჩამოთვლილი ერთ-ერთი მიზეზის გამო. გთხოვთ, შეხვიდეთ ანგარიშში, რათა გააგრძელოთ %s-ს გამოყენება."</string>
<string name="screen_signed_out_title">"თქვენ ანგარიშიდან გამოსული ხართ"</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="screen_signed_out_reason_1">"다른 세션에서 비밀번호를 변경하셨습니다."</string>
<string name="screen_signed_out_reason_2">"다른 세션에서 세션을 삭제했습니다."</string>
<string name="screen_signed_out_reason_3">"귀하의 서버 관리자가 귀하의 액세스를 무효화했습니다."</string>
<string name="screen_signed_out_subtitle">"아래 나열된 이유 중 하나로 인해 로그아웃되었을 수 있습니다. 계속 사용하려면 다시 로그인하세요 %s ."</string>
<string name="screen_signed_out_title">"로그아웃 되었습니다"</string>
</resources>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_signed_out_title">"Esate atsijungę"</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="screen_signed_out_reason_1">"Du har endret passordet ditt i en annen sesjon"</string>
<string name="screen_signed_out_reason_2">"Du har slettet sesjonen fra en annen sesjon"</string>
<string name="screen_signed_out_reason_3">"Serveradministratoren har ugyldiggjort tilgangen din"</string>
<string name="screen_signed_out_subtitle">"Du kan ha blitt logget ut av en av årsakene som er oppført nedenfor. Logg på igjen for å fortsette å bruke %s."</string>
<string name="screen_signed_out_title">"Du er logget ut"</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="screen_signed_out_reason_1">"Je hebt je wachtwoord gewijzigd in een andere sessie"</string>
<string name="screen_signed_out_reason_2">"Je hebt deze sessie verwijderd in een andere sessie"</string>
<string name="screen_signed_out_reason_3">"De beheerder van je server heeft je toegang ongeldig gemaakt"</string>
<string name="screen_signed_out_subtitle">"Je bent mogelijk uitgelogd om een van de onderstaande redenen. Meld je opnieuw aan om %s te blijven gebruiken."</string>
<string name="screen_signed_out_title">"Je bent uitgelogd"</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="screen_signed_out_reason_1">"Zmieniono hasło w innej sesji"</string>
<string name="screen_signed_out_reason_2">"Sesja została usunięta z innej sesji"</string>
<string name="screen_signed_out_reason_3">"Administrator serwera unieważnił Twój dostęp"</string>
<string name="screen_signed_out_subtitle">"Mogłeś zostać wylogowany z powodów wymienionych poniżej. Zaloguj się ponownie, aby dalej korzystać z %s."</string>
<string name="screen_signed_out_title">"Zostałeś wylogowany"</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="screen_signed_out_reason_1">"Você alterou sua senha em outra sessão"</string>
<string name="screen_signed_out_reason_2">"Você apagou essa sessão através de outra sessão"</string>
<string name="screen_signed_out_reason_3">"O administrador do seu servidor invalidou seu acesso"</string>
<string name="screen_signed_out_subtitle">"Você pode ter sido desconectado por um dos motivos listados abaixo. Entre novamente para continuar usando o %s."</string>
<string name="screen_signed_out_title">"Você está desconectado"</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="screen_signed_out_reason_1">"Alteraste a tua senha noutra sessão"</string>
<string name="screen_signed_out_reason_2">"Eliminaste esta sessão a partir de outra"</string>
<string name="screen_signed_out_reason_3">"O administrador do teu servidor invalidou o teu acesso"</string>
<string name="screen_signed_out_subtitle">"A tua sessão pode ter sido terminada por um dos motivos indicados abaixo. Inicia sessão novamente para continuares a utilizar a %s."</string>
<string name="screen_signed_out_title">"Não tens sessão iniciada"</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="screen_signed_out_reason_1">"V-ați schimbat parola într-o altă sesiune"</string>
<string name="screen_signed_out_reason_2">"Ați șters sesiunea dintr-o altă sesiune"</string>
<string name="screen_signed_out_reason_3">"Administratorul serverului dumneavoastra v-a invalidat accesul"</string>
<string name="screen_signed_out_subtitle">"Este posibil să fi fost deconectat din unul dintre motivele enumerate mai jos. Vă rugăm să vă conectați din nou pentru a continua utilizarea%s."</string>
<string name="screen_signed_out_title">"Sunteți deconectat"</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="screen_signed_out_reason_1">"Вы изменили свой пароль в другой сессии"</string>
<string name="screen_signed_out_reason_2">"Вы удалили сессию из другой сессии"</string>
<string name="screen_signed_out_reason_3">"Администратор вашего сервера аннулировал ваш доступ"</string>
<string name="screen_signed_out_subtitle">"Возможно, вы вышли из системы по одной из причин, перечисленных ниже. Пожалуйста, войдите в систему еще раз, чтобы продолжить использование %s."</string>
<string name="screen_signed_out_title">"Вы вышли из системы"</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="screen_signed_out_reason_1">"Zmenili ste heslo pri inej relácii"</string>
<string name="screen_signed_out_reason_2">"Odstránili ste reláciu z inej relácie"</string>
<string name="screen_signed_out_reason_3">"Správca vášho servera vám zrušil váš prístup"</string>
<string name="screen_signed_out_subtitle">"Možno ste boli odhlásení z jedného z nižšie uvedených dôvodov. Ak chcete pokračovať v používaní %s, prihláste sa znova."</string>
<string name="screen_signed_out_title">"Ste odhlásený"</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="screen_signed_out_reason_1">"Du har ändrat ditt lösenord på en annan session"</string>
<string name="screen_signed_out_reason_2">"Du har raderat sessionen från en annan session"</string>
<string name="screen_signed_out_reason_3">"Din servers administratör har ogiltigförklarat din åtkomst"</string>
<string name="screen_signed_out_subtitle">"Du kan ha loggats ut av någon av anledningarna nedan. Vänligen logga in igen för att fortsätta använda %s."</string>
<string name="screen_signed_out_title">"Du är utloggad"</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="screen_signed_out_reason_1">"Başka bir oturumda şifrenizi değiştirdiniz"</string>
<string name="screen_signed_out_reason_2">"Oturumu başka bir oturumdan sildiniz"</string>
<string name="screen_signed_out_reason_3">"Sunucunuzun yöneticisi erişiminizi geçersiz kıldı"</string>
<string name="screen_signed_out_subtitle">"Aşağıda listelenen nedenlerden biri nedeniyle oturumunuz kapatılmış olabilir. %s kullanmaya devam etmek için lütfen tekrar oturum açın."</string>
<string name="screen_signed_out_title">"Oturumunuz kapatıldı"</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="screen_signed_out_reason_1">"Ви змінили пароль під час іншого сеансу"</string>
<string name="screen_signed_out_reason_2">"Ви видалили сеанс з іншого сеансу"</string>
<string name="screen_signed_out_reason_3">"Адміністратор вашого сервера визнав ваш доступ недійсним"</string>
<string name="screen_signed_out_subtitle">"Можливо, ви вийшли з системи з однієї з причин, наведених нижче. Будь ласка, увійдіть знову, щоб продовжити використання %s."</string>
<string name="screen_signed_out_title">"Ви вийшли з системи"</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="screen_signed_out_reason_1">"آپ نے دوسرے جلسے میں اپنا لفظِ عبور تبدیل کر لیا ہے"</string>
<string name="screen_signed_out_reason_2">"آپ نے جلسہ کو دوسرے جلسے سے حذف کر دیا ہے"</string>
<string name="screen_signed_out_reason_3">"آپ کے خادم کے منتظم نے آپکی رسائی کو باطل کردیا"</string>
<string name="screen_signed_out_subtitle">"ہوسکتا ہے کہ آپ کو ذیل میں درج وجوہات میں سے کسی ایک کی وجہ سے خارج کیا گیا ہو۔ برائے مہربانی %s کا استعمال جاری رکھنے کے لئے دوبارہ داخل ہوں۔"</string>
<string name="screen_signed_out_title">"آپ خارج ہوگئے ہیں"</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="screen_signed_out_reason_1">"Siz boshqa seansda parolingizni o\'zgartirdingiz"</string>
<string name="screen_signed_out_reason_2">"Siz seansni boshqa seansdan o\'chirib tashladingiz"</string>
<string name="screen_signed_out_reason_3">"Serveringiz administratori ruxsatingizni bekor qildi"</string>
<string name="screen_signed_out_subtitle">"Siz quyida sanab otilgan sabablardan biri tufayli tizimdan chiqqan bolishingiz mumkin. Foydalanishni davom ettirish uchun qayta kiring%s."</string>
<string name="screen_signed_out_title">"Hisobingizdan chiqdingiz"</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="screen_signed_out_reason_1">"在其他工作階段變更密碼"</string>
<string name="screen_signed_out_reason_2">"在另一個工作階段刪除了此工作階段"</string>
<string name="screen_signed_out_reason_3">"伺服器管理員撤銷了您的存取權限"</string>
<string name="screen_signed_out_subtitle">"您可能因為下列某個原因被登出了。請重新登入以繼續使用 %s。"</string>
<string name="screen_signed_out_title">"您登出了"</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="screen_signed_out_reason_1">"你在另一个会话中更改了密码"</string>
<string name="screen_signed_out_reason_2">"你已从其他会话中删除本会话"</string>
<string name="screen_signed_out_reason_3">"您的服务器管理员已禁止您访问"</string>
<string name="screen_signed_out_subtitle">"您可能因下列原因而被登出。请重新登录以继续使用 %s。"</string>
<string name="screen_signed_out_title">"你已登出"</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="screen_signed_out_reason_1">"Youve changed your password on another session"</string>
<string name="screen_signed_out_reason_2">"You have deleted the session from another session"</string>
<string name="screen_signed_out_reason_3">"Your servers administrator has invalidated your access"</string>
<string name="screen_signed_out_subtitle">"You might have been signed out for one of the reasons listed below. Please sign in again to continue using %s."</string>
<string name="screen_signed_out_title">"Youre signed out"</string>
</resources>

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* 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.signedout.impl
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.bumble.appyx.core.modality.BuildContext
import com.google.common.truth.Truth.assertThat
import io.element.android.features.signedout.api.SignedOutEntryPoint
import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.tests.testutils.node.TestParentNode
import org.junit.Rule
import org.junit.Test
class DefaultSignedOutEntryPointTest {
@get:Rule
val instantTaskExecutorRule = InstantTaskExecutorRule()
@Test
fun `test node builder`() {
val entryPoint = DefaultSignedOutEntryPoint()
val parentNode = TestParentNode.create { buildContext, plugins ->
SignedOutNode(
buildContext = buildContext,
plugins = plugins,
presenterFactory = { sessionId ->
assertThat(sessionId).isEqualTo(A_SESSION_ID)
createSignedOutPresenter()
}
)
}
val params = SignedOutEntryPoint.Params(A_SESSION_ID)
val result = entryPoint.createNode(
parentNode = parentNode,
buildContext = BuildContext.root(null),
params = params,
)
assertThat(result).isInstanceOf(SignedOutNode::class.java)
assertThat(result.plugins).contains(SignedOutNode.Inputs(params.sessionId))
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.signedout.impl
import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.test.AN_APPLICATION_NAME
import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.matrix.test.core.aBuildMeta
import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.libraries.sessionstorage.test.InMemorySessionStore
import io.element.android.libraries.sessionstorage.test.aSessionData
import io.element.android.tests.testutils.WarmUpRule
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
class SignedOutPresenterTest {
@get:Rule
val warmUpRule = WarmUpRule()
@Test
fun `present - initial state`() = runTest {
val aSessionData = aSessionData()
val sessionStore = InMemorySessionStore(
initialList = listOf(aSessionData)
)
val presenter = createSignedOutPresenter(sessionStore = sessionStore)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
skipItems(1)
val initialState = awaitItem()
assertThat(initialState.appName).isEqualTo(AN_APPLICATION_NAME)
assertThat(initialState.signedOutSession).isEqualTo(aSessionData)
}
}
@Test
fun `present - sign in again`() = runTest {
val aSessionData = aSessionData()
val sessionStore = InMemorySessionStore(
initialList = listOf(aSessionData)
)
val presenter = createSignedOutPresenter(sessionStore = sessionStore)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
skipItems(1)
val initialState = awaitItem()
assertThat(initialState.signedOutSession).isEqualTo(aSessionData)
assertThat(sessionStore.getAllSessions()).isNotEmpty()
assertThat(sessionStore.numberOfSessions()).isEqualTo(1)
initialState.eventSink(SignedOutEvents.SignInAgain)
assertThat(awaitItem().signedOutSession).isNull()
assertThat(sessionStore.getAllSessions()).isEmpty()
assertThat(sessionStore.numberOfSessions()).isEqualTo(0)
}
}
}
internal fun createSignedOutPresenter(
sessionId: SessionId = A_SESSION_ID,
sessionStore: SessionStore = InMemorySessionStore(),
): SignedOutPresenter {
return SignedOutPresenter(
sessionId = sessionId,
sessionStore = sessionStore,
buildMeta = aBuildMeta(applicationName = AN_APPLICATION_NAME),
)
}