mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-19 19:49:33 +01:00
add data classes for polls (WIP)
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
parent
12efda5064
commit
f2025332ab
@ -0,0 +1,241 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Talk application
|
||||||
|
*
|
||||||
|
* @author Marcel Hibbe
|
||||||
|
* Copyright (C) 2021 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.adapters.messages
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.graphics.drawable.LayerDrawable
|
||||||
|
import android.os.Build
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.view.View
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.content.res.ResourcesCompat
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
|
import autodagger.AutoInjector
|
||||||
|
import coil.load
|
||||||
|
import com.amulyakhare.textdrawable.TextDrawable
|
||||||
|
import com.nextcloud.talk.R
|
||||||
|
import com.nextcloud.talk.api.NcApi
|
||||||
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
|
import com.nextcloud.talk.databinding.ItemCustomIncomingPollMessageBinding
|
||||||
|
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||||
|
import com.nextcloud.talk.ui.bottom.sheet.ProfileBottomSheet
|
||||||
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
|
import com.nextcloud.talk.utils.DisplayUtils
|
||||||
|
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||||
|
import com.stfalcon.chatkit.messages.MessageHolders
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@AutoInjector(NextcloudTalkApplication::class)
|
||||||
|
class IncomingPollMessageViewHolder(incomingView: View, payload: Any) : MessageHolders
|
||||||
|
.IncomingTextMessageViewHolder<ChatMessage>(incomingView, payload) {
|
||||||
|
|
||||||
|
private val binding: ItemCustomIncomingPollMessageBinding =
|
||||||
|
ItemCustomIncomingPollMessageBinding.bind(itemView)
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Inject
|
||||||
|
var context: Context? = null
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Inject
|
||||||
|
var appPreferences: AppPreferences? = null
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@JvmField
|
||||||
|
var ncApi: NcApi? = null
|
||||||
|
|
||||||
|
lateinit var message: ChatMessage
|
||||||
|
|
||||||
|
lateinit var reactionsInterface: ReactionsInterface
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
override fun onBind(message: ChatMessage) {
|
||||||
|
super.onBind(message)
|
||||||
|
this.message = message
|
||||||
|
sharedApplication!!.componentApplication.inject(this)
|
||||||
|
|
||||||
|
setAvatarAndAuthorOnMessageItem(message)
|
||||||
|
|
||||||
|
colorizeMessageBubble(message)
|
||||||
|
|
||||||
|
itemView.isSelected = false
|
||||||
|
binding.messageTime.setTextColor(ResourcesCompat.getColor(context?.resources!!, R.color.warm_grey_four, null))
|
||||||
|
|
||||||
|
// parent message handling
|
||||||
|
setParentMessageDataOnMessageItem(message)
|
||||||
|
|
||||||
|
setPollPreview(message)
|
||||||
|
|
||||||
|
Reaction().showReactions(message, binding.reactions, binding.messageTime.context, false)
|
||||||
|
binding.reactions.reactionsEmojiWrapper.setOnClickListener {
|
||||||
|
reactionsInterface.onClickReactions(message)
|
||||||
|
}
|
||||||
|
binding.reactions.reactionsEmojiWrapper.setOnLongClickListener { l: View? ->
|
||||||
|
reactionsInterface.onLongClickReactions(message)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setPollPreview(message: ChatMessage) {
|
||||||
|
var pollId: String?
|
||||||
|
var pollName: String? = ""
|
||||||
|
|
||||||
|
if (message.messageParameters != null && message.messageParameters!!.size > 0) {
|
||||||
|
for (key in message.messageParameters!!.keys) {
|
||||||
|
val individualHashMap: Map<String?, String?> = message.messageParameters!![key]!!
|
||||||
|
if (individualHashMap["type"] == "talk-poll") {
|
||||||
|
pollId = individualHashMap["id"]
|
||||||
|
pollName = individualHashMap["name"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.messagePollTitle.text = pollName
|
||||||
|
|
||||||
|
// TODO: how to get room token here?
|
||||||
|
// val credentials = ApiUtils.getCredentials(message.activeUser?.username, message.activeUser?.token)
|
||||||
|
// ncApi!!.getPoll(
|
||||||
|
// credentials,
|
||||||
|
// ApiUtils.getUrlForPoll(
|
||||||
|
// message.activeUser?.baseUrl,
|
||||||
|
// ???????
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setAvatarAndAuthorOnMessageItem(message: ChatMessage) {
|
||||||
|
val author: String = message.actorDisplayName!!
|
||||||
|
if (!TextUtils.isEmpty(author)) {
|
||||||
|
binding.messageAuthor.text = author
|
||||||
|
binding.messageUserAvatar.setOnClickListener {
|
||||||
|
(payload as? ProfileBottomSheet)?.showFor(message.actorId!!, itemView.context)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
binding.messageAuthor.setText(R.string.nc_nick_guest)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!message.isGrouped && !message.isOneToOneConversation) {
|
||||||
|
setAvatarOnMessage(message)
|
||||||
|
} else {
|
||||||
|
if (message.isOneToOneConversation) {
|
||||||
|
binding.messageUserAvatar.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
binding.messageUserAvatar.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
binding.messageAuthor.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setAvatarOnMessage(message: ChatMessage) {
|
||||||
|
binding.messageUserAvatar.visibility = View.VISIBLE
|
||||||
|
if (message.actorType == "guests") {
|
||||||
|
// do nothing, avatar is set
|
||||||
|
} else if (message.actorType == "bots" && message.actorId == "changelog") {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
val layers = arrayOfNulls<Drawable>(2)
|
||||||
|
layers[0] = ContextCompat.getDrawable(context!!, R.drawable.ic_launcher_background)
|
||||||
|
layers[1] = ContextCompat.getDrawable(context!!, R.drawable.ic_launcher_foreground)
|
||||||
|
val layerDrawable = LayerDrawable(layers)
|
||||||
|
binding.messageUserAvatar.setImageDrawable(DisplayUtils.getRoundedDrawable(layerDrawable))
|
||||||
|
} else {
|
||||||
|
binding.messageUserAvatar.setImageResource(R.mipmap.ic_launcher)
|
||||||
|
}
|
||||||
|
} else if (message.actorType == "bots") {
|
||||||
|
val drawable = TextDrawable.builder()
|
||||||
|
.beginConfig()
|
||||||
|
.bold()
|
||||||
|
.endConfig()
|
||||||
|
.buildRound(
|
||||||
|
">",
|
||||||
|
ResourcesCompat.getColor(context!!.resources, R.color.black, null)
|
||||||
|
)
|
||||||
|
binding.messageUserAvatar.visibility = View.VISIBLE
|
||||||
|
binding.messageUserAvatar.setImageDrawable(drawable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun colorizeMessageBubble(message: ChatMessage) {
|
||||||
|
val resources = itemView.resources
|
||||||
|
|
||||||
|
var bubbleResource = R.drawable.shape_incoming_message
|
||||||
|
|
||||||
|
if (message.isGrouped) {
|
||||||
|
bubbleResource = R.drawable.shape_grouped_incoming_message
|
||||||
|
}
|
||||||
|
|
||||||
|
val bgBubbleColor = if (message.isDeleted) {
|
||||||
|
ResourcesCompat.getColor(resources, R.color.bg_message_list_incoming_bubble_deleted, null)
|
||||||
|
} else {
|
||||||
|
ResourcesCompat.getColor(resources, R.color.bg_message_list_incoming_bubble, null)
|
||||||
|
}
|
||||||
|
val bubbleDrawable = DisplayUtils.getMessageSelector(
|
||||||
|
bgBubbleColor,
|
||||||
|
ResourcesCompat.getColor(resources, R.color.transparent, null),
|
||||||
|
bgBubbleColor, bubbleResource
|
||||||
|
)
|
||||||
|
ViewCompat.setBackground(bubble, bubbleDrawable)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setParentMessageDataOnMessageItem(message: ChatMessage) {
|
||||||
|
if (!message.isDeleted && message.parentMessage != null) {
|
||||||
|
val parentChatMessage = message.parentMessage
|
||||||
|
parentChatMessage!!.activeUser = message.activeUser
|
||||||
|
parentChatMessage!!.imageUrl?.let {
|
||||||
|
binding.messageQuote.quotedMessageImage.visibility = View.VISIBLE
|
||||||
|
binding.messageQuote.quotedMessageImage.load(it) {
|
||||||
|
addHeader(
|
||||||
|
"Authorization",
|
||||||
|
ApiUtils.getCredentials(message.activeUser!!.username, message.activeUser!!.token)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} ?: run {
|
||||||
|
binding.messageQuote.quotedMessageImage.visibility = View.GONE
|
||||||
|
}
|
||||||
|
binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName
|
||||||
|
?: context!!.getText(R.string.nc_nick_guest)
|
||||||
|
binding.messageQuote.quotedMessage.text = parentChatMessage.text
|
||||||
|
|
||||||
|
binding.messageQuote.quotedMessageAuthor
|
||||||
|
.setTextColor(ContextCompat.getColor(context!!, R.color.textColorMaxContrast))
|
||||||
|
|
||||||
|
if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) {
|
||||||
|
binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.colorPrimary)
|
||||||
|
} else {
|
||||||
|
binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
binding.messageQuote.quotedChatMessageView.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun assignReactionInterface(reactionsInterface: ReactionsInterface) {
|
||||||
|
this.reactionsInterface = reactionsInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val TAG = NextcloudTalkApplication::class.java.simpleName
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Talk application
|
||||||
|
*
|
||||||
|
* @author Marcel Hibbe
|
||||||
|
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||||
|
* Copyright (C) 2021 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.adapters.messages
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.PorterDuff
|
||||||
|
import android.os.Handler
|
||||||
|
import android.view.View
|
||||||
|
import androidx.appcompat.content.res.AppCompatResources
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
|
import autodagger.AutoInjector
|
||||||
|
import coil.load
|
||||||
|
import com.nextcloud.talk.R
|
||||||
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
|
import com.nextcloud.talk.databinding.ItemCustomOutcomingPollMessageBinding
|
||||||
|
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||||
|
import com.nextcloud.talk.models.json.chat.ReadStatus
|
||||||
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
|
import com.nextcloud.talk.utils.DisplayUtils
|
||||||
|
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||||
|
import com.stfalcon.chatkit.messages.MessageHolders
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@AutoInjector(NextcloudTalkApplication::class)
|
||||||
|
class OutcomingPollMessageViewHolder(outcomingView: View) : MessageHolders
|
||||||
|
.OutcomingTextMessageViewHolder<ChatMessage>(outcomingView) {
|
||||||
|
|
||||||
|
private val binding: ItemCustomOutcomingPollMessageBinding =
|
||||||
|
ItemCustomOutcomingPollMessageBinding.bind(itemView)
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Inject
|
||||||
|
var context: Context? = null
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Inject
|
||||||
|
var appPreferences: AppPreferences? = null
|
||||||
|
|
||||||
|
lateinit var message: ChatMessage
|
||||||
|
|
||||||
|
lateinit var handler: Handler
|
||||||
|
|
||||||
|
lateinit var reactionsInterface: ReactionsInterface
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
override fun onBind(message: ChatMessage) {
|
||||||
|
super.onBind(message)
|
||||||
|
this.message = message
|
||||||
|
sharedApplication!!.componentApplication.inject(this)
|
||||||
|
|
||||||
|
colorizeMessageBubble(message)
|
||||||
|
|
||||||
|
itemView.isSelected = false
|
||||||
|
binding.messageTime.setTextColor(context!!.resources.getColor(R.color.white60))
|
||||||
|
|
||||||
|
// parent message handling
|
||||||
|
setParentMessageDataOnMessageItem(message)
|
||||||
|
|
||||||
|
val readStatusDrawableInt = when (message.readStatus) {
|
||||||
|
ReadStatus.READ -> R.drawable.ic_check_all
|
||||||
|
ReadStatus.SENT -> R.drawable.ic_check
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
val readStatusContentDescriptionString = when (message.readStatus) {
|
||||||
|
ReadStatus.READ -> context?.resources?.getString(R.string.nc_message_read)
|
||||||
|
ReadStatus.SENT -> context?.resources?.getString(R.string.nc_message_sent)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
readStatusDrawableInt?.let { drawableInt ->
|
||||||
|
AppCompatResources.getDrawable(context!!, drawableInt)?.let {
|
||||||
|
it.setColorFilter(context?.resources!!.getColor(R.color.white60), PorterDuff.Mode.SRC_ATOP)
|
||||||
|
binding.checkMark.setImageDrawable(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.checkMark.setContentDescription(readStatusContentDescriptionString)
|
||||||
|
|
||||||
|
Reaction().showReactions(message, binding.reactions, binding.messageTime.context, true)
|
||||||
|
binding.reactions.reactionsEmojiWrapper.setOnClickListener {
|
||||||
|
reactionsInterface.onClickReactions(message)
|
||||||
|
}
|
||||||
|
binding.reactions.reactionsEmojiWrapper.setOnLongClickListener { l: View? ->
|
||||||
|
reactionsInterface.onLongClickReactions(message)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setParentMessageDataOnMessageItem(message: ChatMessage) {
|
||||||
|
if (!message.isDeleted && message.parentMessage != null) {
|
||||||
|
val parentChatMessage = message.parentMessage
|
||||||
|
parentChatMessage!!.activeUser = message.activeUser
|
||||||
|
parentChatMessage.imageUrl?.let {
|
||||||
|
binding.messageQuote.quotedMessageImage.visibility = View.VISIBLE
|
||||||
|
binding.messageQuote.quotedMessageImage.load(it) {
|
||||||
|
addHeader(
|
||||||
|
"Authorization",
|
||||||
|
ApiUtils.getCredentials(message.activeUser!!.username, message.activeUser!!.token)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} ?: run {
|
||||||
|
binding.messageQuote.quotedMessageImage.visibility = View.GONE
|
||||||
|
}
|
||||||
|
binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName
|
||||||
|
?: context!!.getText(R.string.nc_nick_guest)
|
||||||
|
binding.messageQuote.quotedMessage.text = parentChatMessage.text
|
||||||
|
binding.messageQuote.quotedMessage.setTextColor(
|
||||||
|
context!!.resources.getColor(R.color.nc_outcoming_text_default)
|
||||||
|
)
|
||||||
|
binding.messageQuote.quotedMessageAuthor.setTextColor(context!!.resources.getColor(R.color.nc_grey))
|
||||||
|
|
||||||
|
binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.white)
|
||||||
|
|
||||||
|
binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
binding.messageQuote.quotedChatMessageView.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun colorizeMessageBubble(message: ChatMessage) {
|
||||||
|
val resources = sharedApplication!!.resources
|
||||||
|
val bgBubbleColor = if (message.isDeleted) {
|
||||||
|
resources.getColor(R.color.bg_message_list_outcoming_bubble_deleted)
|
||||||
|
} else {
|
||||||
|
resources.getColor(R.color.bg_message_list_outcoming_bubble)
|
||||||
|
}
|
||||||
|
if (message.isGrouped) {
|
||||||
|
val bubbleDrawable = DisplayUtils.getMessageSelector(
|
||||||
|
bgBubbleColor,
|
||||||
|
resources.getColor(R.color.transparent),
|
||||||
|
bgBubbleColor,
|
||||||
|
R.drawable.shape_grouped_outcoming_message
|
||||||
|
)
|
||||||
|
ViewCompat.setBackground(bubble, bubbleDrawable)
|
||||||
|
} else {
|
||||||
|
val bubbleDrawable = DisplayUtils.getMessageSelector(
|
||||||
|
bgBubbleColor,
|
||||||
|
resources.getColor(R.color.transparent),
|
||||||
|
bgBubbleColor,
|
||||||
|
R.drawable.shape_outcoming_message
|
||||||
|
)
|
||||||
|
ViewCompat.setBackground(bubble, bubbleDrawable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun assignReactionInterface(reactionsInterface: ReactionsInterface) {
|
||||||
|
this.reactionsInterface = reactionsInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val TAG = NextcloudTalkApplication::class.java.simpleName
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Nextcloud Talk application
|
* Nextcloud Talk application
|
||||||
*
|
*
|
||||||
* @author Mario Danic
|
* @author Mario Danic
|
||||||
* @author Marcel Hibbe
|
* @author Marcel Hibbe
|
||||||
@ -47,6 +47,7 @@ import com.nextcloud.talk.models.json.statuses.StatusesOverall;
|
|||||||
import com.nextcloud.talk.models.json.unifiedsearch.UnifiedSearchOverall;
|
import com.nextcloud.talk.models.json.unifiedsearch.UnifiedSearchOverall;
|
||||||
import com.nextcloud.talk.models.json.userprofile.UserProfileFieldsOverall;
|
import com.nextcloud.talk.models.json.userprofile.UserProfileFieldsOverall;
|
||||||
import com.nextcloud.talk.models.json.userprofile.UserProfileOverall;
|
import com.nextcloud.talk.models.json.userprofile.UserProfileOverall;
|
||||||
|
import com.nextcloud.talk.polls.repositories.model.PollOverall;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -526,4 +527,20 @@ public interface NcApi {
|
|||||||
@Query("from") String fromUrl,
|
@Query("from") String fromUrl,
|
||||||
@Query("limit") Integer limit,
|
@Query("limit") Integer limit,
|
||||||
@Query("cursor") Integer cursor);
|
@Query("cursor") Integer cursor);
|
||||||
|
|
||||||
|
@GET
|
||||||
|
Observable<PollOverall> getPoll(@Header("Authorization") String authorization,
|
||||||
|
@Url String url);
|
||||||
|
|
||||||
|
@POST
|
||||||
|
Observable<PollOverall> createPoll(@Header("Authorization") String authorization,
|
||||||
|
@Url String url);
|
||||||
|
|
||||||
|
@POST
|
||||||
|
Observable<PollOverall> votePoll(@Header("Authorization") String authorization,
|
||||||
|
@Url String url);
|
||||||
|
|
||||||
|
@DELETE
|
||||||
|
Observable<PollOverall> closePoll(@Header("Authorization") String authorization,
|
||||||
|
@Url String url);
|
||||||
}
|
}
|
||||||
|
@ -104,6 +104,7 @@ import com.nextcloud.talk.activities.CallActivity
|
|||||||
import com.nextcloud.talk.activities.MainActivity
|
import com.nextcloud.talk.activities.MainActivity
|
||||||
import com.nextcloud.talk.activities.TakePhotoActivity
|
import com.nextcloud.talk.activities.TakePhotoActivity
|
||||||
import com.nextcloud.talk.adapters.messages.IncomingLocationMessageViewHolder
|
import com.nextcloud.talk.adapters.messages.IncomingLocationMessageViewHolder
|
||||||
|
import com.nextcloud.talk.adapters.messages.IncomingPollMessageViewHolder
|
||||||
import com.nextcloud.talk.adapters.messages.IncomingPreviewMessageViewHolder
|
import com.nextcloud.talk.adapters.messages.IncomingPreviewMessageViewHolder
|
||||||
import com.nextcloud.talk.adapters.messages.IncomingVoiceMessageViewHolder
|
import com.nextcloud.talk.adapters.messages.IncomingVoiceMessageViewHolder
|
||||||
import com.nextcloud.talk.adapters.messages.MagicIncomingTextMessageViewHolder
|
import com.nextcloud.talk.adapters.messages.MagicIncomingTextMessageViewHolder
|
||||||
@ -111,6 +112,7 @@ import com.nextcloud.talk.adapters.messages.MagicOutcomingTextMessageViewHolder
|
|||||||
import com.nextcloud.talk.adapters.messages.MagicSystemMessageViewHolder
|
import com.nextcloud.talk.adapters.messages.MagicSystemMessageViewHolder
|
||||||
import com.nextcloud.talk.adapters.messages.MagicUnreadNoticeMessageViewHolder
|
import com.nextcloud.talk.adapters.messages.MagicUnreadNoticeMessageViewHolder
|
||||||
import com.nextcloud.talk.adapters.messages.OutcomingLocationMessageViewHolder
|
import com.nextcloud.talk.adapters.messages.OutcomingLocationMessageViewHolder
|
||||||
|
import com.nextcloud.talk.adapters.messages.OutcomingPollMessageViewHolder
|
||||||
import com.nextcloud.talk.adapters.messages.OutcomingPreviewMessageViewHolder
|
import com.nextcloud.talk.adapters.messages.OutcomingPreviewMessageViewHolder
|
||||||
import com.nextcloud.talk.adapters.messages.OutcomingVoiceMessageViewHolder
|
import com.nextcloud.talk.adapters.messages.OutcomingVoiceMessageViewHolder
|
||||||
import com.nextcloud.talk.adapters.messages.PreviewMessageInterface
|
import com.nextcloud.talk.adapters.messages.PreviewMessageInterface
|
||||||
@ -544,6 +546,17 @@ class ChatController(args: Bundle) :
|
|||||||
this
|
this
|
||||||
)
|
)
|
||||||
|
|
||||||
|
messageHolders.registerContentType(
|
||||||
|
CONTENT_TYPE_POLL,
|
||||||
|
IncomingPollMessageViewHolder::class.java,
|
||||||
|
profileBottomSheet,
|
||||||
|
R.layout.item_custom_incoming_poll_message,
|
||||||
|
OutcomingPollMessageViewHolder::class.java,
|
||||||
|
null,
|
||||||
|
R.layout.item_custom_outcoming_poll_message,
|
||||||
|
this
|
||||||
|
)
|
||||||
|
|
||||||
var senderId = ""
|
var senderId = ""
|
||||||
if (!conversationUser?.userId.equals("?")) {
|
if (!conversationUser?.userId.equals("?")) {
|
||||||
senderId = "users/" + conversationUser?.userId
|
senderId = "users/" + conversationUser?.userId
|
||||||
@ -3012,6 +3025,7 @@ class ChatController(args: Bundle) :
|
|||||||
return when (type) {
|
return when (type) {
|
||||||
CONTENT_TYPE_LOCATION -> message.hasGeoLocation()
|
CONTENT_TYPE_LOCATION -> message.hasGeoLocation()
|
||||||
CONTENT_TYPE_VOICE_MESSAGE -> message.isVoiceMessage
|
CONTENT_TYPE_VOICE_MESSAGE -> message.isVoiceMessage
|
||||||
|
CONTENT_TYPE_POLL -> message.isPoll()
|
||||||
CONTENT_TYPE_SYSTEM_MESSAGE -> !TextUtils.isEmpty(message.systemMessage)
|
CONTENT_TYPE_SYSTEM_MESSAGE -> !TextUtils.isEmpty(message.systemMessage)
|
||||||
CONTENT_TYPE_UNREAD_NOTICE_MESSAGE -> message.id == "-1"
|
CONTENT_TYPE_UNREAD_NOTICE_MESSAGE -> message.id == "-1"
|
||||||
else -> false
|
else -> false
|
||||||
@ -3127,6 +3141,7 @@ class ChatController(args: Bundle) :
|
|||||||
private const val CONTENT_TYPE_UNREAD_NOTICE_MESSAGE: Byte = 2
|
private const val CONTENT_TYPE_UNREAD_NOTICE_MESSAGE: Byte = 2
|
||||||
private const val CONTENT_TYPE_LOCATION: Byte = 3
|
private const val CONTENT_TYPE_LOCATION: Byte = 3
|
||||||
private const val CONTENT_TYPE_VOICE_MESSAGE: Byte = 4
|
private const val CONTENT_TYPE_VOICE_MESSAGE: Byte = 4
|
||||||
|
private const val CONTENT_TYPE_POLL: Byte = 5
|
||||||
private const val NEW_MESSAGES_POPUP_BUBBLE_DELAY: Long = 200
|
private const val NEW_MESSAGES_POPUP_BUBBLE_DELAY: Long = 200
|
||||||
private const val POP_CURRENT_CONTROLLER_DELAY: Long = 100
|
private const val POP_CURRENT_CONTROLLER_DELAY: Long = 100
|
||||||
private const val LOBBY_TIMER_DELAY: Long = 5000
|
private const val LOBBY_TIMER_DELAY: Long = 5000
|
||||||
|
@ -124,6 +124,8 @@ data class ChatMessage(
|
|||||||
|
|
||||||
var voiceMessageDownloadProgress: Int = 0,
|
var voiceMessageDownloadProgress: Int = 0,
|
||||||
) : Parcelable, MessageContentType, MessageContentType.Image {
|
) : Parcelable, MessageContentType, MessageContentType.Image {
|
||||||
|
|
||||||
|
// TODO: messageTypesToIgnore is weird. must be deleted by refactoring!
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
var messageTypesToIgnore = Arrays.asList(
|
var messageTypesToIgnore = Arrays.asList(
|
||||||
MessageType.REGULAR_TEXT_MESSAGE,
|
MessageType.REGULAR_TEXT_MESSAGE,
|
||||||
@ -132,7 +134,8 @@ data class ChatMessage(
|
|||||||
MessageType.SINGLE_LINK_AUDIO_MESSAGE,
|
MessageType.SINGLE_LINK_AUDIO_MESSAGE,
|
||||||
MessageType.SINGLE_LINK_MESSAGE,
|
MessageType.SINGLE_LINK_MESSAGE,
|
||||||
MessageType.SINGLE_NC_GEOLOCATION_MESSAGE,
|
MessageType.SINGLE_NC_GEOLOCATION_MESSAGE,
|
||||||
MessageType.VOICE_MESSAGE
|
MessageType.VOICE_MESSAGE,
|
||||||
|
MessageType.POLL_MESSAGE
|
||||||
)
|
)
|
||||||
|
|
||||||
fun hasFileAttachment(): Boolean {
|
fun hasFileAttachment(): Boolean {
|
||||||
@ -165,6 +168,21 @@ data class ChatMessage(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isPoll(): Boolean {
|
||||||
|
if (messageParameters != null && messageParameters!!.size > 0) {
|
||||||
|
for ((_, individualHashMap) in messageParameters!!) {
|
||||||
|
if (MessageDigest.isEqual(
|
||||||
|
individualHashMap["type"]!!.toByteArray(),
|
||||||
|
"talk-poll".toByteArray()
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
override fun getImageUrl(): String? {
|
override fun getImageUrl(): String? {
|
||||||
if (messageParameters != null && messageParameters!!.size > 0) {
|
if (messageParameters != null && messageParameters!!.size > 0) {
|
||||||
for ((_, individualHashMap) in messageParameters!!) {
|
for ((_, individualHashMap) in messageParameters!!) {
|
||||||
@ -207,6 +225,8 @@ data class ChatMessage(
|
|||||||
MessageType.SINGLE_NC_ATTACHMENT_MESSAGE
|
MessageType.SINGLE_NC_ATTACHMENT_MESSAGE
|
||||||
} else if (hasGeoLocation()) {
|
} else if (hasGeoLocation()) {
|
||||||
MessageType.SINGLE_NC_GEOLOCATION_MESSAGE
|
MessageType.SINGLE_NC_GEOLOCATION_MESSAGE
|
||||||
|
} else if (isPoll()) {
|
||||||
|
MessageType.POLL_MESSAGE
|
||||||
} else {
|
} else {
|
||||||
MessageType.REGULAR_TEXT_MESSAGE
|
MessageType.REGULAR_TEXT_MESSAGE
|
||||||
}
|
}
|
||||||
@ -334,6 +354,15 @@ data class ChatMessage(
|
|||||||
getNullsafeActorDisplayName()
|
getNullsafeActorDisplayName()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
} else if (MessageType.POLL_MESSAGE == getCalculateMessageType()) {
|
||||||
|
return if (actorId == activeUser!!.userId) {
|
||||||
|
sharedApplication!!.getString(R.string.nc_sent_poll_you)
|
||||||
|
} else {
|
||||||
|
String.format(
|
||||||
|
sharedApplication!!.resources.getString(R.string.nc_sent_an_image),
|
||||||
|
getNullsafeActorDisplayName()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
@ -410,6 +439,7 @@ data class ChatMessage(
|
|||||||
SINGLE_LINK_AUDIO_MESSAGE,
|
SINGLE_LINK_AUDIO_MESSAGE,
|
||||||
SINGLE_NC_ATTACHMENT_MESSAGE,
|
SINGLE_NC_ATTACHMENT_MESSAGE,
|
||||||
SINGLE_NC_GEOLOCATION_MESSAGE,
|
SINGLE_NC_GEOLOCATION_MESSAGE,
|
||||||
|
POLL_MESSAGE,
|
||||||
VOICE_MESSAGE
|
VOICE_MESSAGE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* 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.polls.repositories.model
|
||||||
|
|
||||||
|
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 Poll(
|
||||||
|
@JsonField(name = ["id"])
|
||||||
|
var id: Int = 0,
|
||||||
|
|
||||||
|
@JsonField(name = ["question"])
|
||||||
|
var question: String? = null,
|
||||||
|
|
||||||
|
@JsonField(name = ["options"])
|
||||||
|
var options: ArrayList<String>? = null,
|
||||||
|
|
||||||
|
@JsonField(name = ["votes"])
|
||||||
|
var votes: ArrayList<Int>? = null,
|
||||||
|
|
||||||
|
@JsonField(name = ["actorType"])
|
||||||
|
var actorType: String? = null,
|
||||||
|
|
||||||
|
@JsonField(name = ["actorId"])
|
||||||
|
var actorId: String? = null,
|
||||||
|
|
||||||
|
@JsonField(name = ["actorDisplayName"])
|
||||||
|
var actorDisplayName: String? = null,
|
||||||
|
|
||||||
|
@JsonField(name = ["status"])
|
||||||
|
var status: Int = 0,
|
||||||
|
|
||||||
|
@JsonField(name = ["resultMode"])
|
||||||
|
var resultMode: Int = 0,
|
||||||
|
|
||||||
|
@JsonField(name = ["maxVotes"])
|
||||||
|
var maxVotes: Int = 0,
|
||||||
|
|
||||||
|
@JsonField(name = ["votedSelf"])
|
||||||
|
var votedSelf: ArrayList<Int>? = null,
|
||||||
|
) : Parcelable {
|
||||||
|
// This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
|
||||||
|
constructor() : this(0, null, null, null, null, null, null, 0, 0, 0, null)
|
||||||
|
}
|
@ -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.polls.repositories.model
|
||||||
|
|
||||||
|
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 PollOCS(
|
||||||
|
@JsonField(name = ["data"])
|
||||||
|
var data: Poll?
|
||||||
|
) : Parcelable {
|
||||||
|
// This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
|
||||||
|
constructor() : this(null)
|
||||||
|
}
|
@ -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.polls.repositories.model
|
||||||
|
|
||||||
|
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 PollOverall(
|
||||||
|
@JsonField(name = ["ocs"])
|
||||||
|
var ocs: PollOCS? = null
|
||||||
|
) : Parcelable {
|
||||||
|
// This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
|
||||||
|
constructor() : this(null)
|
||||||
|
}
|
@ -2,8 +2,10 @@
|
|||||||
* Nextcloud Talk application
|
* Nextcloud Talk application
|
||||||
*
|
*
|
||||||
* @author Mario Danic
|
* @author Mario Danic
|
||||||
|
* @author Marcel Hibbe
|
||||||
* @author Tim Krüger
|
* @author Tim Krüger
|
||||||
* Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
|
* Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
|
||||||
|
* Copyright (C) 2021-2022 Marcel Hibbe <dev@mhibbe.de>
|
||||||
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@ -61,8 +63,8 @@ public class ApiUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated This is only supported on API v1-3, in API v4+ please use
|
* @deprecated This is only supported on API v1-3, in API v4+ please use {@link ApiUtils#getUrlForAttendees(int,
|
||||||
* {@link ApiUtils#getUrlForAttendees(int, String, String)} instead.
|
* String, String)} instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static String getUrlForRemovingParticipantFromConversation(String baseUrl, String roomToken, boolean isGuest) {
|
public static String getUrlForRemovingParticipantFromConversation(String baseUrl, String roomToken, boolean isGuest) {
|
||||||
@ -95,13 +97,13 @@ public class ApiUtils {
|
|||||||
|
|
||||||
public static String getUrlForFilePreviewWithRemotePath(String baseUrl, String remotePath, int px) {
|
public static String getUrlForFilePreviewWithRemotePath(String baseUrl, String remotePath, int px) {
|
||||||
return baseUrl + "/index.php/core/preview.png?file="
|
return baseUrl + "/index.php/core/preview.png?file="
|
||||||
+ Uri.encode(remotePath, "UTF-8")
|
+ Uri.encode(remotePath, "UTF-8")
|
||||||
+ "&x=" + px + "&y=" + px + "&a=1&mode=cover&forceIcon=1";
|
+ "&x=" + px + "&y=" + px + "&a=1&mode=cover&forceIcon=1";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getUrlForFilePreviewWithFileId(String baseUrl, String fileId, int px) {
|
public static String getUrlForFilePreviewWithFileId(String baseUrl, String fileId, int px) {
|
||||||
return baseUrl + "/index.php/core/preview?fileId="
|
return baseUrl + "/index.php/core/preview?fileId="
|
||||||
+ fileId + "&x=" + px + "&y=" + px + "&a=1&mode=cover&forceIcon=1";
|
+ fileId + "&x=" + px + "&y=" + px + "&a=1&mode=cover&forceIcon=1";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getSharingUrl(String baseUrl) {
|
public static String getSharingUrl(String baseUrl) {
|
||||||
@ -151,8 +153,8 @@ public class ApiUtils {
|
|||||||
if (user.hasSpreedFeatureCapability("conversation-v2")) {
|
if (user.hasSpreedFeatureCapability("conversation-v2")) {
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
if (version == APIv1 &&
|
if (version == APIv1 &&
|
||||||
user.hasSpreedFeatureCapability("mention-flag") &&
|
user.hasSpreedFeatureCapability( "mention-flag") &&
|
||||||
!user.hasSpreedFeatureCapability("conversation-v4")) {
|
!user.hasSpreedFeatureCapability("conversation-v4")) {
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
@ -238,7 +240,7 @@ public class ApiUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getUrlForParticipants(int version, String baseUrl, String token) {
|
public static String getUrlForParticipants(int version, String baseUrl, String token) {
|
||||||
if (token == null || token.isEmpty()){
|
if (token == null || token.isEmpty()) {
|
||||||
Log.e(TAG, "token was null or empty");
|
Log.e(TAG, "token was null or empty");
|
||||||
}
|
}
|
||||||
return getUrlForRoom(version, baseUrl, token) + "/participants";
|
return getUrlForRoom(version, baseUrl, token) + "/participants";
|
||||||
@ -287,6 +289,7 @@ public class ApiUtils {
|
|||||||
public static String getUrlForCall(int version, String baseUrl, String token) {
|
public static String getUrlForCall(int version, String baseUrl, String token) {
|
||||||
return getUrlForApi(version, baseUrl) + "/call/" + token;
|
return getUrlForApi(version, baseUrl) + "/call/" + token;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getUrlForChat(int version, String baseUrl, String token) {
|
public static String getUrlForChat(int version, String baseUrl, String token) {
|
||||||
return getUrlForApi(version, baseUrl) + "/chat/" + token;
|
return getUrlForApi(version, baseUrl) + "/chat/" + token;
|
||||||
}
|
}
|
||||||
@ -294,10 +297,11 @@ public class ApiUtils {
|
|||||||
public static String getUrlForMentionSuggestions(int version, String baseUrl, String token) {
|
public static String getUrlForMentionSuggestions(int version, String baseUrl, String token) {
|
||||||
return getUrlForChat(version, baseUrl, token) + "/mentions";
|
return getUrlForChat(version, baseUrl, token) + "/mentions";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getUrlForChatMessage(int version, String baseUrl, String token, String messageId) {
|
public static String getUrlForChatMessage(int version, String baseUrl, String token, String messageId) {
|
||||||
return getUrlForChat(version, baseUrl, token) + "/" + messageId;
|
return getUrlForChat(version, baseUrl, token) + "/" + messageId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getUrlForChatSharedItems(int version, String baseUrl, String token) {
|
public static String getUrlForChatSharedItems(int version, String baseUrl, String token) {
|
||||||
return getUrlForChat(version, baseUrl, token) + "/share";
|
return getUrlForChat(version, baseUrl, token) + "/share";
|
||||||
}
|
}
|
||||||
@ -366,11 +370,11 @@ public class ApiUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static RetrofitBucket getRetrofitBucketForAddParticipantWithSource(
|
public static RetrofitBucket getRetrofitBucketForAddParticipantWithSource(
|
||||||
int version,
|
int version,
|
||||||
String baseUrl,
|
String baseUrl,
|
||||||
String token,
|
String token,
|
||||||
String source,
|
String source,
|
||||||
String id
|
String id
|
||||||
) {
|
) {
|
||||||
RetrofitBucket retrofitBucket = getRetrofitBucketForAddParticipant(version, baseUrl, token, id);
|
RetrofitBucket retrofitBucket = getRetrofitBucketForAddParticipant(version, baseUrl, token, id);
|
||||||
retrofitBucket.getQueryMap().put("source", source);
|
retrofitBucket.getQueryMap().put("source", source);
|
||||||
@ -417,7 +421,7 @@ public class ApiUtils {
|
|||||||
|
|
||||||
public static String getUrlPushProxy() {
|
public static String getUrlPushProxy() {
|
||||||
return NextcloudTalkApplication.Companion.getSharedApplication().
|
return NextcloudTalkApplication.Companion.getSharedApplication().
|
||||||
getApplicationContext().getResources().getString(R.string.nc_push_server_url) + "/devices";
|
getApplicationContext().getResources().getString(R.string.nc_push_server_url) + "/devices";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getUrlForNotificationWithId(String baseUrl, String notificationId) {
|
public static String getUrlForNotificationWithId(String baseUrl, String notificationId) {
|
||||||
@ -448,8 +452,10 @@ public class ApiUtils {
|
|||||||
return getUrlForChat(version, baseUrl, roomToken) + "/share";
|
return getUrlForChat(version, baseUrl, roomToken) + "/share";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getUrlForHoverCard(String baseUrl, String userId) { return baseUrl + ocsApiVersion +
|
public static String getUrlForHoverCard(String baseUrl, String userId) {
|
||||||
"/hovercard/v1/" + userId; }
|
return baseUrl + ocsApiVersion +
|
||||||
|
"/hovercard/v1/" + userId;
|
||||||
|
}
|
||||||
|
|
||||||
public static String getUrlForSetChatReadMarker(int version, String baseUrl, String roomToken) {
|
public static String getUrlForSetChatReadMarker(int version, String baseUrl, String roomToken) {
|
||||||
return getUrlForChat(version, baseUrl, roomToken) + "/read";
|
return getUrlForChat(version, baseUrl, roomToken) + "/read";
|
||||||
@ -497,4 +503,16 @@ public class ApiUtils {
|
|||||||
public static String getUrlForUnifiedSearch(@NotNull String baseUrl, @NotNull String providerId) {
|
public static String getUrlForUnifiedSearch(@NotNull String baseUrl, @NotNull String providerId) {
|
||||||
return baseUrl + ocsApiVersion + "/search/providers/" + providerId + "/search";
|
return baseUrl + ocsApiVersion + "/search/providers/" + providerId + "/search";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getUrlForPoll(String baseUrl,
|
||||||
|
String roomToken,
|
||||||
|
String pollId) {
|
||||||
|
return getUrlForPoll(baseUrl, roomToken) + "/" + pollId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getUrlForPoll(String baseUrl,
|
||||||
|
String roomToken) {
|
||||||
|
return baseUrl + ocsApiVersion + spreedApiVersion + "/poll/" + roomToken;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
10
app/src/main/res/drawable/ic_baseline_bar_chart_24.xml
Normal file
10
app/src/main/res/drawable/ic_baseline_bar_chart_24.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<vector android:height="24dp"
|
||||||
|
android:tint="#000000"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:width="24dp"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M5,9.2h3L8,19L5,19zM10.6,5h2.8v14h-2.8zM16.2,13L19,13v6h-2.8z" />
|
||||||
|
</vector>
|
109
app/src/main/res/layout/item_custom_incoming_poll_message.xml
Normal file
109
app/src/main/res/layout/item_custom_incoming_poll_message.xml
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Nextcloud Talk application
|
||||||
|
~
|
||||||
|
~ @author Marcel Hibbe
|
||||||
|
~ Copyright (C) 2021 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/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<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_marginLeft="16dp"
|
||||||
|
android:layout_marginTop="2dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginBottom="2dp">
|
||||||
|
|
||||||
|
<com.facebook.drawee.view.SimpleDraweeView
|
||||||
|
android:id="@id/messageUserAvatar"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
app:roundAsCircle="true" />
|
||||||
|
|
||||||
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
|
android:id="@id/bubble"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginEnd="@dimen/message_incoming_bubble_margin_right"
|
||||||
|
android:layout_toEndOf="@id/messageUserAvatar"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:alignContent="stretch"
|
||||||
|
app:alignItems="stretch"
|
||||||
|
app:flexWrap="wrap"
|
||||||
|
app:justifyContent="flex_end">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/message_quote"
|
||||||
|
layout="@layout/item_message_quote"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<androidx.emoji.widget.EmojiTextView
|
||||||
|
android:id="@+id/messageAuthor"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
|
android:textAlignment="viewStart"
|
||||||
|
android:textColor="@color/textColorMaxContrast"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/message_poll_icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
android:src="@drawable/ic_baseline_bar_chart_24"
|
||||||
|
app:tint="@color/high_emphasis_menu_icon"></ImageView>
|
||||||
|
|
||||||
|
<androidx.emoji.widget.EmojiTextView
|
||||||
|
android:id="@+id/message_poll_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAlignment="viewStart"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:text="This is the poll title?" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/double_margin_between_elements"
|
||||||
|
android:text="@string/message_poll_tap_to_vote"></TextView>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@id/messageTime"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/messageText"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
app:layout_alignSelf="center"
|
||||||
|
tools:text="12:38" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/reactions"
|
||||||
|
layout="@layout/reactions_inside_message" />
|
||||||
|
|
||||||
|
</com.google.android.flexbox.FlexboxLayout>
|
||||||
|
</RelativeLayout>
|
@ -0,0 +1,78 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Nextcloud Talk application
|
||||||
|
~
|
||||||
|
~ @author Marcel Hibbe
|
||||||
|
~ Copyright (C) 2021 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/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<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_marginLeft="16dp"
|
||||||
|
android:layout_marginTop="2dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginBottom="2dp">
|
||||||
|
|
||||||
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
|
android:id="@id/bubble"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_marginStart="@dimen/message_outcoming_bubble_margin_left"
|
||||||
|
app:alignContent="stretch"
|
||||||
|
app:alignItems="stretch"
|
||||||
|
app:flexWrap="wrap"
|
||||||
|
app:justifyContent="flex_end">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/message_quote"
|
||||||
|
layout="@layout/item_message_quote"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@id/messageTime"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/messageText"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
app:layout_alignSelf="center"
|
||||||
|
tools:text="10:35" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/checkMark"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/messageTime"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
app:layout_alignSelf="center"
|
||||||
|
android:contentDescription="@null" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/reactions"
|
||||||
|
layout="@layout/reactions_inside_message" />
|
||||||
|
|
||||||
|
</com.google.android.flexbox.FlexboxLayout>
|
||||||
|
</RelativeLayout>
|
@ -309,6 +309,7 @@
|
|||||||
<string name="nc_sent_an_audio" formatted="true">%1$s sent an audio.</string>
|
<string name="nc_sent_an_audio" formatted="true">%1$s sent an audio.</string>
|
||||||
<string name="nc_sent_a_video" formatted="true">%1$s sent a video.</string>
|
<string name="nc_sent_a_video" formatted="true">%1$s sent a video.</string>
|
||||||
<string name="nc_sent_an_image" formatted="true">%1$s sent an image.</string>
|
<string name="nc_sent_an_image" formatted="true">%1$s sent an image.</string>
|
||||||
|
<string name="nc_sent_poll" formatted="true">%1$s sent a poll.</string>
|
||||||
<string name="nc_sent_location" formatted="true">%1$s sent a location.</string>
|
<string name="nc_sent_location" formatted="true">%1$s sent a location.</string>
|
||||||
<string name="nc_sent_voice" formatted="true">%1$s sent a voice message.</string>
|
<string name="nc_sent_voice" formatted="true">%1$s sent a voice message.</string>
|
||||||
<string name="nc_sent_a_link_you">You sent a link.</string>
|
<string name="nc_sent_a_link_you">You sent a link.</string>
|
||||||
@ -317,6 +318,7 @@
|
|||||||
<string name="nc_sent_an_audio_you">You sent an audio.</string>
|
<string name="nc_sent_an_audio_you">You sent an audio.</string>
|
||||||
<string name="nc_sent_a_video_you">You sent a video.</string>
|
<string name="nc_sent_a_video_you">You sent a video.</string>
|
||||||
<string name="nc_sent_an_image_you">You sent an image.</string>
|
<string name="nc_sent_an_image_you">You sent an image.</string>
|
||||||
|
<string name="nc_sent_poll_you">You sent a poll.</string>
|
||||||
<string name="nc_sent_location_you">You sent a location.</string>
|
<string name="nc_sent_location_you">You sent a location.</string>
|
||||||
<string name="nc_sent_voice_you">You sent a voice message.</string>
|
<string name="nc_sent_voice_you">You sent a voice message.</string>
|
||||||
<string name="nc_formatted_message" translatable="false">%1$s: %2$s</string>
|
<string name="nc_formatted_message" translatable="false">%1$s: %2$s</string>
|
||||||
@ -435,6 +437,10 @@
|
|||||||
<string name="play_pause_voice_message">Play/pause voice message</string>
|
<string name="play_pause_voice_message">Play/pause voice message</string>
|
||||||
<string name="nc_voice_message_missing_audio_permission">Permission for audio recording is required</string>
|
<string name="nc_voice_message_missing_audio_permission">Permission for audio recording is required</string>
|
||||||
|
|
||||||
|
<!-- polls -->
|
||||||
|
<string name="message_poll_tap_to_vote">Tap to vote</string>
|
||||||
|
<string name="message_poll_tap_see_results">Tap to see results</string>
|
||||||
|
|
||||||
<!-- Phonebook Integration -->
|
<!-- Phonebook Integration -->
|
||||||
<string name="nc_settings_phone_book_integration_key" translatable="false">phone_book_integration</string>
|
<string name="nc_settings_phone_book_integration_key" translatable="false">phone_book_integration</string>
|
||||||
<string name="nc_settings_phone_book_integration_desc">Match contacts based on phone number to integrate Talk shortcut into system contacts app</string>
|
<string name="nc_settings_phone_book_integration_desc">Match contacts based on phone number to integrate Talk shortcut into system contacts app</string>
|
||||||
@ -534,4 +540,5 @@
|
|||||||
<string name="call_without_notification">Call without notification</string>
|
<string name="call_without_notification">Call without notification</string>
|
||||||
<string name="set_avatar_from_camera">Set avatar from camera</string>
|
<string name="set_avatar_from_camera">Set avatar from camera</string>
|
||||||
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user