Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,10 @@ object MatrixPatterns {
fun isValidOrderString(order: String?) : Boolean {
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, "")
}
}
}
Original file line number Diff line number Diff line change
@@ -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()
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,6 @@ interface RoomDirectoryService {
* Set the visibility of a room in the directory
*/
suspend fun setRoomDirectoryVisibility(roomId: String, roomDirectoryVisibility: RoomDirectoryVisibility)

suspend fun checkAliasAvailability(aliasLocalPart: String?) : AliasAvailabilityResult
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ interface SpaceService {
/**
* 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@

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.alias.RoomAliasError
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.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.GetRoomDirectoryVisibilityTask
import org.matrix.android.sdk.internal.session.room.directory.SetRoomDirectoryVisibilityTask
Expand All @@ -28,7 +31,8 @@ import javax.inject.Inject
internal class DefaultRoomDirectoryService @Inject constructor(
private val getPublicRoomTask: GetPublicRoomTask,
private val getRoomDirectoryVisibilityTask: GetRoomDirectoryVisibilityTask,
private val setRoomDirectoryVisibilityTask: SetRoomDirectoryVisibilityTask
private val setRoomDirectoryVisibilityTask: SetRoomDirectoryVisibilityTask,
private val roomAliasAvailabilityChecker: RoomAliasAvailabilityChecker
) : RoomDirectoryService {

override suspend fun getPublicRooms(server: String?,
Expand All @@ -43,4 +47,13 @@ internal class DefaultRoomDirectoryService @Inject constructor(
override suspend fun setRoomDirectoryVisibility(roomId: String, roomDirectoryVisibility: 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)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ internal class RoomAliasAvailabilityChecker @Inject constructor(
} catch (throwable: Throwable) {
if (throwable is Failure.ServerError && throwable.httpCode == 404) {
// This is a 404, so the alias is available: nominal case
null
return
} else {
// Other error, propagate it
throw throwable
}
}
?.let {
.let {
// Alias already exists: error case
throw RoomAliasError.AliasNotAvailable
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,13 @@ internal class DefaultSpaceService @Inject constructor(
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 {
this.name = name
this.topic = topic
this.avatarUri = avatarUri
if (isPublic) {
this.roomAliasName = roomAliasLocalPart
this.powerLevelContentOverride = (powerLevelContentOverride ?: PowerLevelsContent()).copy(
invite = 0
)
Expand Down
1 change: 1 addition & 0 deletions newsfragment/3483.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add option to set aliases for public spaces
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package im.vector.app.features.form

import android.text.Editable
import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.TextView
import com.airbnb.epoxy.EpoxyAttribute
Expand All @@ -40,6 +41,9 @@ abstract class FormEditTextItem : VectorEpoxyModel<FormEditTextItem.Holder>() {
@EpoxyAttribute
var value: String? = null

@EpoxyAttribute
var forceUpdateValue: Boolean = false

@EpoxyAttribute
var errorMessage: String? = null

Expand All @@ -64,20 +68,38 @@ abstract class FormEditTextItem : VectorEpoxyModel<FormEditTextItem.Holder>() {
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
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() {
override fun afterTextChanged(s: Editable) {
onTextChange?.invoke(s.toString())
}
}

private val onFocusChangedListener = View.OnFocusChangeListener { _, hasFocus -> onFocusChange?.invoke(hasFocus) }

override fun bind(holder: Holder) {
super.bind(holder)
holder.textInputLayout.isEnabled = enabled
holder.textInputLayout.hint = hint
holder.textInputLayout.error = errorMessage
holder.textInputLayout.endIconMode = endIconMode ?: TextInputLayout.END_ICON_NONE

holder.setValueOnce(holder.textInputEditText, value)
holder.textInputLayout.prefixText = prefixText
holder.textInputLayout.suffixText = suffixText

if (forceUpdateValue) {
holder.textInputEditText.setText(value)
} else {
holder.setValueOnce(holder.textInputEditText, value)
}

holder.textInputEditText.isEnabled = enabled
inputType?.let { holder.textInputEditText.inputType = it }
Expand All @@ -86,6 +108,7 @@ abstract class FormEditTextItem : VectorEpoxyModel<FormEditTextItem.Holder>() {

holder.textInputEditText.addTextChangedListenerOnce(onTextChangeListener)
holder.textInputEditText.setOnEditorActionListener(editorActionListener)
holder.textInputEditText.onFocusChangeListener = onFocusChangedListener
}

override fun shouldSaveViewState(): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,13 @@ class CreateRoomController @Inject constructor(
}
if (viewState.roomVisibilityType is CreateRoomViewState.RoomVisibilityType.Public) {
// Room alias for public room
roomAliasEditItem {
formEditTextItem {
id("alias")
enabled(enableFormElement)
value(viewState.roomVisibilityType.aliasLocalPart)
homeServer(":" + viewState.homeServerName)
suffixText(":" + viewState.homeServerName)
prefixText("#")
hint(host.stringProvider.getString(R.string.room_alias_address_hint))
errorMessage(
host.roomAliasErrorFormatter.format(
(((viewState.asyncCreateRoomRequest as? Fail)?.error) as? CreateRoomFailure.AliasError)?.aliasError)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ import im.vector.app.features.discovery.settingsInfoItem
import im.vector.app.features.form.formEditTextItem
import im.vector.app.features.form.formSwitchItem
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.model.RoomDirectoryVisibility
import org.matrix.android.sdk.api.session.room.model.RoomType
import javax.inject.Inject

class RoomAliasController @Inject constructor(
Expand Down Expand Up @@ -71,7 +71,9 @@ class RoomAliasController @Inject constructor(
// Published alias
buildPublishInfo(data)
// Room directory visibility
buildRoomDirectoryVisibility(data)
if (data.roomSummary.invoke()?.roomType != RoomType.SPACE) {
buildRoomDirectoryVisibility(data)
}
// Local alias
buildLocalInfo(data)
}
Expand Down Expand Up @@ -243,10 +245,12 @@ class RoomAliasController @Inject constructor(
}
}
is RoomAliasViewState.AddAliasState.Editing -> {
roomAliasEditItem {
formEditTextItem {
id("newLocalAlias")
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))
onTextChange { value ->
host.callback?.setNewLocalAliasLocalPart(value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ class SpaceCreationActivity : SimpleFragmentActivity(), CreateSpaceViewModel.Fac
CreateSpaceEvents.HideModalLoading -> {
hideWaitingView()
}
is CreateSpaceEvents.ShowModalLoading -> {
showWaitingView(it.message)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ sealed class CreateSpaceAction : VectorViewModelAction {
data class SetRoomType(val type: SpaceType) : CreateSpaceAction()
data class NameChanged(val name: String) : CreateSpaceAction()
data class TopicChanged(val topic: String) : CreateSpaceAction()
data class SpaceAliasChanged(val aliasLocalPart: String) : CreateSpaceAction()
data class SetAvatar(val uri: Uri?) : CreateSpaceAction()
object OnBackPressed : CreateSpaceAction()
object NextFromDetails : CreateSpaceAction()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ class CreateSpaceDetailsFragment @Inject constructor(
sharedViewModel.handle(CreateSpaceAction.TopicChanged(newTopic))
}

override fun setAliasLocalPart(aliasLocalPart: String) {
sharedViewModel.handle(CreateSpaceAction.SpaceAliasChanged(aliasLocalPart))
}

override fun onBackPressed(toolbarButton: Boolean): Boolean {
sharedViewModel.handle(CreateSpaceAction.OnBackPressed)
return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ sealed class CreateSpaceEvents : VectorViewEvents {
data class FinishSuccess(val spaceId: String, val defaultRoomId: String?, val topology: SpaceTopology?) : CreateSpaceEvents()
data class ShowModalError(val errorMessage: String) : CreateSpaceEvents()
object HideModalLoading : CreateSpaceEvents()
data class ShowModalLoading(val message: String?) : CreateSpaceEvents()
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ data class CreateSpaceState(
val step: Step = Step.ChooseType,
val spaceType: SpaceType? = 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 defaultRooms: Map<Int /** position in form */, String?>? = null,
val creationResult: Async<String> = Uninitialized
Expand Down
Loading