add details view for reactions (WIP)

TODO: encoding for emoji is wrong to send it to server
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
Marcel Hibbe 2022-04-04 19:37:28 +02:00
parent 0f4f04da8d
commit 4abe8ae41d
No known key found for this signature in database
GPG key ID: C793F8B59F43CE7B
10 changed files with 331 additions and 24 deletions

View file

@ -3,5 +3,5 @@ package com.nextcloud.talk.adapters.messages
import com.nextcloud.talk.models.json.chat.ChatMessage
interface ReactionsInterface {
fun onClickReactions(message: ChatMessage)
fun onClickReactions(chatMessage: ChatMessage)
}

View file

@ -37,6 +37,7 @@ import com.nextcloud.talk.models.json.notifications.NotificationOverall;
import com.nextcloud.talk.models.json.participants.AddParticipantOverall;
import com.nextcloud.talk.models.json.participants.ParticipantsOverall;
import com.nextcloud.talk.models.json.push.PushRegistrationOverall;
import com.nextcloud.talk.models.json.reactions.ReactionsOverall;
import com.nextcloud.talk.models.json.search.ContactsByNumberOverall;
import com.nextcloud.talk.models.json.signaling.SignalingOverall;
import com.nextcloud.talk.models.json.signaling.settings.SignalingSettingsOverall;
@ -62,6 +63,7 @@ import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Headers;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.PUT;
@ -488,4 +490,8 @@ public interface NcApi {
@GET
Observable<StatusesOverall> getUserStatuses(@Header("Authorization") String authorization, @Url String url);
@GET
Observable<ReactionsOverall> getParticipantsForEmojiReaction(@Header("Authorization") String authorization,
@Url String url,
@Query("reaction") String reaction);
}

View file

@ -923,11 +923,13 @@ class ChatController(args: Bundle) :
}
override fun onClickReactions(chatMessage: ChatMessage) {
Log.d(TAG, "onClickReactions" + chatMessage)
activity?.let {
ShowReactionsDialog(
activity!!
activity!!,
currentConversation,
chatMessage,
conversationUser,
ncApi!!
).show()
}
}

View file

@ -0,0 +1,42 @@
/*
*
* Nextcloud Talk application
*
* @author Marcel Hibbe
* 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/>.
*/
package com.nextcloud.talk.models.json.reactions
import android.os.Parcelable
import com.bluelinelabs.logansquare.annotation.JsonField
import com.bluelinelabs.logansquare.annotation.JsonObject
import kotlinx.android.parcel.Parcelize
@Parcelize
@JsonObject
data class ReactionVoter(
@JsonField(name = ["actorType"])
var actorType: String?,
@JsonField(name = ["actorId"])
var actorId: String?,
@JsonField(name = ["actorDisplayName"])
var actorDisplayName: String?,
@JsonField(name = ["timestamp"])
var timestamp: Long = 0
) : Parcelable {
// This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
constructor() : this(null, null, null, 0)
}

View file

@ -0,0 +1,36 @@
/*
* Nextcloud Talk application
*
* @author Marcel Hibbe
* 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/>.
*/
package com.nextcloud.talk.models.json.reactions
import android.os.Parcelable
import com.bluelinelabs.logansquare.annotation.JsonField
import com.bluelinelabs.logansquare.annotation.JsonObject
import com.nextcloud.talk.models.json.generic.GenericOCS
import kotlinx.android.parcel.Parcelize
@Parcelize
@JsonObject
data class ReactionsOCS(
@JsonField(name = ["data"])
var data: List<ReactionVoter>?
) : GenericOCS(), Parcelable {
// This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
constructor() : this(null)
}

View file

@ -0,0 +1,35 @@
/*
* Nextcloud Talk application
*
* @author Marcel Hibbe
* 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/>.
*/
package com.nextcloud.talk.models.json.reactions
import android.os.Parcelable
import com.bluelinelabs.logansquare.annotation.JsonField
import com.bluelinelabs.logansquare.annotation.JsonObject
import kotlinx.android.parcel.Parcelize
@Parcelize
@JsonObject
data class ReactionsOverall(
@JsonField(name = ["ocs"])
var ocs: ReactionsOCS?
) : Parcelable {
// This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
constructor() : this(null)
}

View file

@ -2,20 +2,138 @@ package com.nextcloud.talk.ui.dialog
import android.app.Activity
import android.os.Bundle
import android.util.Log
import android.view.Gravity
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.annotation.NonNull
import autodagger.AutoInjector
import com.google.android.material.bottomsheet.BottomSheetDialog
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
import com.nextcloud.talk.utils.DisplayUtils
import com.vanniktech.emoji.EmojiTextView
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(
val activity: Activity
val activity: Activity,
val currentConversation: Conversation?,
val chatMessage: ChatMessage,
val userEntity: UserEntity?,
val ncApi: NcApi
) : BottomSheetDialog(activity) {
private lateinit var dialogMessageReactionsBinding: DialogMessageReactionsBinding
private lateinit var binding: DialogMessageReactionsBinding
// @Inject
// lateinit var ncApi: NcApi
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
dialogMessageReactionsBinding = DialogMessageReactionsBinding.inflate(layoutInflater)
setContentView(dialogMessageReactionsBinding.root)
binding = DialogMessageReactionsBinding.inflate(layoutInflater)
setContentView(binding.root)
window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
initEmojiReactions()
}
private fun initEmojiReactions() {
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())
emojiView.text = emoji
val params = LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
params.setMargins(0, 0, EMOJI_RIGHT_MARGIN, 0)
params.gravity = Gravity.CENTER
emojiView.layoutParams = params
binding.emojiReactionsWrapper.addView(emojiView)
emojiView.setOnClickListener {
updateParticipantsForEmoji(chatMessage, emoji)
}
}
}
}
private fun updateParticipantsForEmoji(chatMessage: ChatMessage, emoji: String?) {
val credentials = ApiUtils.getCredentials(userEntity?.username, userEntity?.token)
Log.d(TAG, "emoji= " + emoji)
// TODO: fix encoding for emoji. set this in NcApi or here...
// var emojiForServer = StringEscapeUtils.escapeJava(emoji)
// Log.d(TAG, "emojiForServer= " + emojiForServer) // ?reaction=%5Cu2764%5CuFE0F
ncApi.getParticipantsForEmojiReaction(
credentials,
ApiUtils.getUrlForParticipantsForEmojiReaction(
userEntity?.baseUrl,
currentConversation!!.token,
chatMessage.id),
emoji
)
?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.subscribe(object : Observer<ReactionsOverall> {
override fun onSubscribe(d: Disposable) {
Log.d(TAG, "onSubscribe")
}
override fun onNext(@NonNull reactionsOverall: ReactionsOverall) {
Log.d(TAG, "onNext")
val reactionVoters: ArrayList<ReactionVoter> = ArrayList()
if (reactionsOverall.ocs?.data != null){
for (reactionVoter in reactionsOverall.ocs?.data!!) {
reactionVoters.add(reactionVoter)
}
} else {
Log.e(TAG, "no voters for this reaction")
}
}
override fun onError(e: Throwable) {
Log.e(TAG, "failed to retrieve list of reaction voters")
}
override fun onComplete() {
Log.d(TAG, "onComplete")
}
})
// binding.emojiReactionsContactList
}
companion object {
const val TAG = "ShowReactionsDialog"
const val EMOJI_RIGHT_MARGIN: Int = 12
const val EMOJI_SIZE: Float = 30F
}
}

View file

@ -441,4 +441,11 @@ public class ApiUtils {
public static String getUrlForUserStatuses(String baseUrl) {
return baseUrl + ocsApiVersion + "/apps/user_status/api/v1/statuses";
}
public static String getUrlForParticipantsForEmojiReaction(String baseUrl,
String roomToken,
String messageId) {
return baseUrl + ocsApiVersion + spreedApiVersion + "/reaction/" + roomToken + "/" + messageId;
}
}

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Nextcloud Talk application
~
~ @author Andy Scherzinger
~ Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
~ @author Marcel Hibbe
~ 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
@ -19,7 +19,6 @@
-->
<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="wrap_content"
@ -30,25 +29,33 @@
android:paddingBottom="@dimen/standard_half_padding">
<LinearLayout
android:id="@+id/menu_copy_message"
android:layout_width="match_parent"
android:layout_height="@dimen/bottom_sheet_item_height"
android:background="?android:attr/selectableItemBackground"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/test"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/emoji_reactions_contact_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:paddingStart="@dimen/standard_double_padding"
android:paddingEnd="@dimen/zero"
android:text="just a test"
android:textAlignment="viewStart"
android:textColor="@color/high_emphasis_text"
android:textSize="@dimen/bottom_sheet_text_size" />
tools:listitem="@layout/rv_item_emoji_details_contact"
tools:itemCount="4"/>
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center">
<LinearLayout
android:id="@+id/emoji_reactions_wrapper"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:orientation="horizontal"
android:layout_gravity="center">
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>

View file

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Nextcloud Talk application
~
~ @author Mario Danic
~ @author Andy Scherzinger
~ Copyright (C) 2021 Andy Scherzinger
~ Copyright (C) 2017 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 <http://www.gnu.org/licenses/>.
-->
<RelativeLayout 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="wrap_content"
android:layout_marginStart="@dimen/standard_margin"
android:layout_marginTop="@dimen/standard_half_margin"
android:layout_marginEnd="@dimen/standard_margin"
android:layout_marginBottom="@dimen/standard_half_margin"
android:orientation="vertical">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/avatar_drawee_view"
android:layout_width="@dimen/avatar_size"
android:layout_height="@dimen/avatar_size"
android:layout_centerVertical="true"
android:layout_marginEnd="@dimen/standard_margin"
app:roundAsCircle="true" />
<androidx.emoji.widget.EmojiTextView
android:id="@+id/name_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toEndOf="@id/avatar_drawee_view"
android:ellipsize="end"
android:lines="1"
android:textAlignment="viewStart"
android:textAppearance="@style/ListItem"
tools:text="Jane Doe" />
</RelativeLayout>