mirror of
https://github.com/nextcloud/talk-android.git
synced 2024-11-26 06:55:42 +03:00
Merge pull request #3752 from nextcloud/new-result-apis
Use new Result APIs instead of startActivityForResult() and onActivityResult().
This commit is contained in:
commit
4c7ddae084
5 changed files with 339 additions and 253 deletions
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Nextcloud Talk - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2024 Parneet Singh <gurayaparneet@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2024 Giacomo Pacini <giacomo@paciosoft.com>
|
||||
* SPDX-FileCopyrightText: 2023 Ezhil Shanmugham <ezhil56x.contact@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2021-2022 Marcel Hibbe <dev@mhibbe.de>
|
||||
|
@ -9,11 +10,13 @@
|
|||
* SPDX-FileCopyrightText: 2017-2019 Mario Danic <mario@lovelyhq.com>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.chat
|
||||
|
||||
import android.Manifest
|
||||
import android.animation.ObjectAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
|
@ -71,6 +74,8 @@ import android.widget.RelativeLayout.LayoutParams
|
|||
import android.widget.SeekBar
|
||||
import android.widget.TextView
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.activity.result.ActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.view.ContextThemeWrapper
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.FileProvider
|
||||
|
@ -278,6 +283,46 @@ class ChatActivity :
|
|||
|
||||
private lateinit var editMessage: ChatMessage
|
||||
|
||||
private val startSelectContactForResult = registerForActivityResult(
|
||||
ActivityResultContracts
|
||||
.StartActivityForResult()
|
||||
) {
|
||||
executeIfResultOk(it) { intent ->
|
||||
onSelectContactResult(intent)
|
||||
}
|
||||
}
|
||||
|
||||
private val startChooseFileIntentForResult = registerForActivityResult(
|
||||
ActivityResultContracts.StartActivityForResult()
|
||||
) {
|
||||
executeIfResultOk(it) { intent ->
|
||||
onChooseFileResult(intent)
|
||||
}
|
||||
}
|
||||
|
||||
private val startRemoteFileBrowsingForResult = registerForActivityResult(
|
||||
ActivityResultContracts.StartActivityForResult()
|
||||
) {
|
||||
executeIfResultOk(it) { intent ->
|
||||
onRemoteFileBrowsingResult(intent)
|
||||
}
|
||||
}
|
||||
|
||||
private val startMessageSearchForResult =
|
||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
executeIfResultOk(it) { intent ->
|
||||
onMessageSearchResult(intent)
|
||||
}
|
||||
}
|
||||
|
||||
private val startPickCameraIntentForResult = registerForActivityResult(
|
||||
ActivityResultContracts.StartActivityForResult()
|
||||
) {
|
||||
executeIfResultOk(it) { intent ->
|
||||
onPickCameraResult(intent)
|
||||
}
|
||||
}
|
||||
|
||||
override val view: View
|
||||
get() = binding.root
|
||||
|
||||
|
@ -2967,170 +3012,167 @@ class ChatActivity :
|
|||
}
|
||||
}
|
||||
|
||||
@Throws(IllegalStateException::class)
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, intent)
|
||||
if (resultCode != RESULT_OK && (requestCode != REQUEST_CODE_MESSAGE_SEARCH)) {
|
||||
Log.e(TAG, "resultCode for received intent was != ok")
|
||||
return
|
||||
private fun onRemoteFileBrowsingResult(intent: Intent?) {
|
||||
val pathList = intent?.getStringArrayListExtra(RemoteFileBrowserActivity.EXTRA_SELECTED_PATHS)
|
||||
if (pathList?.size!! >= 1) {
|
||||
pathList
|
||||
.chunked(CHUNK_SIZE)
|
||||
.forEach { paths ->
|
||||
val data = Data.Builder()
|
||||
.putLong(KEY_INTERNAL_USER_ID, conversationUser!!.id!!)
|
||||
.putString(KEY_ROOM_TOKEN, roomToken)
|
||||
.putStringArray(KEY_FILE_PATHS, paths.toTypedArray())
|
||||
.build()
|
||||
val worker = OneTimeWorkRequest.Builder(ShareOperationWorker::class.java)
|
||||
.setInputData(data)
|
||||
.build()
|
||||
WorkManager.getInstance().enqueue(worker)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when (requestCode) {
|
||||
REQUEST_CODE_SELECT_REMOTE_FILES -> {
|
||||
val pathList = intent?.getStringArrayListExtra(RemoteFileBrowserActivity.EXTRA_SELECTED_PATHS)
|
||||
if (pathList?.size!! >= 1) {
|
||||
pathList
|
||||
.chunked(CHUNK_SIZE)
|
||||
.forEach { paths ->
|
||||
val data = Data.Builder()
|
||||
.putLong(KEY_INTERNAL_USER_ID, conversationUser!!.id!!)
|
||||
.putString(KEY_ROOM_TOKEN, roomToken)
|
||||
.putStringArray(KEY_FILE_PATHS, paths.toTypedArray())
|
||||
.build()
|
||||
val worker = OneTimeWorkRequest.Builder(ShareOperationWorker::class.java)
|
||||
.setInputData(data)
|
||||
.build()
|
||||
WorkManager.getInstance().enqueue(worker)
|
||||
}
|
||||
@Throws(IllegalStateException::class)
|
||||
private fun onChooseFileResult(intent: Intent?) {
|
||||
try {
|
||||
checkNotNull(intent)
|
||||
filesToUpload.clear()
|
||||
intent.clipData?.let {
|
||||
for (index in 0 until it.itemCount) {
|
||||
filesToUpload.add(it.getItemAt(index).uri.toString())
|
||||
}
|
||||
} ?: run {
|
||||
checkNotNull(intent.data)
|
||||
intent.data.let {
|
||||
filesToUpload.add(intent.data.toString())
|
||||
}
|
||||
}
|
||||
require(filesToUpload.isNotEmpty())
|
||||
|
||||
REQUEST_CODE_CHOOSE_FILE -> {
|
||||
try {
|
||||
checkNotNull(intent)
|
||||
filesToUpload.clear()
|
||||
intent.clipData?.let {
|
||||
for (index in 0 until it.itemCount) {
|
||||
filesToUpload.add(it.getItemAt(index).uri.toString())
|
||||
}
|
||||
} ?: run {
|
||||
checkNotNull(intent.data)
|
||||
intent.data.let {
|
||||
filesToUpload.add(intent.data.toString())
|
||||
}
|
||||
}
|
||||
require(filesToUpload.isNotEmpty())
|
||||
val filenamesWithLineBreaks = StringBuilder("\n")
|
||||
|
||||
val filenamesWithLineBreaks = StringBuilder("\n")
|
||||
|
||||
for (file in filesToUpload) {
|
||||
val filename = FileUtils.getFileName(Uri.parse(file), context)
|
||||
filenamesWithLineBreaks.append(filename).append("\n")
|
||||
}
|
||||
|
||||
val newFragment = FileAttachmentPreviewFragment.newInstance(
|
||||
filenamesWithLineBreaks.toString(),
|
||||
filesToUpload
|
||||
)
|
||||
newFragment.setListener { files, caption ->
|
||||
uploadFiles(files, caption)
|
||||
}
|
||||
newFragment.show(supportFragmentManager, FileAttachmentPreviewFragment.TAG)
|
||||
} catch (e: IllegalStateException) {
|
||||
context.resources?.getString(R.string.nc_upload_failed)?.let {
|
||||
Snackbar.make(
|
||||
binding.root,
|
||||
it,
|
||||
Snackbar.LENGTH_LONG
|
||||
).show()
|
||||
}
|
||||
Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
context.resources?.getString(R.string.nc_upload_failed)?.let {
|
||||
Snackbar.make(
|
||||
binding.root,
|
||||
it,
|
||||
Snackbar.LENGTH_LONG
|
||||
).show()
|
||||
}
|
||||
Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e)
|
||||
}
|
||||
for (file in filesToUpload) {
|
||||
val filename = FileUtils.getFileName(Uri.parse(file), context)
|
||||
filenamesWithLineBreaks.append(filename).append("\n")
|
||||
}
|
||||
|
||||
REQUEST_CODE_SELECT_CONTACT -> {
|
||||
val contactUri = intent?.data ?: return
|
||||
val cursor: Cursor? = contentResolver!!.query(contactUri, null, null, null, null)
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
val id = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts._ID))
|
||||
val fileName = ContactUtils.getDisplayNameFromDeviceContact(context, id) + ".vcf"
|
||||
val file = File(context.cacheDir, fileName)
|
||||
writeContactToVcfFile(cursor, file)
|
||||
|
||||
val shareUri = FileProvider.getUriForFile(
|
||||
this,
|
||||
BuildConfig.APPLICATION_ID,
|
||||
File(file.absolutePath)
|
||||
)
|
||||
uploadFile(shareUri.toString(), false)
|
||||
}
|
||||
cursor?.close()
|
||||
val newFragment = FileAttachmentPreviewFragment.newInstance(
|
||||
filenamesWithLineBreaks.toString(),
|
||||
filesToUpload
|
||||
)
|
||||
newFragment.setListener { files, caption ->
|
||||
uploadFiles(files, caption)
|
||||
}
|
||||
newFragment.show(supportFragmentManager, FileAttachmentPreviewFragment.TAG)
|
||||
} catch (e: IllegalStateException) {
|
||||
context.resources?.getString(R.string.nc_upload_failed)?.let {
|
||||
Snackbar.make(
|
||||
binding.root,
|
||||
it,
|
||||
Snackbar.LENGTH_LONG
|
||||
).show()
|
||||
}
|
||||
Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
context.resources?.getString(R.string.nc_upload_failed)?.let {
|
||||
Snackbar.make(
|
||||
binding.root,
|
||||
it,
|
||||
Snackbar.LENGTH_LONG
|
||||
).show()
|
||||
}
|
||||
Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e)
|
||||
}
|
||||
}
|
||||
|
||||
REQUEST_CODE_PICK_CAMERA -> {
|
||||
if (resultCode == RESULT_OK) {
|
||||
try {
|
||||
filesToUpload.clear()
|
||||
private fun onSelectContactResult(intent: Intent?) {
|
||||
val contactUri = intent?.data ?: return
|
||||
val cursor: Cursor? = contentResolver!!.query(contactUri, null, null, null, null)
|
||||
|
||||
if (intent != null && intent.data != null) {
|
||||
run {
|
||||
intent.data.let {
|
||||
filesToUpload.add(intent.data.toString())
|
||||
}
|
||||
}
|
||||
require(filesToUpload.isNotEmpty())
|
||||
} else if (videoURI != null) {
|
||||
filesToUpload.add(videoURI.toString())
|
||||
videoURI = null
|
||||
} else {
|
||||
error("Failed to get data from intent and uri")
|
||||
}
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
val id = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts._ID))
|
||||
val fileName = ContactUtils.getDisplayNameFromDeviceContact(context, id) + ".vcf"
|
||||
val file = File(context.cacheDir, fileName)
|
||||
writeContactToVcfFile(cursor, file)
|
||||
|
||||
if (permissionUtil.isFilesPermissionGranted()) {
|
||||
val filenamesWithLineBreaks = StringBuilder("\n")
|
||||
val shareUri = FileProvider.getUriForFile(
|
||||
this,
|
||||
BuildConfig.APPLICATION_ID,
|
||||
File(file.absolutePath)
|
||||
)
|
||||
uploadFile(shareUri.toString(), false)
|
||||
}
|
||||
cursor?.close()
|
||||
}
|
||||
|
||||
for (file in filesToUpload) {
|
||||
val filename = FileUtils.getFileName(Uri.parse(file), context)
|
||||
filenamesWithLineBreaks.append(filename).append("\n")
|
||||
}
|
||||
@Throws(IllegalStateException::class)
|
||||
private fun onPickCameraResult(intent: Intent?) {
|
||||
try {
|
||||
filesToUpload.clear()
|
||||
|
||||
val newFragment = FileAttachmentPreviewFragment.newInstance(
|
||||
filenamesWithLineBreaks.toString(),
|
||||
filesToUpload
|
||||
)
|
||||
newFragment.setListener { files, caption -> uploadFiles(files, caption) }
|
||||
newFragment.show(supportFragmentManager, FileAttachmentPreviewFragment.TAG)
|
||||
} else {
|
||||
UploadAndShareFilesWorker.requestStoragePermission(this)
|
||||
}
|
||||
} catch (e: IllegalStateException) {
|
||||
Snackbar.make(
|
||||
binding.root,
|
||||
R.string.nc_upload_failed,
|
||||
Snackbar.LENGTH_LONG
|
||||
)
|
||||
.show()
|
||||
Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
context.resources?.getString(R.string.nc_upload_failed)?.let {
|
||||
Snackbar.make(
|
||||
binding.root,
|
||||
it,
|
||||
Snackbar.LENGTH_LONG
|
||||
)
|
||||
.show()
|
||||
}
|
||||
Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e)
|
||||
if (intent != null && intent.data != null) {
|
||||
run {
|
||||
intent.data.let {
|
||||
filesToUpload.add(intent.data.toString())
|
||||
}
|
||||
}
|
||||
require(filesToUpload.isNotEmpty())
|
||||
} else if (videoURI != null) {
|
||||
filesToUpload.add(videoURI.toString())
|
||||
videoURI = null
|
||||
} else {
|
||||
error("Failed to get data from intent and uri")
|
||||
}
|
||||
|
||||
REQUEST_CODE_MESSAGE_SEARCH -> {
|
||||
val messageId = intent?.getStringExtra(MessageSearchActivity.RESULT_KEY_MESSAGE_ID)
|
||||
messageId?.let { id ->
|
||||
scrollToMessageWithId(id)
|
||||
if (permissionUtil.isFilesPermissionGranted()) {
|
||||
val filenamesWithLineBreaks = StringBuilder("\n")
|
||||
|
||||
for (file in filesToUpload) {
|
||||
val filename = FileUtils.getFileName(Uri.parse(file), context)
|
||||
filenamesWithLineBreaks.append(filename).append("\n")
|
||||
}
|
||||
|
||||
val newFragment = FileAttachmentPreviewFragment.newInstance(
|
||||
filenamesWithLineBreaks.toString(),
|
||||
filesToUpload
|
||||
)
|
||||
newFragment.setListener { files, caption -> uploadFiles(files, caption) }
|
||||
newFragment.show(supportFragmentManager, FileAttachmentPreviewFragment.TAG)
|
||||
} else {
|
||||
UploadAndShareFilesWorker.requestStoragePermission(this)
|
||||
}
|
||||
} catch (e: IllegalStateException) {
|
||||
Snackbar.make(
|
||||
binding.root,
|
||||
R.string.nc_upload_failed,
|
||||
Snackbar.LENGTH_LONG
|
||||
)
|
||||
.show()
|
||||
Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
context.resources?.getString(R.string.nc_upload_failed)?.let {
|
||||
Snackbar.make(
|
||||
binding.root,
|
||||
it,
|
||||
Snackbar.LENGTH_LONG
|
||||
)
|
||||
.show()
|
||||
}
|
||||
Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onMessageSearchResult(intent: Intent?) {
|
||||
val messageId = intent?.getStringExtra(MessageSearchActivity.RESULT_KEY_MESSAGE_ID)
|
||||
messageId?.let { id ->
|
||||
scrollToMessageWithId(id)
|
||||
}
|
||||
}
|
||||
|
||||
private fun executeIfResultOk(result: ActivityResult, onResult: (intent: Intent?) -> Unit) {
|
||||
if (result.resultCode == Activity.RESULT_OK) {
|
||||
onResult(result.data)
|
||||
} else {
|
||||
Log.e(TAG, "resultCode for received intent was != ok")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3202,7 +3244,7 @@ class ChatActivity :
|
|||
} 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)
|
||||
startSelectContactForResult.launch(intent)
|
||||
} else {
|
||||
Snackbar.make(
|
||||
binding.root,
|
||||
|
@ -3275,14 +3317,13 @@ class ChatActivity :
|
|||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
|
||||
}
|
||||
startActivityForResult(
|
||||
startChooseFileIntentForResult.launch(
|
||||
Intent.createChooser(
|
||||
action,
|
||||
context.resources?.getString(
|
||||
R.string.nc_upload_choose_local_files
|
||||
)
|
||||
),
|
||||
REQUEST_CODE_CHOOSE_FILE
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -3328,7 +3369,7 @@ class ChatActivity :
|
|||
|
||||
fun showBrowserScreen() {
|
||||
val sharingFileBrowserIntent = Intent(this, RemoteFileBrowserActivity::class.java)
|
||||
startActivityForResult(sharingFileBrowserIntent, REQUEST_CODE_SELECT_REMOTE_FILES)
|
||||
startRemoteFileBrowsingForResult.launch(sharingFileBrowserIntent)
|
||||
}
|
||||
|
||||
fun showShareLocationScreen() {
|
||||
|
@ -4095,7 +4136,7 @@ class ChatActivity :
|
|||
val intent = Intent(this, MessageSearchActivity::class.java)
|
||||
intent.putExtra(KEY_CONVERSATION_NAME, currentConversation?.displayName)
|
||||
intent.putExtra(KEY_ROOM_TOKEN, roomToken)
|
||||
startActivityForResult(intent, REQUEST_CODE_MESSAGE_SEARCH)
|
||||
startMessageSearchForResult.launch(intent)
|
||||
}
|
||||
|
||||
private fun handleSystemMessages(chatMessageList: List<ChatMessage>): List<ChatMessage> {
|
||||
|
@ -4797,7 +4838,7 @@ class ChatActivity :
|
|||
if (!permissionUtil.isCameraPermissionGranted()) {
|
||||
requestCameraPermissions()
|
||||
} else {
|
||||
startActivityForResult(TakePhotoActivity.createIntent(context), REQUEST_CODE_PICK_CAMERA)
|
||||
startPickCameraIntentForResult.launch(TakePhotoActivity.createIntent(context))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4825,7 +4866,7 @@ class ChatActivity :
|
|||
videoFile?.also {
|
||||
videoURI = FileProvider.getUriForFile(context, context.packageName, it)
|
||||
takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, videoURI)
|
||||
startActivityForResult(takeVideoIntent, REQUEST_CODE_PICK_CAMERA)
|
||||
startPickCameraIntentForResult.launch(takeVideoIntent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4897,15 +4938,10 @@ class ChatActivity :
|
|||
private const val GET_ROOM_INFO_DELAY_LOBBY: Long = 5000
|
||||
private const val HTTP_CODE_OK: Int = 200
|
||||
private const val AGE_THRESHOLD_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_SELECT_CONTACT: Int = 666
|
||||
private const val REQUEST_CODE_MESSAGE_SEARCH: Int = 777
|
||||
private const val REQUEST_SHARE_FILE_PERMISSION: Int = 221
|
||||
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_CODE_PICK_CAMERA: Int = 333
|
||||
private const val REQUEST_CODE_SELECT_REMOTE_FILES = 888
|
||||
private const val OBJECT_MESSAGE: String = "{object}"
|
||||
private const val MINIMUM_VOICE_RECORD_DURATION: Int = 1000
|
||||
private const val MINIMUM_VOICE_RECORD_TO_STOP: Int = 200
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
package com.nextcloud.talk.conversationinfoedit
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
|
@ -16,6 +15,8 @@ import android.util.Log
|
|||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.activity.result.ActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.core.net.toFile
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
|
@ -49,8 +50,7 @@ import java.io.File
|
|||
import javax.inject.Inject
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
class ConversationInfoEditActivity :
|
||||
BaseActivity() {
|
||||
class ConversationInfoEditActivity : BaseActivity() {
|
||||
|
||||
private lateinit var binding: ActivityConversationInfoEditBinding
|
||||
|
||||
|
@ -75,6 +75,31 @@ class ConversationInfoEditActivity :
|
|||
|
||||
private lateinit var spreedCapabilities: SpreedCapability
|
||||
|
||||
private val startImagePickerForResult =
|
||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
handleResult(it) { result ->
|
||||
pickImage.onImagePickerResult(result.data) { uri ->
|
||||
uploadAvatar(uri.toFile())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val startSelectRemoteFilesIntentForResult = registerForActivityResult(
|
||||
ActivityResultContracts.StartActivityForResult()
|
||||
) {
|
||||
handleResult(it) { result ->
|
||||
pickImage.onSelectRemoteFilesResult(startImagePickerForResult, result.data)
|
||||
}
|
||||
}
|
||||
|
||||
private val startTakePictureIntentForResult = registerForActivityResult(
|
||||
ActivityResultContracts.StartActivityForResult()
|
||||
) {
|
||||
handleResult(it) { result ->
|
||||
pickImage.onTakePictureResult(startImagePickerForResult, result.data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
||||
|
@ -158,9 +183,18 @@ class ConversationInfoEditActivity :
|
|||
}
|
||||
|
||||
private fun setupAvatarOptions() {
|
||||
binding.avatarUpload.setOnClickListener { pickImage.selectLocal() }
|
||||
binding.avatarChoose.setOnClickListener { pickImage.selectRemote() }
|
||||
binding.avatarCamera.setOnClickListener { pickImage.takePicture() }
|
||||
binding.avatarUpload.setOnClickListener {
|
||||
pickImage.selectLocal(startImagePickerForResult = startImagePickerForResult)
|
||||
}
|
||||
|
||||
binding.avatarChoose.setOnClickListener {
|
||||
pickImage.selectRemote(startSelectRemoteFilesIntentForResult = startSelectRemoteFilesIntentForResult)
|
||||
}
|
||||
|
||||
binding.avatarCamera.setOnClickListener {
|
||||
pickImage.takePicture(startTakePictureIntentForResult = startTakePictureIntentForResult)
|
||||
}
|
||||
|
||||
if (conversation?.hasCustomAvatar == true) {
|
||||
binding.avatarDelete.visibility = View.VISIBLE
|
||||
binding.avatarDelete.setOnClickListener { deleteAvatar() }
|
||||
|
@ -293,19 +327,12 @@ class ConversationInfoEditActivity :
|
|||
})
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
when (resultCode) {
|
||||
Activity.RESULT_OK -> {
|
||||
pickImage.handleActivityResult(
|
||||
requestCode,
|
||||
resultCode,
|
||||
data
|
||||
) { uploadAvatar(it.toFile()) }
|
||||
}
|
||||
private fun handleResult(result: ActivityResult, onResult: (result: ActivityResult) -> Unit) {
|
||||
when (result.resultCode) {
|
||||
Activity.RESULT_OK -> onResult(result)
|
||||
|
||||
ImagePicker.RESULT_ERROR -> {
|
||||
Snackbar.make(binding.root, ImagePicker.getError(data), Snackbar.LENGTH_SHORT).show()
|
||||
Snackbar.make(binding.root, ImagePicker.getError(result.data), Snackbar.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
else -> {
|
||||
|
|
|
@ -11,9 +11,10 @@ package com.nextcloud.talk.lock
|
|||
import android.app.Activity
|
||||
import android.app.KeyguardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.activity.result.ActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.biometric.BiometricPrompt
|
||||
import autodagger.AutoInjector
|
||||
|
@ -35,6 +36,13 @@ class LockedActivity : AppCompatActivity() {
|
|||
@Inject
|
||||
lateinit var appPreferences: AppPreferences
|
||||
|
||||
private val startForCredentialsResult = registerForActivityResult(
|
||||
ActivityResultContracts.StartActivityForResult
|
||||
()
|
||||
) {
|
||||
onConfirmDeviceCredentials(it)
|
||||
}
|
||||
|
||||
private lateinit var binding: ActivityLockedBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
@ -111,27 +119,23 @@ class LockedActivity : AppCompatActivity() {
|
|||
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager?
|
||||
val intent = keyguardManager?.createConfirmDeviceCredentialIntent(null, null)
|
||||
if (intent != null) {
|
||||
startActivityForResult(intent, REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS)
|
||||
startForCredentialsResult.launch(intent)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (requestCode == REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
if (
|
||||
SecurityUtils.checkIfWeAreAuthenticated(appPreferences.screenLockTimeout)
|
||||
) {
|
||||
finish()
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "Authorization failed")
|
||||
private fun onConfirmDeviceCredentials(result: ActivityResult) {
|
||||
if (result.resultCode == Activity.RESULT_OK) {
|
||||
if (
|
||||
SecurityUtils.checkIfWeAreAuthenticated(appPreferences.screenLockTimeout)
|
||||
) {
|
||||
finish()
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "Authorization failed")
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = LockedActivity::class.java.simpleName
|
||||
private const val REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS = 112
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
package com.nextcloud.talk.profile
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.net.Uri
|
||||
|
@ -24,6 +23,8 @@ import android.view.Menu
|
|||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.result.ActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.net.toFile
|
||||
|
@ -50,13 +51,13 @@ import com.nextcloud.talk.ui.dialog.ScopeDialog
|
|||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||
import com.nextcloud.talk.users.UserManager
|
||||
import com.nextcloud.talk.utils.ApiUtils
|
||||
import com.nextcloud.talk.utils.SpreedFeatures
|
||||
import com.nextcloud.talk.utils.CapabilitiesUtil
|
||||
import com.nextcloud.talk.utils.DisplayUtils
|
||||
import com.nextcloud.talk.utils.Mimetype.IMAGE_JPG
|
||||
import com.nextcloud.talk.utils.Mimetype.IMAGE_PREFIX_GENERIC
|
||||
import com.nextcloud.talk.utils.PickImage
|
||||
import com.nextcloud.talk.utils.PickImage.Companion.REQUEST_PERMISSION_CAMERA
|
||||
import com.nextcloud.talk.utils.CapabilitiesUtil
|
||||
import com.nextcloud.talk.utils.SpreedFeatures
|
||||
import io.reactivex.Observer
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
|
@ -87,6 +88,31 @@ class ProfileActivity : BaseActivity() {
|
|||
|
||||
private lateinit var pickImage: PickImage
|
||||
|
||||
private val startImagePickerForResult =
|
||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
handleResult(it) { result ->
|
||||
pickImage.onImagePickerResult(result.data) { uri ->
|
||||
uploadAvatar(uri.toFile())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val startSelectRemoteFilesIntentForResult = registerForActivityResult(
|
||||
ActivityResultContracts.StartActivityForResult()
|
||||
) {
|
||||
handleResult(it) { result ->
|
||||
pickImage.onSelectRemoteFilesResult(startImagePickerForResult, result.data)
|
||||
}
|
||||
}
|
||||
|
||||
private val startTakePictureIntentForResult = registerForActivityResult(
|
||||
ActivityResultContracts.StartActivityForResult()
|
||||
) {
|
||||
handleResult(it) { result ->
|
||||
pickImage.onTakePictureResult(startImagePickerForResult, result.data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
||||
|
@ -106,9 +132,15 @@ class ProfileActivity : BaseActivity() {
|
|||
val credentials = ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token)
|
||||
|
||||
pickImage = PickImage(this, currentUser)
|
||||
binding.avatarUpload.setOnClickListener { pickImage.selectLocal() }
|
||||
binding.avatarChoose.setOnClickListener { pickImage.selectRemote() }
|
||||
binding.avatarCamera.setOnClickListener { pickImage.takePicture() }
|
||||
binding.avatarUpload.setOnClickListener {
|
||||
pickImage.selectLocal(startImagePickerForResult = startImagePickerForResult)
|
||||
}
|
||||
binding.avatarChoose.setOnClickListener {
|
||||
pickImage.selectRemote(startSelectRemoteFilesIntentForResult = startSelectRemoteFilesIntentForResult)
|
||||
}
|
||||
binding.avatarCamera.setOnClickListener {
|
||||
pickImage.takePicture(startTakePictureIntentForResult = startTakePictureIntentForResult)
|
||||
}
|
||||
binding.avatarDelete.setOnClickListener {
|
||||
ncApi.deleteAvatar(
|
||||
credentials,
|
||||
|
@ -479,7 +511,7 @@ class ProfileActivity : BaseActivity() {
|
|||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
if (requestCode == REQUEST_PERMISSION_CAMERA) {
|
||||
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
pickImage.takePicture()
|
||||
pickImage.takePicture(startTakePictureIntentForResult = startTakePictureIntentForResult)
|
||||
} else {
|
||||
Snackbar
|
||||
.make(binding.root, context.getString(R.string.take_photo_permission), Snackbar.LENGTH_LONG)
|
||||
|
@ -488,19 +520,14 @@ class ProfileActivity : BaseActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
when (resultCode) {
|
||||
Activity.RESULT_OK -> {
|
||||
pickImage.handleActivityResult(
|
||||
requestCode,
|
||||
resultCode,
|
||||
data
|
||||
) { uploadAvatar(it.toFile()) }
|
||||
}
|
||||
private fun handleResult(result: ActivityResult, onResult: (result: ActivityResult) -> Unit) {
|
||||
when (result.resultCode) {
|
||||
Activity.RESULT_OK -> onResult(result)
|
||||
|
||||
ImagePicker.RESULT_ERROR -> {
|
||||
Snackbar.make(binding.root, getError(data), Snackbar.LENGTH_SHORT).show()
|
||||
Snackbar.make(binding.root, getError(result.data), Snackbar.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
else -> {
|
||||
Log.i(TAG, "Task Cancelled")
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
/*
|
||||
* Nextcloud Talk - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2024 Parneet Singh <gurayaparneet@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2022 Tim Krüger <t@timkrueger.me>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.utils
|
||||
|
||||
import android.app.Activity
|
||||
|
@ -13,6 +15,7 @@ import android.graphics.BitmapFactory
|
|||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import autodagger.AutoInjector
|
||||
import com.github.dhaval2404.imagepicker.ImagePicker
|
||||
import com.github.dhaval2404.imagepicker.constant.ImageProvider
|
||||
|
@ -48,17 +51,19 @@ class PickImage(
|
|||
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
||||
}
|
||||
|
||||
fun selectLocal() {
|
||||
fun selectLocal(startImagePickerForResult: ActivityResultLauncher<Intent>) {
|
||||
ImagePicker.Companion.with(activity)
|
||||
.provider(ImageProvider.GALLERY)
|
||||
.crop()
|
||||
.cropSquare()
|
||||
.compress(MAX_SIZE)
|
||||
.maxResultSize(MAX_SIZE, MAX_SIZE)
|
||||
.createIntent { intent -> this.activity.startActivityForResult(intent, REQUEST_CODE_IMAGE_PICKER) }
|
||||
.createIntent { intent ->
|
||||
startImagePickerForResult.launch(intent)
|
||||
}
|
||||
}
|
||||
|
||||
private fun selectLocal(file: File) {
|
||||
private fun selectLocal(startImagePickerForResult: ActivityResultLauncher<Intent>, file: File) {
|
||||
ImagePicker.Companion.with(activity)
|
||||
.provider(ImageProvider.URI)
|
||||
.crop()
|
||||
|
@ -66,25 +71,23 @@ class PickImage(
|
|||
.compress(MAX_SIZE)
|
||||
.maxResultSize(MAX_SIZE, MAX_SIZE)
|
||||
.setUri(Uri.fromFile(file))
|
||||
.createIntent { intent -> this.activity.startActivityForResult(intent, REQUEST_CODE_IMAGE_PICKER) }
|
||||
.createIntent { intent ->
|
||||
startImagePickerForResult.launch(intent)
|
||||
}
|
||||
}
|
||||
|
||||
fun selectRemote() {
|
||||
fun selectRemote(startSelectRemoteFilesIntentForResult: ActivityResultLauncher<Intent>) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(BundleKeys.KEY_MIME_TYPE_FILTER, Mimetype.IMAGE_PREFIX)
|
||||
|
||||
val avatarIntent = Intent(activity, RemoteFileBrowserActivity::class.java)
|
||||
avatarIntent.putExtras(bundle)
|
||||
|
||||
this.activity.startActivityForResult(avatarIntent, REQUEST_CODE_SELECT_REMOTE_FILES)
|
||||
startSelectRemoteFilesIntentForResult.launch(avatarIntent)
|
||||
}
|
||||
|
||||
fun takePicture() {
|
||||
fun takePicture(startTakePictureIntentForResult: ActivityResultLauncher<Intent>) {
|
||||
if (permissionUtil.isCameraPermissionGranted()) {
|
||||
activity.startActivityForResult(
|
||||
TakePhotoActivity.createIntent(activity),
|
||||
REQUEST_CODE_TAKE_PICTURE
|
||||
)
|
||||
startTakePictureIntentForResult.launch(TakePhotoActivity.createIntent(activity))
|
||||
} else {
|
||||
activity.requestPermissions(
|
||||
arrayOf(android.Manifest.permission.CAMERA),
|
||||
|
@ -93,7 +96,7 @@ class PickImage(
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleAvatar(remotePath: String?) {
|
||||
private fun handleAvatar(startImagePickerForResult: ActivityResultLauncher<Intent>, remotePath: String?) {
|
||||
val uri = currentUser!!.baseUrl + "/index.php/apps/files/api/v1/thumbnail/512/512/" +
|
||||
Uri.encode(remotePath, "/")
|
||||
val downloadCall = ncApi.downloadResizedImage(
|
||||
|
@ -102,7 +105,10 @@ class PickImage(
|
|||
)
|
||||
downloadCall.enqueue(object : Callback<ResponseBody> {
|
||||
override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
|
||||
saveBitmapAndPassToImagePicker(BitmapFactory.decodeStream(response.body()!!.byteStream()))
|
||||
saveBitmapAndPassToImagePicker(
|
||||
startImagePickerForResult,
|
||||
BitmapFactory.decodeStream(response.body()!!.byteStream())
|
||||
)
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
|
||||
|
@ -112,9 +118,12 @@ class PickImage(
|
|||
}
|
||||
|
||||
// only possible with API26
|
||||
private fun saveBitmapAndPassToImagePicker(bitmap: Bitmap) {
|
||||
private fun saveBitmapAndPassToImagePicker(
|
||||
startImagePickerForResult: ActivityResultLauncher<Intent>,
|
||||
bitmap: Bitmap
|
||||
) {
|
||||
val file: File = saveBitmapToTempFile(bitmap) ?: return
|
||||
selectLocal(file)
|
||||
selectLocal(startImagePickerForResult, file)
|
||||
}
|
||||
|
||||
private fun saveBitmapToTempFile(bitmap: Bitmap): File? {
|
||||
|
@ -145,35 +154,21 @@ class PickImage(
|
|||
)
|
||||
}
|
||||
|
||||
fun handleActivityResult(requestCode: Int, resultCode: Int, data: Intent?, handleImage: (uri: Uri) -> Unit) {
|
||||
if (resultCode != Activity.RESULT_OK) {
|
||||
Log.w(
|
||||
TAG,
|
||||
"Check result code before calling " +
|
||||
"'PickImage#handleActivtyResult'. It should be ${Activity.RESULT_OK}, but it is $resultCode!"
|
||||
)
|
||||
return
|
||||
}
|
||||
fun onImagePickerResult(data: Intent?, handleImage: (uri: Uri) -> Unit) {
|
||||
val uri: Uri = data?.data!!
|
||||
handleImage(uri)
|
||||
}
|
||||
|
||||
when (requestCode) {
|
||||
REQUEST_CODE_IMAGE_PICKER -> {
|
||||
val uri: Uri = data?.data!!
|
||||
handleImage(uri)
|
||||
}
|
||||
REQUEST_CODE_SELECT_REMOTE_FILES -> {
|
||||
val pathList = data?.getStringArrayListExtra(RemoteFileBrowserActivity.EXTRA_SELECTED_PATHS)
|
||||
if (pathList?.size!! >= 1) {
|
||||
handleAvatar(pathList[0])
|
||||
}
|
||||
}
|
||||
REQUEST_CODE_TAKE_PICTURE -> {
|
||||
data?.data?.path?.let {
|
||||
selectLocal(File(it))
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
Log.w(TAG, "Unknown intent request code")
|
||||
}
|
||||
fun onSelectRemoteFilesResult(startImagePickerForResult: ActivityResultLauncher<Intent>, data: Intent?) {
|
||||
val pathList = data?.getStringArrayListExtra(RemoteFileBrowserActivity.EXTRA_SELECTED_PATHS)
|
||||
if (pathList?.size!! >= 1) {
|
||||
handleAvatar(startImagePickerForResult, pathList[0])
|
||||
}
|
||||
}
|
||||
|
||||
fun onTakePictureResult(startImagePickerForResult: ActivityResultLauncher<Intent>, data: Intent?) {
|
||||
data?.data?.path?.let {
|
||||
selectLocal(startImagePickerForResult, File(it))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,9 +177,6 @@ class PickImage(
|
|||
private const val MAX_SIZE: Int = 1024
|
||||
private const val AVATAR_PATH = "photos/avatar.png"
|
||||
private const val FULL_QUALITY: Int = 100
|
||||
const val REQUEST_CODE_IMAGE_PICKER: Int = 1
|
||||
const val REQUEST_CODE_TAKE_PICTURE: Int = 2
|
||||
const val REQUEST_PERMISSION_CAMERA: Int = 1
|
||||
const val REQUEST_CODE_SELECT_REMOTE_FILES = 22
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue