@ -2,10 +2,7 @@ package org.thoughtcrime.securesms.preferences
import android.Manifest
import android.app.Activity
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.*
import android.net.Uri
import android.os.AsyncTask
import android.os.Bundle
@ -19,6 +16,7 @@ import android.view.MenuItem
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible
import network.loki.messenger.BuildConfig
import network.loki.messenger.R
@ -28,13 +26,11 @@ import nl.komponents.kovenant.all
import nl.komponents.kovenant.ui.alwaysUi
import nl.komponents.kovenant.ui.successUi
import org.session.libsession.avatars.AvatarHelper
import org.session.libsession.utilities.Address
import org.session.libsession.utilities.ProfileKeyUtil
import org.session.libsession.utilities.ProfilePictureUtilities
import org.session.libsession.utilities.*
import org.session.libsession.utilities.SSKEnvironment.ProfileManagerProtocol
import org.session.libsession.utilities.TextSecurePreferences
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.avatar.AvatarSelection
import org.thoughtcrime.securesms.components.ProfilePictureView
import org.thoughtcrime.securesms.home.PathActivity
import org.thoughtcrime.securesms.messagerequests.MessageRequestsActivity
import org.thoughtcrime.securesms.mms.GlideApp
@ -57,8 +53,6 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
private var displayNameEditActionMode : ActionMode ? = null
set ( value ) { field = value ; handleDisplayNameEditActionModeChanged ( ) }
private lateinit var glide : GlideRequests
private var displayNameToBeUploaded : String ? = null
private var profilePictureToBeUploaded : ByteArray ? = null
private var tempFile : File ? = null
private val hexEncodedPublicKey : String
@ -76,14 +70,10 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
super . onCreate ( savedInstanceState , isReady )
binding = ActivitySettingsBinding . inflate ( layoutInflater )
setContentView ( binding . root )
val displayName = TextSecurePreferences . getProfileName ( this ) ?: hexEncodedPublicKey
val displayName = getDisplayName ( )
glide = GlideApp . with ( this )
with ( binding ) {
profilePictureView . root . glide = glide
profilePictureView . root . publicKey = hexEncodedPublicKey
profilePictureView . root . displayName = displayName
profilePictureView . root . isLarge = true
profilePictureView . root . update ( )
setupProfilePictureView ( profilePictureView . root )
profilePictureView . root . setOnClickListener { showEditProfilePictureUI ( ) }
ctnGroupNameSection . setOnClickListener { startActionMode ( DisplayNameEditActionModeCallback ( ) ) }
btnGroupNameDisplay . text = displayName
@ -105,6 +95,17 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
}
}
private fun getDisplayName ( ) : String =
TextSecurePreferences . getProfileName ( this ) ?: truncateIdForDisplay ( hexEncodedPublicKey )
private fun setupProfilePictureView ( view : ProfilePictureView ) {
view . glide = glide
view . publicKey = hexEncodedPublicKey
view . displayName = getDisplayName ( )
view . isLarge = true
view . update ( )
}
override fun onSaveInstanceState ( outState : Bundle ) {
super . onSaveInstanceState ( outState )
val scrollBundle = SparseArray < Parcelable > ( )
@ -154,9 +155,9 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
}
AsyncTask . execute {
try {
profilePictureToBeUploaded = BitmapUtil . createScaledBytes ( this @SettingsActivity , AvatarSelection . getResultUri ( data ) , ProfileMediaConstraints ( ) ) . bitmap
val profilePictureToBeUploaded = BitmapUtil . createScaledBytes ( this @SettingsActivity , AvatarSelection . getResultUri ( data ) , ProfileMediaConstraints ( ) ) . bitmap
Handler ( Looper . getMainLooper ( ) ) . post {
updateProfile ( true )
updateProfile ( true , profilePictureToBeUploaded )
}
} catch ( e : BitmapDecodingException ) {
e . printStackTrace ( )
@ -190,23 +191,30 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
}
}
private fun updateProfile ( isUpdatingProfilePicture : Boolean ) {
private fun updateProfile (
isUpdatingProfilePicture : Boolean ,
profilePicture : ByteArray ? = null ,
displayName : String ? = null
) {
binding . loader . isVisible = true
val promises = mutableListOf < Promise < * , Exception > > ( )
val displayName = displayNameToBeUploaded
if ( displayName != null ) {
TextSecurePreferences . setProfileName ( this , displayName )
}
val profilePicture = profilePictureToBeUploaded
val encodedProfileKey = ProfileKeyUtil . generateEncodedProfileKey ( this )
if ( isUpdatingProfilePicture && profilePicture != null ) {
promises . add ( ProfilePictureUtilities . upload ( profilePicture , encodedProfileKey , this ) )
if ( isUpdatingProfilePicture ) {
if ( profilePicture != null ) {
promises . add ( ProfilePictureUtilities . upload ( profilePicture , encodedProfileKey , this ) )
} else {
TextSecurePreferences . setLastProfilePictureUpload ( this , System . currentTimeMillis ( ) )
TextSecurePreferences . setProfilePictureURL ( this , null )
}
}
val compoundPromise = all ( promises )
compoundPromise . successUi { // Do this on the UI thread so that it happens before the alwaysUi clause below
if ( isUpdatingProfilePicture && profilePicture != null ) {
if ( isUpdatingProfilePicture ) {
AvatarHelper . setAvatar ( this , Address . fromSerialized ( TextSecurePreferences . getLocalNumber ( this ) !! ) , profilePicture )
TextSecurePreferences . setProfileAvatarId ( this , SecureRandom( ) . nextInt ( ) )
TextSecurePreferences . setProfileAvatarId ( this , profilePicture?. let { SecureRandom( ) . nextInt ( ) } ?: 0 )
TextSecurePreferences . setLastProfilePictureUpload ( this , Date ( ) . time )
ProfileKeyUtil . setEncodedProfileKey ( this , encodedProfileKey )
}
@ -218,12 +226,10 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
if ( displayName != null ) {
binding . btnGroupNameDisplay . text = displayName
}
if ( isUpdatingProfilePicture && profilePicture != null ) {
if ( isUpdatingProfilePicture ) {
binding . profilePictureView . root . recycle ( ) // Clear the cached image before updating
binding . profilePictureView . root . update ( )
}
displayNameToBeUploaded = null
profilePictureToBeUploaded = null
binding . loader . isVisible = false
}
}
@ -244,8 +250,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
Toast . makeText ( this , R . string . activity _settings _display _name _too _long _error , Toast . LENGTH _SHORT ) . show ( )
return false
}
displayNameToBeUploaded = displayName
updateProfile ( false )
updateProfile ( false , displayName = displayName )
return true
}
@ -255,6 +260,28 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
}
private fun showEditProfilePictureUI ( ) {
AlertDialog . Builder ( this )
. setTitle ( R . string . activity _settings _set _display _picture )
. setView ( R . layout . dialog _change _avatar )
. setPositiveButton ( R . string . activity _settings _upload ) { _ , _ ->
startAvatarSelection ( )
}
. setNegativeButton ( R . string . cancel ) { _ , _ -> }
. apply {
if ( TextSecurePreferences . getProfileAvatarId ( context ) != 0 ) {
setNeutralButton ( R . string . activity _settings _remove ) { _ , _ -> removeAvatar ( ) }
}
}
. show ( ) . apply {
findViewById < ProfilePictureView > ( R . id . profile _picture _view ) ?. let ( :: setupProfilePictureView )
}
}
private fun removeAvatar ( ) {
updateProfile ( true )
}
private fun startAvatarSelection ( ) {
// Ask for an optional camera permission.
Permissions . with ( this )
. request ( Manifest . permission . CAMERA )