Skip to content

Commit

Permalink
Merge pull request #1895 from nextcloud/feature/1772/reactions
Browse files Browse the repository at this point in the history
Reactions to chat messages
  • Loading branch information
mahibi authored Apr 9, 2022
2 parents 6c5614f + 3d4f3ee commit d66a6a9
Show file tree
Hide file tree
Showing 65 changed files with 1,855 additions and 296 deletions.
14 changes: 2 additions & 12 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,15 @@ If you set your `user.name` and `user.email` git configs, you can sign your comm
You can also use git [aliases](https://git-scm.com/book/tr/v2/Git-Basics-Git-Aliases) like `git config --global alias.ci 'commit -s'`.
Now you can commit with `git ci` and the commit will be signed.

### Git hooks

We provide git hooks to make development process easier for both the developer and the reviewers.
To install them, just run:

```bash
./gradlew installGitHooks
```

## Contribution process

Contribute your code targeting/based-on the branch ```master```.
Expand Down
8 changes: 8 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,14 @@ dependencies {
gplayImplementation "com.google.firebase:firebase-messaging:23.0.0"
}

task installGitHooks(type: Copy, group: "development") {
description = "Install git hooks"
from("../scripts/hooks") {
include '*'
}
into '../.git/hooks'
}

detekt {
reports {
xml {
Expand Down
28 changes: 28 additions & 0 deletions app/src/main/java/com/nextcloud/talk/adapters/ReactionItem.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Nextcloud Talk application
*
* @author Andy Scherzinger
* Copyright (C) 2022 Andy Scherzinger <[email protected]>
*
* 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

data class ReactionItem(
val reactionVoter: ReactionVoter,
val reaction: String?
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Nextcloud Talk application
*
* @author Andy Scherzinger
* Copyright (C) 2022 Andy Scherzinger <[email protected]>
*
* 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)
}
47 changes: 47 additions & 0 deletions app/src/main/java/com/nextcloud/talk/adapters/ReactionsAdapter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Nextcloud Talk application
*
* @author Andy Scherzinger
* Copyright (C) 2022 Andy Scherzinger <[email protected]>
*
* 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
import com.nextcloud.talk.models.database.UserEntity

class ReactionsAdapter(
private val clickListener: ReactionItemClickListener,
private val userEntity: UserEntity?
) : 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, userEntity?.baseUrl)
}

override fun onBindViewHolder(holder: ReactionsViewHolder, position: Int) {
holder.bind(list[position], clickListener)
}

override fun getItemCount(): Int {
return list.size
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Nextcloud Talk application
*
* @author Andy Scherzinger
* Copyright (C) 2022 Andy Scherzinger <[email protected]>
*
* 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.text.TextUtils
import androidx.recyclerview.widget.RecyclerView
import com.facebook.drawee.backends.pipeline.Fresco
import com.facebook.drawee.interfaces.DraweeController
import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
import com.nextcloud.talk.databinding.ReactionItemBinding
import com.nextcloud.talk.models.json.reactions.ReactionVoter
import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DisplayUtils

class ReactionsViewHolder(
private val binding: ReactionItemBinding,
private val baseUrl: String?
) : 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

if (baseUrl != null && baseUrl.isNotEmpty()) {
loadAvatar(reactionItem)
}
}

private fun loadAvatar(reactionItem: ReactionItem) {
if (reactionItem.reactionVoter.actorType == ReactionVoter.ReactionActorType.GUESTS) {
var displayName = sharedApplication?.resources?.getString(R.string.nc_guest)
if (!TextUtils.isEmpty(reactionItem.reactionVoter.actorDisplayName)) {
displayName = reactionItem.reactionVoter.actorDisplayName!!
}
val draweeController: DraweeController = Fresco.newDraweeControllerBuilder()
.setOldController(binding.avatar.controller)
.setAutoPlayAnimations(true)
.setImageRequest(
DisplayUtils.getImageRequestForUrl(
ApiUtils.getUrlForGuestAvatar(
baseUrl,
displayName,
false
),
null
)
)
.build()
binding.avatar.controller = draweeController
} else if (reactionItem.reactionVoter.actorType == ReactionVoter.ReactionActorType.USERS) {
val draweeController: DraweeController = Fresco.newDraweeControllerBuilder()
.setOldController(binding.avatar.controller)
.setAutoPlayAnimations(true)
.setImageRequest(
DisplayUtils.getImageRequestForUrl(
ApiUtils.getUrlForAvatar(
baseUrl,
reactionItem.reactionVoter.actorId,
false
),
null
)
)
.build()
binding.avatar.controller = draweeController
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess
@Inject
var appPreferences: AppPreferences? = null

lateinit var reactionsInterface: ReactionsInterface

@SuppressLint("SetTextI18n")
override fun onBind(message: ChatMessage) {
super.onBind(message)
Expand All @@ -93,13 +95,21 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess
val textSize = context?.resources!!.getDimension(R.dimen.chat_text_size)
binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize)
binding.messageText.text = message.text
binding.messageText.isEnabled = false

// parent message handling
setParentMessageDataOnMessageItem(message)

// geo-location
setLocationDataOnMessageItem(message)

Reaction().showReactions(message, binding.reactions, context!!, true)
binding.reactions.reactionsEmojiWrapper.setOnClickListener {
reactionsInterface.onClickReactions(message)
}
binding.reactions.reactionsEmojiWrapper.setOnLongClickListener { l: View? ->
reactionsInterface.onLongClickReactions(message)
true
}
}

private fun setAvatarAndAuthorOnMessageItem(message: ChatMessage) {
Expand Down Expand Up @@ -270,6 +280,10 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess
return locationGeoLink.replace("geo:", "geo:0,0?q=")
}

fun assignReactionInterface(reactionsInterface: ReactionsInterface) {
this.reactionsInterface = reactionsInterface
}

companion object {
private const val TAG = "LocInMessageView"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import com.facebook.drawee.view.SimpleDraweeView;
import com.nextcloud.talk.databinding.ItemCustomIncomingPreviewMessageBinding;
import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding;

import androidx.emoji.widget.EmojiTextView;

Expand Down Expand Up @@ -77,4 +78,7 @@ public EmojiTextView getPreviewContactName() {
public ProgressBar getPreviewContactProgressBar() {
return binding.contactProgressBar;
}

@Override
public ReactionsInsideMessageBinding getReactionsBinding(){ return binding.reactions; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message
lateinit var message: ChatMessage

lateinit var voiceMessageInterface: VoiceMessageInterface
lateinit var reactionsInterface: ReactionsInterface

@SuppressLint("SetTextI18n")
override fun onBind(message: ChatMessage) {
Expand Down Expand Up @@ -140,6 +141,15 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message
}
}
})

Reaction().showReactions(message, binding.reactions, context!!, true)
binding.reactions.reactionsEmojiWrapper.setOnClickListener {
reactionsInterface.onClickReactions(message)
}
binding.reactions.reactionsEmojiWrapper.setOnLongClickListener { l: View? ->
reactionsInterface.onLongClickReactions(message)
true
}
}

private fun updateDownloadState(message: ChatMessage) {
Expand Down Expand Up @@ -302,10 +312,14 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message
}
}

fun assignAdapter(voiceMessageInterface: VoiceMessageInterface) {
fun assignVoiceMessageInterface(voiceMessageInterface: VoiceMessageInterface) {
this.voiceMessageInterface = voiceMessageInterface
}

fun assignReactionInterface(reactionsInterface: ReactionsInterface) {
this.reactionsInterface = reactionsInterface
}

companion object {
private const val TAG = "VoiceInMessageView"
private const val SEEKBAR_START: Int = 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message
@Inject
var appPreferences: AppPreferences? = null

lateinit var reactionsInterface: ReactionsInterface

override fun onBind(message: ChatMessage) {
super.onBind(message)
sharedApplication!!.componentApplication.inject(this)
Expand Down Expand Up @@ -119,6 +121,15 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message
}

itemView.setTag(MessageSwipeCallback.REPLYABLE_VIEW_TAG, message.isReplyable)

Reaction().showReactions(message, binding.reactions, context!!, true)
binding.reactions.reactionsEmojiWrapper.setOnClickListener {
reactionsInterface.onClickReactions(message)
}
binding.reactions.reactionsEmojiWrapper.setOnLongClickListener { l: View? ->
reactionsInterface.onLongClickReactions(message)
true
}
}

private fun processAuthor(message: ChatMessage) {
Expand Down Expand Up @@ -260,6 +271,10 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message
return messageStringInternal
}

fun assignReactionInterface(reactionsInterface: ReactionsInterface) {
this.reactionsInterface = reactionsInterface
}

companion object {
const val TEXT_SIZE_MULTIPLIER = 2.5
}
Expand Down
Loading

0 comments on commit d66a6a9

Please sign in to comment.