mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 05:31:21 +03:00
Merge pull request #3976 from vector-im/feature/bca/space_team_invite_mail
Add invite by email screen in create space flow
This commit is contained in:
commit
3575157f1c
15 changed files with 362 additions and 137 deletions
1
changelog.d/3678.feature
Normal file
1
changelog.d/3678.feature
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Spaces | M3.23 Invite by email in create private space flow
|
1
changelog.d/3945.bugfix
Normal file
1
changelog.d/3945.bugfix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Remove the "Teammate spaces aren't quite ready" bottom sheet
|
|
@ -142,6 +142,7 @@ import im.vector.app.features.signout.soft.SoftLogoutFragment
|
||||||
import im.vector.app.features.spaces.SpaceListFragment
|
import im.vector.app.features.spaces.SpaceListFragment
|
||||||
import im.vector.app.features.spaces.create.ChoosePrivateSpaceTypeFragment
|
import im.vector.app.features.spaces.create.ChoosePrivateSpaceTypeFragment
|
||||||
import im.vector.app.features.spaces.create.ChooseSpaceTypeFragment
|
import im.vector.app.features.spaces.create.ChooseSpaceTypeFragment
|
||||||
|
import im.vector.app.features.spaces.create.CreateSpaceAdd3pidInvitesFragment
|
||||||
import im.vector.app.features.spaces.create.CreateSpaceDefaultRoomsFragment
|
import im.vector.app.features.spaces.create.CreateSpaceDefaultRoomsFragment
|
||||||
import im.vector.app.features.spaces.create.CreateSpaceDetailsFragment
|
import im.vector.app.features.spaces.create.CreateSpaceDetailsFragment
|
||||||
import im.vector.app.features.spaces.explore.SpaceDirectoryFragment
|
import im.vector.app.features.spaces.explore.SpaceDirectoryFragment
|
||||||
|
@ -793,6 +794,11 @@ interface FragmentModule {
|
||||||
@FragmentKey(ChoosePrivateSpaceTypeFragment::class)
|
@FragmentKey(ChoosePrivateSpaceTypeFragment::class)
|
||||||
fun bindChoosePrivateSpaceTypeFragment(fragment: ChoosePrivateSpaceTypeFragment): Fragment
|
fun bindChoosePrivateSpaceTypeFragment(fragment: ChoosePrivateSpaceTypeFragment): Fragment
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@FragmentKey(CreateSpaceAdd3pidInvitesFragment::class)
|
||||||
|
fun bindCreateSpaceAdd3pidInvitesFragment(fragment: CreateSpaceAdd3pidInvitesFragment): Fragment
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@IntoMap
|
@IntoMap
|
||||||
@FragmentKey(SpaceAddRoomFragment::class)
|
@FragmentKey(SpaceAddRoomFragment::class)
|
||||||
|
|
|
@ -31,6 +31,7 @@ import im.vector.app.core.platform.SimpleFragmentActivity
|
||||||
import im.vector.app.features.spaces.create.ChoosePrivateSpaceTypeFragment
|
import im.vector.app.features.spaces.create.ChoosePrivateSpaceTypeFragment
|
||||||
import im.vector.app.features.spaces.create.ChooseSpaceTypeFragment
|
import im.vector.app.features.spaces.create.ChooseSpaceTypeFragment
|
||||||
import im.vector.app.features.spaces.create.CreateSpaceAction
|
import im.vector.app.features.spaces.create.CreateSpaceAction
|
||||||
|
import im.vector.app.features.spaces.create.CreateSpaceAdd3pidInvitesFragment
|
||||||
import im.vector.app.features.spaces.create.CreateSpaceDefaultRoomsFragment
|
import im.vector.app.features.spaces.create.CreateSpaceDefaultRoomsFragment
|
||||||
import im.vector.app.features.spaces.create.CreateSpaceDetailsFragment
|
import im.vector.app.features.spaces.create.CreateSpaceDetailsFragment
|
||||||
import im.vector.app.features.spaces.create.CreateSpaceEvents
|
import im.vector.app.features.spaces.create.CreateSpaceEvents
|
||||||
|
@ -55,18 +56,21 @@ class SpaceCreationActivity : SimpleFragmentActivity(), CreateSpaceViewModel.Fac
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
if (isFirstCreation()) {
|
if (isFirstCreation()) {
|
||||||
when (withState(viewModel) { it.step }) {
|
when (withState(viewModel) { it.step }) {
|
||||||
CreateSpaceState.Step.ChooseType -> {
|
CreateSpaceState.Step.ChooseType -> {
|
||||||
navigateToFragment(ChooseSpaceTypeFragment::class.java)
|
navigateToFragment(ChooseSpaceTypeFragment::class.java)
|
||||||
}
|
}
|
||||||
CreateSpaceState.Step.SetDetails -> {
|
CreateSpaceState.Step.SetDetails -> {
|
||||||
navigateToFragment(ChooseSpaceTypeFragment::class.java)
|
navigateToFragment(ChooseSpaceTypeFragment::class.java)
|
||||||
}
|
}
|
||||||
CreateSpaceState.Step.AddRooms -> {
|
CreateSpaceState.Step.AddRooms -> {
|
||||||
navigateToFragment(CreateSpaceDefaultRoomsFragment::class.java)
|
navigateToFragment(CreateSpaceDefaultRoomsFragment::class.java)
|
||||||
}
|
}
|
||||||
CreateSpaceState.Step.ChoosePrivateType -> {
|
CreateSpaceState.Step.ChoosePrivateType -> {
|
||||||
navigateToFragment(ChoosePrivateSpaceTypeFragment::class.java)
|
navigateToFragment(ChoosePrivateSpaceTypeFragment::class.java)
|
||||||
}
|
}
|
||||||
|
CreateSpaceState.Step.AddEmailsOrInvites -> {
|
||||||
|
navigateToFragment(CreateSpaceAdd3pidInvitesFragment::class.java)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,6 +96,9 @@ class SpaceCreationActivity : SimpleFragmentActivity(), CreateSpaceViewModel.Fac
|
||||||
CreateSpaceEvents.NavigateToAddRooms -> {
|
CreateSpaceEvents.NavigateToAddRooms -> {
|
||||||
navigateToFragment(CreateSpaceDefaultRoomsFragment::class.java)
|
navigateToFragment(CreateSpaceDefaultRoomsFragment::class.java)
|
||||||
}
|
}
|
||||||
|
CreateSpaceEvents.NavigateToAdd3Pid -> {
|
||||||
|
navigateToFragment(CreateSpaceAdd3pidInvitesFragment::class.java)
|
||||||
|
}
|
||||||
CreateSpaceEvents.NavigateToChoosePrivateType -> {
|
CreateSpaceEvents.NavigateToChoosePrivateType -> {
|
||||||
navigateToFragment(ChoosePrivateSpaceTypeFragment::class.java)
|
navigateToFragment(ChoosePrivateSpaceTypeFragment::class.java)
|
||||||
}
|
}
|
||||||
|
@ -143,6 +150,7 @@ class SpaceCreationActivity : SimpleFragmentActivity(), CreateSpaceViewModel.Fac
|
||||||
if (state.spaceType == SpaceType.Public) R.string.your_public_space
|
if (state.spaceType == SpaceType.Public) R.string.your_public_space
|
||||||
else R.string.your_private_space
|
else R.string.your_private_space
|
||||||
}
|
}
|
||||||
|
CreateSpaceState.Step.AddEmailsOrInvites,
|
||||||
CreateSpaceState.Step.ChoosePrivateType -> R.string.your_private_space
|
CreateSpaceState.Step.ChoosePrivateType -> R.string.your_private_space
|
||||||
}
|
}
|
||||||
supportActionBar?.let {
|
supportActionBar?.let {
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2021 New Vector Ltd
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package im.vector.app.features.spaces.create
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.fragment.app.setFragmentResult
|
|
||||||
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
|
|
||||||
import im.vector.app.databinding.BottomSheetSpaceCreatePrivateWarningBinding
|
|
||||||
|
|
||||||
class BetaWarningBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetSpaceCreatePrivateWarningBinding>() {
|
|
||||||
|
|
||||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?) =
|
|
||||||
BottomSheetSpaceCreatePrivateWarningBinding.inflate(inflater, container, false)
|
|
||||||
|
|
||||||
override val showExpanded = true
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
|
|
||||||
views.continueButton.debouncedClicks {
|
|
||||||
setFragmentResult(REQUEST_KEY, Bundle.EMPTY)
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val REQUEST_KEY = "BetaWarningBottomSheet"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -20,7 +20,6 @@ import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.fragment.app.setFragmentResultListener
|
|
||||||
import com.airbnb.mvrx.activityViewModel
|
import com.airbnb.mvrx.activityViewModel
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.epoxy.onClick
|
import im.vector.app.core.epoxy.onClick
|
||||||
|
@ -39,13 +38,6 @@ class ChoosePrivateSpaceTypeFragment @Inject constructor(
|
||||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?) =
|
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?) =
|
||||||
FragmentSpaceCreateChoosePrivateModelBinding.inflate(layoutInflater, container, false)
|
FragmentSpaceCreateChoosePrivateModelBinding.inflate(layoutInflater, container, false)
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
setFragmentResultListener(BetaWarningBottomSheet.REQUEST_KEY) { _, _ ->
|
|
||||||
sharedViewModel.handle(CreateSpaceAction.SetSpaceTopology(SpaceTopology.MeAndTeammates))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
@ -54,7 +46,7 @@ class ChoosePrivateSpaceTypeFragment @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
views.teammatesButton.onClick {
|
views.teammatesButton.onClick {
|
||||||
BetaWarningBottomSheet().show(parentFragmentManager, "warning")
|
sharedViewModel.handle(CreateSpaceAction.SetSpaceTopology(SpaceTopology.MeAndTeammates))
|
||||||
}
|
}
|
||||||
|
|
||||||
sharedViewModel.subscribe { state ->
|
sharedViewModel.subscribe { state ->
|
||||||
|
|
|
@ -28,6 +28,8 @@ sealed class CreateSpaceAction : VectorViewModelAction {
|
||||||
object OnBackPressed : CreateSpaceAction()
|
object OnBackPressed : CreateSpaceAction()
|
||||||
object NextFromDetails : CreateSpaceAction()
|
object NextFromDetails : CreateSpaceAction()
|
||||||
object NextFromDefaultRooms : CreateSpaceAction()
|
object NextFromDefaultRooms : CreateSpaceAction()
|
||||||
|
object NextFromAdd3pid : CreateSpaceAction()
|
||||||
data class DefaultRoomNameChanged(val index: Int, val name: String) : CreateSpaceAction()
|
data class DefaultRoomNameChanged(val index: Int, val name: String) : CreateSpaceAction()
|
||||||
|
data class DefaultInvite3pidChanged(val index: Int, val email: String) : CreateSpaceAction()
|
||||||
data class SetSpaceTopology(val topology: SpaceTopology) : CreateSpaceAction()
|
data class SetSpaceTopology(val topology: SpaceTopology) : CreateSpaceAction()
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.features.spaces.create
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import com.airbnb.mvrx.activityViewModel
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.extensions.cleanup
|
||||||
|
import im.vector.app.core.extensions.configureWith
|
||||||
|
import im.vector.app.core.extensions.hideKeyboard
|
||||||
|
import im.vector.app.core.platform.OnBackPressed
|
||||||
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
|
import im.vector.app.databinding.FragmentSpaceCreateGenericEpoxyFormBinding
|
||||||
|
import im.vector.app.features.settings.VectorSettingsActivity
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class CreateSpaceAdd3pidInvitesFragment @Inject constructor(
|
||||||
|
private val epoxyController: SpaceAdd3pidEpoxyController
|
||||||
|
) : VectorBaseFragment<FragmentSpaceCreateGenericEpoxyFormBinding>(),
|
||||||
|
SpaceAdd3pidEpoxyController.Listener,
|
||||||
|
OnBackPressed {
|
||||||
|
|
||||||
|
private val sharedViewModel: CreateSpaceViewModel by activityViewModel()
|
||||||
|
|
||||||
|
override fun onBackPressed(toolbarButton: Boolean): Boolean {
|
||||||
|
sharedViewModel.handle(CreateSpaceAction.OnBackPressed)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
views.recyclerView.configureWith(epoxyController)
|
||||||
|
epoxyController.listener = this
|
||||||
|
|
||||||
|
sharedViewModel.subscribe(this) {
|
||||||
|
invalidateState(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
views.nextButton.setText(R.string.next_pf)
|
||||||
|
views.nextButton.debouncedClicks {
|
||||||
|
view.hideKeyboard()
|
||||||
|
sharedViewModel.handle(CreateSpaceAction.NextFromAdd3pid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun invalidateState(it: CreateSpaceState) {
|
||||||
|
epoxyController.setData(it)
|
||||||
|
val noEmails = it.default3pidInvite?.all { it.value.isNullOrBlank() } ?: true
|
||||||
|
views.nextButton.text = if (noEmails) {
|
||||||
|
getString(R.string.skip_for_now)
|
||||||
|
} else {
|
||||||
|
getString(R.string.next_pf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
views.recyclerView.cleanup()
|
||||||
|
epoxyController.listener = null
|
||||||
|
super.onDestroyView()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?) =
|
||||||
|
FragmentSpaceCreateGenericEpoxyFormBinding.inflate(layoutInflater, container, false)
|
||||||
|
|
||||||
|
override fun on3pidChange(index: Int, newName: String) {
|
||||||
|
sharedViewModel.handle(CreateSpaceAction.DefaultInvite3pidChanged(index, newName))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNoIdentityServer() {
|
||||||
|
navigator.openSettings(
|
||||||
|
requireContext(),
|
||||||
|
VectorSettingsActivity.EXTRA_DIRECT_ACCESS_DISCOVERY_SETTINGS
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ sealed class CreateSpaceEvents : VectorViewEvents {
|
||||||
object NavigateToDetails : CreateSpaceEvents()
|
object NavigateToDetails : CreateSpaceEvents()
|
||||||
object NavigateToChooseType : CreateSpaceEvents()
|
object NavigateToChooseType : CreateSpaceEvents()
|
||||||
object NavigateToAddRooms : CreateSpaceEvents()
|
object NavigateToAddRooms : CreateSpaceEvents()
|
||||||
|
object NavigateToAdd3Pid : CreateSpaceEvents()
|
||||||
object NavigateToChoosePrivateType : CreateSpaceEvents()
|
object NavigateToChoosePrivateType : CreateSpaceEvents()
|
||||||
object Dismiss : CreateSpaceEvents()
|
object Dismiss : CreateSpaceEvents()
|
||||||
data class FinishSuccess(val spaceId: String, val defaultRoomId: String?, val topology: SpaceTopology?) : CreateSpaceEvents()
|
data class FinishSuccess(val spaceId: String, val defaultRoomId: String?, val topology: SpaceTopology?) : CreateSpaceEvents()
|
||||||
|
|
|
@ -34,13 +34,17 @@ data class CreateSpaceState(
|
||||||
val aliasVerificationTask: Async<Boolean> = Uninitialized,
|
val aliasVerificationTask: Async<Boolean> = Uninitialized,
|
||||||
val nameInlineError: String? = null,
|
val nameInlineError: String? = null,
|
||||||
val defaultRooms: Map<Int /** position in form */, String?>? = null,
|
val defaultRooms: Map<Int /** position in form */, String?>? = null,
|
||||||
val creationResult: Async<String> = Uninitialized
|
val default3pidInvite: Map<Int /** position in form */, String?>? = null,
|
||||||
|
val emailValidationResult: Map<Int /** position in form */, Boolean>? = null,
|
||||||
|
val creationResult: Async<String> = Uninitialized,
|
||||||
|
val canInviteByMail: Boolean = false
|
||||||
) : MvRxState {
|
) : MvRxState {
|
||||||
|
|
||||||
enum class Step {
|
enum class Step {
|
||||||
ChooseType,
|
ChooseType,
|
||||||
SetDetails,
|
SetDetails,
|
||||||
AddRooms,
|
AddRooms,
|
||||||
ChoosePrivateType
|
ChoosePrivateType,
|
||||||
|
AddEmailsOrInvites
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import dagger.assisted.AssistedInject
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.error.ErrorFormatter
|
import im.vector.app.core.error.ErrorFormatter
|
||||||
import im.vector.app.core.extensions.exhaustive
|
import im.vector.app.core.extensions.exhaustive
|
||||||
|
import im.vector.app.core.extensions.isEmail
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
@ -38,6 +39,7 @@ import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.MatrixPatterns
|
import org.matrix.android.sdk.api.MatrixPatterns
|
||||||
import org.matrix.android.sdk.api.MatrixPatterns.getDomain
|
import org.matrix.android.sdk.api.MatrixPatterns.getDomain
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
import org.matrix.android.sdk.api.session.identity.IdentityServiceListener
|
||||||
import org.matrix.android.sdk.api.session.room.AliasAvailabilityResult
|
import org.matrix.android.sdk.api.session.room.AliasAvailabilityResult
|
||||||
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
|
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
|
||||||
|
|
||||||
|
@ -49,12 +51,28 @@ class CreateSpaceViewModel @AssistedInject constructor(
|
||||||
private val errorFormatter: ErrorFormatter
|
private val errorFormatter: ErrorFormatter
|
||||||
) : VectorViewModel<CreateSpaceState, CreateSpaceAction, CreateSpaceEvents>(initialState) {
|
) : VectorViewModel<CreateSpaceState, CreateSpaceAction, CreateSpaceEvents>(initialState) {
|
||||||
|
|
||||||
|
private val identityService = session.identityService()
|
||||||
|
|
||||||
|
private val identityServerManagerListener = object : IdentityServiceListener {
|
||||||
|
override fun onIdentityServerChange() {
|
||||||
|
val identityServerUrl = identityService.getCurrentIdentityServerUrl()
|
||||||
|
setState {
|
||||||
|
copy(
|
||||||
|
canInviteByMail = identityServerUrl != null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
val identityServerUrl = identityService.getCurrentIdentityServerUrl()
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
homeServerName = session.myUserId.getDomain()
|
homeServerName = session.myUserId.getDomain(),
|
||||||
|
canInviteByMail = identityServerUrl != null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
startListenToIdentityManager()
|
||||||
}
|
}
|
||||||
|
|
||||||
@AssistedFactory
|
@AssistedFactory
|
||||||
|
@ -62,6 +80,19 @@ class CreateSpaceViewModel @AssistedInject constructor(
|
||||||
fun create(initialState: CreateSpaceState): CreateSpaceViewModel
|
fun create(initialState: CreateSpaceState): CreateSpaceViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun startListenToIdentityManager() {
|
||||||
|
identityService.addListener(identityServerManagerListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun stopListenToIdentityManager() {
|
||||||
|
identityService.removeListener(identityServerManagerListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCleared() {
|
||||||
|
stopListenToIdentityManager()
|
||||||
|
super.onCleared()
|
||||||
|
}
|
||||||
|
|
||||||
companion object : MvRxViewModelFactory<CreateSpaceViewModel, CreateSpaceState> {
|
companion object : MvRxViewModelFactory<CreateSpaceViewModel, CreateSpaceState> {
|
||||||
|
|
||||||
override fun create(viewModelContext: ViewModelContext, state: CreateSpaceState): CreateSpaceViewModel? {
|
override fun create(viewModelContext: ViewModelContext, state: CreateSpaceState): CreateSpaceViewModel? {
|
||||||
|
@ -84,7 +115,7 @@ class CreateSpaceViewModel @AssistedInject constructor(
|
||||||
|
|
||||||
override fun handle(action: CreateSpaceAction) {
|
override fun handle(action: CreateSpaceAction) {
|
||||||
when (action) {
|
when (action) {
|
||||||
is CreateSpaceAction.SetRoomType -> {
|
is CreateSpaceAction.SetRoomType -> {
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
step = CreateSpaceState.Step.SetDetails,
|
step = CreateSpaceState.Step.SetDetails,
|
||||||
|
@ -93,7 +124,7 @@ class CreateSpaceViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
_viewEvents.post(CreateSpaceEvents.NavigateToDetails)
|
_viewEvents.post(CreateSpaceEvents.NavigateToDetails)
|
||||||
}
|
}
|
||||||
is CreateSpaceAction.NameChanged -> {
|
is CreateSpaceAction.NameChanged -> {
|
||||||
setState {
|
setState {
|
||||||
if (aliasManuallyModified) {
|
if (aliasManuallyModified) {
|
||||||
copy(
|
copy(
|
||||||
|
@ -113,14 +144,14 @@ class CreateSpaceViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is CreateSpaceAction.TopicChanged -> {
|
is CreateSpaceAction.TopicChanged -> {
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
topic = action.topic
|
topic = action.topic
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is CreateSpaceAction.SpaceAliasChanged -> {
|
is CreateSpaceAction.SpaceAliasChanged -> {
|
||||||
// This called only when the alias is change manually
|
// This called only when the alias is change manually
|
||||||
// not when programmatically changed via a change on name
|
// not when programmatically changed via a change on name
|
||||||
setState {
|
setState {
|
||||||
|
@ -131,28 +162,43 @@ class CreateSpaceViewModel @AssistedInject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CreateSpaceAction.OnBackPressed -> {
|
CreateSpaceAction.OnBackPressed -> {
|
||||||
handleBackNavigation()
|
handleBackNavigation()
|
||||||
}
|
}
|
||||||
CreateSpaceAction.NextFromDetails -> {
|
CreateSpaceAction.NextFromDetails -> {
|
||||||
handleNextFromDetails()
|
handleNextFromDetails()
|
||||||
}
|
}
|
||||||
CreateSpaceAction.NextFromDefaultRooms -> {
|
CreateSpaceAction.NextFromDefaultRooms -> {
|
||||||
handleNextFromDefaultRooms()
|
handleNextFromDefaultRooms()
|
||||||
}
|
}
|
||||||
is CreateSpaceAction.DefaultRoomNameChanged -> {
|
CreateSpaceAction.NextFromAdd3pid -> {
|
||||||
|
handleNextFrom3pid()
|
||||||
|
}
|
||||||
|
is CreateSpaceAction.DefaultRoomNameChanged -> {
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
defaultRooms = (defaultRooms ?: emptyMap()).toMutableMap().apply {
|
defaultRooms = defaultRooms.orEmpty().toMutableMap().apply {
|
||||||
this[action.index] = action.name
|
this[action.index] = action.name
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is CreateSpaceAction.SetAvatar -> {
|
is CreateSpaceAction.DefaultInvite3pidChanged -> {
|
||||||
|
setState {
|
||||||
|
copy(
|
||||||
|
default3pidInvite = default3pidInvite.orEmpty().toMutableMap().apply {
|
||||||
|
this[action.index] = action.email
|
||||||
|
},
|
||||||
|
emailValidationResult = emailValidationResult.orEmpty().toMutableMap().apply {
|
||||||
|
this.remove(action.index)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is CreateSpaceAction.SetAvatar -> {
|
||||||
setState { copy(avatarUri = action.uri) }
|
setState { copy(avatarUri = action.uri) }
|
||||||
}
|
}
|
||||||
is CreateSpaceAction.SetSpaceTopology -> {
|
is CreateSpaceAction.SetSpaceTopology -> {
|
||||||
handleSetTopology(action)
|
handleSetTopology(action)
|
||||||
}
|
}
|
||||||
}.exhaustive
|
}.exhaustive
|
||||||
|
@ -173,20 +219,20 @@ class CreateSpaceViewModel @AssistedInject constructor(
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
spaceTopology = SpaceTopology.MeAndTeammates,
|
spaceTopology = SpaceTopology.MeAndTeammates,
|
||||||
step = CreateSpaceState.Step.AddRooms
|
step = CreateSpaceState.Step.AddEmailsOrInvites
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_viewEvents.post(CreateSpaceEvents.NavigateToAddRooms)
|
_viewEvents.post(CreateSpaceEvents.NavigateToAdd3Pid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleBackNavigation() = withState { state ->
|
private fun handleBackNavigation() = withState { state ->
|
||||||
when (state.step) {
|
when (state.step) {
|
||||||
CreateSpaceState.Step.ChooseType -> {
|
CreateSpaceState.Step.ChooseType -> {
|
||||||
_viewEvents.post(CreateSpaceEvents.Dismiss)
|
_viewEvents.post(CreateSpaceEvents.Dismiss)
|
||||||
}
|
}
|
||||||
CreateSpaceState.Step.SetDetails -> {
|
CreateSpaceState.Step.SetDetails -> {
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
step = CreateSpaceState.Step.ChooseType,
|
step = CreateSpaceState.Step.ChooseType,
|
||||||
|
@ -196,15 +242,15 @@ class CreateSpaceViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
_viewEvents.post(CreateSpaceEvents.NavigateToChooseType)
|
_viewEvents.post(CreateSpaceEvents.NavigateToChooseType)
|
||||||
}
|
}
|
||||||
CreateSpaceState.Step.AddRooms -> {
|
CreateSpaceState.Step.AddRooms -> {
|
||||||
if (state.spaceType == SpaceType.Private && state.spaceTopology == SpaceTopology.MeAndTeammates) {
|
if (state.spaceType == SpaceType.Private && state.spaceTopology == SpaceTopology.MeAndTeammates) {
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
spaceTopology = null,
|
spaceTopology = null,
|
||||||
step = CreateSpaceState.Step.ChoosePrivateType
|
step = CreateSpaceState.Step.AddEmailsOrInvites
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_viewEvents.post(CreateSpaceEvents.NavigateToChoosePrivateType)
|
_viewEvents.post(CreateSpaceEvents.NavigateToAdd3Pid)
|
||||||
} else {
|
} else {
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
|
@ -214,7 +260,7 @@ class CreateSpaceViewModel @AssistedInject constructor(
|
||||||
_viewEvents.post(CreateSpaceEvents.NavigateToDetails)
|
_viewEvents.post(CreateSpaceEvents.NavigateToDetails)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CreateSpaceState.Step.ChoosePrivateType -> {
|
CreateSpaceState.Step.ChoosePrivateType -> {
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
step = CreateSpaceState.Step.SetDetails
|
step = CreateSpaceState.Step.SetDetails
|
||||||
|
@ -222,6 +268,36 @@ class CreateSpaceViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
_viewEvents.post(CreateSpaceEvents.NavigateToDetails)
|
_viewEvents.post(CreateSpaceEvents.NavigateToDetails)
|
||||||
}
|
}
|
||||||
|
CreateSpaceState.Step.AddEmailsOrInvites -> {
|
||||||
|
setState {
|
||||||
|
copy(
|
||||||
|
step = CreateSpaceState.Step.ChoosePrivateType
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_viewEvents.post(CreateSpaceEvents.NavigateToChoosePrivateType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleNextFrom3pid() = withState { state ->
|
||||||
|
// check if emails are valid
|
||||||
|
val emailValidation = state.default3pidInvite?.mapValues {
|
||||||
|
val email = it.value
|
||||||
|
email.isNullOrEmpty() || email.isEmail()
|
||||||
|
}
|
||||||
|
if (emailValidation?.all { it.value } != false) {
|
||||||
|
setState {
|
||||||
|
copy(
|
||||||
|
step = CreateSpaceState.Step.AddRooms
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_viewEvents.post(CreateSpaceEvents.NavigateToAddRooms)
|
||||||
|
} else {
|
||||||
|
setState {
|
||||||
|
copy(
|
||||||
|
emailValidationResult = emailValidation
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,8 +372,14 @@ class CreateSpaceViewModel @AssistedInject constructor(
|
||||||
defaultRooms = state.defaultRooms
|
defaultRooms = state.defaultRooms
|
||||||
?.entries
|
?.entries
|
||||||
?.sortedBy { it.key }
|
?.sortedBy { it.key }
|
||||||
?.mapNotNull { it.value } ?: emptyList(),
|
?.mapNotNull { it.value }
|
||||||
spaceAlias = alias
|
.orEmpty(),
|
||||||
|
spaceAlias = alias,
|
||||||
|
defaultEmailToInvite = state.default3pidInvite
|
||||||
|
?.values
|
||||||
|
?.mapNotNull { it.takeIf { it?.isEmail() == true } }
|
||||||
|
?.takeIf { state.spaceTopology == SpaceTopology.MeAndTeammates }
|
||||||
|
.orEmpty()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
when (result) {
|
when (result) {
|
||||||
|
|
|
@ -25,12 +25,17 @@ import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
import org.matrix.android.sdk.api.raw.RawService
|
import org.matrix.android.sdk.api.raw.RawService
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
|
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
|
||||||
|
import org.matrix.android.sdk.api.session.identity.ThreePid
|
||||||
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
|
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.GuestAccess
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry
|
import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.RestrictedRoomPreset
|
import org.matrix.android.sdk.api.session.room.model.create.RestrictedRoomPreset
|
||||||
|
import org.matrix.android.sdk.api.session.space.CreateSpaceParams
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -49,7 +54,8 @@ data class CreateSpaceTaskParams(
|
||||||
val spaceAvatar: Uri? = null,
|
val spaceAvatar: Uri? = null,
|
||||||
val spaceAlias: String? = null,
|
val spaceAlias: String? = null,
|
||||||
val isPublic: Boolean,
|
val isPublic: Boolean,
|
||||||
val defaultRooms: List<String> = emptyList()
|
val defaultRooms: List<String> = emptyList(),
|
||||||
|
val defaultEmailToInvite: List<String> = emptyList()
|
||||||
)
|
)
|
||||||
|
|
||||||
class CreateSpaceViewModelTask @Inject constructor(
|
class CreateSpaceViewModelTask @Inject constructor(
|
||||||
|
@ -60,13 +66,28 @@ class CreateSpaceViewModelTask @Inject constructor(
|
||||||
|
|
||||||
override suspend fun execute(params: CreateSpaceTaskParams): CreateSpaceTaskResult {
|
override suspend fun execute(params: CreateSpaceTaskParams): CreateSpaceTaskResult {
|
||||||
val spaceID = try {
|
val spaceID = try {
|
||||||
session.spaceService().createSpace(
|
session.spaceService().createSpace(CreateSpaceParams().apply {
|
||||||
params.spaceName,
|
this.name = params.spaceName
|
||||||
params.spaceTopic,
|
this.topic = params.spaceTopic
|
||||||
params.spaceAvatar,
|
this.avatarUri = params.spaceAvatar
|
||||||
params.isPublic,
|
if (params.isPublic) {
|
||||||
params.spaceAlias
|
this.roomAliasName = params.spaceAlias
|
||||||
)
|
this.powerLevelContentOverride = (powerLevelContentOverride ?: PowerLevelsContent()).copy(
|
||||||
|
invite = 0
|
||||||
|
)
|
||||||
|
this.preset = CreateRoomPreset.PRESET_PUBLIC_CHAT
|
||||||
|
this.historyVisibility = RoomHistoryVisibility.WORLD_READABLE
|
||||||
|
this.guestAccess = GuestAccess.CanJoin
|
||||||
|
} else {
|
||||||
|
this.preset = CreateRoomPreset.PRESET_PRIVATE_CHAT
|
||||||
|
visibility = RoomDirectoryVisibility.PRIVATE
|
||||||
|
this.invite3pids.addAll(
|
||||||
|
params.defaultEmailToInvite.map {
|
||||||
|
ThreePid.Email(it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
return CreateSpaceTaskResult.FailedToCreateSpace(failure)
|
return CreateSpaceTaskResult.FailedToCreateSpace(failure)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.features.spaces.create
|
||||||
|
|
||||||
|
import android.text.InputType
|
||||||
|
import com.airbnb.epoxy.TypedEpoxyController
|
||||||
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.resources.ColorProvider
|
||||||
|
import im.vector.app.core.resources.StringProvider
|
||||||
|
import im.vector.app.core.ui.list.ItemStyle
|
||||||
|
import im.vector.app.core.ui.list.genericButtonItem
|
||||||
|
import im.vector.app.core.ui.list.genericFooterItem
|
||||||
|
import im.vector.app.core.ui.list.genericPillItem
|
||||||
|
import im.vector.app.features.form.formEditTextItem
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class SpaceAdd3pidEpoxyController @Inject constructor(
|
||||||
|
private val stringProvider: StringProvider,
|
||||||
|
private val colorProvider: ColorProvider
|
||||||
|
) : TypedEpoxyController<CreateSpaceState>() {
|
||||||
|
|
||||||
|
var listener: Listener? = null
|
||||||
|
|
||||||
|
override fun buildModels(data: CreateSpaceState?) {
|
||||||
|
val host = this
|
||||||
|
data ?: return
|
||||||
|
genericFooterItem {
|
||||||
|
id("info_help_header")
|
||||||
|
style(ItemStyle.TITLE)
|
||||||
|
text(host.stringProvider.getString(R.string.create_spaces_invite_public_header))
|
||||||
|
textColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
|
||||||
|
}
|
||||||
|
genericFooterItem {
|
||||||
|
id("info_help_desc")
|
||||||
|
text(host.stringProvider.getString(R.string.create_spaces_invite_public_header_desc, data.name ?: ""))
|
||||||
|
textColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.canInviteByMail) {
|
||||||
|
buildEmailFields(data, host)
|
||||||
|
} else {
|
||||||
|
genericPillItem {
|
||||||
|
id("no_IDS")
|
||||||
|
imageRes(R.drawable.ic_baseline_perm_contact_calendar_24)
|
||||||
|
text(host.stringProvider.getString(R.string.create_space_identity_server_info_none))
|
||||||
|
}
|
||||||
|
genericButtonItem {
|
||||||
|
id("Discover_Settings")
|
||||||
|
text(host.stringProvider.getString(R.string.open_discovery_settings))
|
||||||
|
textColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
|
||||||
|
buttonClickAction {
|
||||||
|
host.listener?.onNoIdentityServer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildEmailFields(data: CreateSpaceState, host: SpaceAdd3pidEpoxyController) {
|
||||||
|
for (index in 0..2) {
|
||||||
|
val mail = data.default3pidInvite?.get(index)
|
||||||
|
formEditTextItem {
|
||||||
|
id("3pid$index")
|
||||||
|
enabled(true)
|
||||||
|
value(mail)
|
||||||
|
hint(host.stringProvider.getString(R.string.medium_email))
|
||||||
|
inputType(InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS)
|
||||||
|
endIconMode(TextInputLayout.END_ICON_CLEAR_TEXT)
|
||||||
|
errorMessage(
|
||||||
|
if (data.emailValidationResult?.get(index) == false) {
|
||||||
|
host.stringProvider.getString(R.string.does_not_look_like_valid_email)
|
||||||
|
} else null
|
||||||
|
)
|
||||||
|
onTextChange { text ->
|
||||||
|
host.listener?.on3pidChange(index, text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Listener {
|
||||||
|
fun on3pidChange(index: Int, newName: String)
|
||||||
|
fun onNoIdentityServer()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,46 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="?colorSurface"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:padding="16dp">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginBottom="12dp"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
android:src="@drawable/ic_beta_pill" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
style="@style/Widget.Vector.TextView.HeadlineMedium"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginBottom="12dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/teammate_spaces_arent_quite_ready"
|
|
||||||
android:textColor="?vctr_content_primary"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
style="@style/Widget.Vector.TextView.Subtitle"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="20dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/teammate_spaces_might_not_join"
|
|
||||||
android:textColor="?vctr_content_secondary" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/continueButton"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/layout_vertical_margin"
|
|
||||||
android:text="@string/continue_anyway"
|
|
||||||
android:textAllCaps="true" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
|
@ -2316,6 +2316,7 @@
|
||||||
<string name="identity_server">Identity server</string>
|
<string name="identity_server">Identity server</string>
|
||||||
<string name="disconnect_identity_server">Disconnect identity server</string>
|
<string name="disconnect_identity_server">Disconnect identity server</string>
|
||||||
<string name="add_identity_server">Configure identity server</string>
|
<string name="add_identity_server">Configure identity server</string>
|
||||||
|
<string name="open_discovery_settings">Open Discovery Settings</string>
|
||||||
<string name="change_identity_server">Change identity server</string>
|
<string name="change_identity_server">Change identity server</string>
|
||||||
<string name="settings_discovery_identity_server_info">You are currently using %1$s to discover and be discoverable by existing contacts you know.</string>
|
<string name="settings_discovery_identity_server_info">You are currently using %1$s to discover and be discoverable by existing contacts you know.</string>
|
||||||
<string name="settings_discovery_identity_server_info_none">You are not currently using an identity server. To discover and be discoverable by existing contacts you know, configure one below.</string>
|
<string name="settings_discovery_identity_server_info_none">You are not currently using an identity server. To discover and be discoverable by existing contacts you know, configure one below.</string>
|
||||||
|
@ -2538,6 +2539,7 @@
|
||||||
<string name="login_set_email_mandatory_hint">Email</string>
|
<string name="login_set_email_mandatory_hint">Email</string>
|
||||||
<string name="login_set_email_optional_hint">Email (optional)</string>
|
<string name="login_set_email_optional_hint">Email (optional)</string>
|
||||||
<string name="login_set_email_submit">Next</string>
|
<string name="login_set_email_submit">Next</string>
|
||||||
|
<string name="does_not_look_like_valid_email">Doesn\'t look like a valid email address</string>
|
||||||
|
|
||||||
<string name="login_set_msisdn_title">Set phone number</string>
|
<string name="login_set_msisdn_title">Set phone number</string>
|
||||||
<string name="login_set_msisdn_notice">Set a phone number to optionally allow people you know to discover you.</string>
|
<string name="login_set_msisdn_notice">Set a phone number to optionally allow people you know to discover you.</string>
|
||||||
|
@ -3423,6 +3425,8 @@
|
||||||
<string name="create_space_error_empty_field_space_name">Give it a name to continue.</string>
|
<string name="create_space_error_empty_field_space_name">Give it a name to continue.</string>
|
||||||
<string name="create_spaces_room_public_header">What are some discussions you want to have in %s?</string>
|
<string name="create_spaces_room_public_header">What are some discussions you want to have in %s?</string>
|
||||||
<string name="create_spaces_room_public_header_desc">We’ll create rooms for them. You can add more later too.</string>
|
<string name="create_spaces_room_public_header_desc">We’ll create rooms for them. You can add more later too.</string>
|
||||||
|
<string name="create_spaces_invite_public_header">Who are your teammates?</string>
|
||||||
|
<string name="create_spaces_invite_public_header_desc">Ensure the right people have access to %s company. You can invite more later.</string>
|
||||||
<string name="create_spaces_room_private_header">What things are you working on?</string>
|
<string name="create_spaces_room_private_header">What things are you working on?</string>
|
||||||
<string name="create_spaces_room_private_header_desc">Let’s create a room for each of them. You can add more later too, including already existing ones.</string>
|
<string name="create_spaces_room_private_header_desc">Let’s create a room for each of them. You can add more later too, including already existing ones.</string>
|
||||||
<string name="create_spaces_default_public_room_name">General</string>
|
<string name="create_spaces_default_public_room_name">General</string>
|
||||||
|
@ -3448,6 +3452,9 @@
|
||||||
<string name="join_anyway">Join Anyway</string>
|
<string name="join_anyway">Join Anyway</string>
|
||||||
<string name="room_alias_preview_not_found">This alias is not accessible at this time.\nTry again later, or ask a room admin to check if you have access.</string>
|
<string name="room_alias_preview_not_found">This alias is not accessible at this time.\nTry again later, or ask a room admin to check if you have access.</string>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="create_space_identity_server_info_none">You are not currently using an identity server. In order to invite teammates and be discoverable by them, configure one below.</string>
|
||||||
|
|
||||||
<string name="suggested_rooms_pills_on_empty_text">You’re not in any rooms yet. Below are some suggested rooms, but you can see more with the green button bottom right.</string>
|
<string name="suggested_rooms_pills_on_empty_text">You’re not in any rooms yet. Below are some suggested rooms, but you can see more with the green button bottom right.</string>
|
||||||
<!-- First one is the space name, and the second one is user name -->
|
<!-- First one is the space name, and the second one is user name -->
|
||||||
<string name="suggested_rooms_pills_on_empty_header">Welcome to %1$s, %2$s.</string>
|
<string name="suggested_rooms_pills_on_empty_header">Welcome to %1$s, %2$s.</string>
|
||||||
|
|
Loading…
Reference in a new issue