Browse Source

WIP: add new screen for conversation info editing

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
Marcel Hibbe 2 years ago
parent
commit
3dc3bf0cf8

+ 4 - 0
app/src/main/AndroidManifest.xml

@@ -214,6 +214,10 @@
             android:name=".conversation.info.ConversationInfoActivity"
             android:theme="@style/AppTheme" />
 
+        <activity
+            android:name=".conversation.info.ConversationInfoEditActivity"
+            android:theme="@style/AppTheme" />
+
         <activity
             android:name=".contacts.ContactsActivity"
             android:theme="@style/AppTheme" />

+ 13 - 168
app/src/main/java/com/nextcloud/talk/conversation/info/ConversationInfoActivity.kt

@@ -27,7 +27,6 @@
 package com.nextcloud.talk.conversation.info
 
 import android.annotation.SuppressLint
-import android.app.Activity
 import android.content.Intent
 import android.graphics.drawable.ColorDrawable
 import android.os.Bundle
@@ -42,8 +41,6 @@ import android.view.View.VISIBLE
 import android.widget.Toast
 import androidx.appcompat.app.AlertDialog
 import androidx.appcompat.widget.SwitchCompat
-import androidx.core.net.toFile
-import androidx.core.view.ViewCompat
 import androidx.work.Data
 import androidx.work.OneTimeWorkRequest
 import androidx.work.WorkManager
@@ -52,7 +49,6 @@ import com.afollestad.materialdialogs.LayoutMode.WRAP_CONTENT
 import com.afollestad.materialdialogs.MaterialDialog
 import com.afollestad.materialdialogs.bottomsheets.BottomSheet
 import com.afollestad.materialdialogs.datetime.dateTimePicker
-import com.github.dhaval2404.imagepicker.ImagePicker
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
 import com.nextcloud.talk.R
 import com.nextcloud.talk.activities.BaseActivity
@@ -85,9 +81,6 @@ import com.nextcloud.talk.shareditems.activities.SharedItemsActivity
 import com.nextcloud.talk.utils.ApiUtils
 import com.nextcloud.talk.utils.DateConstants
 import com.nextcloud.talk.utils.DateUtils
-import com.nextcloud.talk.utils.DisplayUtils
-import com.nextcloud.talk.utils.Mimetype
-import com.nextcloud.talk.utils.PickImage
 import com.nextcloud.talk.utils.bundle.BundleKeys
 import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew
 import com.nextcloud.talk.utils.preferences.preferencestorage.DatabaseStorageModule
@@ -97,12 +90,9 @@ import io.reactivex.Observer
 import io.reactivex.android.schedulers.AndroidSchedulers
 import io.reactivex.disposables.Disposable
 import io.reactivex.schedulers.Schedulers
-import okhttp3.MediaType.Companion.toMediaTypeOrNull
-import okhttp3.MultipartBody
-import okhttp3.RequestBody.Companion.asRequestBody
 import org.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.ThreadMode
-import java.io.File
+import org.parceler.Parcels
 import java.util.Calendar
 import java.util.Collections
 import java.util.Locale
@@ -137,11 +127,6 @@ class ConversationInfoActivity :
     private var adapter: FlexibleAdapter<ParticipantItem>? = null
     private var userItems: MutableList<ParticipantItem> = ArrayList()
 
-    private lateinit var optionsMenu: Menu
-    private var edit = false
-
-    private lateinit var pickImage: PickImage
-
     private val workerData: Data?
         get() {
             if (!TextUtils.isEmpty(conversationToken) && conversationUser != null) {
@@ -176,8 +161,6 @@ class ConversationInfoActivity :
             databaseStorageModule = DatabaseStorageModule(conversationUser, conversationToken)
         }
 
-        setupAvatarOptions()
-
         binding.notificationSettingsView.notificationSettings.setStorageModule(databaseStorageModule)
         binding.webinarInfoView.webinarSettings.setStorageModule(databaseStorageModule)
         binding.guestAccessView.guestAccessSettings.setStorageModule(databaseStorageModule)
@@ -203,22 +186,6 @@ class ConversationInfoActivity :
         binding.progressBar.let { viewThemeUtils.platform.colorCircularProgressBar(it) }
     }
 
