Add option to record a video from the camera

Replace #2411
This commit is contained in:
Benoit Marty 2021-05-03 16:59:32 +02:00 committed by Benoit Marty
parent 30a54cfdbc
commit d9ffce7e0d
11 changed files with 404 additions and 12 deletions

View File

@ -10,6 +10,7 @@ Improvements 🙌:
- Compress video before sending (#442) - Compress video before sending (#442)
- Improve file too big error detection (#3245) - Improve file too big error detection (#3245)
- User can now select video when selecting Gallery to send attachments to a room - User can now select video when selecting Gallery to send attachments to a room
- Add option to record a video from the camera
Bugfix 🐛: Bugfix 🐛:
- Message states cosmetic changes (#3007) - Message states cosmetic changes (#3007)

View File

@ -0,0 +1,126 @@
/*
* 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.lib.multipicker
import android.content.Context
import android.content.Intent
import android.media.MediaMetadataRetriever
import android.net.Uri
import android.provider.MediaStore
import androidx.activity.result.ActivityResultLauncher
import androidx.core.content.FileProvider
import im.vector.lib.multipicker.entity.MultiPickerVideoType
import java.io.File
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
/**
* Implementation of taking a video with Camera
*/
class CameraVideoPicker {
/**
* Start camera by using a ActivityResultLauncher
* @return Uri of taken photo or null if the operation is cancelled.
*/
fun startWithExpectingFile(context: Context, activityResultLauncher: ActivityResultLauncher<Intent>): Uri? {
val videoUri = createVideoUri(context)
val intent = createIntent().apply {
putExtra(MediaStore.EXTRA_OUTPUT, videoUri)
}
activityResultLauncher.launch(intent)
return videoUri
}
/**
* Call this function from onActivityResult(int, int, Intent).
* @return Taken photo or null if request code is wrong
* or result code is not Activity.RESULT_OK
* or user cancelled the operation.
*/
fun getTakenVideo(context: Context, videoUri: Uri): MultiPickerVideoType? {
val projection = arrayOf(
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.SIZE,
MediaStore.Images.Media.MIME_TYPE
)
context.contentResolver.query(
videoUri,
projection,
null,
null,
null
)?.use { cursor ->
val nameColumn = cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)
val sizeColumn = cursor.getColumnIndex(MediaStore.Images.Media.SIZE)
if (cursor.moveToNext()) {
val name = cursor.getString(nameColumn)
val size = cursor.getLong(sizeColumn)
var duration = 0L
var width = 0
var height = 0
var orientation = 0
context.contentResolver.openFileDescriptor(videoUri, "r")?.use { pfd ->
val mediaMetadataRetriever = MediaMetadataRetriever()
mediaMetadataRetriever.setDataSource(pfd.fileDescriptor)
duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong() ?: 0L
width = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toInt() ?: 0
height = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toInt() ?: 0
orientation = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION)?.toInt() ?: 0
}
return MultiPickerVideoType(
name,
size,
context.contentResolver.getType(videoUri),
videoUri,
width,
height,
orientation,
duration
)
}
}
return null
}
private fun createIntent(): Intent {
return Intent(MediaStore.ACTION_VIDEO_CAPTURE)
}
companion object {
fun createVideoUri(context: Context): Uri {
val file = createVideoFile(context)
val authority = context.packageName + ".multipicker.fileprovider"
return FileProvider.getUriForFile(context, authority, file)
}
private fun createVideoFile(context: Context): File {
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
val storageDir: File = context.filesDir
return File.createTempFile(
"${timeStamp}_", /* prefix */
".mp4", /* suffix */
storageDir /* directory */
)
}
}
}

View File

@ -26,6 +26,7 @@ class MultiPicker<T> {
val AUDIO by lazy { MultiPicker<AudioPicker>() } val AUDIO by lazy { MultiPicker<AudioPicker>() }
val CONTACT by lazy { MultiPicker<ContactPicker>() } val CONTACT by lazy { MultiPicker<ContactPicker>() }
val CAMERA by lazy { MultiPicker<CameraPicker>() } val CAMERA by lazy { MultiPicker<CameraPicker>() }
val CAMERA_VIDEO by lazy { MultiPicker<CameraVideoPicker>() }
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
fun <T> get(type: MultiPicker<T>): T { fun <T> get(type: MultiPicker<T>): T {
@ -37,6 +38,7 @@ class MultiPicker<T> {
AUDIO -> AudioPicker() as T AUDIO -> AudioPicker() as T
CONTACT -> ContactPicker() as T CONTACT -> ContactPicker() as T
CAMERA -> CameraPicker() as T CAMERA -> CameraPicker() as T
CAMERA_VIDEO -> CameraVideoPicker() as T
else -> throw IllegalArgumentException("Unsupported type $type") else -> throw IllegalArgumentException("Unsupported type $type")
} }
} }

View File

@ -0,0 +1,118 @@
/*
* 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.core.dialogs
import android.app.Activity
import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible
import im.vector.app.R
import im.vector.app.databinding.DialogPhotoOrVideoBinding
import im.vector.app.features.settings.VectorPreferences
class PhotoOrVideoDialog(
private val activity: Activity,
private val vectorPreferences: VectorPreferences
) {
interface PhotoOrVideoDialogListener {
fun takePhoto()
fun takeVideo()
}
interface PhotoOrVideoDialogSettingsListener {
fun onUpdated()
}
fun show(listener: PhotoOrVideoDialogListener) {
when (vectorPreferences.getTakePhotoVideoMode()) {
VectorPreferences.TAKE_PHOTO_VIDEO_MODE_PHOTO -> listener.takePhoto()
VectorPreferences.TAKE_PHOTO_VIDEO_MODE_VIDEO -> listener.takeVideo()
/* VectorPreferences.TAKE_PHOTO_VIDEO_MODE_ALWAYS_ASK */
else -> {
val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_photo_or_video, null)
val views = DialogPhotoOrVideoBinding.bind(dialogLayout)
// Show option to set as default in this case
views.dialogPhotoOrVideoAsDefault.isVisible = true
// Always default to photo
views.dialogPhotoOrVideoPhoto.isChecked = true
AlertDialog.Builder(activity)
.setTitle(R.string.option_take_photo_video)
.setView(dialogLayout)
.setPositiveButton(R.string._continue) { _, _ ->
submit(views, vectorPreferences, listener)
}
.setNegativeButton(R.string.cancel, null)
.show()
}
}
}
private fun submit(views: DialogPhotoOrVideoBinding,
vectorPreferences: VectorPreferences,
listener: PhotoOrVideoDialogListener) {
val mode = if (views.dialogPhotoOrVideoPhoto.isChecked) {
VectorPreferences.TAKE_PHOTO_VIDEO_MODE_PHOTO
} else {
VectorPreferences.TAKE_PHOTO_VIDEO_MODE_VIDEO
}
if (views.dialogPhotoOrVideoAsDefault.isChecked) {
vectorPreferences.setTakePhotoVideoMode(mode)
}
when (mode) {
VectorPreferences.TAKE_PHOTO_VIDEO_MODE_PHOTO -> listener.takePhoto()
VectorPreferences.TAKE_PHOTO_VIDEO_MODE_VIDEO -> listener.takeVideo()
}
}
fun showForSettings(listener: PhotoOrVideoDialogSettingsListener) {
val currentMode = vectorPreferences.getTakePhotoVideoMode()
val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_photo_or_video, null)
val views = DialogPhotoOrVideoBinding.bind(dialogLayout)
// Show option for always ask in this case
views.dialogPhotoOrVideoAlwaysAsk.isVisible = true
// Always default to photo
views.dialogPhotoOrVideoPhoto.isChecked = currentMode == VectorPreferences.TAKE_PHOTO_VIDEO_MODE_PHOTO
views.dialogPhotoOrVideoVideo.isChecked = currentMode == VectorPreferences.TAKE_PHOTO_VIDEO_MODE_VIDEO
views.dialogPhotoOrVideoAlwaysAsk.isChecked = currentMode == VectorPreferences.TAKE_PHOTO_VIDEO_MODE_ALWAYS_ASK
AlertDialog.Builder(activity)
.setTitle(R.string.option_take_photo_video)
.setView(dialogLayout)
.setPositiveButton(R.string.save) { _, _ ->
submitSettings(views)
listener.onUpdated()
}
.setNegativeButton(R.string.cancel, null)
.show()
}
private fun submitSettings(views: DialogPhotoOrVideoBinding) {
vectorPreferences.setTakePhotoVideoMode(
when {
views.dialogPhotoOrVideoPhoto.isChecked -> VectorPreferences.TAKE_PHOTO_VIDEO_MODE_PHOTO
views.dialogPhotoOrVideoVideo.isChecked -> VectorPreferences.TAKE_PHOTO_VIDEO_MODE_VIDEO
else -> VectorPreferences.TAKE_PHOTO_VIDEO_MODE_ALWAYS_ASK
}
)
}
}

View File

@ -15,12 +15,15 @@
*/ */
package im.vector.app.features.attachments package im.vector.app.features.attachments
import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import im.vector.app.core.dialogs.PhotoOrVideoDialog
import im.vector.app.core.platform.Restorable import im.vector.app.core.platform.Restorable
import im.vector.app.features.settings.VectorPreferences
import im.vector.lib.multipicker.MultiPicker import im.vector.lib.multipicker.MultiPicker
import org.matrix.android.sdk.BuildConfig import org.matrix.android.sdk.BuildConfig
import org.matrix.android.sdk.api.session.content.ContentAttachmentData import org.matrix.android.sdk.api.session.content.ContentAttachmentData
@ -91,10 +94,21 @@ class AttachmentsHelper(val context: Context, val callback: Callback) : Restorab
} }
/** /**
* Starts the process for handling capture image picking * Starts the process for handling image/video capture. Can open a dialog
*/ */
fun openCamera(context: Context, activityResultLauncher: ActivityResultLauncher<Intent>) { fun openCamera(activity: Activity,
captureUri = MultiPicker.get(MultiPicker.CAMERA).startWithExpectingFile(context, activityResultLauncher) vectorPreferences: VectorPreferences,
cameraActivityResultLauncher: ActivityResultLauncher<Intent>,
cameraVideoActivityResultLauncher: ActivityResultLauncher<Intent>) {
PhotoOrVideoDialog(activity, vectorPreferences).show(object : PhotoOrVideoDialog.PhotoOrVideoDialogListener {
override fun takePhoto() {
captureUri = MultiPicker.get(MultiPicker.CAMERA).startWithExpectingFile(context, cameraActivityResultLauncher)
}
override fun takeVideo() {
captureUri = MultiPicker.get(MultiPicker.CAMERA_VIDEO).startWithExpectingFile(context, cameraVideoActivityResultLauncher)
}
})
} }
/** /**
@ -141,7 +155,7 @@ class AttachmentsHelper(val context: Context, val callback: Callback) : Restorab
) )
} }
fun onPhotoResult() { fun onCameraResult() {
captureUri?.let { captureUri -> captureUri?.let { captureUri ->
MultiPicker.get(MultiPicker.CAMERA) MultiPicker.get(MultiPicker.CAMERA)
.getTakenPhoto(context, captureUri) .getTakenPhoto(context, captureUri)
@ -153,6 +167,18 @@ class AttachmentsHelper(val context: Context, val callback: Callback) : Restorab
} }
} }
fun onCameraVideoResult() {
captureUri?.let { captureUri ->
MultiPicker.get(MultiPicker.CAMERA_VIDEO)
.getTakenVideo(context, captureUri)
?.let {
callback.onContentAttachmentsReady(
listOf(it).map { it.toContentAttachmentData() }
)
}
}
}
fun onVideoResult(data: Intent?) { fun onVideoResult(data: Intent?) {
callback.onContentAttachmentsReady( callback.onContentAttachmentsReady(
MultiPicker.get(MultiPicker.VIDEO) MultiPicker.get(MultiPicker.VIDEO)

View File

@ -994,9 +994,15 @@ class RoomDetailFragment @Inject constructor(
} }
} }
private val attachmentPhotoActivityResultLauncher = registerStartForActivityResult { private val attachmentCameraActivityResultLauncher = registerStartForActivityResult {
if (it.resultCode == Activity.RESULT_OK) { if (it.resultCode == Activity.RESULT_OK) {
attachmentsHelper.onPhotoResult() attachmentsHelper.onCameraResult()
}
}
private val attachmentCameraVideoActivityResultLauncher = registerStartForActivityResult {
if (it.resultCode == Activity.RESULT_OK) {
attachmentsHelper.onCameraVideoResult()
} }
} }
@ -1989,7 +1995,12 @@ class RoomDetailFragment @Inject constructor(
private fun launchAttachmentProcess(type: AttachmentTypeSelectorView.Type) { private fun launchAttachmentProcess(type: AttachmentTypeSelectorView.Type) {
when (type) { when (type) {
AttachmentTypeSelectorView.Type.CAMERA -> attachmentsHelper.openCamera(requireContext(), attachmentPhotoActivityResultLauncher) AttachmentTypeSelectorView.Type.CAMERA -> attachmentsHelper.openCamera(
activity = requireActivity(),
vectorPreferences = vectorPreferences,
cameraActivityResultLauncher = attachmentCameraActivityResultLauncher,
cameraVideoActivityResultLauncher = attachmentCameraVideoActivityResultLauncher
)
AttachmentTypeSelectorView.Type.FILE -> attachmentsHelper.selectFile(attachmentFileActivityResultLauncher) AttachmentTypeSelectorView.Type.FILE -> attachmentsHelper.selectFile(attachmentFileActivityResultLauncher)
AttachmentTypeSelectorView.Type.GALLERY -> attachmentsHelper.selectGallery(attachmentMediaActivityResultLauncher) AttachmentTypeSelectorView.Type.GALLERY -> attachmentsHelper.selectGallery(attachmentMediaActivityResultLauncher)
AttachmentTypeSelectorView.Type.AUDIO -> attachmentsHelper.selectAudio(attachmentAudioActivityResultLauncher) AttachmentTypeSelectorView.Type.AUDIO -> attachmentsHelper.selectAudio(attachmentAudioActivityResultLauncher)

View File

@ -193,6 +193,13 @@ class VectorPreferences @Inject constructor(private val context: Context) {
private const val SETTINGS_UNKNOWN_DEVICE_DISMISSED_LIST = "SETTINGS_UNKNWON_DEVICE_DISMISSED_LIST" private const val SETTINGS_UNKNOWN_DEVICE_DISMISSED_LIST = "SETTINGS_UNKNWON_DEVICE_DISMISSED_LIST"
private const val TAKE_PHOTO_VIDEO_MODE = "TAKE_PHOTO_VIDEO_MODE"
// Possible values for TAKE_PHOTO_VIDEO_MODE
const val TAKE_PHOTO_VIDEO_MODE_ALWAYS_ASK = 0
const val TAKE_PHOTO_VIDEO_MODE_PHOTO = 1
const val TAKE_PHOTO_VIDEO_MODE_VIDEO = 2
// Background sync modes // Background sync modes
// some preferences keys must be kept after a logout // some preferences keys must be kept after a logout
@ -948,4 +955,17 @@ class VectorPreferences @Inject constructor(private val context: Context) {
fun labsUseExperimentalRestricted(): Boolean { fun labsUseExperimentalRestricted(): Boolean {
return defaultPrefs.getBoolean(SETTINGS_LABS_USE_RESTRICTED_JOIN_RULE, false) return defaultPrefs.getBoolean(SETTINGS_LABS_USE_RESTRICTED_JOIN_RULE, false)
} }
/*
* Photo / video picker
*/
fun getTakePhotoVideoMode(): Int {
return defaultPrefs.getInt(TAKE_PHOTO_VIDEO_MODE, TAKE_PHOTO_VIDEO_MODE_ALWAYS_ASK)
}
fun setTakePhotoVideoMode(mode: Int) {
return defaultPrefs.edit {
putInt(TAKE_PHOTO_VIDEO_MODE, mode)
}
}
} }

View File

@ -23,6 +23,7 @@ import androidx.appcompat.app.AlertDialog
import androidx.core.view.children import androidx.core.view.children
import androidx.preference.Preference import androidx.preference.Preference
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.dialogs.PhotoOrVideoDialog
import im.vector.app.core.extensions.restart import im.vector.app.core.extensions.restart
import im.vector.app.core.preference.VectorListPreference import im.vector.app.core.preference.VectorListPreference
import im.vector.app.core.preference.VectorPreference import im.vector.app.core.preference.VectorPreference
@ -45,6 +46,9 @@ class VectorSettingsPreferencesFragment @Inject constructor(
private val textSizePreference by lazy { private val textSizePreference by lazy {
findPreference<VectorPreference>(VectorPreferences.SETTINGS_INTERFACE_TEXT_SIZE_KEY)!! findPreference<VectorPreference>(VectorPreferences.SETTINGS_INTERFACE_TEXT_SIZE_KEY)!!
} }
private val takePhotoOrVideoPreference by lazy {
findPreference<VectorPreference>("SETTINGS_INTERFACE_TAKE_PHOTO_VIDEO")!!
}
override fun bindPref() { override fun bindPref() {
// user interface preferences // user interface preferences
@ -123,6 +127,28 @@ class VectorSettingsPreferencesFragment @Inject constructor(
false false
} }
} }
// Take photo or video
updateTakePhotoOrVideoPreferenceSummary()
takePhotoOrVideoPreference.onPreferenceClickListener = Preference.OnPreferenceClickListener {
PhotoOrVideoDialog(requireActivity(), vectorPreferences).showForSettings(object: PhotoOrVideoDialog.PhotoOrVideoDialogSettingsListener {
override fun onUpdated() {
updateTakePhotoOrVideoPreferenceSummary()
}
})
true
}
}
private fun updateTakePhotoOrVideoPreferenceSummary() {
takePhotoOrVideoPreference.summary = getString(
when (vectorPreferences.getTakePhotoVideoMode()) {
VectorPreferences.TAKE_PHOTO_VIDEO_MODE_PHOTO -> R.string.option_take_photo
VectorPreferences.TAKE_PHOTO_VIDEO_MODE_VIDEO -> R.string.option_take_video
/* VectorPreferences.TAKE_PHOTO_VIDEO_MODE_ALWAYS_ASK */
else -> R.string.option_always_ask
}
)
} }
// ============================================================================================================== // ==============================================================================================================

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="?dialogPreferredPadding"
android:paddingTop="12dp"
android:paddingEnd="?dialogPreferredPadding"
android:paddingBottom="12dp">
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/dialog_photo_or_video_photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/option_take_photo"
tools:checked="true" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/dialog_photo_or_video_video"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="180dp"
android:text="@string/option_take_video" />
<!-- Displayed only form the settings -->
<com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/dialog_photo_or_video_always_ask"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="180dp"
android:text="@string/option_always_ask"
android:visibility="gone"
tools:visibility="visible" />
</RadioGroup>
<!-- Displayed only form the timeline -->
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/dialog_photo_or_video_as_default"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/use_as_default_and_do_not_ask_again"
android:visibility="gone"
tools:visibility="visible" />
</LinearLayout>

