mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-27 16:49:21 +00:00
Factorized code related to copying data into clipboard, added exception catch
This commit is contained in:
parent
5ad7b5da14
commit
d467699388
13 changed files with 83 additions and 118 deletions
|
|
@ -19,9 +19,6 @@
|
|||
*/
|
||||
package org.linphone.ui.call.conference.fragment
|
||||
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.os.SystemClock
|
||||
import android.view.LayoutInflater
|
||||
|
|
@ -43,6 +40,7 @@ import org.linphone.ui.call.CallActivity
|
|||
import org.linphone.ui.call.fragment.GenericCallFragment
|
||||
import org.linphone.ui.call.viewmodel.CallsViewModel
|
||||
import org.linphone.ui.call.viewmodel.CurrentCallViewModel
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.startAnimatedDrawable
|
||||
|
||||
|
|
@ -272,14 +270,12 @@ class ActiveConferenceCallFragment : GenericCallFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
binding.setShareConferenceClickListener {
|
||||
binding.setCopyConferenceUriToClipboardClickListener {
|
||||
val sipUri = callViewModel.conferenceModel.sipUri.value.orEmpty()
|
||||
if (sipUri.isNotEmpty()) {
|
||||
Log.i("$TAG Sharing conference SIP URI [$sipUri]")
|
||||
|
||||
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
Log.i("$TAG Copying conference SIP URI [$sipUri] into clipboard")
|
||||
val label = "Conference SIP address"
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText(label, sipUri))
|
||||
AppUtils.copyToClipboard(requireContext(), label, sipUri)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,9 +19,6 @@
|
|||
*/
|
||||
package org.linphone.ui.call.conference.fragment
|
||||
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
|
|
@ -45,6 +42,7 @@ import org.linphone.ui.GenericActivity
|
|||
import org.linphone.ui.call.adapter.ConferenceParticipantsListAdapter
|
||||
import org.linphone.ui.call.fragment.GenericCallFragment
|
||||
import org.linphone.ui.call.viewmodel.CurrentCallViewModel
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.ConfirmationDialogModel
|
||||
import org.linphone.utils.DialogUtils
|
||||
|
||||
|
|
@ -207,10 +205,8 @@ class ConferenceParticipantsListFragment : GenericCallFragment() {
|
|||
val sipUri = viewModel.conferenceModel.sipUri.value.orEmpty()
|
||||
if (sipUri.isNotEmpty()) {
|
||||
Log.i("$TAG Sharing conference SIP URI [$sipUri]")
|
||||
|
||||
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val label = "Conference SIP address"
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText(label, sipUri))
|
||||
AppUtils.copyToClipboard(requireContext(), label, sipUri)
|
||||
}
|
||||
|
||||
popupWindow.dismiss()
|
||||
|
|
|
|||
|
|
@ -19,9 +19,6 @@
|
|||
*/
|
||||
package org.linphone.ui.main.chat.fragment
|
||||
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
|
|
@ -46,6 +43,7 @@ import org.linphone.ui.main.chat.viewmodel.ConversationInfoViewModel
|
|||
import org.linphone.ui.main.fragment.SlidingPaneChildFragment
|
||||
import org.linphone.utils.ConfirmationDialogModel
|
||||
import org.linphone.ui.main.model.GroupSetOrEditSubjectDialogModel
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.DialogUtils
|
||||
import org.linphone.utils.Event
|
||||
|
||||
|
|
@ -428,14 +426,13 @@ class ConversationInfoFragment : SlidingPaneChildFragment() {
|
|||
|
||||
popupView.setCopySipUriClickListener {
|
||||
val sipUri = participantModel.sipUri
|
||||
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText("SIP address", sipUri))
|
||||
|
||||
val message = getString(R.string.sip_address_copied_to_clipboard_toast)
|
||||
(requireActivity() as GenericActivity).showGreenToast(
|
||||
message,
|
||||
R.drawable.check
|
||||
)
|
||||
if (AppUtils.copyToClipboard(requireContext(), "SIP address", sipUri)) {
|
||||
val message = getString(R.string.sip_address_copied_to_clipboard_toast)
|
||||
(requireActivity() as GenericActivity).showGreenToast(
|
||||
message,
|
||||
R.drawable.check
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Elevation is for showing a shadow around the popup
|
||||
|
|
@ -490,12 +487,9 @@ class ConversationInfoFragment : SlidingPaneChildFragment() {
|
|||
}
|
||||
|
||||
private fun copyAddressToClipboard(value: String) {
|
||||
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText("SIP address", value))
|
||||
val message = getString(R.string.sip_address_copied_to_clipboard_toast)
|
||||
(requireActivity() as GenericActivity).showGreenToast(
|
||||
message,
|
||||
R.drawable.check
|
||||
)
|
||||
if (AppUtils.copyToClipboard(requireContext(), "SIP address", value)) {
|
||||
val message = getString(R.string.sip_address_copied_to_clipboard_toast)
|
||||
(requireActivity() as GenericActivity).showGreenToast(message, R.drawable.check)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,9 +19,6 @@
|
|||
*/
|
||||
package org.linphone.ui.main.chat.viewmodel
|
||||
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
|
|
@ -31,6 +28,7 @@ import org.linphone.core.tools.Log
|
|||
import org.linphone.databinding.ChatBubbleEmojiPickerBottomSheetBinding
|
||||
import org.linphone.ui.GenericViewModel
|
||||
import org.linphone.ui.main.chat.model.MessageModel
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.Event
|
||||
|
||||
class ChatMessageLongPressViewModel : GenericViewModel() {
|
||||
|
|
@ -148,12 +146,12 @@ class ChatMessageLongPressViewModel : GenericViewModel() {
|
|||
|
||||
@UiThread
|
||||
fun copyClickListener() {
|
||||
Log.i("$TAG Copying message text into clipboard")
|
||||
|
||||
val text = messageModel.value?.getRawTextContent()
|
||||
val clipboard = coreContext.context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val label = "Message"
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText(label, text))
|
||||
val text = messageModel.value?.getRawTextContent().orEmpty()
|
||||
if (text.isNotEmpty()) {
|
||||
Log.i("$TAG Copying message text into clipboard")
|
||||
val label = "Message"
|
||||
AppUtils.copyToClipboard(coreContext.context, label, text)
|
||||
}
|
||||
|
||||
dismiss()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,9 +21,6 @@ package org.linphone.ui.main.contacts.fragment
|
|||
|
||||
import android.app.Dialog
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.provider.ContactsContract
|
||||
|
|
@ -252,19 +249,15 @@ class ContactFragment : SlidingPaneChildFragment() {
|
|||
}
|
||||
|
||||
private fun copyNumberOrAddressToClipboard(value: String, isSip: Boolean) {
|
||||
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val label = if (isSip) "SIP address" else "Phone number"
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText(label, value))
|
||||
|
||||
val message = if (isSip) {
|
||||
getString(R.string.sip_address_copied_to_clipboard_toast)
|
||||
} else {
|
||||
getString(R.string.contact_details_phone_number_copied_to_clipboard_toast)
|
||||
if (AppUtils.copyToClipboard(requireContext(), label, value)) {
|
||||
val message = if (isSip) {
|
||||
getString(R.string.sip_address_copied_to_clipboard_toast)
|
||||
} else {
|
||||
getString(R.string.contact_details_phone_number_copied_to_clipboard_toast)
|
||||
}
|
||||
(requireActivity() as GenericActivity).showGreenToast(message, R.drawable.check)
|
||||
}
|
||||
(requireActivity() as GenericActivity).showGreenToast(
|
||||
message,
|
||||
R.drawable.check
|
||||
)
|
||||
}
|
||||
|
||||
private fun shareContact(name: String, file: File) {
|
||||
|
|
|
|||
|
|
@ -20,9 +20,6 @@
|
|||
package org.linphone.ui.main.help.fragment
|
||||
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
|
|
@ -39,6 +36,7 @@ import org.linphone.ui.fileviewer.FileViewerActivity
|
|||
import org.linphone.ui.main.MainActivity
|
||||
import org.linphone.ui.main.fragment.GenericMainFragment
|
||||
import org.linphone.ui.main.help.viewmodel.HelpViewModel
|
||||
import org.linphone.utils.AppUtils
|
||||
|
||||
class DebugFragment : GenericMainFragment() {
|
||||
private lateinit var binding: HelpDebugFragmentBinding
|
||||
|
|
@ -69,19 +67,15 @@ class DebugFragment : GenericMainFragment() {
|
|||
}
|
||||
|
||||
binding.setAppVersionClickListener {
|
||||
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val label = getString(R.string.help_troubleshooting_app_version_title)
|
||||
clipboard.setPrimaryClip(
|
||||
ClipData.newPlainText(label, viewModel.appVersion.value.orEmpty())
|
||||
)
|
||||
val value = viewModel.appVersion.value.orEmpty()
|
||||
AppUtils.copyToClipboard(requireContext(), label, value)
|
||||
}
|
||||
|
||||
binding.setSdkVersionClickListener {
|
||||
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val label = getString(R.string.help_troubleshooting_sdk_version_title)
|
||||
clipboard.setPrimaryClip(
|
||||
ClipData.newPlainText(label, viewModel.sdkVersion.value.orEmpty())
|
||||
)
|
||||
val value = viewModel.sdkVersion.value.orEmpty()
|
||||
AppUtils.copyToClipboard(requireContext(), label, value)
|
||||
}
|
||||
|
||||
viewModel.debugLogsCleanedEvent.observe(viewLifecycleOwner) {
|
||||
|
|
@ -96,9 +90,7 @@ class DebugFragment : GenericMainFragment() {
|
|||
viewModel.uploadDebugLogsFinishedEvent.observe(viewLifecycleOwner) {
|
||||
it.consume { url ->
|
||||
if (requireActivity() is AssistantActivity) {
|
||||
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val label = "Logs upload URL"
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText(label, url))
|
||||
AppUtils.copyToClipboard(requireContext(), "Logs upload URL", url)
|
||||
return@consume
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,9 +19,6 @@
|
|||
*/
|
||||
package org.linphone.ui.main.history.fragment
|
||||
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
|
|
@ -44,6 +41,7 @@ import org.linphone.ui.main.fragment.SlidingPaneChildFragment
|
|||
import org.linphone.ui.main.history.adapter.ContactHistoryListAdapter
|
||||
import org.linphone.utils.ConfirmationDialogModel
|
||||
import org.linphone.ui.main.history.viewmodel.HistoryViewModel
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.DialogUtils
|
||||
import org.linphone.utils.Event
|
||||
|
||||
|
|
@ -190,14 +188,12 @@ class HistoryFragment : SlidingPaneChildFragment() {
|
|||
}
|
||||
|
||||
private fun copyNumberOrAddressToClipboard(value: String) {
|
||||
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val label = "SIP address"
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText(label, value))
|
||||
|
||||
(requireActivity() as GenericActivity).showGreenToast(
|
||||
getString(R.string.sip_address_copied_to_clipboard_toast),
|
||||
R.drawable.check
|
||||
)
|
||||
if (AppUtils.copyToClipboard(requireContext(), "SIP address", value)) {
|
||||
(requireActivity() as GenericActivity).showGreenToast(
|
||||
getString(R.string.sip_address_copied_to_clipboard_toast),
|
||||
R.drawable.check
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showPopupMenu() {
|
||||
|
|
|
|||
|
|
@ -19,9 +19,6 @@
|
|||
*/
|
||||
package org.linphone.ui.main.history.fragment
|
||||
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
|
|
@ -47,6 +44,7 @@ import org.linphone.ui.main.fragment.AbstractMainFragment
|
|||
import org.linphone.ui.main.history.adapter.HistoryListAdapter
|
||||
import org.linphone.utils.ConfirmationDialogModel
|
||||
import org.linphone.ui.main.history.viewmodel.HistoryListViewModel
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.DialogUtils
|
||||
import org.linphone.utils.Event
|
||||
|
||||
|
|
@ -283,14 +281,12 @@ class HistoryListFragment : AbstractMainFragment() {
|
|||
}
|
||||
|
||||
private fun copyNumberOrAddressToClipboard(value: String) {
|
||||
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val label = "SIP address"
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText(label, value))
|
||||
|
||||
(requireActivity() as GenericActivity).showGreenToast(
|
||||
getString(R.string.sip_address_copied_to_clipboard_toast),
|
||||
R.drawable.check
|
||||
)
|
||||
if (AppUtils.copyToClipboard(requireContext(), "SIP address", value)) {
|
||||
(requireActivity() as GenericActivity).showGreenToast(
|
||||
getString(R.string.sip_address_copied_to_clipboard_toast),
|
||||
R.drawable.check
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showPopupMenu() {
|
||||
|
|
|
|||
|
|
@ -20,9 +20,6 @@
|
|||
package org.linphone.ui.main.meetings.fragment
|
||||
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.provider.CalendarContract
|
||||
|
|
@ -47,6 +44,7 @@ import org.linphone.ui.main.fragment.SlidingPaneChildFragment
|
|||
import org.linphone.utils.ConfirmationDialogModel
|
||||
import org.linphone.ui.main.meetings.adapter.MeetingParticipantsAdapter
|
||||
import org.linphone.ui.main.meetings.viewmodel.MeetingViewModel
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.DialogUtils
|
||||
import org.linphone.utils.Event
|
||||
|
||||
|
|
@ -136,7 +134,7 @@ class MeetingFragment : SlidingPaneChildFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
binding.setShareClickListener {
|
||||
binding.setCopyUriToClipboardClickListener {
|
||||
copyMeetingAddressIntoClipboard(uri)
|
||||
}
|
||||
|
||||
|
|
@ -249,15 +247,12 @@ class MeetingFragment : SlidingPaneChildFragment() {
|
|||
|
||||
private fun copyMeetingAddressIntoClipboard(meetingSipUri: String) {
|
||||
Log.i("$TAG Copying conference SIP URI [$meetingSipUri] into clipboard")
|
||||
|
||||
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val label = "Meeting SIP address"
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText(label, meetingSipUri))
|
||||
|
||||
(requireActivity() as GenericActivity).showGreenToast(
|
||||
getString(R.string.meeting_address_copied_to_clipboard_toast),
|
||||
R.drawable.check
|
||||
)
|
||||
if (AppUtils.copyToClipboard(requireContext(), "Meeting SIP address", meetingSipUri)) {
|
||||
(requireActivity() as GenericActivity).showGreenToast(
|
||||
getString(R.string.meeting_address_copied_to_clipboard_toast),
|
||||
R.drawable.check
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun shareMeetingInfoAsCalendarEvent() {
|
||||
|
|
|
|||
|
|
@ -19,9 +19,6 @@
|
|||
*/
|
||||
package org.linphone.ui.main.settings.fragment
|
||||
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
|
|
@ -43,6 +40,7 @@ import org.linphone.ui.GenericActivity
|
|||
import org.linphone.ui.main.fragment.GenericMainFragment
|
||||
import org.linphone.utils.ConfirmationDialogModel
|
||||
import org.linphone.ui.main.settings.viewmodel.AccountProfileViewModel
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.DialogUtils
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.FileUtils
|
||||
|
|
@ -229,13 +227,10 @@ class AccountProfileFragment : GenericMainFragment() {
|
|||
}
|
||||
|
||||
private fun copyAddressToClipboard(value: String) {
|
||||
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText("SIP address", value))
|
||||
val message = getString(R.string.sip_address_copied_to_clipboard_toast)
|
||||
(requireActivity() as GenericActivity).showGreenToast(
|
||||
message,
|
||||
R.drawable.check
|
||||
)
|
||||
if (AppUtils.copyToClipboard(requireContext(), "SIP address", value)) {
|
||||
val message = getString(R.string.sip_address_copied_to_clipboard_toast)
|
||||
(requireActivity() as GenericActivity).showGreenToast(message, R.drawable.check)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupDialPlanPicker() {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
package org.linphone.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
|
|
@ -205,6 +207,18 @@ class AppUtils {
|
|||
return name
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
fun copyToClipboard(context: Context, label: String, value: String): Boolean {
|
||||
try {
|
||||
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText(label, value))
|
||||
return true
|
||||
} catch (e: Exception) {
|
||||
Log.e("$TAG Failed to copy text [$value] with label [$label] to clipboard: $e")
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
private fun extractFirstSymbol(text: String): String {
|
||||
val sequence = StringBuilder(text.length)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
name="backClickListener"
|
||||
type="View.OnClickListener" />
|
||||
<variable
|
||||
name="shareConferenceClickListener"
|
||||
name="copyConferenceUriToClipboardClickListener"
|
||||
type="View.OnClickListener" />
|
||||
<variable
|
||||
name="callsListClickListener"
|
||||
|
|
@ -219,7 +219,7 @@
|
|||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/default_text_style_600"
|
||||
android:id="@+id/share_conference_link"
|
||||
android:onClick="@{shareConferenceClickListener}"
|
||||
android:onClick="@{copyConferenceUriToClipboardClickListener}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
name="menuClickListener"
|
||||
type="View.OnClickListener" />
|
||||
<variable
|
||||
name="shareClickListener"
|
||||
name="copyUriToClipboardClickListener"
|
||||
type="View.OnClickListener" />
|
||||
<variable
|
||||
name="joinClickListener"
|
||||
|
|
@ -139,7 +139,7 @@
|
|||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/default_text_style"
|
||||
android:id="@+id/sip_uri"
|
||||
android:onClick="@{shareClickListener}"
|
||||
android:onClick="@{copyUriToClipboardClickListener}"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue