diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/Room.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/Room.kt index cdc971fd..c2e69d33 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/Room.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/Room.kt @@ -21,12 +21,13 @@ import im.vector.matrix.android.api.session.room.members.RoomMembersService import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.read.ReadService import im.vector.matrix.android.api.session.room.send.SendService +import im.vector.matrix.android.api.session.room.state.StateService import im.vector.matrix.android.api.session.room.timeline.TimelineService /** * This interface defines methods to interact within a room. */ -interface Room : TimelineService, SendService, ReadService, RoomMembersService { +interface Room : TimelineService, SendService, ReadService, RoomMembersService, StateService { /** * The roomId of this room diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/send/SendService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/send/SendService.kt index fe4cb200..7ab9495b 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/send/SendService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/send/SendService.kt @@ -18,6 +18,7 @@ package im.vector.matrix.android.api.session.room.send import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.events.model.Event +import im.vector.matrix.android.api.session.room.model.message.MessageType import im.vector.matrix.android.api.util.Cancelable /** @@ -28,10 +29,13 @@ interface SendService { /** * Method to send a text message asynchronously. * @param text the text message to send + * @param msgType the message type: MessageType.MSGTYPE_TEXT (default) or MessageType.MSGTYPE_EMOTE * @param callback the callback to be notified. * @return a [Cancelable] */ - fun sendTextMessage(text: String, callback: MatrixCallback): Cancelable + fun sendTextMessage(text: String, + msgType: String = MessageType.MSGTYPE_TEXT, + callback: MatrixCallback): Cancelable } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/state/StateService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/state/StateService.kt new file mode 100644 index 00000000..79443d0b --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/state/StateService.kt @@ -0,0 +1,28 @@ +/* + * 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.matrix.android.api.session.room.state + +import im.vector.matrix.android.api.MatrixCallback + +interface StateService { + + /** + * Update the topic of the room + */ + fun updateTopic(topic: String, callback: MatrixCallback) + +} \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt index 952a1eca..d67072d1 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt @@ -24,6 +24,7 @@ import im.vector.matrix.android.api.session.room.members.RoomMembersService import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.read.ReadService import im.vector.matrix.android.api.session.room.send.SendService +import im.vector.matrix.android.api.session.room.state.StateService import im.vector.matrix.android.api.session.room.timeline.TimelineService import im.vector.matrix.android.internal.database.RealmLiveData import im.vector.matrix.android.internal.database.mapper.asDomain @@ -36,13 +37,13 @@ internal class DefaultRoom( private val monarchy: Monarchy, private val timelineService: TimelineService, private val sendService: SendService, + private val stateService: StateService, private val readService: ReadService, private val roomMembersService: RoomMembersService - - ) : Room, TimelineService by timelineService, SendService by sendService, + StateService by stateService, ReadService by readService, RoomMembersService by roomMembersService { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAPI.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAPI.kt index 1b89662d..c3617504 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAPI.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAPI.kt @@ -131,4 +131,29 @@ internal interface RoomAPI { @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/invite") fun invite(@Path("roomId") roomId: String, @Body body: InviteBody): Call + /** + * Send a generic state events + * + * @param roomId the room id. + * @param stateEventType the state event type + * @param params the request parameters + */ + @PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/state/{state_event_type}") + fun sendStateEvent(@Path("roomId") roomId: String, + @Path("state_event_type") stateEventType: String, + @Body params: Map): Call + + /** + * Send a generic state events + * + * @param roomId the room id. + * @param stateEventType the state event type + * @param stateKey the state keys + * @param params the request parameters + */ + @PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/state/{state_event_type}/{state_key}") + fun sendStateEvent(@Path("roomId") roomId: String, + @Path("state_event_type") stateEventType: String, + @Path("state_key") stateKey: String, + @Body params: Map): Call } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt index 720d3804..a92714f4 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomFactory.kt @@ -26,6 +26,8 @@ import im.vector.matrix.android.internal.session.room.read.DefaultReadService import im.vector.matrix.android.internal.session.room.read.SetReadMarkersTask import im.vector.matrix.android.internal.session.room.send.DefaultSendService import im.vector.matrix.android.internal.session.room.send.EventFactory +import im.vector.matrix.android.internal.session.room.state.DefaultStateService +import im.vector.matrix.android.internal.session.room.state.SendStateTask import im.vector.matrix.android.internal.session.room.timeline.DefaultTimelineService import im.vector.matrix.android.internal.session.room.timeline.GetContextOfEventTask import im.vector.matrix.android.internal.session.room.timeline.PaginationTask @@ -34,6 +36,7 @@ import im.vector.matrix.android.internal.task.TaskExecutor internal class RoomFactory(private val loadRoomMembersTask: LoadRoomMembersTask, private val inviteTask: InviteTask, + private val sendStateTask: SendStateTask, private val monarchy: Monarchy, private val paginationTask: PaginationTask, private val contextOfEventTask: GetContextOfEventTask, @@ -46,6 +49,7 @@ internal class RoomFactory(private val loadRoomMembersTask: LoadRoomMembersTask, val timelineEventFactory = TimelineEventFactory(roomMemberExtractor) val timelineService = DefaultTimelineService(roomId, monarchy, taskExecutor, contextOfEventTask, timelineEventFactory, paginationTask) val sendService = DefaultSendService(roomId, eventFactory, monarchy) + val stateService = DefaultStateService(roomId, sendStateTask, taskExecutor) val roomMembersService = DefaultRoomMembersService(roomId, monarchy, loadRoomMembersTask, inviteTask, taskExecutor) val readService = DefaultReadService(roomId, monarchy, setReadMarkersTask, taskExecutor) @@ -54,6 +58,7 @@ internal class RoomFactory(private val loadRoomMembersTask: LoadRoomMembersTask, monarchy, timelineService, sendService, + stateService, readService, roomMembersService ) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt index ccdfe9ad..78cf1eed 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt @@ -26,6 +26,8 @@ import im.vector.matrix.android.internal.session.room.members.LoadRoomMembersTas import im.vector.matrix.android.internal.session.room.read.DefaultSetReadMarkersTask import im.vector.matrix.android.internal.session.room.read.SetReadMarkersTask import im.vector.matrix.android.internal.session.room.send.EventFactory +import im.vector.matrix.android.internal.session.room.state.DefaultSendStateTask +import im.vector.matrix.android.internal.session.room.state.SendStateTask import im.vector.matrix.android.internal.session.room.timeline.* import org.koin.dsl.module.module import retrofit2.Retrofit @@ -65,7 +67,7 @@ class RoomModule { } scope(DefaultSession.SCOPE) { - RoomFactory(get(), get(), get(), get(), get(), get(), get(), get()) + RoomFactory(get(), get(), get(), get(), get(), get(), get(), get(), get()) } scope(DefaultSession.SCOPE) { @@ -76,5 +78,9 @@ class RoomModule { DefaultInviteTask(get()) as InviteTask } + scope(DefaultSession.SCOPE) { + DefaultSendStateTask(get()) as SendStateTask + } + } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt index 5480cced..42749511 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt @@ -42,8 +42,8 @@ internal class DefaultSendService(private val roomId: String, .build() // TODO callback is not used - override fun sendTextMessage(text: String, callback: MatrixCallback): Cancelable { - val event = eventFactory.createTextEvent(roomId, text) + override fun sendTextMessage(text: String, msgType: String, callback: MatrixCallback): Cancelable { + val event = eventFactory.createTextEvent(roomId, msgType, text) monarchy.tryTransactionAsync { realm -> val chunkEntity = ChunkEntity.findLastLiveChunkFromRoom(realm, roomId) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EventFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EventFactory.kt index 47605ea0..d42c7222 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EventFactory.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/EventFactory.kt @@ -21,15 +21,14 @@ import im.vector.matrix.android.api.session.events.model.Content import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.room.model.message.MessageTextContent -import im.vector.matrix.android.api.session.room.model.message.MessageType import im.vector.matrix.android.internal.di.MoshiProvider internal class EventFactory(private val credentials: Credentials) { private val moshi = MoshiProvider.providesMoshi() - fun createTextEvent(roomId: String, text: String): Event { - val content = MessageTextContent(type = MessageType.MSGTYPE_TEXT, body = text) + fun createTextEvent(roomId: String, msgType: String, text: String): Event { + val content = MessageTextContent(type = msgType, body = text) return Event( roomId = roomId, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt new file mode 100644 index 00000000..b471bf19 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt @@ -0,0 +1,41 @@ +/* + * 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.matrix.android.internal.session.room.state + +import im.vector.matrix.android.api.MatrixCallback +import im.vector.matrix.android.api.session.events.model.EventType +import im.vector.matrix.android.api.session.room.state.StateService +import im.vector.matrix.android.internal.task.TaskExecutor +import im.vector.matrix.android.internal.task.configureWith + +internal class DefaultStateService(private val roomId: String, + private val sendStateTask: SendStateTask, + private val taskExecutor: TaskExecutor) : StateService { + + override fun updateTopic(topic: String, callback: MatrixCallback) { + val params = SendStateTask.Params(roomId, + EventType.STATE_ROOM_TOPIC, + HashMap().apply { + put("topic", topic) + }) + + + sendStateTask.configureWith(params) + .dispatchTo(callback) + .executeBy(taskExecutor) + } +} \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/SendStateTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/SendStateTask.kt new file mode 100644 index 00000000..1d84bd9c --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/SendStateTask.kt @@ -0,0 +1,38 @@ +/* + * 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.matrix.android.internal.session.room.state + +import arrow.core.Try +import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.room.RoomAPI +import im.vector.matrix.android.internal.task.Task + +internal interface SendStateTask : Task { + data class Params( + val roomId: String, + val eventType: String, + val body: Map + ) +} + +internal class DefaultSendStateTask(private val roomAPI: RoomAPI) : SendStateTask { + override fun execute(params: SendStateTask.Params): Try { + return executeRequest { + apiCall = roomAPI.sendStateEvent(params.roomId, params.eventType, params.body) + } + } +} diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailViewModel.kt index 895c6659..1db55773 100644 --- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailViewModel.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailViewModel.kt @@ -24,6 +24,7 @@ import com.jakewharton.rxrelay2.BehaviorRelay import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.events.model.Event +import im.vector.matrix.android.api.session.room.model.message.MessageType import im.vector.matrix.rx.rx import im.vector.riotredesign.core.platform.VectorViewModel import im.vector.riotredesign.core.utils.LiveEvent @@ -136,12 +137,11 @@ class RoomDetailViewModel(initialState: RoomDetailViewState, _sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandNotImplemented)) } is ParsedCommand.SendEmote -> { - // TODO - _sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandNotImplemented)) + room.sendTextMessage(slashCommandResult.message, msgType = MessageType.MSGTYPE_EMOTE, callback = object : MatrixCallback {}) + _sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandHandled)) } is ParsedCommand.ChangeTopic -> { - // TODO - _sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandNotImplemented)) + handleChangeTopicSlashCommand(slashCommandResult) } is ParsedCommand.ChangeDisplayName -> { // TODO @@ -150,6 +150,20 @@ class RoomDetailViewModel(initialState: RoomDetailViewState, } } + private fun handleChangeTopicSlashCommand(changeTopic: ParsedCommand.ChangeTopic) { + _sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandHandled)) + + room.updateTopic(changeTopic.topic, object : MatrixCallback { + override fun onSuccess(data: Unit) { + _sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandResultOk)) + } + + override fun onFailure(failure: Throwable) { + _sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandResultError(failure))) + } + }) + } + private fun handleInviteSlashCommand(invite: ParsedCommand.Invite) { _sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandHandled))