diff --git a/changelog.d/7393.wip b/changelog.d/7393.wip
new file mode 100644
index 0000000000..7d82dc5769
--- /dev/null
+++ b/changelog.d/7393.wip
@@ -0,0 +1 @@
+[Voice Broadcast] Enable the feature (behind a lab flag and only for Android 10 and up)
diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml
index 74ec175d17..fac36ffa52 100644
--- a/library/ui-strings/src/main/res/values/strings.xml
+++ b/library/ui-strings/src/main/res/values/strings.xml
@@ -3346,6 +3346,8 @@
Have greater visibility and control over all your sessions.
Enable client info recording
Record the client name, version, and url to recognise sessions more easily in session manager.
+ Enable voice broadcast (under active development)
+ Be able to record and send voice broadcast in room timeline.
%s\nis looking a little empty.
diff --git a/vector-config/src/main/res/values/config-settings.xml b/vector-config/src/main/res/values/config-settings.xml
index 7b7aac8156..504c587b8d 100755
--- a/vector-config/src/main/res/values/config-settings.xml
+++ b/vector-config/src/main/res/values/config-settings.xml
@@ -49,6 +49,8 @@
false
true
false
+ true
+ false
diff --git a/vector/src/main/java/im/vector/app/features/VectorFeatures.kt b/vector/src/main/java/im/vector/app/features/VectorFeatures.kt
index 255ac6d188..95cf272abd 100644
--- a/vector/src/main/java/im/vector/app/features/VectorFeatures.kt
+++ b/vector/src/main/java/im/vector/app/features/VectorFeatures.kt
@@ -62,5 +62,5 @@ class DefaultVectorFeatures : VectorFeatures {
override fun isQrCodeLoginEnabled(): Boolean = true
override fun isQrCodeLoginForAllServers(): Boolean = false
override fun isReciprocateQrCodeLogin(): Boolean = false
- override fun isVoiceBroadcastEnabled(): Boolean = false
+ override fun isVoiceBroadcastEnabled(): Boolean = true
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt
index 59f9737542..55ec922a57 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt
@@ -310,7 +310,7 @@ class MessageComposerFragment : VectorBaseFragment(), A
)
attachmentTypeSelector.setAttachmentVisibility(
AttachmentTypeSelectorView.Type.VOICE_BROADCAST,
- vectorFeatures.isVoiceBroadcastEnabled(), // TODO check user permission
+ vectorPreferences.isVoiceBroadcastEnabled(), // TODO check user permission
)
}
attachmentTypeSelector.show(composer.attachmentButton)
diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt
index 89fcda142a..2dc8b12160 100755
--- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt
@@ -74,6 +74,7 @@ class VectorPreferences @Inject constructor(
const val SETTINGS_LABS_RICH_TEXT_EDITOR_KEY = "SETTINGS_LABS_RICH_TEXT_EDITOR_KEY"
const val SETTINGS_LABS_NEW_SESSION_MANAGER_KEY = "SETTINGS_LABS_NEW_SESSION_MANAGER_KEY"
const val SETTINGS_LABS_CLIENT_INFO_RECORDING_KEY = "SETTINGS_LABS_CLIENT_INFO_RECORDING_KEY"
+ const val SETTINGS_LABS_VOICE_BROADCAST_KEY = "SETTINGS_LABS_VOICE_BROADCAST_KEY"
const val SETTINGS_CRYPTOGRAPHY_PREFERENCE_KEY = "SETTINGS_CRYPTOGRAPHY_PREFERENCE_KEY"
const val SETTINGS_CRYPTOGRAPHY_DIVIDER_PREFERENCE_KEY = "SETTINGS_CRYPTOGRAPHY_DIVIDER_PREFERENCE_KEY"
const val SETTINGS_CRYPTOGRAPHY_MANAGE_PREFERENCE_KEY = "SETTINGS_CRYPTOGRAPHY_MANAGE_PREFERENCE_KEY"
@@ -1203,4 +1204,9 @@ class VectorPreferences @Inject constructor(
fun isRichTextEditorEnabled(): Boolean {
return defaultPrefs.getBoolean(SETTINGS_LABS_RICH_TEXT_EDITOR_KEY, getDefault(R.bool.settings_labs_rich_text_editor_default))
}
+
+ fun isVoiceBroadcastEnabled(): Boolean {
+ return vectorFeatures.isVoiceBroadcastEnabled() &&
+ defaultPrefs.getBoolean(SETTINGS_LABS_VOICE_BROADCAST_KEY, getDefault(R.bool.settings_labs_enable_voice_broadcast_default))
+ }
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/labs/VectorSettingsLabsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/labs/VectorSettingsLabsFragment.kt
index 6c31e32567..c10411301f 100644
--- a/vector/src/main/java/im/vector/app/features/settings/labs/VectorSettingsLabsFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/labs/VectorSettingsLabsFragment.kt
@@ -16,6 +16,7 @@
package im.vector.app.features.settings.labs
+import android.os.Build
import android.os.Bundle
import android.text.method.LinkMovementMethod
import android.widget.TextView
@@ -90,6 +91,11 @@ class VectorSettingsLabsFragment :
}
}
+ findPreference(VectorPreferences.SETTINGS_LABS_VOICE_BROADCAST_KEY)?.let { pref ->
+ // Voice Broadcast recording is not available on Android < 10
+ pref.isVisible = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && vectorFeatures.isVoiceBroadcastEnabled()
+ }
+
configureUnreadNotificationsAsTabPreference()
configureEnableClientInfoRecordingPreference()
}
diff --git a/vector/src/main/java/im/vector/app/features/voicebroadcast/VoiceBroadcastConstants.kt b/vector/src/main/java/im/vector/app/features/voicebroadcast/VoiceBroadcastConstants.kt
index 3a9aac12d5..d445dfdfbe 100644
--- a/vector/src/main/java/im/vector/app/features/voicebroadcast/VoiceBroadcastConstants.kt
+++ b/vector/src/main/java/im/vector/app/features/voicebroadcast/VoiceBroadcastConstants.kt
@@ -22,5 +22,5 @@ object VoiceBroadcastConstants {
const val STATE_ROOM_VOICE_BROADCAST_INFO = "io.element.voice_broadcast_info"
/** Default voice broadcast chunk duration, in seconds. */
- const val DEFAULT_CHUNK_LENGTH_IN_SECONDS = 30
+ const val DEFAULT_CHUNK_LENGTH_IN_SECONDS = 120
}
diff --git a/vector/src/main/java/im/vector/app/features/voicebroadcast/VoiceBroadcastRecorder.kt b/vector/src/main/java/im/vector/app/features/voicebroadcast/VoiceBroadcastRecorder.kt
index 2668501a8d..37ff920c57 100644
--- a/vector/src/main/java/im/vector/app/features/voicebroadcast/VoiceBroadcastRecorder.kt
+++ b/vector/src/main/java/im/vector/app/features/voicebroadcast/VoiceBroadcastRecorder.kt
@@ -16,6 +16,7 @@
package im.vector.app.features.voicebroadcast
+import androidx.annotation.IntRange
import im.vector.app.features.voice.VoiceRecorder
import java.io.File
@@ -26,6 +27,6 @@ interface VoiceBroadcastRecorder : VoiceRecorder {
fun startRecord(roomId: String, chunkLength: Int)
fun interface Listener {
- fun onVoiceMessageCreated(file: File)
+ fun onVoiceMessageCreated(file: File, @IntRange(from = 1) sequence: Int)
}
}
diff --git a/vector/src/main/java/im/vector/app/features/voicebroadcast/VoiceBroadcastRecorderQ.kt b/vector/src/main/java/im/vector/app/features/voicebroadcast/VoiceBroadcastRecorderQ.kt
index 620db721c9..404b112574 100644
--- a/vector/src/main/java/im/vector/app/features/voicebroadcast/VoiceBroadcastRecorderQ.kt
+++ b/vector/src/main/java/im/vector/app/features/voicebroadcast/VoiceBroadcastRecorderQ.kt
@@ -29,6 +29,7 @@ class VoiceBroadcastRecorderQ(
) : AbstractVoiceRecorderQ(context), VoiceBroadcastRecorder {
private var maxFileSize = 0L // zero or negative for no limit
+ private var currentSequence = 0
override var listener: VoiceBroadcastRecorder.Listener? = null
@@ -51,6 +52,7 @@ class VoiceBroadcastRecorderQ(
override fun startRecord(roomId: String, chunkLength: Int) {
maxFileSize = (chunkLength * audioEncodingBitRate / 8).toLong()
+ currentSequence = 1
startRecord(roomId)
}
@@ -58,6 +60,7 @@ class VoiceBroadcastRecorderQ(
super.stopRecord()
notifyOutputFileCreated()
listener = null
+ currentSequence = 0
}
override fun release() {
@@ -71,11 +74,12 @@ class VoiceBroadcastRecorderQ(
private fun onNextOutputFileStarted() {
notifyOutputFileCreated()
+ currentSequence++
}
private fun notifyOutputFileCreated() {
outputFile?.let {
- listener?.onVoiceMessageCreated(it)
+ listener?.onVoiceMessageCreated(it, currentSequence)
outputFile = nextOutputFile
nextOutputFile = null
}
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
index 2a306bcd28..780150d5e7 100644
--- 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
@@ -79,20 +79,21 @@ class StartVoiceBroadcastUseCase @Inject constructor(
}
private fun startRecording(room: Room, eventId: String, chunkLength: Int) {
- voiceBroadcastRecorder?.listener = VoiceBroadcastRecorder.Listener { file ->
- sendVoiceFile(room, file, eventId)
+ voiceBroadcastRecorder?.listener = VoiceBroadcastRecorder.Listener { file, sequence ->
+ sendVoiceFile(room, file, eventId, sequence)
}
voiceBroadcastRecorder?.startRecord(room.roomId, chunkLength)
}
- private fun sendVoiceFile(room: Room, voiceMessageFile: File, referenceEventId: String) {
+ private fun sendVoiceFile(room: Room, voiceMessageFile: File, referenceEventId: String, sequence: Int) {
val outputFileUri = FileProvider.getUriForFile(
context,
buildMeta.applicationId + ".fileProvider",
voiceMessageFile,
- "Voice message.${voiceMessageFile.extension}"
+ "Voice Broadcast Part ($sequence).${voiceMessageFile.extension}"
)
val audioType = outputFileUri.toMultiPickerAudioType(context) ?: return
+ // TODO put sequence in event content
room.sendService().sendMedia(
attachment = audioType.toContentAttachmentData(isVoiceMessage = true),
compressBeforeSending = false,
diff --git a/vector/src/main/res/xml/vector_settings_labs.xml b/vector/src/main/res/xml/vector_settings_labs.xml
index 5b519bdd91..15a255753a 100644
--- a/vector/src/main/res/xml/vector_settings_labs.xml
+++ b/vector/src/main/res/xml/vector_settings_labs.xml
@@ -117,4 +117,11 @@
android:title="@string/labs_enable_client_info_recording_title"
app:isPreferenceVisible="@bool/settings_labs_client_info_recording_visible" />
+
+