WIP: Add conversation avatar options in conversation info

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
Marcel Hibbe 2023-04-21 09:53:04 +02:00
parent 87c53979c4
commit fdb845d298
No known key found for this signature in database
GPG Key ID: C793F8B59F43CE7B
3 changed files with 159 additions and 5 deletions

View File

@ -27,6 +27,7 @@
package com.nextcloud.talk.conversation.info package com.nextcloud.talk.conversation.info
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent import android.content.Intent
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.os.Bundle import android.os.Bundle
@ -39,6 +40,8 @@ import android.view.View.VISIBLE
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.SwitchCompat import androidx.appcompat.widget.SwitchCompat
import androidx.core.net.toFile
import androidx.core.view.ViewCompat
import androidx.work.Data import androidx.work.Data
import androidx.work.OneTimeWorkRequest import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager import androidx.work.WorkManager
@ -47,6 +50,7 @@ import com.afollestad.materialdialogs.LayoutMode.WRAP_CONTENT
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.bottomsheets.BottomSheet import com.afollestad.materialdialogs.bottomsheets.BottomSheet
import com.afollestad.materialdialogs.datetime.dateTimePicker import com.afollestad.materialdialogs.datetime.dateTimePicker
import com.github.dhaval2404.imagepicker.ImagePicker
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.activities.BaseActivity import com.nextcloud.talk.activities.BaseActivity
@ -58,7 +62,7 @@ import com.nextcloud.talk.contacts.ContactsActivity
import com.nextcloud.talk.controllers.bottomsheet.items.BasicListItemWithImage import com.nextcloud.talk.controllers.bottomsheet.items.BasicListItemWithImage
import com.nextcloud.talk.controllers.bottomsheet.items.listItemsWithImage import com.nextcloud.talk.controllers.bottomsheet.items.listItemsWithImage
import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.databinding.ControllerConversationInfoBinding import com.nextcloud.talk.databinding.ActivityConversationInfoBinding
import com.nextcloud.talk.events.EventStatus import com.nextcloud.talk.events.EventStatus
import com.nextcloud.talk.extensions.loadAvatar import com.nextcloud.talk.extensions.loadAvatar
import com.nextcloud.talk.extensions.loadConversationAvatar import com.nextcloud.talk.extensions.loadConversationAvatar
@ -79,6 +83,9 @@ import com.nextcloud.talk.shareditems.activities.SharedItemsActivity
import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DateConstants import com.nextcloud.talk.utils.DateConstants
import com.nextcloud.talk.utils.DateUtils 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.bundle.BundleKeys
import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew
import com.nextcloud.talk.utils.preferences.preferencestorage.DatabaseStorageModule import com.nextcloud.talk.utils.preferences.preferencestorage.DatabaseStorageModule
@ -88,8 +95,12 @@ import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers 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.Subscribe
import org.greenrobot.eventbus.ThreadMode import org.greenrobot.eventbus.ThreadMode
import java.io.File
import java.util.Calendar import java.util.Calendar
import java.util.Collections import java.util.Collections
import java.util.Locale import java.util.Locale
@ -100,7 +111,7 @@ class ConversationInfoActivity :
BaseActivity(), BaseActivity(),
FlexibleAdapter.OnItemClickListener { FlexibleAdapter.OnItemClickListener {
private lateinit var binding: ControllerConversationInfoBinding private lateinit var binding: ActivityConversationInfoBinding
@Inject @Inject
lateinit var ncApi: NcApi lateinit var ncApi: NcApi
@ -124,6 +135,8 @@ class ConversationInfoActivity :
private var adapter: FlexibleAdapter<ParticipantItem>? = null private var adapter: FlexibleAdapter<ParticipantItem>? = null
private var userItems: MutableList<ParticipantItem> = ArrayList() private var userItems: MutableList<ParticipantItem> = ArrayList()
private lateinit var pickImage: PickImage
private val workerData: Data? private val workerData: Data?
get() { get() {
if (!TextUtils.isEmpty(conversationToken) && conversationUser != null) { if (!TextUtils.isEmpty(conversationToken) && conversationUser != null) {
@ -140,7 +153,7 @@ class ConversationInfoActivity :
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this) NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
binding = ControllerConversationInfoBinding.inflate(layoutInflater) binding = ActivityConversationInfoBinding.inflate(layoutInflater)
setupActionBar() setupActionBar()
setContentView(binding.root) setContentView(binding.root)
setupSystemColors() setupSystemColors()
@ -158,6 +171,8 @@ class ConversationInfoActivity :
databaseStorageModule = DatabaseStorageModule(conversationUser, conversationToken) databaseStorageModule = DatabaseStorageModule(conversationUser, conversationToken)
} }
setupAvatarOptions()
binding.notificationSettingsView.notificationSettings.setStorageModule(databaseStorageModule) binding.notificationSettingsView.notificationSettings.setStorageModule(databaseStorageModule)
binding.webinarInfoView.webinarSettings.setStorageModule(databaseStorageModule) binding.webinarInfoView.webinarSettings.setStorageModule(databaseStorageModule)
binding.guestAccessView.guestAccessSettings.setStorageModule(databaseStorageModule) binding.guestAccessView.guestAccessSettings.setStorageModule(databaseStorageModule)
@ -183,6 +198,81 @@ class ConversationInfoActivity :
binding.progressBar.let { viewThemeUtils.platform.colorCircularProgressBar(it) } 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 {}
binding.avatarImage.let { ViewCompat.setTransitionName(it, "userAvatar.transitionTag") }
}
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(
"files[]",
file!!.name,
file.asRequestBody(Mimetype.IMAGE_PREFIX_GENERIC.toMediaTypeOrNull())
)
val filePart: MultipartBody.Part = MultipartBody.Part.createFormData(
"files[]",
file.name,
file.asRequestBody(Mimetype.IMAGE_JPG.toMediaTypeOrNull())
)
// upload file
ncApi.uploadAvatar(
ApiUtils.getCredentials(conversationUser.username, conversationUser.token),
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() {
// unused atm
}
})
}
private fun setupActionBar() { private fun setupActionBar() {
setSupportActionBar(binding.conversationInfoToolbar) setSupportActionBar(binding.conversationInfoToolbar)
binding.conversationInfoToolbar.setNavigationOnClickListener { binding.conversationInfoToolbar.setNavigationOnClickListener {
@ -627,9 +717,11 @@ class ConversationInfoActivity :
} else { } else {
binding?.clearConversationHistory?.visibility = GONE binding?.clearConversationHistory?.visibility = GONE
} }
binding.avatarButtons.visibility = VISIBLE
} else { } else {
binding?.addParticipantsAction?.visibility = GONE binding?.addParticipantsAction?.visibility = GONE
binding?.clearConversationHistory?.visibility = GONE binding?.clearConversationHistory?.visibility = GONE
binding.avatarButtons.visibility = GONE
} }
if (!isDestroyed) { if (!isDestroyed) {
@ -761,9 +853,11 @@ class ConversationInfoActivity :
Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL -> if (!TextUtils.isEmpty(conversation!!.name)) { Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL -> if (!TextUtils.isEmpty(conversation!!.name)) {
conversation!!.name?.let { binding.avatarImage.loadAvatar(conversationUser, it) } conversation!!.name?.let { binding.avatarImage.loadAvatar(conversationUser, it) }
} }
Conversation.ConversationType.ROOM_GROUP_CALL, Conversation.ConversationType.ROOM_PUBLIC_CALL -> { Conversation.ConversationType.ROOM_GROUP_CALL, Conversation.ConversationType.ROOM_PUBLIC_CALL -> {
binding.avatarImage.loadConversationAvatar(conversationUser, conversation!!) binding.avatarImage.loadConversationAvatar(conversationUser, conversation!!)
} }
Conversation.ConversationType.ROOM_SYSTEM -> { Conversation.ConversationType.ROOM_SYSTEM -> {
binding.avatarImage.loadSystemAvatar() binding.avatarImage.loadSystemAvatar()
} }

View File

@ -11,7 +11,7 @@ import androidx.appcompat.widget.SwitchCompat
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.databinding.ControllerConversationInfoBinding import com.nextcloud.talk.databinding.ActivityConversationInfoBinding
import com.nextcloud.talk.databinding.DialogPasswordBinding import com.nextcloud.talk.databinding.DialogPasswordBinding
import com.nextcloud.talk.models.json.conversations.Conversation import com.nextcloud.talk.models.json.conversations.Conversation
import com.nextcloud.talk.repositories.conversations.ConversationsRepository import com.nextcloud.talk.repositories.conversations.ConversationsRepository
@ -24,7 +24,7 @@ import io.reactivex.schedulers.Schedulers
class GuestAccessHelper( class GuestAccessHelper(
private val activity: ConversationInfoActivity, private val activity: ConversationInfoActivity,
private val binding: ControllerConversationInfoBinding, private val binding: ActivityConversationInfoBinding,
private val conversation: Conversation, private val conversation: Conversation,
private val conversationUser: User private val conversationUser: User
) { ) {

View File

@ -104,6 +104,66 @@
android:contentDescription="@string/avatar" /> android:contentDescription="@string/avatar" />
</RelativeLayout> </RelativeLayout>
<LinearLayout
android:id="@+id/avatar_buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
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>
<com.yarolegovich.mp.MaterialPreferenceCategory <com.yarolegovich.mp.MaterialPreferenceCategory