Various improvements

This commit is contained in:
Sylvain Berfini 2023-05-23 16:37:28 +02:00
parent 09f5f4f254
commit fc7a17d5e2
52 changed files with 151 additions and 84 deletions

View file

@ -29,7 +29,7 @@ import org.linphone.activities.assistant.adapters.CountryPickerAdapter
import org.linphone.core.DialPlan import org.linphone.core.DialPlan
import org.linphone.databinding.AssistantCountryPickerFragmentBinding import org.linphone.databinding.AssistantCountryPickerFragmentBinding
class CountryPickerFragment() : DialogFragment() { class CountryPickerFragment : DialogFragment() {
private var _binding: AssistantCountryPickerFragmentBinding? = null private var _binding: AssistantCountryPickerFragmentBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
private lateinit var adapter: CountryPickerAdapter private lateinit var adapter: CountryPickerAdapter

View file

@ -34,6 +34,7 @@ import org.linphone.activities.assistant.viewmodels.PhoneAccountValidationViewMo
import org.linphone.activities.assistant.viewmodels.SharedAssistantViewModel import org.linphone.activities.assistant.viewmodels.SharedAssistantViewModel
import org.linphone.activities.navigateToAccountSettings import org.linphone.activities.navigateToAccountSettings
import org.linphone.activities.navigateToEchoCancellerCalibration import org.linphone.activities.navigateToEchoCancellerCalibration
import org.linphone.compatibility.Compatibility
import org.linphone.core.tools.Log import org.linphone.core.tools.Log
import org.linphone.databinding.AssistantPhoneAccountValidationFragmentBinding import org.linphone.databinding.AssistantPhoneAccountValidationFragmentBinding
@ -113,7 +114,7 @@ class PhoneAccountValidationFragment : GenericFragment<AssistantPhoneAccountVali
"[Assistant] [Phone Account Validation] Found 4 digits as primary clip in clipboard, using it and clear it" "[Assistant] [Phone Account Validation] Found 4 digits as primary clip in clipboard, using it and clear it"
) )
viewModel.code.value = clip viewModel.code.value = clip
clipboard.clearPrimaryClip() Compatibility.clearClipboard(clipboard)
} }
} }
} }

View file

@ -21,7 +21,6 @@
package org.linphone.activities.assistant.viewmodels package org.linphone.activities.assistant.viewmodels
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import kotlinx.coroutines.*
import org.linphone.activities.assistant.fragments.CountryPickerFragment import org.linphone.activities.assistant.fragments.CountryPickerFragment
import org.linphone.core.AccountCreator import org.linphone.core.AccountCreator
import org.linphone.core.DialPlan import org.linphone.core.DialPlan

View file

@ -83,7 +83,6 @@ class ChatMessageContentData(
val conferenceDate = MutableLiveData<String>() val conferenceDate = MutableLiveData<String>()
val conferenceTime = MutableLiveData<String>() val conferenceTime = MutableLiveData<String>()
val conferenceDuration = MutableLiveData<String>() val conferenceDuration = MutableLiveData<String>()
var conferenceAddress = MutableLiveData<String>()
val showDuration = MutableLiveData<Boolean>() val showDuration = MutableLiveData<Boolean>()
val isAlone: Boolean val isAlone: Boolean
@ -107,6 +106,8 @@ class ChatMessageContentData(
stopVoiceRecording() stopVoiceRecording()
} }
private var conferenceAddress: String? = null
private fun getContent(): Content { private fun getContent(): Content {
return chatMessage.contents[contentIndex] return chatMessage.contents[contentIndex]
} }
@ -342,9 +343,9 @@ class ChatMessageContentData(
val conferenceInfo = Factory.instance().createConferenceInfoFromIcalendarContent(content) val conferenceInfo = Factory.instance().createConferenceInfoFromIcalendarContent(content)
val conferenceUri = conferenceInfo?.uri?.asStringUriOnly() val conferenceUri = conferenceInfo?.uri?.asStringUriOnly()
if (conferenceInfo != null && conferenceUri != null) { if (conferenceInfo != null && conferenceUri != null) {
conferenceAddress.value = conferenceUri!! conferenceAddress = conferenceUri!!
Log.i( Log.i(
"[Content] Created conference info from ICS with address ${conferenceAddress.value}" "[Content] Created conference info from ICS with address $conferenceAddress"
) )
conferenceSubject.value = conferenceInfo.subject conferenceSubject.value = conferenceInfo.subject
conferenceDescription.value = conferenceInfo.description conferenceDescription.value = conferenceInfo.description
@ -407,7 +408,7 @@ class ChatMessageContentData(
} }
fun callConferenceAddress() { fun callConferenceAddress() {
val address = conferenceAddress.value val address = conferenceAddress
if (address == null) { if (address == null) {
Log.e("[Content] Can't call null conference address!") Log.e("[Content] Can't call null conference address!")
return return

View file

@ -469,7 +469,7 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
} else { } else {
if (path.isEmpty()) { if (path.isEmpty()) {
val name = content.name val name = content.name
if (name != null && name.isNotEmpty()) { if (!name.isNullOrEmpty()) {
val file = FileUtils.getFileStoragePath(name) val file = FileUtils.getFileStoragePath(name)
FileUtils.writeIntoFile(content.buffer, file) FileUtils.writeIntoFile(content.buffer, file)
path = file.absolutePath path = file.absolutePath
@ -834,7 +834,7 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
if (_adapter != null) { if (_adapter != null) {
try { try {
adapter.registerAdapterDataObserver(observer) adapter.registerAdapterDataObserver(observer)
} catch (ise: IllegalStateException) {} } catch (_: IllegalStateException) {}
} }
// Wait for items to be displayed // Wait for items to be displayed
@ -859,7 +859,7 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
if (_adapter != null) { if (_adapter != null) {
try { try {
adapter.unregisterAdapterDataObserver(observer) adapter.unregisterAdapterDataObserver(observer)
} catch (ise: IllegalStateException) {} } catch (_: IllegalStateException) {}
} }
// Conversation isn't visible anymore, any new message received in it will trigger a notification // Conversation isn't visible anymore, any new message received in it will trigger a notification

View file

@ -134,7 +134,7 @@ class DialerViewModel : LogsUploadViewModel() {
) { ) {
if (result == VersionUpdateCheckResult.NewVersionAvailable) { if (result == VersionUpdateCheckResult.NewVersionAvailable) {
Log.i("[Dialer] Update available, version [$version], url [$url]") Log.i("[Dialer] Update available, version [$version], url [$url]")
if (url != null && url.isNotEmpty()) { if (!url.isNullOrEmpty()) {
updateAvailableEvent.value = Event(url) updateAvailableEvent.value = Event(url)
} }
} }

View file

@ -72,7 +72,7 @@ class AudioFileViewModel(content: Content) : FileViewerViewModel(content), Media
override fun getCurrentPosition(): Int { override fun getCurrentPosition(): Int {
try { try {
return mediaPlayer.currentPosition return mediaPlayer.currentPosition
} catch (ise: IllegalStateException) {} } catch (_: IllegalStateException) {}
return 0 return 0
} }

View file

@ -50,7 +50,7 @@ abstract class SecureFragment<T : ViewDataBinding> : GenericFragment<T>() {
override fun onResume() { override fun onResume() {
if (isSecure) { if (isSecure) {
enableSecureMode(isSecure) enableSecureMode(true)
} else { } else {
// This is a workaround to prevent a small blink showing the previous secured screen // This is a workaround to prevent a small blink showing the previous secured screen
lifecycleScope.launch { lifecycleScope.launch {

View file

@ -289,7 +289,7 @@ class AccountSettingsViewModel(val account: Account) : GenericSettingsViewModel(
account.params = params account.params = params
transportIndex.value = account.params.transport.toInt() transportIndex.value = account.params.transport.toInt()
} else { } else {
Log.e("[Account Settings] Couldn't parse address: $address") Log.e("[Account Settings] Couldn't parse address: $newValue")
} }
} }
} }

View file

@ -141,7 +141,7 @@ class AudioSettingsViewModel : GenericSettingsViewModel() {
override fun onTextValueChanged(newValue: String) { override fun onTextValueChanged(newValue: String) {
try { try {
core.micGainDb = newValue.toFloat() core.micGainDb = newValue.toFloat()
} catch (nfe: NumberFormatException) { } catch (_: NumberFormatException) {
} }
} }
} }
@ -151,7 +151,7 @@ class AudioSettingsViewModel : GenericSettingsViewModel() {
override fun onTextValueChanged(newValue: String) { override fun onTextValueChanged(newValue: String) {
try { try {
core.playbackGainDb = newValue.toFloat() core.playbackGainDb = newValue.toFloat()
} catch (nfe: NumberFormatException) { } catch (_: NumberFormatException) {
} }
} }
} }

View file

@ -97,7 +97,7 @@ class CallSettingsViewModel : GenericSettingsViewModel() {
Log.w("[Call Settings] Disabling Telecom Manager auto-enable") Log.w("[Call Settings] Disabling Telecom Manager auto-enable")
prefs.manuallyDisabledTelecomManager = true prefs.manuallyDisabledTelecomManager = true
} }
prefs.useTelecomManager = newValue prefs.useTelecomManager = false
} }
} }
} }
@ -169,7 +169,7 @@ class CallSettingsViewModel : GenericSettingsViewModel() {
override fun onTextValueChanged(newValue: String) { override fun onTextValueChanged(newValue: String) {
try { try {
prefs.autoAnswerDelay = newValue.toInt() prefs.autoAnswerDelay = newValue.toInt()
} catch (nfe: NumberFormatException) { } catch (_: NumberFormatException) {
} }
} }
} }
@ -179,7 +179,7 @@ class CallSettingsViewModel : GenericSettingsViewModel() {
override fun onTextValueChanged(newValue: String) { override fun onTextValueChanged(newValue: String) {
try { try {
core.incTimeout = newValue.toInt() core.incTimeout = newValue.toInt()
} catch (nfe: NumberFormatException) { } catch (_: NumberFormatException) {
} }
} }
} }

View file

@ -61,7 +61,7 @@ class ChatSettingsViewModel : GenericSettingsViewModel() {
val maxSize = newValue.toInt() val maxSize = newValue.toInt()
core.maxSizeForAutoDownloadIncomingFiles = maxSize core.maxSizeForAutoDownloadIncomingFiles = maxSize
updateAutoDownloadIndexFromMaxSize(maxSize) updateAutoDownloadIndexFromMaxSize(maxSize)
} catch (nfe: NumberFormatException) { } catch (_: NumberFormatException) {
} }
} }
} }

View file

@ -77,12 +77,12 @@ class ContactsSettingsViewModel : GenericSettingsViewModel() {
override fun onBoolValueChanged(newValue: Boolean) { override fun onBoolValueChanged(newValue: Boolean) {
if (newValue) { if (newValue) {
if (PermissionHelper.get().hasWriteContactsPermission()) { if (PermissionHelper.get().hasWriteContactsPermission()) {
prefs.storePresenceInNativeContact = newValue prefs.storePresenceInNativeContact = true
} else { } else {
askWriteContactsPermissionForPresenceStorageEvent.value = Event(true) askWriteContactsPermissionForPresenceStorageEvent.value = Event(true)
} }
} else { } else {
prefs.storePresenceInNativeContact = newValue prefs.storePresenceInNativeContact = false
} }
} }
} }

View file

@ -52,7 +52,7 @@ class NetworkSettingsViewModel : GenericSettingsViewModel() {
try { try {
val port = newValue.toInt() val port = newValue.toInt()
setTransportPort(port) setTransportPort(port)
} catch (nfe: NumberFormatException) { } catch (_: NumberFormatException) {
} }
} }
} }

View file

@ -43,7 +43,7 @@ class TunnelSettingsViewModel : GenericSettingsViewModel() {
val config = getTunnelConfig() val config = getTunnelConfig()
config.port = newValue.toInt() config.port = newValue.toInt()
updateTunnelConfig(config) updateTunnelConfig(config)
} catch (nfe: NumberFormatException) { } catch (_: NumberFormatException) {
} }
} }
} }
@ -72,7 +72,7 @@ class TunnelSettingsViewModel : GenericSettingsViewModel() {
val config = getTunnelConfig() val config = getTunnelConfig()
config.port2 = newValue.toInt() config.port2 = newValue.toInt()
updateTunnelConfig(config) updateTunnelConfig(config)
} catch (nfe: NumberFormatException) { } catch (_: NumberFormatException) {
} }
} }
} }

View file

@ -106,7 +106,7 @@ class VideoSettingsViewModel : GenericSettingsViewModel() {
try { try {
core.downloadBandwidth = newValue.toInt() core.downloadBandwidth = newValue.toInt()
core.uploadBandwidth = newValue.toInt() core.uploadBandwidth = newValue.toInt()
} catch (nfe: NumberFormatException) { } catch (_: NumberFormatException) {
} }
} }
} }

View file

@ -63,7 +63,7 @@ class ListTopBarViewModel : ViewModel() {
val list = arrayListOf<Int>() val list = arrayListOf<Int>()
selectedItems.value = list selectedItems.value = list
isSelectionNotEmpty.value = list.isNotEmpty() isSelectionNotEmpty.value = false
} }
fun onToggleSelect(position: Int) { fun onToggleSelect(position: Int) {

View file

@ -536,7 +536,7 @@ class ControlsViewModel : ViewModel() {
isVideoEnabled.value = enabled isVideoEnabled.value = enabled
showTakeSnapshotButton.value = enabled && corePreferences.showScreenshotButton showTakeSnapshotButton.value = enabled && corePreferences.showScreenshotButton
var isVideoBeingSent = if (coreContext.core.currentCall?.conference != null) { val isVideoBeingSent = if (coreContext.core.currentCall?.conference != null) {
val videoDirection = coreContext.core.currentCall?.currentParams?.videoDirection val videoDirection = coreContext.core.currentCall?.currentParams?.videoDirection
videoDirection == MediaDirection.SendRecv || videoDirection == MediaDirection.SendOnly videoDirection == MediaDirection.SendRecv || videoDirection == MediaDirection.SendOnly
} else { } else {

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2010-2023 Belledonne Communications SARL.
*
* This file is part of linphone-android
* (see https://www.linphone.org).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.linphone.compatibility
import android.annotation.TargetApi
import android.content.ClipboardManager
@TargetApi(28)
class Api28Compatibility {
companion object {
fun clearClipboard(clipboard: ClipboardManager) {
clipboard.clearPrimaryClip()
}
}
}

View file

@ -23,6 +23,7 @@ import android.app.Activity
import android.app.Notification import android.app.Notification
import android.app.PendingIntent import android.app.PendingIntent
import android.app.Service import android.app.Service
import android.content.ClipboardManager
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Bitmap import android.graphics.Bitmap
@ -455,5 +456,11 @@ class Compatibility {
} }
return false return false
} }
fun clearClipboard(clipboard: ClipboardManager) {
if (Version.sdkAboveOrEqual(Version.API28_PIE_90)) {
Api28Compatibility.clearClipboard(clipboard)
}
}
} }
} }

View file

@ -88,7 +88,7 @@ abstract class GenericContactViewModel(private val sipAddress: Address) : Messag
contactLookup() contactLookup()
} }
protected fun contactLookup() { private fun contactLookup() {
displayName.value = LinphoneUtils.getDisplayName(sipAddress) displayName.value = LinphoneUtils.getDisplayName(sipAddress)
val friend = coreContext.contactsManager.findContactByAddress(sipAddress) val friend = coreContext.contactsManager.findContactByAddress(sipAddress)
if (friend != null) { if (friend != null) {

View file

@ -410,10 +410,12 @@ fun Friend.getPictureUri(thumbnailPreferred: Boolean = false): Uri? {
// Check that the URI points to a real file // Check that the URI points to a real file
val contentResolver = coreContext.context.contentResolver val contentResolver = coreContext.context.contentResolver
try { try {
if (contentResolver.openAssetFileDescriptor(pictureUri, "r") != null) { val fd = contentResolver.openAssetFileDescriptor(pictureUri, "r")
if (fd != null) {
fd.close()
return pictureUri return pictureUri
} }
} catch (ioe: IOException) { } } catch (_: IOException) { }
} }
// Fallback to thumbnail if high res picture isn't available // Fallback to thumbnail if high res picture isn't available
@ -421,11 +423,11 @@ fun Friend.getPictureUri(thumbnailPreferred: Boolean = false): Uri? {
lookupUri, lookupUri,
ContactsContract.Contacts.Photo.CONTENT_DIRECTORY ContactsContract.Contacts.Photo.CONTENT_DIRECTORY
) )
} catch (e: Exception) { } } catch (_: Exception) { }
} else if (photo != null) { } else if (photo != null) {
try { try {
return Uri.parse(photo) return Uri.parse(photo)
} catch (e: Exception) { } } catch (_: Exception) { }
} }
return null return null
} }

View file

@ -598,7 +598,7 @@ fun addPrefixEditTextValidation(editText: EditText, enabled: Boolean) {
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (s == null || s.isEmpty() || !s.startsWith("+")) { if (s.isNullOrEmpty() || !s.startsWith("+")) {
editText.setText("+$s") editText.setText("+$s")
} }
} }

View file

@ -51,7 +51,7 @@ class LinphoneUtils {
} }
val localDisplayName = account?.params?.identityAddress?.displayName val localDisplayName = account?.params?.identityAddress?.displayName
// Do not return an empty local display name // Do not return an empty local display name
if (localDisplayName != null && localDisplayName.isNotEmpty()) { if (!localDisplayName.isNullOrEmpty()) {
return localDisplayName return localDisplayName
} }
} }
@ -179,7 +179,7 @@ class LinphoneUtils {
fun deleteFilesAttachedToChatMessage(chatMessage: ChatMessage) { fun deleteFilesAttachedToChatMessage(chatMessage: ChatMessage) {
for (content in chatMessage.contents) { for (content in chatMessage.contents) {
val filePath = content.filePath val filePath = content.filePath
if (filePath != null && filePath.isNotEmpty()) { if (!filePath.isNullOrEmpty()) {
Log.i("[Linphone Utils] Deleting file $filePath") Log.i("[Linphone Utils] Deleting file $filePath")
FileUtils.deleteFile(filePath) FileUtils.deleteFile(filePath)
} }

View file

@ -4,8 +4,7 @@
android:layout_height="40dp" android:layout_height="40dp"
android:layout_gravity="center" android:layout_gravity="center"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="5dp" android:padding="5dp">
android:background="?attr/backgroundColor">
<TextView <TextView
android:id="@+id/country_name" android:id="@+id/country_name"

View file

@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"> <layout xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<data> <data>
<import type="android.view.View"/> <import type="android.view.View"/>
@ -46,8 +48,8 @@
android:gravity="center" android:gravity="center"
android:textAlignment="center" android:textAlignment="center"
android:drawablePadding="5dp" android:drawablePadding="5dp"
android:drawableTop="@drawable/file_video" android:text="@{data.fileName, default=`test.mkv`}"
android:text="@{data.fileName, default=`test.mkv`}"/> app:drawableTopCompat="@drawable/file_video" />
<ImageView <ImageView
android:visibility="@{data.video ? View.VISIBLE : View.GONE, default=gone}" android:visibility="@{data.video ? View.VISIBLE : View.GONE, default=gone}"
@ -73,9 +75,10 @@
android:gravity="center" android:gravity="center"
android:textAlignment="center" android:textAlignment="center"
android:drawablePadding="5dp" android:drawablePadding="5dp"
android:drawableTop="@{data.pdf ? @drawable/file_pdf : (data.audio ? @drawable/file_audio : @drawable/file), default=@drawable/file}"
android:visibility="@{data.image || data.video ? View.GONE : View.VISIBLE, default=gone}" android:visibility="@{data.image || data.video ? View.GONE : View.VISIBLE, default=gone}"
android:text="@{data.fileName, default=`test.txt`}"/> android:text="@{data.fileName, default=`test.txt`}"
android:drawableTop="@{data.pdf ? @drawable/file_pdf : (data.audio ? @drawable/file_audio : @drawable/file), default=@drawable/file}"
tools:ignore="UseCompatTextViewDrawableXml" />
<ImageView <ImageView
android:onClick="@{() -> data.delete()}" android:onClick="@{() -> data.delete()}"

View file

@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"> <layout xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<data> <data>
<import type="android.view.View" /> <import type="android.view.View" />
@ -29,7 +31,6 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="5dp" android:layout_margin="5dp"
android:drawableTop="@{data.video ? @drawable/file_video : (data.image ? @drawable/file_picture : (data.pdf ? @drawable/file_pdf : (data.audio ? @drawable/file_audio : (data.voiceRecording ? @drawable/audio_recording_reply_preview_default : @drawable/file)))), default=@drawable/file}"
android:drawablePadding="5dp" android:drawablePadding="5dp"
android:ellipsize="middle" android:ellipsize="middle"
android:gravity="center" android:gravity="center"
@ -37,7 +38,9 @@
android:onLongClick="@{longClickListener}" android:onLongClick="@{longClickListener}"
android:singleLine="true" android:singleLine="true"
android:text="@{data.fileName, default=`test.pdf`}" android:text="@{data.fileName, default=`test.pdf`}"
android:textAlignment="center" /> android:textAlignment="center"
android:drawableTop="@{data.video ? @drawable/file_video : (data.image ? @drawable/file_picture : (data.pdf ? @drawable/file_pdf : (data.audio ? @drawable/file_audio : (data.voiceRecording ? @drawable/audio_recording_reply_preview_default : @drawable/file)))), default=@drawable/file}"
tools:ignore="UseCompatTextViewDrawableXml" />
<TextView <TextView
style="@style/chat_file_attachment_font" style="@style/chat_file_attachment_font"

View file

@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"> <layout xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<data> <data>
<import type="android.view.View" /> <import type="android.view.View" />
@ -29,7 +31,6 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="5dp" android:layout_margin="5dp"
android:drawableTop="@{data.video ? @drawable/file_video : (data.image ? @drawable/file_picture : (data.pdf ? @drawable/file_pdf : (data.audio ? @drawable/file_audio : (data.voiceRecording ? @drawable/audio_recording_reply_preview_default : @drawable/file)))), default=@drawable/file}"
android:drawablePadding="5dp" android:drawablePadding="5dp"
android:ellipsize="middle" android:ellipsize="middle"
android:gravity="center" android:gravity="center"
@ -37,7 +38,9 @@
android:onLongClick="@{longClickListener}" android:onLongClick="@{longClickListener}"
android:singleLine="true" android:singleLine="true"
android:text="@{data.fileName, default=`test.pdf`}" android:text="@{data.fileName, default=`test.pdf`}"
android:textAlignment="center" /> android:textAlignment="center"
android:drawableTop="@{data.video ? @drawable/file_video : (data.image ? @drawable/file_picture : (data.pdf ? @drawable/file_pdf : (data.audio ? @drawable/file_audio : (data.voiceRecording ? @drawable/audio_recording_reply_preview_default : @drawable/file)))), default=@drawable/file}"
tools:ignore="UseCompatTextViewDrawableXml" />
</RelativeLayout> </RelativeLayout>

View file

@ -85,7 +85,8 @@
android:background="@drawable/led_background" android:background="@drawable/led_background"
android:padding="2dp" android:padding="2dp"
app:presenceIcon="@{data.presenceStatus}" app:presenceIcon="@{data.presenceStatus}"
android:visibility="@{data.chatMessage.outgoing || selectionListViewModel.isEditionEnabled || data.hideAvatar || data.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" /> android:visibility="@{data.chatMessage.outgoing || selectionListViewModel.isEditionEnabled || data.hideAvatar || data.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}"
tools:ignore="ContentDescription" />
<LinearLayout <LinearLayout
android:id="@+id/background" android:id="@+id/background"

View file

@ -163,6 +163,7 @@
android:layout_alignRight="@id/searchBar" android:layout_alignRight="@id/searchBar"
android:layout_alignBottom="@id/searchBar" android:layout_alignBottom="@id/searchBar"
android:onClick="@{() -> viewModel.clearFilter()}" android:onClick="@{() -> viewModel.clearFilter()}"
android:contentDescription="@string/content_description_clear_field"
android:src="@drawable/field_clean" /> android:src="@drawable/field_clean" />
<View <View

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <layout 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">
<data> <data>
<import type="android.view.View"/> <import type="android.view.View"/>
@ -49,7 +50,8 @@
android:background="@drawable/led_background" android:background="@drawable/led_background"
android:padding="@dimen/contact_presence_badge_padding" android:padding="@dimen/contact_presence_badge_padding"
app:presenceIcon="@{data.presenceStatus}" app:presenceIcon="@{data.presenceStatus}"
android:visibility="@{data.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" /> android:visibility="@{data.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}"
tools:ignore="ContentDescription" />
<ImageView <ImageView
android:layout_width="20dp" android:layout_width="20dp"

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <layout 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">
<data> <data>
<import type="android.view.View"/> <import type="android.view.View"/>
@ -50,7 +51,8 @@
android:background="@drawable/led_background" android:background="@drawable/led_background"
android:padding="@dimen/contact_presence_badge_padding" android:padding="@dimen/contact_presence_badge_padding"
android:visibility="@{data.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" android:visibility="@{data.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}"
app:presenceIcon="@{data.presenceStatus}" /> app:presenceIcon="@{data.presenceStatus}"
tools:ignore="ContentDescription" />
<ImageView <ImageView
android:layout_width="20dp" android:layout_width="20dp"

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <layout 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">
<data> <data>
<import type="android.view.View"/> <import type="android.view.View"/>
@ -37,7 +38,8 @@
android:background="@drawable/led_background" android:background="@drawable/led_background"
android:padding="@dimen/contact_presence_badge_padding" android:padding="@dimen/contact_presence_badge_padding"
app:presenceIcon="@{data.presenceStatus}" app:presenceIcon="@{data.presenceStatus}"
android:visibility="@{data.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" /> android:visibility="@{data.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}"
tools:ignore="ContentDescription" />
<TextView <TextView
android:id="@+id/time" android:id="@+id/time"

View file

@ -62,7 +62,8 @@
app:presenceIcon="@{data.presenceStatus}" app:presenceIcon="@{data.presenceStatus}"
android:visibility="@{data.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" android:visibility="@{data.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}"
app:layout_constraintStart_toStartOf="@id/avatar" app:layout_constraintStart_toStartOf="@id/avatar"
app:layout_constraintBottom_toBottomOf="@id/avatar"/> app:layout_constraintBottom_toBottomOf="@id/avatar"
tools:ignore="ContentDescription"/>
<ImageView <ImageView
android:id="@+id/securityLevel" android:id="@+id/securityLevel"

View file

@ -205,6 +205,7 @@
android:paddingTop="@dimen/chat_message_sending_icons_margin" android:paddingTop="@dimen/chat_message_sending_icons_margin"
android:paddingBottom="@dimen/chat_message_sending_icons_margin" android:paddingBottom="@dimen/chat_message_sending_icons_margin"
android:src="@drawable/emoji" android:src="@drawable/emoji"
android:contentDescription="@string/content_description_emoji_picker"
android:selected="@{chatSendingViewModel.isEmojiPickerOpen}" android:selected="@{chatSendingViewModel.isEmojiPickerOpen}"
android:visibility="@{chatSendingViewModel.isEmojiPickerVisible ? View.VISIBLE : View.GONE}" android:visibility="@{chatSendingViewModel.isEmojiPickerVisible ? View.VISIBLE : View.GONE}"
app:layout_constraintHeight_max="@dimen/chat_message_sending_icons_size" app:layout_constraintHeight_max="@dimen/chat_message_sending_icons_size"

View file

@ -79,6 +79,7 @@
android:layout_alignRight="@id/searchBar" android:layout_alignRight="@id/searchBar"
android:layout_alignBottom="@id/searchBar" android:layout_alignBottom="@id/searchBar"
android:onClick="@{() -> viewModel.clearFilter()}" android:onClick="@{() -> viewModel.clearFilter()}"
android:contentDescription="@string/content_description_clear_field"
android:src="@drawable/field_clean" /> android:src="@drawable/field_clean" />
</RelativeLayout> </RelativeLayout>

View file

@ -102,6 +102,7 @@
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:layout_marginEnd="5dp" android:layout_marginEnd="5dp"
android:inputType="textEmailSubject"
style="@style/conference_scheduling_font" style="@style/conference_scheduling_font"
android:background="?attr/voipFormDisabledFieldBackgroundColor" android:background="?attr/voipFormDisabledFieldBackgroundColor"
android:text="@{viewModel.subject}" android:text="@{viewModel.subject}"
@ -252,6 +253,7 @@
android:gravity="top" android:gravity="top"
android:minLines="3" android:minLines="3"
android:maxLines="5" android:maxLines="5"
android:inputType="textMultiLine"
style="@style/conference_scheduling_font" style="@style/conference_scheduling_font"
android:background="?attr/voipFormDisabledFieldBackgroundColor" android:background="?attr/voipFormDisabledFieldBackgroundColor"
android:hint="@string/conference_schedule_description_hint" android:hint="@string/conference_schedule_description_hint"

View file

@ -105,7 +105,8 @@
android:background="@drawable/led_background" android:background="@drawable/led_background"
android:padding="@dimen/contact_presence_big_badge_padding" android:padding="@dimen/contact_presence_big_badge_padding"
app:presenceIcon="@{viewModel.presenceStatus}" app:presenceIcon="@{viewModel.presenceStatus}"
android:visibility="@{viewModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" /> android:visibility="@{viewModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}"
tools:ignore="ContentDescription" />
</RelativeLayout> </RelativeLayout>

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <layout 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">
<data> <data>
<import type="android.view.View"/> <import type="android.view.View"/>
@ -54,7 +55,8 @@
android:background="@drawable/led_background" android:background="@drawable/led_background"
android:padding="@dimen/contact_presence_badge_padding" android:padding="@dimen/contact_presence_badge_padding"
app:presenceIcon="@{viewModel.presenceStatus}" app:presenceIcon="@{viewModel.presenceStatus}"
android:visibility="@{viewModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" /> android:visibility="@{viewModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}"
tools:ignore="ContentDescription" />
<LinearLayout <LinearLayout
android:id="@+id/right" android:id="@+id/right"

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <layout 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">
<data> <data>
<import type="android.view.View"/> <import type="android.view.View"/>
@ -52,7 +53,8 @@
android:background="@drawable/led_background" android:background="@drawable/led_background"
android:padding="@dimen/contact_presence_badge_padding" android:padding="@dimen/contact_presence_badge_padding"
app:presenceIcon="@{data.presenceStatus}" app:presenceIcon="@{data.presenceStatus}"
android:visibility="@{data.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" /> android:visibility="@{data.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}"
tools:ignore="ContentDescription" />
<ImageView <ImageView
android:visibility="@{data.hasLimeX3DHCapability ? View.VISIBLE : View.GONE, default=gone}" android:visibility="@{data.hasLimeX3DHCapability ? View.VISIBLE : View.GONE, default=gone}"

View file

@ -2,7 +2,6 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
android:background="?attr/backgroundColor">
</LinearLayout> </LinearLayout>

View file

@ -107,7 +107,8 @@
android:background="@drawable/led_background" android:background="@drawable/led_background"
android:padding="@dimen/contact_presence_big_badge_padding" android:padding="@dimen/contact_presence_big_badge_padding"
app:presenceIcon="@{viewModel.presenceStatus}" app:presenceIcon="@{viewModel.presenceStatus}"
android:visibility="@{viewModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" /> android:visibility="@{viewModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}"
bind:ignore="ContentDescription" />
</RelativeLayout> </RelativeLayout>

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <layout 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">
<data> <data>
@ -103,7 +104,8 @@
android:background="@drawable/led_background" android:background="@drawable/led_background"
android:padding="@dimen/contact_presence_badge_padding" android:padding="@dimen/contact_presence_badge_padding"
app:presenceIcon="@{viewModel.presenceStatus}" app:presenceIcon="@{viewModel.presenceStatus}"
android:visibility="@{viewModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" /> android:visibility="@{viewModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}"
tools:ignore="ContentDescription" />
<ImageView <ImageView
android:id="@+id/icon" android:id="@+id/icon"

View file

@ -63,6 +63,7 @@
android:padding="5dp" android:padding="5dp"
android:onClick="@{() -> data.export()}" android:onClick="@{() -> data.export()}"
android:src="@drawable/icon_share" android:src="@drawable/icon_share"
android:contentDescription="@string/content_description_recording_export"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toStartOf="@id/delete" /> app:layout_constraintEnd_toStartOf="@id/delete" />

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <layout 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">
<data> <data>
<import type="android.view.View"/> <import type="android.view.View"/>
@ -81,7 +82,8 @@
android:background="@drawable/led_background" android:background="@drawable/led_background"
android:padding="@dimen/contact_presence_badge_padding" android:padding="@dimen/contact_presence_badge_padding"
app:presenceIcon="@{viewModel.presenceStatus}" app:presenceIcon="@{viewModel.presenceStatus}"
android:visibility="@{!viewModel.defaultAccountFound || viewModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" /> android:visibility="@{!viewModel.defaultAccountFound || viewModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}"
tools:ignore="ContentDescription" />
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"

View file

@ -120,6 +120,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:src="@drawable/icon_video_conf_incoming" android:src="@drawable/icon_video_conf_incoming"
android:contentDescription="@null"
app:layout_constraintBottom_toTopOf="@id/participants_count" app:layout_constraintBottom_toTopOf="@id/participants_count"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_max="120dp" app:layout_constraintHeight_max="120dp"

View file

@ -2,7 +2,7 @@
<!DOCTYPE resources [ <!DOCTYPE resources [
<!ENTITY appName "Linphone"> <!ENTITY appName "Linphone">
]> ]>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingQuantity">
<string name="content_description_copy_conference_address">Kopírovat adresu schůzky</string> <string name="content_description_copy_conference_address">Kopírovat adresu schůzky</string>
<string name="call_settings_auto_start_title">Okamžité zahájení volání</string> <string name="call_settings_auto_start_title">Okamžité zahájení volání</string>
<string name="call_settings_auto_start_summary">Volání se spustí automaticky, pokud je spuštěno z jiné aplikace</string> <string name="call_settings_auto_start_summary">Volání se spustí automaticky, pokud je spuštěno z jiné aplikace</string>
@ -107,7 +107,7 @@
<string name="sip_address">SIP adresa</string> <string name="sip_address">SIP adresa</string>
<string name="sip_addresses">SIP adresy</string> <string name="sip_addresses">SIP adresy</string>
<string name="cancel">Zrušit</string> <string name="cancel">Zrušit</string>
<plurals name="days"> <plurals name="days" tools:ignore="MissingQuantity">
<item quantity="one">den</item> <item quantity="one">den</item>
<item quantity="few">dny</item> <item quantity="few">dny</item>
<item quantity="other">dní</item> <item quantity="other">dní</item>
@ -670,7 +670,7 @@
<string name="chat_room_ephemeral_message_disabled">Zakázáno</string> <string name="chat_room_ephemeral_message_disabled">Zakázáno</string>
<string name="chat_room_ephemeral_message_one_hour">1 hodina</string> <string name="chat_room_ephemeral_message_one_hour">1 hodina</string>
<string name="chat_room_ephemeral_message_one_week">1 týden</string> <string name="chat_room_ephemeral_message_one_week">1 týden</string>
<plurals name="chat_room_remote_composing"> <plurals name="chat_room_remote_composing" tools:ignore="MissingQuantity">
<item quantity="one">%s píše…</item> <item quantity="one">%s píše…</item>
<item quantity="few">%s píší…</item> <item quantity="few">%s píší…</item>
<item quantity="other">%s píše…</item> <item quantity="other">%s píše…</item>

View file

@ -788,4 +788,5 @@
<string name="dialog_authentication_required_title">Authentification requise</string> <string name="dialog_authentication_required_title">Authentification requise</string>
<string name="dialog_authentication_required_message">La connexion a échouée car l\'authentification est manquante ou invalide pour le compte\n%s.\n\nVous pouvez fournir le mot de passe à nouveau ou vérifier la configuration de votre compte dans les paramètres.</string> <string name="dialog_authentication_required_message">La connexion a échouée car l\'authentification est manquante ou invalide pour le compte\n%s.\n\nVous pouvez fournir le mot de passe à nouveau ou vérifier la configuration de votre compte dans les paramètres.</string>
<string name="dialog_authentication_required_change_password_label">Confirmer</string> <string name="dialog_authentication_required_change_password_label">Confirmer</string>
<string name="content_description_emoji_picker">Change la visibilité du selectionneur d\'emoji</string>
</resources> </resources>

View file

@ -2,7 +2,7 @@
<!DOCTYPE resources [ <!DOCTYPE resources [
<!ENTITY appName "Linphone"> <!ENTITY appName "Linphone">
]> ]>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="UnusedQuantity">
<string name="transport">传输</string> <string name="transport">传输</string>
<string name="transport_udp">UDP 用户数据报协议</string> <string name="transport_udp">UDP 用户数据报协议</string>
<string name="transport_tls">TLS安全传输层协议</string> <string name="transport_tls">TLS安全传输层协议</string>
@ -351,9 +351,6 @@
<string name="contact_editor_write_permission_denied">写入联系人权限被拒绝,无法编辑联系人</string> <string name="contact_editor_write_permission_denied">写入联系人权限被拒绝,无法编辑联系人</string>
<string name="contact_delete_one_dialog">您要删除这个联系人吗?\n它也将会从您的设备通讯录中删除</string> <string name="contact_delete_one_dialog">您要删除这个联系人吗?\n它也将会从您的设备通讯录中删除</string>
<string name="contact_delete_many_dialog">您确定要删除这些联系人吗?\n他们将会从您的设备通讯录中删除</string> <string name="contact_delete_many_dialog">您确定要删除这些联系人吗?\n他们将会从您的设备通讯录中删除</string>
<plurals name="history_delete_dialog">
<item quantity="other">\@string/history_delete_one_dialog</item>
</plurals>
<string name="contact_new_choose_sync_account">选择保存联系人的位置</string> <string name="contact_new_choose_sync_account">选择保存联系人的位置</string>
<string name="contact_local_sync_account">本地存储</string> <string name="contact_local_sync_account">本地存储</string>
<string name="dialer_address_bar_hint">输入电话号码或地址</string> <string name="dialer_address_bar_hint">输入电话号码或地址</string>
@ -503,17 +500,11 @@
<string name="chat_message_forward_confirmation_dialog">是否要在此聊天室转发信息?</string> <string name="chat_message_forward_confirmation_dialog">是否要在此聊天室转发信息?</string>
<string name="chat_room_ephemeral_fragment_title">短暂信息</string> <string name="chat_room_ephemeral_fragment_title">短暂信息</string>
<string name="chat_room_creation_failed_snack">群组创建失败</string> <string name="chat_room_creation_failed_snack">群组创建失败</string>
<plurals name="chat_room_delete_dialog">
<item quantity="other">\@string/chat_room_delete_one_dialog</item>
</plurals>
<string name="call_video_update_requested_dialog">对方要求启用视讯</string> <string name="call_video_update_requested_dialog">对方要求启用视讯</string>
<string name="assistant_phone_number_link_info_content">\n如果将您的帐户关联您的电话号码您的朋友们可以更容易的找到你。\n\n您在通讯录里可以查看谁在使用&appName;,他们也同样可以通过&appName;联系您。\n</string> <string name="assistant_phone_number_link_info_content">\n如果将您的帐户关联您的电话号码您的朋友们可以更容易的找到你。\n\n您在通讯录里可以查看谁在使用&appName;,他们也同样可以通过&appName;联系您。\n</string>
<string name="assistant_login_desc">请输入您的用户名与密码和您的SIP域名</string> <string name="assistant_login_desc">请输入您的用户名与密码和您的SIP域名</string>
<string name="assistant_validate_account_1">您的帐户已经创建。请检查邮件以驗證您的帐户:</string> <string name="assistant_validate_account_1">您的帐户已经创建。请检查邮件以驗證您的帐户:</string>
<string name="call_stats_video_resolution_received">接收视频分辨率:</string> <string name="call_stats_video_resolution_received">接收视频分辨率:</string>
<plurals name="contact_delete_dialog">
<item quantity="other">\@string/contact_delete_one_dialog</item>
</plurals>
<string name="chat_settings_mark_as_read_notif_dismissal_title">撤消通知后标记为已读</string> <string name="chat_settings_mark_as_read_notif_dismissal_title">撤消通知后标记为已读</string>
<string name="advanced_settings_send_debug_logs_title">发送日志</string> <string name="advanced_settings_send_debug_logs_title">发送日志</string>
<string name="advanced_settings_reset_debug_logs_title">重启日志</string> <string name="advanced_settings_reset_debug_logs_title">重启日志</string>
@ -549,7 +540,7 @@
<string name="chat_room_sending_message_hint">信息</string> <string name="chat_room_sending_message_hint">信息</string>
<string name="chat_message_voice_recording_hold_to_record">按住按钮录制语音信息</string> <string name="chat_message_voice_recording_hold_to_record">按住按钮录制语音信息</string>
<string name="chat_message_voice_recording_playback_low_volume">您的媒体音量很低,您可能需要提高音量</string> <string name="chat_message_voice_recording_playback_low_volume">您的媒体音量很低,您可能需要提高音量</string>
<plurals name="chat_room_unread_messages_event"> <plurals name="chat_room_unread_messages_event" tools:ignore="UnusedQuantity">
<item quantity="one">%1$d 未读消息</item> <item quantity="one">%1$d 未读消息</item>
<item quantity="other">%1$d 未读消息</item> <item quantity="other">%1$d 未读消息</item>
</plurals> </plurals>

View file

@ -541,7 +541,6 @@
<string name="content_descripton_scroll_to_bottom">滑動到畫面底部或第一則未讀訊息</string> <string name="content_descripton_scroll_to_bottom">滑動到畫面底部或第一則未讀訊息</string>
<string name="content_description_copy_conference_address">複製會議地址</string> <string name="content_description_copy_conference_address">複製會議地址</string>
<string name="content_description_toggle_conference_info_details">切換顯示會議詳細資訊</string> <string name="content_description_toggle_conference_info_details">切換顯示會議詳細資訊</string>
<string name="chat_event_ephemeral_enabled">您已開啟「閱後即焚」訊息</string>
<string name="chat_settings_use_in_app_file_viewer_title">總是在此程式中開啟</string> <string name="chat_settings_use_in_app_file_viewer_title">總是在此程式中開啟</string>
<string name="chat_settings_use_in_app_file_viewer_summary">還是可以匯出到第三方應用程式</string> <string name="chat_settings_use_in_app_file_viewer_summary">還是可以匯出到第三方應用程式</string>
<string name="chat_settings_auto_download_voice_recordings">自動下載收到的錄音檔</string> <string name="chat_settings_auto_download_voice_recordings">自動下載收到的錄音檔</string>

View file

@ -920,4 +920,5 @@
<string name="content_description_presence_online">User is online</string> <string name="content_description_presence_online">User is online</string>
<string name="content_description_presence_offline">User is offline</string> <string name="content_description_presence_offline">User is offline</string>
<string name="content_description_presence_do_not_disturb">User is asking not to be disturbed</string> <string name="content_description_presence_do_not_disturb">User is asking not to be disturbed</string>
<string name="content_description_emoji_picker">Toggle emoji picker visibility</string>
</resources> </resources>

View file

@ -11,6 +11,7 @@
<locale android:name="he"/> <locale android:name="he"/>
<locale android:name="hu"/> <locale android:name="hu"/>
<locale android:name="it"/> <locale android:name="it"/>
<locale android:name="ja"/>
<locale android:name="ka"/> <locale android:name="ka"/>
<locale android:name="nl"/> <locale android:name="nl"/>
<locale android:name="pt"/> <locale android:name="pt"/>