@@ -12,18 +12,18 @@ package com.nextcloud.talk.profile
1212import android.app.Activity
1313import android.content.pm.PackageManager
1414import android.os.Bundle
15- import android.text.Editable
1615import android.text.TextUtils
17- import android.text.TextWatcher
1816import android.util.Log
19- import android.view.LayoutInflater
2017import android.view.Menu
2118import android.view.MenuItem
2219import android.view.View
2320import android.view.ViewGroup
2421import androidx.activity.result.ActivityResult
2522import androidx.activity.result.contract.ActivityResultContracts
2623import androidx.annotation.DrawableRes
24+ import androidx.compose.material3.MaterialTheme
25+ import androidx.compose.ui.platform.ComposeView
26+ import androidx.compose.ui.platform.ViewCompositionStrategy
2727import androidx.core.content.ContextCompat
2828import androidx.core.graphics.drawable.toDrawable
2929import androidx.core.net.toFile
@@ -34,14 +34,12 @@ import autodagger.AutoInjector
3434import com.github.dhaval2404.imagepicker.ImagePicker
3535import com.github.dhaval2404.imagepicker.ImagePicker.Companion.getError
3636import com.google.android.material.snackbar.Snackbar
37- import com.nextcloud.android.common.ui.theme.utils.ColorRole
3837import com.nextcloud.talk.R
3938import com.nextcloud.talk.activities.BaseActivity
4039import com.nextcloud.talk.api.NcApi
4140import com.nextcloud.talk.application.NextcloudTalkApplication
4241import com.nextcloud.talk.data.user.model.User
4342import com.nextcloud.talk.databinding.ActivityProfileBinding
44- import com.nextcloud.talk.databinding.UserInfoDetailsTableItemBinding
4543import com.nextcloud.talk.models.json.generic.GenericOverall
4644import com.nextcloud.talk.models.json.userprofile.Scope
4745import com.nextcloud.talk.models.json.userprofile.UserProfileData
@@ -433,7 +431,7 @@ class ProfileActivity : BaseActivity() {
433431 result.add(
434432 UserInfoDetailsItem (
435433 R .drawable.ic_web,
436- DisplayUtils .beautifyURL( userInfo.website) ,
434+ userInfo.website,
437435 resources!! .getString(R .string.user_info_website),
438436 Field .WEBSITE ,
439437 userInfo.websiteScope
@@ -442,7 +440,7 @@ class ProfileActivity : BaseActivity() {
442440 result.add(
443441 UserInfoDetailsItem (
444442 R .drawable.ic_twitter,
445- DisplayUtils .beautifyTwitterHandle( userInfo.twitter) ,
443+ userInfo.twitter,
446444 resources!! .getString(R .string.user_info_twitter),
447445 Field .TWITTER ,
448446 userInfo.twitterScope
@@ -587,7 +585,7 @@ class ProfileActivity : BaseActivity() {
587585 credentials,
588586 ApiUtils .getUrlForUserData(currentUser!! .baseUrl!! , currentUser!! .userId!! ),
589587 item.field.scopeName,
590- item.scope!! .name
588+ item.scope!! .id
591589 )
592590 .retry(DEFAULT_RETRIES )
593591 .subscribeOn(Schedulers .io())
@@ -598,12 +596,12 @@ class ProfileActivity : BaseActivity() {
598596 }
599597
600598 override fun onNext (userProfileOverall : GenericOverall ) {
601- Log .d(TAG , " Successfully saved: " + item.scope + " as " + item.field)
599+ Log .d(TAG , " Successfully saved: " + item.scope!! .id + " as " + item.field.scopeName )
602600 }
603601
604602 override fun onError (e : Throwable ) {
605603 item.scope = userInfo?.getScopeByField(item.field)
606- Log .e(TAG , " Failed to saved: " + item.scope + " as " + item.field, e)
604+ Log .e(TAG , " Failed to saved: " + item.scope!! .id + " as " + item.field.scopeName , e)
607605 }
608606
609607 override fun onComplete () {
@@ -629,7 +627,7 @@ class ProfileActivity : BaseActivity() {
629627 var displayList: List <UserInfoDetailsItem >?
630628 var filteredDisplayList: MutableList <UserInfoDetailsItem > = LinkedList ()
631629
632- class ViewHolder (val binding : UserInfoDetailsTableItemBinding ) : RecyclerView.ViewHolder(binding.root )
630+ class ViewHolder (val composeView : ComposeView ) : RecyclerView.ViewHolder(composeView )
633631
634632 init {
635633 this .displayList = displayList ? : LinkedList ()
@@ -653,9 +651,12 @@ class ProfileActivity : BaseActivity() {
653651 }
654652
655653 override fun onCreateViewHolder (parent : ViewGroup , viewType : Int ): ViewHolder {
656- val itemBinding =
657- UserInfoDetailsTableItemBinding .inflate(LayoutInflater .from(parent.context), parent, false )
658- return ViewHolder (itemBinding)
654+ val composeView = ComposeView (parent.context).apply {
655+ layoutParams =
656+ ViewGroup .LayoutParams (ViewGroup .LayoutParams .MATCH_PARENT , ViewGroup .LayoutParams .WRAP_CONTENT )
657+ setViewCompositionStrategy(ViewCompositionStrategy .DisposeOnDetachedFromWindowOrReleasedFromPool )
658+ }
659+ return ViewHolder (composeView)
659660 }
660661
661662 override fun onBindViewHolder (holder : ViewHolder , position : Int ) {
@@ -664,87 +665,60 @@ class ProfileActivity : BaseActivity() {
664665 } else {
665666 filteredDisplayList[position]
666667 }
667-
668- initScopeElements(item, holder)
669-
670- holder.binding.icon.setImageResource(item.icon)
671- initUserInfoEditText(holder, item)
672-
673- holder.binding.icon.contentDescription = item.hint
674- viewThemeUtils.platform.colorImageView(holder.binding.icon, ColorRole .PRIMARY )
675- if (! TextUtils .isEmpty(item.text) || profileActivity.edit) {
676- holder.binding.userInfoDetailContainer.visibility = View .VISIBLE
677- profileActivity.viewThemeUtils.material.colorTextInputLayout(holder.binding.userInfoInputLayout)
678- if (profileActivity.edit &&
679- profileActivity.editableFields.contains(item.field.toString().lowercase())
680- ) {
681- holder.binding.userInfoEditTextEdit.isEnabled = true
682- holder.binding.userInfoEditTextEdit.isFocusableInTouchMode = true
683- holder.binding.userInfoEditTextEdit.isEnabled = true
684- holder.binding.userInfoEditTextEdit.isCursorVisible = true
685- holder.binding.scope.setOnClickListener {
686- ScopeDialog (
687- holder.binding.scope.context,
688- this ,
689- item.field,
690- holder.adapterPosition
691- ).show()
692- }
693- holder.binding.scope.alpha = HIGH_EMPHASIS_ALPHA
694- } else {
695- holder.binding.userInfoEditTextEdit.isEnabled = false
696- holder.binding.userInfoEditTextEdit.isFocusableInTouchMode = false
697- holder.binding.userInfoEditTextEdit.isEnabled = false
698- holder.binding.userInfoEditTextEdit.isCursorVisible = false
699- holder.binding.scope.setOnClickListener(null )
700- holder.binding.scope.alpha = MEDIUM_EMPHASIS_ALPHA
701- }
702- } else {
703- holder.binding.userInfoDetailContainer.visibility = View .GONE
668+ val colorScheme = viewThemeUtils.getColorScheme(profileActivity)
669+ val itemPosition = when (position) {
670+ 0 -> UserInfoDetailItemPosition .FIRST
671+ filteredDisplayList.size - 1 -> UserInfoDetailItemPosition .LAST
672+ else -> UserInfoDetailItemPosition .MIDDLE
704673 }
705- }
706-
707- private fun initUserInfoEditText (holder : ViewHolder , item : UserInfoDetailsItem ) {
708- holder.binding.userInfoEditTextEdit.setText(item.text)
709- holder.binding.userInfoInputLayout.hint = item.hint
710- holder.binding.userInfoEditTextEdit.addTextChangedListener(object : TextWatcher {
711- override fun beforeTextChanged (s : CharSequence , start : Int , count : Int , after : Int ) {
712- // unused atm
713- }
714674
715- override fun onTextChanged (s : CharSequence , start : Int , before : Int , count : Int ) {
716- if (profileActivity.edit) {
717- displayList!! [holder.adapterPosition].text = holder.binding.userInfoEditTextEdit.text.toString()
718- } else {
719- filteredDisplayList[holder.adapterPosition].text =
720- holder.binding.userInfoEditTextEdit.text.toString()
675+ if (profileActivity.edit) {
676+ val itemData = UserInfoDetailItemData (
677+ icon = item.icon,
678+ text = item.text.orEmpty(),
679+ hint = item.hint,
680+ scope = item.scope
681+ )
682+ val listeners = UserInfoDetailListeners (
683+ onTextChange = { newText ->
684+ if (profileActivity.edit) {
685+ displayList!! [position].text = newText
686+ } else {
687+ filteredDisplayList[position].text = newText
688+ }
689+ },
690+ onScopeClick = { ScopeDialog (profileActivity, this , item.field, position).show() }
691+ )
692+ holder.composeView.setContent {
693+ MaterialTheme (colorScheme = colorScheme) {
694+ UserInfoDetailItemEditable (
695+ data = itemData,
696+ listeners = listeners,
697+ position = itemPosition,
698+ enabled = profileActivity.editableFields.contains(item.field.toString().lowercase())
699+ )
721700 }
722701 }
723-
724- override fun afterTextChanged (s : Editable ) {
725- // unused atm
726- }
727- })
728- }
729-
730- private fun initScopeElements (item : UserInfoDetailsItem , holder : ViewHolder ) {
731- if (item.scope == null ) {
732- holder.binding.scope.visibility = View .GONE
733702 } else {
734- holder.binding.scope.visibility = View .VISIBLE
735- when (item.scope) {
736- Scope .PRIVATE -> holder.binding.scope.setImageResource(R .drawable.ic_cellphone)
737- Scope .LOCAL -> holder.binding.scope.setImageResource(R .drawable.ic_password)
738- Scope .FEDERATED -> holder.binding.scope.setImageResource(R .drawable.ic_contacts)
739- Scope .PUBLISHED -> holder.binding.scope.setImageResource(R .drawable.ic_link)
740- null -> {
741- // nothing
703+ val displayText = when (item.field) {
704+ Field .WEBSITE -> DisplayUtils .beautifyURL(item.text)
705+ Field .TWITTER -> DisplayUtils .beautifyTwitterHandle(item.text)
706+ else -> item.text.orEmpty()
707+ }
708+ holder.composeView.setContent {
709+ MaterialTheme (colorScheme = colorScheme) {
710+ UserInfoDetailItemViewOnly (
711+ userInfo = UserInfoDetailItemData (
712+ icon = item.icon,
713+ text = displayText,
714+ hint = item.hint,
715+ scope = item.scope
716+ ),
717+ position = itemPosition,
718+ ellipsize = Field .EMAIL == item.field
719+ )
742720 }
743721 }
744- holder.binding.scope.contentDescription = holder.binding.scope.context.getString(
745- R .string.scope_toggle_description,
746- item.hint
747- )
748722 }
749723 }
750724
@@ -774,7 +748,5 @@ class ProfileActivity : BaseActivity() {
774748 private val TAG = ProfileActivity ::class .java.simpleName
775749 private const val DEFAULT_CACHE_SIZE : Int = 20
776750 private const val DEFAULT_RETRIES : Long = 3
777- private const val HIGH_EMPHASIS_ALPHA : Float = 0.87f
778- private const val MEDIUM_EMPHASIS_ALPHA : Float = 0.6f
779751 }
780752}
0 commit comments