refactor (start chat) : start splitting things (create room, invite people, start chat)
This commit is contained in:
parent
cab9291934
commit
1170a44116
133 changed files with 2613 additions and 397 deletions
|
|
@ -46,7 +46,6 @@ import io.element.android.appnav.loggedin.SendQueues
|
||||||
import io.element.android.appnav.room.RoomFlowNode
|
import io.element.android.appnav.room.RoomFlowNode
|
||||||
import io.element.android.appnav.room.RoomNavigationTarget
|
import io.element.android.appnav.room.RoomNavigationTarget
|
||||||
import io.element.android.appnav.room.joined.JoinedRoomLoadedFlowNode
|
import io.element.android.appnav.room.joined.JoinedRoomLoadedFlowNode
|
||||||
import io.element.android.features.createroom.api.CreateRoomEntryPoint
|
|
||||||
import io.element.android.features.enterprise.api.SessionEnterpriseService
|
import io.element.android.features.enterprise.api.SessionEnterpriseService
|
||||||
import io.element.android.features.ftue.api.FtueEntryPoint
|
import io.element.android.features.ftue.api.FtueEntryPoint
|
||||||
import io.element.android.features.ftue.api.state.FtueService
|
import io.element.android.features.ftue.api.state.FtueService
|
||||||
|
|
@ -60,6 +59,7 @@ import io.element.android.features.roomdirectory.api.RoomDescription
|
||||||
import io.element.android.features.roomdirectory.api.RoomDirectoryEntryPoint
|
import io.element.android.features.roomdirectory.api.RoomDirectoryEntryPoint
|
||||||
import io.element.android.features.securebackup.api.SecureBackupEntryPoint
|
import io.element.android.features.securebackup.api.SecureBackupEntryPoint
|
||||||
import io.element.android.features.share.api.ShareEntryPoint
|
import io.element.android.features.share.api.ShareEntryPoint
|
||||||
|
import io.element.android.features.startchat.api.StartChatEntryPoint
|
||||||
import io.element.android.features.userprofile.api.UserProfileEntryPoint
|
import io.element.android.features.userprofile.api.UserProfileEntryPoint
|
||||||
import io.element.android.features.verifysession.api.IncomingVerificationEntryPoint
|
import io.element.android.features.verifysession.api.IncomingVerificationEntryPoint
|
||||||
import io.element.android.libraries.architecture.BackstackView
|
import io.element.android.libraries.architecture.BackstackView
|
||||||
|
|
@ -94,15 +94,6 @@ import java.time.Duration
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.Optional
|
import java.util.Optional
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlin.collections.List
|
|
||||||
import kotlin.collections.any
|
|
||||||
import kotlin.collections.emptyList
|
|
||||||
import kotlin.collections.first
|
|
||||||
import kotlin.collections.forEach
|
|
||||||
import kotlin.collections.listOf
|
|
||||||
import kotlin.collections.mapNotNull
|
|
||||||
import kotlin.collections.plus
|
|
||||||
import kotlin.collections.setOf
|
|
||||||
import kotlin.time.Duration.Companion.minutes
|
import kotlin.time.Duration.Companion.minutes
|
||||||
import kotlin.time.Duration.Companion.seconds
|
import kotlin.time.Duration.Companion.seconds
|
||||||
import kotlin.time.toKotlinDuration
|
import kotlin.time.toKotlinDuration
|
||||||
|
|
@ -113,7 +104,7 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||||
@Assisted plugins: List<Plugin>,
|
@Assisted plugins: List<Plugin>,
|
||||||
private val homeEntryPoint: HomeEntryPoint,
|
private val homeEntryPoint: HomeEntryPoint,
|
||||||
private val preferencesEntryPoint: PreferencesEntryPoint,
|
private val preferencesEntryPoint: PreferencesEntryPoint,
|
||||||
private val createRoomEntryPoint: CreateRoomEntryPoint,
|
private val startChatEntryPoint: StartChatEntryPoint,
|
||||||
private val appNavigationStateService: AppNavigationStateService,
|
private val appNavigationStateService: AppNavigationStateService,
|
||||||
private val secureBackupEntryPoint: SecureBackupEntryPoint,
|
private val secureBackupEntryPoint: SecureBackupEntryPoint,
|
||||||
private val userProfileEntryPoint: UserProfileEntryPoint,
|
private val userProfileEntryPoint: UserProfileEntryPoint,
|
||||||
|
|
@ -304,7 +295,7 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||||
backstack.push(NavTarget.Settings())
|
backstack.push(NavTarget.Settings())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateRoomClick() {
|
override fun onStartChatClick() {
|
||||||
backstack.push(NavTarget.CreateRoom)
|
backstack.push(NavTarget.CreateRoom)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -422,7 +413,7 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
NavTarget.CreateRoom -> {
|
NavTarget.CreateRoom -> {
|
||||||
val callback = object : CreateRoomEntryPoint.Callback {
|
val callback = object : StartChatEntryPoint.Callback {
|
||||||
override fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>) {
|
override fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>) {
|
||||||
backstack.replace(NavTarget.Room(roomIdOrAlias = roomIdOrAlias, serverNames = serverNames))
|
backstack.replace(NavTarget.Room(roomIdOrAlias = roomIdOrAlias, serverNames = serverNames))
|
||||||
}
|
}
|
||||||
|
|
@ -432,7 +423,7 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createRoomEntryPoint
|
startChatEntryPoint
|
||||||
.nodeBuilder(this, buildContext)
|
.nodeBuilder(this, buildContext)
|
||||||
.callback(callback)
|
.callback(callback)
|
||||||
.build()
|
.build()
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2023, 2024 New Vector Ltd.
|
* Copyright 2025 New Vector Ltd.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
|
@ -7,21 +7,6 @@
|
||||||
|
|
||||||
package io.element.android.features.createroom.api
|
package io.element.android.features.createroom.api
|
||||||
|
|
||||||
import com.bumble.appyx.core.modality.BuildContext
|
import io.element.android.libraries.architecture.SimpleFeatureEntryPoint
|
||||||
import com.bumble.appyx.core.node.Node
|
|
||||||
import com.bumble.appyx.core.plugin.Plugin
|
|
||||||
import io.element.android.libraries.architecture.FeatureEntryPoint
|
|
||||||
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
|
|
||||||
|
|
||||||
interface CreateRoomEntryPoint : FeatureEntryPoint {
|
interface CreateRoomEntryPoint: SimpleFeatureEntryPoint
|
||||||
fun nodeBuilder(parentNode: Node, buildContext: BuildContext): NodeBuilder
|
|
||||||
interface NodeBuilder {
|
|
||||||
fun callback(callback: Callback): NodeBuilder
|
|
||||||
fun build(): Node
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Callback : Plugin {
|
|
||||||
fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>)
|
|
||||||
fun onOpenRoomDirectory()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ dependencies {
|
||||||
testImplementation(projects.libraries.mediaupload.test)
|
testImplementation(projects.libraries.mediaupload.test)
|
||||||
testImplementation(projects.libraries.permissions.test)
|
testImplementation(projects.libraries.permissions.test)
|
||||||
testImplementation(projects.libraries.usersearch.test)
|
testImplementation(projects.libraries.usersearch.test)
|
||||||
testImplementation(projects.features.createroom.test)
|
testImplementation(projects.features.startchat.test)
|
||||||
testImplementation(projects.libraries.featureflag.test)
|
testImplementation(projects.libraries.featureflag.test)
|
||||||
testImplementation(projects.tests.testutils)
|
testImplementation(projects.tests.testutils)
|
||||||
testImplementation(libs.androidx.compose.ui.test.junit)
|
testImplementation(libs.androidx.compose.ui.test.junit)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2023, 2024 New Vector Ltd.
|
* Copyright 2025 New Vector Ltd.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
|
@ -8,28 +8,19 @@
|
||||||
package io.element.android.features.createroom.impl
|
package io.element.android.features.createroom.impl
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import com.bumble.appyx.core.modality.BuildContext
|
import com.bumble.appyx.core.modality.BuildContext
|
||||||
import com.bumble.appyx.core.navigation.transition.JumpToEndTransitionHandler
|
|
||||||
import com.bumble.appyx.core.node.Node
|
import com.bumble.appyx.core.node.Node
|
||||||
import com.bumble.appyx.core.plugin.Plugin
|
import com.bumble.appyx.core.plugin.Plugin
|
||||||
import com.bumble.appyx.core.plugin.plugins
|
|
||||||
import com.bumble.appyx.navmodel.backstack.BackStack
|
import com.bumble.appyx.navmodel.backstack.BackStack
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import io.element.android.anvilannotations.ContributesNode
|
import io.element.android.anvilannotations.ContributesNode
|
||||||
import io.element.android.features.createroom.DefaultCreateRoomNavigator
|
import io.element.android.features.createroom.impl.addpeople.AddPeopleNode
|
||||||
import io.element.android.features.createroom.api.CreateRoomEntryPoint
|
import io.element.android.features.createroom.impl.configureroom.ConfigureRoomNode
|
||||||
import io.element.android.features.createroom.impl.joinbyaddress.JoinRoomByAddressNode
|
|
||||||
import io.element.android.features.createroom.impl.root.CreateRoomRootNode
|
|
||||||
import io.element.android.libraries.architecture.BackstackView
|
|
||||||
import io.element.android.libraries.architecture.BaseFlowNode
|
import io.element.android.libraries.architecture.BaseFlowNode
|
||||||
import io.element.android.libraries.architecture.OverlayView
|
|
||||||
import io.element.android.libraries.architecture.createNode
|
import io.element.android.libraries.architecture.createNode
|
||||||
import io.element.android.libraries.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
@ContributesNode(SessionScope::class)
|
@ContributesNode(SessionScope::class)
|
||||||
|
|
@ -38,53 +29,24 @@ class CreateRoomFlowNode @AssistedInject constructor(
|
||||||
@Assisted plugins: List<Plugin>,
|
@Assisted plugins: List<Plugin>,
|
||||||
) : BaseFlowNode<CreateRoomFlowNode.NavTarget>(
|
) : BaseFlowNode<CreateRoomFlowNode.NavTarget>(
|
||||||
backstack = BackStack(
|
backstack = BackStack(
|
||||||
initialElement = NavTarget.Root,
|
initialElement = NavTarget.ConfigureRoom,
|
||||||
savedStateMap = buildContext.savedStateMap,
|
savedStateMap = buildContext.savedStateMap,
|
||||||
),
|
),
|
||||||
buildContext = buildContext,
|
buildContext = buildContext,
|
||||||
plugins = plugins
|
plugins = plugins
|
||||||
) {
|
) {
|
||||||
sealed interface NavTarget : Parcelable {
|
|
||||||
@Parcelize
|
|
||||||
data object Root : NavTarget
|
|
||||||
|
|
||||||
@Parcelize
|
|
||||||
data object NewRoom : NavTarget
|
|
||||||
|
|
||||||
@Parcelize
|
|
||||||
data object JoinByAddress : NavTarget
|
|
||||||
}
|
|
||||||
|
|
||||||
private val navigator = DefaultCreateRoomNavigator(
|
|
||||||
backstack = backstack,
|
|
||||||
overlay = overlay,
|
|
||||||
openRoom = { roomIdOrAlias, viaServers ->
|
|
||||||
plugins<CreateRoomEntryPoint.Callback>().forEach { it.onOpenRoom(roomIdOrAlias, viaServers) }
|
|
||||||
},
|
|
||||||
openRoomDirectory = {
|
|
||||||
plugins<CreateRoomEntryPoint.Callback>().forEach { it.onOpenRoomDirectory() }
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
|
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
|
||||||
return when (navTarget) {
|
return when (navTarget) {
|
||||||
NavTarget.Root -> {
|
NavTarget.ConfigureRoom -> createNode<ConfigureRoomNode>(buildContext)
|
||||||
createNode<CreateRoomRootNode>(buildContext = buildContext, plugins = listOf(navigator))
|
is NavTarget.AddPeople -> createNode<AddPeopleNode>(buildContext)
|
||||||
}
|
|
||||||
NavTarget.NewRoom -> {
|
|
||||||
createNode<ConfigureRoomFlowNode>(buildContext = buildContext, plugins = listOf(navigator))
|
|
||||||
}
|
|
||||||
NavTarget.JoinByAddress -> {
|
|
||||||
createNode<JoinRoomByAddressNode>(buildContext = buildContext, plugins = listOf(navigator))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
sealed interface NavTarget : Parcelable {
|
||||||
override fun View(modifier: Modifier) {
|
@Parcelize
|
||||||
Box(modifier = modifier) {
|
data object ConfigureRoom : NavTarget
|
||||||
BackstackView()
|
|
||||||
OverlayView(transitionHandler = remember { JumpToEndTransitionHandler() })
|
@Parcelize
|
||||||
}
|
data class AddPeople(val roomId: RoomId) : NavTarget
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2023, 2024 New Vector Ltd.
|
* Copyright 2025 New Vector Ltd.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
|
@ -9,27 +9,12 @@ package io.element.android.features.createroom.impl
|
||||||
|
|
||||||
import com.bumble.appyx.core.modality.BuildContext
|
import com.bumble.appyx.core.modality.BuildContext
|
||||||
import com.bumble.appyx.core.node.Node
|
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.createroom.api.CreateRoomEntryPoint
|
import io.element.android.features.createroom.api.CreateRoomEntryPoint
|
||||||
import io.element.android.libraries.architecture.createNode
|
import io.element.android.libraries.architecture.createNode
|
||||||
import io.element.android.libraries.di.AppScope
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ContributesBinding(AppScope::class)
|
class DefaultCreateRoomEntryPoint @Inject constructor(): CreateRoomEntryPoint {
|
||||||
class DefaultCreateRoomEntryPoint @Inject constructor() : CreateRoomEntryPoint {
|
override fun createNode(parentNode: Node, buildContext: BuildContext): Node {
|
||||||
override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): CreateRoomEntryPoint.NodeBuilder {
|
return parentNode.createNode<CreateRoomFlowNode>(buildContext)
|
||||||
val plugins = ArrayList<Plugin>()
|
|
||||||
|
|
||||||
return object : CreateRoomEntryPoint.NodeBuilder {
|
|
||||||
override fun callback(callback: CreateRoomEntryPoint.Callback): CreateRoomEntryPoint.NodeBuilder {
|
|
||||||
plugins += callback
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun build(): Node {
|
|
||||||
return parentNode.createNode<CreateRoomFlowNode>(buildContext, plugins)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2023, 2024 New Vector Ltd.
|
* Copyright 2025 New Vector Ltd.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
|
@ -7,39 +7,11 @@
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.addpeople
|
package io.element.android.features.createroom.impl.addpeople
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import com.bumble.appyx.core.modality.BuildContext
|
import com.bumble.appyx.core.modality.BuildContext
|
||||||
import com.bumble.appyx.core.node.Node
|
import com.bumble.appyx.core.node.Node
|
||||||
import com.bumble.appyx.core.plugin.Plugin
|
import com.bumble.appyx.core.plugin.Plugin
|
||||||
import com.bumble.appyx.core.plugin.plugins
|
|
||||||
import dagger.assisted.Assisted
|
|
||||||
import dagger.assisted.AssistedInject
|
|
||||||
import io.element.android.anvilannotations.ContributesNode
|
|
||||||
import io.element.android.features.createroom.impl.di.CreateRoomScope
|
|
||||||
|
|
||||||
@ContributesNode(CreateRoomScope::class)
|
class AddPeopleNode(
|
||||||
class AddPeopleNode @AssistedInject constructor(
|
buildContext: BuildContext,
|
||||||
@Assisted buildContext: BuildContext,
|
plugins: List<Plugin>,
|
||||||
@Assisted plugins: List<Plugin>,
|
) : Node(buildContext, plugins = plugins)
|
||||||
private val presenter: AddPeoplePresenter,
|
|
||||||
) : Node(buildContext, plugins = plugins) {
|
|
||||||
interface Callback : Plugin {
|
|
||||||
fun onContinue()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onContinue() {
|
|
||||||
plugins<Callback>().forEach { it.onContinue() }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
override fun View(modifier: Modifier) {
|
|
||||||
val state = presenter.present()
|
|
||||||
AddPeopleView(
|
|
||||||
state = state,
|
|
||||||
modifier = modifier,
|
|
||||||
onBackClick = this::navigateUp,
|
|
||||||
onNextClick = this::onContinue,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ sealed interface ConfigureRoomEvents {
|
||||||
data class RoomVisibilityChanged(val visibilityItem: RoomVisibilityItem) : ConfigureRoomEvents
|
data class RoomVisibilityChanged(val visibilityItem: RoomVisibilityItem) : ConfigureRoomEvents
|
||||||
data class RoomAccessChanged(val roomAccess: RoomAccessItem) : ConfigureRoomEvents
|
data class RoomAccessChanged(val roomAccess: RoomAccessItem) : ConfigureRoomEvents
|
||||||
data class RoomAddressChanged(val roomAddress: String) : ConfigureRoomEvents
|
data class RoomAddressChanged(val roomAddress: String) : ConfigureRoomEvents
|
||||||
data class RemoveUserFromSelection(val matrixUser: MatrixUser) : ConfigureRoomEvents
|
|
||||||
data object CreateRoom : ConfigureRoomEvents
|
data object CreateRoom : ConfigureRoomEvents
|
||||||
data class HandleAvatarAction(val action: AvatarAction) : ConfigureRoomEvents
|
data class HandleAvatarAction(val action: AvatarAction) : ConfigureRoomEvents
|
||||||
data object CancelCreateRoom : ConfigureRoomEvents
|
data object CancelCreateRoom : ConfigureRoomEvents
|
||||||
|
|
|
||||||
|
|
@ -13,24 +13,20 @@ import com.bumble.appyx.core.lifecycle.subscribe
|
||||||
import com.bumble.appyx.core.modality.BuildContext
|
import com.bumble.appyx.core.modality.BuildContext
|
||||||
import com.bumble.appyx.core.node.Node
|
import com.bumble.appyx.core.node.Node
|
||||||
import com.bumble.appyx.core.plugin.Plugin
|
import com.bumble.appyx.core.plugin.Plugin
|
||||||
import com.bumble.appyx.core.plugin.plugins
|
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import im.vector.app.features.analytics.plan.MobileScreen
|
import im.vector.app.features.analytics.plan.MobileScreen
|
||||||
import io.element.android.anvilannotations.ContributesNode
|
import io.element.android.anvilannotations.ContributesNode
|
||||||
import io.element.android.features.createroom.CreateRoomNavigator
|
import io.element.android.libraries.di.SessionScope
|
||||||
import io.element.android.features.createroom.impl.di.CreateRoomScope
|
|
||||||
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
|
|
||||||
import io.element.android.services.analytics.api.AnalyticsService
|
import io.element.android.services.analytics.api.AnalyticsService
|
||||||
|
|
||||||
@ContributesNode(CreateRoomScope::class)
|
@ContributesNode(SessionScope::class)
|
||||||
class ConfigureRoomNode @AssistedInject constructor(
|
class ConfigureRoomNode @AssistedInject constructor(
|
||||||
@Assisted buildContext: BuildContext,
|
@Assisted buildContext: BuildContext,
|
||||||
@Assisted plugins: List<Plugin>,
|
@Assisted plugins: List<Plugin>,
|
||||||
private val presenter: ConfigureRoomPresenter,
|
private val presenter: ConfigureRoomPresenter,
|
||||||
private val analyticsService: AnalyticsService,
|
private val analyticsService: AnalyticsService,
|
||||||
) : Node(buildContext, plugins = plugins) {
|
) : Node(buildContext, plugins = plugins) {
|
||||||
private val navigator = plugins<CreateRoomNavigator>().first()
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
lifecycle.subscribe(
|
lifecycle.subscribe(
|
||||||
|
|
@ -48,7 +44,7 @@ class ConfigureRoomNode @AssistedInject constructor(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
onBackClick = this::navigateUp,
|
onBackClick = this::navigateUp,
|
||||||
onCreateRoomSuccess = {
|
onCreateRoomSuccess = {
|
||||||
navigator.onOpenRoom(roomIdOrAlias = it.toRoomIdOrAlias(), serverNames = emptyList())
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,6 @@ import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import im.vector.app.features.analytics.plan.CreatedRoom
|
import im.vector.app.features.analytics.plan.CreatedRoom
|
||||||
import io.element.android.features.createroom.impl.CreateRoomConfig
|
|
||||||
import io.element.android.features.createroom.impl.CreateRoomDataStore
|
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
import io.element.android.libraries.architecture.runCatchingUpdatingState
|
import io.element.android.libraries.architecture.runCatchingUpdatingState
|
||||||
|
|
@ -50,7 +48,7 @@ import javax.inject.Inject
|
||||||
import kotlin.jvm.optionals.getOrDefault
|
import kotlin.jvm.optionals.getOrDefault
|
||||||
|
|
||||||
class ConfigureRoomPresenter @Inject constructor(
|
class ConfigureRoomPresenter @Inject constructor(
|
||||||
private val dataStore: CreateRoomDataStore,
|
private val dataStore: CreateRoomConfigStore,
|
||||||
private val matrixClient: MatrixClient,
|
private val matrixClient: MatrixClient,
|
||||||
private val mediaPickerProvider: PickerProvider,
|
private val mediaPickerProvider: PickerProvider,
|
||||||
private val mediaPreProcessor: MediaPreProcessor,
|
private val mediaPreProcessor: MediaPreProcessor,
|
||||||
|
|
@ -66,7 +64,7 @@ class ConfigureRoomPresenter @Inject constructor(
|
||||||
@Composable
|
@Composable
|
||||||
override fun present(): ConfigureRoomState {
|
override fun present(): ConfigureRoomState {
|
||||||
val cameraPermissionState = cameraPermissionPresenter.present()
|
val cameraPermissionState = cameraPermissionPresenter.present()
|
||||||
val createRoomConfig by dataStore.createRoomConfigWithInvites.collectAsState(CreateRoomConfig())
|
val createRoomConfig by dataStore.getCreateRoomConfigFlow().collectAsState(CreateRoomConfig())
|
||||||
val homeserverName = remember { matrixClient.userIdServerName() }
|
val homeserverName = remember { matrixClient.userIdServerName() }
|
||||||
val isKnockFeatureEnabled by remember {
|
val isKnockFeatureEnabled by remember {
|
||||||
featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock)
|
featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock)
|
||||||
|
|
@ -121,7 +119,6 @@ class ConfigureRoomPresenter @Inject constructor(
|
||||||
is ConfigureRoomEvents.RoomNameChanged -> dataStore.setRoomName(event.name)
|
is ConfigureRoomEvents.RoomNameChanged -> dataStore.setRoomName(event.name)
|
||||||
is ConfigureRoomEvents.TopicChanged -> dataStore.setTopic(event.topic)
|
is ConfigureRoomEvents.TopicChanged -> dataStore.setTopic(event.topic)
|
||||||
is ConfigureRoomEvents.RoomVisibilityChanged -> dataStore.setRoomVisibility(event.visibilityItem)
|
is ConfigureRoomEvents.RoomVisibilityChanged -> dataStore.setRoomVisibility(event.visibilityItem)
|
||||||
is ConfigureRoomEvents.RemoveUserFromSelection -> dataStore.selectedUserListDataStore.removeUserFromSelection(event.matrixUser)
|
|
||||||
is ConfigureRoomEvents.RoomAccessChanged -> dataStore.setRoomAccess(event.roomAccess)
|
is ConfigureRoomEvents.RoomAccessChanged -> dataStore.setRoomAccess(event.roomAccess)
|
||||||
is ConfigureRoomEvents.RoomAddressChanged -> dataStore.setRoomAddress(event.roomAddress)
|
is ConfigureRoomEvents.RoomAddressChanged -> dataStore.setRoomAddress(event.roomAddress)
|
||||||
is ConfigureRoomEvents.CreateRoom -> createRoom(createRoomConfig)
|
is ConfigureRoomEvents.CreateRoom -> createRoom(createRoomConfig)
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.configureroom
|
package io.element.android.features.createroom.impl.configureroom
|
||||||
|
|
||||||
import io.element.android.features.createroom.impl.CreateRoomConfig
|
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
import io.element.android.libraries.matrix.ui.media.AvatarAction
|
import io.element.android.libraries.matrix.ui.media.AvatarAction
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
||||||
package io.element.android.features.createroom.impl.configureroom
|
package io.element.android.features.createroom.impl.configureroom
|
||||||
|
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
import io.element.android.features.createroom.impl.CreateRoomConfig
|
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
import io.element.android.libraries.matrix.ui.components.aMatrixUserList
|
import io.element.android.libraries.matrix.ui.components.aMatrixUserList
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.ColumnScope
|
import androidx.compose.foundation.layout.ColumnScope
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||||
|
|
@ -58,7 +57,6 @@ import io.element.android.libraries.designsystem.theme.components.TextField
|
||||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
import io.element.android.libraries.matrix.ui.components.AvatarActionBottomSheet
|
import io.element.android.libraries.matrix.ui.components.AvatarActionBottomSheet
|
||||||
import io.element.android.libraries.matrix.ui.components.SelectedUsersRowList
|
|
||||||
import io.element.android.libraries.matrix.ui.components.UnsavedAvatar
|
import io.element.android.libraries.matrix.ui.components.UnsavedAvatar
|
||||||
import io.element.android.libraries.matrix.ui.room.address.RoomAddressField
|
import io.element.android.libraries.matrix.ui.room.address.RoomAddressField
|
||||||
import io.element.android.libraries.permissions.api.PermissionsView
|
import io.element.android.libraries.permissions.api.PermissionsView
|
||||||
|
|
@ -112,16 +110,6 @@ fun ConfigureRoomView(
|
||||||
topic = state.config.topic.orEmpty(),
|
topic = state.config.topic.orEmpty(),
|
||||||
onTopicChange = { state.eventSink(ConfigureRoomEvents.TopicChanged(it)) },
|
onTopicChange = { state.eventSink(ConfigureRoomEvents.TopicChanged(it)) },
|
||||||
)
|
)
|
||||||
if (state.config.invites.isNotEmpty()) {
|
|
||||||
SelectedUsersRowList(
|
|
||||||
contentPadding = PaddingValues(horizontal = 24.dp),
|
|
||||||
selectedUsers = state.config.invites,
|
|
||||||
onUserRemove = {
|
|
||||||
focusManager.clearFocus()
|
|
||||||
state.eventSink(ConfigureRoomEvents.RemoveUserFromSelection(it))
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
RoomVisibilityOptions(
|
RoomVisibilityOptions(
|
||||||
selected = when (state.config.roomVisibility) {
|
selected = when (state.config.roomVisibility) {
|
||||||
is RoomVisibilityState.Private -> RoomVisibilityItem.Private
|
is RoomVisibilityState.Private -> RoomVisibilityItem.Private
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,9 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl
|
package io.element.android.features.createroom.impl.configureroom
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import io.element.android.features.createroom.impl.configureroom.RoomVisibilityState
|
|
||||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
* 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.createroom.impl.configureroom
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import io.element.android.libraries.androidutils.file.safeDelete
|
||||||
|
import io.element.android.libraries.matrix.api.room.alias.RoomAliasHelper
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.getAndUpdate
|
||||||
|
import java.io.File
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class CreateRoomConfigStore @Inject constructor(
|
||||||
|
private val roomAliasHelper: RoomAliasHelper,
|
||||||
|
) {
|
||||||
|
private val createRoomConfigFlow: MutableStateFlow<CreateRoomConfig> = MutableStateFlow(CreateRoomConfig())
|
||||||
|
|
||||||
|
private var cachedAvatarUri: Uri? = null
|
||||||
|
set(value) {
|
||||||
|
field?.path?.let { File(it) }?.safeDelete()
|
||||||
|
field = value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCreateRoomConfigFlow(): StateFlow<CreateRoomConfig> = createRoomConfigFlow
|
||||||
|
|
||||||
|
fun setRoomName(roomName: String) {
|
||||||
|
createRoomConfigFlow.getAndUpdate { config ->
|
||||||
|
val newVisibility = when (config.roomVisibility) {
|
||||||
|
is RoomVisibilityState.Public -> {
|
||||||
|
val roomAddress = config.roomVisibility.roomAddress
|
||||||
|
if (roomAddress is RoomAddress.AutoFilled || roomName.isEmpty()) {
|
||||||
|
val roomAliasName = roomAliasHelper.roomAliasNameFromRoomDisplayName(roomName)
|
||||||
|
config.roomVisibility.copy(
|
||||||
|
roomAddress = RoomAddress.AutoFilled(roomAliasName),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
config.roomVisibility
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> config.roomVisibility
|
||||||
|
}
|
||||||
|
config.copy(
|
||||||
|
roomName = roomName.takeIf { it.isNotEmpty() },
|
||||||
|
roomVisibility = newVisibility,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setTopic(topic: String) {
|
||||||
|
createRoomConfigFlow.getAndUpdate { config ->
|
||||||
|
config.copy(topic = topic.takeIf { it.isNotEmpty() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setAvatarUri(uri: Uri?, cached: Boolean = false) {
|
||||||
|
cachedAvatarUri = uri.takeIf { cached }
|
||||||
|
createRoomConfigFlow.getAndUpdate { config ->
|
||||||
|
config.copy(avatarUri = uri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setRoomVisibility(visibility: RoomVisibilityItem) {
|
||||||
|
createRoomConfigFlow.getAndUpdate { config ->
|
||||||
|
config.copy(
|
||||||
|
roomVisibility = when (visibility) {
|
||||||
|
RoomVisibilityItem.Private -> RoomVisibilityState.Private
|
||||||
|
RoomVisibilityItem.Public -> {
|
||||||
|
val roomAliasName = roomAliasHelper.roomAliasNameFromRoomDisplayName(config.roomName.orEmpty())
|
||||||
|
RoomVisibilityState.Public(
|
||||||
|
roomAddress = RoomAddress.AutoFilled(roomAliasName),
|
||||||
|
roomAccess = RoomAccess.Anyone,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setRoomAddress(address: String) {
|
||||||
|
createRoomConfigFlow.getAndUpdate { config ->
|
||||||
|
config.copy(
|
||||||
|
roomVisibility = when (config.roomVisibility) {
|
||||||
|
is RoomVisibilityState.Public -> {
|
||||||
|
val sanitizedAddress = address.lowercase()
|
||||||
|
config.roomVisibility.copy(roomAddress = RoomAddress.Edited(sanitizedAddress))
|
||||||
|
}
|
||||||
|
else -> config.roomVisibility
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setRoomAccess(access: RoomAccessItem) {
|
||||||
|
createRoomConfigFlow.getAndUpdate { config ->
|
||||||
|
config.copy(
|
||||||
|
roomVisibility = when (config.roomVisibility) {
|
||||||
|
is RoomVisibilityState.Public -> {
|
||||||
|
when (access) {
|
||||||
|
RoomAccessItem.Anyone -> config.roomVisibility.copy(roomAccess = RoomAccess.Anyone)
|
||||||
|
RoomAccessItem.AskToJoin -> config.roomVisibility.copy(roomAccess = RoomAccess.Knocking)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> config.roomVisibility
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearCachedData() {
|
||||||
|
cachedAvatarUri = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.createroom.impl.root
|
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
|
||||||
|
|
||||||
sealed interface CreateRoomRootEvents {
|
|
||||||
data class StartDM(val matrixUser: MatrixUser) : CreateRoomRootEvents
|
|
||||||
data object CancelStartDM : CreateRoomRootEvents
|
|
||||||
}
|
|
||||||
|
|
@ -22,7 +22,7 @@ interface HomeEntryPoint : FeatureEntryPoint {
|
||||||
|
|
||||||
interface Callback : Plugin {
|
interface Callback : Plugin {
|
||||||
fun onRoomClick(roomId: RoomId)
|
fun onRoomClick(roomId: RoomId)
|
||||||
fun onCreateRoomClick()
|
fun onStartChatClick()
|
||||||
fun onSettingsClick()
|
fun onSettingsClick()
|
||||||
fun onSetUpRecoveryClick()
|
fun onSetUpRecoveryClick()
|
||||||
fun onSessionConfirmRecoveryKeyClick()
|
fun onSessionConfirmRecoveryKeyClick()
|
||||||
|
|
|
||||||
|
|
@ -120,8 +120,8 @@ class HomeFlowNode @AssistedInject constructor(
|
||||||
plugins<HomeEntryPoint.Callback>().forEach { it.onSettingsClick() }
|
plugins<HomeEntryPoint.Callback>().forEach { it.onSettingsClick() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onCreateRoomClick() {
|
private fun onStartChatClick() {
|
||||||
plugins<HomeEntryPoint.Callback>().forEach { it.onCreateRoomClick() }
|
plugins<HomeEntryPoint.Callback>().forEach { it.onStartChatClick() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onSetUpRecoveryClick() {
|
private fun onSetUpRecoveryClick() {
|
||||||
|
|
@ -171,7 +171,7 @@ class HomeFlowNode @AssistedInject constructor(
|
||||||
homeState = state,
|
homeState = state,
|
||||||
onRoomClick = this::onRoomClick,
|
onRoomClick = this::onRoomClick,
|
||||||
onSettingsClick = this::onOpenSettings,
|
onSettingsClick = this::onOpenSettings,
|
||||||
onCreateRoomClick = this::onCreateRoomClick,
|
onStartChatClick = this::onStartChatClick,
|
||||||
onSetUpRecoveryClick = this::onSetUpRecoveryClick,
|
onSetUpRecoveryClick = this::onSetUpRecoveryClick,
|
||||||
onConfirmRecoveryKeyClick = this::onSessionConfirmRecoveryKeyClick,
|
onConfirmRecoveryKeyClick = this::onSessionConfirmRecoveryKeyClick,
|
||||||
onRoomSettingsClick = this::onRoomSettingsClick,
|
onRoomSettingsClick = this::onRoomSettingsClick,
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ fun HomeView(
|
||||||
onSettingsClick: () -> Unit,
|
onSettingsClick: () -> Unit,
|
||||||
onSetUpRecoveryClick: () -> Unit,
|
onSetUpRecoveryClick: () -> Unit,
|
||||||
onConfirmRecoveryKeyClick: () -> Unit,
|
onConfirmRecoveryKeyClick: () -> Unit,
|
||||||
onCreateRoomClick: () -> Unit,
|
onStartChatClick: () -> Unit,
|
||||||
onRoomSettingsClick: (roomId: RoomId) -> Unit,
|
onRoomSettingsClick: (roomId: RoomId) -> Unit,
|
||||||
onMenuActionClick: (RoomListMenuAction) -> Unit,
|
onMenuActionClick: (RoomListMenuAction) -> Unit,
|
||||||
onReportRoomClick: (roomId: RoomId) -> Unit,
|
onReportRoomClick: (roomId: RoomId) -> Unit,
|
||||||
|
|
@ -116,7 +116,7 @@ fun HomeView(
|
||||||
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
|
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
|
||||||
onRoomClick = { if (firstThrottler.canHandle()) onRoomClick(it) },
|
onRoomClick = { if (firstThrottler.canHandle()) onRoomClick(it) },
|
||||||
onOpenSettings = { if (firstThrottler.canHandle()) onSettingsClick() },
|
onOpenSettings = { if (firstThrottler.canHandle()) onSettingsClick() },
|
||||||
onCreateRoomClick = { if (firstThrottler.canHandle()) onCreateRoomClick() },
|
onStartChatClick = { if (firstThrottler.canHandle()) onStartChatClick() },
|
||||||
onMenuActionClick = onMenuActionClick,
|
onMenuActionClick = onMenuActionClick,
|
||||||
modifier = Modifier.padding(top = topPadding),
|
modifier = Modifier.padding(top = topPadding),
|
||||||
)
|
)
|
||||||
|
|
@ -145,7 +145,7 @@ private fun HomeScaffold(
|
||||||
onConfirmRecoveryKeyClick: () -> Unit,
|
onConfirmRecoveryKeyClick: () -> Unit,
|
||||||
onRoomClick: (RoomId) -> Unit,
|
onRoomClick: (RoomId) -> Unit,
|
||||||
onOpenSettings: () -> Unit,
|
onOpenSettings: () -> Unit,
|
||||||
onCreateRoomClick: () -> Unit,
|
onStartChatClick: () -> Unit,
|
||||||
onMenuActionClick: (RoomListMenuAction) -> Unit,
|
onMenuActionClick: (RoomListMenuAction) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
|
|
@ -236,7 +236,7 @@ private fun HomeScaffold(
|
||||||
onSetUpRecoveryClick = onSetUpRecoveryClick,
|
onSetUpRecoveryClick = onSetUpRecoveryClick,
|
||||||
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
|
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
|
||||||
onRoomClick = ::onRoomClick,
|
onRoomClick = ::onRoomClick,
|
||||||
onCreateRoomClick = onCreateRoomClick,
|
onCreateRoomClick = onStartChatClick,
|
||||||
contentPadding = PaddingValues(
|
contentPadding = PaddingValues(
|
||||||
// FAB height is 56dp, bottom padding is 16dp, we add 8dp as extra margin -> 56+16+8 = 80,
|
// FAB height is 56dp, bottom padding is 16dp, we add 8dp as extra margin -> 56+16+8 = 80,
|
||||||
// and include provided bottom padding
|
// and include provided bottom padding
|
||||||
|
|
@ -280,7 +280,7 @@ private fun HomeScaffold(
|
||||||
floatingActionButton = {
|
floatingActionButton = {
|
||||||
if (state.displayActions) {
|
if (state.displayActions) {
|
||||||
FloatingActionButton(
|
FloatingActionButton(
|
||||||
onClick = onCreateRoomClick,
|
onClick = onStartChatClick,
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = CompoundIcons.Plus(),
|
imageVector = CompoundIcons.Plus(),
|
||||||
|
|
@ -304,7 +304,7 @@ internal fun HomeViewPreview(@PreviewParameter(HomeStateProvider::class) state:
|
||||||
onSettingsClick = {},
|
onSettingsClick = {},
|
||||||
onSetUpRecoveryClick = {},
|
onSetUpRecoveryClick = {},
|
||||||
onConfirmRecoveryKeyClick = {},
|
onConfirmRecoveryKeyClick = {},
|
||||||
onCreateRoomClick = {},
|
onStartChatClick = {},
|
||||||
onRoomSettingsClick = {},
|
onRoomSettingsClick = {},
|
||||||
onReportRoomClick = {},
|
onReportRoomClick = {},
|
||||||
onMenuActionClick = {},
|
onMenuActionClick = {},
|
||||||
|
|
|
||||||
|
|
@ -284,7 +284,7 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setRoomL
|
||||||
onSettingsClick = onSettingsClick,
|
onSettingsClick = onSettingsClick,
|
||||||
onSetUpRecoveryClick = onSetUpRecoveryClick,
|
onSetUpRecoveryClick = onSetUpRecoveryClick,
|
||||||
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
|
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
|
||||||
onCreateRoomClick = onCreateRoomClick,
|
onStartChatClick = onCreateRoomClick,
|
||||||
onRoomSettingsClick = onRoomSettingsClick,
|
onRoomSettingsClick = onRoomSettingsClick,
|
||||||
onMenuActionClick = onMenuActionClick,
|
onMenuActionClick = onMenuActionClick,
|
||||||
onDeclineInviteAndBlockUser = onDeclineInviteAndBlockUser,
|
onDeclineInviteAndBlockUser = onDeclineInviteAndBlockUser,
|
||||||
|
|
|
||||||
18
features/invitepeople/api/build.gradle.kts
Normal file
18
features/invitepeople/api/build.gradle.kts
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* 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-library")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "io.element.android.features.invitepeople.api"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(projects.libraries.architecture)
|
||||||
|
implementation(projects.libraries.matrix.api)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
/*
|
||||||
|
* 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.invitepeople.api
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
|
||||||
|
interface InvitePeoplePresenter {
|
||||||
|
@Composable
|
||||||
|
fun present(): InvitePeopleState
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* 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.invitepeople.api
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
|
||||||
|
interface InvitePeopleRenderer {
|
||||||
|
@Composable
|
||||||
|
fun Render(state: InvitePeopleState, modifier: Modifier)
|
||||||
|
}
|
||||||
|
|
@ -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.invitepeople.api
|
||||||
|
|
||||||
|
interface InvitePeopleState
|
||||||
64
features/invitepeople/impl/build.gradle.kts
Normal file
64
features/invitepeople/impl/build.gradle.kts
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
import extension.ComponentMergingStrategy
|
||||||
|
import extension.setupAnvil
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2022-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.invitepeople.impl"
|
||||||
|
|
||||||
|
testOptions {
|
||||||
|
unitTests {
|
||||||
|
isIncludeAndroidResources = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setupAnvil(componentMergingStrategy = ComponentMergingStrategy.KSP)
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
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)
|
||||||
|
implementation(projects.libraries.androidutils)
|
||||||
|
implementation(projects.libraries.deeplink)
|
||||||
|
implementation(projects.libraries.mediapickers.api)
|
||||||
|
implementation(projects.libraries.mediaupload.api)
|
||||||
|
implementation(projects.libraries.permissions.api)
|
||||||
|
implementation(projects.libraries.usersearch.impl)
|
||||||
|
implementation(projects.services.analytics.api)
|
||||||
|
implementation(libs.coil.compose)
|
||||||
|
implementation(projects.libraries.featureflag.api)
|
||||||
|
api(projects.features.invitepeople.api)
|
||||||
|
|
||||||
|
testImplementation(libs.test.junit)
|
||||||
|
testImplementation(libs.test.mockk)
|
||||||
|
testImplementation(libs.coroutines.test)
|
||||||
|
testImplementation(libs.molecule.runtime)
|
||||||
|
testImplementation(libs.test.truth)
|
||||||
|
testImplementation(libs.test.turbine)
|
||||||
|
testImplementation(libs.test.robolectric)
|
||||||
|
testImplementation(projects.services.analytics.test)
|
||||||
|
testImplementation(projects.libraries.matrix.test)
|
||||||
|
testImplementation(projects.libraries.mediapickers.test)
|
||||||
|
testImplementation(projects.libraries.mediaupload.test)
|
||||||
|
testImplementation(projects.libraries.permissions.test)
|
||||||
|
testImplementation(projects.libraries.usersearch.test)
|
||||||
|
testImplementation(projects.features.startchat.test)
|
||||||
|
testImplementation(projects.libraries.featureflag.test)
|
||||||
|
testImplementation(projects.tests.testutils)
|
||||||
|
testImplementation(libs.androidx.compose.ui.test.junit)
|
||||||
|
testReleaseImplementation(libs.androidx.compose.ui.test.manifest)
|
||||||
|
}
|
||||||
|
|
@ -44,7 +44,7 @@ dependencies {
|
||||||
api(projects.services.apperror.api)
|
api(projects.services.apperror.api)
|
||||||
implementation(libs.coil.compose)
|
implementation(libs.coil.compose)
|
||||||
implementation(projects.features.call.api)
|
implementation(projects.features.call.api)
|
||||||
implementation(projects.features.createroom.api)
|
implementation(projects.features.startchat.api)
|
||||||
implementation(projects.features.leaveroom.api)
|
implementation(projects.features.leaveroom.api)
|
||||||
implementation(projects.features.userprofile.shared)
|
implementation(projects.features.userprofile.shared)
|
||||||
implementation(projects.services.analytics.compose)
|
implementation(projects.services.analytics.compose)
|
||||||
|
|
@ -72,7 +72,7 @@ dependencies {
|
||||||
testImplementation(projects.libraries.usersearch.test)
|
testImplementation(projects.libraries.usersearch.test)
|
||||||
testImplementation(projects.libraries.featureflag.test)
|
testImplementation(projects.libraries.featureflag.test)
|
||||||
testImplementation(projects.tests.testutils)
|
testImplementation(projects.tests.testutils)
|
||||||
testImplementation(projects.features.createroom.test)
|
testImplementation(projects.features.startchat.test)
|
||||||
testImplementation(projects.services.analytics.test)
|
testImplementation(projects.services.analytics.test)
|
||||||
testImplementation(libs.androidx.compose.ui.test.junit)
|
testImplementation(libs.androidx.compose.ui.test.junit)
|
||||||
testReleaseImplementation(libs.androidx.compose.ui.test.manifest)
|
testReleaseImplementation(libs.androidx.compose.ui.test.manifest)
|
||||||
|
|
|
||||||
18
features/startchat/api/build.gradle.kts
Normal file
18
features/startchat/api/build.gradle.kts
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* 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-library")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "io.element.android.features.startchat.api"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(projects.libraries.architecture)
|
||||||
|
implementation(projects.libraries.matrix.api)
|
||||||
|
}
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.api
|
package io.element.android.features.startchat.api
|
||||||
|
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* 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.startchat.api
|
||||||
|
|
||||||
|
import com.bumble.appyx.core.modality.BuildContext
|
||||||
|
import com.bumble.appyx.core.node.Node
|
||||||
|
import com.bumble.appyx.core.plugin.Plugin
|
||||||
|
import io.element.android.libraries.architecture.FeatureEntryPoint
|
||||||
|
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
|
||||||
|
|
||||||
|
interface StartChatEntryPoint : FeatureEntryPoint {
|
||||||
|
fun nodeBuilder(parentNode: Node, buildContext: BuildContext): NodeBuilder
|
||||||
|
interface NodeBuilder {
|
||||||
|
fun callback(callback: Callback): NodeBuilder
|
||||||
|
fun build(): Node
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Callback : Plugin {
|
||||||
|
fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>)
|
||||||
|
fun onOpenRoomDirectory()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.api
|
package io.element.android.features.startchat.api
|
||||||
|
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
64
features/startchat/impl/build.gradle.kts
Normal file
64
features/startchat/impl/build.gradle.kts
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
import extension.ComponentMergingStrategy
|
||||||
|
import extension.setupAnvil
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2022-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.startchat.impl"
|
||||||
|
|
||||||
|
testOptions {
|
||||||
|
unitTests {
|
||||||
|
isIncludeAndroidResources = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setupAnvil(componentMergingStrategy = ComponentMergingStrategy.KSP)
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
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)
|
||||||
|
implementation(projects.libraries.androidutils)
|
||||||
|
implementation(projects.libraries.deeplink)
|
||||||
|
implementation(projects.libraries.mediapickers.api)
|
||||||
|
implementation(projects.libraries.mediaupload.api)
|
||||||
|
implementation(projects.libraries.permissions.api)
|
||||||
|
implementation(projects.libraries.usersearch.impl)
|
||||||
|
implementation(projects.services.analytics.api)
|
||||||
|
implementation(libs.coil.compose)
|
||||||
|
implementation(projects.libraries.featureflag.api)
|
||||||
|
api(projects.features.startchat.api)
|
||||||
|
|
||||||
|
testImplementation(libs.test.junit)
|
||||||
|
testImplementation(libs.test.mockk)
|
||||||
|
testImplementation(libs.coroutines.test)
|
||||||
|
testImplementation(libs.molecule.runtime)
|
||||||
|
testImplementation(libs.test.truth)
|
||||||
|
testImplementation(libs.test.turbine)
|
||||||
|
testImplementation(libs.test.robolectric)
|
||||||
|
testImplementation(projects.services.analytics.test)
|
||||||
|
testImplementation(projects.libraries.matrix.test)
|
||||||
|
testImplementation(projects.libraries.mediapickers.test)
|
||||||
|
testImplementation(projects.libraries.mediaupload.test)
|
||||||
|
testImplementation(projects.libraries.permissions.test)
|
||||||
|
testImplementation(projects.libraries.usersearch.test)
|
||||||
|
testImplementation(projects.features.startchat.test)
|
||||||
|
testImplementation(projects.libraries.featureflag.test)
|
||||||
|
testImplementation(projects.tests.testutils)
|
||||||
|
testImplementation(libs.androidx.compose.ui.test.junit)
|
||||||
|
testReleaseImplementation(libs.androidx.compose.ui.test.manifest)
|
||||||
|
}
|
||||||
|
|
@ -5,18 +5,18 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom
|
package io.element.android.features.startchat
|
||||||
|
|
||||||
import com.bumble.appyx.core.plugin.Plugin
|
import com.bumble.appyx.core.plugin.Plugin
|
||||||
import com.bumble.appyx.navmodel.backstack.BackStack
|
import com.bumble.appyx.navmodel.backstack.BackStack
|
||||||
import com.bumble.appyx.navmodel.backstack.operation.push
|
import com.bumble.appyx.navmodel.backstack.operation.push
|
||||||
import io.element.android.features.createroom.impl.CreateRoomFlowNode.NavTarget
|
import io.element.android.features.startchat.impl.StartChatFlowNode.NavTarget
|
||||||
import io.element.android.libraries.architecture.overlay.Overlay
|
import io.element.android.libraries.architecture.overlay.Overlay
|
||||||
import io.element.android.libraries.architecture.overlay.operation.hide
|
import io.element.android.libraries.architecture.overlay.operation.hide
|
||||||
import io.element.android.libraries.architecture.overlay.operation.show
|
import io.element.android.libraries.architecture.overlay.operation.show
|
||||||
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
|
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
|
||||||
|
|
||||||
interface CreateRoomNavigator : Plugin {
|
interface StartChatNavigator : Plugin {
|
||||||
fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>)
|
fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>)
|
||||||
fun onCreateNewRoom()
|
fun onCreateNewRoom()
|
||||||
fun onShowJoinRoomByAddress()
|
fun onShowJoinRoomByAddress()
|
||||||
|
|
@ -24,12 +24,12 @@ interface CreateRoomNavigator : Plugin {
|
||||||
fun onOpenRoomDirectory()
|
fun onOpenRoomDirectory()
|
||||||
}
|
}
|
||||||
|
|
||||||
class DefaultCreateRoomNavigator(
|
class DefaultStartChatNavigator(
|
||||||
private val backstack: BackStack<NavTarget>,
|
private val backstack: BackStack<NavTarget>,
|
||||||
private val overlay: Overlay<NavTarget>,
|
private val overlay: Overlay<NavTarget>,
|
||||||
private val openRoom: (RoomIdOrAlias, List<String>) -> Unit,
|
private val openRoom: (RoomIdOrAlias, List<String>) -> Unit,
|
||||||
private val openRoomDirectory: () -> Unit,
|
private val openRoomDirectory: () -> Unit,
|
||||||
) : CreateRoomNavigator {
|
) : StartChatNavigator {
|
||||||
override fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>) = openRoom(roomIdOrAlias, serverNames)
|
override fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>) = openRoom(roomIdOrAlias, serverNames)
|
||||||
|
|
||||||
override fun onOpenRoomDirectory() = openRoomDirectory()
|
override fun onOpenRoomDirectory() = openRoomDirectory()
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* 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.startchat.impl
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import io.element.android.features.startchat.impl.configureroom.RoomVisibilityState
|
||||||
|
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
||||||
|
data class CreateRoomConfig(
|
||||||
|
val roomName: String? = null,
|
||||||
|
val topic: String? = null,
|
||||||
|
val avatarUri: Uri? = null,
|
||||||
|
val invites: ImmutableList<MatrixUser> = persistentListOf(),
|
||||||
|
val roomVisibility: RoomVisibilityState = RoomVisibilityState.Private,
|
||||||
|
)
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2023, 2024 New Vector Ltd.
|
* Copyright 2025 New Vector Ltd.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl
|
package io.element.android.features.startchat.impl
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import io.element.android.features.createroom.impl.configureroom.RoomAccess
|
import io.element.android.features.startchat.impl.configureroom.RoomAccess
|
||||||
import io.element.android.features.createroom.impl.configureroom.RoomAccessItem
|
import io.element.android.features.startchat.impl.configureroom.RoomAccessItem
|
||||||
import io.element.android.features.createroom.impl.configureroom.RoomAddress
|
import io.element.android.features.startchat.impl.configureroom.RoomAddress
|
||||||
import io.element.android.features.createroom.impl.configureroom.RoomVisibilityItem
|
import io.element.android.features.startchat.impl.configureroom.RoomVisibilityItem
|
||||||
import io.element.android.features.createroom.impl.configureroom.RoomVisibilityState
|
import io.element.android.features.startchat.impl.configureroom.RoomVisibilityState
|
||||||
import io.element.android.features.createroom.impl.di.CreateRoomScope
|
import io.element.android.features.startchat.impl.di.CreateRoomScope
|
||||||
import io.element.android.features.createroom.impl.userlist.UserListDataStore
|
import io.element.android.features.startchat.impl.userlist.UserListDataStore
|
||||||
import io.element.android.libraries.androidutils.file.safeDelete
|
import io.element.android.libraries.androidutils.file.safeDelete
|
||||||
import io.element.android.libraries.di.SingleIn
|
import io.element.android.libraries.di.SingleIn
|
||||||
import io.element.android.libraries.matrix.api.room.alias.RoomAliasHelper
|
import io.element.android.libraries.matrix.api.room.alias.RoomAliasHelper
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2023, 2024 New Vector Ltd.
|
* Copyright 2025 New Vector Ltd.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl
|
package io.element.android.features.startchat.impl
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
|
@ -19,10 +19,10 @@ import com.bumble.appyx.navmodel.backstack.operation.push
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import io.element.android.anvilannotations.ContributesNode
|
import io.element.android.anvilannotations.ContributesNode
|
||||||
import io.element.android.features.createroom.CreateRoomNavigator
|
import io.element.android.features.startchat.StartChatNavigator
|
||||||
import io.element.android.features.createroom.impl.addpeople.AddPeopleNode
|
import io.element.android.features.startchat.impl.addpeople.AddPeopleNode
|
||||||
import io.element.android.features.createroom.impl.configureroom.ConfigureRoomNode
|
import io.element.android.features.startchat.impl.configureroom.ConfigureRoomNode
|
||||||
import io.element.android.features.createroom.impl.di.CreateRoomComponent
|
import io.element.android.features.startchat.impl.di.CreateRoomComponent
|
||||||
import io.element.android.libraries.architecture.BackstackView
|
import io.element.android.libraries.architecture.BackstackView
|
||||||
import io.element.android.libraries.architecture.BaseFlowNode
|
import io.element.android.libraries.architecture.BaseFlowNode
|
||||||
import io.element.android.libraries.architecture.bindings
|
import io.element.android.libraries.architecture.bindings
|
||||||
|
|
@ -32,13 +32,13 @@ import io.element.android.libraries.di.SessionScope
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
@ContributesNode(SessionScope::class)
|
@ContributesNode(SessionScope::class)
|
||||||
class ConfigureRoomFlowNode @AssistedInject constructor(
|
class CreateRoomFlowNode @AssistedInject constructor(
|
||||||
@Assisted buildContext: BuildContext,
|
@Assisted buildContext: BuildContext,
|
||||||
@Assisted plugins: List<Plugin>,
|
@Assisted plugins: List<Plugin>,
|
||||||
) : DaggerComponentOwner,
|
) : DaggerComponentOwner,
|
||||||
BaseFlowNode<ConfigureRoomFlowNode.NavTarget>(
|
BaseFlowNode<CreateRoomFlowNode.NavTarget>(
|
||||||
backstack = BackStack(
|
backstack = BackStack(
|
||||||
initialElement = NavTarget.Root,
|
initialElement = NavTarget.ConfigureRoom,
|
||||||
savedStateMap = buildContext.savedStateMap,
|
savedStateMap = buildContext.savedStateMap,
|
||||||
),
|
),
|
||||||
buildContext = buildContext,
|
buildContext = buildContext,
|
||||||
|
|
@ -47,14 +47,14 @@ class ConfigureRoomFlowNode @AssistedInject constructor(
|
||||||
private val component by lazy {
|
private val component by lazy {
|
||||||
parent!!.bindings<CreateRoomComponent.ParentBindings>().createRoomComponentBuilder().build()
|
parent!!.bindings<CreateRoomComponent.ParentBindings>().createRoomComponentBuilder().build()
|
||||||
}
|
}
|
||||||
private val navigator = plugins<CreateRoomNavigator>().first()
|
private val navigator = plugins<StartChatNavigator>().first()
|
||||||
|
|
||||||
override val daggerComponent: Any
|
override val daggerComponent: Any
|
||||||
get() = component
|
get() = component
|
||||||
|
|
||||||
sealed interface NavTarget : Parcelable {
|
sealed interface NavTarget : Parcelable {
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data object Root : NavTarget
|
data object AddPeople : NavTarget
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data object ConfigureRoom : NavTarget
|
data object ConfigureRoom : NavTarget
|
||||||
|
|
@ -62,7 +62,7 @@ class ConfigureRoomFlowNode @AssistedInject constructor(
|
||||||
|
|
||||||
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
|
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
|
||||||
return when (navTarget) {
|
return when (navTarget) {
|
||||||
NavTarget.Root -> {
|
NavTarget.AddPeople -> {
|
||||||
val callback = object : AddPeopleNode.Callback {
|
val callback = object : AddPeopleNode.Callback {
|
||||||
override fun onContinue() {
|
override fun onContinue() {
|
||||||
backstack.push(NavTarget.ConfigureRoom)
|
backstack.push(NavTarget.ConfigureRoom)
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* 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.startchat.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.startchat.api.StartChatEntryPoint
|
||||||
|
import io.element.android.libraries.architecture.createNode
|
||||||
|
import io.element.android.libraries.di.AppScope
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ContributesBinding(AppScope::class)
|
||||||
|
class DefaultStartChatEntryPoint @Inject constructor() : StartChatEntryPoint {
|
||||||
|
override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): StartChatEntryPoint.NodeBuilder {
|
||||||
|
val plugins = ArrayList<Plugin>()
|
||||||
|
|
||||||
|
return object : StartChatEntryPoint.NodeBuilder {
|
||||||
|
override fun callback(callback: StartChatEntryPoint.Callback): StartChatEntryPoint.NodeBuilder {
|
||||||
|
plugins += callback
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun build(): Node {
|
||||||
|
return parentNode.createNode<StartChatFlowNode>(buildContext, plugins)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,13 +5,13 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl
|
package io.element.android.features.startchat.impl
|
||||||
|
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
import com.squareup.anvil.annotations.ContributesBinding
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
import im.vector.app.features.analytics.plan.CreatedRoom
|
import im.vector.app.features.analytics.plan.CreatedRoom
|
||||||
import io.element.android.features.createroom.api.ConfirmingStartDmWithMatrixUser
|
import io.element.android.features.startchat.api.ConfirmingStartDmWithMatrixUser
|
||||||
import io.element.android.features.createroom.api.StartDMAction
|
import io.element.android.features.startchat.api.StartDMAction
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
import io.element.android.libraries.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* 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.startchat.impl
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import com.bumble.appyx.core.modality.BuildContext
|
||||||
|
import com.bumble.appyx.core.navigation.transition.JumpToEndTransitionHandler
|
||||||
|
import com.bumble.appyx.core.node.Node
|
||||||
|
import com.bumble.appyx.core.plugin.Plugin
|
||||||
|
import com.bumble.appyx.core.plugin.plugins
|
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStack
|
||||||
|
import dagger.assisted.Assisted
|
||||||
|
import dagger.assisted.AssistedInject
|
||||||
|
import io.element.android.anvilannotations.ContributesNode
|
||||||
|
import io.element.android.features.startchat.DefaultStartChatNavigator
|
||||||
|
import io.element.android.features.startchat.api.StartChatEntryPoint
|
||||||
|
import io.element.android.features.startchat.impl.joinbyaddress.JoinRoomByAddressNode
|
||||||
|
import io.element.android.features.startchat.impl.root.StartChatNode
|
||||||
|
import io.element.android.libraries.architecture.BackstackView
|
||||||
|
import io.element.android.libraries.architecture.BaseFlowNode
|
||||||
|
import io.element.android.libraries.architecture.OverlayView
|
||||||
|
import io.element.android.libraries.architecture.createNode
|
||||||
|
import io.element.android.libraries.di.SessionScope
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@ContributesNode(SessionScope::class)
|
||||||
|
class StartChatFlowNode @AssistedInject constructor(
|
||||||
|
@Assisted buildContext: BuildContext,
|
||||||
|
@Assisted plugins: List<Plugin>,
|
||||||
|
) : BaseFlowNode<StartChatFlowNode.NavTarget>(
|
||||||
|
backstack = BackStack(
|
||||||
|
initialElement = NavTarget.Root,
|
||||||
|
savedStateMap = buildContext.savedStateMap,
|
||||||
|
),
|
||||||
|
buildContext = buildContext,
|
||||||
|
plugins = plugins
|
||||||
|
) {
|
||||||
|
sealed interface NavTarget : Parcelable {
|
||||||
|
@Parcelize
|
||||||
|
data object Root : NavTarget
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
data object NewRoom : NavTarget
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
data object JoinByAddress : NavTarget
|
||||||
|
}
|
||||||
|
|
||||||
|
private val navigator = DefaultStartChatNavigator(
|
||||||
|
backstack = backstack,
|
||||||
|
overlay = overlay,
|
||||||
|
openRoom = { roomIdOrAlias, viaServers ->
|
||||||
|
plugins<StartChatEntryPoint.Callback>().forEach { it.onOpenRoom(roomIdOrAlias, viaServers) }
|
||||||
|
},
|
||||||
|
openRoomDirectory = {
|
||||||
|
plugins<StartChatEntryPoint.Callback>().forEach { it.onOpenRoomDirectory() }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
|
||||||
|
return when (navTarget) {
|
||||||
|
NavTarget.Root -> {
|
||||||
|
createNode<StartChatNode>(buildContext = buildContext, plugins = listOf(navigator))
|
||||||
|
}
|
||||||
|
NavTarget.NewRoom -> {
|
||||||
|
createNode<CreateRoomFlowNode>(buildContext = buildContext, plugins = listOf(navigator))
|
||||||
|
}
|
||||||
|
NavTarget.JoinByAddress -> {
|
||||||
|
createNode<JoinRoomByAddressNode>(buildContext = buildContext, plugins = listOf(navigator))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun View(modifier: Modifier) {
|
||||||
|
Box(modifier = modifier) {
|
||||||
|
BackstackView()
|
||||||
|
OverlayView(transitionHandler = remember { JumpToEndTransitionHandler() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* 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.startchat.impl.addpeople
|
||||||
|
|
||||||
|
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 com.bumble.appyx.core.plugin.plugins
|
||||||
|
import dagger.assisted.Assisted
|
||||||
|
import dagger.assisted.AssistedInject
|
||||||
|
import io.element.android.anvilannotations.ContributesNode
|
||||||
|
import io.element.android.features.startchat.impl.di.CreateRoomScope
|
||||||
|
|
||||||
|
@ContributesNode(CreateRoomScope::class)
|
||||||
|
class AddPeopleNode @AssistedInject constructor(
|
||||||
|
@Assisted buildContext: BuildContext,
|
||||||
|
@Assisted plugins: List<Plugin>,
|
||||||
|
private val presenter: AddPeoplePresenter,
|
||||||
|
) : Node(buildContext, plugins = plugins) {
|
||||||
|
interface Callback : Plugin {
|
||||||
|
fun onContinue()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onContinue() {
|
||||||
|
plugins<Callback>().forEach { it.onContinue() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun View(modifier: Modifier) {
|
||||||
|
val state = presenter.present()
|
||||||
|
AddPeopleView(
|
||||||
|
state = state,
|
||||||
|
modifier = modifier,
|
||||||
|
onBackClick = this::navigateUp,
|
||||||
|
onSkipClick = this::onContinue,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2023, 2024 New Vector Ltd.
|
* Copyright 2025 New Vector Ltd.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.addpeople
|
package io.element.android.features.startchat.impl.addpeople
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import io.element.android.features.createroom.impl.CreateRoomDataStore
|
import io.element.android.features.startchat.impl.CreateRoomDataStore
|
||||||
import io.element.android.features.createroom.impl.userlist.SelectionMode
|
import io.element.android.features.startchat.impl.userlist.SelectionMode
|
||||||
import io.element.android.features.createroom.impl.userlist.UserListPresenter
|
import io.element.android.features.startchat.impl.userlist.UserListPresenter
|
||||||
import io.element.android.features.createroom.impl.userlist.UserListPresenterArgs
|
import io.element.android.features.startchat.impl.userlist.UserListPresenterArgs
|
||||||
import io.element.android.features.createroom.impl.userlist.UserListState
|
import io.element.android.features.startchat.impl.userlist.UserListState
|
||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
import io.element.android.libraries.usersearch.api.UserRepository
|
import io.element.android.libraries.usersearch.api.UserRepository
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2023, 2024 New Vector Ltd.
|
* Copyright 2025 New Vector Ltd.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.addpeople
|
package io.element.android.features.startchat.impl.addpeople
|
||||||
|
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
import io.element.android.features.createroom.impl.userlist.SelectionMode
|
import io.element.android.features.startchat.impl.userlist.SelectionMode
|
||||||
import io.element.android.features.createroom.impl.userlist.UserListState
|
import io.element.android.features.startchat.impl.userlist.UserListState
|
||||||
import io.element.android.features.createroom.impl.userlist.aRecentDirectRoomList
|
import io.element.android.features.startchat.impl.userlist.aRecentDirectRoomList
|
||||||
import io.element.android.features.createroom.impl.userlist.aUserListState
|
import io.element.android.features.startchat.impl.userlist.aUserListState
|
||||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||||
import io.element.android.libraries.matrix.ui.components.aMatrixUserList
|
import io.element.android.libraries.matrix.ui.components.aMatrixUserList
|
||||||
import io.element.android.libraries.usersearch.api.UserSearchResult
|
import io.element.android.libraries.usersearch.api.UserSearchResult
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2022-2024 New Vector Ltd.
|
* Copyright 2025 New Vector Ltd.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.addpeople
|
package io.element.android.features.startchat.impl.addpeople
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
|
@ -15,10 +15,10 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import io.element.android.features.createroom.impl.R
|
import io.element.android.features.startchat.impl.R
|
||||||
import io.element.android.features.createroom.impl.components.UserListView
|
import io.element.android.features.startchat.impl.components.UserListView
|
||||||
import io.element.android.features.createroom.impl.userlist.UserListEvents
|
import io.element.android.features.startchat.impl.userlist.UserListEvents
|
||||||
import io.element.android.features.createroom.impl.userlist.UserListState
|
import io.element.android.features.startchat.impl.userlist.UserListState
|
||||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||||
|
|
@ -31,7 +31,7 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
fun AddPeopleView(
|
fun AddPeopleView(
|
||||||
state: UserListState,
|
state: UserListState,
|
||||||
onBackClick: () -> Unit,
|
onBackClick: () -> Unit,
|
||||||
onNextClick: () -> Unit,
|
onSkipClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|
@ -46,7 +46,7 @@ fun AddPeopleView(
|
||||||
onBackClick()
|
onBackClick()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onNextClick = onNextClick,
|
onNextClick = onSkipClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) { padding ->
|
) { padding ->
|
||||||
|
|
@ -89,6 +89,6 @@ internal fun AddPeopleViewPreview(@PreviewParameter(AddPeopleUserListStateProvid
|
||||||
AddPeopleView(
|
AddPeopleView(
|
||||||
state = state,
|
state = state,
|
||||||
onBackClick = {},
|
onBackClick = {},
|
||||||
onNextClick = {},
|
onSkipClick = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.components
|
package io.element.android.features.startchat.impl.components
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.components
|
package io.element.android.features.startchat.impl.components
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.components
|
package io.element.android.features.startchat.impl.components
|
||||||
|
|
||||||
import androidx.compose.animation.animateColorAsState
|
import androidx.compose.animation.animateColorAsState
|
||||||
import androidx.compose.animation.core.Spring
|
import androidx.compose.animation.core.Spring
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2023, 2024 New Vector Ltd.
|
* Copyright 2025 New Vector Ltd.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.components
|
package io.element.android.features.startchat.impl.components
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
|
@ -16,9 +16,9 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.element.android.features.createroom.impl.userlist.UserListEvents
|
import io.element.android.features.startchat.impl.userlist.UserListEvents
|
||||||
import io.element.android.features.createroom.impl.userlist.UserListState
|
import io.element.android.features.startchat.impl.userlist.UserListState
|
||||||
import io.element.android.features.createroom.impl.userlist.UserListStateProvider
|
import io.element.android.features.startchat.impl.userlist.UserListStateProvider
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* 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.startchat.impl.configureroom
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
|
import io.element.android.libraries.matrix.ui.media.AvatarAction
|
||||||
|
|
||||||
|
sealed interface ConfigureRoomEvents {
|
||||||
|
data class RoomNameChanged(val name: String) : ConfigureRoomEvents
|
||||||
|
data class TopicChanged(val topic: String) : ConfigureRoomEvents
|
||||||
|
data class RoomVisibilityChanged(val visibilityItem: RoomVisibilityItem) : ConfigureRoomEvents
|
||||||
|
data class RoomAccessChanged(val roomAccess: RoomAccessItem) : ConfigureRoomEvents
|
||||||
|
data class RoomAddressChanged(val roomAddress: String) : ConfigureRoomEvents
|
||||||
|
data class RemoveUserFromSelection(val matrixUser: MatrixUser) : ConfigureRoomEvents
|
||||||
|
data object CreateRoom : ConfigureRoomEvents
|
||||||
|
data class HandleAvatarAction(val action: AvatarAction) : ConfigureRoomEvents
|
||||||
|
data object CancelCreateRoom : ConfigureRoomEvents
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* 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.startchat.impl.configureroom
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import com.bumble.appyx.core.lifecycle.subscribe
|
||||||
|
import com.bumble.appyx.core.modality.BuildContext
|
||||||
|
import com.bumble.appyx.core.node.Node
|
||||||
|
import com.bumble.appyx.core.plugin.Plugin
|
||||||
|
import com.bumble.appyx.core.plugin.plugins
|
||||||
|
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.startchat.StartChatNavigator
|
||||||
|
import io.element.android.features.startchat.impl.di.CreateRoomScope
|
||||||
|
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
|
||||||
|
import io.element.android.services.analytics.api.AnalyticsService
|
||||||
|
|
||||||
|
@ContributesNode(CreateRoomScope::class)
|
||||||
|
class ConfigureRoomNode @AssistedInject constructor(
|
||||||
|
@Assisted buildContext: BuildContext,
|
||||||
|
@Assisted plugins: List<Plugin>,
|
||||||
|
private val presenter: ConfigureRoomPresenter,
|
||||||
|
private val analyticsService: AnalyticsService,
|
||||||
|
) : Node(buildContext, plugins = plugins) {
|
||||||
|
private val navigator = plugins<StartChatNavigator>().first()
|
||||||
|
|
||||||
|
init {
|
||||||
|
lifecycle.subscribe(
|
||||||
|
onResume = {
|
||||||
|
analyticsService.screen(MobileScreen(screenName = MobileScreen.ScreenName.CreateRoom))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun View(modifier: Modifier) {
|
||||||
|
val state = presenter.present()
|
||||||
|
ConfigureRoomView(
|
||||||
|
state = state,
|
||||||
|
modifier = modifier,
|
||||||
|
onBackClick = this::navigateUp,
|
||||||
|
onCreateRoomSuccess = {
|
||||||
|
navigator.onOpenRoom(roomIdOrAlias = it.toRoomIdOrAlias(), serverNames = emptyList())
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,209 @@
|
||||||
|
/*
|
||||||
|
* 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.startchat.impl.configureroom
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.MutableState
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import im.vector.app.features.analytics.plan.CreatedRoom
|
||||||
|
import io.element.android.features.startchat.impl.CreateRoomConfig
|
||||||
|
import io.element.android.features.startchat.impl.CreateRoomDataStore
|
||||||
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
|
import io.element.android.libraries.architecture.Presenter
|
||||||
|
import io.element.android.libraries.architecture.runCatchingUpdatingState
|
||||||
|
import io.element.android.libraries.core.mimetype.MimeTypes
|
||||||
|
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||||
|
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||||
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
|
import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters
|
||||||
|
import io.element.android.libraries.matrix.api.createroom.RoomPreset
|
||||||
|
import io.element.android.libraries.matrix.api.room.alias.RoomAliasHelper
|
||||||
|
import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility
|
||||||
|
import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility
|
||||||
|
import io.element.android.libraries.matrix.ui.media.AvatarAction
|
||||||
|
import io.element.android.libraries.matrix.ui.room.address.RoomAddressValidity
|
||||||
|
import io.element.android.libraries.matrix.ui.room.address.RoomAddressValidityEffect
|
||||||
|
import io.element.android.libraries.mediapickers.api.PickerProvider
|
||||||
|
import io.element.android.libraries.mediaupload.api.MediaPreProcessor
|
||||||
|
import io.element.android.libraries.permissions.api.PermissionsEvents
|
||||||
|
import io.element.android.libraries.permissions.api.PermissionsPresenter
|
||||||
|
import io.element.android.services.analytics.api.AnalyticsService
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import timber.log.Timber
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlin.jvm.optionals.getOrDefault
|
||||||
|
|
||||||
|
class ConfigureRoomPresenter @Inject constructor(
|
||||||
|
private val dataStore: CreateRoomDataStore,
|
||||||
|
private val matrixClient: MatrixClient,
|
||||||
|
private val mediaPickerProvider: PickerProvider,
|
||||||
|
private val mediaPreProcessor: MediaPreProcessor,
|
||||||
|
private val analyticsService: AnalyticsService,
|
||||||
|
permissionsPresenterFactory: PermissionsPresenter.Factory,
|
||||||
|
private val featureFlagService: FeatureFlagService,
|
||||||
|
private val roomAliasHelper: RoomAliasHelper,
|
||||||
|
) : Presenter<ConfigureRoomState> {
|
||||||
|
private val cameraPermissionPresenter: PermissionsPresenter = permissionsPresenterFactory.create(android.Manifest.permission.CAMERA)
|
||||||
|
private var pendingPermissionRequest = false
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun present(): ConfigureRoomState {
|
||||||
|
val cameraPermissionState = cameraPermissionPresenter.present()
|
||||||
|
val createRoomConfig by dataStore.createRoomConfigWithInvites.collectAsState(CreateRoomConfig())
|
||||||
|
val homeserverName = remember { matrixClient.userIdServerName() }
|
||||||
|
val isKnockFeatureEnabled by remember {
|
||||||
|
featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock)
|
||||||
|
}.collectAsState(initial = false)
|
||||||
|
val roomAddressValidity = remember {
|
||||||
|
mutableStateOf<RoomAddressValidity>(RoomAddressValidity.Unknown)
|
||||||
|
}
|
||||||
|
|
||||||
|
val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker(
|
||||||
|
onResult = { uri -> if (uri != null) dataStore.setAvatarUri(uri = uri, cached = true) },
|
||||||
|
)
|
||||||
|
val galleryImagePicker = mediaPickerProvider.registerGalleryImagePicker(
|
||||||
|
onResult = { uri -> if (uri != null) dataStore.setAvatarUri(uri = uri) }
|
||||||
|
)
|
||||||
|
|
||||||
|
val avatarActions by remember(createRoomConfig.avatarUri) {
|
||||||
|
derivedStateOf {
|
||||||
|
listOfNotNull(
|
||||||
|
AvatarAction.TakePhoto,
|
||||||
|
AvatarAction.ChoosePhoto,
|
||||||
|
AvatarAction.Remove.takeIf { createRoomConfig.avatarUri != null },
|
||||||
|
).toImmutableList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(cameraPermissionState.permissionGranted) {
|
||||||
|
if (cameraPermissionState.permissionGranted && pendingPermissionRequest) {
|
||||||
|
pendingPermissionRequest = false
|
||||||
|
cameraPhotoPicker.launch()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RoomAddressValidityEffect(
|
||||||
|
client = matrixClient,
|
||||||
|
roomAliasHelper = roomAliasHelper,
|
||||||
|
newRoomAddress = createRoomConfig.roomVisibility.roomAddress().getOrDefault(""),
|
||||||
|
knownRoomAddress = null,
|
||||||
|
) { newRoomAddressValidity ->
|
||||||
|
roomAddressValidity.value = newRoomAddressValidity
|
||||||
|
}
|
||||||
|
|
||||||
|
val localCoroutineScope = rememberCoroutineScope()
|
||||||
|
val createRoomAction: MutableState<AsyncAction<RoomId>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
|
||||||
|
|
||||||
|
fun createRoom(config: CreateRoomConfig) {
|
||||||
|
createRoomAction.value = AsyncAction.Uninitialized
|
||||||
|
localCoroutineScope.createRoom(config, createRoomAction)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun handleEvents(event: ConfigureRoomEvents) {
|
||||||
|
when (event) {
|
||||||
|
is ConfigureRoomEvents.RoomNameChanged -> dataStore.setRoomName(event.name)
|
||||||
|
is ConfigureRoomEvents.TopicChanged -> dataStore.setTopic(event.topic)
|
||||||
|
is ConfigureRoomEvents.RoomVisibilityChanged -> dataStore.setRoomVisibility(event.visibilityItem)
|
||||||
|
is ConfigureRoomEvents.RemoveUserFromSelection -> dataStore.selectedUserListDataStore.removeUserFromSelection(event.matrixUser)
|
||||||
|
is ConfigureRoomEvents.RoomAccessChanged -> dataStore.setRoomAccess(event.roomAccess)
|
||||||
|
is ConfigureRoomEvents.RoomAddressChanged -> dataStore.setRoomAddress(event.roomAddress)
|
||||||
|
is ConfigureRoomEvents.CreateRoom -> createRoom(createRoomConfig)
|
||||||
|
is ConfigureRoomEvents.HandleAvatarAction -> {
|
||||||
|
when (event.action) {
|
||||||
|
AvatarAction.ChoosePhoto -> galleryImagePicker.launch()
|
||||||
|
AvatarAction.TakePhoto -> if (cameraPermissionState.permissionGranted) {
|
||||||
|
cameraPhotoPicker.launch()
|
||||||
|
} else {
|
||||||
|
pendingPermissionRequest = true
|
||||||
|
cameraPermissionState.eventSink(PermissionsEvents.RequestPermissions)
|
||||||
|
}
|
||||||
|
AvatarAction.Remove -> dataStore.setAvatarUri(uri = null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigureRoomEvents.CancelCreateRoom -> createRoomAction.value = AsyncAction.Uninitialized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ConfigureRoomState(
|
||||||
|
isKnockFeatureEnabled = isKnockFeatureEnabled,
|
||||||
|
config = createRoomConfig,
|
||||||
|
avatarActions = avatarActions,
|
||||||
|
createRoomAction = createRoomAction.value,
|
||||||
|
cameraPermissionState = cameraPermissionState,
|
||||||
|
homeserverName = homeserverName,
|
||||||
|
roomAddressValidity = roomAddressValidity.value,
|
||||||
|
eventSink = ::handleEvents,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun CoroutineScope.createRoom(
|
||||||
|
config: CreateRoomConfig,
|
||||||
|
createRoomAction: MutableState<AsyncAction<RoomId>>
|
||||||
|
) = launch {
|
||||||
|
suspend {
|
||||||
|
val avatarUrl = config.avatarUri?.let { uploadAvatar(it) }
|
||||||
|
val params = if (config.roomVisibility is RoomVisibilityState.Public) {
|
||||||
|
CreateRoomParameters(
|
||||||
|
name = config.roomName,
|
||||||
|
topic = config.topic,
|
||||||
|
isEncrypted = false,
|
||||||
|
isDirect = false,
|
||||||
|
visibility = RoomVisibility.Public,
|
||||||
|
joinRuleOverride = config.roomVisibility.roomAccess.toJoinRule(),
|
||||||
|
preset = RoomPreset.PUBLIC_CHAT,
|
||||||
|
invite = config.invites.map { it.userId },
|
||||||
|
avatar = avatarUrl,
|
||||||
|
roomAliasName = config.roomVisibility.roomAddress()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
CreateRoomParameters(
|
||||||
|
name = config.roomName,
|
||||||
|
topic = config.topic,
|
||||||
|
isEncrypted = config.roomVisibility is RoomVisibilityState.Private,
|
||||||
|
isDirect = false,
|
||||||
|
visibility = RoomVisibility.Private,
|
||||||
|
historyVisibilityOverride = RoomHistoryVisibility.Invited,
|
||||||
|
preset = RoomPreset.PRIVATE_CHAT,
|
||||||
|
invite = config.invites.map { it.userId },
|
||||||
|
avatar = avatarUrl,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
matrixClient.createRoom(params)
|
||||||
|
.onFailure { failure ->
|
||||||
|
Timber.e(failure, "Failed to create room")
|
||||||
|
}
|
||||||
|
.onSuccess {
|
||||||
|
dataStore.clearCachedData()
|
||||||
|
analyticsService.capture(CreatedRoom(isDM = false))
|
||||||
|
}
|
||||||
|
.getOrThrow()
|
||||||
|
}.runCatchingUpdatingState(createRoomAction)
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun uploadAvatar(avatarUri: Uri): String {
|
||||||
|
val preprocessed = mediaPreProcessor.process(
|
||||||
|
uri = avatarUri,
|
||||||
|
mimeType = MimeTypes.Jpeg,
|
||||||
|
deleteOriginal = false,
|
||||||
|
compressIfPossible = false,
|
||||||
|
).getOrThrow()
|
||||||
|
val byteArray = preprocessed.file.readBytes()
|
||||||
|
return matrixClient.uploadMedia(MimeTypes.Jpeg, byteArray, null).getOrThrow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
/*
|
||||||
|
* 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.startchat.impl.configureroom
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
|
|
||||||
|
data class ConfigureRoomPresenterArgs(
|
||||||
|
val selectedUsers: List<MatrixUser>,
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* 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.startchat.impl.configureroom
|
||||||
|
|
||||||
|
import io.element.android.features.startchat.impl.CreateRoomConfig
|
||||||
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
|
import io.element.android.libraries.matrix.ui.media.AvatarAction
|
||||||
|
import io.element.android.libraries.matrix.ui.room.address.RoomAddressValidity
|
||||||
|
import io.element.android.libraries.permissions.api.PermissionsState
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
|
data class ConfigureRoomState(
|
||||||
|
val isKnockFeatureEnabled: Boolean,
|
||||||
|
val config: CreateRoomConfig,
|
||||||
|
val avatarActions: ImmutableList<AvatarAction>,
|
||||||
|
val createRoomAction: AsyncAction<RoomId>,
|
||||||
|
val cameraPermissionState: PermissionsState,
|
||||||
|
val roomAddressValidity: RoomAddressValidity,
|
||||||
|
val homeserverName: String,
|
||||||
|
val eventSink: (ConfigureRoomEvents) -> Unit
|
||||||
|
) {
|
||||||
|
val isValid: Boolean = config.roomName?.isNotEmpty() == true &&
|
||||||
|
(config.roomVisibility is RoomVisibilityState.Private || roomAddressValidity == RoomAddressValidity.Valid)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* 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.startchat.impl.configureroom
|
||||||
|
|
||||||
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
|
import io.element.android.features.startchat.impl.CreateRoomConfig
|
||||||
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
|
import io.element.android.libraries.matrix.ui.components.aMatrixUserList
|
||||||
|
import io.element.android.libraries.matrix.ui.media.AvatarAction
|
||||||
|
import io.element.android.libraries.matrix.ui.room.address.RoomAddressValidity
|
||||||
|
import io.element.android.libraries.permissions.api.PermissionsState
|
||||||
|
import io.element.android.libraries.permissions.api.aPermissionsState
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
|
|
||||||
|
open class ConfigureRoomStateProvider : PreviewParameterProvider<ConfigureRoomState> {
|
||||||
|
override val values: Sequence<ConfigureRoomState>
|
||||||
|
get() = sequenceOf(
|
||||||
|
aConfigureRoomState(),
|
||||||
|
aConfigureRoomState(
|
||||||
|
isKnockFeatureEnabled = false,
|
||||||
|
config = CreateRoomConfig(
|
||||||
|
roomName = "Room 101",
|
||||||
|
topic = "Room topic for this room when the text goes onto multiple lines and is really long, there shouldn’t be more than 3 lines",
|
||||||
|
invites = aMatrixUserList().toImmutableList(),
|
||||||
|
roomVisibility = RoomVisibilityState.Public(
|
||||||
|
roomAddress = RoomAddress.AutoFilled("Room-101"),
|
||||||
|
roomAccess = RoomAccess.Knocking,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
aConfigureRoomState(
|
||||||
|
config = CreateRoomConfig(
|
||||||
|
roomName = "Room 101",
|
||||||
|
topic = "Room topic for this room when the text goes onto multiple lines and is really long, there shouldn’t be more than 3 lines",
|
||||||
|
invites = aMatrixUserList().toImmutableList(),
|
||||||
|
roomVisibility = RoomVisibilityState.Public(
|
||||||
|
roomAddress = RoomAddress.AutoFilled("Room-101"),
|
||||||
|
roomAccess = RoomAccess.Knocking,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
aConfigureRoomState(
|
||||||
|
config = CreateRoomConfig(
|
||||||
|
roomName = "Room 101",
|
||||||
|
topic = "Room topic for this room when the text goes onto multiple lines and is really long, there shouldn’t be more than 3 lines",
|
||||||
|
roomVisibility = RoomVisibilityState.Public(
|
||||||
|
roomAddress = RoomAddress.AutoFilled("Room-101"),
|
||||||
|
roomAccess = RoomAccess.Knocking,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
roomAddressValidity = RoomAddressValidity.NotAvailable,
|
||||||
|
),
|
||||||
|
aConfigureRoomState(
|
||||||
|
config = CreateRoomConfig(
|
||||||
|
roomName = "Room 101",
|
||||||
|
topic = "Room topic for this room when the text goes onto multiple lines and is really long, there shouldn’t be more than 3 lines",
|
||||||
|
roomVisibility = RoomVisibilityState.Public(
|
||||||
|
roomAddress = RoomAddress.AutoFilled("Room-101"),
|
||||||
|
roomAccess = RoomAccess.Knocking,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
roomAddressValidity = RoomAddressValidity.InvalidSymbols,
|
||||||
|
),
|
||||||
|
aConfigureRoomState(
|
||||||
|
config = CreateRoomConfig(
|
||||||
|
roomName = "Room 101",
|
||||||
|
topic = "Room topic for this room when the text goes onto multiple lines and is really long, there shouldn’t be more than 3 lines",
|
||||||
|
roomVisibility = RoomVisibilityState.Public(
|
||||||
|
roomAddress = RoomAddress.AutoFilled("Room-101"),
|
||||||
|
roomAccess = RoomAccess.Knocking,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
roomAddressValidity = RoomAddressValidity.Valid,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun aConfigureRoomState(
|
||||||
|
config: CreateRoomConfig = CreateRoomConfig(),
|
||||||
|
isKnockFeatureEnabled: Boolean = true,
|
||||||
|
avatarActions: List<AvatarAction> = emptyList(),
|
||||||
|
createRoomAction: AsyncAction<RoomId> = AsyncAction.Uninitialized,
|
||||||
|
cameraPermissionState: PermissionsState = aPermissionsState(showDialog = false),
|
||||||
|
homeserverName: String = "matrix.org",
|
||||||
|
roomAddressValidity: RoomAddressValidity = RoomAddressValidity.Valid,
|
||||||
|
eventSink: (ConfigureRoomEvents) -> Unit = { },
|
||||||
|
) = ConfigureRoomState(
|
||||||
|
config = config,
|
||||||
|
isKnockFeatureEnabled = isKnockFeatureEnabled,
|
||||||
|
avatarActions = avatarActions.toImmutableList(),
|
||||||
|
createRoomAction = createRoomAction,
|
||||||
|
cameraPermissionState = cameraPermissionState,
|
||||||
|
homeserverName = homeserverName,
|
||||||
|
roomAddressValidity = roomAddressValidity,
|
||||||
|
eventSink = eventSink,
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,339 @@
|
||||||
|
/*
|
||||||
|
* 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.startchat.impl.configureroom
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.ColumnScope
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||||
|
import androidx.compose.foundation.layout.imePadding
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.selection.selectableGroup
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalFocusManager
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||||
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import io.element.android.compound.theme.ElementTheme
|
||||||
|
import io.element.android.features.startchat.impl.R
|
||||||
|
import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage
|
||||||
|
import io.element.android.libraries.designsystem.atomic.atoms.RoundedIconAtom
|
||||||
|
import io.element.android.libraries.designsystem.atomic.atoms.RoundedIconAtomSize
|
||||||
|
import io.element.android.libraries.designsystem.components.async.AsyncActionView
|
||||||
|
import io.element.android.libraries.designsystem.components.async.AsyncActionViewDefaults
|
||||||
|
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||||
|
import io.element.android.libraries.designsystem.components.avatar.AvatarType
|
||||||
|
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||||
|
import io.element.android.libraries.designsystem.components.list.ListItemContent
|
||||||
|
import io.element.android.libraries.designsystem.modifiers.clearFocusOnTap
|
||||||
|
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||||
|
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||||
|
import io.element.android.libraries.designsystem.preview.PreviewWithLargeHeight
|
||||||
|
import io.element.android.libraries.designsystem.theme.components.ListItem
|
||||||
|
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.TextButton
|
||||||
|
import io.element.android.libraries.designsystem.theme.components.TextField
|
||||||
|
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||||
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
|
import io.element.android.libraries.matrix.ui.components.AvatarActionBottomSheet
|
||||||
|
import io.element.android.libraries.matrix.ui.components.SelectedUsersRowList
|
||||||
|
import io.element.android.libraries.matrix.ui.components.UnsavedAvatar
|
||||||
|
import io.element.android.libraries.matrix.ui.room.address.RoomAddressField
|
||||||
|
import io.element.android.libraries.permissions.api.PermissionsView
|
||||||
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ConfigureRoomView(
|
||||||
|
state: ConfigureRoomState,
|
||||||
|
onBackClick: () -> Unit,
|
||||||
|
onCreateRoomSuccess: (RoomId) -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
val focusManager = LocalFocusManager.current
|
||||||
|
val isAvatarActionsSheetVisible = remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
fun onAvatarClick() {
|
||||||
|
focusManager.clearFocus()
|
||||||
|
isAvatarActionsSheetVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
modifier = modifier.clearFocusOnTap(focusManager),
|
||||||
|
topBar = {
|
||||||
|
ConfigureRoomToolbar(
|
||||||
|
isNextActionEnabled = state.isValid,
|
||||||
|
onBackClick = onBackClick,
|
||||||
|
onNextClick = {
|
||||||
|
focusManager.clearFocus()
|
||||||
|
state.eventSink(ConfigureRoomEvents.CreateRoom)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { padding ->
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(padding)
|
||||||
|
.imePadding()
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
.consumeWindowInsets(padding),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(24.dp),
|
||||||
|
) {
|
||||||
|
RoomNameWithAvatar(
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
|
avatarUri = state.config.avatarUri,
|
||||||
|
roomName = state.config.roomName.orEmpty(),
|
||||||
|
onAvatarClick = ::onAvatarClick,
|
||||||
|
onChangeRoomName = { state.eventSink(ConfigureRoomEvents.RoomNameChanged(it)) },
|
||||||
|
)
|
||||||
|
RoomTopic(
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
|
topic = state.config.topic.orEmpty(),
|
||||||
|
onTopicChange = { state.eventSink(ConfigureRoomEvents.TopicChanged(it)) },
|
||||||
|
)
|
||||||
|
if (state.config.invites.isNotEmpty()) {
|
||||||
|
SelectedUsersRowList(
|
||||||
|
contentPadding = PaddingValues(horizontal = 24.dp),
|
||||||
|
selectedUsers = state.config.invites,
|
||||||
|
onUserRemove = {
|
||||||
|
focusManager.clearFocus()
|
||||||
|
state.eventSink(ConfigureRoomEvents.RemoveUserFromSelection(it))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
RoomVisibilityOptions(
|
||||||
|
selected = when (state.config.roomVisibility) {
|
||||||
|
is RoomVisibilityState.Private -> RoomVisibilityItem.Private
|
||||||
|
is RoomVisibilityState.Public -> RoomVisibilityItem.Public
|
||||||
|
},
|
||||||
|
onOptionClick = {
|
||||||
|
focusManager.clearFocus()
|
||||||
|
state.eventSink(ConfigureRoomEvents.RoomVisibilityChanged(it))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if (state.config.roomVisibility is RoomVisibilityState.Public && state.isKnockFeatureEnabled) {
|
||||||
|
RoomAccessOptions(
|
||||||
|
selected = when (state.config.roomVisibility.roomAccess) {
|
||||||
|
RoomAccess.Anyone -> RoomAccessItem.Anyone
|
||||||
|
RoomAccess.Knocking -> RoomAccessItem.AskToJoin
|
||||||
|
},
|
||||||
|
onOptionClick = {
|
||||||
|
focusManager.clearFocus()
|
||||||
|
state.eventSink(ConfigureRoomEvents.RoomAccessChanged(it))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
RoomAddressField(
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
|
address = state.config.roomVisibility.roomAddress.value,
|
||||||
|
homeserverName = state.homeserverName,
|
||||||
|
addressValidity = state.roomAddressValidity,
|
||||||
|
onAddressChange = { state.eventSink(ConfigureRoomEvents.RoomAddressChanged(it)) },
|
||||||
|
label = stringResource(R.string.screen_create_room_room_address_section_title),
|
||||||
|
supportingText = stringResource(R.string.screen_create_room_room_address_section_footer),
|
||||||
|
)
|
||||||
|
Spacer(Modifier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AvatarActionBottomSheet(
|
||||||
|
actions = state.avatarActions,
|
||||||
|
isVisible = isAvatarActionsSheetVisible.value,
|
||||||
|
onDismiss = { isAvatarActionsSheetVisible.value = false },
|
||||||
|
onSelectAction = { state.eventSink(ConfigureRoomEvents.HandleAvatarAction(it)) }
|
||||||
|
)
|
||||||
|
|
||||||
|
AsyncActionView(
|
||||||
|
async = state.createRoomAction,
|
||||||
|
progressDialog = {
|
||||||
|
AsyncActionViewDefaults.ProgressDialog(
|
||||||
|
progressText = stringResource(CommonStrings.common_creating_room),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onSuccess = { onCreateRoomSuccess(it) },
|
||||||
|
errorMessage = { stringResource(R.string.screen_create_room_error_creating_room) },
|
||||||
|
onRetry = { state.eventSink(ConfigureRoomEvents.CreateRoom) },
|
||||||
|
onErrorDismiss = { state.eventSink(ConfigureRoomEvents.CancelCreateRoom) },
|
||||||
|
)
|
||||||
|
|
||||||
|
PermissionsView(
|
||||||
|
state = state.cameraPermissionState,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
private fun ConfigureRoomToolbar(
|
||||||
|
isNextActionEnabled: Boolean,
|
||||||
|
onBackClick: () -> Unit,
|
||||||
|
onNextClick: () -> Unit,
|
||||||
|
) {
|
||||||
|
TopAppBar(
|
||||||
|
titleStr = stringResource(R.string.screen_create_room_title),
|
||||||
|
navigationIcon = { BackButton(onClick = onBackClick) },
|
||||||
|
actions = {
|
||||||
|
TextButton(
|
||||||
|
text = stringResource(CommonStrings.action_create),
|
||||||
|
enabled = isNextActionEnabled,
|
||||||
|
onClick = onNextClick,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun RoomNameWithAvatar(
|
||||||
|
avatarUri: Uri?,
|
||||||
|
roomName: String,
|
||||||
|
onAvatarClick: () -> Unit,
|
||||||
|
onChangeRoomName: (String) -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = modifier,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
) {
|
||||||
|
UnsavedAvatar(
|
||||||
|
avatarUri = avatarUri,
|
||||||
|
avatarSize = AvatarSize.EditRoomDetails,
|
||||||
|
avatarType = AvatarType.Room(),
|
||||||
|
modifier = Modifier.clickable(onClick = onAvatarClick),
|
||||||
|
)
|
||||||
|
|
||||||
|
TextField(
|
||||||
|
label = stringResource(R.string.screen_create_room_room_name_label),
|
||||||
|
value = roomName,
|
||||||
|
placeholder = stringResource(CommonStrings.common_room_name_placeholder),
|
||||||
|
singleLine = true,
|
||||||
|
onValueChange = onChangeRoomName,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun RoomTopic(
|
||||||
|
topic: String,
|
||||||
|
onTopicChange: (String) -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
TextField(
|
||||||
|
modifier = modifier,
|
||||||
|
label = stringResource(R.string.screen_create_room_topic_label),
|
||||||
|
value = topic,
|
||||||
|
onValueChange = onTopicChange,
|
||||||
|
maxLines = 3,
|
||||||
|
supportingText = stringResource(CommonStrings.common_topic_placeholder),
|
||||||
|
keyboardOptions = KeyboardOptions(
|
||||||
|
capitalization = KeyboardCapitalization.Sentences,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ConfigureRoomOptions(
|
||||||
|
title: String,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
content: @Composable ColumnScope.() -> Unit,
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = modifier.selectableGroup()
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = title,
|
||||||
|
style = ElementTheme.typography.fontBodyLgMedium,
|
||||||
|
color = ElementTheme.colors.textPrimary,
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
|
)
|
||||||
|
content()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun RoomVisibilityOptions(
|
||||||
|
selected: RoomVisibilityItem,
|
||||||
|
onOptionClick: (RoomVisibilityItem) -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
ConfigureRoomOptions(
|
||||||
|
title = stringResource(R.string.screen_create_room_room_visibility_section_title),
|
||||||
|
modifier = modifier,
|
||||||
|
) {
|
||||||
|
RoomVisibilityItem.entries.forEach { item ->
|
||||||
|
val isSelected = item == selected
|
||||||
|
ListItem(
|
||||||
|
leadingContent = ListItemContent.Custom {
|
||||||
|
RoundedIconAtom(
|
||||||
|
size = RoundedIconAtomSize.Big,
|
||||||
|
resourceId = item.icon,
|
||||||
|
tint = if (isSelected) ElementTheme.colors.iconPrimary else ElementTheme.colors.iconSecondary,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
headlineContent = { Text(text = stringResource(item.title)) },
|
||||||
|
supportingContent = { Text(text = stringResource(item.description)) },
|
||||||
|
trailingContent = ListItemContent.RadioButton(selected = isSelected),
|
||||||
|
onClick = { onOptionClick(item) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun RoomAccessOptions(
|
||||||
|
selected: RoomAccessItem,
|
||||||
|
onOptionClick: (RoomAccessItem) -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
ConfigureRoomOptions(
|
||||||
|
title = stringResource(R.string.screen_create_room_room_access_section_header),
|
||||||
|
modifier = modifier,
|
||||||
|
) {
|
||||||
|
RoomAccessItem.entries.forEach { item ->
|
||||||
|
ListItem(
|
||||||
|
headlineContent = { Text(text = stringResource(item.title)) },
|
||||||
|
supportingContent = { Text(text = stringResource(item.description)) },
|
||||||
|
trailingContent = ListItemContent.RadioButton(selected = item == selected),
|
||||||
|
onClick = { onOptionClick(item) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreviewWithLargeHeight
|
||||||
|
@Composable
|
||||||
|
internal fun ConfigureRoomViewLightPreview(@PreviewParameter(ConfigureRoomStateProvider::class) state: ConfigureRoomState) =
|
||||||
|
ElementPreviewLight { ContentToPreview(state) }
|
||||||
|
|
||||||
|
@PreviewWithLargeHeight
|
||||||
|
@Composable
|
||||||
|
internal fun ConfigureRoomViewDarkPreview(@PreviewParameter(ConfigureRoomStateProvider::class) state: ConfigureRoomState) =
|
||||||
|
ElementPreviewDark { ContentToPreview(state) }
|
||||||
|
|
||||||
|
@ExcludeFromCoverage
|
||||||
|
@Composable
|
||||||
|
private fun ContentToPreview(state: ConfigureRoomState) {
|
||||||
|
ConfigureRoomView(
|
||||||
|
state = state,
|
||||||
|
onBackClick = {},
|
||||||
|
onCreateRoomSuccess = {},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* 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.startchat.impl.configureroom
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.room.join.JoinRule
|
||||||
|
|
||||||
|
enum class RoomAccess {
|
||||||
|
Anyone,
|
||||||
|
Knocking
|
||||||
|
}
|
||||||
|
|
||||||
|
fun RoomAccess.toJoinRule(): JoinRule? {
|
||||||
|
return when (this) {
|
||||||
|
RoomAccess.Anyone -> null
|
||||||
|
RoomAccess.Knocking -> JoinRule.Knock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* 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.startchat.impl.configureroom
|
||||||
|
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import io.element.android.features.startchat.impl.R
|
||||||
|
|
||||||
|
enum class RoomAccessItem(
|
||||||
|
@StringRes val title: Int,
|
||||||
|
@StringRes val description: Int
|
||||||
|
) {
|
||||||
|
Anyone(
|
||||||
|
title = R.string.screen_create_room_room_access_section_anyone_option_title,
|
||||||
|
description = R.string.screen_create_room_room_access_section_anyone_option_description,
|
||||||
|
),
|
||||||
|
AskToJoin(
|
||||||
|
title = R.string.screen_create_room_room_access_section_knocking_option_title,
|
||||||
|
description = R.string.screen_create_room_room_access_section_knocking_option_description,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
* 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.startchat.impl.configureroom
|
||||||
|
|
||||||
|
sealed class RoomAddress(open val value: String) {
|
||||||
|
data class AutoFilled(override val value: String) : RoomAddress(value)
|
||||||
|
data class Edited(override val value: String) : RoomAddress(value)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* 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.startchat.impl.configureroom
|
||||||
|
|
||||||
|
import androidx.annotation.DrawableRes
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import io.element.android.features.startchat.impl.R
|
||||||
|
import io.element.android.libraries.designsystem.icons.CompoundDrawables
|
||||||
|
|
||||||
|
enum class RoomVisibilityItem(
|
||||||
|
@DrawableRes val icon: Int,
|
||||||
|
@StringRes val title: Int,
|
||||||
|
@StringRes val description: Int
|
||||||
|
) {
|
||||||
|
Private(
|
||||||
|
icon = CompoundDrawables.ic_compound_lock,
|
||||||
|
title = R.string.screen_create_room_private_option_title,
|
||||||
|
description = R.string.screen_create_room_private_option_description,
|
||||||
|
),
|
||||||
|
Public(
|
||||||
|
icon = CompoundDrawables.ic_compound_public,
|
||||||
|
title = R.string.screen_create_room_public_option_title,
|
||||||
|
description = R.string.screen_create_room_public_option_description,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* 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.startchat.impl.configureroom
|
||||||
|
|
||||||
|
import java.util.Optional
|
||||||
|
|
||||||
|
sealed interface RoomVisibilityState {
|
||||||
|
data object Private : RoomVisibilityState
|
||||||
|
|
||||||
|
data class Public(
|
||||||
|
val roomAddress: RoomAddress,
|
||||||
|
val roomAccess: RoomAccess,
|
||||||
|
) : RoomVisibilityState
|
||||||
|
|
||||||
|
fun roomAddress(): Optional<String> {
|
||||||
|
return when (this) {
|
||||||
|
is Private -> Optional.empty()
|
||||||
|
is Public -> Optional.of(roomAddress.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.di
|
package io.element.android.features.startchat.impl.di
|
||||||
|
|
||||||
import com.squareup.anvil.annotations.ContributesTo
|
import com.squareup.anvil.annotations.ContributesTo
|
||||||
import com.squareup.anvil.annotations.MergeSubcomponent
|
import com.squareup.anvil.annotations.MergeSubcomponent
|
||||||
|
|
@ -5,6 +5,6 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.di
|
package io.element.android.features.startchat.impl.di
|
||||||
|
|
||||||
abstract class CreateRoomScope private constructor()
|
abstract class CreateRoomScope private constructor()
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.joinbyaddress
|
package io.element.android.features.startchat.impl.joinbyaddress
|
||||||
|
|
||||||
sealed interface JoinRoomByAddressEvents {
|
sealed interface JoinRoomByAddressEvents {
|
||||||
data object Dismiss : JoinRoomByAddressEvents
|
data object Dismiss : JoinRoomByAddressEvents
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.joinbyaddress
|
package io.element.android.features.startchat.impl.joinbyaddress
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
|
@ -16,7 +16,7 @@ import com.bumble.appyx.core.plugin.plugins
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import io.element.android.anvilannotations.ContributesNode
|
import io.element.android.anvilannotations.ContributesNode
|
||||||
import io.element.android.features.createroom.CreateRoomNavigator
|
import io.element.android.features.startchat.StartChatNavigator
|
||||||
import io.element.android.libraries.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
|
|
||||||
@ContributesNode(SessionScope::class)
|
@ContributesNode(SessionScope::class)
|
||||||
|
|
@ -25,7 +25,7 @@ class JoinRoomByAddressNode @AssistedInject constructor(
|
||||||
@Assisted plugins: List<Plugin>,
|
@Assisted plugins: List<Plugin>,
|
||||||
presenterFactory: JoinRoomByAddressPresenter.Factory,
|
presenterFactory: JoinRoomByAddressPresenter.Factory,
|
||||||
) : Node(buildContext, plugins = plugins) {
|
) : Node(buildContext, plugins = plugins) {
|
||||||
private val navigator = plugins<CreateRoomNavigator>().first()
|
private val navigator = plugins<StartChatNavigator>().first()
|
||||||
private val presenter = presenterFactory.create(navigator)
|
private val presenter = presenterFactory.create(navigator)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.joinbyaddress
|
package io.element.android.features.startchat.impl.joinbyaddress
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
|
@ -18,7 +18,7 @@ import androidx.compose.runtime.setValue
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import io.element.android.features.createroom.CreateRoomNavigator
|
import io.element.android.features.startchat.StartChatNavigator
|
||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
import io.element.android.libraries.core.data.tryOrNull
|
import io.element.android.libraries.core.data.tryOrNull
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
|
|
@ -32,13 +32,13 @@ import kotlin.time.Duration.Companion.seconds
|
||||||
private const val ADDRESS_RESOLVE_TIMEOUT_IN_SECONDS = 10
|
private const val ADDRESS_RESOLVE_TIMEOUT_IN_SECONDS = 10
|
||||||
|
|
||||||
class JoinRoomByAddressPresenter @AssistedInject constructor(
|
class JoinRoomByAddressPresenter @AssistedInject constructor(
|
||||||
@Assisted private val navigator: CreateRoomNavigator,
|
@Assisted private val navigator: StartChatNavigator,
|
||||||
private val client: MatrixClient,
|
private val client: MatrixClient,
|
||||||
private val roomAliasHelper: RoomAliasHelper,
|
private val roomAliasHelper: RoomAliasHelper,
|
||||||
) : Presenter<JoinRoomByAddressState> {
|
) : Presenter<JoinRoomByAddressState> {
|
||||||
@AssistedFactory
|
@AssistedFactory
|
||||||
interface Factory {
|
interface Factory {
|
||||||
fun create(navigator: CreateRoomNavigator): JoinRoomByAddressPresenter
|
fun create(navigator: StartChatNavigator): JoinRoomByAddressPresenter
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.joinbyaddress
|
package io.element.android.features.startchat.impl.joinbyaddress
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
|
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.joinbyaddress
|
package io.element.android.features.startchat.impl.joinbyaddress
|
||||||
|
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.joinbyaddress
|
package io.element.android.features.startchat.impl.joinbyaddress
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
|
@ -29,7 +29,7 @@ import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.element.android.features.createroom.impl.R
|
import io.element.android.features.startchat.impl.R
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||||
import io.element.android.libraries.designsystem.theme.components.Button
|
import io.element.android.libraries.designsystem.theme.components.Button
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
/*
|
||||||
|
* 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.startchat.impl.root
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
|
|
||||||
|
sealed interface StartChatEvents {
|
||||||
|
data class StartDM(val matrixUser: MatrixUser) : StartChatEvents
|
||||||
|
data object CancelStartDM : StartChatEvents
|
||||||
|
}
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2023, 2024 New Vector Ltd.
|
* Copyright 2025 New Vector Ltd.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.root
|
package io.element.android.features.startchat.impl.root
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import androidx.activity.compose.LocalActivity
|
import androidx.activity.compose.LocalActivity
|
||||||
|
|
@ -20,21 +20,21 @@ import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import im.vector.app.features.analytics.plan.MobileScreen
|
import im.vector.app.features.analytics.plan.MobileScreen
|
||||||
import io.element.android.anvilannotations.ContributesNode
|
import io.element.android.anvilannotations.ContributesNode
|
||||||
import io.element.android.features.createroom.CreateRoomNavigator
|
import io.element.android.features.startchat.StartChatNavigator
|
||||||
import io.element.android.libraries.deeplink.usecase.InviteFriendsUseCase
|
import io.element.android.libraries.deeplink.usecase.InviteFriendsUseCase
|
||||||
import io.element.android.libraries.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
|
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
|
||||||
import io.element.android.services.analytics.api.AnalyticsService
|
import io.element.android.services.analytics.api.AnalyticsService
|
||||||
|
|
||||||
@ContributesNode(SessionScope::class)
|
@ContributesNode(SessionScope::class)
|
||||||
class CreateRoomRootNode @AssistedInject constructor(
|
class StartChatNode @AssistedInject constructor(
|
||||||
@Assisted buildContext: BuildContext,
|
@Assisted buildContext: BuildContext,
|
||||||
@Assisted plugins: List<Plugin>,
|
@Assisted plugins: List<Plugin>,
|
||||||
private val presenter: CreateRoomRootPresenter,
|
private val presenter: StartChatPresenter,
|
||||||
private val analyticsService: AnalyticsService,
|
private val analyticsService: AnalyticsService,
|
||||||
private val inviteFriendsUseCase: InviteFriendsUseCase,
|
private val inviteFriendsUseCase: InviteFriendsUseCase,
|
||||||
) : Node(buildContext, plugins = plugins) {
|
) : Node(buildContext, plugins = plugins) {
|
||||||
private val navigator = plugins<CreateRoomNavigator>().first()
|
private val navigator = plugins<StartChatNavigator>().first()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
lifecycle.subscribe(
|
lifecycle.subscribe(
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2023, 2024 New Vector Ltd.
|
* Copyright 2025 New Vector Ltd.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.root
|
package io.element.android.features.startchat.impl.root
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
|
|
@ -14,11 +14,11 @@ import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import io.element.android.features.createroom.api.StartDMAction
|
import io.element.android.features.startchat.api.StartDMAction
|
||||||
import io.element.android.features.createroom.impl.userlist.SelectionMode
|
import io.element.android.features.startchat.impl.userlist.SelectionMode
|
||||||
import io.element.android.features.createroom.impl.userlist.UserListDataStore
|
import io.element.android.features.startchat.impl.userlist.UserListDataStore
|
||||||
import io.element.android.features.createroom.impl.userlist.UserListPresenter
|
import io.element.android.features.startchat.impl.userlist.UserListPresenter
|
||||||
import io.element.android.features.createroom.impl.userlist.UserListPresenterArgs
|
import io.element.android.features.startchat.impl.userlist.UserListPresenterArgs
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
import io.element.android.libraries.core.meta.BuildMeta
|
import io.element.android.libraries.core.meta.BuildMeta
|
||||||
|
|
@ -29,14 +29,14 @@ import io.element.android.libraries.usersearch.api.UserRepository
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class CreateRoomRootPresenter @Inject constructor(
|
class StartChatPresenter @Inject constructor(
|
||||||
presenterFactory: UserListPresenter.Factory,
|
presenterFactory: UserListPresenter.Factory,
|
||||||
userRepository: UserRepository,
|
userRepository: UserRepository,
|
||||||
userListDataStore: UserListDataStore,
|
userListDataStore: UserListDataStore,
|
||||||
private val startDMAction: StartDMAction,
|
private val startDMAction: StartDMAction,
|
||||||
private val buildMeta: BuildMeta,
|
private val buildMeta: BuildMeta,
|
||||||
private val featureFlagService: FeatureFlagService,
|
private val featureFlagService: FeatureFlagService,
|
||||||
) : Presenter<CreateRoomRootState> {
|
) : Presenter<StartChatState> {
|
||||||
private val presenter = presenterFactory.create(
|
private val presenter = presenterFactory.create(
|
||||||
UserListPresenterArgs(
|
UserListPresenterArgs(
|
||||||
selectionMode = SelectionMode.Single,
|
selectionMode = SelectionMode.Single,
|
||||||
|
|
@ -46,7 +46,7 @@ class CreateRoomRootPresenter @Inject constructor(
|
||||||
)
|
)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun present(): CreateRoomRootState {
|
override fun present(): StartChatState {
|
||||||
val userListState = presenter.present()
|
val userListState = presenter.present()
|
||||||
|
|
||||||
val localCoroutineScope = rememberCoroutineScope()
|
val localCoroutineScope = rememberCoroutineScope()
|
||||||
|
|
@ -56,20 +56,20 @@ class CreateRoomRootPresenter @Inject constructor(
|
||||||
featureFlagService.isFeatureEnabledFlow(FeatureFlags.RoomDirectorySearch)
|
featureFlagService.isFeatureEnabledFlow(FeatureFlags.RoomDirectorySearch)
|
||||||
}.collectAsState(initial = false)
|
}.collectAsState(initial = false)
|
||||||
|
|
||||||
fun handleEvents(event: CreateRoomRootEvents) {
|
fun handleEvents(event: StartChatEvents) {
|
||||||
when (event) {
|
when (event) {
|
||||||
is CreateRoomRootEvents.StartDM -> localCoroutineScope.launch {
|
is StartChatEvents.StartDM -> localCoroutineScope.launch {
|
||||||
startDMAction.execute(
|
startDMAction.execute(
|
||||||
matrixUser = event.matrixUser,
|
matrixUser = event.matrixUser,
|
||||||
createIfDmDoesNotExist = startDmActionState.value is AsyncAction.Confirming,
|
createIfDmDoesNotExist = startDmActionState.value is AsyncAction.Confirming,
|
||||||
actionState = startDmActionState,
|
actionState = startDmActionState,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
CreateRoomRootEvents.CancelStartDM -> startDmActionState.value = AsyncAction.Uninitialized
|
StartChatEvents.CancelStartDM -> startDmActionState.value = AsyncAction.Uninitialized
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return CreateRoomRootState(
|
return StartChatState(
|
||||||
applicationName = buildMeta.applicationName,
|
applicationName = buildMeta.applicationName,
|
||||||
userListState = userListState,
|
userListState = userListState,
|
||||||
startDmAction = startDmActionState.value,
|
startDmAction = startDmActionState.value,
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2023, 2024 New Vector Ltd.
|
* Copyright 2025 New Vector Ltd.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.root
|
package io.element.android.features.startchat.impl.root
|
||||||
|
|
||||||
import io.element.android.features.createroom.impl.userlist.UserListState
|
import io.element.android.features.startchat.impl.userlist.UserListState
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
|
|
||||||
data class CreateRoomRootState(
|
data class StartChatState(
|
||||||
val applicationName: String,
|
val applicationName: String,
|
||||||
val userListState: UserListState,
|
val userListState: UserListState,
|
||||||
val startDmAction: AsyncAction<RoomId>,
|
val startDmAction: AsyncAction<RoomId>,
|
||||||
val isRoomDirectorySearchEnabled: Boolean,
|
val isRoomDirectorySearchEnabled: Boolean,
|
||||||
val eventSink: (CreateRoomRootEvents) -> Unit,
|
val eventSink: (StartChatEvents) -> Unit,
|
||||||
)
|
)
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2023, 2024 New Vector Ltd.
|
* Copyright 2025 New Vector Ltd.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.root
|
package io.element.android.features.startchat.impl.root
|
||||||
|
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
import io.element.android.features.createroom.api.ConfirmingStartDmWithMatrixUser
|
import io.element.android.features.startchat.api.ConfirmingStartDmWithMatrixUser
|
||||||
import io.element.android.features.createroom.impl.userlist.UserListState
|
import io.element.android.features.startchat.impl.userlist.UserListState
|
||||||
import io.element.android.features.createroom.impl.userlist.aRecentDirectRoomList
|
import io.element.android.features.startchat.impl.userlist.aRecentDirectRoomList
|
||||||
import io.element.android.features.createroom.impl.userlist.aUserListState
|
import io.element.android.features.startchat.impl.userlist.aUserListState
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
|
|
@ -19,8 +19,8 @@ import io.element.android.libraries.matrix.ui.components.aMatrixUser
|
||||||
import io.element.android.libraries.usersearch.api.UserSearchResult
|
import io.element.android.libraries.usersearch.api.UserSearchResult
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
||||||
open class CreateRoomRootStateProvider : PreviewParameterProvider<CreateRoomRootState> {
|
open class CreateRoomRootStateProvider : PreviewParameterProvider<StartChatState> {
|
||||||
override val values: Sequence<CreateRoomRootState>
|
override val values: Sequence<StartChatState>
|
||||||
get() = sequenceOf(
|
get() = sequenceOf(
|
||||||
aCreateRoomRootState(),
|
aCreateRoomRootState(),
|
||||||
aCreateRoomRootState(
|
aCreateRoomRootState(
|
||||||
|
|
@ -64,8 +64,8 @@ fun aCreateRoomRootState(
|
||||||
userListState: UserListState = aUserListState(),
|
userListState: UserListState = aUserListState(),
|
||||||
startDmAction: AsyncAction<RoomId> = AsyncAction.Uninitialized,
|
startDmAction: AsyncAction<RoomId> = AsyncAction.Uninitialized,
|
||||||
isRoomDirectorySearchEnabled: Boolean = false,
|
isRoomDirectorySearchEnabled: Boolean = false,
|
||||||
eventSink: (CreateRoomRootEvents) -> Unit = {},
|
eventSink: (StartChatEvents) -> Unit = {},
|
||||||
) = CreateRoomRootState(
|
) = StartChatState(
|
||||||
applicationName = applicationName,
|
applicationName = applicationName,
|
||||||
userListState = userListState,
|
userListState = userListState,
|
||||||
startDmAction = startDmAction,
|
startDmAction = startDmAction,
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2023, 2024 New Vector Ltd.
|
* Copyright 2025 New Vector Ltd.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.root
|
package io.element.android.features.startchat.impl.root
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
|
|
@ -27,9 +27,9 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.element.android.compound.theme.ElementTheme
|
import io.element.android.compound.theme.ElementTheme
|
||||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||||
import io.element.android.features.createroom.api.ConfirmingStartDmWithMatrixUser
|
import io.element.android.features.startchat.api.ConfirmingStartDmWithMatrixUser
|
||||||
import io.element.android.features.createroom.impl.R
|
import io.element.android.features.startchat.impl.R
|
||||||
import io.element.android.features.createroom.impl.components.UserListView
|
import io.element.android.features.startchat.impl.components.UserListView
|
||||||
import io.element.android.libraries.designsystem.components.async.AsyncActionView
|
import io.element.android.libraries.designsystem.components.async.AsyncActionView
|
||||||
import io.element.android.libraries.designsystem.components.async.AsyncActionViewDefaults
|
import io.element.android.libraries.designsystem.components.async.AsyncActionViewDefaults
|
||||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||||
|
|
@ -49,7 +49,7 @@ import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CreateRoomRootView(
|
fun CreateRoomRootView(
|
||||||
state: CreateRoomRootState,
|
state: StartChatState,
|
||||||
onCloseClick: () -> Unit,
|
onCloseClick: () -> Unit,
|
||||||
onNewRoomClick: () -> Unit,
|
onNewRoomClick: () -> Unit,
|
||||||
onOpenDM: (RoomId) -> Unit,
|
onOpenDM: (RoomId) -> Unit,
|
||||||
|
|
@ -80,7 +80,7 @@ fun CreateRoomRootView(
|
||||||
recentDirectRooms = persistentListOf(),
|
recentDirectRooms = persistentListOf(),
|
||||||
),
|
),
|
||||||
onSelectUser = {
|
onSelectUser = {
|
||||||
state.eventSink(CreateRoomRootEvents.StartDM(it))
|
state.eventSink(StartChatEvents.StartDM(it))
|
||||||
},
|
},
|
||||||
onDeselectUser = { },
|
onDeselectUser = { },
|
||||||
)
|
)
|
||||||
|
|
@ -109,20 +109,20 @@ fun CreateRoomRootView(
|
||||||
errorMessage = { stringResource(R.string.screen_start_chat_error_starting_chat) },
|
errorMessage = { stringResource(R.string.screen_start_chat_error_starting_chat) },
|
||||||
onRetry = {
|
onRetry = {
|
||||||
state.userListState.selectedUsers.firstOrNull()
|
state.userListState.selectedUsers.firstOrNull()
|
||||||
?.let { state.eventSink(CreateRoomRootEvents.StartDM(it)) }
|
?.let { state.eventSink(StartChatEvents.StartDM(it)) }
|
||||||
// Cancel start DM if there is no more selected user (should not happen)
|
// Cancel start DM if there is no more selected user (should not happen)
|
||||||
?: state.eventSink(CreateRoomRootEvents.CancelStartDM)
|
?: state.eventSink(StartChatEvents.CancelStartDM)
|
||||||
},
|
},
|
||||||
onErrorDismiss = { state.eventSink(CreateRoomRootEvents.CancelStartDM) },
|
onErrorDismiss = { state.eventSink(StartChatEvents.CancelStartDM) },
|
||||||
confirmationDialog = { data ->
|
confirmationDialog = { data ->
|
||||||
if (data is ConfirmingStartDmWithMatrixUser) {
|
if (data is ConfirmingStartDmWithMatrixUser) {
|
||||||
CreateDmConfirmationBottomSheet(
|
CreateDmConfirmationBottomSheet(
|
||||||
matrixUser = data.matrixUser,
|
matrixUser = data.matrixUser,
|
||||||
onSendInvite = {
|
onSendInvite = {
|
||||||
state.eventSink(CreateRoomRootEvents.StartDM(data.matrixUser))
|
state.eventSink(StartChatEvents.StartDM(data.matrixUser))
|
||||||
},
|
},
|
||||||
onDismiss = {
|
onDismiss = {
|
||||||
state.eventSink(CreateRoomRootEvents.CancelStartDM)
|
state.eventSink(StartChatEvents.CancelStartDM)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -148,7 +148,7 @@ private fun CreateRoomRootViewTopBar(
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun CreateRoomActionButtonsList(
|
private fun CreateRoomActionButtonsList(
|
||||||
state: CreateRoomRootState,
|
state: StartChatState,
|
||||||
onNewRoomClick: () -> Unit,
|
onNewRoomClick: () -> Unit,
|
||||||
onInvitePeopleClick: () -> Unit,
|
onInvitePeopleClick: () -> Unit,
|
||||||
onJoinByAddressClick: () -> Unit,
|
onJoinByAddressClick: () -> Unit,
|
||||||
|
|
@ -239,7 +239,7 @@ private fun CreateRoomActionButton(
|
||||||
|
|
||||||
@PreviewsDayNight
|
@PreviewsDayNight
|
||||||
@Composable
|
@Composable
|
||||||
internal fun CreateRoomRootViewPreview(@PreviewParameter(CreateRoomRootStateProvider::class) state: CreateRoomRootState) =
|
internal fun CreateRoomRootViewPreview(@PreviewParameter(CreateRoomRootStateProvider::class) state: StartChatState) =
|
||||||
ElementPreview {
|
ElementPreview {
|
||||||
CreateRoomRootView(
|
CreateRoomRootView(
|
||||||
state = state,
|
state = state,
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.userlist
|
package io.element.android.features.startchat.impl.userlist
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.userlist
|
package io.element.android.features.startchat.impl.userlist
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.userlist
|
package io.element.android.features.startchat.impl.userlist
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.userlist
|
package io.element.android.features.startchat.impl.userlist
|
||||||
|
|
||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
import io.element.android.libraries.usersearch.api.UserRepository
|
import io.element.android.libraries.usersearch.api.UserRepository
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.userlist
|
package io.element.android.features.startchat.impl.userlist
|
||||||
|
|
||||||
data class UserListPresenterArgs(
|
data class UserListPresenterArgs(
|
||||||
val selectionMode: SelectionMode,
|
val selectionMode: SelectionMode,
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.userlist
|
package io.element.android.features.startchat.impl.userlist
|
||||||
|
|
||||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||||
import io.element.android.libraries.matrix.api.room.recent.RecentDirectRoom
|
import io.element.android.libraries.matrix.api.room.recent.RecentDirectRoom
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.userlist
|
package io.element.android.features.startchat.impl.userlist
|
||||||
|
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?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_add_people_title">"Запрасіць карыстальнікаў"</string>
|
||||||
|
<string name="screen_create_room_error_creating_room">"Пры стварэнні пакоя адбылася памылка"</string>
|
||||||
|
<string name="screen_create_room_private_option_description">"Толькі запрошаныя людзі могуць атрымаць доступ да гэтага пакоя. Усе паведамленні абаронены end-to-end шыфраваннем."</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_title">"Хто заўгодна"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_header">"Доступ у пакой"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_title">"Папрасіце далучыцца"</string>
|
||||||
|
<string name="screen_create_room_room_name_label">"Назва пакоя"</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_start_chat_error_starting_chat">"Пры спробе пачаць чат адбылася памылка"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?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_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_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>
|
||||||
|
|
@ -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">"Nová místnost"</string>
|
||||||
|
<string name="screen_create_room_add_people_title">"Pozvat přátele"</string>
|
||||||
|
<string name="screen_create_room_error_creating_room">"Při vytváření místnosti došlo k chybě"</string>
|
||||||
|
<string name="screen_create_room_private_option_description">"Do této místnosti mají přístup pouze pozvaní lidé. Všechny zprávy jsou koncově šifrovány."</string>
|
||||||
|
<string name="screen_create_room_private_option_title">"Soukromá místnost"</string>
|
||||||
|
<string name="screen_create_room_public_option_description">"Tuto místnost může najít kdokoli.
|
||||||
|
To můžete kdykoli změnit v nastavení místnosti."</string>
|
||||||
|
<string name="screen_create_room_public_option_title">"Veřejná místnost"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_description">"Do této místnosti může vstoupit kdokoli"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_title">"Kdokoliv"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_header">"Přístup do místnosti"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_description">"Kdokoli může požádat o vstup do místnosti, ale správce nebo moderátor bude muset žádost přijmout"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_title">"Požádat o připojení"</string>
|
||||||
|
<string name="screen_create_room_room_address_section_footer">"Aby byla tato místnost viditelná v adresáři veřejných místností, budete potřebovat adresu místnosti."</string>
|
||||||
|
<string name="screen_create_room_room_address_section_title">"Adresa místnosti"</string>
|
||||||
|
<string name="screen_create_room_room_name_label">"Název místnosti"</string>
|
||||||
|
<string name="screen_create_room_room_visibility_section_title">"Viditelnost místnosti"</string>
|
||||||
|
<string name="screen_create_room_title">"Vytvořit místnost"</string>
|
||||||
|
<string name="screen_create_room_topic_label">"Téma (nepovinné)"</string>
|
||||||
|
<string name="screen_room_directory_search_title">"Adresář místností"</string>
|
||||||
|
<string name="screen_start_chat_error_starting_chat">"Při pokusu o zahájení chatu došlo k chybě"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_action">"Vstoupit do místnosti pomocí adresy"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_invalid_address">"Neplatná adresa"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_placeholder">"Zadejte…"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_found">"Odpovídající místnost nalezena"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_not_found">"Místnost nebyla nalezena"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_supporting_text">"např. #room-name:matrix.org"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -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">"Ystafell newydd"</string>
|
||||||
|
<string name="screen_create_room_add_people_title">"Gwahodd pobl"</string>
|
||||||
|
<string name="screen_create_room_error_creating_room">"Bu gwall wrth greu\'r ystafell"</string>
|
||||||
|
<string name="screen_create_room_private_option_description">"Dim ond pobl wahoddwyd all gael mynediad i\'r ystafell hon. Mae pob neges wedi\'i hamgryptio o\'r dechrau i\'r diwedd."</string>
|
||||||
|
<string name="screen_create_room_private_option_title">"Ystafell breifat"</string>
|
||||||
|
<string name="screen_create_room_public_option_description">"Gall unrhyw un ddod o hyd i\'r ystafell hon.
|
||||||
|
Gallwch newid hyn unrhyw bryd yng ngosodiadau ystafell."</string>
|
||||||
|
<string name="screen_create_room_public_option_title">"Ystafell gyhoeddus"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_description">"Gall unrhyw un ymuno â\'r ystafell hon"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_title">"Unrhyw un"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_header">"Mynediad i\'r Ystafell"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_description">"Gall unrhyw un ofyn am gael ymuno â\'r ystafell ond bydd rhaid i weinyddwr neu gymedrolwr dderbyn y cais"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_title">"Gofyn i gael ymuno"</string>
|
||||||
|
<string name="screen_create_room_room_address_section_footer">"Er mwyn i\'r ystafell hon fod yn weladwy yn y cyfeiriadur ystafelloedd cyhoeddus, bydd angen cyfeiriad ystafell arnoch."</string>
|
||||||
|
<string name="screen_create_room_room_address_section_title">"Cyfeiriad yr ystafell"</string>
|
||||||
|
<string name="screen_create_room_room_name_label">"Enw\'r ystafell"</string>
|
||||||
|
<string name="screen_create_room_room_visibility_section_title">"Gwelededd yr ystafell"</string>
|
||||||
|
<string name="screen_create_room_title">"Creu ystafell"</string>
|
||||||
|
<string name="screen_create_room_topic_label">"Pwnc (dewisol)"</string>
|
||||||
|
<string name="screen_room_directory_search_title">"Cyfeiriadur ystafelloedd"</string>
|
||||||
|
<string name="screen_start_chat_error_starting_chat">"Digwyddodd gwall wrth geisio cychwyn sgwrs"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_action">"Ymuno â\'r ystafell yn ôl cyfeiriad"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_invalid_address">"Ddim yn gyfeiriad dilys"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_placeholder">"Ewch i mewn…"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_found">"Cafwyd hyd i ystafell gyfatebol"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_not_found">"Heb ganfod yr ystafell"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_supporting_text">"e.e. #enw-ystafell:matrix.org"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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">"Neuer Raum"</string>
|
||||||
|
<string name="screen_create_room_add_people_title">"Nutzer einladen"</string>
|
||||||
|
<string name="screen_create_room_error_creating_room">"Beim Erstellen des Chats ist ein Fehler aufgetreten"</string>
|
||||||
|
<string name="screen_create_room_private_option_description">"Nur eingeladene Personen haben Zutritt zu diesem Chatroom. Alle Nachrichten sind Ende-zu-Ende verschlüsselt."</string>
|
||||||
|
<string name="screen_create_room_private_option_title">"Privater Chatroom"</string>
|
||||||
|
<string name="screen_create_room_public_option_description">"Alle können diesen Chatroom finden.
|
||||||
|
Sie können dies aber jederzeit in den Chatroomeinstellungen ändern."</string>
|
||||||
|
<string name="screen_create_room_public_option_title">"Öffentlicher Raum"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_description">"Jeder darf diesen Raum betreten"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_title">"Jeder"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_header">"Chatroomzugang"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_description">"Jeder kann den Zutritt zum Raum beantragen, aber ein Moderator muss die Anfrage akzeptieren."</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_title">"Beitritt beantragen"</string>
|
||||||
|
<string name="screen_create_room_room_address_section_footer">"Damit dieser Chatroom im öffentlichen Chatroomverzeichnis sichtbar ist, benötigen Sie eine Chatroomadresse."</string>
|
||||||
|
<string name="screen_create_room_room_address_section_title">"Chatroomadresse"</string>
|
||||||
|
<string name="screen_create_room_room_name_label">"Raumname"</string>
|
||||||
|
<string name="screen_create_room_room_visibility_section_title">" Sichtbarkeit des Chatrooms"</string>
|
||||||
|
<string name="screen_create_room_title">"Raum erstellen"</string>
|
||||||
|
<string name="screen_create_room_topic_label">"Thema (optional)"</string>
|
||||||
|
<string name="screen_room_directory_search_title">"Raum-Verzeichnis"</string>
|
||||||
|
<string name="screen_start_chat_error_starting_chat">"Beim Versuch, einen Chat zu starten, ist ein Fehler aufgetreten"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_action">"Raum per Adresse betreten"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_invalid_address">"Keine gültige Adresse"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_placeholder">"Eintreten…"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_found">"Passender Raum gefunden"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_not_found">"Raum nicht gefunden"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_supporting_text">"z. B. #room -name:matrix.org"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -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">"Νέα αίθουσα"</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_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_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_topic_label">"Θέμα (προαιρετικό)"</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_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>
|
||||||
|
</resources>
|
||||||
|
|
@ -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">"Nueva sala"</string>
|
||||||
|
<string name="screen_create_room_add_people_title">"Invitar personas"</string>
|
||||||
|
<string name="screen_create_room_error_creating_room">"Se ha producido un error al crear la sala"</string>
|
||||||
|
<string name="screen_create_room_private_option_description">"Solo las personas invitadas pueden acceder a esta sala. Todos los mensajes están cifrados de extremo a extremo."</string>
|
||||||
|
<string name="screen_create_room_private_option_title">"Sala privada"</string>
|
||||||
|
<string name="screen_create_room_public_option_description">"Cualquiera puede encontrar esta sala.
|
||||||
|
Puedes cambiar esto en cualquier momento en los ajustes de la sala."</string>
|
||||||
|
<string name="screen_create_room_public_option_title">"Sala pública"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_description">"Cualquiera puede unirse a esta sala"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_title">"Cualquiera"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_header">"Acceso a la sala"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_description">"Cualquiera puede solicitar unirse a la sala, pero un administrador o un moderador tendrá que aceptar la solicitud"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_title">"Solicitud para unirse"</string>
|
||||||
|
<string name="screen_create_room_room_address_section_footer">"Para que esta sala sea visible en el directorio de salas públicas, necesitarás una dirección de sala."</string>
|
||||||
|
<string name="screen_create_room_room_address_section_title">"Dirección de la sala"</string>
|
||||||
|
<string name="screen_create_room_room_name_label">"Nombre de la sala"</string>
|
||||||
|
<string name="screen_create_room_room_visibility_section_title">"Visibilidad de la sala"</string>
|
||||||
|
<string name="screen_create_room_title">"Crear una sala"</string>
|
||||||
|
<string name="screen_create_room_topic_label">"Tema (opcional)"</string>
|
||||||
|
<string name="screen_room_directory_search_title">"Directorio de salas"</string>
|
||||||
|
<string name="screen_start_chat_error_starting_chat">"Se ha producido un error al intentar iniciar un chat"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_action">"Unirse a una sala por su dirección"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_invalid_address">"Dirección no válida"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_placeholder">"Introducir…"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_found">"Sala encontrada"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_not_found">"No se encontró la sala"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_supporting_text">"p. ej., #nombre-de-la-sala:matrix.org"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -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">"Uus jututuba"</string>
|
||||||
|
<string name="screen_create_room_add_people_title">"Kutsu osalejaid"</string>
|
||||||
|
<string name="screen_create_room_error_creating_room">"Jututoa loomisel tekkis viga"</string>
|
||||||
|
<string name="screen_create_room_private_option_description">"Ligipääs siia jututuppa on vaid kutse alusel. Kõik sõnumid siin jututoas on läbivalt krüptitud."</string>
|
||||||
|
<string name="screen_create_room_private_option_title">"Privaatne jututuba"</string>
|
||||||
|
<string name="screen_create_room_public_option_description">"Kõik saavad seda jututuba leida.
|
||||||
|
Sa võid seda jututoa seadistustest alati muuta."</string>
|
||||||
|
<string name="screen_create_room_public_option_title">"Avalik jututuba"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_description">"Kõik võivad selle jututoaga liituda"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_title">"Kõik"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_header">"Ligipääs jututoale"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_description">"Kõik võivad paluda selle jututoaga liitumist, kuid peakasutaja või moderaator peavad selle kinnitama"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_title">"Küsi võimalust liitumiseks"</string>
|
||||||
|
<string name="screen_create_room_room_address_section_footer">"Selleks, et see jututuba oleks nähtav jututubade avalikus kataloogis, sa vajad jututoa aadressi."</string>
|
||||||
|
<string name="screen_create_room_room_address_section_title">"Jututoa aadress"</string>
|
||||||
|
<string name="screen_create_room_room_name_label">"Jututoa nimi"</string>
|
||||||
|
<string name="screen_create_room_room_visibility_section_title">"Jututoa nähtavus"</string>
|
||||||
|
<string name="screen_create_room_title">"Loo jututuba"</string>
|
||||||
|
<string name="screen_create_room_topic_label">"Teema (kui soovid lisada)"</string>
|
||||||
|
<string name="screen_room_directory_search_title">"Jututubade kataloog"</string>
|
||||||
|
<string name="screen_start_chat_error_starting_chat">"Vestluse alustamisel tekkis viga"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_action">"Liitu jututoaga aadressi alusel"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_invalid_address">"See pole kehtiv aadress"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_placeholder">"Sisene…"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_found">"Leidsime vastava jututoa"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_not_found">"Jututuba ei leidu"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_supporting_text">"nt. #jututoa-nimi:matrix.org"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?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">"Gela berria"</string>
|
||||||
|
<string name="screen_create_room_add_people_title">"Gonbidatu jendea"</string>
|
||||||
|
<string name="screen_create_room_error_creating_room">"Errorea gertatu da gela sortzean"</string>
|
||||||
|
<string name="screen_create_room_private_option_description">"Gonbidatutako jendea soilik sar daiteke gelara. Mezu guztiak daude ertzetik ertzera zifratuta."</string>
|
||||||
|
<string name="screen_create_room_private_option_title">"Gela pribatua"</string>
|
||||||
|
<string name="screen_create_room_public_option_description">"Edonork aurki dezake gela hau.
|
||||||
|
Gelaren ezarpenetan aldatu dezakezu hobespena."</string>
|
||||||
|
<string name="screen_create_room_public_option_title">"Gela publikoa"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_description">"Edonor sar daiteke gela honetara"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_title">"Edonork"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_header">"Gelarako sarbidea"</string>
|
||||||
|
<string name="screen_create_room_room_address_section_title">"Gelaren helbidea"</string>
|
||||||
|
<string name="screen_create_room_room_name_label">"Gelaren izena"</string>
|
||||||
|
<string name="screen_create_room_room_visibility_section_title">"Gelaren ikusgarritasuna"</string>
|
||||||
|
<string name="screen_create_room_title">"Sortu gela"</string>
|
||||||
|
<string name="screen_create_room_topic_label">"Mintzagaia (aukerakoa)"</string>
|
||||||
|
<string name="screen_room_directory_search_title">"Gelen direktorioa"</string>
|
||||||
|
<string name="screen_start_chat_error_starting_chat">"Errorea gertatu da txata hasten saiatzean"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_placeholder">"Sartu…"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_not_found">"Ez da gela aurkitu"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?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_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_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_title">"درخواست دعوت"</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_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_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">"نمونه: #room-name:matrix.org"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -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">"Uusi huone"</string>
|
||||||
|
<string name="screen_create_room_add_people_title">"Kutsu ihmisiä"</string>
|
||||||
|
<string name="screen_create_room_error_creating_room">"Huoneen luomisessa tapahtui virhe"</string>
|
||||||
|
<string name="screen_create_room_private_option_description">"Vain kutsutut henkilöt pääsevät tähän huoneeseen. Kaikki viestit ovat päästä päähän salattuja."</string>
|
||||||
|
<string name="screen_create_room_private_option_title">"Yksityinen huone"</string>
|
||||||
|
<string name="screen_create_room_public_option_description">"Kuka tahansa voi löytää tämän huoneen.
|
||||||
|
Voit muuttaa tämän milloin tahansa huoneen asetuksista."</string>
|
||||||
|
<string name="screen_create_room_public_option_title">"Julkinen huone"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_description">"Kuka tahansa voi liittyä tähän huoneeseen"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_title">"Kuka tahansa"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_header">"Huoneeseen Pääsy"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_description">"Kuka tahansa voi pyytää saada liittyä huoneeseen, mutta ylläpitäjän tai valvojan on hyväksyttävä pyyntö"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_title">"Pyydä liittymistä"</string>
|
||||||
|
<string name="screen_create_room_room_address_section_footer">"Jotta tämä huone näkyisi julkisessa huonehakemistossa, tarvitset huoneen osoitteen."</string>
|
||||||
|
<string name="screen_create_room_room_address_section_title">"Huoneen osoite"</string>
|
||||||
|
<string name="screen_create_room_room_name_label">"Huoneen nimi"</string>
|
||||||
|
<string name="screen_create_room_room_visibility_section_title">"Huoneen näkyvyys"</string>
|
||||||
|
<string name="screen_create_room_title">"Luo huone"</string>
|
||||||
|
<string name="screen_create_room_topic_label">"Aihe (valinnainen)"</string>
|
||||||
|
<string name="screen_room_directory_search_title">"Huoneluettelo"</string>
|
||||||
|
<string name="screen_start_chat_error_starting_chat">"Keskustelun aloituksessa tapahtui virhe"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_action">"Liity huoneeseen osoitteella"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_invalid_address">"Osoite ei ole kelvollinen"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_placeholder">"Syötä…"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_found">"Täsmäävä huone löytyi"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_not_found">"Huonetta ei löytynyt"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_supporting_text">"esim. #huoneen-nimi:matrix.org"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -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">"Nouveau salon"</string>
|
||||||
|
<string name="screen_create_room_add_people_title">"Inviter des amis"</string>
|
||||||
|
<string name="screen_create_room_error_creating_room">"Une erreur s’est produite lors de la création du salon"</string>
|
||||||
|
<string name="screen_create_room_private_option_description">"Seules les personnes invitées peuvent accéder à ce salon. Tous les messages sont chiffrés de bout en bout."</string>
|
||||||
|
<string name="screen_create_room_private_option_title">"Salon privé"</string>
|
||||||
|
<string name="screen_create_room_public_option_description">"N’importe qui peut trouver ce salon.
|
||||||
|
Vous pouvez modifier cela à tout moment dans les paramètres du salon."</string>
|
||||||
|
<string name="screen_create_room_public_option_title">"Salon public"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_description">"Tout le monde peut rejoindre ce salon"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_title">"Tout le monde"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_header">"Accès au salon"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_description">"Tout le monde peut demander à rejoindre le salon, mais un administrateur ou un modérateur devra accepter la demande"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_title">"Demander à rejoindre"</string>
|
||||||
|
<string name="screen_create_room_room_address_section_footer">"Pour que ce salon soit visible dans le répertoire des salons publics, vous aurez besoin d’une adresse de salon."</string>
|
||||||
|
<string name="screen_create_room_room_address_section_title">"Adresse du salon"</string>
|
||||||
|
<string name="screen_create_room_room_name_label">"Nom du salon"</string>
|
||||||
|
<string name="screen_create_room_room_visibility_section_title">"Visibilité du salon"</string>
|
||||||
|
<string name="screen_create_room_title">"Créer un salon"</string>
|
||||||
|
<string name="screen_create_room_topic_label">"Sujet (facultatif)"</string>
|
||||||
|
<string name="screen_room_directory_search_title">"Annuaire des salons"</string>
|
||||||
|
<string name="screen_start_chat_error_starting_chat">"Une erreur s’est produite lors de la tentative de création de la discussion"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_action">"Saisir une adresse de salon"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_invalid_address">"Ce n’est pas une adresse valide"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_placeholder">"Saisir…"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_found">"Ce salon existe"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_not_found">"Salon non trouvé"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_supporting_text">"ex: #nom-du-salon:matrix.org"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -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">"Új szoba"</string>
|
||||||
|
<string name="screen_create_room_add_people_title">"Ismerősök meghívása"</string>
|
||||||
|
<string name="screen_create_room_error_creating_room">"Hiba történt a szoba létrehozásakor"</string>
|
||||||
|
<string name="screen_create_room_private_option_description">"Csak a meghívottak léphetnek be ebbe a szobába. Az összes üzenet végpontok közti titkosítással van védve."</string>
|
||||||
|
<string name="screen_create_room_private_option_title">"Privát szoba"</string>
|
||||||
|
<string name="screen_create_room_public_option_description">"Bárki megtalálhatja ezt a szobát.
|
||||||
|
Ezt bármikor módosíthatja a szobabeállításokban."</string>
|
||||||
|
<string name="screen_create_room_public_option_title">"Nyilvános szoba"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_description">"Bárki csatlakozhat ehhez a szobához"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_title">"Bárki"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_header">"Szobahozzáférés"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_description">"Bárki kérheti, hogy csatlakozzon a szobához, de egy adminisztrátornak vagy moderátornak el kell fogadnia a kérést"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_title">"Csatlakozás kérése"</string>
|
||||||
|
<string name="screen_create_room_room_address_section_footer">"Ahhoz, hogy ez a szoba látható legyen a nyilvános szobák címtárában, meg kell adnia a szoba címét."</string>
|
||||||
|
<string name="screen_create_room_room_address_section_title">"A szoba címe"</string>
|
||||||
|
<string name="screen_create_room_room_name_label">"Szoba neve"</string>
|
||||||
|
<string name="screen_create_room_room_visibility_section_title">"Szoba láthatósága"</string>
|
||||||
|
<string name="screen_create_room_title">"Szoba létrehozása"</string>
|
||||||
|
<string name="screen_create_room_topic_label">"Téma (nem kötelező)"</string>
|
||||||
|
<string name="screen_room_directory_search_title">"Szobakatalógus"</string>
|
||||||
|
<string name="screen_start_chat_error_starting_chat">"Hiba történt a csevegés indításakor"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_action">"Csatlakozás a szobához cím szerint"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_invalid_address">"Nem érvényes cím"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_placeholder">"Írja be…"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_found">"Megfelelő szoba található"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_not_found">"Szoba nem található"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_supporting_text">"pl. #szoba-neve:matrix.org"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -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">"Ruangan baru"</string>
|
||||||
|
<string name="screen_create_room_add_people_title">"Undang orang-orang"</string>
|
||||||
|
<string name="screen_create_room_error_creating_room">"Terjadi kesalahan saat membuat ruangan"</string>
|
||||||
|
<string name="screen_create_room_private_option_description">"Hanya orang-orang yang diundang dapat mengakses ruangan ini. Semua pesan terenkripsi secara ujung ke ujung."</string>
|
||||||
|
<string name="screen_create_room_private_option_title">"Ruangan pribadi"</string>
|
||||||
|
<string name="screen_create_room_public_option_description">"Siapa pun dapat mencari ruangan ini.
|
||||||
|
Anda dapat mengubah ini kapan pun dalam pengaturan ruangan."</string>
|
||||||
|
<string name="screen_create_room_public_option_title">"Ruangan publik"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_description">"Siapa pun dapat bergabung dengan ruangan ini"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_title">"Siapa pun"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_header">"Akses Ruangan"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_description">"Siapa pun dapat meminta untuk bergabung dengan ruangan tetapi administrator atau moderator harus menerima permintaan tersebut"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_title">"Minta untuk bergabung"</string>
|
||||||
|
<string name="screen_create_room_room_address_section_footer">"Supaya ruangan ini terlihat di direktori ruangan publik, Anda memerlukan alamat ruangan."</string>
|
||||||
|
<string name="screen_create_room_room_address_section_title">"Alamat ruangan"</string>
|
||||||
|
<string name="screen_create_room_room_name_label">"Nama ruangan"</string>
|
||||||
|
<string name="screen_create_room_room_visibility_section_title">"Keterlihatan ruangan"</string>
|
||||||
|
<string name="screen_create_room_title">"Buat ruangan"</string>
|
||||||
|
<string name="screen_create_room_topic_label">"Topik (opsional)"</string>
|
||||||
|
<string name="screen_room_directory_search_title">"Direktori ruangan"</string>
|
||||||
|
<string name="screen_start_chat_error_starting_chat">"Terjadi kesalahan saat mencoba memulai obrolan"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_action">"Bergabung dalam ruangan berdasarkan alamat"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_invalid_address">"Bukan alamat yang valid"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_placeholder">"Masuk…"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_found">"Ruangan yang cocok ditemukan"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_not_found">"Ruangan tidak ditemukan"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_supporting_text">"mis. #nama-ruangan:matrix.org"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -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">"Nuova stanza"</string>
|
||||||
|
<string name="screen_create_room_add_people_title">"Invita persone"</string>
|
||||||
|
<string name="screen_create_room_error_creating_room">"Si è verificato un errore durante la creazione della stanza"</string>
|
||||||
|
<string name="screen_create_room_private_option_description">"Solo le persone invitate possono accedere a questa stanza. Tutti i messaggi sono cifrati end-to-end."</string>
|
||||||
|
<string name="screen_create_room_private_option_title">"Stanza privata"</string>
|
||||||
|
<string name="screen_create_room_public_option_description">"Chiunque può trovare questa stanza.
|
||||||
|
Puoi modificarlo in qualsiasi momento nelle impostazioni della stanza."</string>
|
||||||
|
<string name="screen_create_room_public_option_title">"Stanza pubblica"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_description">"Chiunque può entrare in questa stanza"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_title">"Chiunque"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_header">"Accesso alla stanza"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_description">"Chiunque può chiedere di entrare nella stanza, ma un amministratore o un moderatore dovrà accettare la richiesta"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_title">"Chiedi di entrare"</string>
|
||||||
|
<string name="screen_create_room_room_address_section_footer">"Affinché questa stanza sia visibile nell\'elenco delle stanze pubbliche, è necessario un indirizzo della stanza."</string>
|
||||||
|
<string name="screen_create_room_room_address_section_title">"Indirizzo della stanza"</string>
|
||||||
|
<string name="screen_create_room_room_name_label">"Nome stanza"</string>
|
||||||
|
<string name="screen_create_room_room_visibility_section_title">"Visibilità della stanza"</string>
|
||||||
|
<string name="screen_create_room_title">"Crea una stanza"</string>
|
||||||
|
<string name="screen_create_room_topic_label">"Argomento (facoltativo)"</string>
|
||||||
|
<string name="screen_room_directory_search_title">"Elenco delle stanze"</string>
|
||||||
|
<string name="screen_start_chat_error_starting_chat">"Si è verificato un errore durante il tentativo di avviare una chat"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_action">"Accedi alla stanza tramite indirizzo"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_invalid_address">"Indirizzo non valido"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_placeholder">"Inserisci…"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_found">"Stanza trovata"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_not_found">"Stanza non trovata"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_supporting_text">"ad esempio #room -name:matrix.org"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?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_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_room_name_label">"ოთახის სახელი"</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_start_chat_error_starting_chat">"ჩატის დაწყების მცდელობისას შეცდომა მოხდა"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -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_create_room_action_create_room">"Naujas kambarys"</string>
|
||||||
|
<string name="screen_create_room_add_people_title">"Pakviesti žmonių"</string>
|
||||||
|
<string name="screen_create_room_error_creating_room">"Kuriant kambarį įvyko klaida"</string>
|
||||||
|
<string name="screen_create_room_private_option_description">"Į šį kambarį gali patekti tik pakviesti žmonės. Visi pranešimai yra užšifruoti nuo pradžios iki galo."</string>
|
||||||
|
<string name="screen_create_room_private_option_title">"Privatus kambarys"</string>
|
||||||
|
<string name="screen_create_room_public_option_description">"Bet kas gali rasti šį kambarį.
|
||||||
|
Tai galite bet kada pakeisti kambario nustatymuose."</string>
|
||||||
|
<string name="screen_create_room_room_name_label">"Kambario pavadinimas"</string>
|
||||||
|
<string name="screen_create_room_title">"Kurti kambarį"</string>
|
||||||
|
<string name="screen_create_room_topic_label">"Tema (nebūtina)"</string>
|
||||||
|
<string name="screen_start_chat_error_starting_chat">"Bandant pradėti pokalbį įvyko klaida"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -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">"Nytt rom"</string>
|
||||||
|
<string name="screen_create_room_add_people_title">"Inviter folk"</string>
|
||||||
|
<string name="screen_create_room_error_creating_room">"Det oppsto en feil under opprettelsen av rommet"</string>
|
||||||
|
<string name="screen_create_room_private_option_description">"Bare inviterte personer har tilgang til dette rommet. Alle meldinger er ende-til-ende-kryptert."</string>
|
||||||
|
<string name="screen_create_room_private_option_title">"Privat rom"</string>
|
||||||
|
<string name="screen_create_room_public_option_description">"Alle kan finne dette rommet.
|
||||||
|
Du kan endre dette når som helst i rominnstillingene."</string>
|
||||||
|
<string name="screen_create_room_public_option_title">"Offentlig rom"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_description">"Alle kan bli med i dette rommet"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_title">"Alle"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_header">"Tilgang til rom"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_description">"Alle kan be om å få bli med i rommet, men en administrator eller moderator må godta forespørselen"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_title">"Be om å bli med"</string>
|
||||||
|
<string name="screen_create_room_room_address_section_footer">"For at dette rommet skal være synlig i den offentlige romkatalogen, trenger du en romadresse."</string>
|
||||||
|
<string name="screen_create_room_room_address_section_title">"Romadresse"</string>
|
||||||
|
<string name="screen_create_room_room_name_label">"Romnavn"</string>
|
||||||
|
<string name="screen_create_room_room_visibility_section_title">"Romsynlighet"</string>
|
||||||
|
<string name="screen_create_room_title">"Opprett et rom"</string>
|
||||||
|
<string name="screen_create_room_topic_label">"Emne (valgfritt)"</string>
|
||||||
|
<string name="screen_room_directory_search_title">"Romkatalog"</string>
|
||||||
|
<string name="screen_start_chat_error_starting_chat">"Det oppstod en feil når du prøvde å starte en chat"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_action">"Bli med i rommet med adresse"</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">"Gå inn…"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_found">"Matchende rom funnet"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_not_found">"Rom ikke funnet"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_supporting_text">"f.eks. #rom-navn:matrix.org"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?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">"Nieuwe kamer"</string>
|
||||||
|
<string name="screen_create_room_add_people_title">"Mensen uitnodigen"</string>
|
||||||
|
<string name="screen_create_room_error_creating_room">"Er is een fout opgetreden bij het aanmaken van de kamer"</string>
|
||||||
|
<string name="screen_create_room_private_option_description">"Alleen uitgenodigde personen hebben toegang tot deze kamer. Alle berichten zijn end-to-end versleuteld."</string>
|
||||||
|
<string name="screen_create_room_private_option_title">"Privé kamer"</string>
|
||||||
|
<string name="screen_create_room_public_option_description">"Iedereen kan deze kamer vinden.
|
||||||
|
Je kunt dit op elk gewenst moment wijzigen in de kamerinstellingen."</string>
|
||||||
|
<string name="screen_create_room_public_option_title">"Openbare kamer"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_description">"Iedereen kan toetreden tot deze kamer"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_title">"Iedereen"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_header">"Toegang tot de kamer"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_description">"Iedereen kan vragen om toe te treden tot de kamer, maar een beheerder of moderator moet het verzoek accepteren"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_title">"Vraag om toe te treden"</string>
|
||||||
|
<string name="screen_create_room_room_name_label">"Naam van de kamer"</string>
|
||||||
|
<string name="screen_create_room_title">"Creëer een kamer"</string>
|
||||||
|
<string name="screen_create_room_topic_label">"Onderwerp (optioneel)"</string>
|
||||||
|
<string name="screen_room_directory_search_title">"Kamergids"</string>
|
||||||
|
<string name="screen_start_chat_error_starting_chat">"Er is een fout opgetreden bij het starten van een chat"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -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">"Nowy pokój"</string>
|
||||||
|
<string name="screen_create_room_add_people_title">"Zaproś znajomych"</string>
|
||||||
|
<string name="screen_create_room_error_creating_room">"Wystąpił błąd w trakcie tworzenia pokoju"</string>
|
||||||
|
<string name="screen_create_room_private_option_description">"Tylko zaproszone osoby mogą dołączyć do tego pokoju. Wszystkie wiadomości są szyfrowane end-to-end."</string>
|
||||||
|
<string name="screen_create_room_private_option_title">"Pokój prywatny"</string>
|
||||||
|
<string name="screen_create_room_public_option_description">"Każdy może znaleźć ten pokój.
|
||||||
|
Możesz to zmienić w ustawieniach pokoju."</string>
|
||||||
|
<string name="screen_create_room_public_option_title">"Pokój publiczny"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_description">"Każdy może dołączyć do tego pokoju"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_title">"Wszyscy"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_header">"Dostęp do pokoju"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_description">"Każdy może poprosić o dołączenie do pokoju, ale administrator lub moderator będzie musiał zatwierdzić prośbę"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_title">"Poproś o dołączenie"</string>
|
||||||
|
<string name="screen_create_room_room_address_section_footer">"Aby ten pokój był widoczny w katalogu pomieszczeń publicznych, będziesz potrzebował adres pokoju."</string>
|
||||||
|
<string name="screen_create_room_room_address_section_title">"Adres pokoju"</string>
|
||||||
|
<string name="screen_create_room_room_name_label">"Nazwa pokoju"</string>
|
||||||
|
<string name="screen_create_room_room_visibility_section_title">"Widoczność pomieszczenia"</string>
|
||||||
|
<string name="screen_create_room_title">"Utwórz pokój"</string>
|
||||||
|
<string name="screen_create_room_topic_label">"Temat (opcjonalnie)"</string>
|
||||||
|
<string name="screen_room_directory_search_title">"Katalog pokoi"</string>
|
||||||
|
<string name="screen_start_chat_error_starting_chat">"Wystąpił błąd podczas próby rozpoczęcia czatu"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_action">"Dołącz do pokoju za pomocą adresu"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_invalid_address">"Nieprawidłowy adres"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_placeholder">"Wprowadź…"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_found">"Znaleziono pasujący pokój"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_not_found">"Nie znaleziono pokoju"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_supporting_text">"np. #room-name:matrix.org"</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -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">"Nova sala"</string>
|
||||||
|
<string name="screen_create_room_add_people_title">"Convidar pessoas"</string>
|
||||||
|
<string name="screen_create_room_error_creating_room">"Ocorreu um erro ao criar a sala"</string>
|
||||||
|
<string name="screen_create_room_private_option_description">"Apenas as pessoas convidadas podem aceder a esta sala. Todas as mensagens são criptografadas de ponta a ponta."</string>
|
||||||
|
<string name="screen_create_room_private_option_title">"Sala privada"</string>
|
||||||
|
<string name="screen_create_room_public_option_description">"Qualquer um pode encontrar esta sala.
|
||||||
|
Você pode mudar isso a qualquer momento nas configurações da sala."</string>
|
||||||
|
<string name="screen_create_room_public_option_title">"Sala pública"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_description">"Qualquer pessoa pode entrar nesta sala"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_anyone_option_title">"Qualquer pessoa"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_header">"Acesso à sala"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_description">"Qualquer pessoa pode pedir para entrar na sala, mas um administrador ou moderador terá de aceitar a solicitação"</string>
|
||||||
|
<string name="screen_create_room_room_access_section_knocking_option_title">"Pedir para entrar"</string>
|
||||||
|
<string name="screen_create_room_room_address_section_footer">"Para que esta sala fique visível no diretório público de salas, você precisará de um endereço de sala."</string>
|
||||||
|
<string name="screen_create_room_room_address_section_title">"Endereço da sala"</string>
|
||||||
|
<string name="screen_create_room_room_name_label">"Nome da sala"</string>
|
||||||
|
<string name="screen_create_room_room_visibility_section_title">"Visibilidade da sala"</string>
|
||||||
|
<string name="screen_create_room_title">"Criar uma sala"</string>
|
||||||
|
<string name="screen_create_room_topic_label">"Tópico (opcional)"</string>
|
||||||
|
<string name="screen_room_directory_search_title">"Diretório de salas"</string>
|
||||||
|
<string name="screen_start_chat_error_starting_chat">"Ocorreu um erro ao tentar iniciar um chat"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_action">"Entrar na sala pelo endereço"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_invalid_address">"Não é um endereço válido"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_placeholder">"Entrar…"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_found">"Foi encontrada uma sala correspondente"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_room_not_found">"Sala não encontrada"</string>
|
||||||
|
<string name="screen_start_chat_join_room_by_address_supporting_text">"Por exemplo, #nome-da-sala:matrix.org"</string>
|
||||||
|
</resources>
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue