diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index bd1ef180f..4a4c17575 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -214,6 +214,10 @@
android:name=".conversation.info.ConversationInfoActivity"
android:theme="@style/AppTheme" />
+
+
diff --git a/app/src/main/java/com/nextcloud/talk/conversation/info/ConversationInfoActivity.kt b/app/src/main/java/com/nextcloud/talk/conversation/info/ConversationInfoActivity.kt
index 614030faa..3615b2d75 100644
--- a/app/src/main/java/com/nextcloud/talk/conversation/info/ConversationInfoActivity.kt
+++ b/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? = null
private var userItems: MutableList = 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 {
- 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 {
- 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) {
diff --git a/app/src/main/java/com/nextcloud/talk/conversation/info/ConversationInfoEditActivity.kt b/app/src/main/java/com/nextcloud/talk/conversation/info/ConversationInfoEditActivity.kt
new file mode 100644
index 000000000..55718e9c3
--- /dev/null
+++ b/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
+ * Copyright (C) 2021 Andy Scherzinger (info@andy-scherzinger.de)
+ * Copyright (C) 2017-2018 Mario Danic
+ *
+ * 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 .
+ */
+
+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(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 {
+ 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 {
+ 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"
+ }
+}
diff --git a/app/src/main/res/layout/activity_conversation_info.xml b/app/src/main/res/layout/activity_conversation_info.xml
index 2ed5437ef..daf7f7964 100644
--- a/app/src/main/res/layout/activity_conversation_info.xml
+++ b/app/src/main/res/layout/activity_conversation_info.xml
@@ -106,66 +106,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+