mirror of
https://github.com/nextcloud/talk-android
synced 2025-07-10 22:34:15 +01:00
share contact from attachment dialog
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
parent
b87cc5927f
commit
4167cb63bf
@ -33,7 +33,9 @@ import android.content.ClipData
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.res.AssetFileDescriptor
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
|
import android.database.Cursor
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.drawable.ColorDrawable
|
import android.graphics.drawable.ColorDrawable
|
||||||
import android.media.MediaPlayer
|
import android.media.MediaPlayer
|
||||||
@ -46,6 +48,7 @@ import android.os.Handler
|
|||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import android.os.VibrationEffect
|
import android.os.VibrationEffect
|
||||||
import android.os.Vibrator
|
import android.os.Vibrator
|
||||||
|
import android.provider.ContactsContract
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.InputFilter
|
import android.text.InputFilter
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
@ -69,6 +72,7 @@ import android.widget.RelativeLayout
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.view.ContextThemeWrapper
|
import androidx.appcompat.view.ContextThemeWrapper
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.content.FileProvider
|
||||||
import androidx.core.content.PermissionChecker
|
import androidx.core.content.PermissionChecker
|
||||||
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
|
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
|
||||||
import androidx.core.widget.doAfterTextChanged
|
import androidx.core.widget.doAfterTextChanged
|
||||||
@ -93,6 +97,7 @@ import com.facebook.drawee.backends.pipeline.Fresco
|
|||||||
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber
|
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber
|
||||||
import com.facebook.imagepipeline.image.CloseableImage
|
import com.facebook.imagepipeline.image.CloseableImage
|
||||||
import com.google.android.flexbox.FlexboxLayout
|
import com.google.android.flexbox.FlexboxLayout
|
||||||
|
import com.nextcloud.talk.BuildConfig
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.activities.CallActivity
|
import com.nextcloud.talk.activities.CallActivity
|
||||||
import com.nextcloud.talk.activities.MainActivity
|
import com.nextcloud.talk.activities.MainActivity
|
||||||
@ -140,6 +145,7 @@ import com.nextcloud.talk.ui.recyclerview.MessageSwipeCallback
|
|||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.ConductorRemapping
|
import com.nextcloud.talk.utils.ConductorRemapping
|
||||||
import com.nextcloud.talk.utils.ConductorRemapping.remapChatController
|
import com.nextcloud.talk.utils.ConductorRemapping.remapChatController
|
||||||
|
import com.nextcloud.talk.utils.ContactUtils
|
||||||
import com.nextcloud.talk.utils.DateUtils
|
import com.nextcloud.talk.utils.DateUtils
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
import com.nextcloud.talk.utils.DisplayUtils
|
||||||
import com.nextcloud.talk.utils.KeyboardUtils
|
import com.nextcloud.talk.utils.KeyboardUtils
|
||||||
@ -1100,6 +1106,15 @@ class ChatController(args: Bundle) :
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun requestReadContacts() {
|
||||||
|
requestPermissions(
|
||||||
|
arrayOf(
|
||||||
|
Manifest.permission.READ_CONTACTS
|
||||||
|
),
|
||||||
|
REQUEST_READ_CONTACT_PERMISSION
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun checkReadOnlyState() {
|
private fun checkReadOnlyState() {
|
||||||
if (currentConversation != null && isAlive()) {
|
if (currentConversation != null && isAlive()) {
|
||||||
if (currentConversation?.shouldShowLobby(conversationUser) ?: false ||
|
if (currentConversation?.shouldShowLobby(conversationUser) ?: false ||
|
||||||
@ -1186,62 +1201,83 @@ class ChatController(args: Bundle) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
|
||||||
|
if (resultCode != RESULT_OK) {
|
||||||
|
Log.e(TAG, "resultCode for received intent was != ok")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (requestCode == REQUEST_CODE_CHOOSE_FILE) {
|
if (requestCode == REQUEST_CODE_CHOOSE_FILE) {
|
||||||
if (resultCode == RESULT_OK) {
|
try {
|
||||||
try {
|
checkNotNull(intent)
|
||||||
checkNotNull(intent)
|
filesToUpload.clear()
|
||||||
filesToUpload.clear()
|
intent.clipData?.let {
|
||||||
intent.clipData?.let {
|
for (index in 0 until it.itemCount) {
|
||||||
for (index in 0 until it.itemCount) {
|
filesToUpload.add(it.getItemAt(index).uri.toString())
|
||||||
filesToUpload.add(it.getItemAt(index).uri.toString())
|
|
||||||
}
|
|
||||||
} ?: run {
|
|
||||||
checkNotNull(intent.data)
|
|
||||||
intent.data.let {
|
|
||||||
filesToUpload.add(intent.data.toString())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
require(filesToUpload.isNotEmpty())
|
} ?: run {
|
||||||
|
checkNotNull(intent.data)
|
||||||
val filenamesWithLinebreaks = StringBuilder("\n")
|
intent.data.let {
|
||||||
|
filesToUpload.add(intent.data.toString())
|
||||||
for (file in filesToUpload) {
|
|
||||||
val filename = UriUtils.getFileName(Uri.parse(file), context)
|
|
||||||
filenamesWithLinebreaks.append(filename).append("\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val confirmationQuestion = when (filesToUpload.size) {
|
|
||||||
1 -> context?.resources?.getString(R.string.nc_upload_confirm_send_single)?.let {
|
|
||||||
String.format(it, title)
|
|
||||||
}
|
|
||||||
else -> context?.resources?.getString(R.string.nc_upload_confirm_send_multiple)?.let {
|
|
||||||
String.format(it, title)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LovelyStandardDialog(activity)
|
|
||||||
.setPositiveButtonColorRes(R.color.nc_darkGreen)
|
|
||||||
.setTitle(confirmationQuestion)
|
|
||||||
.setMessage(filenamesWithLinebreaks.toString())
|
|
||||||
.setPositiveButton(R.string.nc_yes) { v ->
|
|
||||||
if (UploadAndShareFilesWorker.isStoragePermissionGranted(context!!)) {
|
|
||||||
uploadFiles(filesToUpload, false)
|
|
||||||
} else {
|
|
||||||
UploadAndShareFilesWorker.requestStoragePermission(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.setNegativeButton(R.string.nc_no) {}
|
|
||||||
.show()
|
|
||||||
} catch (e: IllegalStateException) {
|
|
||||||
Toast.makeText(context, context?.resources?.getString(R.string.nc_upload_failed), Toast.LENGTH_LONG)
|
|
||||||
.show()
|
|
||||||
Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e)
|
|
||||||
} catch (e: IllegalArgumentException) {
|
|
||||||
Toast.makeText(context, context?.resources?.getString(R.string.nc_upload_failed), Toast.LENGTH_LONG)
|
|
||||||
.show()
|
|
||||||
Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e)
|
|
||||||
}
|
}
|
||||||
|
require(filesToUpload.isNotEmpty())
|
||||||
|
|
||||||
|
val filenamesWithLinebreaks = StringBuilder("\n")
|
||||||
|
|
||||||
|
for (file in filesToUpload) {
|
||||||
|
val filename = UriUtils.getFileName(Uri.parse(file), context)
|
||||||
|
filenamesWithLinebreaks.append(filename).append("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
val confirmationQuestion = when (filesToUpload.size) {
|
||||||
|
1 -> context?.resources?.getString(R.string.nc_upload_confirm_send_single)?.let {
|
||||||
|
String.format(it, title)
|
||||||
|
}
|
||||||
|
else -> context?.resources?.getString(R.string.nc_upload_confirm_send_multiple)?.let {
|
||||||
|
String.format(it, title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LovelyStandardDialog(activity)
|
||||||
|
.setPositiveButtonColorRes(R.color.nc_darkGreen)
|
||||||
|
.setTitle(confirmationQuestion)
|
||||||
|
.setMessage(filenamesWithLinebreaks.toString())
|
||||||
|
.setPositiveButton(R.string.nc_yes) { v ->
|
||||||
|
if (UploadAndShareFilesWorker.isStoragePermissionGranted(context!!)) {
|
||||||
|
uploadFiles(filesToUpload, false)
|
||||||
|
} else {
|
||||||
|
UploadAndShareFilesWorker.requestStoragePermission(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.setNegativeButton(R.string.nc_no) {}
|
||||||
|
.show()
|
||||||
|
} catch (e: IllegalStateException) {
|
||||||
|
Toast.makeText(context, context?.resources?.getString(R.string.nc_upload_failed), Toast.LENGTH_LONG)
|
||||||
|
.show()
|
||||||
|
Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e)
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
Toast.makeText(context, context?.resources?.getString(R.string.nc_upload_failed), Toast.LENGTH_LONG)
|
||||||
|
.show()
|
||||||
|
Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e)
|
||||||
}
|
}
|
||||||
|
} else if (requestCode == REQUEST_CODE_SELECT_CONTACT) {
|
||||||
|
val contactUri = intent?.data ?: return
|
||||||
|
val cursor: Cursor? = activity?.contentResolver!!.query(contactUri, null, null, null, null)
|
||||||
|
|
||||||
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
|
val id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID))
|
||||||
|
val fileName = ContactUtils.getDisplayNameFromDeviceContact(context!!, id) + ".vcf"
|
||||||
|
val file = File(context?.cacheDir, fileName)
|
||||||
|
writeContactToVcfFile(cursor, file)
|
||||||
|
|
||||||
|
val shareUri = FileProvider.getUriForFile(
|
||||||
|
activity!!,
|
||||||
|
BuildConfig.APPLICATION_ID,
|
||||||
|
File(file.absolutePath)
|
||||||
|
)
|
||||||
|
uploadFiles(mutableListOf(shareUri.toString()), false)
|
||||||
|
}
|
||||||
|
cursor?.close()
|
||||||
} else if (requestCode == REQUEST_CODE_PICK_CAMERA) {
|
} else if (requestCode == REQUEST_CODE_PICK_CAMERA) {
|
||||||
if (resultCode == RESULT_OK) {
|
if (resultCode == RESULT_OK) {
|
||||||
try {
|
try {
|
||||||
@ -1273,6 +1309,21 @@ class ChatController(args: Bundle) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun writeContactToVcfFile(cursor: Cursor, file: File) {
|
||||||
|
val lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY))
|
||||||
|
val uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey)
|
||||||
|
|
||||||
|
val fd: AssetFileDescriptor = activity?.contentResolver!!.openAssetFileDescriptor(uri, "r")!!
|
||||||
|
val fis = fd.createInputStream()
|
||||||
|
|
||||||
|
file.createNewFile()
|
||||||
|
fis.use { input ->
|
||||||
|
file.outputStream().use { output ->
|
||||||
|
input.copyTo(output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||||
if (requestCode == UploadAndShareFilesWorker.REQUEST_PERMISSION) {
|
if (requestCode == UploadAndShareFilesWorker.REQUEST_PERMISSION) {
|
||||||
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||||
@ -1295,6 +1346,17 @@ class ChatController(args: Bundle) :
|
|||||||
Toast.LENGTH_LONG
|
Toast.LENGTH_LONG
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
|
} else if (requestCode == REQUEST_READ_CONTACT_PERMISSION) {
|
||||||
|
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
val intent = Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI)
|
||||||
|
startActivityForResult(intent, REQUEST_CODE_SELECT_CONTACT)
|
||||||
|
} else {
|
||||||
|
Toast.makeText(
|
||||||
|
context,
|
||||||
|
context!!.getString(R.string.nc_share_contact_permission),
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
}
|
||||||
} else if (requestCode == REQUEST_CAMERA_PERMISSION) {
|
} else if (requestCode == REQUEST_CAMERA_PERMISSION) {
|
||||||
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||||
Log.d(TAG, "launch cam activity since permission for cam has been granted")
|
Log.d(TAG, "launch cam activity since permission for cam has been granted")
|
||||||
@ -1358,6 +1420,10 @@ class ChatController(args: Bundle) :
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun sendChooseContactIntent() {
|
||||||
|
requestReadContacts()
|
||||||
|
}
|
||||||
|
|
||||||
fun showBrowserScreen(browserType: BrowserController.BrowserType) {
|
fun showBrowserScreen(browserType: BrowserController.BrowserType) {
|
||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
bundle.putParcelable(BundleKeys.KEY_BROWSER_TYPE, Parcels.wrap<BrowserController.BrowserType>(browserType))
|
bundle.putParcelable(BundleKeys.KEY_BROWSER_TYPE, Parcels.wrap<BrowserController.BrowserType>(browserType))
|
||||||
@ -2621,7 +2687,9 @@ class ChatController(args: Bundle) :
|
|||||||
private const val MESSAGE_MAX_LENGTH: Int = 1000
|
private const val MESSAGE_MAX_LENGTH: Int = 1000
|
||||||
private const val AGE_THREHOLD_FOR_DELETE_MESSAGE: Int = 21600000 // (6 hours in millis = 6 * 3600 * 1000)
|
private const val AGE_THREHOLD_FOR_DELETE_MESSAGE: Int = 21600000 // (6 hours in millis = 6 * 3600 * 1000)
|
||||||
private const val REQUEST_CODE_CHOOSE_FILE: Int = 555
|
private const val REQUEST_CODE_CHOOSE_FILE: Int = 555
|
||||||
|
private const val REQUEST_CODE_SELECT_CONTACT: Int = 666
|
||||||
private const val REQUEST_RECORD_AUDIO_PERMISSION = 222
|
private const val REQUEST_RECORD_AUDIO_PERMISSION = 222
|
||||||
|
private const val REQUEST_READ_CONTACT_PERMISSION = 234
|
||||||
private const val REQUEST_CAMERA_PERMISSION = 223
|
private const val REQUEST_CAMERA_PERMISSION = 223
|
||||||
private const val REQUEST_CODE_PICK_CAMERA: Int = 333
|
private const val REQUEST_CODE_PICK_CAMERA: Int = 333
|
||||||
private const val OBJECT_MESSAGE: String = "{object}"
|
private const val OBJECT_MESSAGE: String = "{object}"
|
||||||
|
@ -48,6 +48,7 @@ import com.nextcloud.talk.application.NextcloudTalkApplication
|
|||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
import com.nextcloud.talk.models.json.search.ContactsByNumberOverall
|
import com.nextcloud.talk.models.json.search.ContactsByNumberOverall
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
|
import com.nextcloud.talk.utils.ContactUtils
|
||||||
import com.nextcloud.talk.utils.database.user.UserUtils
|
import com.nextcloud.talk.utils.database.user.UserUtils
|
||||||
import com.nextcloud.talk.utils.preferences.AppPreferences
|
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||||
import io.reactivex.Observer
|
import io.reactivex.Observer
|
||||||
@ -299,7 +300,7 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
}
|
}
|
||||||
|
|
||||||
val numbers = getPhoneNumbersFromDeviceContact(id)
|
val numbers = getPhoneNumbersFromDeviceContact(id)
|
||||||
val displayName = getDisplayNameFromDeviceContact(id)
|
val displayName = ContactUtils.getDisplayNameFromDeviceContact(context, id)
|
||||||
|
|
||||||
if (displayName == null) {
|
if (displayName == null) {
|
||||||
return
|
return
|
||||||
@ -393,33 +394,6 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getDisplayNameFromDeviceContact(id: String?): String? {
|
|
||||||
var displayName: String? = null
|
|
||||||
val whereName =
|
|
||||||
ContactsContract.Data.MIMETYPE +
|
|
||||||
" = ? AND " +
|
|
||||||
ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID +
|
|
||||||
" = ?"
|
|
||||||
val whereNameParams = arrayOf(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, id)
|
|
||||||
val nameCursor = context.contentResolver.query(
|
|
||||||
ContactsContract.Data.CONTENT_URI,
|
|
||||||
null,
|
|
||||||
whereName,
|
|
||||||
whereNameParams,
|
|
||||||
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME
|
|
||||||
)
|
|
||||||
if (nameCursor != null) {
|
|
||||||
while (nameCursor.moveToNext()) {
|
|
||||||
displayName =
|
|
||||||
nameCursor.getString(
|
|
||||||
nameCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
nameCursor.close()
|
|
||||||
}
|
|
||||||
return displayName
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getPhoneNumbersFromDeviceContact(id: String?): MutableList<String> {
|
private fun getPhoneNumbersFromDeviceContact(id: String?): MutableList<String> {
|
||||||
val numbers = mutableListOf<String>()
|
val numbers = mutableListOf<String>()
|
||||||
val phonesNumbersCursor = context.contentResolver.query(
|
val phonesNumbersCursor = context.contentResolver.query(
|
||||||
|
@ -79,6 +79,11 @@ class AttachmentDialog(val activity: Activity, var chatController: ChatControlle
|
|||||||
chatController.showBrowserScreen(BrowserController.BrowserType.DAV_BROWSER)
|
chatController.showBrowserScreen(BrowserController.BrowserType.DAV_BROWSER)
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dialogAttachmentBinding.menuAttachContact.setOnClickListener {
|
||||||
|
chatController.sendChooseContactIntent()
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
|
34
app/src/main/java/com/nextcloud/talk/utils/ContactUtils.kt
Normal file
34
app/src/main/java/com/nextcloud/talk/utils/ContactUtils.kt
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package com.nextcloud.talk.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.provider.ContactsContract
|
||||||
|
|
||||||
|
object ContactUtils {
|
||||||
|
|
||||||
|
fun getDisplayNameFromDeviceContact(context: Context, id: String?): String? {
|
||||||
|
var displayName: String? = null
|
||||||
|
val whereName =
|
||||||
|
ContactsContract.Data.MIMETYPE +
|
||||||
|
" = ? AND " +
|
||||||
|
ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID +
|
||||||
|
" = ?"
|
||||||
|
val whereNameParams = arrayOf(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, id)
|
||||||
|
val nameCursor = context.contentResolver.query(
|
||||||
|
ContactsContract.Data.CONTENT_URI,
|
||||||
|
null,
|
||||||
|
whereName,
|
||||||
|
whereNameParams,
|
||||||
|
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME
|
||||||
|
)
|
||||||
|
if (nameCursor != null) {
|
||||||
|
while (nameCursor.moveToNext()) {
|
||||||
|
displayName =
|
||||||
|
nameCursor.getString(
|
||||||
|
nameCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
nameCursor.close()
|
||||||
|
}
|
||||||
|
return displayName
|
||||||
|
}
|
||||||
|
}
|
10
app/src/main/res/drawable/ic_baseline_person_24.xml
Normal file
10
app/src/main/res/drawable/ic_baseline_person_24.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
|
||||||
|
</vector>
|
@ -39,6 +39,39 @@
|
|||||||
android:textColor="@color/medium_emphasis_text"
|
android:textColor="@color/medium_emphasis_text"
|
||||||
android:textSize="@dimen/bottom_sheet_text_size" />
|
android:textSize="@dimen/bottom_sheet_text_size" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/menu_attach_contact"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingLeft="@dimen/standard_padding"
|
||||||
|
android:paddingTop="@dimen/standard_half_padding"
|
||||||
|
android:paddingRight="@dimen/standard_padding"
|
||||||
|
android:paddingBottom="@dimen/standard_half_padding"
|
||||||
|
tools:ignore="UseCompoundDrawables">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/menu_icon_share_contact"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
android:src="@drawable/ic_baseline_person_24"
|
||||||
|
app:tint="@color/colorPrimary" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/shareContactText"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="start|center_vertical"
|
||||||
|
android:layout_marginStart="@dimen/standard_margin"
|
||||||
|
android:text="@string/nc_share_contact"
|
||||||
|
android:textAlignment="viewStart"
|
||||||
|
android:textColor="@color/high_emphasis_text"
|
||||||
|
android:textSize="@dimen/bottom_sheet_text_size" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/menu_share_location"
|
android:id="@+id/menu_share_location"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -72,39 +105,6 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/menu_attach_file_from_local"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:paddingLeft="@dimen/standard_padding"
|
|
||||||
android:paddingTop="@dimen/standard_half_padding"
|
|
||||||
android:paddingRight="@dimen/standard_padding"
|
|
||||||
android:paddingBottom="@dimen/standard_half_padding"
|
|
||||||
tools:ignore="UseCompoundDrawables">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/menu_icon_attach_file_from_local"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:contentDescription="@null"
|
|
||||||
android:src="@drawable/upload"
|
|
||||||
app:tint="@color/colorPrimary" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
|
||||||
android:id="@+id/txt_attach_file_from_local"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="start|center_vertical"
|
|
||||||
android:layout_marginStart="@dimen/standard_margin"
|
|
||||||
android:text="@string/nc_upload_local_file"
|
|
||||||
android:textAlignment="viewStart"
|
|
||||||
android:textColor="@color/high_emphasis_text"
|
|
||||||
android:textSize="@dimen/bottom_sheet_text_size" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/menu_attach_picture_from_cam"
|
android:id="@+id/menu_attach_picture_from_cam"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -138,6 +138,39 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/menu_attach_file_from_local"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingLeft="@dimen/standard_padding"
|
||||||
|
android:paddingTop="@dimen/standard_half_padding"
|
||||||
|
android:paddingRight="@dimen/standard_padding"
|
||||||
|
android:paddingBottom="@dimen/standard_half_padding"
|
||||||
|
tools:ignore="UseCompoundDrawables">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/menu_icon_attach_file_from_local"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
android:src="@drawable/upload"
|
||||||
|
app:tint="@color/colorPrimary" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/txt_attach_file_from_local"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="start|center_vertical"
|
||||||
|
android:layout_marginStart="@dimen/standard_margin"
|
||||||
|
android:text="@string/nc_upload_local_file"
|
||||||
|
android:textAlignment="viewStart"
|
||||||
|
android:textColor="@color/high_emphasis_text"
|
||||||
|
android:textSize="@dimen/bottom_sheet_text_size" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/menu_attach_file_from_cloud"
|
android:id="@+id/menu_attach_file_from_cloud"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -406,6 +406,10 @@
|
|||||||
<string name="nc_location_current_position_description">Your current location</string>
|
<string name="nc_location_current_position_description">Your current location</string>
|
||||||
<string name="nc_location_unknown">Position unknown</string>
|
<string name="nc_location_unknown">Position unknown</string>
|
||||||
|
|
||||||
|
<!-- share contact -->
|
||||||
|
<string name="nc_share_contact">Share contact</string>
|
||||||
|
<string name="nc_share_contact_permission">Permission to read contacts is required</string>
|
||||||
|
|
||||||
<!-- voice messages -->
|
<!-- voice messages -->
|
||||||
<string name="nc_voice_message_filename">Talk recording from %1$s (%2$s)</string>
|
<string name="nc_voice_message_filename">Talk recording from %1$s (%2$s)</string>
|
||||||
<string name="nc_voice_message_hold_to_record_info">Hold to record, release to send.</string>
|
<string name="nc_voice_message_hold_to_record_info">Hold to record, release to send.</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user