View File

@ -575,6 +575,9 @@
<string name="option_take_photo_video">Take photo or video</string> <string name="option_take_photo_video">Take photo or video</string>
<string name="option_take_photo">Take photo</string> <string name="option_take_photo">Take photo</string>
<string name="option_take_video">Take video</string> <string name="option_take_video">Take video</string>
<string name="option_always_ask">Always ask</string>
<string name="use_as_default_and_do_not_ask_again">Use as default and do not ask again</string>
<!-- No sticker application dialog --> <!-- No sticker application dialog -->
<string name="no_sticker_application_dialog_content">You dont currently have any stickerpacks enabled.\n\nAdd some now?</string> <string name="no_sticker_application_dialog_content">You dont currently have any stickerpacks enabled.\n\nAdd some now?</string>

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" <androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<im.vector.app.core.preference.VectorPreferenceCategory <im.vector.app.core.preference.VectorPreferenceCategory
android:key="SETTINGS_USER_INTERFACE_KEY" android:key="SETTINGS_USER_INTERFACE_KEY"
@ -55,6 +56,12 @@
android:summary="@string/settings_show_emoji_keyboard_summary" android:summary="@string/settings_show_emoji_keyboard_summary"
android:title="@string/settings_show_emoji_keyboard" /> android:title="@string/settings_show_emoji_keyboard" />
<im.vector.app.core.preference.VectorPreference
android:key="SETTINGS_INTERFACE_TAKE_PHOTO_VIDEO"
android:persistent="false"
android:title="@string/option_take_photo_video"
tools:summary="@string/option_always_ask" />
</im.vector.app.core.preference.VectorPreferenceCategory> </im.vector.app.core.preference.VectorPreferenceCategory>
<im.vector.app.core.preference.VectorPreferenceCategory android:title="@string/settings_category_timeline"> <im.vector.app.core.preference.VectorPreferenceCategory android:title="@string/settings_category_timeline">
@ -185,10 +192,10 @@
<im.vector.app.core.preference.VectorPreferenceCategory android:title="@string/settings_category_room_directory"> <im.vector.app.core.preference.VectorPreferenceCategory android:title="@string/settings_category_room_directory">
<im.vector.app.core.preference.VectorSwitchPreference <im.vector.app.core.preference.VectorSwitchPreference
android:key="SETTINGS_ROOM_DIRECTORY_SHOW_ALL_PUBLIC_ROOMS" android:key="SETTINGS_ROOM_DIRECTORY_SHOW_ALL_PUBLIC_ROOMS"
android:summary="@string/settings_room_directory_show_all_rooms_summary" android:summary="@string/settings_room_directory_show_all_rooms_summary"
android:title="@string/settings_room_directory_show_all_rooms" /> android:title="@string/settings_room_directory_show_all_rooms" />
</im.vector.app.core.preference.VectorPreferenceCategory> </im.vector.app.core.preference.VectorPreferenceCategory>
</androidx.preference.PreferenceScreen> </androidx.preference.PreferenceScreen>