Merge pull request #3484 from vector-im/feature/bca/spaces_alias
Feature/bca/spaces alias
This commit is contained in:
commit
be578d7fae
@ -157,4 +157,10 @@ object MatrixPatterns {
|
|||||||
fun isValidOrderString(order: String?) : Boolean {
|
fun isValidOrderString(order: String?) : Boolean {
|
||||||
return order != null && order.length < 50 && order matches ORDER_STRING_REGEX
|
return order != null && order.length < 50 && order matches ORDER_STRING_REGEX
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun candidateAliasFromRoomName(name: String): String {
|
||||||
|
return Regex("\\s").replace(name.lowercase(), "_").let {
|
||||||
|
"[^a-z0-9._%#@=+-]".toRegex().replace(it, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.api.session.room
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError
|
||||||
|
|
||||||
|
sealed class AliasAvailabilityResult {
|
||||||
|
object Available: AliasAvailabilityResult()
|
||||||
|
data class NotAvailable(val roomAliasError: RoomAliasError) : AliasAvailabilityResult()
|
||||||
|
}
|
@ -40,4 +40,6 @@ interface RoomDirectoryService {
|
|||||||
* Set the visibility of a room in the directory
|
* Set the visibility of a room in the directory
|
||||||
*/
|
*/
|
||||||
suspend fun setRoomDirectoryVisibility(roomId: String, roomDirectoryVisibility: RoomDirectoryVisibility)
|
suspend fun setRoomDirectoryVisibility(roomId: String, roomDirectoryVisibility: RoomDirectoryVisibility)
|
||||||
|
|
||||||
|
suspend fun checkAliasAvailability(aliasLocalPart: String?) : AliasAvailabilityResult
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,11 @@ interface SpaceService {
|
|||||||
/**
|
/**
|
||||||
* Just a shortcut for space creation for ease of use
|
* Just a shortcut for space creation for ease of use
|
||||||
*/
|
*/
|
||||||
suspend fun createSpace(name: String, topic: String?, avatarUri: Uri?, isPublic: Boolean): String
|
suspend fun createSpace(name: String,
|
||||||
|
topic: String?,
|
||||||
|
avatarUri: Uri?,
|
||||||
|
isPublic: Boolean,
|
||||||
|
roomAliasLocalPart: String? = null): String
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a space from a roomId
|
* Get a space from a roomId
|
||||||
|
@ -16,10 +16,13 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.internal.session.room
|
package org.matrix.android.sdk.internal.session.room
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.api.session.room.AliasAvailabilityResult
|
||||||
import org.matrix.android.sdk.api.session.room.RoomDirectoryService
|
import org.matrix.android.sdk.api.session.room.RoomDirectoryService
|
||||||
|
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError
|
||||||
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.roomdirectory.PublicRoomsParams
|
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsParams
|
||||||
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsResponse
|
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsResponse
|
||||||
|
import org.matrix.android.sdk.internal.session.room.alias.RoomAliasAvailabilityChecker
|
||||||
import org.matrix.android.sdk.internal.session.room.directory.GetPublicRoomTask
|
import org.matrix.android.sdk.internal.session.room.directory.GetPublicRoomTask
|
||||||
import org.matrix.android.sdk.internal.session.room.directory.GetRoomDirectoryVisibilityTask
|
import org.matrix.android.sdk.internal.session.room.directory.GetRoomDirectoryVisibilityTask
|
||||||
import org.matrix.android.sdk.internal.session.room.directory.SetRoomDirectoryVisibilityTask
|
import org.matrix.android.sdk.internal.session.room.directory.SetRoomDirectoryVisibilityTask
|
||||||
@ -28,7 +31,8 @@ import javax.inject.Inject
|
|||||||
internal class DefaultRoomDirectoryService @Inject constructor(
|
internal class DefaultRoomDirectoryService @Inject constructor(
|
||||||
private val getPublicRoomTask: GetPublicRoomTask,
|
private val getPublicRoomTask: GetPublicRoomTask,
|
||||||
private val getRoomDirectoryVisibilityTask: GetRoomDirectoryVisibilityTask,
|
private val getRoomDirectoryVisibilityTask: GetRoomDirectoryVisibilityTask,
|
||||||
private val setRoomDirectoryVisibilityTask: SetRoomDirectoryVisibilityTask
|
private val setRoomDirectoryVisibilityTask: SetRoomDirectoryVisibilityTask,
|
||||||
|
private val roomAliasAvailabilityChecker: RoomAliasAvailabilityChecker
|
||||||
) : RoomDirectoryService {
|
) : RoomDirectoryService {
|
||||||
|
|
||||||
override suspend fun getPublicRooms(server: String?,
|
override suspend fun getPublicRooms(server: String?,
|
||||||
@ -43,4 +47,13 @@ internal class DefaultRoomDirectoryService @Inject constructor(
|
|||||||
override suspend fun setRoomDirectoryVisibility(roomId: String, roomDirectoryVisibility: RoomDirectoryVisibility) {
|
override suspend fun setRoomDirectoryVisibility(roomId: String, roomDirectoryVisibility: RoomDirectoryVisibility) {
|
||||||
setRoomDirectoryVisibilityTask.execute(SetRoomDirectoryVisibilityTask.Params(roomId, roomDirectoryVisibility))
|
setRoomDirectoryVisibilityTask.execute(SetRoomDirectoryVisibilityTask.Params(roomId, roomDirectoryVisibility))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun checkAliasAvailability(aliasLocalPart: String?): AliasAvailabilityResult {
|
||||||
|
return try {
|
||||||
|
roomAliasAvailabilityChecker.check(aliasLocalPart)
|
||||||
|
AliasAvailabilityResult.Available
|
||||||
|
} catch (failure: RoomAliasError) {
|
||||||
|
AliasAvailabilityResult.NotAvailable(failure)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,13 +51,13 @@ internal class RoomAliasAvailabilityChecker @Inject constructor(
|
|||||||
} catch (throwable: Throwable) {
|
} catch (throwable: Throwable) {
|
||||||
if (throwable is Failure.ServerError && throwable.httpCode == 404) {
|
if (throwable is Failure.ServerError && throwable.httpCode == 404) {
|
||||||
// This is a 404, so the alias is available: nominal case
|
// This is a 404, so the alias is available: nominal case
|
||||||
null
|
return
|
||||||
} else {
|
} else {
|
||||||
// Other error, propagate it
|
// Other error, propagate it
|
||||||
throw throwable
|
throw throwable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?.let {
|
.let {
|
||||||
// Alias already exists: error case
|
// Alias already exists: error case
|
||||||
throw RoomAliasError.AliasNotAvailable
|
throw RoomAliasError.AliasNotAvailable
|
||||||
}
|
}
|
||||||
|
@ -66,12 +66,13 @@ internal class DefaultSpaceService @Inject constructor(
|
|||||||
return createRoomTask.executeRetry(params, 3)
|
return createRoomTask.executeRetry(params, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun createSpace(name: String, topic: String?, avatarUri: Uri?, isPublic: Boolean): String {
|
override suspend fun createSpace(name: String, topic: String?, avatarUri: Uri?, isPublic: Boolean, roomAliasLocalPart: String?): String {
|
||||||
return createSpace(CreateSpaceParams().apply {
|
return createSpace(CreateSpaceParams().apply {
|
||||||
this.name = name
|
this.name = name
|
||||||
this.topic = topic
|
this.topic = topic
|
||||||
this.avatarUri = avatarUri
|
this.avatarUri = avatarUri
|
||||||
if (isPublic) {
|
if (isPublic) {
|
||||||
|
this.roomAliasName = roomAliasLocalPart
|
||||||
this.powerLevelContentOverride = (powerLevelContentOverride ?: PowerLevelsContent()).copy(
|
this.powerLevelContentOverride = (powerLevelContentOverride ?: PowerLevelsContent()).copy(
|
||||||
invite = 0
|
invite = 0
|
||||||
)
|
)
|
||||||
|
1
newsfragment/3483.feature
Normal file
1
newsfragment/3483.feature
Normal file
@ -0,0 +1 @@
|
|||||||
|
Add option to set aliases for public spaces
|
@ -17,6 +17,7 @@
|
|||||||
package im.vector.app.features.form
|
package im.vector.app.features.form
|
||||||
|
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
|
import android.view.View
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
@ -40,6 +41,9 @@ abstract class FormEditTextItem : VectorEpoxyModel<FormEditTextItem.Holder>() {
|
|||||||
@EpoxyAttribute
|
@EpoxyAttribute
|
||||||
var value: String? = null
|
var value: String? = null
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
var forceUpdateValue: Boolean = false
|
||||||
|
|
||||||
@EpoxyAttribute
|
@EpoxyAttribute
|
||||||
var errorMessage: String? = null
|
var errorMessage: String? = null
|
||||||
|
|
||||||
@ -64,12 +68,23 @@ abstract class FormEditTextItem : VectorEpoxyModel<FormEditTextItem.Holder>() {
|
|||||||
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
|
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
|
||||||
var editorActionListener: TextView.OnEditorActionListener? = null
|
var editorActionListener: TextView.OnEditorActionListener? = null
|
||||||
|
|
||||||
|
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
|
||||||
|
var onFocusChange: ((Boolean) -> Unit)? = null
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
var prefixText: String? = null
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
var suffixText: String? = null
|
||||||
|
|
||||||
private val onTextChangeListener = object : SimpleTextWatcher() {
|
private val onTextChangeListener = object : SimpleTextWatcher() {
|
||||||
override fun afterTextChanged(s: Editable) {
|
override fun afterTextChanged(s: Editable) {
|
||||||
onTextChange?.invoke(s.toString())
|
onTextChange?.invoke(s.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val onFocusChangedListener = View.OnFocusChangeListener { _, hasFocus -> onFocusChange?.invoke(hasFocus) }
|
||||||
|
|
||||||
override fun bind(holder: Holder) {
|
override fun bind(holder: Holder) {
|
||||||
super.bind(holder)
|
super.bind(holder)
|
||||||
holder.textInputLayout.isEnabled = enabled
|
holder.textInputLayout.isEnabled = enabled
|
||||||
@ -77,7 +92,14 @@ abstract class FormEditTextItem : VectorEpoxyModel<FormEditTextItem.Holder>() {
|
|||||||
holder.textInputLayout.error = errorMessage
|
holder.textInputLayout.error = errorMessage
|
||||||
holder.textInputLayout.endIconMode = endIconMode ?: TextInputLayout.END_ICON_NONE
|
holder.textInputLayout.endIconMode = endIconMode ?: TextInputLayout.END_ICON_NONE
|
||||||
|
|
||||||
|
holder.textInputLayout.prefixText = prefixText
|
||||||
|
holder.textInputLayout.suffixText = suffixText
|
||||||
|
|
||||||
|
if (forceUpdateValue) {
|
||||||
|
holder.textInputEditText.setText(value)
|
||||||
|
} else {
|
||||||
holder.setValueOnce(holder.textInputEditText, value)
|
holder.setValueOnce(holder.textInputEditText, value)
|
||||||
|
}
|
||||||
|
|
||||||
holder.textInputEditText.isEnabled = enabled
|
holder.textInputEditText.isEnabled = enabled
|
||||||
inputType?.let { holder.textInputEditText.inputType = it }
|
inputType?.let { holder.textInputEditText.inputType = it }
|
||||||
@ -86,6 +108,7 @@ abstract class FormEditTextItem : VectorEpoxyModel<FormEditTextItem.Holder>() {
|
|||||||
|
|
||||||
holder.textInputEditText.addTextChangedListenerOnce(onTextChangeListener)
|
holder.textInputEditText.addTextChangedListenerOnce(onTextChangeListener)
|
||||||
holder.textInputEditText.setOnEditorActionListener(editorActionListener)
|
holder.textInputEditText.setOnEditorActionListener(editorActionListener)
|
||||||
|
holder.textInputEditText.onFocusChangeListener = onFocusChangedListener
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shouldSaveViewState(): Boolean {
|
override fun shouldSaveViewState(): Boolean {
|
||||||
|
@ -99,11 +99,13 @@ class CreateRoomController @Inject constructor(
|
|||||||
}
|
}
|
||||||
if (viewState.roomVisibilityType is CreateRoomViewState.RoomVisibilityType.Public) {
|
if (viewState.roomVisibilityType is CreateRoomViewState.RoomVisibilityType.Public) {
|
||||||
// Room alias for public room
|
// Room alias for public room
|
||||||
roomAliasEditItem {
|
formEditTextItem {
|
||||||
id("alias")
|
id("alias")
|
||||||
enabled(enableFormElement)
|
enabled(enableFormElement)
|
||||||
value(viewState.roomVisibilityType.aliasLocalPart)
|
value(viewState.roomVisibilityType.aliasLocalPart)
|
||||||
homeServer(":" + viewState.homeServerName)
|
suffixText(":" + viewState.homeServerName)
|
||||||
|
prefixText("#")
|
||||||
|
hint(host.stringProvider.getString(R.string.room_alias_address_hint))
|
||||||
errorMessage(
|
errorMessage(
|
||||||
host.roomAliasErrorFormatter.format(
|
host.roomAliasErrorFormatter.format(
|
||||||
(((viewState.asyncCreateRoomRequest as? Fail)?.error) as? CreateRoomFailure.AliasError)?.aliasError)
|
(((viewState.asyncCreateRoomRequest as? Fail)?.error) as? CreateRoomFailure.AliasError)?.aliasError)
|
||||||
|
@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 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.roomdirectory.createroom
|
|
||||||
|
|
||||||
import android.text.Editable
|
|
||||||
import android.widget.TextView
|
|
||||||
import com.airbnb.epoxy.EpoxyAttribute
|
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
|
||||||
import com.google.android.material.textfield.TextInputEditText
|
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
|
||||||
import im.vector.app.R
|
|
||||||
import im.vector.app.core.epoxy.TextListener
|
|
||||||
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
|
||||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
|
||||||
import im.vector.app.core.epoxy.addTextChangedListenerOnce
|
|
||||||
import im.vector.app.core.epoxy.setValueOnce
|
|
||||||
import im.vector.app.core.platform.SimpleTextWatcher
|
|
||||||
|
|
||||||
@EpoxyModelClass(layout = R.layout.item_room_alias_text_input)
|
|
||||||
abstract class RoomAliasEditItem : VectorEpoxyModel<RoomAliasEditItem.Holder>() {
|
|
||||||
|
|
||||||
@EpoxyAttribute
|
|
||||||
var value: String? = null
|
|
||||||
|
|
||||||
@EpoxyAttribute
|
|
||||||
var errorMessage: String? = null
|
|
||||||
|
|
||||||
@EpoxyAttribute
|
|
||||||
var homeServer: String? = null
|
|
||||||
|
|
||||||
@EpoxyAttribute
|
|
||||||
var enabled: Boolean = true
|
|
||||||
|
|
||||||
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
|
|
||||||
var onTextChange: TextListener? = null
|
|
||||||
|
|
||||||
private val onTextChangeListener = object : SimpleTextWatcher() {
|
|
||||||
override fun afterTextChanged(s: Editable) {
|
|
||||||
onTextChange?.invoke(s.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun bind(holder: Holder) {
|
|
||||||
super.bind(holder)
|
|
||||||
holder.textInputLayout.isEnabled = enabled
|
|
||||||
holder.textInputLayout.error = errorMessage
|
|
||||||
|
|
||||||
holder.setValueOnce(holder.textInputEditText, value)
|
|
||||||
holder.textInputEditText.isEnabled = enabled
|
|
||||||
holder.textInputEditText.addTextChangedListenerOnce(onTextChangeListener)
|
|
||||||
holder.homeServerText.text = homeServer
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun shouldSaveViewState(): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unbind(holder: Holder) {
|
|
||||||
super.unbind(holder)
|
|
||||||
holder.textInputEditText.removeTextChangedListener(onTextChangeListener)
|
|
||||||
}
|
|
||||||
|
|
||||||
class Holder : VectorEpoxyHolder() {
|
|
||||||
val textInputLayout by bind<TextInputLayout>(R.id.itemRoomAliasTextInputLayout)
|
|
||||||
val textInputEditText by bind<TextInputEditText>(R.id.itemRoomAliasTextInputEditText)
|
|
||||||
val homeServerText by bind<TextView>(R.id.itemRoomAliasHomeServer)
|
|
||||||
}
|
|
||||||
}
|
|
@ -36,9 +36,9 @@ import im.vector.app.features.discovery.settingsInfoItem
|
|||||||
import im.vector.app.features.form.formEditTextItem
|
import im.vector.app.features.form.formEditTextItem
|
||||||
import im.vector.app.features.form.formSwitchItem
|
import im.vector.app.features.form.formSwitchItem
|
||||||
import im.vector.app.features.roomdirectory.createroom.RoomAliasErrorFormatter
|
import im.vector.app.features.roomdirectory.createroom.RoomAliasErrorFormatter
|
||||||
import im.vector.app.features.roomdirectory.createroom.roomAliasEditItem
|
|
||||||
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError
|
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError
|
||||||
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.RoomType
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class RoomAliasController @Inject constructor(
|
class RoomAliasController @Inject constructor(
|
||||||
@ -71,7 +71,9 @@ class RoomAliasController @Inject constructor(
|
|||||||
// Published alias
|
// Published alias
|
||||||
buildPublishInfo(data)
|
buildPublishInfo(data)
|
||||||
// Room directory visibility
|
// Room directory visibility
|
||||||
|
if (data.roomSummary.invoke()?.roomType != RoomType.SPACE) {
|
||||||
buildRoomDirectoryVisibility(data)
|
buildRoomDirectoryVisibility(data)
|
||||||
|
}
|
||||||
// Local alias
|
// Local alias
|
||||||
buildLocalInfo(data)
|
buildLocalInfo(data)
|
||||||
}
|
}
|
||||||
@ -243,10 +245,12 @@ class RoomAliasController @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is RoomAliasViewState.AddAliasState.Editing -> {
|
is RoomAliasViewState.AddAliasState.Editing -> {
|
||||||
roomAliasEditItem {
|
formEditTextItem {
|
||||||
id("newLocalAlias")
|
id("newLocalAlias")
|
||||||
value(data.newLocalAliasState.value)
|
value(data.newLocalAliasState.value)
|
||||||
homeServer(":" + data.homeServerName)
|
suffixText(":" + data.homeServerName)
|
||||||
|
prefixText("#")
|
||||||
|
hint(host.stringProvider.getString(R.string.room_alias_address_hint))
|
||||||
errorMessage(host.roomAliasErrorFormatter.format((data.newLocalAliasState.asyncRequest as? Fail)?.error as? RoomAliasError))
|
errorMessage(host.roomAliasErrorFormatter.format((data.newLocalAliasState.asyncRequest as? Fail)?.error as? RoomAliasError))
|
||||||
onTextChange { value ->
|
onTextChange { value ->
|
||||||
host.callback?.setNewLocalAliasLocalPart(value)
|
host.callback?.setNewLocalAliasLocalPart(value)
|
||||||
|
@ -113,6 +113,9 @@ class SpaceCreationActivity : SimpleFragmentActivity(), CreateSpaceViewModel.Fac
|
|||||||
CreateSpaceEvents.HideModalLoading -> {
|
CreateSpaceEvents.HideModalLoading -> {
|
||||||
hideWaitingView()
|
hideWaitingView()
|
||||||
}
|
}
|
||||||
|
is CreateSpaceEvents.ShowModalLoading -> {
|
||||||
|
showWaitingView(it.message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ sealed class CreateSpaceAction : VectorViewModelAction {
|
|||||||
data class SetRoomType(val type: SpaceType) : CreateSpaceAction()
|
data class SetRoomType(val type: SpaceType) : CreateSpaceAction()
|
||||||
data class NameChanged(val name: String) : CreateSpaceAction()
|
data class NameChanged(val name: String) : CreateSpaceAction()
|
||||||
data class TopicChanged(val topic: String) : CreateSpaceAction()
|
data class TopicChanged(val topic: String) : CreateSpaceAction()
|
||||||
|
data class SpaceAliasChanged(val aliasLocalPart: String) : CreateSpaceAction()
|
||||||
data class SetAvatar(val uri: Uri?) : CreateSpaceAction()
|
data class SetAvatar(val uri: Uri?) : CreateSpaceAction()
|
||||||
object OnBackPressed : CreateSpaceAction()
|
object OnBackPressed : CreateSpaceAction()
|
||||||
object NextFromDetails : CreateSpaceAction()
|
object NextFromDetails : CreateSpaceAction()
|
||||||
|
@ -84,6 +84,10 @@ class CreateSpaceDetailsFragment @Inject constructor(
|
|||||||
sharedViewModel.handle(CreateSpaceAction.TopicChanged(newTopic))
|
sharedViewModel.handle(CreateSpaceAction.TopicChanged(newTopic))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun setAliasLocalPart(aliasLocalPart: String) {
|
||||||
|
sharedViewModel.handle(CreateSpaceAction.SpaceAliasChanged(aliasLocalPart))
|
||||||
|
}
|
||||||
|
|
||||||
override fun onBackPressed(toolbarButton: Boolean): Boolean {
|
override fun onBackPressed(toolbarButton: Boolean): Boolean {
|
||||||
sharedViewModel.handle(CreateSpaceAction.OnBackPressed)
|
sharedViewModel.handle(CreateSpaceAction.OnBackPressed)
|
||||||
return true
|
return true
|
||||||
|
@ -27,4 +27,5 @@ sealed class CreateSpaceEvents : VectorViewEvents {
|
|||||||
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()
|
||||||
data class ShowModalError(val errorMessage: String) : CreateSpaceEvents()
|
data class ShowModalError(val errorMessage: String) : CreateSpaceEvents()
|
||||||
object HideModalLoading : CreateSpaceEvents()
|
object HideModalLoading : CreateSpaceEvents()
|
||||||
|
data class ShowModalLoading(val message: String?) : CreateSpaceEvents()
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,10 @@ data class CreateSpaceState(
|
|||||||
val step: Step = Step.ChooseType,
|
val step: Step = Step.ChooseType,
|
||||||
val spaceType: SpaceType? = null,
|
val spaceType: SpaceType? = null,
|
||||||
val spaceTopology: SpaceTopology? = null,
|
val spaceTopology: SpaceTopology? = null,
|
||||||
|
val homeServerName: String? = null,
|
||||||
|
val aliasLocalPart: String? = null,
|
||||||
|
val aliasManuallyModified: Boolean = false,
|
||||||
|
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 creationResult: Async<String> = Uninitialized
|
||||||
|
@ -35,14 +35,27 @@ 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
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import org.matrix.android.sdk.api.MatrixPatterns
|
||||||
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
import org.matrix.android.sdk.api.session.room.AliasAvailabilityResult
|
||||||
|
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
|
||||||
|
|
||||||
class CreateSpaceViewModel @AssistedInject constructor(
|
class CreateSpaceViewModel @AssistedInject constructor(
|
||||||
@Assisted initialState: CreateSpaceState,
|
@Assisted initialState: CreateSpaceState,
|
||||||
|
private val session: Session,
|
||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
private val createSpaceViewModelTask: CreateSpaceViewModelTask,
|
private val createSpaceViewModelTask: CreateSpaceViewModelTask,
|
||||||
private val errorFormatter: ErrorFormatter
|
private val errorFormatter: ErrorFormatter
|
||||||
) : VectorViewModel<CreateSpaceState, CreateSpaceAction, CreateSpaceEvents>(initialState) {
|
) : VectorViewModel<CreateSpaceState, CreateSpaceAction, CreateSpaceEvents>(initialState) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
setState {
|
||||||
|
copy(
|
||||||
|
homeServerName = session.myUserId.substringAfter(":")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@AssistedFactory
|
@AssistedFactory
|
||||||
interface Factory {
|
interface Factory {
|
||||||
fun create(initialState: CreateSpaceState): CreateSpaceViewModel
|
fun create(initialState: CreateSpaceState): CreateSpaceViewModel
|
||||||
@ -81,10 +94,22 @@ class CreateSpaceViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
is CreateSpaceAction.NameChanged -> {
|
is CreateSpaceAction.NameChanged -> {
|
||||||
setState {
|
setState {
|
||||||
|
if (aliasManuallyModified) {
|
||||||
copy(
|
copy(
|
||||||
nameInlineError = null,
|
nameInlineError = null,
|
||||||
name = action.name
|
name = action.name,
|
||||||
|
aliasVerificationTask = Uninitialized
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
val tentativeAlias =
|
||||||
|
MatrixPatterns.candidateAliasFromRoomName(action.name)
|
||||||
|
copy(
|
||||||
|
nameInlineError = null,
|
||||||
|
name = action.name,
|
||||||
|
aliasLocalPart = tentativeAlias,
|
||||||
|
aliasVerificationTask = Uninitialized
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is CreateSpaceAction.TopicChanged -> {
|
is CreateSpaceAction.TopicChanged -> {
|
||||||
@ -94,6 +119,17 @@ class CreateSpaceViewModel @AssistedInject constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
is CreateSpaceAction.SpaceAliasChanged -> {
|
||||||
|
// This called only when the alias is change manually
|
||||||
|
// not when programmatically changed via a change on name
|
||||||
|
setState {
|
||||||
|
copy(
|
||||||
|
aliasManuallyModified = true,
|
||||||
|
aliasLocalPart = action.aliasLocalPart,
|
||||||
|
aliasVerificationTask = Uninitialized
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
CreateSpaceAction.OnBackPressed -> {
|
CreateSpaceAction.OnBackPressed -> {
|
||||||
handleBackNavigation()
|
handleBackNavigation()
|
||||||
}
|
}
|
||||||
@ -204,13 +240,39 @@ class CreateSpaceViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
_viewEvents.post(CreateSpaceEvents.NavigateToChoosePrivateType)
|
_viewEvents.post(CreateSpaceEvents.NavigateToChoosePrivateType)
|
||||||
} else {
|
} else {
|
||||||
|
// it'a public space, let's check alias
|
||||||
|
val aliasLocalPart = state.aliasLocalPart
|
||||||
|
_viewEvents.post(CreateSpaceEvents.ShowModalLoading(null))
|
||||||
|
setState {
|
||||||
|
copy(aliasVerificationTask = Loading())
|
||||||
|
}
|
||||||
|
viewModelScope.launch {
|
||||||
|
try {
|
||||||
|
when (val result = session.checkAliasAvailability(aliasLocalPart)) {
|
||||||
|
AliasAvailabilityResult.Available -> {
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
step = CreateSpaceState.Step.AddRooms
|
step = CreateSpaceState.Step.AddRooms
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
_viewEvents.post(CreateSpaceEvents.HideModalLoading)
|
||||||
_viewEvents.post(CreateSpaceEvents.NavigateToAddRooms)
|
_viewEvents.post(CreateSpaceEvents.NavigateToAddRooms)
|
||||||
}
|
}
|
||||||
|
is AliasAvailabilityResult.NotAvailable -> {
|
||||||
|
setState {
|
||||||
|
copy(aliasVerificationTask = Fail(result.roomAliasError))
|
||||||
|
}
|
||||||
|
_viewEvents.post(CreateSpaceEvents.HideModalLoading)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (failure: Throwable) {
|
||||||
|
setState {
|
||||||
|
copy(aliasVerificationTask = Fail(failure))
|
||||||
|
}
|
||||||
|
_viewEvents.post(CreateSpaceEvents.HideModalLoading)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,6 +283,9 @@ class CreateSpaceViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
|
val alias = if (state.spaceType == SpaceType.Public) {
|
||||||
|
state.aliasLocalPart
|
||||||
|
} else null
|
||||||
val result = createSpaceViewModelTask.execute(
|
val result = createSpaceViewModelTask.execute(
|
||||||
CreateSpaceTaskParams(
|
CreateSpaceTaskParams(
|
||||||
spaceName = spaceName,
|
spaceName = spaceName,
|
||||||
@ -230,7 +295,8 @@ 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 } ?: emptyList(),
|
||||||
|
spaceAlias = alias
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
when (result) {
|
when (result) {
|
||||||
@ -260,12 +326,24 @@ class CreateSpaceViewModel @AssistedInject constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
is CreateSpaceTaskResult.FailedToCreateSpace -> {
|
is CreateSpaceTaskResult.FailedToCreateSpace -> {
|
||||||
|
if (result.failure is CreateRoomFailure.AliasError) {
|
||||||
|
setState {
|
||||||
|
copy(
|
||||||
|
step = CreateSpaceState.Step.SetDetails,
|
||||||
|
aliasVerificationTask = Fail(result.failure.aliasError),
|
||||||
|
creationResult = Uninitialized
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_viewEvents.post(CreateSpaceEvents.HideModalLoading)
|
||||||
|
_viewEvents.post(CreateSpaceEvents.NavigateToDetails)
|
||||||
|
} else {
|
||||||
setState {
|
setState {
|
||||||
copy(creationResult = Fail(result.failure))
|
copy(creationResult = Fail(result.failure))
|
||||||
}
|
}
|
||||||
_viewEvents.post(CreateSpaceEvents.ShowModalError(errorFormatter.toHumanReadable(result.failure)))
|
_viewEvents.post(CreateSpaceEvents.ShowModalError(errorFormatter.toHumanReadable(result.failure)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
setState {
|
setState {
|
||||||
copy(creationResult = Fail(failure))
|
copy(creationResult = Fail(failure))
|
||||||
|
@ -45,6 +45,7 @@ data class CreateSpaceTaskParams(
|
|||||||
val spaceName: String,
|
val spaceName: String,
|
||||||
val spaceTopic: String?,
|
val spaceTopic: String?,
|
||||||
val spaceAvatar: Uri? = null,
|
val spaceAvatar: Uri? = null,
|
||||||
|
val spaceAlias: String? = null,
|
||||||
val isPublic: Boolean,
|
val isPublic: Boolean,
|
||||||
val defaultRooms: List<String> = emptyList()
|
val defaultRooms: List<String> = emptyList()
|
||||||
)
|
)
|
||||||
@ -57,7 +58,13 @@ 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(params.spaceName, params.spaceTopic, params.spaceAvatar, params.isPublic)
|
session.spaceService().createSpace(
|
||||||
|
params.spaceName,
|
||||||
|
params.spaceTopic,
|
||||||
|
params.spaceAvatar,
|
||||||
|
params.isPublic,
|
||||||
|
params.spaceAlias
|
||||||
|
)
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
return CreateSpaceTaskResult.FailedToCreateSpace(failure)
|
return CreateSpaceTaskResult.FailedToCreateSpace(failure)
|
||||||
}
|
}
|
||||||
|
@ -17,24 +17,39 @@
|
|||||||
package im.vector.app.features.spaces.create
|
package im.vector.app.features.spaces.create
|
||||||
|
|
||||||
import com.airbnb.epoxy.TypedEpoxyController
|
import com.airbnb.epoxy.TypedEpoxyController
|
||||||
|
import com.airbnb.mvrx.Fail
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.epoxy.TextListener
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.core.ui.list.genericFooterItem
|
import im.vector.app.core.ui.list.genericFooterItem
|
||||||
import im.vector.app.features.form.formEditTextItem
|
import im.vector.app.features.form.formEditTextItem
|
||||||
import im.vector.app.features.form.formEditableSquareAvatarItem
|
import im.vector.app.features.form.formEditableSquareAvatarItem
|
||||||
import im.vector.app.features.form.formMultiLineEditTextItem
|
import im.vector.app.features.form.formMultiLineEditTextItem
|
||||||
import im.vector.app.features.home.AvatarRenderer
|
import im.vector.app.features.home.AvatarRenderer
|
||||||
|
import im.vector.app.features.roomdirectory.createroom.RoomAliasErrorFormatter
|
||||||
|
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError
|
||||||
import org.matrix.android.sdk.api.util.MatrixItem
|
import org.matrix.android.sdk.api.util.MatrixItem
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class SpaceDetailEpoxyController @Inject constructor(
|
class SpaceDetailEpoxyController @Inject constructor(
|
||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
private val avatarRenderer: AvatarRenderer
|
private val avatarRenderer: AvatarRenderer,
|
||||||
|
private val roomAliasErrorFormatter: RoomAliasErrorFormatter
|
||||||
) : TypedEpoxyController<CreateSpaceState>() {
|
) : TypedEpoxyController<CreateSpaceState>() {
|
||||||
|
|
||||||
var listener: Listener? = null
|
var listener: Listener? = null
|
||||||
|
|
||||||
// var shouldForceFocusOnce = true
|
/**
|
||||||
|
* Alias text can be automatically set when changing the room name,
|
||||||
|
* We have to be able to make a difference between a programming change versus
|
||||||
|
* a user change.
|
||||||
|
*/
|
||||||
|
var aliasTextIsFocused = false
|
||||||
|
private val aliasTextWatcher: TextListener = {
|
||||||
|
if (aliasTextIsFocused) {
|
||||||
|
listener?.setAliasLocalPart(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun buildModels(data: CreateSpaceState?) {
|
override fun buildModels(data: CreateSpaceState?) {
|
||||||
val host = this
|
val host = this
|
||||||
@ -65,20 +80,31 @@ class SpaceDetailEpoxyController @Inject constructor(
|
|||||||
value(data?.name)
|
value(data?.name)
|
||||||
hint(host.stringProvider.getString(R.string.create_room_name_hint))
|
hint(host.stringProvider.getString(R.string.create_room_name_hint))
|
||||||
errorMessage(data?.nameInlineError)
|
errorMessage(data?.nameInlineError)
|
||||||
// onBind { _, view, _ ->
|
|
||||||
// if (shouldForceFocusOnce && data?.name.isNullOrBlank()) {
|
|
||||||
// shouldForceFocusOnce = false
|
|
||||||
// // sad face :(
|
|
||||||
// view.textInputEditText.post {
|
|
||||||
// view.textInputEditText.showKeyboard(true)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
onTextChange { text ->
|
onTextChange { text ->
|
||||||
host.listener?.onNameChange(text)
|
host.listener?.onNameChange(text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data?.spaceType == SpaceType.Public) {
|
||||||
|
formEditTextItem {
|
||||||
|
id("alias")
|
||||||
|
enabled(true)
|
||||||
|
forceUpdateValue(!data.aliasManuallyModified)
|
||||||
|
value(data.aliasLocalPart)
|
||||||
|
hint(host.stringProvider.getString(R.string.create_space_alias_hint))
|
||||||
|
suffixText(":" + data.homeServerName)
|
||||||
|
prefixText("#")
|
||||||
|
onFocusChange { hasFocus ->
|
||||||
|
host.aliasTextIsFocused = hasFocus
|
||||||
|
}
|
||||||
|
errorMessage(
|
||||||
|
host.roomAliasErrorFormatter.format(
|
||||||
|
(((data.aliasVerificationTask as? Fail)?.error) as? RoomAliasError))
|
||||||
|
)
|
||||||
|
onTextChange(host.aliasTextWatcher)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
formMultiLineEditTextItem {
|
formMultiLineEditTextItem {
|
||||||
id("topic")
|
id("topic")
|
||||||
enabled(true)
|
enabled(true)
|
||||||
@ -96,5 +122,6 @@ class SpaceDetailEpoxyController @Inject constructor(
|
|||||||
fun onAvatarChange()
|
fun onAvatarChange()
|
||||||
fun onNameChange(newName: String)
|
fun onNameChange(newName: String)
|
||||||
fun onTopicChange(newTopic: String)
|
fun onTopicChange(newTopic: String)
|
||||||
|
fun setAliasLocalPart(aliasLocalPart: String)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ import im.vector.app.features.roomdirectory.RoomDirectorySharedActionViewModel
|
|||||||
import im.vector.app.features.roomdirectory.createroom.CreateRoomArgs
|
import im.vector.app.features.roomdirectory.createroom.CreateRoomArgs
|
||||||
import im.vector.app.features.roomdirectory.createroom.CreateRoomFragment
|
import im.vector.app.features.roomdirectory.createroom.CreateRoomFragment
|
||||||
import im.vector.app.features.roomprofile.RoomProfileArgs
|
import im.vector.app.features.roomprofile.RoomProfileArgs
|
||||||
|
import im.vector.app.features.roomprofile.alias.RoomAliasFragment
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -155,6 +156,15 @@ class SpaceManageActivity : VectorBaseActivity<ActivitySimpleLoadingBinding>(),
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SpaceManagedSharedViewEvents.NavigateToAliasSettings -> {
|
||||||
|
args?.spaceId?.let { spaceId ->
|
||||||
|
addFragmentToBackstack(
|
||||||
|
R.id.simpleFragmentContainer,
|
||||||
|
RoomAliasFragment::class.java,
|
||||||
|
RoomProfileArgs(spaceId)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,7 @@ class SpaceManageSharedViewModel @AssistedInject constructor(
|
|||||||
SpaceManagedSharedAction.ShowLoading -> _viewEvents.post(SpaceManagedSharedViewEvents.ShowLoading)
|
SpaceManagedSharedAction.ShowLoading -> _viewEvents.post(SpaceManagedSharedViewEvents.ShowLoading)
|
||||||
SpaceManagedSharedAction.CreateRoom -> _viewEvents.post(SpaceManagedSharedViewEvents.NavigateToCreateRoom)
|
SpaceManagedSharedAction.CreateRoom -> _viewEvents.post(SpaceManagedSharedViewEvents.NavigateToCreateRoom)
|
||||||
SpaceManagedSharedAction.ManageRooms -> _viewEvents.post(SpaceManagedSharedViewEvents.NavigateToManageRooms)
|
SpaceManagedSharedAction.ManageRooms -> _viewEvents.post(SpaceManagedSharedViewEvents.NavigateToManageRooms)
|
||||||
|
SpaceManagedSharedAction.OpenSpaceAliasesSettings -> _viewEvents.post(SpaceManagedSharedViewEvents.NavigateToAliasSettings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,4 +24,5 @@ sealed class SpaceManagedSharedAction : VectorViewModelAction {
|
|||||||
object HideLoading : SpaceManagedSharedAction()
|
object HideLoading : SpaceManagedSharedAction()
|
||||||
object CreateRoom : SpaceManagedSharedAction()
|
object CreateRoom : SpaceManagedSharedAction()
|
||||||
object ManageRooms : SpaceManagedSharedAction()
|
object ManageRooms : SpaceManagedSharedAction()
|
||||||
|
object OpenSpaceAliasesSettings : SpaceManagedSharedAction()
|
||||||
}
|
}
|
||||||
|
@ -24,4 +24,5 @@ sealed class SpaceManagedSharedViewEvents : VectorViewEvents {
|
|||||||
object HideLoading : SpaceManagedSharedViewEvents()
|
object HideLoading : SpaceManagedSharedViewEvents()
|
||||||
object NavigateToCreateRoom : SpaceManagedSharedViewEvents()
|
object NavigateToCreateRoom : SpaceManagedSharedViewEvents()
|
||||||
object NavigateToManageRooms : SpaceManagedSharedViewEvents()
|
object NavigateToManageRooms : SpaceManagedSharedViewEvents()
|
||||||
|
object NavigateToAliasSettings : SpaceManagedSharedViewEvents()
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,7 @@ class SpaceSettingsController @Inject constructor(
|
|||||||
fun onDevRoomSettings()
|
fun onDevRoomSettings()
|
||||||
fun onManageRooms()
|
fun onManageRooms()
|
||||||
fun setIsPublic(public: Boolean)
|
fun setIsPublic(public: Boolean)
|
||||||
|
fun onRoomAliasesClicked()
|
||||||
}
|
}
|
||||||
|
|
||||||
var callback: Callback? = null
|
var callback: Callback? = null
|
||||||
@ -103,6 +104,7 @@ class SpaceSettingsController @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val isPublic = (data.newRoomJoinRules.newJoinRules ?: data.currentRoomJoinRules) == RoomJoinRules.PUBLIC
|
||||||
if (vectorPreferences.labsUseExperimentalRestricted()) {
|
if (vectorPreferences.labsUseExperimentalRestricted()) {
|
||||||
buildProfileAction(
|
buildProfileAction(
|
||||||
id = "joinRule",
|
id = "joinRule",
|
||||||
@ -113,7 +115,6 @@ class SpaceSettingsController @Inject constructor(
|
|||||||
action = { if (data.actionPermissions.canChangeJoinRule) callback?.onJoinRuleClicked() }
|
action = { if (data.actionPermissions.canChangeJoinRule) callback?.onJoinRuleClicked() }
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
val isPublic = (data.newRoomJoinRules.newJoinRules ?: data.currentRoomJoinRules) == RoomJoinRules.PUBLIC
|
|
||||||
formSwitchItem {
|
formSwitchItem {
|
||||||
id("isPublic")
|
id("isPublic")
|
||||||
enabled(data.actionPermissions.canChangeJoinRule)
|
enabled(data.actionPermissions.canChangeJoinRule)
|
||||||
@ -133,13 +134,24 @@ class SpaceSettingsController @Inject constructor(
|
|||||||
id = "manage_rooms",
|
id = "manage_rooms",
|
||||||
title = stringProvider.getString(R.string.space_settings_manage_rooms),
|
title = stringProvider.getString(R.string.space_settings_manage_rooms),
|
||||||
// subtitle = data.getJoinRuleWording(stringProvider),
|
// subtitle = data.getJoinRuleWording(stringProvider),
|
||||||
divider = vectorPreferences.developerMode(),
|
divider = vectorPreferences.developerMode() || isPublic,
|
||||||
editable = data.actionPermissions.canAddChildren,
|
editable = data.actionPermissions.canAddChildren,
|
||||||
action = {
|
action = {
|
||||||
if (data.actionPermissions.canAddChildren) callback?.onManageRooms()
|
if (data.actionPermissions.canAddChildren) callback?.onManageRooms()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (isPublic) {
|
||||||
|
buildProfileAction(
|
||||||
|
id = "alias",
|
||||||
|
title = stringProvider.getString(R.string.space_settings_alias_title),
|
||||||
|
subtitle = stringProvider.getString(R.string.space_settings_alias_subtitle),
|
||||||
|
divider = vectorPreferences.developerMode(),
|
||||||
|
editable = true,
|
||||||
|
action = { callback?.onRoomAliasesClicked() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (vectorPreferences.developerMode()) {
|
if (vectorPreferences.developerMode()) {
|
||||||
buildProfileAction(
|
buildProfileAction(
|
||||||
id = "dev_tools",
|
id = "dev_tools",
|
||||||
|
@ -233,6 +233,10 @@ class SpaceSettingsFragment @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onRoomAliasesClicked() {
|
||||||
|
sharedViewModel.handle(SpaceManagedSharedAction.OpenSpaceAliasesSettings)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onImageReady(uri: Uri?) {
|
override fun onImageReady(uri: Uri?) {
|
||||||
uri ?: return
|
uri ?: return
|
||||||
viewModel.handle(
|
viewModel.handle(
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="?android:colorBackground"
|
|
||||||
android:minHeight="@dimen/item_form_min_height">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/itemRoomAliasHash"
|
|
||||||
style="@style/Widget.Vector.TextView.HeadlineMedium"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="@dimen/layout_horizontal_margin"
|
|
||||||
android:text="@string/matrix_room_alias_prefix"
|
|
||||||
app:layout_constraintBaseline_toBaselineOf="@+id/itemRoomAliasTextInputLayout"
|
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/itemRoomAliasTextInputLayout"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
app:errorEnabled="true"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/itemRoomAliasHomeServer"
|
|
||||||
app:layout_constraintStart_toEndOf="@+id/itemRoomAliasHash"
|
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
|
||||||
|
|
||||||
<!-- android:imeOptions="actionDone" to fix a crash -->
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:id="@+id/itemRoomAliasTextInputEditText"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="@string/create_room_alias_hint"
|
|
||||||
android:imeOptions="actionDone"
|
|
||||||
android:inputType="text" />
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/itemRoomAliasHomeServer"
|
|
||||||
style="@style/Widget.Vector.TextView.HeadlineMedium"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="@dimen/layout_horizontal_margin"
|
|
||||||
android:maxWidth="200dp"
|
|
||||||
app:layout_constraintBaseline_toBaselineOf="@+id/itemRoomAliasTextInputLayout"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
tools:text=":matrix.org" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1414,6 +1414,8 @@
|
|||||||
<!-- room settings : alias -->
|
<!-- room settings : alias -->
|
||||||
<string name="room_settings_alias_title">Room addresses</string>
|
<string name="room_settings_alias_title">Room addresses</string>
|
||||||
<string name="room_settings_alias_subtitle">See and managed addresses of this room, and its visibility in the room directory.</string>
|
<string name="room_settings_alias_subtitle">See and managed addresses of this room, and its visibility in the room directory.</string>
|
||||||
|
<string name="space_settings_alias_title">Space addresses</string>
|
||||||
|
<string name="space_settings_alias_subtitle">See and managed addresses of this space.</string>
|
||||||
|
|
||||||
<string name="room_alias_title">Room Addresses</string>
|
<string name="room_alias_title">Room Addresses</string>
|
||||||
<string name="room_alias_published_alias_title">Published Addresses</string>
|
<string name="room_alias_published_alias_title">Published Addresses</string>
|
||||||
@ -2585,6 +2587,7 @@
|
|||||||
<string name="create_room_disable_federation_description">You might enable this if the room will only be used for collaborating with internal teams on your homeserver. This cannot be changed later.</string>
|
<string name="create_room_disable_federation_description">You might enable this if the room will only be used for collaborating with internal teams on your homeserver. This cannot be changed later.</string>
|
||||||
|
|
||||||
<string name="create_room_alias_hint">Room address</string>
|
<string name="create_room_alias_hint">Room address</string>
|
||||||
|
<string name="create_space_alias_hint">Space address</string>
|
||||||
<string name="create_room_alias_already_in_use">This address is already in use</string>
|
<string name="create_room_alias_already_in_use">This address is already in use</string>
|
||||||
<string name="create_room_alias_empty">Please provide a room address</string>
|
<string name="create_room_alias_empty">Please provide a room address</string>
|
||||||
<string name="create_room_alias_invalid">Some characters are not allowed</string>
|
<string name="create_room_alias_invalid">Some characters are not allowed</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user