Render list of reactions in recycler view in bottom sheet

Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
This commit is contained in:
Andy Scherzinger 2022-04-05 00:11:51 +02:00 committed by Marcel Hibbe
parent c19dd5fc71
commit 06f42a4c00
No known key found for this signature in database
GPG Key ID: C793F8B59F43CE7B
7 changed files with 253 additions and 15 deletions

View File

@ -0,0 +1,29 @@
/*
* Nextcloud Talk application
*
* @author Andy Scherzinger
* Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
*
* 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.adapters
import com.nextcloud.talk.models.json.reactions.ReactionVoter
// TODO: replace with proper class with correct data objects
data class ReactionItem(
val reactionVoter: ReactionVoter,
val reaction: String?
)

View File

@ -0,0 +1,25 @@
/*
* Nextcloud Talk application
*
* @author Andy Scherzinger
* Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
*
* 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.adapters
interface ReactionItemClickListener {
fun onClick(reactionItem: ReactionItem)
}

View File

@ -0,0 +1,45 @@
/*
* Nextcloud Talk application
*
* @author Andy Scherzinger
* Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
*
* 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.adapters
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.nextcloud.talk.databinding.ReactionItemBinding
class ReactionsAdapter(
private val clickListener: ReactionItemClickListener
) : RecyclerView.Adapter<ReactionsViewHolder>() {
internal var list: MutableList<ReactionItem> = ArrayList<ReactionItem>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ReactionsViewHolder {
val itemBinding = ReactionItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ReactionsViewHolder(itemBinding)
}
override fun onBindViewHolder(holder: ReactionsViewHolder, position: Int) {
holder.bind(list[position], clickListener)
}
override fun getItemCount(): Int {
return list.size
}
}

View File

@ -0,0 +1,33 @@
/*
* Nextcloud Talk application
*
* @author Andy Scherzinger
* Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
*
* 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.adapters
import androidx.recyclerview.widget.RecyclerView
import com.nextcloud.talk.databinding.ReactionItemBinding
class ReactionsViewHolder(private val binding: ReactionItemBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(reactionItem: ReactionItem, clickListener: ReactionItemClickListener) {
binding.root.setOnClickListener { clickListener.onClick(reactionItem) }
binding.reaction.text = reactionItem.reaction
binding.name.text = reactionItem.reactionVoter.actorDisplayName
}
}

View File

@ -1,3 +1,29 @@
/*
* Nextcloud Talk application
*
* @author Andy Scherzinger
* @author Mario Danic
* @author Marcel Hibbe
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
* Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
* Copyright (C) 2022 Marcel Hibbe (dev@mhibbe.de)
*
* 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/>.
*
* Parts related to account import were either copied from or inspired by the great work done by David Luhmer at:
* https://github.com/nextcloud/ownCloud-Account-Importer
*/
package com.nextcloud.talk.ui.dialog
import android.app.Activity
@ -7,15 +33,18 @@ import android.view.Gravity
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.annotation.NonNull
import androidx.recyclerview.widget.LinearLayoutManager
import autodagger.AutoInjector
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.nextcloud.talk.adapters.ReactionItem
import com.nextcloud.talk.adapters.ReactionItemClickListener
import com.nextcloud.talk.adapters.ReactionsAdapter
import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.databinding.DialogMessageReactionsBinding
import com.nextcloud.talk.models.database.UserEntity
import com.nextcloud.talk.models.json.chat.ChatMessage
import com.nextcloud.talk.models.json.conversations.Conversation
import com.nextcloud.talk.models.json.generic.GenericOverall
import com.nextcloud.talk.models.json.reactions.ReactionVoter
import com.nextcloud.talk.models.json.reactions.ReactionsOverall
import com.nextcloud.talk.utils.ApiUtils
@ -25,10 +54,6 @@ import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import org.apache.commons.lang3.StringEscapeUtils
import java.net.URLDecoder
import java.net.URLEncoder
import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class)
class ShowReactionsDialog(
@ -37,10 +62,12 @@ class ShowReactionsDialog(
val chatMessage: ChatMessage,
val userEntity: UserEntity?,
val ncApi: NcApi
) : BottomSheetDialog(activity) {
) : BottomSheetDialog(activity), ReactionItemClickListener {
private lateinit var binding: DialogMessageReactionsBinding
private var adapter: ReactionsAdapter? = null
// @Inject
// lateinit var ncApi: NcApi
@ -49,12 +76,16 @@ class ShowReactionsDialog(
binding = DialogMessageReactionsBinding.inflate(layoutInflater)
setContentView(binding.root)
window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
adapter = ReactionsAdapter(this)
binding.reactionsList.adapter = adapter
binding.reactionsList.layoutManager = LinearLayoutManager(context)
initEmojiReactions()
}
private fun initEmojiReactions() {
adapter?.list?.clear()
if (chatMessage.reactions != null && chatMessage.reactions.isNotEmpty()) {
for ((emoji, amount) in chatMessage.reactions) {
var emojiView = EmojiTextView(activity)
emojiView.setEmojiSize(DisplayUtils.convertDpToPixel(EMOJI_SIZE, context).toInt())
@ -73,8 +104,12 @@ class ShowReactionsDialog(
emojiView.setOnClickListener {
updateParticipantsForEmoji(chatMessage, emoji)
}
// TODO: Add proper implementation
adapter?.list?.add(ReactionItem(ReactionVoter(null, null, "Marcel", 0), emoji))
}
}
adapter?.notifyDataSetChanged()
}
private fun updateParticipantsForEmoji(chatMessage: ChatMessage, emoji: String?) {
@ -93,7 +128,8 @@ class ShowReactionsDialog(
ApiUtils.getUrlForParticipantsForEmojiReaction(
userEntity?.baseUrl,
currentConversation!!.token,
chatMessage.id),
chatMessage.id
),
emoji
)
?.subscribeOn(Schedulers.io())
@ -106,11 +142,14 @@ class ShowReactionsDialog(
override fun onNext(@NonNull reactionsOverall: ReactionsOverall) {
Log.d(TAG, "onNext")
val reactionVoters: ArrayList<ReactionVoter> = ArrayList()
val reactionVoters: ArrayList<ReactionItem> = ArrayList()
if (reactionsOverall.ocs?.data != null) {
for (reactionVoter in reactionsOverall.ocs?.data!!) {
reactionVoters.add(reactionVoter)
reactionVoters.add(ReactionItem(reactionVoter, emoji))
}
// TODO: Test and check for data notification call need
adapter?.list?.addAll(reactionVoters)
Log.e(TAG, "voters:" + reactionVoters.size)
} else {
Log.e(TAG, "no voters for this reaction")
}
@ -125,12 +164,17 @@ class ShowReactionsDialog(
}
})
// binding.emojiReactionsContactList
}
override fun onClick(reactionItem: ReactionItem) {
Log.d(TAG, "onClick(reactionItem: ReactionItem): " + reactionItem.reaction)
// TODO: implement removal of users reaction,
// ownership needs to be checked, so only owned
// reactions can be removed upon click
dismiss()
}
companion object {
const val TAG = "ShowReactionsDialog"
const val EMOJI_RIGHT_MARGIN: Int = 12

View File

@ -1,7 +1,9 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Nextcloud Talk application
~
~ @author Andy Scherzinger
~ @author Marcel Hibbe
~ Copyright (C) 2022 Andy Scherzinger
~ Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
~
~ This program is free software: you can redistribute it and/or modify
@ -28,12 +30,19 @@
android:paddingEnd="@dimen/standard_padding"
android:paddingBottom="@dimen/standard_half_padding">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/reactions_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:listitem="@layout/reaction_item" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
tools:ignore="UseCompoundDrawables"
android:visibility="gone">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/emoji_reactions_contact_list"

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?><!--
Nextcloud Talk application
Copyright (C) 2022 Andy Scherzinger
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://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:layout_width="match_parent"
android:layout_height="48dp">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/avatar"
android:layout_width="@dimen/avatar_size"
android:layout_height="@dimen/avatar_size"
android:layout_gravity="center_vertical"
android:layout_marginEnd="@dimen/standard_margin"
app:roundAsCircle="true" />
<TextView
android:id="@+id/name"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:ellipsize="middle"
android:gravity="center_vertical"
android:textAppearance="?android:attr/textAppearanceListItem"
tools:text="Participant Name" />
<androidx.emoji.widget.EmojiTextView
android:id="@+id/reaction"
android:layout_width="48dp"
android:layout_height="48dp"
android:gravity="center"
android:textSize="25sp"
tools:text="@string/default_emoji" />
</LinearLayout>