-    private fun setupAvatarOptions() {
-        pickImage = PickImage(this, conversationUser)
-        binding.avatarUpload.setOnClickListener { pickImage.selectLocal() }
-        binding.avatarChoose.setOnClickListener { pickImage.selectRemote() }
-        binding.avatarCamera.setOnClickListener { pickImage.takePicture() }
-        binding.avatarDelete.setOnClickListener { deleteAvatar() }
-        binding.avatarImage.let { ViewCompat.setTransitionName(it, "userAvatar.transitionTag") }
-
-        binding.let {
-            viewThemeUtils.material.themeFAB(it.avatarUpload)
-            viewThemeUtils.material.themeFAB(it.avatarChoose)
-            viewThemeUtils.material.themeFAB(it.avatarCamera)
-            viewThemeUtils.material.themeFAB(it.avatarDelete)
-        }
-    }
-
     private fun setupActionBar() {
         setSupportActionBar(binding.conversationInfoToolbar)
         binding.conversationInfoToolbar.setNavigationOnClickListener {
@@ -239,7 +206,6 @@ class ConversationInfoActivity :
         super.onCreateOptionsMenu(menu)
         if (CapabilitiesUtilNew.isConversationAvatarEndpointAvailable(conversationUser)) {
             menuInflater.inflate(R.menu.menu_conversation_info, menu)
-            optionsMenu = menu
             return true
         }
         return false
@@ -248,13 +214,23 @@ class ConversationInfoActivity :
     override fun onPrepareOptionsMenu(menu: Menu): Boolean {
         super.onPrepareOptionsMenu(menu)
         // menu.findItem(R.id.edit).isVisible = editableFields.size > 0
-        setEditMode(false)
+
         return true
     }
 
     override fun onOptionsItemSelected(item: MenuItem): Boolean {
         if (item.itemId == R.id.edit) {
-            toggleEditMode()
+            val bundle = Bundle()
+            bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, conversationUser)
+            bundle.putParcelable(
+                BundleKeys.KEY_ACTIVE_CONVERSATION,
+                Parcels.wrap(conversation)
+            )
+            bundle.putString(BundleKeys.KEY_ROOM_TOKEN, conversationToken)
+
+            val intent = Intent(this, ConversationInfoEditActivity::class.java)
+            intent.putExtras(bundle)
+            startActivity(intent)
         }
         return true
     }
@@ -288,135 +264,6 @@ class ConversationInfoActivity :
         }
     }
 
-    private fun toggleEditMode() {
-        edit = !edit
-        if (edit) {
-            setEditMode(true)
-        } else {
-            setEditMode(false)
-        }
-    }
-
-    private fun setEditMode(editing: Boolean) {
-        if (editing) {
-            optionsMenu.findItem(R.id.edit).setTitle(R.string.save)
-            binding.avatarUpload.visibility = VISIBLE
-            binding.avatarChoose.visibility = VISIBLE
-            binding.avatarCamera.visibility = VISIBLE
-            binding.avatarDelete.visibility = VISIBLE
-            edit = true
-        } else {
-            optionsMenu.findItem(R.id.edit).setTitle(R.string.edit)
-            binding.avatarUpload.visibility = GONE
-            binding.avatarChoose.visibility = GONE
-            binding.avatarCamera.visibility = GONE
-            binding.avatarDelete.visibility = GONE
-            edit = false
-        }
-    }
-
-    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()) }
-            }
-
-            ImagePicker.RESULT_ERROR -> {
-                Toast.makeText(this, ImagePicker.getError(data), Toast.LENGTH_SHORT).show()
-            }
-
-            else -> {
-                Log.i(TAG, "Task Cancelled")
-            }
-        }
-    }
-
-    private fun uploadAvatar(file: File?) {
-        val builder = MultipartBody.Builder()
-        builder.setType(MultipartBody.FORM)
-        builder.addFormDataPart(
-            "file",
-            file!!.name,
-            file.asRequestBody(Mimetype.IMAGE_PREFIX_GENERIC.toMediaTypeOrNull())
-        )
-        val filePart: MultipartBody.Part = MultipartBody.Part.createFormData(
-            "file",
-            file.name,
-            file.asRequestBody(Mimetype.IMAGE_JPG.toMediaTypeOrNull())
-        )
-
-        // upload file
-        ncApi.uploadAvatar(
-            credentials,
-            ApiUtils.getUrlForConversationAvatar(1, conversationUser.baseUrl, conversation!!.token),
-            filePart
-        )
-            .subscribeOn(Schedulers.io())
-            .observeOn(AndroidSchedulers.mainThread())
-            .subscribe(object : Observer<GenericOverall> {
-                override fun onSubscribe(d: Disposable) {
-                    // unused atm
-                }
-
-                override fun onNext(genericOverall: GenericOverall) {
-                    DisplayUtils.loadAvatarImage(conversationUser, binding.avatarImage, true)
-                }
-
-                override fun onError(e: Throwable) {
-                    Toast.makeText(
-                        applicationContext,
-                        context.getString(R.string.default_error_msg),
-                        Toast.LENGTH_LONG
-                    ).show()
-                    Log.e(TAG, "Error uploading avatar", e)
-                }
-
-                override fun onComplete() {
-                    setEditMode(false)
-                }
-            })
-    }
-
-    private fun deleteAvatar() {
-        ncApi.deleteAvatar(
-            credentials,
-            ApiUtils.getUrlForConversationAvatar(1, conversationUser.baseUrl, conversationToken)
-        )
-            .subscribeOn(Schedulers.io())
-            .observeOn(AndroidSchedulers.mainThread())
-            .subscribe(object : Observer<GenericOverall> {
-                override fun onSubscribe(d: Disposable) {
-                    // unused atm
-                }
-
-                override fun onNext(genericOverall: GenericOverall) {
-                    DisplayUtils.loadAvatarImage(
-                        conversationUser,
-                        binding.avatarImage,
-                        true
-                    )
-                }
-
-                override fun onError(e: Throwable) {
-                    Toast.makeText(
-                        applicationContext,
-                        context.getString(R.string.default_error_msg),
-                        Toast.LENGTH_LONG
-                    ).show()
-                    Log.e(TAG, "Failed to delete avatar", e)
-                }
-
-                override fun onComplete() {
-                    setEditMode(false)
-                }
-            })
-    }
-
     private fun showSharedItems() {
         val intent = Intent(this, SharedItemsActivity::class.java)
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
@@ -816,11 +663,9 @@ class ConversationInfoActivity :
                         } else {
                             binding?.clearConversationHistory?.visibility = GONE
                         }
-                        binding.avatarButtons.visibility = VISIBLE
                     } else {
                         binding?.addParticipantsAction?.visibility = GONE
                         binding?.clearConversationHistory?.visibility = GONE
-                        binding.avatarButtons.visibility = GONE
                     }
 
                     if (!isDestroyed) {

+ 327 - 0
app/src/main/java/com/nextcloud/talk/conversation/info/ConversationInfoEditActivity.kt

@@ -0,0 +1,327 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Mario Danic
+ * @author Andy Scherzinger
+ * @author Tim Krüger
+ * @author Marcel Hibbe
+ * Copyright (C) 2022-2023 Marcel Hibbe (dev@mhibbe.de)
+ * Copyright (C) 2021-2022 Tim Krüger <t@timkrueger.me>
+ * Copyright (C) 2021 Andy Scherzinger (info@andy-scherzinger.de)
+ * Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.talk.conversation.info
+
+import android.app.Activity
+import android.content.Intent
+import android.graphics.drawable.ColorDrawable
+import android.os.Bundle
+import android.text.TextUtils
+import android.util.Log
+import android.view.Menu
+import android.widget.Toast
+import androidx.core.net.toFile
+import androidx.core.view.ViewCompat
+import autodagger.AutoInjector
+import com.github.dhaval2404.imagepicker.ImagePicker
+import com.nextcloud.talk.R
+import com.nextcloud.talk.activities.BaseActivity
+import com.nextcloud.talk.api.NcApi
+import com.nextcloud.talk.application.NextcloudTalkApplication
+import com.nextcloud.talk.data.user.model.User
+import com.nextcloud.talk.databinding.ActivityConversationInfoEditBinding
+import com.nextcloud.talk.extensions.loadAvatar
+import com.nextcloud.talk.extensions.loadConversationAvatar
+import com.nextcloud.talk.extensions.loadSystemAvatar
+import com.nextcloud.talk.models.json.conversations.Conversation
+import com.nextcloud.talk.models.json.generic.GenericOverall
+import com.nextcloud.talk.repositories.conversations.ConversationsRepository
+import com.nextcloud.talk.utils.ApiUtils
+import com.nextcloud.talk.utils.DateUtils
+import com.nextcloud.talk.utils.DisplayUtils
+import com.nextcloud.talk.utils.Mimetype
+import com.nextcloud.talk.utils.PickImage
+import com.nextcloud.talk.utils.bundle.BundleKeys
+import io.reactivex.Observer
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.Disposable
+import io.reactivex.schedulers.Schedulers
+import okhttp3.MediaType.Companion.toMediaTypeOrNull
+import okhttp3.MultipartBody
+import okhttp3.RequestBody.Companion.asRequestBody
+import org.parceler.Parcels
+import java.io.File
+import javax.inject.Inject
+
+@AutoInjector(NextcloudTalkApplication::class)
+class ConversationInfoEditActivity :
+    BaseActivity() {
+
+    private lateinit var binding: ActivityConversationInfoEditBinding
+
+    @Inject
+    lateinit var ncApi: NcApi
+
+    @Inject
+    lateinit var conversationsRepository: ConversationsRepository
+
+    @Inject
+    lateinit var dateUtils: DateUtils
+
+    private lateinit var conversationToken: String
+    private lateinit var conversationUser: User
+    private lateinit var credentials: String
+
+    private var conversation: Conversation? = null
+
+    private lateinit var optionsMenu: Menu
+    private var edit = false
+
+    private lateinit var pickImage: PickImage
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
+
+        binding = ActivityConversationInfoEditBinding.inflate(layoutInflater)
+        setupActionBar()
+        setContentView(binding.root)
+        setupSystemColors()
+
+        val extras: Bundle? = intent.extras
+
+        conversationUser = extras?.getParcelable(BundleKeys.KEY_USER_ENTITY)!!
+        conversationToken = extras.getString(BundleKeys.KEY_ROOM_TOKEN)!!
+
+        if (intent.hasExtra(BundleKeys.KEY_ACTIVE_CONVERSATION)) {
+            conversation = Parcels.unwrap<Conversation>(extras.getParcelable(BundleKeys.KEY_ACTIVE_CONVERSATION))
+        }
+
+        credentials = ApiUtils.getCredentials(conversationUser.username, conversationUser.token)
+    }
+
+    override fun onResume() {
+        super.onResume()
+
+        loadConversationAvatar()
+
+        binding.displayNameText.text = conversation!!.displayName
+
+        if (conversation!!.description != null && conversation!!.description!!.isNotEmpty()) {
+            binding.descriptionText.text = conversation!!.description
+        }
+
+        setupAvatarOptions()
+    }
+
+    private fun setupAvatarOptions() {
+        pickImage = PickImage(this, conversationUser)
+        binding.avatarUpload.setOnClickListener { pickImage.selectLocal() }
+        binding.avatarChoose.setOnClickListener { pickImage.selectRemote() }
+        binding.avatarCamera.setOnClickListener { pickImage.takePicture() }
+        binding.avatarDelete.setOnClickListener { deleteAvatar() }
+        binding.avatarImage.let { ViewCompat.setTransitionName(it, "userAvatar.transitionTag") }
+
+        binding.let {
+            viewThemeUtils.material.themeFAB(it.avatarUpload)
+            viewThemeUtils.material.themeFAB(it.avatarChoose)
+            viewThemeUtils.material.themeFAB(it.avatarCamera)
+            viewThemeUtils.material.themeFAB(it.avatarDelete)
+        }
+    }
+
+    private fun setupActionBar() {
+        setSupportActionBar(binding.conversationInfoEditToolbar)
+        binding.conversationInfoEditToolbar.setNavigationOnClickListener {
+            onBackPressed()
+        }
+        supportActionBar?.setDisplayHomeAsUpEnabled(true)
+        supportActionBar?.setDisplayShowHomeEnabled(true)
+        supportActionBar?.setIcon(ColorDrawable(resources!!.getColor(android.R.color.transparent)))
+        supportActionBar?.title = resources!!.getString(R.string.nc_conversation_menu_conversation_info)
+
+        viewThemeUtils.material.themeToolbar(binding.conversationInfoEditToolbar)
+    }
+
+    // override fun onCreateOptionsMenu(menu: Menu): Boolean {
+    //     super.onCreateOptionsMenu(menu)
+    //
+    //     menuInflater.inflate(R.menu.menu_conversation_info, menu)
+    //     optionsMenu = menu
+    //     return true
+    // }
+    //
+    // override fun onPrepareOptionsMenu(menu: Menu): Boolean {
+    //     super.onPrepareOptionsMenu(menu)
+    //     // menu.findItem(R.id.edit).isVisible = editableFields.size > 0
+    //     setEditMode(true)
+    //     return true
+    // }
+    //
+    // override fun onOptionsItemSelected(item: MenuItem): Boolean {
+    //     if (item.itemId == R.id.edit) {
+    //         toggleEditMode()
+    //     }
+    //     return true
+    // }
+    //
+    //
+    // private fun toggleEditMode() {
+    //     edit = !edit
+    //     if (edit) {
+    //         setEditMode(true)
+    //     } else {
+    //         setEditMode(false)
+    //     }
+    // }
+    //
+    // private fun setEditMode(editing: Boolean) {
+    //     if (editing) {
+    //         optionsMenu.findItem(R.id.edit).setTitle(R.string.save)
+    //         edit = true
+    //     } else {
+    //         optionsMenu.findItem(R.id.edit).setTitle(R.string.edit)
+    //         edit = false
+    //     }
+    // }
+
+    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()) }
+            }
+
+            ImagePicker.RESULT_ERROR -> {
+                Toast.makeText(this, ImagePicker.getError(data), Toast.LENGTH_SHORT).show()
+            }
+
+            else -> {
+                Log.i(TAG, "Task Cancelled")
+            }
+        }
+    }
+
+    private fun uploadAvatar(file: File?) {
+        val builder = MultipartBody.Builder()
+        builder.setType(MultipartBody.FORM)
+        builder.addFormDataPart(
+            "file",
+            file!!.name,
+            file.asRequestBody(Mimetype.IMAGE_PREFIX_GENERIC.toMediaTypeOrNull())
+        )
+        val filePart: MultipartBody.Part = MultipartBody.Part.createFormData(
+            "file",
+            file.name,
+            file.asRequestBody(Mimetype.IMAGE_JPG.toMediaTypeOrNull())
+        )
+
+        // upload file
+        ncApi.uploadAvatar(
+            credentials,
+            ApiUtils.getUrlForConversationAvatar(1, conversationUser.baseUrl, conversation!!.token),
+            filePart
+        )
+            .subscribeOn(Schedulers.io())
+            .observeOn(AndroidSchedulers.mainThread())
+            .subscribe(object : Observer<GenericOverall> {
+                override fun onSubscribe(d: Disposable) {
+                    // unused atm
+                }
+
+                override fun onNext(genericOverall: GenericOverall) {
+                    DisplayUtils.loadAvatarImage(conversationUser, binding.avatarImage, true)
+                }
+
+                override fun onError(e: Throwable) {
+                    Toast.makeText(
+                        applicationContext,
+                        context.getString(R.string.default_error_msg),
+                        Toast.LENGTH_LONG
+                    ).show()
+                    Log.e(TAG, "Error uploading avatar", e)
+                }
+
+                override fun onComplete() {
+                    // setEditMode(false)
+                }
+            })
+    }
+
+    private fun deleteAvatar() {
+        ncApi.deleteAvatar(
+            credentials,
+            ApiUtils.getUrlForConversationAvatar(1, conversationUser.baseUrl, conversationToken)
+        )
+            .subscribeOn(Schedulers.io())
+            .observeOn(AndroidSchedulers.mainThread())
+            .subscribe(object : Observer<GenericOverall> {
+                override fun onSubscribe(d: Disposable) {
+                    // unused atm
+                }
+
+                override fun onNext(genericOverall: GenericOverall) {
+                    DisplayUtils.loadAvatarImage(
+                        conversationUser,
+                        binding.avatarImage,
+                        true
+                    )
+                }
+
+                override fun onError(e: Throwable) {
+                    Toast.makeText(
+                        applicationContext,
+                        context.getString(R.string.default_error_msg),
+                        Toast.LENGTH_LONG
+                    ).show()
+                    Log.e(TAG, "Failed to delete avatar", e)
+                }
+
+                override fun onComplete() {
+                    // setEditMode(false)
+                }
+            })
+    }
+
+    private fun loadConversationAvatar() {
+        when (conversation!!.type) {
+            Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL -> if (!TextUtils.isEmpty(conversation!!.name)) {
+                conversation!!.name?.let { binding.avatarImage.loadAvatar(conversationUser, it) }
+            }
+
+            Conversation.ConversationType.ROOM_GROUP_CALL, Conversation.ConversationType.ROOM_PUBLIC_CALL -> {
+                binding.avatarImage.loadConversationAvatar(conversationUser, conversation!!)
+            }
+
+            Conversation.ConversationType.ROOM_SYSTEM -> {
+                binding.avatarImage.loadSystemAvatar()
+            }
+
+            else -> {
+                // unused atm
+            }
+        }
+    }
+
+    companion object {
+        private const val TAG = "ConversationEditInfo"
+    }
+}

