2222package com.nextcloud.talk.controllers
2323
2424import android.app.Activity
25+ import android.content.ActivityNotFoundException
2526import android.content.Intent
27+ import android.content.pm.PackageManager
2628import android.content.res.ColorStateList
2729import android.graphics.Bitmap
2830import android.graphics.BitmapFactory
@@ -52,6 +54,7 @@ import com.github.dhaval2404.imagepicker.ImagePicker.Companion.getError
5254import com.github.dhaval2404.imagepicker.ImagePicker.Companion.getFile
5355import com.github.dhaval2404.imagepicker.ImagePicker.Companion.with
5456import com.nextcloud.talk.R
57+ import com.nextcloud.talk.activities.TakePhotoActivity
5558import com.nextcloud.talk.api.NcApi
5659import com.nextcloud.talk.application.NextcloudTalkApplication
5760import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
@@ -76,6 +79,7 @@ import com.nextcloud.talk.utils.Mimetype.IMAGE_PREFIX
7679import com.nextcloud.talk.utils.Mimetype.IMAGE_PREFIX_GENERIC
7780import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_MIME_TYPE_FILTER
7881import com.nextcloud.talk.utils.database.user.UserUtils
82+ import com.nextcloud.talk.utils.permissions.PlatformPermissionUtil
7983import io.reactivex.Observer
8084import io.reactivex.android.schedulers.AndroidSchedulers
8185import io.reactivex.disposables.Disposable
@@ -95,6 +99,7 @@ import java.util.Locale
9599import javax.inject.Inject
96100
97101@AutoInjector(NextcloudTalkApplication ::class )
102+ @Suppress(" Detekt.TooManyFunctions" )
98103class ProfileController : NewBaseController (R .layout.controller_profile) {
99104 private val binding: ControllerProfileBinding by viewBinding(ControllerProfileBinding ::bind)
100105
@@ -104,6 +109,9 @@ class ProfileController : NewBaseController(R.layout.controller_profile) {
104109 @Inject
105110 lateinit var userUtils: UserUtils
106111
112+ @Inject
113+ lateinit var permissionUtil: PlatformPermissionUtil
114+
107115 private var currentUser: UserEntity ? = null
108116 private var edit = false
109117 private var adapter: UserInfoAdapter ? = null
@@ -197,6 +205,7 @@ class ProfileController : NewBaseController(R.layout.controller_profile) {
197205 val credentials = ApiUtils .getCredentials(currentUser!! .username, currentUser!! .token)
198206 binding.avatarUpload.setOnClickListener { sendSelectLocalFileIntent() }
199207 binding.avatarChoose.setOnClickListener { showBrowserScreen() }
208+ binding.avatarCamera.setOnClickListener { checkPermissionAndTakePicture() }
200209 binding.avatarDelete.setOnClickListener {
201210 ncApi.deleteAvatar(
202211 credentials,
@@ -493,7 +502,23 @@ class ProfileController : NewBaseController(R.layout.controller_profile) {
493502 startActivityForResult(avatarIntent, REQUEST_CODE_SELECT_REMOTE_FILES )
494503 }
495504
496- fun handleAvatar (remotePath : String? ) {
505+ private fun checkPermissionAndTakePicture () {
506+ if (permissionUtil.isCameraPermissionGranted()) {
507+ takePictureForAvatar()
508+ } else {
509+ requestPermissions(arrayOf(android.Manifest .permission.CAMERA ), REQUEST_PERMISSION_CAMERA )
510+ }
511+ }
512+
513+ private fun takePictureForAvatar () {
514+ try {
515+ startActivityForResult(TakePhotoActivity .createIntent(context!! ), REQUEST_CODE_TAKE_PICTURE )
516+ } catch (e: ActivityNotFoundException ) {
517+ // TODO
518+ }
519+ }
520+
521+ private fun handleAvatar (remotePath : String? ) {
497522 val uri = currentUser!! .baseUrl + " /index.php/apps/files/api/v1/thumbnail/512/512/" +
498523 Uri .encode(remotePath, " /" )
499524 val downloadCall = ncApi.downloadResizedImage(
@@ -511,30 +536,54 @@ class ProfileController : NewBaseController(R.layout.controller_profile) {
511536 })
512537 }
513538
539+ override fun onRequestPermissionsResult (requestCode : Int , permissions : Array <out String >, grantResults : IntArray ) {
540+ super .onRequestPermissionsResult(requestCode, permissions, grantResults)
541+ if (requestCode == REQUEST_PERMISSION_CAMERA ) {
542+ if (grantResults.isNotEmpty() && grantResults[0 ] == PackageManager .PERMISSION_GRANTED ) {
543+ takePictureForAvatar()
544+ } else {
545+ Toast
546+ .makeText(context, context?.getString(R .string.take_photo_permission), Toast .LENGTH_LONG )
547+ .show()
548+ }
549+ }
550+ }
551+
514552 // only possible with API26
515553 private fun saveBitmapAndPassToImagePicker (bitmap : Bitmap ) {
516- var file: File ? = null
554+ val file: File = saveBitmapToTempFile(bitmap) ? : return
555+ openImageWithPicker(file)
556+ }
557+
558+ private fun saveBitmapToTempFile (bitmap : Bitmap ): File ? {
517559 try {
518- FileUtils .removeTempCacheFile(
519- this .context!! ,
520- AVATAR_PATH
521- )
522- file = FileUtils .getTempCacheFile(
523- this .context!! ,
524- AVATAR_PATH
525- )
560+ val file = createTempFileForAvatar()
526561 try {
527- FileOutputStream (file).use { out -> bitmap.compress(Bitmap .CompressFormat .PNG , FULL_QUALITY , out ) }
562+ FileOutputStream (file).use { out ->
563+ bitmap.compress(Bitmap .CompressFormat .PNG , FULL_QUALITY , out )
564+ }
565+ return file
528566 } catch (e: IOException ) {
529567 Log .e(TAG , " Error compressing bitmap" , e)
530568 }
531569 } catch (e: IOException ) {
532570 Log .e(TAG , " Error creating temporary avatar image" , e)
533571 }
534- if (file == null ) {
535- // TODO exception
536- return
537- }
572+ return null
573+ }
574+
575+ private fun createTempFileForAvatar (): File ? {
576+ FileUtils .removeTempCacheFile(
577+ this .context!! ,
578+ AVATAR_PATH
579+ )
580+ return FileUtils .getTempCacheFile(
581+ context!! ,
582+ AVATAR_PATH
583+ )
584+ }
585+
586+ private fun openImageWithPicker (file : File ) {
538587 val intent = with (activity!! )
539588 .fileOnly()
540589 .crop()
@@ -546,20 +595,24 @@ class ProfileController : NewBaseController(R.layout.controller_profile) {
546595 startActivityForResult(intent, REQUEST_CODE_IMAGE_PICKER )
547596 }
548597
549- override fun onActivityResult (requestCode : Int , resultCode : Int , intent : Intent ? ) {
598+ override fun onActivityResult (requestCode : Int , resultCode : Int , data : Intent ? ) {
550599 if (resultCode == Activity .RESULT_OK ) {
551600 if (requestCode == REQUEST_CODE_IMAGE_PICKER ) {
552- uploadAvatar(getFile(intent ))
601+ uploadAvatar(getFile(data ))
553602 } else if (requestCode == REQUEST_CODE_SELECT_REMOTE_FILES ) {
554- val pathList = intent ?.getStringArrayListExtra(RemoteFileBrowserActivity .EXTRA_SELECTED_PATHS )
603+ val pathList = data ?.getStringArrayListExtra(RemoteFileBrowserActivity .EXTRA_SELECTED_PATHS )
555604 if (pathList?.size!! >= 1 ) {
556605 handleAvatar(pathList[0 ])
557606 }
607+ } else if (requestCode == REQUEST_CODE_TAKE_PICTURE ) {
608+ data?.data?.path?.let {
609+ openImageWithPicker(File (it))
610+ }
558611 } else {
559612 Log .w(TAG , " Unknown intent request code" )
560613 }
561614 } else if (resultCode == ImagePicker .RESULT_ERROR ) {
562- Toast .makeText(activity, getError(intent ), Toast .LENGTH_SHORT ).show()
615+ Toast .makeText(activity, getError(data ), Toast .LENGTH_SHORT ).show()
563616 } else {
564617 Log .i(TAG , " Task Cancelled" )
565618 }
@@ -595,7 +648,11 @@ class ProfileController : NewBaseController(R.layout.controller_profile) {
595648 }
596649
597650 override fun onError (e : Throwable ) {
598- Toast .makeText(applicationContext, " Error" , Toast .LENGTH_LONG ).show()
651+ Toast .makeText(
652+ applicationContext, context!! .getString(R .string.default_error_msg),
653+ Toast
654+ .LENGTH_LONG
655+ ).show()
599656 Log .e(TAG , " Error uploading avatar" , e)
600657 }
601658
@@ -823,6 +880,8 @@ class ProfileController : NewBaseController(R.layout.controller_profile) {
823880 private const val DEFAULT_RETRIES : Long = 3
824881 private const val MAX_SIZE : Int = 1024
825882 private const val REQUEST_CODE_IMAGE_PICKER : Int = 1
883+ private const val REQUEST_CODE_TAKE_PICTURE : Int = 2
884+ private const val REQUEST_PERMISSION_CAMERA : Int = 1
826885 private const val FULL_QUALITY : Int = 100
827886 private const val HIGH_EMPHASIS_ALPHA : Float = 0.87f
828887 private const val MEDIUM_EMPHASIS_ALPHA : Float = 0.6f
0 commit comments