diff --git a/vector/src/main/java/im/vector/app/features/voicebroadcast/VoiceBroadcastHelper.kt b/vector/src/main/java/im/vector/app/features/voicebroadcast/VoiceBroadcastHelper.kt new file mode 100644 index 0000000000..f682cd2f5e --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/voicebroadcast/VoiceBroadcastHelper.kt @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.voicebroadcast + +import im.vector.app.features.voicebroadcast.usecase.PauseVoiceBroadcastUseCase +import im.vector.app.features.voicebroadcast.usecase.ResumeVoiceBroadcastUseCase +import im.vector.app.features.voicebroadcast.usecase.StartVoiceBroadcastUseCase +import im.vector.app.features.voicebroadcast.usecase.StopVoiceBroadcastUseCase +import javax.inject.Inject + +/** + * Helper class to record voice broadcast. + */ +class VoiceBroadcastHelper @Inject constructor( + private val startVoiceBroadcastUseCase: StartVoiceBroadcastUseCase, + private val pauseVoiceBroadcastUseCase: PauseVoiceBroadcastUseCase, + private val resumeVoiceBroadcastUseCase: ResumeVoiceBroadcastUseCase, + private val stopVoiceBroadcastUseCase: StopVoiceBroadcastUseCase, +) { + suspend fun startVoiceBroadcast(roomId: String) = startVoiceBroadcastUseCase.execute(roomId) + + suspend fun pauseVoiceBroadcast(roomId: String) = pauseVoiceBroadcastUseCase.execute(roomId) + + suspend fun resumeVoiceBroadcast(roomId: String) = resumeVoiceBroadcastUseCase.execute(roomId) + + suspend fun stopVoiceBroadcast(roomId: String) = stopVoiceBroadcastUseCase.execute(roomId) +} diff --git a/vector/src/main/java/im/vector/app/features/voicebroadcast/usecase/PauseVoiceBroadcastUseCase.kt b/vector/src/main/java/im/vector/app/features/voicebroadcast/usecase/PauseVoiceBroadcastUseCase.kt new file mode 100644 index 0000000000..a7b544f69e --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/voicebroadcast/usecase/PauseVoiceBroadcastUseCase.kt @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2022 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.voicebroadcast.usecase + +import im.vector.app.features.voicebroadcast.STATE_ROOM_VOICE_BROADCAST_INFO +import im.vector.app.features.voicebroadcast.model.MessageVoiceBroadcastInfoContent +import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState +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.Event +import org.matrix.android.sdk.api.session.events.model.RelationType +import org.matrix.android.sdk.api.session.events.model.toContent +import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.room.Room +import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent +import timber.log.Timber +import javax.inject.Inject + +class PauseVoiceBroadcastUseCase @Inject constructor( + private val session: Session, +) { + + suspend fun execute(roomId: String) { + val room = session.roomService().getRoom(roomId) ?: return + + Timber.d("## PauseVoiceBroadcastUseCase: Pause voice broadcast requested") + + val lastVoiceBroadcastEvent = room.stateService().getStateEvent(STATE_ROOM_VOICE_BROADCAST_INFO, QueryStringValue.Equals(session.myUserId)) + val lastVoiceBroadcastInfoContent = lastVoiceBroadcastEvent?.content.toModel() + when (val voiceBroadcastState = lastVoiceBroadcastInfoContent?.voiceBroadcastState) { + VoiceBroadcastState.STARTED, + VoiceBroadcastState.RESUMED -> pauseVoiceBroadcast(room, lastVoiceBroadcastEvent) + else -> Timber.d("## PauseVoiceBroadcastUseCase: Cannot pause voice broadcast: currentState=$voiceBroadcastState") + } + } + + private suspend fun pauseVoiceBroadcast(room: Room, event: Event?) { + Timber.d("## PauseVoiceBroadcastUseCase: Send new voice broadcast info state event") + val lastVoiceBroadcastContent = event?.content.toModel() + val relatesTo = if (lastVoiceBroadcastContent?.voiceBroadcastState == VoiceBroadcastState.STARTED) { + RelationDefaultContent(RelationType.REFERENCE, event?.eventId) + } else { + lastVoiceBroadcastContent?.relatesTo + } + room.stateService().sendStateEvent( + eventType = STATE_ROOM_VOICE_BROADCAST_INFO, + stateKey = session.myUserId, + body = MessageVoiceBroadcastInfoContent( + relatesTo = relatesTo, + voiceBroadcastStateStr = VoiceBroadcastState.PAUSED.value, + ).toContent(), + ) + + // TODO pause recording audio files + } +} diff --git a/vector/src/main/java/im/vector/app/features/voicebroadcast/usecase/ResumeVoiceBroadcastUseCase.kt b/vector/src/main/java/im/vector/app/features/voicebroadcast/usecase/ResumeVoiceBroadcastUseCase.kt new file mode 100644 index 0000000000..294d91da0f --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/voicebroadcast/usecase/ResumeVoiceBroadcastUseCase.kt @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2022 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.voicebroadcast.usecase + +import im.vector.app.features.voicebroadcast.STATE_ROOM_VOICE_BROADCAST_INFO +import im.vector.app.features.voicebroadcast.model.MessageVoiceBroadcastInfoContent +import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState +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.Event +import org.matrix.android.sdk.api.session.events.model.RelationType +import org.matrix.android.sdk.api.session.events.model.toContent +import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.room.Room +import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent +import timber.log.Timber +import javax.inject.Inject + +class ResumeVoiceBroadcastUseCase @Inject constructor( + private val session: Session, +) { + + suspend fun execute(roomId: String) { + val room = session.roomService().getRoom(roomId) ?: return + + Timber.d("## ResumeVoiceBroadcastUseCase: Resume voice broadcast requested") + + val lastVoiceBroadcastEvent = room.stateService().getStateEvent(STATE_ROOM_VOICE_BROADCAST_INFO, QueryStringValue.Equals(session.myUserId)) + when (val voiceBroadcastState = lastVoiceBroadcastEvent?.content.toModel()?.voiceBroadcastState) { + VoiceBroadcastState.PAUSED -> resumeVoiceBroadcast(room, lastVoiceBroadcastEvent) + else -> Timber.d("## ResumeVoiceBroadcastUseCase: Cannot resume voice broadcast: currentState=$voiceBroadcastState") + } + } + + private suspend fun resumeVoiceBroadcast(room: Room, event: Event?) { + Timber.d("## ResumeVoiceBroadcastUseCase: Send new voice broadcast info state event") + val lastVoiceBroadcastContent = event?.content.toModel() + val relatesTo = if (lastVoiceBroadcastContent?.voiceBroadcastState == VoiceBroadcastState.STARTED) { + RelationDefaultContent(RelationType.REFERENCE, event?.eventId) + } else { + lastVoiceBroadcastContent?.relatesTo + } + room.stateService().sendStateEvent( + eventType = STATE_ROOM_VOICE_BROADCAST_INFO, + stateKey = session.myUserId, + body = MessageVoiceBroadcastInfoContent( + relatesTo = relatesTo, + voiceBroadcastStateStr = VoiceBroadcastState.RESUMED.value, + ).toContent(), + ) + + // TODO resume recording audio files + } +} diff --git a/vector/src/main/java/im/vector/app/features/voicebroadcast/usecase/StartVoiceBroadcastUseCase.kt b/vector/src/main/java/im/vector/app/features/voicebroadcast/usecase/StartVoiceBroadcastUseCase.kt new file mode 100644 index 0000000000..3a9a8e1437 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/voicebroadcast/usecase/StartVoiceBroadcastUseCase.kt @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022 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.voicebroadcast.usecase + +import im.vector.app.features.voicebroadcast.STATE_ROOM_VOICE_BROADCAST_INFO +import im.vector.app.features.voicebroadcast.model.MessageVoiceBroadcastInfoContent +import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState +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.toContent +import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.room.Room +import timber.log.Timber +import javax.inject.Inject + +class StartVoiceBroadcastUseCase @Inject constructor( + private val session: Session, +) { + + suspend fun execute(roomId: String) { + val room = session.roomService().getRoom(roomId) ?: return + + Timber.d("## StartVoiceBroadcastUseCase: Start voice broadcast requested") + + val lastVoiceBroadcastEvent = room.stateService().getStateEvent(STATE_ROOM_VOICE_BROADCAST_INFO, QueryStringValue.Equals(session.myUserId)) + when (val voiceBroadcastState = lastVoiceBroadcastEvent?.content.toModel()?.voiceBroadcastState) { + VoiceBroadcastState.STOPPED, + null -> startVoiceBroadcast(room) + else -> Timber.d("## StartVoiceBroadcastUseCase: Cannot start voice broadcast: currentState=$voiceBroadcastState") + } + } + + private suspend fun startVoiceBroadcast(room: Room) { + Timber.d("## StartVoiceBroadcastUseCase: Send new voice broadcast info state event") + room.stateService().sendStateEvent( + eventType = STATE_ROOM_VOICE_BROADCAST_INFO, + stateKey = session.myUserId, + body = MessageVoiceBroadcastInfoContent( + voiceBroadcastStateStr = VoiceBroadcastState.STARTED.value, + chunkLength = 5L, // TODO Get length from voice broadcast settings + ).toContent() + ) + + // TODO start recording audio files + } +} diff --git a/vector/src/main/java/im/vector/app/features/voicebroadcast/usecase/StopVoiceBroadcastUseCase.kt b/vector/src/main/java/im/vector/app/features/voicebroadcast/usecase/StopVoiceBroadcastUseCase.kt new file mode 100644 index 0000000000..5a72f379a3 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/voicebroadcast/usecase/StopVoiceBroadcastUseCase.kt @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2022 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.voicebroadcast.usecase + +import im.vector.app.features.voicebroadcast.STATE_ROOM_VOICE_BROADCAST_INFO +import im.vector.app.features.voicebroadcast.model.MessageVoiceBroadcastInfoContent +import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState +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.Event +import org.matrix.android.sdk.api.session.events.model.RelationType +import org.matrix.android.sdk.api.session.events.model.toContent +import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.room.Room +import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent +import timber.log.Timber +import javax.inject.Inject + +class StopVoiceBroadcastUseCase @Inject constructor( + private val session: Session, +) { + + suspend fun execute(roomId: String) { + val room = session.roomService().getRoom(roomId) ?: return + + Timber.d("## StopVoiceBroadcastUseCase: Stop voice broadcast requested") + + val lastVoiceBroadcastEvent = room.stateService().getStateEvent(STATE_ROOM_VOICE_BROADCAST_INFO, QueryStringValue.Equals(session.myUserId)) + when (val voiceBroadcastState = lastVoiceBroadcastEvent?.content.toModel()?.voiceBroadcastState) { + VoiceBroadcastState.STARTED, + VoiceBroadcastState.PAUSED, + VoiceBroadcastState.RESUMED -> stopVoiceBroadcast(room, lastVoiceBroadcastEvent) + else -> Timber.d("## StopVoiceBroadcastUseCase: Cannot stop voice broadcast: currentState=$voiceBroadcastState") + } + } + + private suspend fun stopVoiceBroadcast(room: Room, event: Event?) { + Timber.d("## StopVoiceBroadcastUseCase: Send new voice broadcast info state event") + val lastVoiceBroadcastContent = event?.content.toModel() + val relatesTo = if (lastVoiceBroadcastContent?.voiceBroadcastState == VoiceBroadcastState.STARTED) { + RelationDefaultContent(RelationType.REFERENCE, event?.eventId) + } else { + lastVoiceBroadcastContent?.relatesTo + } + room.stateService().sendStateEvent( + eventType = STATE_ROOM_VOICE_BROADCAST_INFO, + stateKey = session.myUserId, + body = MessageVoiceBroadcastInfoContent( + relatesTo = relatesTo, + voiceBroadcastStateStr = VoiceBroadcastState.STOPPED.value, + ).toContent(), + ) + + // TODO stop recording audio files + } +}