+ 0 - 60
app/src/main/res/layout/activity_conversation_info.xml

@@ -106,66 +106,6 @@
 
                 </RelativeLayout>
 
-                <LinearLayout
-                    android:id="@+id/avatar_buttons"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:gravity="center"
-                    android:orientation="horizontal"
-                    android:layout_marginTop="@dimen/standard_margin"
-                    android:visibility="invisible"
-                    tools:visibility="visible">
-
-                    <com.google.android.material.floatingactionbutton.FloatingActionButton
-                        android:id="@+id/avatar_upload"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:layout_marginLeft="@dimen/standard_quarter_margin"
-                        android:layout_marginRight="@dimen/standard_quarter_margin"
-                        android:contentDescription="@string/upload_new_avatar_from_device"
-                        android:tint="@android:color/white"
-                        app:elevation="0dp"
-                        app:fabSize="mini"
-                        app:srcCompat="@drawable/upload" />
-
-                    <com.google.android.material.floatingactionbutton.FloatingActionButton
-                        android:id="@+id/avatar_choose"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:layout_marginLeft="@dimen/standard_quarter_margin"
-                        android:layout_marginRight="@dimen/standard_quarter_margin"
-                        android:contentDescription="@string/choose_avatar_from_cloud"
-                        android:tint="@android:color/white"
-                        app:elevation="0dp"
-                        app:fabSize="mini"
-                        app:srcCompat="@drawable/ic_mimetype_folder" />
-
-                    <com.google.android.material.floatingactionbutton.FloatingActionButton
-                        android:id="@+id/avatar_camera"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:layout_marginLeft="@dimen/standard_quarter_margin"
-                        android:layout_marginRight="@dimen/standard_quarter_margin"
-                        android:contentDescription="@string/set_avatar_from_camera"
-                        android:tint="@android:color/white"
-                        app:elevation="0dp"
-                        app:fabSize="mini"
-                        app:srcCompat="@drawable/ic_baseline_photo_camera_24" />
-
-                    <com.google.android.material.floatingactionbutton.FloatingActionButton
-                        android:id="@+id/avatar_delete"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:layout_marginLeft="@dimen/standard_quarter_margin"
-                        android:layout_marginRight="@dimen/standard_quarter_margin"
-                        android:contentDescription="@string/delete_avatar"
-                        android:tint="@android:color/white"
-                        app:elevation="0dp"
-                        app:fabSize="mini"
-                        app:srcCompat="@drawable/trashbin" />
-
-                </LinearLayout>
-
             </com.yarolegovich.mp.MaterialPreferenceCategory>
 
             <com.yarolegovich.mp.MaterialPreferenceCategory

+ 145 - 0
app/src/main/res/layout/activity_conversation_info_edit.xml

@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Nextcloud Talk application
+  ~
+  ~ @author Mario Danic
+  ~ @author Andy Scherzinger
+  ~ @author Marcel Hibbe
+  ~ @author Tim Krüger
+  ~ Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
+  ~ Copyright (C) 2022-2023 Marcel Hibbe <dev@mhibbe.de>
+  ~ Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
+  ~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
+  ~
+  ~ This program is free software: you can redistribute it and/or modify
+  ~ it under the terms of the GNU General Public License as published by
+  ~ the Free Software Foundation, either version 3 of the License, or
+  ~ at your option) any later version.
+  ~
+  ~ This program is distributed in the hope that it will be useful,
+  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  ~ GNU General Public License for more details.
+  ~
+  ~ You should have received a copy of the GNU General Public License
+  ~ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/parent_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <com.google.android.material.appbar.AppBarLayout
+        android:id="@+id/conversation_info_edit_appbar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+
+        <com.google.android.material.appbar.MaterialToolbar
+            android:id="@+id/conversation_info_edit_toolbar"
+            android:layout_width="match_parent"
+            android:layout_height="?attr/actionBarSize"
+            android:background="@color/appbar"
+            android:theme="?attr/actionBarPopupTheme"
+            app:layout_scrollFlags="scroll|enterAlways"
+            app:navigationIconTint="@color/fontAppbar"
+            app:popupTheme="@style/appActionBarPopupMenu"
+            app:titleTextColor="@color/fontAppbar"
+            tools:title="@string/nc_app_product_name" />
+    </com.google.android.material.appbar.AppBarLayout>
+
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+
+        <ImageView
+            android:id="@+id/avatar_image"
+            android:layout_width="@dimen/avatar_size_big"
+            android:layout_height="@dimen/avatar_size_big"
+            android:layout_marginTop="@dimen/standard_margin"
+            android:layout_gravity="center"
+            android:contentDescription="@string/avatar"
+            tools:src="@drawable/account_circle_48dp" />
+
+        <LinearLayout
+            android:id="@+id/avatar_buttons"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_margin="@dimen/standard_margin"
+            android:gravity="center"
+            android:orientation="horizontal">
+
+            <com.google.android.material.floatingactionbutton.FloatingActionButton
+                android:id="@+id/avatar_upload"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/standard_quarter_margin"
+                android:layout_marginRight="@dimen/standard_quarter_margin"
+                android:contentDescription="@string/upload_new_avatar_from_device"
+                android:tint="@android:color/white"
+                app:elevation="0dp"
+                app:fabSize="mini"
+                app:srcCompat="@drawable/upload" />
+
+            <com.google.android.material.floatingactionbutton.FloatingActionButton
+                android:id="@+id/avatar_choose"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/standard_quarter_margin"
+                android:layout_marginRight="@dimen/standard_quarter_margin"
+                android:contentDescription="@string/choose_avatar_from_cloud"
+                android:tint="@android:color/white"
+                app:elevation="0dp"
+                app:fabSize="mini"
+                app:srcCompat="@drawable/ic_mimetype_folder" />
+
+            <com.google.android.material.floatingactionbutton.FloatingActionButton
+                android:id="@+id/avatar_camera"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/standard_quarter_margin"
+                android:layout_marginRight="@dimen/standard_quarter_margin"
+                android:contentDescription="@string/set_avatar_from_camera"
+                android:tint="@android:color/white"
+                app:elevation="0dp"
+                app:fabSize="mini"
+                app:srcCompat="@drawable/ic_baseline_photo_camera_24" />
+
+            <com.google.android.material.floatingactionbutton.FloatingActionButton
+                android:id="@+id/avatar_delete"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/standard_quarter_margin"
+                android:layout_marginRight="@dimen/standard_quarter_margin"
+                android:contentDescription="@string/delete_avatar"
+                android:tint="@android:color/white"
+                app:elevation="0dp"
+                app:fabSize="mini"
+                app:srcCompat="@drawable/trashbin" />
+        </LinearLayout>
+
+        <androidx.emoji2.widget.EmojiTextView
+            android:id="@+id/display_name_text"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:layout_marginTop="@dimen/margin_between_elements"
+            tools:text="Jane Doe" />
+
+        <androidx.emoji2.widget.EmojiTextView
+            android:id="@+id/description_text"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:layout_margin="@dimen/standard_margin"
+            android:layout_marginTop="@dimen/margin_between_elements"
+            android:autoLink="web"
+            tools:text="Hello world!" />
+
+    </LinearLayout>
+
+</LinearLayout>