mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-03-18 20:29:10 +03:00
Merge pull request #2439 from vector-im/feature/bma/alias
Add room alias management
This commit is contained in:
commit
93ffb116b7
75 changed files with 2244 additions and 220 deletions
1
.idea/dictionaries/bmarty.xml
generated
1
.idea/dictionaries/bmarty.xml
generated
|
@ -31,6 +31,7 @@
|
|||
<w>ssss</w>
|
||||
<w>sygnal</w>
|
||||
<w>threepid</w>
|
||||
<w>unpublish</w>
|
||||
<w>unwedging</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
|
|
|
@ -2,7 +2,7 @@ Changes in Element 1.0.12 (2020-XX-XX)
|
|||
===================================================
|
||||
|
||||
Features ✨:
|
||||
-
|
||||
- Add room aliases management, and room directory visibility management in a dedicated screen (#1579, #2428)
|
||||
|
||||
Improvements 🙌:
|
||||
- Add Setting Item to Change PIN (#2462)
|
||||
|
|
|
@ -127,14 +127,6 @@ class RxRoom(private val room: Room) {
|
|||
room.updateName(name, it)
|
||||
}
|
||||
|
||||
fun addRoomAlias(alias: String): Completable = completableBuilder<Unit> {
|
||||
room.addRoomAlias(alias, it)
|
||||
}
|
||||
|
||||
fun updateCanonicalAlias(alias: String): Completable = completableBuilder<Unit> {
|
||||
room.updateCanonicalAlias(alias, it)
|
||||
}
|
||||
|
||||
fun updateHistoryReadability(readability: RoomHistoryVisibility): Completable = completableBuilder<Unit> {
|
||||
room.updateHistoryReadability(readability, it)
|
||||
}
|
||||
|
|
|
@ -49,6 +49,12 @@ object EventType {
|
|||
const val STATE_ROOM_JOIN_RULES = "m.room.join_rules"
|
||||
const val STATE_ROOM_GUEST_ACCESS = "m.room.guest_access"
|
||||
const val STATE_ROOM_POWER_LEVELS = "m.room.power_levels"
|
||||
|
||||
/**
|
||||
* Note that this Event has been deprecated, see
|
||||
* - https://matrix.org/docs/spec/client_server/r0.6.1#historical-events
|
||||
* - https://github.com/matrix-org/matrix-doc/pull/2432
|
||||
*/
|
||||
const val STATE_ROOM_ALIASES = "m.room.aliases"
|
||||
const val STATE_ROOM_TOMBSTONE = "m.room.tombstone"
|
||||
const val STATE_ROOM_CANONICAL_ALIAS = "m.room.canonical_alias"
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.matrix.android.sdk.api.session.room
|
|||
|
||||
import androidx.lifecycle.LiveData
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.session.room.alias.AliasService
|
||||
import org.matrix.android.sdk.api.session.room.call.RoomCallService
|
||||
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
|
||||
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
||||
|
@ -46,6 +47,7 @@ interface Room :
|
|||
DraftService,
|
||||
ReadService,
|
||||
TypingService,
|
||||
AliasService,
|
||||
TagsService,
|
||||
MembershipService,
|
||||
StateService,
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.matrix.android.sdk.api.session.room
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
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.api.session.room.model.thirdparty.ThirdPartyProtocol
|
||||
|
@ -39,4 +40,14 @@ interface RoomDirectoryService {
|
|||
* Includes both the available protocols and all fields required for queries against each protocol.
|
||||
*/
|
||||
fun getThirdPartyProtocol(callback: MatrixCallback<Map<String, ThirdPartyProtocol>>): Cancelable
|
||||
|
||||
/**
|
||||
* Get the visibility of a room in the directory
|
||||
*/
|
||||
suspend fun getRoomDirectoryVisibility(roomId: String): RoomDirectoryVisibility
|
||||
|
||||
/**
|
||||
* Set the visibility of a room in the directory
|
||||
*/
|
||||
suspend fun setRoomDirectoryVisibility(roomId: String, roomDirectoryVisibility: RoomDirectoryVisibility)
|
||||
}
|
||||
|
|
|
@ -122,6 +122,11 @@ interface RoomService {
|
|||
searchOnServer: Boolean,
|
||||
callback: MatrixCallback<Optional<String>>): Cancelable
|
||||
|
||||
/**
|
||||
* Delete a room alias
|
||||
*/
|
||||
suspend fun deleteRoomAlias(roomAlias: String)
|
||||
|
||||
/**
|
||||
* Return a live data of all local changes membership that happened since the session has been opened.
|
||||
* It allows you to track this in your client to known what is currently being processed by the SDK.
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2020 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.alias
|
||||
|
||||
interface AliasService {
|
||||
/**
|
||||
* Get list of local alias of the room
|
||||
* @return the list of the aliases (full aliases, not only the local part)
|
||||
*/
|
||||
suspend fun getRoomAliases(): List<String>
|
||||
|
||||
/**
|
||||
* Add local alias to the room
|
||||
* @param aliasLocalPart the local part of the alias.
|
||||
* Ex: for the alias "#my_alias:example.org", the local part is "my_alias"
|
||||
*/
|
||||
suspend fun addAlias(aliasLocalPart: String)
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright 2020 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.alias
|
||||
|
||||
sealed class RoomAliasError : Throwable() {
|
||||
object AliasEmpty : RoomAliasError()
|
||||
object AliasNotAvailable : RoomAliasError()
|
||||
object AliasInvalid : RoomAliasError()
|
||||
}
|
|
@ -18,13 +18,10 @@ package org.matrix.android.sdk.api.session.room.failure
|
|||
|
||||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import org.matrix.android.sdk.api.failure.MatrixError
|
||||
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError
|
||||
|
||||
sealed class CreateRoomFailure : Failure.FeatureFailure() {
|
||||
object CreatedWithTimeout : CreateRoomFailure()
|
||||
data class CreatedWithFederationFailure(val matrixError: MatrixError) : CreateRoomFailure()
|
||||
sealed class RoomAliasError : CreateRoomFailure() {
|
||||
object AliasEmpty : RoomAliasError()
|
||||
object AliasNotAvailable : RoomAliasError()
|
||||
object AliasInvalid : RoomAliasError()
|
||||
}
|
||||
data class AliasError(val aliasError: RoomAliasError) : CreateRoomFailure()
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@ import com.squareup.moshi.JsonClass
|
|||
|
||||
/**
|
||||
* Class representing the EventType.STATE_ROOM_ALIASES state event content
|
||||
* Note that this Event has been deprecated, see
|
||||
* - https://matrix.org/docs/spec/client_server/r0.6.1#historical-events
|
||||
* - https://github.com/matrix-org/matrix-doc/pull/2432
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class RoomAliasesContent(
|
||||
|
|
|
@ -24,5 +24,14 @@ import com.squareup.moshi.JsonClass
|
|||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class RoomCanonicalAliasContent(
|
||||
@Json(name = "alias") val canonicalAlias: String? = null
|
||||
/**
|
||||
* The canonical alias for the room. If not present, null, or empty the room should be considered to have no canonical alias.
|
||||
*/
|
||||
@Json(name = "alias") val canonicalAlias: String? = null,
|
||||
|
||||
/**
|
||||
* Alternative aliases the room advertises.
|
||||
* This list can have aliases despite the alias field being null, empty, or otherwise not present.
|
||||
*/
|
||||
@Json(name = "alt_aliases") val alternativeAliases: List<String>? = null
|
||||
)
|
||||
|
|
|
@ -38,15 +38,12 @@ interface StateService {
|
|||
*/
|
||||
fun updateName(name: String, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
/**
|
||||
* Add new alias to the room.
|
||||
*/
|
||||
fun addRoomAlias(roomAlias: String, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
/**
|
||||
* Update the canonical alias of the room
|
||||
* @param alias the canonical alias, or null to reset the canonical alias of this room
|
||||
* @param altAliases the alternative aliases for this room. It should include the canonical alias if any.
|
||||
*/
|
||||
fun updateCanonicalAlias(alias: String, callback: MatrixCallback<Unit>): Cancelable
|
||||
fun updateCanonicalAlias(alias: String?, altAliases: List<String>, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
/**
|
||||
* Update the history readability of the room
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright 2020 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.internal.session.directory
|
||||
|
||||
import org.matrix.android.sdk.internal.network.NetworkConstants
|
||||
import org.matrix.android.sdk.internal.session.room.alias.AddRoomAliasBody
|
||||
import org.matrix.android.sdk.internal.session.room.alias.RoomAliasDescription
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.DELETE
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.PUT
|
||||
import retrofit2.http.Path
|
||||
|
||||
internal interface DirectoryAPI {
|
||||
/**
|
||||
* Get the room ID associated to the room alias.
|
||||
*
|
||||
* @param roomAlias the room alias.
|
||||
*/
|
||||
@GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/room/{roomAlias}")
|
||||
fun getRoomIdByAlias(@Path("roomAlias") roomAlias: String): Call<RoomAliasDescription>
|
||||
|
||||
/**
|
||||
* Get the room directory visibility.
|
||||
*
|
||||
* @param roomId the room id.
|
||||
*/
|
||||
@GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/list/room/{roomId}")
|
||||
fun getRoomDirectoryVisibility(@Path("roomId") roomId: String): Call<RoomDirectoryVisibilityJson>
|
||||
|
||||
/**
|
||||
* Set the room directory visibility.
|
||||
*
|
||||
* @param roomId the room id.
|
||||
* @param body the body containing the new directory visibility
|
||||
*/
|
||||
@PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/list/room/{roomId}")
|
||||
fun setRoomDirectoryVisibility(@Path("roomId") roomId: String,
|
||||
@Body body: RoomDirectoryVisibilityJson): Call<Unit>
|
||||
|
||||
/**
|
||||
* Add alias to the room.
|
||||
* @param roomAlias the room alias.
|
||||
*/
|
||||
@PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/room/{roomAlias}")
|
||||
fun addRoomAlias(@Path("roomAlias") roomAlias: String,
|
||||
@Body body: AddRoomAliasBody): Call<Unit>
|
||||
|
||||
/**
|
||||
* Delete a room alias
|
||||
* @param roomAlias the room alias.
|
||||
*/
|
||||
@DELETE(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/room/{roomAlias}")
|
||||
fun deleteRoomAlias(@Path("roomAlias") roomAlias: String): Call<Unit>
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2020 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.internal.session.directory
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class RoomDirectoryVisibilityJson(
|
||||
/**
|
||||
* The visibility of the room in the directory. One of: ["private", "public"]
|
||||
*/
|
||||
@Json(name = "visibility") val visibility: RoomDirectoryVisibility
|
||||
)
|
|
@ -21,6 +21,7 @@ import org.matrix.android.sdk.api.MatrixCallback
|
|||
import org.matrix.android.sdk.api.session.crypto.CryptoService
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.room.Room
|
||||
import org.matrix.android.sdk.api.session.room.alias.AliasService
|
||||
import org.matrix.android.sdk.api.session.room.call.RoomCallService
|
||||
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
|
@ -58,6 +59,7 @@ internal class DefaultRoom @Inject constructor(override val roomId: String,
|
|||
private val roomCallService: RoomCallService,
|
||||
private val readService: ReadService,
|
||||
private val typingService: TypingService,
|
||||
private val aliasService: AliasService,
|
||||
private val tagsService: TagsService,
|
||||
private val cryptoService: CryptoService,
|
||||
private val relationService: RelationService,
|
||||
|
@ -76,6 +78,7 @@ internal class DefaultRoom @Inject constructor(override val roomId: String,
|
|||
RoomCallService by roomCallService,
|
||||
ReadService by readService,
|
||||
TypingService by typingService,
|
||||
AliasService by aliasService,
|
||||
TagsService by tagsService,
|
||||
RelationService by relationService,
|
||||
MembershipService by roomMembersService,
|
||||
|
|
|
@ -18,19 +18,25 @@ package org.matrix.android.sdk.internal.session.room
|
|||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.session.room.RoomDirectoryService
|
||||
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.api.session.room.model.thirdparty.ThirdPartyProtocol
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
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.GetThirdPartyProtocolsTask
|
||||
import org.matrix.android.sdk.internal.session.room.directory.SetRoomDirectoryVisibilityTask
|
||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
||||
import org.matrix.android.sdk.internal.task.configureWith
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class DefaultRoomDirectoryService @Inject constructor(private val getPublicRoomTask: GetPublicRoomTask,
|
||||
private val getThirdPartyProtocolsTask: GetThirdPartyProtocolsTask,
|
||||
private val taskExecutor: TaskExecutor) : RoomDirectoryService {
|
||||
internal class DefaultRoomDirectoryService @Inject constructor(
|
||||
private val getPublicRoomTask: GetPublicRoomTask,
|
||||
private val getThirdPartyProtocolsTask: GetThirdPartyProtocolsTask,
|
||||
private val getRoomDirectoryVisibilityTask: GetRoomDirectoryVisibilityTask,
|
||||
private val setRoomDirectoryVisibilityTask: SetRoomDirectoryVisibilityTask,
|
||||
private val taskExecutor: TaskExecutor) : RoomDirectoryService {
|
||||
|
||||
override fun getPublicRooms(server: String?,
|
||||
publicRoomsParams: PublicRoomsParams,
|
||||
|
@ -49,4 +55,12 @@ internal class DefaultRoomDirectoryService @Inject constructor(private val getPu
|
|||
}
|
||||
.executeBy(taskExecutor)
|
||||
}
|
||||
|
||||
override suspend fun getRoomDirectoryVisibility(roomId: String): RoomDirectoryVisibility {
|
||||
return getRoomDirectoryVisibilityTask.execute(GetRoomDirectoryVisibilityTask.Params(roomId))
|
||||
}
|
||||
|
||||
override suspend fun setRoomDirectoryVisibility(roomId: String, roomDirectoryVisibility: RoomDirectoryVisibility) {
|
||||
setRoomDirectoryVisibilityTask.execute(SetRoomDirectoryVisibilityTask.Params(roomId, roomDirectoryVisibility))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.matrix.android.sdk.api.util.toOptional
|
|||
import org.matrix.android.sdk.internal.database.mapper.asDomain
|
||||
import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import org.matrix.android.sdk.internal.session.room.alias.DeleteRoomAliasTask
|
||||
import org.matrix.android.sdk.internal.session.room.alias.GetRoomIdByAliasTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.membership.RoomChangeMembershipStateDataSource
|
||||
|
@ -53,6 +54,7 @@ internal class DefaultRoomService @Inject constructor(
|
|||
private val markAllRoomsReadTask: MarkAllRoomsReadTask,
|
||||
private val updateBreadcrumbsTask: UpdateBreadcrumbsTask,
|
||||
private val roomIdByAliasTask: GetRoomIdByAliasTask,
|
||||
private val deleteRoomAliasTask: DeleteRoomAliasTask,
|
||||
private val roomGetter: RoomGetter,
|
||||
private val roomSummaryDataSource: RoomSummaryDataSource,
|
||||
private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource,
|
||||
|
@ -125,6 +127,10 @@ internal class DefaultRoomService @Inject constructor(
|
|||
.executeBy(taskExecutor)
|
||||
}
|
||||
|
||||
override suspend fun deleteRoomAlias(roomAlias: String) {
|
||||
deleteRoomAliasTask.execute(DeleteRoomAliasTask.Params(roomAlias))
|
||||
}
|
||||
|
||||
override fun getChangeMembershipsLive(): LiveData<Map<String, ChangeMembershipState>> {
|
||||
return roomChangeMembershipStateDataSource.getLiveStates()
|
||||
}
|
||||
|
|
|
@ -23,8 +23,7 @@ import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsRe
|
|||
import org.matrix.android.sdk.api.session.room.model.thirdparty.ThirdPartyProtocol
|
||||
import org.matrix.android.sdk.api.util.JsonDict
|
||||
import org.matrix.android.sdk.internal.network.NetworkConstants
|
||||
import org.matrix.android.sdk.internal.session.room.alias.AddRoomAliasBody
|
||||
import org.matrix.android.sdk.internal.session.room.alias.RoomAliasDescription
|
||||
import org.matrix.android.sdk.internal.session.room.alias.GetAliasesResponse
|
||||
import org.matrix.android.sdk.internal.session.room.create.CreateRoomBody
|
||||
import org.matrix.android.sdk.internal.session.room.create.CreateRoomResponse
|
||||
import org.matrix.android.sdk.internal.session.room.create.JoinRoomResponse
|
||||
|
@ -321,20 +320,11 @@ internal interface RoomAPI {
|
|||
@Body body: ReportContentBody): Call<Unit>
|
||||
|
||||
/**
|
||||
* Get the room ID associated to the room alias.
|
||||
*
|
||||
* @param roomAlias the room alias.
|
||||
* Get a list of aliases maintained by the local server for the given room.
|
||||
* Ref: https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-rooms-roomid-aliases
|
||||
*/
|
||||
@GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/room/{roomAlias}")
|
||||
fun getRoomIdByAlias(@Path("roomAlias") roomAlias: String): Call<RoomAliasDescription>
|
||||
|
||||
/**
|
||||
* Add alias to the room.
|
||||
* @param roomAlias the room alias.
|
||||
*/
|
||||
@PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/room/{roomAlias}")
|
||||
fun addRoomAlias(@Path("roomAlias") roomAlias: String,
|
||||
@Body body: AddRoomAliasBody): Call<Unit>
|
||||
@GET(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "org.matrix.msc2432/rooms/{roomId}/aliases")
|
||||
fun getAliases(@Path("roomId") roomId: String): Call<GetAliasesResponse>
|
||||
|
||||
/**
|
||||
* Inform that the user is starting to type or has stopped typing
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.session.room
|
|||
import org.matrix.android.sdk.api.session.crypto.CryptoService
|
||||
import org.matrix.android.sdk.api.session.room.Room
|
||||
import org.matrix.android.sdk.internal.session.SessionScope
|
||||
import org.matrix.android.sdk.internal.session.room.alias.DefaultAliasService
|
||||
import org.matrix.android.sdk.internal.session.room.call.DefaultRoomCallService
|
||||
import org.matrix.android.sdk.internal.session.room.draft.DefaultDraftService
|
||||
import org.matrix.android.sdk.internal.session.room.membership.DefaultMembershipService
|
||||
|
@ -54,6 +55,7 @@ internal class DefaultRoomFactory @Inject constructor(private val cryptoService:
|
|||
private val roomCallServiceFactory: DefaultRoomCallService.Factory,
|
||||
private val readServiceFactory: DefaultReadService.Factory,
|
||||
private val typingServiceFactory: DefaultTypingService.Factory,
|
||||
private val aliasServiceFactory: DefaultAliasService.Factory,
|
||||
private val tagsServiceFactory: DefaultTagsService.Factory,
|
||||
private val relationServiceFactory: DefaultRelationService.Factory,
|
||||
private val membershipServiceFactory: DefaultMembershipService.Factory,
|
||||
|
@ -76,6 +78,7 @@ internal class DefaultRoomFactory @Inject constructor(private val cryptoService:
|
|||
roomCallService = roomCallServiceFactory.create(roomId),
|
||||
readService = readServiceFactory.create(roomId),
|
||||
typingService = typingServiceFactory.create(roomId),
|
||||
aliasService = aliasServiceFactory.create(roomId),
|
||||
tagsService = tagsServiceFactory.create(roomId),
|
||||
cryptoService = cryptoService,
|
||||
relationService = relationServiceFactory.create(roomId),
|
||||
|
|
|
@ -26,16 +26,25 @@ import org.matrix.android.sdk.api.session.room.RoomDirectoryService
|
|||
import org.matrix.android.sdk.api.session.room.RoomService
|
||||
import org.matrix.android.sdk.internal.session.DefaultFileService
|
||||
import org.matrix.android.sdk.internal.session.SessionScope
|
||||
import org.matrix.android.sdk.internal.session.directory.DirectoryAPI
|
||||
import org.matrix.android.sdk.internal.session.room.alias.AddRoomAliasTask
|
||||
import org.matrix.android.sdk.internal.session.room.alias.DefaultAddRoomAliasTask
|
||||
import org.matrix.android.sdk.internal.session.room.alias.DefaultDeleteRoomAliasTask
|
||||
import org.matrix.android.sdk.internal.session.room.alias.DefaultGetRoomIdByAliasTask
|
||||
import org.matrix.android.sdk.internal.session.room.alias.DefaultGetRoomLocalAliasesTask
|
||||
import org.matrix.android.sdk.internal.session.room.alias.DeleteRoomAliasTask
|
||||
import org.matrix.android.sdk.internal.session.room.alias.GetRoomIdByAliasTask
|
||||
import org.matrix.android.sdk.internal.session.room.alias.GetRoomLocalAliasesTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.DefaultCreateRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.directory.DefaultGetPublicRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.directory.DefaultGetRoomDirectoryVisibilityTask
|
||||
import org.matrix.android.sdk.internal.session.room.directory.DefaultGetThirdPartyProtocolsTask
|
||||
import org.matrix.android.sdk.internal.session.room.directory.DefaultSetRoomDirectoryVisibilityTask
|
||||
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.GetThirdPartyProtocolsTask
|
||||
import org.matrix.android.sdk.internal.session.room.directory.SetRoomDirectoryVisibilityTask
|
||||
import org.matrix.android.sdk.internal.session.room.membership.DefaultLoadRoomMembersTask
|
||||
import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask
|
||||
import org.matrix.android.sdk.internal.session.room.membership.admin.DefaultMembershipAdminTask
|
||||
|
@ -90,6 +99,13 @@ internal abstract class RoomModule {
|
|||
return retrofit.create(RoomAPI::class.java)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@JvmStatic
|
||||
@SessionScope
|
||||
fun providesDirectoryAPI(retrofit: Retrofit): DirectoryAPI {
|
||||
return retrofit.create(DirectoryAPI::class.java)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@JvmStatic
|
||||
fun providesParser(): Parser {
|
||||
|
@ -127,6 +143,12 @@ internal abstract class RoomModule {
|
|||
@Binds
|
||||
abstract fun bindGetPublicRoomTask(task: DefaultGetPublicRoomTask): GetPublicRoomTask
|
||||
|
||||
@Binds
|
||||
abstract fun bindGetRoomDirectoryVisibilityTask(task: DefaultGetRoomDirectoryVisibilityTask): GetRoomDirectoryVisibilityTask
|
||||
|
||||
@Binds
|
||||
abstract fun bindSetRoomDirectoryVisibilityTask(task: DefaultSetRoomDirectoryVisibilityTask): SetRoomDirectoryVisibilityTask
|
||||
|
||||
@Binds
|
||||
abstract fun bindGetThirdPartyProtocolsTask(task: DefaultGetThirdPartyProtocolsTask): GetThirdPartyProtocolsTask
|
||||
|
||||
|
@ -181,9 +203,15 @@ internal abstract class RoomModule {
|
|||
@Binds
|
||||
abstract fun bindGetRoomIdByAliasTask(task: DefaultGetRoomIdByAliasTask): GetRoomIdByAliasTask
|
||||
|
||||
@Binds
|
||||
abstract fun bindGetRoomLocalAliasesTask(task: DefaultGetRoomLocalAliasesTask): GetRoomLocalAliasesTask
|
||||
|
||||
@Binds
|
||||
abstract fun bindAddRoomAliasTask(task: DefaultAddRoomAliasTask): AddRoomAliasTask
|
||||
|
||||
@Binds
|
||||
abstract fun bindDeleteRoomAliasTask(task: DefaultDeleteRoomAliasTask): DeleteRoomAliasTask
|
||||
|
||||
@Binds
|
||||
abstract fun bindSendTypingTask(task: DefaultSendTypingTask): SendTypingTask
|
||||
|
||||
|
|
|
@ -16,28 +16,38 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.session.room.alias
|
||||
|
||||
import org.matrix.android.sdk.internal.network.executeRequest
|
||||
import org.matrix.android.sdk.internal.session.room.RoomAPI
|
||||
import org.matrix.android.sdk.internal.task.Task
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.network.executeRequest
|
||||
import org.matrix.android.sdk.internal.session.directory.DirectoryAPI
|
||||
import org.matrix.android.sdk.internal.session.room.alias.RoomAliasAvailabilityChecker.Companion.toFullLocalAlias
|
||||
import org.matrix.android.sdk.internal.task.Task
|
||||
import javax.inject.Inject
|
||||
|
||||
internal interface AddRoomAliasTask : Task<AddRoomAliasTask.Params, Unit> {
|
||||
data class Params(
|
||||
val roomId: String,
|
||||
val roomAlias: String
|
||||
/**
|
||||
* the local part of the alias.
|
||||
* Ex: for the alias "#my_alias:example.org", the local part is "my_alias"
|
||||
*/
|
||||
val aliasLocalPart: String
|
||||
)
|
||||
}
|
||||
|
||||
internal class DefaultAddRoomAliasTask @Inject constructor(
|
||||
private val roomAPI: RoomAPI,
|
||||
@UserId private val userId: String,
|
||||
private val directoryAPI: DirectoryAPI,
|
||||
private val aliasAvailabilityChecker: RoomAliasAvailabilityChecker,
|
||||
private val eventBus: EventBus
|
||||
) : AddRoomAliasTask {
|
||||
|
||||
override suspend fun execute(params: AddRoomAliasTask.Params) {
|
||||
aliasAvailabilityChecker.check(params.aliasLocalPart)
|
||||
|
||||
executeRequest<Unit>(eventBus) {
|
||||
apiCall = roomAPI.addRoomAlias(
|
||||
roomAlias = params.roomAlias,
|
||||
apiCall = directoryAPI.addRoomAlias(
|
||||
roomAlias = params.aliasLocalPart.toFullLocalAlias(userId),
|
||||
body = AddRoomAliasBody(
|
||||
roomId = params.roomId
|
||||
)
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright 2020 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.internal.session.room.alias
|
||||
|
||||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import org.matrix.android.sdk.api.session.room.alias.AliasService
|
||||
|
||||
internal class DefaultAliasService @AssistedInject constructor(
|
||||
@Assisted private val roomId: String,
|
||||
private val getRoomLocalAliasesTask: GetRoomLocalAliasesTask,
|
||||
private val addRoomAliasTask: AddRoomAliasTask
|
||||
) : AliasService {
|
||||
|
||||
@AssistedInject.Factory
|
||||
interface Factory {
|
||||
fun create(roomId: String): AliasService
|
||||
}
|
||||
|
||||
override suspend fun getRoomAliases(): List<String> {
|
||||
return getRoomLocalAliasesTask.execute(GetRoomLocalAliasesTask.Params(roomId))
|
||||
}
|
||||
|
||||
override suspend fun addAlias(aliasLocalPart: String) {
|
||||
addRoomAliasTask.execute(AddRoomAliasTask.Params(roomId, aliasLocalPart))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright 2020 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.internal.session.room.alias
|
||||
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.matrix.android.sdk.internal.network.executeRequest
|
||||
import org.matrix.android.sdk.internal.session.directory.DirectoryAPI
|
||||
import org.matrix.android.sdk.internal.task.Task
|
||||
import javax.inject.Inject
|
||||
|
||||
internal interface DeleteRoomAliasTask : Task<DeleteRoomAliasTask.Params, Unit> {
|
||||
data class Params(
|
||||
val roomAlias: String
|
||||
)
|
||||
}
|
||||
|
||||
internal class DefaultDeleteRoomAliasTask @Inject constructor(
|
||||
private val directoryAPI: DirectoryAPI,
|
||||
private val eventBus: EventBus
|
||||
) : DeleteRoomAliasTask {
|
||||
|
||||
override suspend fun execute(params: DeleteRoomAliasTask.Params) {
|
||||
executeRequest<Unit>(eventBus) {
|
||||
apiCall = directoryAPI.deleteRoomAlias(
|
||||
roomAlias = params.roomAlias
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright 2020 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.internal.session.room.alias
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class GetAliasesResponse(
|
||||
/**
|
||||
* Required. The server's local aliases on the room. Can be empty.
|
||||
*/
|
||||
@Json(name = "aliases") val aliases: List<String> = emptyList()
|
||||
)
|
|
@ -25,7 +25,7 @@ import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
|
|||
import org.matrix.android.sdk.internal.database.query.findByAlias
|
||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import org.matrix.android.sdk.internal.network.executeRequest
|
||||
import org.matrix.android.sdk.internal.session.room.RoomAPI
|
||||
import org.matrix.android.sdk.internal.session.directory.DirectoryAPI
|
||||
import org.matrix.android.sdk.internal.task.Task
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -38,7 +38,7 @@ internal interface GetRoomIdByAliasTask : Task<GetRoomIdByAliasTask.Params, Opti
|
|||
|
||||
internal class DefaultGetRoomIdByAliasTask @Inject constructor(
|
||||
@SessionDatabase private val monarchy: Monarchy,
|
||||
private val roomAPI: RoomAPI,
|
||||
private val directoryAPI: DirectoryAPI,
|
||||
private val eventBus: EventBus
|
||||
) : GetRoomIdByAliasTask {
|
||||
|
||||
|
@ -53,7 +53,7 @@ internal class DefaultGetRoomIdByAliasTask @Inject constructor(
|
|||
} else {
|
||||
roomId = tryOrNull("## Failed to get roomId from alias") {
|
||||
executeRequest<RoomAliasDescription>(eventBus) {
|
||||
apiCall = roomAPI.getRoomIdByAlias(params.roomAlias)
|
||||
apiCall = directoryAPI.getRoomIdByAlias(params.roomAlias)
|
||||
}
|
||||
}?.roomId
|
||||
Optional.from(roomId)
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright 2020 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.internal.session.room.alias
|
||||
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.matrix.android.sdk.internal.network.executeRequest
|
||||
import org.matrix.android.sdk.internal.session.room.RoomAPI
|
||||
import org.matrix.android.sdk.internal.task.Task
|
||||
import javax.inject.Inject
|
||||
|
||||
internal interface GetRoomLocalAliasesTask : Task<GetRoomLocalAliasesTask.Params, List<String>> {
|
||||
data class Params(
|
||||
val roomId: String
|
||||
)
|
||||
}
|
||||
|
||||
internal class DefaultGetRoomLocalAliasesTask @Inject constructor(
|
||||
private val roomAPI: RoomAPI,
|
||||
private val eventBus: EventBus
|
||||
) : GetRoomLocalAliasesTask {
|
||||
|
||||
override suspend fun execute(params: GetRoomLocalAliasesTask.Params): List<String> {
|
||||
// We do not check for "org.matrix.msc2432", so the API may be missing
|
||||
val response = executeRequest<GetAliasesResponse>(eventBus) {
|
||||
apiCall = roomAPI.getAliases(roomId = params.roomId)
|
||||
}
|
||||
|
||||
return response.aliases
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright 2020 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.internal.session.room.alias
|
||||
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.network.executeRequest
|
||||
import org.matrix.android.sdk.internal.session.directory.DirectoryAPI
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class RoomAliasAvailabilityChecker @Inject constructor(
|
||||
@UserId private val userId: String,
|
||||
private val directoryAPI: DirectoryAPI,
|
||||
private val eventBus: EventBus
|
||||
) {
|
||||
/**
|
||||
* @param aliasLocalPart the local part of the alias.
|
||||
* Ex: for the alias "#my_alias:example.org", the local part is "my_alias"
|
||||
*/
|
||||
@Throws(RoomAliasError::class)
|
||||
suspend fun check(aliasLocalPart: String?) {
|
||||
if (aliasLocalPart.isNullOrEmpty()) {
|
||||
throw RoomAliasError.AliasEmpty
|
||||
}
|
||||
// Check alias availability
|
||||
val fullAlias = aliasLocalPart.toFullLocalAlias(userId)
|
||||
try {
|
||||
executeRequest<RoomAliasDescription>(eventBus) {
|
||||
apiCall = directoryAPI.getRoomIdByAlias(fullAlias)
|
||||
}
|
||||
} catch (throwable: Throwable) {
|
||||
if (throwable is Failure.ServerError && throwable.httpCode == 404) {
|
||||
// This is a 404, so the alias is available: nominal case
|
||||
null
|
||||
} else {
|
||||
// Other error, propagate it
|
||||
throw throwable
|
||||
}
|
||||
}
|
||||
?.let {
|
||||
// Alias already exists: error case
|
||||
throw RoomAliasError.AliasNotAvailable
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
internal fun String.toFullLocalAlias(userId: String) = "#" + this + ":" + userId.substringAfter(":")
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ import kotlinx.coroutines.TimeoutCancellationException
|
|||
import org.greenrobot.eventbus.EventBus
|
||||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import org.matrix.android.sdk.api.failure.MatrixError
|
||||
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError
|
||||
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
|
||||
|
@ -31,10 +32,9 @@ import org.matrix.android.sdk.internal.database.model.RoomEntityFields
|
|||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
|
||||
import org.matrix.android.sdk.internal.database.query.where
|
||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.network.executeRequest
|
||||
import org.matrix.android.sdk.internal.session.room.RoomAPI
|
||||
import org.matrix.android.sdk.internal.session.room.alias.RoomAliasDescription
|
||||
import org.matrix.android.sdk.internal.session.room.alias.RoomAliasAvailabilityChecker
|
||||
import org.matrix.android.sdk.internal.session.room.read.SetReadMarkersTask
|
||||
import org.matrix.android.sdk.internal.session.user.accountdata.DirectChatsHelper
|
||||
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask
|
||||
|
@ -47,8 +47,8 @@ internal interface CreateRoomTask : Task<CreateRoomParams, String>
|
|||
|
||||
internal class DefaultCreateRoomTask @Inject constructor(
|
||||
private val roomAPI: RoomAPI,
|
||||
@UserId private val userId: String,
|
||||
@SessionDatabase private val monarchy: Monarchy,
|
||||
private val aliasAvailabilityChecker: RoomAliasAvailabilityChecker,
|
||||
private val directChatsHelper: DirectChatsHelper,
|
||||
private val updateUserAccountDataTask: UpdateUserAccountDataTask,
|
||||
private val readMarkersTask: SetReadMarkersTask,
|
||||
|
@ -65,28 +65,11 @@ internal class DefaultCreateRoomTask @Inject constructor(
|
|||
} else null
|
||||
|
||||
if (params.preset == CreateRoomPreset.PRESET_PUBLIC_CHAT) {
|
||||
if (params.roomAliasName.isNullOrEmpty()) {
|
||||
throw CreateRoomFailure.RoomAliasError.AliasEmpty
|
||||
}
|
||||
// Check alias availability
|
||||
val fullAlias = "#" + params.roomAliasName + ":" + userId.substringAfter(":")
|
||||
try {
|
||||
executeRequest<RoomAliasDescription>(eventBus) {
|
||||
apiCall = roomAPI.getRoomIdByAlias(fullAlias)
|
||||
}
|
||||
} catch (throwable: Throwable) {
|
||||
if (throwable is Failure.ServerError && throwable.httpCode == 404) {
|
||||
// This is a 404, so the alias is available: nominal case
|
||||
null
|
||||
} else {
|
||||
// Other error, propagate it
|
||||
throw throwable
|
||||
}
|
||||
aliasAvailabilityChecker.check(params.roomAliasName)
|
||||
} catch (aliasError: RoomAliasError) {
|
||||
throw CreateRoomFailure.AliasError(aliasError)
|
||||
}
|
||||
?.let {
|
||||
// Alias already exists: error case
|
||||
throw CreateRoomFailure.RoomAliasError.AliasNotAvailable
|
||||
}
|
||||
}
|
||||
|
||||
val createRoomBody = createRoomBodyBuilder.build(params)
|
||||
|
@ -104,7 +87,7 @@ internal class DefaultCreateRoomTask @Inject constructor(
|
|||
} else if (throwable.httpCode == 400
|
||||
&& throwable.error.code == MatrixError.M_UNKNOWN
|
||||
&& throwable.error.message == "Invalid characters in room alias") {
|
||||
throw CreateRoomFailure.RoomAliasError.AliasInvalid
|
||||
throw CreateRoomFailure.AliasError(RoomAliasError.AliasInvalid)
|
||||
}
|
||||
}
|
||||
throw throwable
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright 2020 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.internal.session.room.directory
|
||||
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||
import org.matrix.android.sdk.internal.network.executeRequest
|
||||
import org.matrix.android.sdk.internal.session.directory.DirectoryAPI
|
||||
import org.matrix.android.sdk.internal.session.directory.RoomDirectoryVisibilityJson
|
||||
import org.matrix.android.sdk.internal.task.Task
|
||||
import javax.inject.Inject
|
||||
|
||||
internal interface GetRoomDirectoryVisibilityTask : Task<GetRoomDirectoryVisibilityTask.Params, RoomDirectoryVisibility> {
|
||||
data class Params(
|
||||
val roomId: String
|
||||
)
|
||||
}
|
||||
|
||||
internal class DefaultGetRoomDirectoryVisibilityTask @Inject constructor(
|
||||
private val directoryAPI: DirectoryAPI,
|
||||
private val eventBus: EventBus
|
||||
) : GetRoomDirectoryVisibilityTask {
|
||||
|
||||
override suspend fun execute(params: GetRoomDirectoryVisibilityTask.Params): RoomDirectoryVisibility {
|
||||
return executeRequest<RoomDirectoryVisibilityJson>(eventBus) {
|
||||
apiCall = directoryAPI.getRoomDirectoryVisibility(params.roomId)
|
||||
}
|
||||
.visibility
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright 2020 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.internal.session.room.directory
|
||||
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||
import org.matrix.android.sdk.internal.network.executeRequest
|
||||
import org.matrix.android.sdk.internal.session.directory.DirectoryAPI
|
||||
import org.matrix.android.sdk.internal.session.directory.RoomDirectoryVisibilityJson
|
||||
import org.matrix.android.sdk.internal.task.Task
|
||||
import javax.inject.Inject
|
||||
|
||||
internal interface SetRoomDirectoryVisibilityTask : Task<SetRoomDirectoryVisibilityTask.Params, Unit> {
|
||||
data class Params(
|
||||
val roomId: String,
|
||||
val roomDirectoryVisibility: RoomDirectoryVisibility
|
||||
)
|
||||
}
|
||||
|
||||
internal class DefaultSetRoomDirectoryVisibilityTask @Inject constructor(
|
||||
private val directoryAPI: DirectoryAPI,
|
||||
private val eventBus: EventBus
|
||||
) : SetRoomDirectoryVisibilityTask {
|
||||
|
||||
override suspend fun execute(params: SetRoomDirectoryVisibilityTask.Params) {
|
||||
executeRequest<Unit>(eventBus) {
|
||||
apiCall = directoryAPI.setRoomDirectoryVisibility(
|
||||
params.roomId,
|
||||
RoomDirectoryVisibilityJson(visibility = params.roomDirectoryVisibility)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,7 +21,6 @@ import org.matrix.android.sdk.R
|
|||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomAliasesContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomCanonicalAliasContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomNameContent
|
||||
import org.matrix.android.sdk.internal.database.mapper.ContentMapper
|
||||
|
@ -71,12 +70,6 @@ internal class RoomDisplayNameResolver @Inject constructor(
|
|||
return name
|
||||
}
|
||||
|
||||
val aliases = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_ALIASES, stateKey = "")?.root
|
||||
name = ContentMapper.map(aliases?.content).toModel<RoomAliasesContent>()?.aliases?.firstOrNull()
|
||||
if (!name.isNullOrEmpty()) {
|
||||
return name
|
||||
}
|
||||
|
||||
val roomMembers = RoomMemberHelper(realm, roomId)
|
||||
val activeMembers = roomMembers.queryActiveRoomMembersEvent().findAll()
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@ import org.matrix.android.sdk.api.MatrixCallback
|
|||
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomCanonicalAliasContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
||||
import org.matrix.android.sdk.api.session.room.state.StateService
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
|
@ -104,18 +106,19 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private
|
|||
)
|
||||
}
|
||||
|
||||
override fun addRoomAlias(roomAlias: String, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return addRoomAliasTask
|
||||
.configureWith(AddRoomAliasTask.Params(roomId, roomAlias)) {
|
||||
this.callback = callback
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
}
|
||||
|
||||
override fun updateCanonicalAlias(alias: String, callback: MatrixCallback<Unit>): Cancelable {
|
||||
override fun updateCanonicalAlias(alias: String?, altAliases: List<String>, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return sendStateEvent(
|
||||
eventType = EventType.STATE_ROOM_CANONICAL_ALIAS,
|
||||
body = mapOf("alias" to alias),
|
||||
body = RoomCanonicalAliasContent(
|
||||
canonicalAlias = alias,
|
||||
alternativeAliases = altAliases
|
||||
// Ensure there is no duplicate
|
||||
.distinct()
|
||||
// Ensure the canonical alias is not also included in the alt alias
|
||||
.minus(listOfNotNull(alias))
|
||||
// Sort for the cleanup
|
||||
.sorted()
|
||||
).toContent(),
|
||||
callback = callback,
|
||||
stateKey = null
|
||||
)
|
||||
|
|
|
@ -246,7 +246,7 @@
|
|||
|
||||
<plurals name="notice_room_aliases_removed">
|
||||
<item quantity="one">%1$s removed %2$s as an address for this room.</item>
|
||||
<item quantity="other">%1$s removed %3$s as addresses for this room.</item>
|
||||
<item quantity="other">%1$s removed %2$s as addresses for this room.</item>
|
||||
</plurals>
|
||||
|
||||
<plurals name="notice_room_aliases_removed_by_you">
|
||||
|
@ -262,6 +262,33 @@
|
|||
<string name="notice_room_canonical_alias_unset">"%1$s removed the main address for this room."</string>
|
||||
<string name="notice_room_canonical_alias_unset_by_you">"You removed the main address for this room."</string>
|
||||
|
||||
<plurals name="notice_room_canonical_alias_alternative_added">
|
||||
<item quantity="one">%1$s added the alternative address %2$s for this room.</item>
|
||||
<item quantity="other">%1$s added the alternative addresses %2$s for this room.</item>
|
||||
</plurals>
|
||||
|
||||
<plurals name="notice_room_canonical_alias_alternative_added_by_you">
|
||||
<item quantity="one">You added the alternative address %1$s for this room.</item>
|
||||
<item quantity="other">You added the alternative addresses %1$s for this room.</item>
|
||||
</plurals>
|
||||
|
||||
<plurals name="notice_room_canonical_alias_alternative_removed">
|
||||
<item quantity="one">%1$s removed the alternative address %2$s for this room.</item>
|
||||
<item quantity="other">%1$s removed the alternative addresses %2$s for this room.</item>
|
||||
</plurals>
|
||||
|
||||
<plurals name="notice_room_canonical_alias_alternative_removed_by_you">
|
||||
<item quantity="one">You removed the alternative address %1$s for this room.</item>
|
||||
<item quantity="other">You removed the alternative addresses %1$s for this room.</item>
|
||||
</plurals>
|
||||
|
||||
<string name="notice_room_canonical_alias_alternative_changed">%1$s changed the alternative addresses for this room.</string>
|
||||
<string name="notice_room_canonical_alias_alternative_changed_by_you">You changed the alternative addresses for this room.</string>
|
||||
<string name="notice_room_canonical_alias_main_and_alternative_changed">%1$s changed the main and alternative addresses for this room.</string>
|
||||
<string name="notice_room_canonical_alias_main_and_alternative_changed_by_you">You changed the main and alternative addresses for this room.</string>
|
||||
<string name="notice_room_canonical_alias_no_change">%1$s changed the addresses for this room.</string>
|
||||
<string name="notice_room_canonical_alias_no_change_by_you">You changed the addresses for this room.</string>
|
||||
|
||||
<string name="notice_room_guest_access_can_join">"%1$s has allowed guests to join the room."</string>
|
||||
<string name="notice_room_guest_access_can_join_by_you">"You have allowed guests to join the room."</string>
|
||||
<string name="notice_direct_room_guest_access_can_join">"%1$s has allowed guests to join here."</string>
|
||||
|
|
|
@ -84,6 +84,7 @@ import im.vector.app.features.roomprofile.RoomProfileFragment
|
|||
import im.vector.app.features.roomprofile.banned.RoomBannedMemberListFragment
|
||||
import im.vector.app.features.roomprofile.members.RoomMemberListFragment
|
||||
import im.vector.app.features.roomprofile.settings.RoomSettingsFragment
|
||||
import im.vector.app.features.roomprofile.alias.RoomAliasFragment
|
||||
import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment
|
||||
import im.vector.app.features.roomprofile.uploads.files.RoomUploadsFilesFragment
|
||||
import im.vector.app.features.roomprofile.uploads.media.RoomUploadsMediaFragment
|
||||
|
@ -364,6 +365,11 @@ interface FragmentModule {
|
|||
@FragmentKey(RoomSettingsFragment::class)
|
||||
fun bindRoomSettingsFragment(fragment: RoomSettingsFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(RoomAliasFragment::class)
|
||||
fun bindRoomAliasFragment(fragment: RoomAliasFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(RoomMemberProfileFragment::class)
|
||||
|
|
|
@ -67,6 +67,7 @@ import im.vector.app.features.roomdirectory.createroom.CreateRoomActivity
|
|||
import im.vector.app.features.roommemberprofile.RoomMemberProfileActivity
|
||||
import im.vector.app.features.roommemberprofile.devices.DeviceListBottomSheet
|
||||
import im.vector.app.features.roomprofile.RoomProfileActivity
|
||||
import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheet
|
||||
import im.vector.app.features.settings.VectorSettingsActivity
|
||||
import im.vector.app.features.settings.devices.DeviceVerificationInfoBottomSheet
|
||||
import im.vector.app.features.share.IncomingShareActivity
|
||||
|
@ -153,6 +154,7 @@ interface ScreenComponent {
|
|||
fun inject(bottomSheet: ViewEditHistoryBottomSheet)
|
||||
fun inject(bottomSheet: DisplayReadReceiptsBottomSheet)
|
||||
fun inject(bottomSheet: RoomListQuickActionsBottomSheet)
|
||||
fun inject(bottomSheet: RoomAliasBottomSheet)
|
||||
fun inject(bottomSheet: VerificationBottomSheet)
|
||||
fun inject(bottomSheet: DeviceVerificationInfoBottomSheet)
|
||||
fun inject(bottomSheet: DeviceListBottomSheet)
|
||||
|
|
|
@ -35,6 +35,7 @@ import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedA
|
|||
import im.vector.app.features.reactions.EmojiChooserViewModel
|
||||
import im.vector.app.features.roomdirectory.RoomDirectorySharedActionViewModel
|
||||
import im.vector.app.features.roomprofile.RoomProfileSharedActionViewModel
|
||||
import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheetSharedActionViewModel
|
||||
import im.vector.app.features.userdirectory.UserListSharedActionViewModel
|
||||
|
||||
@Module
|
||||
|
@ -105,6 +106,11 @@ interface ViewModelModule {
|
|||
@ViewModelKey(RoomListQuickActionsSharedActionViewModel::class)
|
||||
fun bindRoomListQuickActionsSharedActionViewModel(viewModel: RoomListQuickActionsSharedActionViewModel): ViewModel
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ViewModelKey(RoomAliasBottomSheetSharedActionViewModel::class)
|
||||
fun bindRoomAliasBottomSheetSharedActionViewModel(viewModel: RoomAliasBottomSheetSharedActionViewModel): ViewModel
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ViewModelKey(RoomDirectorySharedActionViewModel::class)
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
package im.vector.app.core.epoxy.profiles
|
||||
|
||||
import android.content.res.ColorStateList
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
|
@ -26,8 +25,10 @@ import androidx.core.widget.ImageViewCompat
|
|||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import com.airbnb.epoxy.EpoxyModelClass
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.ClickListener
|
||||
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||
import im.vector.app.core.epoxy.onClick
|
||||
import im.vector.app.core.extensions.setTextOrHide
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
|
@ -67,11 +68,11 @@ abstract class ProfileActionItem : VectorEpoxyModel<ProfileActionItem.Holder>()
|
|||
var destructive: Boolean = false
|
||||
|
||||
@EpoxyAttribute
|
||||
var listener: View.OnClickListener? = null
|
||||
var listener: ClickListener? = null
|
||||
|
||||
override fun bind(holder: Holder) {
|
||||
super.bind(holder)
|
||||
holder.view.setOnClickListener(listener)
|
||||
holder.view.onClick(listener)
|
||||
if (listener == null) {
|
||||
holder.view.isClickable = false
|
||||
}
|
||||
|
|
|
@ -59,9 +59,7 @@ fun EpoxyController.buildProfileAction(
|
|||
accessoryRes(accessory)
|
||||
accessoryMatrixItem(accessoryMatrixItem)
|
||||
avatarRenderer(avatarRenderer)
|
||||
listener { _ ->
|
||||
action?.invoke()
|
||||
}
|
||||
listener(action)
|
||||
}
|
||||
|
||||
if (divider) {
|
||||
|
|
|
@ -27,6 +27,9 @@ import im.vector.app.core.epoxy.onClick
|
|||
@EpoxyModelClass(layout = R.layout.item_settings_continue_cancel)
|
||||
abstract class SettingsContinueCancelItem : EpoxyModelWithHolder<SettingsContinueCancelItem.Holder>() {
|
||||
|
||||
@EpoxyAttribute
|
||||
var continueText: String? = null
|
||||
|
||||
@EpoxyAttribute
|
||||
var continueOnClick: ClickListener? = null
|
||||
|
||||
|
@ -37,6 +40,8 @@ abstract class SettingsContinueCancelItem : EpoxyModelWithHolder<SettingsContinu
|
|||
super.bind(holder)
|
||||
|
||||
holder.cancelButton.onClick(cancelOnClick)
|
||||
|
||||
continueText?.let { holder.continueButton.text = it }
|
||||
holder.continueButton.onClick(continueOnClick)
|
||||
}
|
||||
|
||||
|
|
|
@ -61,8 +61,8 @@ abstract class FormSwitchItem : VectorEpoxyModel<FormSwitchItem.Holder>() {
|
|||
|
||||
holder.switchView.isEnabled = enabled
|
||||
|
||||
holder.switchView.setOnCheckedChangeListener(null)
|
||||
holder.switchView.isChecked = switchChecked
|
||||
|
||||
holder.switchView.setOnCheckedChangeListener { _, isChecked ->
|
||||
listener?.invoke(isChecked)
|
||||
}
|
||||
|
|
|
@ -53,7 +53,6 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
|
|||
EventType.STATE_ROOM_AVATAR,
|
||||
EventType.STATE_ROOM_MEMBER,
|
||||
EventType.STATE_ROOM_THIRD_PARTY_INVITE,
|
||||
EventType.STATE_ROOM_ALIASES,
|
||||
EventType.STATE_ROOM_CANONICAL_ALIAS,
|
||||
EventType.STATE_ROOM_JOIN_RULES,
|
||||
EventType.STATE_ROOM_HISTORY_VISIBILITY,
|
||||
|
@ -79,6 +78,7 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
|
|||
encryptedItemFactory.create(event, nextEvent, highlight, callback)
|
||||
}
|
||||
}
|
||||
EventType.STATE_ROOM_ALIASES,
|
||||
EventType.KEY_VERIFICATION_ACCEPT,
|
||||
EventType.KEY_VERIFICATION_START,
|
||||
EventType.KEY_VERIFICATION_KEY,
|
||||
|
|
|
@ -465,21 +465,72 @@ class NoticeEventFormatter @Inject constructor(
|
|||
|
||||
private fun formatRoomCanonicalAliasEvent(event: Event, senderName: String?): String? {
|
||||
val eventContent: RoomCanonicalAliasContent? = event.getClearContent().toModel()
|
||||
val canonicalAlias = eventContent?.canonicalAlias
|
||||
return canonicalAlias
|
||||
?.takeIf { it.isNotBlank() }
|
||||
?.let {
|
||||
val prevContent: RoomCanonicalAliasContent? = event.resolvedPrevContent().toModel()
|
||||
val canonicalAlias = eventContent?.canonicalAlias?.takeIf { it.isNotEmpty() }
|
||||
val prevCanonicalAlias = prevContent?.canonicalAlias?.takeIf { it.isNotEmpty() }
|
||||
val altAliases = eventContent?.alternativeAliases.orEmpty()
|
||||
val prevAltAliases = prevContent?.alternativeAliases.orEmpty()
|
||||
val added = altAliases - prevAltAliases
|
||||
val removed = prevAltAliases - altAliases
|
||||
|
||||
return when {
|
||||
added.isEmpty() && removed.isEmpty() && canonicalAlias == prevCanonicalAlias -> {
|
||||
// No difference between the two events say something as we can't simply hide the event from here
|
||||
if (event.isSentByCurrentUser()) {
|
||||
sp.getString(R.string.notice_room_canonical_alias_no_change_by_you)
|
||||
} else {
|
||||
sp.getString(R.string.notice_room_canonical_alias_no_change, senderName)
|
||||
}
|
||||
}
|
||||
added.isEmpty() && removed.isEmpty() -> {
|
||||
// Canonical has changed
|
||||
if (canonicalAlias != null) {
|
||||
if (event.isSentByCurrentUser()) {
|
||||
sp.getString(R.string.notice_room_canonical_alias_set_by_you, it)
|
||||
sp.getString(R.string.notice_room_canonical_alias_set_by_you, canonicalAlias)
|
||||
} else {
|
||||
sp.getString(R.string.notice_room_canonical_alias_set, senderName, it)
|
||||
sp.getString(R.string.notice_room_canonical_alias_set, senderName, canonicalAlias)
|
||||
}
|
||||
} else {
|
||||
if (event.isSentByCurrentUser()) {
|
||||
sp.getString(R.string.notice_room_canonical_alias_unset_by_you)
|
||||
} else {
|
||||
sp.getString(R.string.notice_room_canonical_alias_unset, senderName)
|
||||
}
|
||||
}
|
||||
?: if (event.isSentByCurrentUser()) {
|
||||
sp.getString(R.string.notice_room_canonical_alias_unset_by_you)
|
||||
}
|
||||
added.isEmpty() && canonicalAlias == prevCanonicalAlias -> {
|
||||
// Some alternative has been removed
|
||||
if (event.isSentByCurrentUser()) {
|
||||
sp.getQuantityString(R.plurals.notice_room_canonical_alias_alternative_removed_by_you, removed.size, removed.joinToString())
|
||||
} else {
|
||||
sp.getString(R.string.notice_room_canonical_alias_unset, senderName)
|
||||
sp.getQuantityString(R.plurals.notice_room_canonical_alias_alternative_removed, removed.size, senderName, removed.joinToString())
|
||||
}
|
||||
}
|
||||
removed.isEmpty() && canonicalAlias == prevCanonicalAlias -> {
|
||||
// Some alternative has been added
|
||||
if (event.isSentByCurrentUser()) {
|
||||
sp.getQuantityString(R.plurals.notice_room_canonical_alias_alternative_added_by_you, added.size, added.joinToString())
|
||||
} else {
|
||||
sp.getQuantityString(R.plurals.notice_room_canonical_alias_alternative_added, added.size, senderName, added.joinToString())
|
||||
}
|
||||
}
|
||||
canonicalAlias == prevCanonicalAlias -> {
|
||||
// Alternative added and removed
|
||||
if (event.isSentByCurrentUser()) {
|
||||
sp.getString(R.string.notice_room_canonical_alias_alternative_changed_by_you)
|
||||
} else {
|
||||
sp.getString(R.string.notice_room_canonical_alias_alternative_changed, senderName)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
// Main and removed, or main and added, or main and added and removed
|
||||
if (event.isSentByCurrentUser()) {
|
||||
sp.getString(R.string.notice_room_canonical_alias_main_and_alternative_changed_by_you)
|
||||
} else {
|
||||
sp.getString(R.string.notice_room_canonical_alias_main_and_alternative_changed, senderName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatRoomGuestAccessEvent(event: Event, senderName: String?, rs: RoomSummary?): String? {
|
||||
|
|
|
@ -77,6 +77,7 @@ class RoomListQuickActionsBottomSheet : VectorBaseBottomSheetDialogFragment(), R
|
|||
|
||||
override fun onDestroyView() {
|
||||
recyclerView.cleanup()
|
||||
roomListActionsEpoxyController.listener = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ import com.airbnb.epoxy.TypedEpoxyController
|
|||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Loading
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.error.ErrorFormatter
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.features.discovery.settingsSectionTitleItem
|
||||
import im.vector.app.features.form.formAdvancedToggleItem
|
||||
|
@ -31,8 +30,9 @@ import im.vector.app.features.form.formSwitchItem
|
|||
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
|
||||
import javax.inject.Inject
|
||||
|
||||
class CreateRoomController @Inject constructor(private val stringProvider: StringProvider,
|
||||
private val errorFormatter: ErrorFormatter
|
||||
class CreateRoomController @Inject constructor(
|
||||
private val stringProvider: StringProvider,
|
||||
private val roomAliasErrorFormatter: RoomAliasErrorFormatter
|
||||
) : TypedEpoxyController<CreateRoomViewState>() {
|
||||
|
||||
var listener: Listener? = null
|
||||
|
@ -104,13 +104,8 @@ class CreateRoomController @Inject constructor(private val stringProvider: Strin
|
|||
value(viewState.roomType.aliasLocalPart)
|
||||
homeServer(":" + viewState.homeServerName)
|
||||
errorMessage(
|
||||
when ((viewState.asyncCreateRoomRequest as? Fail)?.error) {
|
||||
is CreateRoomFailure.RoomAliasError.AliasEmpty -> R.string.create_room_alias_empty
|
||||
is CreateRoomFailure.RoomAliasError.AliasNotAvailable -> R.string.create_room_alias_already_in_use
|
||||
is CreateRoomFailure.RoomAliasError.AliasInvalid -> R.string.create_room_alias_invalid
|
||||
else -> null
|
||||
}
|
||||
?.let { stringProvider.getString(it) }
|
||||
roomAliasErrorFormatter.format(
|
||||
(((viewState.asyncCreateRoomRequest as? Fail)?.error) as? CreateRoomFailure.AliasError)?.aliasError)
|
||||
)
|
||||
onTextChange { value ->
|
||||
listener?.setAliasLocalPart(value)
|
||||
|
|
|
@ -84,7 +84,7 @@ class CreateRoomFragment @Inject constructor(
|
|||
|
||||
override fun showFailure(throwable: Throwable) {
|
||||
// Note: RoomAliasError are displayed directly in the form
|
||||
if (throwable !is CreateRoomFailure.RoomAliasError) {
|
||||
if (throwable !is CreateRoomFailure.AliasError) {
|
||||
super.showFailure(throwable)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2020 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 im.vector.app.R
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError
|
||||
import javax.inject.Inject
|
||||
|
||||
class RoomAliasErrorFormatter @Inject constructor(
|
||||
private val stringProvider: StringProvider
|
||||
) {
|
||||
fun format(roomAliasError: RoomAliasError?): String? {
|
||||
return when (roomAliasError) {
|
||||
is RoomAliasError.AliasEmpty -> R.string.create_room_alias_empty
|
||||
is RoomAliasError.AliasNotAvailable -> R.string.create_room_alias_already_in_use
|
||||
is RoomAliasError.AliasInvalid -> R.string.create_room_alias_invalid
|
||||
else -> null
|
||||
}
|
||||
?.let { stringProvider.getString(it) }
|
||||
}
|
||||
}
|
|
@ -36,6 +36,7 @@ import im.vector.app.features.room.RequireActiveMembershipViewState
|
|||
import im.vector.app.features.roomprofile.banned.RoomBannedMemberListFragment
|
||||
import im.vector.app.features.roomprofile.members.RoomMemberListFragment
|
||||
import im.vector.app.features.roomprofile.settings.RoomSettingsFragment
|
||||
import im.vector.app.features.roomprofile.alias.RoomAliasFragment
|
||||
import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -98,10 +99,11 @@ class RoomProfileActivity :
|
|||
.observe()
|
||||
.subscribe { sharedAction ->
|
||||
when (sharedAction) {
|
||||
is RoomProfileSharedAction.OpenRoomMembers -> openRoomMembers()
|
||||
is RoomProfileSharedAction.OpenRoomSettings -> openRoomSettings()
|
||||
is RoomProfileSharedAction.OpenRoomUploads -> openRoomUploads()
|
||||
is RoomProfileSharedAction.OpenBannedRoomMembers -> openBannedRoomMembers()
|
||||
is RoomProfileSharedAction.OpenRoomMembers -> openRoomMembers()
|
||||
is RoomProfileSharedAction.OpenRoomSettings -> openRoomSettings()
|
||||
is RoomProfileSharedAction.OpenRoomAliasesSettings -> openRoomAlias()
|
||||
is RoomProfileSharedAction.OpenRoomUploads -> openRoomUploads()
|
||||
is RoomProfileSharedAction.OpenBannedRoomMembers -> openBannedRoomMembers()
|
||||
}
|
||||
}
|
||||
.disposeOnDestroy()
|
||||
|
@ -135,6 +137,10 @@ class RoomProfileActivity :
|
|||
addFragmentToBackstack(R.id.simpleFragmentContainer, RoomSettingsFragment::class.java, roomProfileArgs)
|
||||
}
|
||||
|
||||
private fun openRoomAlias() {
|
||||
addFragmentToBackstack(R.id.simpleFragmentContainer, RoomAliasFragment::class.java, roomProfileArgs)
|
||||
}
|
||||
|
||||
private fun openRoomMembers() {
|
||||
addFragmentToBackstack(R.id.simpleFragmentContainer, RoomMemberListFragment::class.java, roomProfileArgs)
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import im.vector.app.core.platform.VectorSharedAction
|
|||
*/
|
||||
sealed class RoomProfileSharedAction : VectorSharedAction {
|
||||
object OpenRoomSettings : RoomProfileSharedAction()
|
||||
object OpenRoomAliasesSettings : RoomProfileSharedAction()
|
||||
object OpenRoomUploads : RoomProfileSharedAction()
|
||||
object OpenRoomMembers : RoomProfileSharedAction()
|
||||
object OpenBannedRoomMembers : RoomProfileSharedAction()
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright 2020 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.roomprofile.alias
|
||||
|
||||
import im.vector.app.core.platform.VectorViewModelAction
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||
|
||||
sealed class RoomAliasAction : VectorViewModelAction {
|
||||
// Canonical
|
||||
object ToggleManualPublishForm : RoomAliasAction()
|
||||
data class SetNewAlias(val alias: String) : RoomAliasAction()
|
||||
object ManualPublishAlias : RoomAliasAction()
|
||||
data class PublishAlias(val alias: String) : RoomAliasAction()
|
||||
data class UnpublishAlias(val alias: String) : RoomAliasAction()
|
||||
data class SetCanonicalAlias(val canonicalAlias: String?) : RoomAliasAction()
|
||||
|
||||
// Room directory
|
||||
data class SetRoomDirectoryVisibility(val roomDirectoryVisibility: RoomDirectoryVisibility) : RoomAliasAction()
|
||||
|
||||
// Local
|
||||
data class RemoveLocalAlias(val alias: String) : RoomAliasAction()
|
||||
object ToggleAddLocalAliasForm : RoomAliasAction()
|
||||
data class SetNewLocalAliasLocalPart(val aliasLocalPart: String) : RoomAliasAction()
|
||||
object AddLocalAlias : RoomAliasAction()
|
||||
}
|
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* Copyright 2020 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.roomprofile.alias
|
||||
|
||||
import android.text.InputType
|
||||
import com.airbnb.epoxy.TypedEpoxyController
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.errorWithRetryItem
|
||||
import im.vector.app.core.epoxy.loadingItem
|
||||
import im.vector.app.core.epoxy.profiles.buildProfileSection
|
||||
import im.vector.app.core.epoxy.profiles.profileActionItem
|
||||
import im.vector.app.core.error.ErrorFormatter
|
||||
import im.vector.app.core.resources.ColorProvider
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.features.discovery.settingsButtonItem
|
||||
import im.vector.app.features.discovery.settingsContinueCancelItem
|
||||
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 javax.inject.Inject
|
||||
|
||||
class RoomAliasController @Inject constructor(
|
||||
private val stringProvider: StringProvider,
|
||||
private val errorFormatter: ErrorFormatter,
|
||||
private val colorProvider: ColorProvider,
|
||||
private val roomAliasErrorFormatter: RoomAliasErrorFormatter
|
||||
) : TypedEpoxyController<RoomAliasViewState>() {
|
||||
|
||||
interface Callback {
|
||||
fun toggleManualPublishForm()
|
||||
fun setNewAlias(alias: String)
|
||||
fun addAlias()
|
||||
fun setRoomDirectoryVisibility(roomDirectoryVisibility: RoomDirectoryVisibility)
|
||||
fun toggleLocalAliasForm()
|
||||
fun setNewLocalAliasLocalPart(aliasLocalPart: String)
|
||||
fun addLocalAlias()
|
||||
fun openAliasDetail(alias: String)
|
||||
}
|
||||
|
||||
var callback: Callback? = null
|
||||
|
||||
init {
|
||||
setData(null)
|
||||
}
|
||||
|
||||
override fun buildModels(data: RoomAliasViewState?) {
|
||||
data ?: return
|
||||
|
||||
// Published alias
|
||||
buildPublishInfo(data)
|
||||
// Room directory visibility
|
||||
buildRoomDirectoryVisibility(data)
|
||||
// Local alias
|
||||
buildLocalInfo(data)
|
||||
}
|
||||
|
||||
private fun buildRoomDirectoryVisibility(data: RoomAliasViewState) {
|
||||
when (data.roomDirectoryVisibility) {
|
||||
Uninitialized -> Unit
|
||||
is Loading -> Unit
|
||||
is Success -> {
|
||||
formSwitchItem {
|
||||
id("roomVisibility")
|
||||
title(stringProvider.getString(R.string.room_alias_publish_to_directory, data.homeServerName))
|
||||
showDivider(false)
|
||||
switchChecked(data.roomDirectoryVisibility() == RoomDirectoryVisibility.PUBLIC)
|
||||
listener {
|
||||
if (it) {
|
||||
callback?.setRoomDirectoryVisibility(RoomDirectoryVisibility.PUBLIC)
|
||||
} else {
|
||||
callback?.setRoomDirectoryVisibility(RoomDirectoryVisibility.PRIVATE)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
is Fail -> {
|
||||
errorWithRetryItem {
|
||||
text(stringProvider.getString(R.string.room_alias_publish_to_directory_error,
|
||||
errorFormatter.toHumanReadable(data.roomDirectoryVisibility.error)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildPublishInfo(data: RoomAliasViewState) {
|
||||
buildProfileSection(
|
||||
stringProvider.getString(R.string.room_alias_published_alias_title)
|
||||
)
|
||||
settingsInfoItem {
|
||||
id("publishedInfo")
|
||||
helperTextResId(R.string.room_alias_published_alias_subtitle)
|
||||
}
|
||||
|
||||
data.canonicalAlias
|
||||
?.takeIf { it.isNotEmpty() }
|
||||
?.let { canonicalAlias ->
|
||||
|
||||
profileActionItem {
|
||||
id("canonical")
|
||||
title(data.canonicalAlias)
|
||||
subtitle(stringProvider.getString(R.string.room_alias_published_alias_main))
|
||||
listener { callback?.openAliasDetail(canonicalAlias) }
|
||||
}
|
||||
}
|
||||
|
||||
if (data.alternativeAliases.isEmpty()) {
|
||||
settingsInfoItem {
|
||||
id("otherPublishedEmpty")
|
||||
if (data.actionPermissions.canChangeCanonicalAlias) {
|
||||
helperTextResId(R.string.room_alias_address_empty_can_add)
|
||||
} else {
|
||||
helperTextResId(R.string.room_alias_address_empty)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
settingsInfoItem {
|
||||
id("otherPublished")
|
||||
helperTextResId(R.string.room_alias_published_other)
|
||||
}
|
||||
data.alternativeAliases.forEachIndexed { idx, altAlias ->
|
||||
profileActionItem {
|
||||
id("alt_$idx")
|
||||
title(altAlias)
|
||||
listener { callback?.openAliasDetail(altAlias) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (data.actionPermissions.canChangeCanonicalAlias) {
|
||||
buildPublishManuallyForm(data)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildPublishManuallyForm(data: RoomAliasViewState) {
|
||||
when (data.publishManuallyState) {
|
||||
RoomAliasViewState.AddAliasState.Hidden -> Unit
|
||||
RoomAliasViewState.AddAliasState.Closed -> {
|
||||
settingsButtonItem {
|
||||
id("publishManually")
|
||||
colorProvider(colorProvider)
|
||||
buttonTitleId(R.string.room_alias_published_alias_add_manually)
|
||||
buttonClickListener { callback?.toggleManualPublishForm() }
|
||||
}
|
||||
}
|
||||
is RoomAliasViewState.AddAliasState.Editing -> {
|
||||
formEditTextItem {
|
||||
id("publishManuallyEdit")
|
||||
value(data.publishManuallyState.value)
|
||||
showBottomSeparator(false)
|
||||
hint(stringProvider.getString(R.string.room_alias_address_hint))
|
||||
inputType(InputType.TYPE_CLASS_TEXT)
|
||||
onTextChange { text ->
|
||||
callback?.setNewAlias(text)
|
||||
}
|
||||
}
|
||||
settingsContinueCancelItem {
|
||||
id("publishManuallySubmit")
|
||||
continueText(stringProvider.getString(R.string.room_alias_published_alias_add_manually_submit))
|
||||
continueOnClick { callback?.addAlias() }
|
||||
cancelOnClick { callback?.toggleManualPublishForm() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildLocalInfo(data: RoomAliasViewState) {
|
||||
buildProfileSection(
|
||||
stringProvider.getString(R.string.room_alias_local_address_title)
|
||||
)
|
||||
settingsInfoItem {
|
||||
id("localInfo")
|
||||
helperText(stringProvider.getString(R.string.room_alias_local_address_subtitle, data.homeServerName))
|
||||
}
|
||||
|
||||
when (val localAliases = data.localAliases) {
|
||||
is Uninitialized -> {
|
||||
loadingItem {
|
||||
id("loadingAliases")
|
||||
}
|
||||
}
|
||||
is Success -> {
|
||||
if (localAliases().isEmpty()) {
|
||||
settingsInfoItem {
|
||||
id("locEmpty")
|
||||
helperTextResId(R.string.room_alias_local_address_empty)
|
||||
}
|
||||
} else {
|
||||
localAliases().forEachIndexed { idx, localAlias ->
|
||||
profileActionItem {
|
||||
id("loc_$idx")
|
||||
title(localAlias)
|
||||
listener { callback?.openAliasDetail(localAlias) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
is Fail -> {
|
||||
errorWithRetryItem {
|
||||
id("alt_error")
|
||||
text(errorFormatter.toHumanReadable(localAliases.error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add local
|
||||
buildAddLocalAlias(data)
|
||||
}
|
||||
|
||||
private fun buildAddLocalAlias(data: RoomAliasViewState) {
|
||||
when (data.newLocalAliasState) {
|
||||
RoomAliasViewState.AddAliasState.Hidden -> Unit
|
||||
RoomAliasViewState.AddAliasState.Closed -> {
|
||||
settingsButtonItem {
|
||||
id("newLocalAliasButton")
|
||||
colorProvider(colorProvider)
|
||||
buttonTitleId(R.string.room_alias_local_address_add)
|
||||
buttonClickListener { callback?.toggleLocalAliasForm() }
|
||||
}
|
||||
}
|
||||
is RoomAliasViewState.AddAliasState.Editing -> {
|
||||
roomAliasEditItem {
|
||||
id("newLocalAlias")
|
||||
value(data.newLocalAliasState.value)
|
||||
homeServer(":" + data.homeServerName)
|
||||
showBottomSeparator(false)
|
||||
errorMessage(roomAliasErrorFormatter.format((data.newLocalAliasState.asyncRequest as? Fail)?.error as? RoomAliasError))
|
||||
onTextChange { value ->
|
||||
callback?.setNewLocalAliasLocalPart(value)
|
||||
}
|
||||
}
|
||||
settingsContinueCancelItem {
|
||||
id("newLocalAliasSubmit")
|
||||
continueText(stringProvider.getString(R.string.action_add))
|
||||
continueOnClick { callback?.addLocalAlias() }
|
||||
cancelOnClick { callback?.toggleLocalAliasForm() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* Copyright 2020 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.roomprofile.alias
|
||||
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.isVisible
|
||||
import com.airbnb.mvrx.args
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.dialogs.withColoredButton
|
||||
import im.vector.app.core.extensions.cleanup
|
||||
import im.vector.app.core.extensions.configureWith
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.core.utils.shareText
|
||||
import im.vector.app.core.utils.toast
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.roomprofile.RoomProfileArgs
|
||||
import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheet
|
||||
import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheetSharedAction
|
||||
import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheetSharedActionViewModel
|
||||
import kotlinx.android.synthetic.main.fragment_room_setting_generic.*
|
||||
import kotlinx.android.synthetic.main.merge_overlay_waiting_view.*
|
||||
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.util.toMatrixItem
|
||||
import javax.inject.Inject
|
||||
|
||||
class RoomAliasFragment @Inject constructor(
|
||||
val viewModelFactory: RoomAliasViewModel.Factory,
|
||||
private val controller: RoomAliasController,
|
||||
private val avatarRenderer: AvatarRenderer
|
||||
) :
|
||||
VectorBaseFragment(),
|
||||
RoomAliasController.Callback {
|
||||
|
||||
private val viewModel: RoomAliasViewModel by fragmentViewModel()
|
||||
private lateinit var sharedActionViewModel: RoomAliasBottomSheetSharedActionViewModel
|
||||
|
||||
private val roomProfileArgs: RoomProfileArgs by args()
|
||||
|
||||
override fun getLayoutResId() = R.layout.fragment_room_setting_generic
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
sharedActionViewModel = activityViewModelProvider.get(RoomAliasBottomSheetSharedActionViewModel::class.java)
|
||||
|
||||
controller.callback = this
|
||||
setupToolbar(roomSettingsToolbar)
|
||||
roomSettingsRecyclerView.configureWith(controller, hasFixedSize = true)
|
||||
waiting_view_status_text.setText(R.string.please_wait)
|
||||
waiting_view_status_text.isVisible = true
|
||||
|
||||
viewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is RoomAliasViewEvents.Failure -> showFailure(it.throwable)
|
||||
RoomAliasViewEvents.Success -> showSuccess()
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
sharedActionViewModel
|
||||
.observe()
|
||||
.subscribe { handleAliasAction(it) }
|
||||
.disposeOnDestroyView()
|
||||
}
|
||||
|
||||
private fun handleAliasAction(action: RoomAliasBottomSheetSharedAction?) {
|
||||
when (action) {
|
||||
is RoomAliasBottomSheetSharedAction.ShareAlias -> shareAlias(action.matrixTo)
|
||||
is RoomAliasBottomSheetSharedAction.PublishAlias -> viewModel.handle(RoomAliasAction.PublishAlias(action.alias))
|
||||
is RoomAliasBottomSheetSharedAction.UnPublishAlias -> unpublishAlias(action.alias)
|
||||
is RoomAliasBottomSheetSharedAction.DeleteAlias -> removeLocalAlias(action.alias)
|
||||
is RoomAliasBottomSheetSharedAction.SetMainAlias -> viewModel.handle(RoomAliasAction.SetCanonicalAlias(action.alias))
|
||||
RoomAliasBottomSheetSharedAction.UnsetMainAlias -> viewModel.handle(RoomAliasAction.SetCanonicalAlias(canonicalAlias = null))
|
||||
null -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
private fun shareAlias(matrixTo: String) {
|
||||
shareText(requireContext(), matrixTo)
|
||||
}
|
||||
|
||||
override fun showFailure(throwable: Throwable) {
|
||||
if (throwable !is RoomAliasError) {
|
||||
super.showFailure(throwable)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSuccess() {
|
||||
activity?.toast(R.string.room_settings_save_success)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
controller.callback = null
|
||||
roomSettingsRecyclerView.cleanup()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun invalidate() = withState(viewModel) { state ->
|
||||
waiting_view.isVisible = state.isLoading
|
||||
controller.setData(state)
|
||||
renderRoomSummary(state)
|
||||
}
|
||||
|
||||
private fun renderRoomSummary(state: RoomAliasViewState) {
|
||||
state.roomSummary()?.let {
|
||||
roomSettingsToolbarTitleView.text = it.displayName
|
||||
avatarRenderer.render(it.toMatrixItem(), roomSettingsToolbarAvatarImageView)
|
||||
}
|
||||
}
|
||||
|
||||
private fun unpublishAlias(alias: String) {
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setTitle(R.string.dialog_title_confirmation)
|
||||
.setMessage(getString(R.string.room_alias_unpublish_confirmation, alias))
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setPositiveButton(R.string.action_unpublish) { _, _ ->
|
||||
viewModel.handle(RoomAliasAction.UnpublishAlias(alias))
|
||||
}
|
||||
.show()
|
||||
.withColoredButton(DialogInterface.BUTTON_POSITIVE)
|
||||
}
|
||||
|
||||
override fun toggleManualPublishForm() {
|
||||
viewModel.handle(RoomAliasAction.ToggleManualPublishForm)
|
||||
}
|
||||
|
||||
override fun setNewAlias(alias: String) {
|
||||
viewModel.handle(RoomAliasAction.SetNewAlias(alias))
|
||||
}
|
||||
|
||||
override fun addAlias() {
|
||||
viewModel.handle(RoomAliasAction.ManualPublishAlias)
|
||||
}
|
||||
|
||||
override fun setRoomDirectoryVisibility(roomDirectoryVisibility: RoomDirectoryVisibility) {
|
||||
viewModel.handle(RoomAliasAction.SetRoomDirectoryVisibility(roomDirectoryVisibility))
|
||||
}
|
||||
|
||||
override fun toggleLocalAliasForm() {
|
||||
viewModel.handle(RoomAliasAction.ToggleAddLocalAliasForm)
|
||||
}
|
||||
|
||||
override fun setNewLocalAliasLocalPart(aliasLocalPart: String) {
|
||||
viewModel.handle(RoomAliasAction.SetNewLocalAliasLocalPart(aliasLocalPart))
|
||||
}
|
||||
|
||||
override fun addLocalAlias() {
|
||||
viewModel.handle(RoomAliasAction.AddLocalAlias)
|
||||
}
|
||||
|
||||
override fun openAliasDetail(alias: String) = withState(viewModel) { state ->
|
||||
RoomAliasBottomSheet
|
||||
.newInstance(
|
||||
alias = alias,
|
||||
isPublished = alias in state.allPublishedAliases,
|
||||
isMainAlias = alias == state.canonicalAlias,
|
||||
isLocal = alias in state.localAliases().orEmpty(),
|
||||
canEditCanonicalAlias = state.actionPermissions.canChangeCanonicalAlias
|
||||
)
|
||||
.show(childFragmentManager, "ROOM_ALIAS_ACTIONS")
|
||||
}
|
||||
|
||||
private fun removeLocalAlias(alias: String) {
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setTitle(R.string.dialog_title_confirmation)
|
||||
.setMessage(getString(R.string.room_alias_delete_confirmation, alias))
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setPositiveButton(R.string.delete) { _, _ ->
|
||||
viewModel.handle(RoomAliasAction.RemoveLocalAlias(alias))
|
||||
}
|
||||
.show()
|
||||
.withColoredButton(DialogInterface.BUTTON_POSITIVE)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright 2020 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.roomprofile.alias
|
||||
|
||||
import im.vector.app.core.platform.VectorViewEvents
|
||||
|
||||
/**
|
||||
* Transient events for room settings screen
|
||||
*/
|
||||
sealed class RoomAliasViewEvents : VectorViewEvents {
|
||||
data class Failure(val throwable: Throwable) : RoomAliasViewEvents()
|
||||
object Success : RoomAliasViewEvents()
|
||||
}
|
|
@ -0,0 +1,384 @@
|
|||
/*
|
||||
* Copyright 2020 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.roomprofile.alias
|
||||
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.FragmentViewModelContext
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.features.powerlevel.PowerLevelsObservableFactory
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomCanonicalAliasContent
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
||||
import org.matrix.android.sdk.rx.mapOptional
|
||||
import org.matrix.android.sdk.rx.rx
|
||||
import org.matrix.android.sdk.rx.unwrap
|
||||
|
||||
class RoomAliasViewModel @AssistedInject constructor(@Assisted initialState: RoomAliasViewState,
|
||||
private val session: Session)
|
||||
: VectorViewModel<RoomAliasViewState, RoomAliasAction, RoomAliasViewEvents>(initialState) {
|
||||
|
||||
@AssistedInject.Factory
|
||||
interface Factory {
|
||||
fun create(initialState: RoomAliasViewState): RoomAliasViewModel
|
||||
}
|
||||
|
||||
companion object : MvRxViewModelFactory<RoomAliasViewModel, RoomAliasViewState> {
|
||||
|
||||
@JvmStatic
|
||||
override fun create(viewModelContext: ViewModelContext, state: RoomAliasViewState): RoomAliasViewModel? {
|
||||
val fragment: RoomAliasFragment = (viewModelContext as FragmentViewModelContext).fragment()
|
||||
return fragment.viewModelFactory.create(state)
|
||||
}
|
||||
}
|
||||
|
||||
private val room = session.getRoom(initialState.roomId)!!
|
||||
|
||||
init {
|
||||
initHomeServerName()
|
||||
observeRoomSummary()
|
||||
observePowerLevel()
|
||||
observeRoomCanonicalAlias()
|
||||
fetchRoomAlias()
|
||||
fetchRoomDirectoryVisibility()
|
||||
}
|
||||
|
||||
private fun fetchRoomDirectoryVisibility() {
|
||||
setState {
|
||||
copy(
|
||||
roomDirectoryVisibility = Loading()
|
||||
)
|
||||
}
|
||||
viewModelScope.launch {
|
||||
runCatching {
|
||||
session.getRoomDirectoryVisibility(room.roomId)
|
||||
}.fold(
|
||||
{
|
||||
setState {
|
||||
copy(
|
||||
roomDirectoryVisibility = Success(it)
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
setState {
|
||||
copy(
|
||||
roomDirectoryVisibility = Fail(it)
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initHomeServerName() {
|
||||
setState {
|
||||
copy(
|
||||
homeServerName = session.myUserId.substringAfter(":")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchRoomAlias() {
|
||||
setState {
|
||||
copy(
|
||||
localAliases = Loading()
|
||||
)
|
||||
}
|
||||
|
||||
viewModelScope.launch {
|
||||
runCatching { room.getRoomAliases() }
|
||||
.fold(
|
||||
{
|
||||
setState { copy(localAliases = Success(it.sorted())) }
|
||||
},
|
||||
{
|
||||
setState { copy(localAliases = Fail(it)) }
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun observeRoomSummary() {
|
||||
room.rx().liveRoomSummary()
|
||||
.unwrap()
|
||||
.execute { async ->
|
||||
copy(
|
||||
roomSummary = async
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun observePowerLevel() {
|
||||
PowerLevelsObservableFactory(room)
|
||||
.createObservable()
|
||||
.subscribe {
|
||||
val powerLevelsHelper = PowerLevelsHelper(it)
|
||||
val permissions = RoomAliasViewState.ActionPermissions(
|
||||
canChangeCanonicalAlias = powerLevelsHelper.isUserAllowedToSend(
|
||||
userId = session.myUserId,
|
||||
isState = true,
|
||||
eventType = EventType.STATE_ROOM_CANONICAL_ALIAS
|
||||
)
|
||||
)
|
||||
setState {
|
||||
val newPublishManuallyState = if (permissions.canChangeCanonicalAlias) {
|
||||
when (publishManuallyState) {
|
||||
RoomAliasViewState.AddAliasState.Hidden -> RoomAliasViewState.AddAliasState.Closed
|
||||
else -> publishManuallyState
|
||||
}
|
||||
} else {
|
||||
RoomAliasViewState.AddAliasState.Hidden
|
||||
}
|
||||
copy(
|
||||
actionPermissions = permissions,
|
||||
publishManuallyState = newPublishManuallyState
|
||||
)
|
||||
}
|
||||
}
|
||||
.disposeOnClear()
|
||||
}
|
||||
|
||||
/**
|
||||
* We do not want to use the fallback avatar url, which can be the other user avatar, or the current user avatar.
|
||||
*/
|
||||
private fun observeRoomCanonicalAlias() {
|
||||
room.rx()
|
||||
.liveStateEvent(EventType.STATE_ROOM_CANONICAL_ALIAS, QueryStringValue.NoCondition)
|
||||
.mapOptional { it.content.toModel<RoomCanonicalAliasContent>() }
|
||||
.unwrap()
|
||||
.subscribe {
|
||||
setState {
|
||||
copy(
|
||||
canonicalAlias = it.canonicalAlias,
|
||||
alternativeAliases = it.alternativeAliases.orEmpty().sorted()
|
||||
)
|
||||
}
|
||||
}
|
||||
.disposeOnClear()
|
||||
}
|
||||
|
||||
override fun handle(action: RoomAliasAction) {
|
||||
when (action) {
|
||||
RoomAliasAction.ToggleManualPublishForm -> handleToggleManualPublishForm()
|
||||
is RoomAliasAction.SetNewAlias -> handleSetNewAlias(action)
|
||||
is RoomAliasAction.ManualPublishAlias -> handleManualPublishAlias()
|
||||
is RoomAliasAction.UnpublishAlias -> handleUnpublishAlias(action)
|
||||
is RoomAliasAction.SetCanonicalAlias -> handleSetCanonicalAlias(action)
|
||||
is RoomAliasAction.SetRoomDirectoryVisibility -> handleSetRoomDirectoryVisibility(action)
|
||||
RoomAliasAction.ToggleAddLocalAliasForm -> handleToggleAddLocalAliasForm()
|
||||
is RoomAliasAction.SetNewLocalAliasLocalPart -> handleSetNewLocalAliasLocalPart(action)
|
||||
RoomAliasAction.AddLocalAlias -> handleAddLocalAlias()
|
||||
is RoomAliasAction.RemoveLocalAlias -> handleRemoveLocalAlias(action)
|
||||
is RoomAliasAction.PublishAlias -> handlePublishAlias(action)
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
private fun handleSetRoomDirectoryVisibility(action: RoomAliasAction.SetRoomDirectoryVisibility) {
|
||||
postLoading(true)
|
||||
viewModelScope.launch {
|
||||
runCatching {
|
||||
session.setRoomDirectoryVisibility(room.roomId, action.roomDirectoryVisibility)
|
||||
}.fold(
|
||||
{
|
||||
setState {
|
||||
copy(
|
||||
isLoading = false,
|
||||
// Local echo, no need to fetch the data from the server again
|
||||
roomDirectoryVisibility = Success(action.roomDirectoryVisibility)
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
postLoading(false)
|
||||
_viewEvents.post(RoomAliasViewEvents.Failure(it))
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleToggleAddLocalAliasForm() {
|
||||
setState {
|
||||
copy(
|
||||
newLocalAliasState = when (newLocalAliasState) {
|
||||
RoomAliasViewState.AddAliasState.Hidden -> RoomAliasViewState.AddAliasState.Hidden
|
||||
RoomAliasViewState.AddAliasState.Closed -> RoomAliasViewState.AddAliasState.Editing("", Uninitialized)
|
||||
is RoomAliasViewState.AddAliasState.Editing -> RoomAliasViewState.AddAliasState.Closed
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleToggleManualPublishForm() {
|
||||
setState {
|
||||
copy(
|
||||
publishManuallyState = when (publishManuallyState) {
|
||||
RoomAliasViewState.AddAliasState.Hidden -> RoomAliasViewState.AddAliasState.Hidden
|
||||
RoomAliasViewState.AddAliasState.Closed -> RoomAliasViewState.AddAliasState.Editing("", Uninitialized)
|
||||
is RoomAliasViewState.AddAliasState.Editing -> RoomAliasViewState.AddAliasState.Closed
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSetNewAlias(action: RoomAliasAction.SetNewAlias) {
|
||||
setState {
|
||||
copy(
|
||||
publishManuallyState = RoomAliasViewState.AddAliasState.Editing(action.alias, Uninitialized)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSetNewLocalAliasLocalPart(action: RoomAliasAction.SetNewLocalAliasLocalPart) {
|
||||
setState {
|
||||
copy(
|
||||
newLocalAliasState = RoomAliasViewState.AddAliasState.Editing(action.aliasLocalPart, Uninitialized)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleManualPublishAlias() = withState { state ->
|
||||
val newAlias = (state.publishManuallyState as? RoomAliasViewState.AddAliasState.Editing)?.value ?: return@withState
|
||||
updateCanonicalAlias(
|
||||
canonicalAlias = state.canonicalAlias,
|
||||
alternativeAliases = state.alternativeAliases + newAlias,
|
||||
closeForm = true
|
||||
)
|
||||
}
|
||||
|
||||
private fun handlePublishAlias(action: RoomAliasAction.PublishAlias) = withState { state ->
|
||||
updateCanonicalAlias(
|
||||
canonicalAlias = state.canonicalAlias,
|
||||
alternativeAliases = state.alternativeAliases + action.alias,
|
||||
closeForm = false
|
||||
)
|
||||
}
|
||||
|
||||
private fun handleUnpublishAlias(action: RoomAliasAction.UnpublishAlias) = withState { state ->
|
||||
updateCanonicalAlias(
|
||||
// We can also unpublish the canonical alias
|
||||
canonicalAlias = state.canonicalAlias.takeIf { it != action.alias },
|
||||
alternativeAliases = state.alternativeAliases - action.alias,
|
||||
closeForm = false
|
||||
)
|
||||
}
|
||||
|
||||
private fun handleSetCanonicalAlias(action: RoomAliasAction.SetCanonicalAlias) = withState { state ->
|
||||
updateCanonicalAlias(
|
||||
canonicalAlias = action.canonicalAlias,
|
||||
// Ensure the previous canonical alias is moved to the alt aliases
|
||||
alternativeAliases = state.allPublishedAliases,
|
||||
closeForm = false
|
||||
)
|
||||
}
|
||||
|
||||
private fun updateCanonicalAlias(canonicalAlias: String?, alternativeAliases: List<String>, closeForm: Boolean) {
|
||||
postLoading(true)
|
||||
room.updateCanonicalAlias(canonicalAlias, alternativeAliases, object : MatrixCallback<Unit> {
|
||||
override fun onSuccess(data: Unit) {
|
||||
setState {
|
||||
copy(
|
||||
isLoading = false,
|
||||
publishManuallyState = if (closeForm) RoomAliasViewState.AddAliasState.Closed else publishManuallyState
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
postLoading(false)
|
||||
_viewEvents.post(RoomAliasViewEvents.Failure(failure))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun handleAddLocalAlias() = withState { state ->
|
||||
val previousState = (state.newLocalAliasState as? RoomAliasViewState.AddAliasState.Editing) ?: return@withState
|
||||
|
||||
setState {
|
||||
copy(
|
||||
isLoading = true,
|
||||
newLocalAliasState = previousState.copy(asyncRequest = Loading())
|
||||
)
|
||||
}
|
||||
viewModelScope.launch {
|
||||
runCatching { room.addAlias(previousState.value) }
|
||||
.onFailure {
|
||||
setState {
|
||||
copy(
|
||||
isLoading = false,
|
||||
newLocalAliasState = previousState.copy(asyncRequest = Fail(it))
|
||||
)
|
||||
}
|
||||
_viewEvents.post(RoomAliasViewEvents.Failure(it))
|
||||
}
|
||||
.onSuccess {
|
||||
setState {
|
||||
copy(
|
||||
isLoading = false,
|
||||
newLocalAliasState = RoomAliasViewState.AddAliasState.Closed,
|
||||
// Local echo
|
||||
localAliases = Success((localAliases().orEmpty() + previousState.value).sorted())
|
||||
)
|
||||
}
|
||||
fetchRoomAlias()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleRemoveLocalAlias(action: RoomAliasAction.RemoveLocalAlias) {
|
||||
postLoading(true)
|
||||
viewModelScope.launch {
|
||||
runCatching { session.deleteRoomAlias(action.alias) }
|
||||
.onFailure {
|
||||
setState {
|
||||
copy(isLoading = false)
|
||||
}
|
||||
_viewEvents.post(RoomAliasViewEvents.Failure(it))
|
||||
}
|
||||
.onSuccess {
|
||||
// Local echo
|
||||
setState {
|
||||
copy(
|
||||
isLoading = false,
|
||||
// Local echo
|
||||
localAliases = Success(localAliases().orEmpty() - action.alias)
|
||||
)
|
||||
}
|
||||
fetchRoomAlias()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun postLoading(isLoading: Boolean) {
|
||||
setState {
|
||||
copy(isLoading = isLoading)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright 2020 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.roomprofile.alias
|
||||
|
||||
import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import im.vector.app.features.roomprofile.RoomProfileArgs
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
|
||||
data class RoomAliasViewState(
|
||||
val roomId: String,
|
||||
val homeServerName: String = "",
|
||||
val roomSummary: Async<RoomSummary> = Uninitialized,
|
||||
val actionPermissions: ActionPermissions = ActionPermissions(),
|
||||
val roomDirectoryVisibility: Async<RoomDirectoryVisibility> = Uninitialized,
|
||||
val isLoading: Boolean = false,
|
||||
val canonicalAlias: String? = null,
|
||||
val alternativeAliases: List<String> = emptyList(),
|
||||
val publishManuallyState: AddAliasState = AddAliasState.Hidden,
|
||||
val localAliases: Async<List<String>> = Uninitialized,
|
||||
val newLocalAliasState: AddAliasState = AddAliasState.Closed
|
||||
) : MvRxState {
|
||||
|
||||
constructor(args: RoomProfileArgs) : this(roomId = args.roomId)
|
||||
|
||||
val allPublishedAliases: List<String>
|
||||
get() = (alternativeAliases + listOfNotNull(canonicalAlias)).distinct()
|
||||
|
||||
data class ActionPermissions(
|
||||
val canChangeCanonicalAlias: Boolean = false
|
||||
)
|
||||
|
||||
sealed class AddAliasState {
|
||||
object Hidden : AddAliasState()
|
||||
object Closed : AddAliasState()
|
||||
data class Editing(val value: String, val asyncRequest: Async<Unit> = Uninitialized) : AddAliasState()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* 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.roomprofile.alias.detail
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import butterknife.BindView
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.di.ScreenComponent
|
||||
import im.vector.app.core.extensions.cleanup
|
||||
import im.vector.app.core.extensions.configureWith
|
||||
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import javax.inject.Inject
|
||||
|
||||
@Parcelize
|
||||
data class RoomAliasBottomSheetArgs(
|
||||
val alias: String,
|
||||
val isPublished: Boolean,
|
||||
val isMainAlias: Boolean,
|
||||
val isLocal: Boolean,
|
||||
val canEditCanonicalAlias: Boolean
|
||||
) : Parcelable
|
||||
|
||||
/**
|
||||
* Bottom sheet fragment that shows room alias information with list of contextual actions
|
||||
*/
|
||||
class RoomAliasBottomSheet : VectorBaseBottomSheetDialogFragment(), RoomAliasBottomSheetController.Listener {
|
||||
|
||||
private lateinit var sharedActionViewModel: RoomAliasBottomSheetSharedActionViewModel
|
||||
@Inject lateinit var sharedViewPool: RecyclerView.RecycledViewPool
|
||||
@Inject lateinit var roomAliasBottomSheetViewModelFactory: RoomAliasBottomSheetViewModel.Factory
|
||||
@Inject lateinit var controller: RoomAliasBottomSheetController
|
||||
|
||||
private val viewModel: RoomAliasBottomSheetViewModel by fragmentViewModel(RoomAliasBottomSheetViewModel::class)
|
||||
|
||||
@BindView(R.id.bottomSheetRecyclerView)
|
||||
lateinit var recyclerView: RecyclerView
|
||||
|
||||
override val showExpanded = true
|
||||
|
||||
override fun injectWith(injector: ScreenComponent) {
|
||||
injector.inject(this)
|
||||
}
|
||||
|
||||
override fun getLayoutResId() = R.layout.bottom_sheet_generic_list
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
sharedActionViewModel = activityViewModelProvider.get(RoomAliasBottomSheetSharedActionViewModel::class.java)
|
||||
recyclerView.configureWith(controller, viewPool = sharedViewPool, hasFixedSize = false, disableItemAnimation = true)
|
||||
controller.listener = this
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
recyclerView.cleanup()
|
||||
controller.listener = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun invalidate() = withState(viewModel) {
|
||||
controller.setData(it)
|
||||
super.invalidate()
|
||||
}
|
||||
|
||||
override fun didSelectMenuAction(quickAction: RoomAliasBottomSheetSharedAction) {
|
||||
sharedActionViewModel.post(quickAction)
|
||||
|
||||
dismiss()
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun newInstance(alias: String,
|
||||
isPublished: Boolean,
|
||||
isMainAlias: Boolean,
|
||||
isLocal: Boolean,
|
||||
canEditCanonicalAlias: Boolean): RoomAliasBottomSheet {
|
||||
return RoomAliasBottomSheet().apply {
|
||||
setArguments(RoomAliasBottomSheetArgs(
|
||||
alias = alias,
|
||||
isPublished = isPublished,
|
||||
isMainAlias = isMainAlias,
|
||||
isLocal = isLocal,
|
||||
canEditCanonicalAlias = canEditCanonicalAlias
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* 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.roomprofile.alias.detail
|
||||
|
||||
import android.view.View
|
||||
import com.airbnb.epoxy.TypedEpoxyController
|
||||
import im.vector.app.core.epoxy.bottomsheet.bottomSheetActionItem
|
||||
import im.vector.app.core.epoxy.dividerItem
|
||||
import im.vector.app.core.epoxy.profiles.profileActionItem
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Epoxy controller for room alias actions
|
||||
*/
|
||||
class RoomAliasBottomSheetController @Inject constructor() : TypedEpoxyController<RoomAliasBottomSheetState>() {
|
||||
|
||||
var listener: Listener? = null
|
||||
|
||||
override fun buildModels(state: RoomAliasBottomSheetState) {
|
||||
profileActionItem {
|
||||
id("alias")
|
||||
title(state.alias)
|
||||
subtitle(state.matrixToLink)
|
||||
editable(false)
|
||||
}
|
||||
|
||||
// Notifications
|
||||
dividerItem {
|
||||
id("aliasSeparator")
|
||||
}
|
||||
|
||||
var idx = 0
|
||||
// Share
|
||||
state.matrixToLink?.let {
|
||||
RoomAliasBottomSheetSharedAction.ShareAlias(it).toBottomSheetItem(++idx)
|
||||
}
|
||||
|
||||
// Action on published alias
|
||||
if (state.isPublished) {
|
||||
// Published address
|
||||
if (state.canEditCanonicalAlias) {
|
||||
if (state.isMainAlias) {
|
||||
RoomAliasBottomSheetSharedAction.UnsetMainAlias.toBottomSheetItem(++idx)
|
||||
} else {
|
||||
RoomAliasBottomSheetSharedAction.SetMainAlias(state.alias).toBottomSheetItem(++idx)
|
||||
}
|
||||
RoomAliasBottomSheetSharedAction.UnPublishAlias(state.alias).toBottomSheetItem(++idx)
|
||||
}
|
||||
}
|
||||
|
||||
if (state.isLocal) {
|
||||
// Local address
|
||||
if (state.canEditCanonicalAlias && state.isPublished.not()) {
|
||||
// Publish
|
||||
RoomAliasBottomSheetSharedAction.PublishAlias(state.alias).toBottomSheetItem(++idx)
|
||||
}
|
||||
// Delete
|
||||
RoomAliasBottomSheetSharedAction.DeleteAlias(state.alias).toBottomSheetItem(++idx)
|
||||
}
|
||||
}
|
||||
|
||||
private fun RoomAliasBottomSheetSharedAction.toBottomSheetItem(index: Int) {
|
||||
return bottomSheetActionItem {
|
||||
id("action_$index")
|
||||
iconRes(iconResId)
|
||||
textRes(titleRes)
|
||||
destructive(this@toBottomSheetItem.destructive)
|
||||
listener(View.OnClickListener { listener?.didSelectMenuAction(this@toBottomSheetItem) })
|
||||
}
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
fun didSelectMenuAction(quickAction: RoomAliasBottomSheetSharedAction)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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.roomprofile.alias.detail
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.platform.VectorSharedAction
|
||||
|
||||
sealed class RoomAliasBottomSheetSharedAction(
|
||||
@StringRes val titleRes: Int,
|
||||
@DrawableRes val iconResId: Int = 0,
|
||||
val destructive: Boolean = false)
|
||||
: VectorSharedAction {
|
||||
|
||||
data class ShareAlias(val matrixTo: String) : RoomAliasBottomSheetSharedAction(
|
||||
R.string.share,
|
||||
R.drawable.ic_material_share
|
||||
)
|
||||
|
||||
data class PublishAlias(val alias: String) : RoomAliasBottomSheetSharedAction(
|
||||
R.string.room_alias_action_publish
|
||||
)
|
||||
|
||||
data class UnPublishAlias(val alias: String) : RoomAliasBottomSheetSharedAction(
|
||||
R.string.room_alias_action_unpublish
|
||||
)
|
||||
|
||||
data class DeleteAlias(val alias: String) : RoomAliasBottomSheetSharedAction(
|
||||
R.string.delete,
|
||||
R.drawable.ic_trash_24,
|
||||
true
|
||||
)
|
||||
|
||||
data class SetMainAlias(val alias: String) : RoomAliasBottomSheetSharedAction(
|
||||
R.string.room_settings_set_main_address
|
||||
)
|
||||
|
||||
object UnsetMainAlias : RoomAliasBottomSheetSharedAction(
|
||||
R.string.room_settings_unset_main_address
|
||||
)
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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.roomprofile.alias.detail
|
||||
|
||||
import im.vector.app.core.platform.VectorSharedActionViewModel
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Activity shared view model to handle room alias quick actions
|
||||
*/
|
||||
class RoomAliasBottomSheetSharedActionViewModel @Inject constructor() : VectorSharedActionViewModel<RoomAliasBottomSheetSharedAction>()
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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.roomprofile.alias.detail
|
||||
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
|
||||
data class RoomAliasBottomSheetState(
|
||||
val alias: String,
|
||||
val matrixToLink: String? = null,
|
||||
val isPublished: Boolean,
|
||||
val isMainAlias: Boolean,
|
||||
val isLocal: Boolean,
|
||||
val canEditCanonicalAlias: Boolean
|
||||
) : MvRxState {
|
||||
|
||||
constructor(args: RoomAliasBottomSheetArgs) : this(
|
||||
alias = args.alias,
|
||||
isPublished = args.isPublished,
|
||||
isMainAlias = args.isMainAlias,
|
||||
isLocal = args.isLocal,
|
||||
canEditCanonicalAlias = args.canEditCanonicalAlias
|
||||
)
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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.roomprofile.alias.detail
|
||||
|
||||
import com.airbnb.mvrx.FragmentViewModelContext
|
||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.app.core.platform.EmptyAction
|
||||
import im.vector.app.core.platform.EmptyViewEvents
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
|
||||
class RoomAliasBottomSheetViewModel @AssistedInject constructor(
|
||||
@Assisted initialState: RoomAliasBottomSheetState,
|
||||
session: Session
|
||||
) : VectorViewModel<RoomAliasBottomSheetState, EmptyAction, EmptyViewEvents>(initialState) {
|
||||
|
||||
@AssistedInject.Factory
|
||||
interface Factory {
|
||||
fun create(initialState: RoomAliasBottomSheetState): RoomAliasBottomSheetViewModel
|
||||
}
|
||||
|
||||
companion object : MvRxViewModelFactory<RoomAliasBottomSheetViewModel, RoomAliasBottomSheetState> {
|
||||
|
||||
@JvmStatic
|
||||
override fun create(viewModelContext: ViewModelContext, state: RoomAliasBottomSheetState): RoomAliasBottomSheetViewModel? {
|
||||
val fragment: RoomAliasBottomSheet = (viewModelContext as FragmentViewModelContext).fragment()
|
||||
return fragment.roomAliasBottomSheetViewModelFactory.create(state)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
setState {
|
||||
copy(
|
||||
matrixToLink = session.permalinkService().createPermalink(alias)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun handle(action: EmptyAction) {
|
||||
// No op
|
||||
}
|
||||
}
|
|
@ -19,8 +19,8 @@ package im.vector.app.features.roomprofile.banned
|
|||
import im.vector.app.core.platform.VectorViewModelAction
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||
|
||||
sealed class RoomBannedListMemberAction : VectorViewModelAction {
|
||||
data class QueryInfo(val roomMemberSummary: RoomMemberSummary) : RoomBannedListMemberAction()
|
||||
data class UnBanUser(val roomMemberSummary: RoomMemberSummary) : RoomBannedListMemberAction()
|
||||
data class Filter(val filter: String) : RoomBannedListMemberAction()
|
||||
sealed class RoomBannedMemberListAction : VectorViewModelAction {
|
||||
data class QueryInfo(val roomMemberSummary: RoomMemberSummary) : RoomBannedMemberListAction()
|
||||
data class UnBanUser(val roomMemberSummary: RoomMemberSummary) : RoomBannedMemberListAction()
|
||||
data class Filter(val filter: String) : RoomBannedMemberListAction()
|
||||
}
|
|
@ -37,18 +37,18 @@ import org.matrix.android.sdk.api.util.toMatrixItem
|
|||
import javax.inject.Inject
|
||||
|
||||
class RoomBannedMemberListFragment @Inject constructor(
|
||||
val viewModelFactory: RoomBannedListMemberViewModel.Factory,
|
||||
val viewModelFactory: RoomBannedMemberListViewModel.Factory,
|
||||
private val roomMemberListController: RoomBannedMemberListController,
|
||||
private val avatarRenderer: AvatarRenderer
|
||||
) : VectorBaseFragment(), RoomBannedMemberListController.Callback {
|
||||
|
||||
private val viewModel: RoomBannedListMemberViewModel by fragmentViewModel()
|
||||
private val viewModel: RoomBannedMemberListViewModel by fragmentViewModel()
|
||||
private val roomProfileArgs: RoomProfileArgs by args()
|
||||
|
||||
override fun getLayoutResId() = R.layout.fragment_room_setting_generic
|
||||
|
||||
override fun onUnbanClicked(roomMember: RoomMemberSummary) {
|
||||
viewModel.handle(RoomBannedListMemberAction.QueryInfo(roomMember))
|
||||
viewModel.handle(RoomBannedMemberListAction.QueryInfo(roomMember))
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
|
@ -60,7 +60,7 @@ class RoomBannedMemberListFragment @Inject constructor(
|
|||
|
||||
viewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is RoomBannedViewEvents.ShowBannedInfo -> {
|
||||
is RoomBannedMemberListViewEvents.ShowBannedInfo -> {
|
||||
val canBan = withState(viewModel) { state -> state.canUserBan }
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(getString(R.string.member_banned_by, it.bannedByUserId))
|
||||
|
@ -69,13 +69,13 @@ class RoomBannedMemberListFragment @Inject constructor(
|
|||
.apply {
|
||||
if (canBan) {
|
||||
setNegativeButton(R.string.room_participants_action_unban) { _, _ ->
|
||||
viewModel.handle(RoomBannedListMemberAction.UnBanUser(it.roomMemberSummary))
|
||||
viewModel.handle(RoomBannedMemberListAction.UnBanUser(it.roomMemberSummary))
|
||||
}
|
||||
}
|
||||
}
|
||||
.show()
|
||||
}
|
||||
is RoomBannedViewEvents.ToastError -> {
|
||||
is RoomBannedMemberListViewEvents.ToastError -> {
|
||||
requireActivity().toast(it.info)
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ class RoomBannedMemberListFragment @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onQueryTextChange(newText: String): Boolean {
|
||||
viewModel.handle(RoomBannedListMemberAction.Filter(newText))
|
||||
viewModel.handle(RoomBannedMemberListAction.Filter(newText))
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
|
|
@ -19,7 +19,7 @@ package im.vector.app.features.roomprofile.banned
|
|||
import im.vector.app.core.platform.VectorViewEvents
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||
|
||||
sealed class RoomBannedViewEvents : VectorViewEvents {
|
||||
data class ShowBannedInfo(val bannedByUserId: String, val banReason: String, val roomMemberSummary: RoomMemberSummary) : RoomBannedViewEvents()
|
||||
data class ToastError(val info: String) : RoomBannedViewEvents()
|
||||
sealed class RoomBannedMemberListViewEvents : VectorViewEvents {
|
||||
data class ShowBannedInfo(val bannedByUserId: String, val banReason: String, val roomMemberSummary: RoomMemberSummary) : RoomBannedMemberListViewEvents()
|
||||
data class ToastError(val info: String) : RoomBannedMemberListViewEvents()
|
||||
}
|
|
@ -42,14 +42,14 @@ import org.matrix.android.sdk.internal.util.awaitCallback
|
|||
import org.matrix.android.sdk.rx.rx
|
||||
import org.matrix.android.sdk.rx.unwrap
|
||||
|
||||
class RoomBannedListMemberViewModel @AssistedInject constructor(@Assisted initialState: RoomBannedMemberListViewState,
|
||||
class RoomBannedMemberListViewModel @AssistedInject constructor(@Assisted initialState: RoomBannedMemberListViewState,
|
||||
private val stringProvider: StringProvider,
|
||||
private val session: Session)
|
||||
: VectorViewModel<RoomBannedMemberListViewState, RoomBannedListMemberAction, RoomBannedViewEvents>(initialState) {
|
||||
: VectorViewModel<RoomBannedMemberListViewState, RoomBannedMemberListAction, RoomBannedMemberListViewEvents>(initialState) {
|
||||
|
||||
@AssistedInject.Factory
|
||||
interface Factory {
|
||||
fun create(initialState: RoomBannedMemberListViewState): RoomBannedListMemberViewModel
|
||||
fun create(initialState: RoomBannedMemberListViewState): RoomBannedMemberListViewModel
|
||||
}
|
||||
|
||||
private val room = session.getRoom(initialState.roomId)!!
|
||||
|
@ -78,24 +78,24 @@ class RoomBannedListMemberViewModel @AssistedInject constructor(@Assisted initia
|
|||
}.disposeOnClear()
|
||||
}
|
||||
|
||||
companion object : MvRxViewModelFactory<RoomBannedListMemberViewModel, RoomBannedMemberListViewState> {
|
||||
companion object : MvRxViewModelFactory<RoomBannedMemberListViewModel, RoomBannedMemberListViewState> {
|
||||
|
||||
@JvmStatic
|
||||
override fun create(viewModelContext: ViewModelContext, state: RoomBannedMemberListViewState): RoomBannedListMemberViewModel? {
|
||||
override fun create(viewModelContext: ViewModelContext, state: RoomBannedMemberListViewState): RoomBannedMemberListViewModel? {
|
||||
val fragment: RoomBannedMemberListFragment = (viewModelContext as FragmentViewModelContext).fragment()
|
||||
return fragment.viewModelFactory.create(state)
|
||||
}
|
||||
}
|
||||
|
||||
override fun handle(action: RoomBannedListMemberAction) {
|
||||
override fun handle(action: RoomBannedMemberListAction) {
|
||||
when (action) {
|
||||
is RoomBannedListMemberAction.QueryInfo -> onQueryBanInfo(action.roomMemberSummary)
|
||||
is RoomBannedListMemberAction.UnBanUser -> unBanUser(action.roomMemberSummary)
|
||||
is RoomBannedListMemberAction.Filter -> handleFilter(action)
|
||||
is RoomBannedMemberListAction.QueryInfo -> onQueryBanInfo(action.roomMemberSummary)
|
||||
is RoomBannedMemberListAction.UnBanUser -> unBanUser(action.roomMemberSummary)
|
||||
is RoomBannedMemberListAction.Filter -> handleFilter(action)
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
private fun handleFilter(action: RoomBannedListMemberAction.Filter) {
|
||||
private fun handleFilter(action: RoomBannedMemberListAction.Filter) {
|
||||
setState {
|
||||
copy(
|
||||
filter = action.filter
|
||||
|
@ -114,7 +114,7 @@ class RoomBannedListMemberViewModel @AssistedInject constructor(@Assisted initia
|
|||
val reason = content.reason
|
||||
val bannedBy = bannedEvent?.senderId ?: return
|
||||
|
||||
_viewEvents.post(RoomBannedViewEvents.ShowBannedInfo(bannedBy, reason ?: "", roomMemberSummary))
|
||||
_viewEvents.post(RoomBannedMemberListViewEvents.ShowBannedInfo(bannedBy, reason ?: "", roomMemberSummary))
|
||||
}
|
||||
|
||||
private fun unBanUser(roomMemberSummary: RoomMemberSummary) {
|
||||
|
@ -127,7 +127,7 @@ class RoomBannedListMemberViewModel @AssistedInject constructor(@Assisted initia
|
|||
room.unban(roomMemberSummary.userId, null, it)
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
_viewEvents.post(RoomBannedViewEvents.ToastError(stringProvider.getString(R.string.failed_to_unban)))
|
||||
_viewEvents.post(RoomBannedMemberListViewEvents.ToastError(stringProvider.getString(R.string.failed_to_unban)))
|
||||
} finally {
|
||||
setState {
|
||||
copy(
|
|
@ -24,7 +24,6 @@ sealed class RoomSettingsAction : VectorViewModelAction {
|
|||
data class SetRoomName(val newName: String) : RoomSettingsAction()
|
||||
data class SetRoomTopic(val newTopic: String) : RoomSettingsAction()
|
||||
data class SetRoomHistoryVisibility(val visibility: RoomHistoryVisibility) : RoomSettingsAction()
|
||||
data class SetRoomCanonicalAlias(val newCanonicalAlias: String) : RoomSettingsAction()
|
||||
object Save : RoomSettingsAction()
|
||||
object Cancel : RoomSettingsAction()
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ class RoomSettingsController @Inject constructor(
|
|||
fun onNameChanged(name: String)
|
||||
fun onTopicChanged(topic: String)
|
||||
fun onHistoryVisibilityClicked()
|
||||
fun onAliasChanged(alias: String)
|
||||
fun onRoomAliasesClicked()
|
||||
}
|
||||
|
||||
private val dividerColor = colorProvider.getColorFromAttribute(R.attr.vctr_list_divider_color)
|
||||
|
@ -67,13 +67,13 @@ class RoomSettingsController @Inject constructor(
|
|||
id("avatar")
|
||||
enabled(data.actionPermissions.canChangeAvatar)
|
||||
when (val avatarAction = data.avatarAction) {
|
||||
RoomSettingsViewState.AvatarAction.None -> {
|
||||
RoomSettingsViewState.AvatarAction.None -> {
|
||||
// Use the current value
|
||||
avatarRenderer(avatarRenderer)
|
||||
// We do not want to use the fallback avatar url, which can be the other user avatar, or the current user avatar.
|
||||
matrixItem(roomSummary.toMatrixItem().copy(avatarUrl = data.currentRoomAvatarUrl))
|
||||
}
|
||||
RoomSettingsViewState.AvatarAction.DeleteAvatar ->
|
||||
RoomSettingsViewState.AvatarAction.DeleteAvatar ->
|
||||
imageUri(null)
|
||||
is RoomSettingsViewState.AvatarAction.UpdateAvatar ->
|
||||
imageUri(avatarAction.newAvatarUri)
|
||||
|
@ -108,16 +108,15 @@ class RoomSettingsController @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
formEditTextItem {
|
||||
id("alias")
|
||||
enabled(data.actionPermissions.canChangeCanonicalAlias)
|
||||
value(data.newCanonicalAlias ?: roomSummary.canonicalAlias)
|
||||
hint(stringProvider.getString(R.string.room_settings_addresses_add_new_address))
|
||||
|
||||
onTextChange { text ->
|
||||
callback?.onAliasChanged(text)
|
||||
}
|
||||
}
|
||||
buildProfileAction(
|
||||
id = "alias",
|
||||
title = stringProvider.getString(R.string.room_settings_alias_title),
|
||||
subtitle = stringProvider.getString(R.string.room_settings_alias_subtitle),
|
||||
dividerColor = dividerColor,
|
||||
divider = true,
|
||||
editable = true,
|
||||
action = { callback?.onRoomAliasesClicked() }
|
||||
)
|
||||
|
||||
buildProfileAction(
|
||||
id = "historyReadability",
|
||||
|
|
|
@ -39,6 +39,8 @@ import im.vector.app.core.utils.toast
|
|||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.home.room.detail.timeline.format.RoomHistoryVisibilityFormatter
|
||||
import im.vector.app.features.roomprofile.RoomProfileArgs
|
||||
import im.vector.app.features.roomprofile.RoomProfileSharedAction
|
||||
import im.vector.app.features.roomprofile.RoomProfileSharedActionViewModel
|
||||
import kotlinx.android.synthetic.main.fragment_room_setting_generic.*
|
||||
import kotlinx.android.synthetic.main.merge_overlay_waiting_view.*
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
|
@ -61,6 +63,7 @@ class RoomSettingsFragment @Inject constructor(
|
|||
GalleryOrCameraDialogHelper.Listener {
|
||||
|
||||
private val viewModel: RoomSettingsViewModel by fragmentViewModel()
|
||||
private lateinit var roomProfileSharedActionViewModel: RoomProfileSharedActionViewModel
|
||||
private val roomProfileArgs: RoomProfileArgs by args()
|
||||
private val galleryOrCameraDialogHelper = GalleryOrCameraDialogHelper(this, colorProvider)
|
||||
|
||||
|
@ -70,6 +73,7 @@ class RoomSettingsFragment @Inject constructor(
|
|||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
roomProfileSharedActionViewModel = activityViewModelProvider.get(RoomProfileSharedActionViewModel::class.java)
|
||||
controller.callback = this
|
||||
setupToolbar(roomSettingsToolbar)
|
||||
roomSettingsRecyclerView.configureWith(controller, hasFixedSize = true)
|
||||
|
@ -164,8 +168,8 @@ class RoomSettingsFragment @Inject constructor(
|
|||
return@withState
|
||||
}
|
||||
|
||||
override fun onAliasChanged(alias: String) {
|
||||
viewModel.handle(RoomSettingsAction.SetRoomCanonicalAlias(alias))
|
||||
override fun onRoomAliasesClicked() {
|
||||
roomProfileSharedActionViewModel.post(RoomProfileSharedAction.OpenRoomAliasesSettings)
|
||||
}
|
||||
|
||||
override fun onImageReady(uri: Uri?) {
|
||||
|
|
|
@ -68,12 +68,10 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState:
|
|||
selectSubscribe(
|
||||
RoomSettingsViewState::avatarAction,
|
||||
RoomSettingsViewState::newName,
|
||||
RoomSettingsViewState::newCanonicalAlias,
|
||||
RoomSettingsViewState::newTopic,
|
||||
RoomSettingsViewState::newHistoryVisibility,
|
||||
RoomSettingsViewState::roomSummary) { avatarAction,
|
||||
newName,
|
||||
newCanonicalAlias,
|
||||
newTopic,
|
||||
newHistoryVisibility,
|
||||
asyncSummary ->
|
||||
|
@ -83,7 +81,6 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState:
|
|||
showSaveAction = avatarAction !is RoomSettingsViewState.AvatarAction.None
|
||||
|| summary?.name != newName
|
||||
|| summary?.topic != newTopic
|
||||
|| summary?.canonicalAlias != newCanonicalAlias?.takeIf { it.isNotEmpty() }
|
||||
|| newHistoryVisibility != null
|
||||
)
|
||||
}
|
||||
|
@ -99,8 +96,7 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState:
|
|||
historyVisibilityEvent = room.getStateEvent(EventType.STATE_ROOM_HISTORY_VISIBILITY),
|
||||
roomSummary = async,
|
||||
newName = roomSummary?.name,
|
||||
newTopic = roomSummary?.topic,
|
||||
newCanonicalAlias = roomSummary?.canonicalAlias
|
||||
newTopic = roomSummary?.topic
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -113,8 +109,6 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState:
|
|||
canChangeAvatar = powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_AVATAR),
|
||||
canChangeName = powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_NAME),
|
||||
canChangeTopic = powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_TOPIC),
|
||||
canChangeCanonicalAlias = powerLevelsHelper.isUserAllowedToSend(session.myUserId, true,
|
||||
EventType.STATE_ROOM_CANONICAL_ALIAS),
|
||||
canChangeHistoryReadability = powerLevelsHelper.isUserAllowedToSend(session.myUserId, true,
|
||||
EventType.STATE_ROOM_HISTORY_VISIBILITY)
|
||||
)
|
||||
|
@ -143,7 +137,6 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState:
|
|||
is RoomSettingsAction.SetRoomName -> setState { copy(newName = action.newName) }
|
||||
is RoomSettingsAction.SetRoomTopic -> setState { copy(newTopic = action.newTopic) }
|
||||
is RoomSettingsAction.SetRoomHistoryVisibility -> setState { copy(newHistoryVisibility = action.visibility) }
|
||||
is RoomSettingsAction.SetRoomCanonicalAlias -> setState { copy(newCanonicalAlias = action.newCanonicalAlias) }
|
||||
is RoomSettingsAction.Save -> saveSettings()
|
||||
is RoomSettingsAction.Cancel -> cancel()
|
||||
}.exhaustive
|
||||
|
@ -191,11 +184,6 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState:
|
|||
operationList.add(room.rx().updateTopic(state.newTopic ?: ""))
|
||||
}
|
||||
|
||||
if (state.newCanonicalAlias != null && summary?.canonicalAlias != state.newCanonicalAlias.takeIf { it.isNotEmpty() }) {
|
||||
operationList.add(room.rx().addRoomAlias(state.newCanonicalAlias))
|
||||
operationList.add(room.rx().updateCanonicalAlias(state.newCanonicalAlias))
|
||||
}
|
||||
|
||||
if (state.newHistoryVisibility != null) {
|
||||
operationList.add(room.rx().updateHistoryReadability(state.newHistoryVisibility))
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ data class RoomSettingsViewState(
|
|||
val newName: String? = null,
|
||||
val newTopic: String? = null,
|
||||
val newHistoryVisibility: RoomHistoryVisibility? = null,
|
||||
val newCanonicalAlias: String? = null,
|
||||
val showSaveAction: Boolean = false,
|
||||
val actionPermissions: ActionPermissions = ActionPermissions()
|
||||
) : MvRxState {
|
||||
|
@ -46,7 +45,6 @@ data class RoomSettingsViewState(
|
|||
val canChangeAvatar: Boolean = false,
|
||||
val canChangeName: Boolean = false,
|
||||
val canChangeTopic: Boolean = false,
|
||||
val canChangeCanonicalAlias: Boolean = false,
|
||||
val canChangeHistoryReadability: Boolean = false
|
||||
)
|
||||
|
||||
|
|
|
@ -1,41 +1,47 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M2.25,5.5H5.1667H21.75"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#2E2F32"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M16.5,5.5L15,1H9L7.5,5.5"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#2E2F32"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M5.25,9.25V20.75C5.25,21.8546 6.1454,22.75 7.25,22.75H16.75C17.8546,22.75 18.75,21.8546 18.75,20.75V9.25"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#2E2F32"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M9.75,9.25V18.25"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#2E2F32"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M14.25,9.25V18.25"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#2E2F32"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M2.25,5.5H5.1667H21.75"
|
||||
android:strokeWidth="2"
|
||||
android:strokeColor="#2E2F32"
|
||||
android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round"
|
||||
tools:strokeColor="@color/riotx_destructive_accent" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M16.5,5.5L15,1H9L7.5,5.5"
|
||||
android:strokeWidth="2"
|
||||
android:strokeColor="#2E2F32"
|
||||
android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round"
|
||||
tools:strokeColor="@color/riotx_destructive_accent" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M5.25,9.25V20.75C5.25,21.8546 6.1454,22.75 7.25,22.75H16.75C17.8546,22.75 18.75,21.8546 18.75,20.75V9.25"
|
||||
android:strokeWidth="2"
|
||||
android:strokeColor="#2E2F32"
|
||||
android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round"
|
||||
tools:strokeColor="@color/riotx_destructive_accent" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9.75,9.25V18.25"
|
||||
android:strokeWidth="2"
|
||||
android:strokeColor="#2E2F32"
|
||||
android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round"
|
||||
tools:strokeColor="@color/riotx_destructive_accent" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M14.25,9.25V18.25"
|
||||
android:strokeWidth="2"
|
||||
android:strokeColor="#2E2F32"
|
||||
android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round"
|
||||
tools:strokeColor="@color/riotx_destructive_accent" />
|
||||
</vector>
|
||||
|
|
|
@ -20,10 +20,12 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<!-- android:imeOptions="actionDone" to fix a crash -->
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/formTextInputTextInputEditText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:imeOptions="actionDone"
|
||||
tools:hint="@string/create_room_name_hint" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
|
|
@ -30,11 +30,13 @@
|
|||
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>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?riotx_background"
|
||||
android:minHeight="64dp"
|
||||
android:paddingStart="@dimen/layout_horizontal_margin"
|
||||
android:paddingEnd="@dimen/layout_horizontal_margin">
|
||||
|
@ -12,19 +13,20 @@
|
|||
android:id="@+id/item_settings_three_pid_icon"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:scaleType="center"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/item_settings_three_pid_title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@drawable/ic_phone"
|
||||
app:tint="?riotx_text_secondary"
|
||||
tools:ignore="MissingPrefix" />
|
||||
tools:ignore="MissingPrefix"
|
||||
tools:src="@drawable/ic_phone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_settings_three_pid_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:textColor="?riotx_text_primary"
|
||||
android:textSize="16sp"
|
||||
|
|
|
@ -137,6 +137,8 @@
|
|||
<string name="action_open">Open</string>
|
||||
<string name="action_close">Close</string>
|
||||
<string name="action_copy">Copy</string>
|
||||
<string name="action_add">Add</string>
|
||||
<string name="action_unpublish">Unpublish</string>
|
||||
<string name="copied_to_clipboard">Copied to clipboard</string>
|
||||
<string name="disable">Disable</string>
|
||||
|
||||
|
@ -1022,6 +1024,40 @@
|
|||
<string name="room_settings_room_read_history_rules_pref_dialog_title">Who can read history?</string>
|
||||
<string name="room_settings_room_access_rules_pref_dialog_title">Who can access this room?</string>
|
||||
|
||||
<!-- room settings : alias -->
|
||||
<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_alias_title">Room Addresses</string>
|
||||
<string name="room_alias_published_alias_title">Published Addresses</string>
|
||||
<string name="room_alias_published_alias_subtitle">Published addresses can be used by anyone on any server to join your room. To publish an address, it needs to be set as a local address first.</string>
|
||||
<string name="room_alias_published_alias_main">This is the main address</string>
|
||||
<string name="room_alias_main_address_hint">Main address</string>
|
||||
<string name="room_alias_published_other">Other published addresses:</string>
|
||||
<string name="room_alias_published_alias_add_manually">Publish a new address manually</string>
|
||||
<string name="room_alias_published_alias_add_manually_submit">Publish</string>
|
||||
<string name="room_alias_unpublish_confirmation">Unpublish the address \"%1$s\"?</string>
|
||||
<string name="room_alias_delete_confirmation">Delete the address \"%1$s\"?</string>
|
||||
<!-- Parameter will be the url of the homeserver, ex: matrix.org -->
|
||||
<string name="room_alias_publish">Publish this room to the public in %1$s\'s room directory?</string>
|
||||
<string name="room_alias_address_empty_can_add">No other published addresses yet, add one below.</string>
|
||||
<string name="room_alias_address_empty">No other published addresses yet.</string>
|
||||
<string name="room_alias_address_hint">New published address (e.g. #alias:server)</string>
|
||||
|
||||
<string name="room_alias_local_address_title">Local Addresses</string>
|
||||
<!-- Parameter will be the url of the homeserver, ex: matrix.org -->
|
||||
<string name="room_alias_local_address_subtitle">Set addresses for this room so users can find this room through your homeserver (%1$s)</string>
|
||||
<string name="room_alias_local_address_empty">This room has no local addresses</string>
|
||||
<string name="room_alias_local_address_add">Add a local address</string>
|
||||
|
||||
<string name="room_alias_action_publish">Publish this address</string>
|
||||
<string name="room_alias_action_unpublish">Unpublish this address</string>
|
||||
|
||||
<!-- Parameter will be the url of the homeserver, ex: matrix.org -->
|
||||
<string name="room_alias_publish_to_directory">Publish this room to the public in %1$s\'s room directory?</string>
|
||||
<!-- Parameter will be a technical error message -->
|
||||
<string name="room_alias_publish_to_directory_error">Unable to retrieve the current room directory visibility (%1$s).</string>
|
||||
|
||||
<!-- Room settings, access and visibility : WHO CAN READ HISTORY? (read rule) -->
|
||||
<string name="room_settings_read_history_entry_anyone">Anyone</string>
|
||||
<string name="room_settings_read_history_entry_members_only_option_time_shared">Members only (since the point in time of selecting this option)</string>
|
||||
|
@ -1068,8 +1104,8 @@
|
|||
<string name="room_settings_addresses_disable_main_address_prompt_msg">You will have no main address specified for this room."</string>
|
||||
<string name="room_settings_addresses_disable_main_address_prompt_title">Main address warnings</string>
|
||||
|
||||
<string name="room_settings_set_main_address">Set as Main Address</string>
|
||||
<string name="room_settings_unset_main_address">Unset as Main Address</string>
|
||||
<string name="room_settings_set_main_address">Set as main address</string>
|
||||
<string name="room_settings_unset_main_address">Unset as main address</string>
|
||||
<string name="room_settings_copy_room_id">Copy Room ID</string>
|
||||
<string name="room_settings_copy_room_address">Copy Room Address</string>
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue