mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-15 01:35:07 +08:00
parent
30a54cfdbc
commit
d9ffce7e0d
@ -10,6 +10,7 @@ Improvements 🙌:
|
||||
- Compress video before sending (#442)
|
||||
- Improve file too big error detection (#3245)
|
||||
- User can now select video when selecting Gallery to send attachments to a room
|
||||
- Add option to record a video from the camera
|
||||
|
||||
Bugfix 🐛:
|
||||
- Message states cosmetic changes (#3007)
|
||||
|
@ -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 */
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -26,6 +26,7 @@ class MultiPicker<T> {
|
||||
val AUDIO by lazy { MultiPicker<AudioPicker>() }
|
||||
val CONTACT by lazy { MultiPicker<ContactPicker>() }
|
||||
val CAMERA by lazy { MultiPicker<CameraPicker>() }
|
||||
val CAMERA_VIDEO by lazy { MultiPicker<CameraVideoPicker>() }
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T> get(type: MultiPicker<T>): T {
|
||||
@ -37,6 +38,7 @@ class MultiPicker<T> {
|
||||
AUDIO -> AudioPicker() as T
|
||||
CONTACT -> ContactPicker() as T
|
||||
CAMERA -> CameraPicker() as T
|
||||
CAMERA_VIDEO -> CameraVideoPicker() as T
|
||||
else -> throw IllegalArgumentException("Unsupported type $type")
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
@ -15,12 +15,15 @@
|
||||
*/
|
||||
package im.vector.app.features.attachments
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import im.vector.app.core.dialogs.PhotoOrVideoDialog
|
||||
import im.vector.app.core.platform.Restorable
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import im.vector.lib.multipicker.MultiPicker
|
||||
import org.matrix.android.sdk.BuildConfig
|
||||
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>) {
|
||||
captureUri = MultiPicker.get(MultiPicker.CAMERA).startWithExpectingFile(context, activityResultLauncher)
|
||||
fun openCamera(activity: Activity,
|
||||
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 ->
|
||||
MultiPicker.get(MultiPicker.CAMERA)
|
||||
.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?) {
|
||||
callback.onContentAttachmentsReady(
|
||||
MultiPicker.get(MultiPicker.VIDEO)
|
||||
|
@ -994,9 +994,15 @@ class RoomDetailFragment @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private val attachmentPhotoActivityResultLauncher = registerStartForActivityResult {
|
||||
private val attachmentCameraActivityResultLauncher = registerStartForActivityResult {
|
||||
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) {
|
||||
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.GALLERY -> attachmentsHelper.selectGallery(attachmentMediaActivityResultLauncher)
|
||||
AttachmentTypeSelectorView.Type.AUDIO -> attachmentsHelper.selectAudio(attachmentAudioActivityResultLauncher)
|
||||
|
@ -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 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
|
||||
|
||||
// some preferences keys must be kept after a logout
|
||||
@ -948,4 +955,17 @@ class VectorPreferences @Inject constructor(private val context: Context) {
|
||||
fun labsUseExperimentalRestricted(): Boolean {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.children
|
||||
import androidx.preference.Preference
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.dialogs.PhotoOrVideoDialog
|
||||
import im.vector.app.core.extensions.restart
|
||||
import im.vector.app.core.preference.VectorListPreference
|
||||
import im.vector.app.core.preference.VectorPreference
|
||||
@ -45,6 +46,9 @@ class VectorSettingsPreferencesFragment @Inject constructor(
|
||||
private val textSizePreference by lazy {
|
||||
findPreference<VectorPreference>(VectorPreferences.SETTINGS_INTERFACE_TEXT_SIZE_KEY)!!
|
||||
}
|
||||
private val takePhotoOrVideoPreference by lazy {
|
||||
findPreference<VectorPreference>("SETTINGS_INTERFACE_TAKE_PHOTO_VIDEO")!!
|
||||
}
|
||||
|
||||
override fun bindPref() {
|
||||
// user interface preferences
|
||||
@ -123,6 +127,28 @@ class VectorSettingsPreferencesFragment @Inject constructor(
|
||||
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
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// ==============================================================================================================
|
||||
|
52
vector/src/main/res/layout/dialog_photo_or_video.xml
Normal file
52
vector/src/main/res/layout/dialog_photo_or_video.xml
Normal 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>
|
@ -575,6 +575,9 @@
|
||||
<string name="option_take_photo_video">Take photo or video</string>
|
||||
<string name="option_take_photo">Take photo</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 -->
|
||||
<string name="no_sticker_application_dialog_content">You don’t currently have any stickerpacks enabled.\n\nAdd some now?</string>
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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
|
||||
android:key="SETTINGS_USER_INTERFACE_KEY"
|
||||
@ -55,6 +56,12 @@
|
||||
android:summary="@string/settings_show_emoji_keyboard_summary"
|
||||
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 android:title="@string/settings_category_timeline">
|
||||
|
Loading…
Reference in New Issue
Block a user