Skip to content

Commit

Permalink
Show Accept Call Button in Chat
Browse files Browse the repository at this point in the history
- added call_started_message.xml
- added CallStartedViewHolder.kt
- added CallStartedMessageInterface.kt
- Both join audio and join video buttons
- Gets destroyed if call ends, persists despite state changes

Signed-off-by: Julius Linus <[email protected]>
  • Loading branch information
Julius Linus authored and rapterjet2004 committed Sep 13, 2023
1 parent 7e4a3dc commit 63ed6e8
Show file tree
Hide file tree
Showing 6 changed files with 272 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Nextcloud Talk application
*
* @author Julius Linus
* Copyright (C) 2023 Julius Linus <[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.messages

interface CallStartedMessageInterface {
fun joinAudioCall()
fun joinVideoCall()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Nextcloud Talk application
*
* @author Julius Linus
* Copyright (C) 2023 Julius Linus <[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.messages

import android.content.Context
import android.text.Spannable
import android.text.SpannableString
import android.view.View
import autodagger.AutoInjector
import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.databinding.CallStartedMessageBinding
import com.nextcloud.talk.models.json.chat.ChatMessage
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.users.UserManager
import com.nextcloud.talk.utils.DisplayUtils
import com.stfalcon.chatkit.messages.MessageHolders
import javax.inject.Inject

@AutoInjector(NextcloudTalkApplication::class)
class CallStartedViewHolder(incomingView: View, payload: Any) :
MessageHolders.BaseIncomingMessageViewHolder<ChatMessage>(incomingView, payload) {
private val binding: CallStartedMessageBinding = CallStartedMessageBinding.bind(incomingView)

@Inject
lateinit var context: Context

@Inject
lateinit var userManager: UserManager

@Inject
lateinit var viewThemeUtils: ViewThemeUtils

private lateinit var messageInterface: CallStartedMessageInterface

override fun onBind(message: ChatMessage?) {
super.onBind(message)
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
themeBackground()
val name = "@" + message!!.actorDisplayName
val text = name + " " + context.resources.getString(R.string.started_a_call)
var spannable: Spannable = SpannableString(text)
// TODO figure out a way to replace with mentioned chip
val mentionColor: Int = context.resources.getColor(R.color.textColorMaxContrast)
spannable = DisplayUtils.searchAndColor(spannable, name, mentionColor)

binding.callAuthorTextview.text = spannable
binding.joinVideoCall.setOnClickListener { messageInterface.joinVideoCall() }
binding.joinAudioCall.setOnClickListener { messageInterface.joinAudioCall() }
}

private fun themeBackground() {
binding.callStartedBackground.apply {
viewThemeUtils.talk.themeOutgoingMessageBubble(this, grouped = true, false)
}
}

fun assignCallStartedMessageInterface(inf: CallStartedMessageInterface) {
messageInterface = inf
}

companion object {
var TAG: String? = CallStartedViewHolder::class.simpleName
}

override fun viewDetached() {
// unused atm
}

override fun viewAttached() {
// unused atm
}

override fun viewRecycled() {
// unused atm
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ public void onBindViewHolder(ViewHolder holder, int position) {

} else if (holder instanceof SystemMessageViewHolder) {
((SystemMessageViewHolder) holder).assignSystemMessageInterface(chatActivity);
} else if (holder instanceof CallStartedViewHolder) {
((CallStartedViewHolder) holder).assignCallStartedMessageInterface(chatActivity);
}
}
}
75 changes: 68 additions & 7 deletions app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ import com.nextcloud.talk.R
import com.nextcloud.talk.activities.BaseActivity
import com.nextcloud.talk.activities.CallActivity
import com.nextcloud.talk.activities.TakePhotoActivity
import com.nextcloud.talk.adapters.messages.CallStartedMessageInterface
import com.nextcloud.talk.adapters.messages.CallStartedViewHolder
import com.nextcloud.talk.adapters.messages.CommonMessageInterface
import com.nextcloud.talk.adapters.messages.IncomingLinkPreviewMessageViewHolder
import com.nextcloud.talk.adapters.messages.IncomingLocationMessageViewHolder
Expand Down Expand Up @@ -267,7 +269,8 @@ class ChatActivity :
VoiceMessageInterface,
CommonMessageInterface,
PreviewMessageInterface,
SystemMessageInterface {
SystemMessageInterface,
CallStartedMessageInterface {

var active = false

Expand Down Expand Up @@ -376,6 +379,8 @@ class ChatActivity :
var typedWhileTypingTimerIsRunning: Boolean = false
val typingParticipants = HashMap<String, TypingParticipant>()

var callStarted = false

private val localParticipantMessageListener = object : SignalingMessageReceiver.LocalParticipantMessageListener {
override fun onSwitchTo(token: String?) {
if (token != null) {
Expand Down Expand Up @@ -945,6 +950,17 @@ class ChatActivity :
R.layout.item_custom_outcoming_preview_message
)

messageHolders.registerContentType(
CONTENT_TYPE_CALL_STARTED,
CallStartedViewHolder::class.java,
payload,
R.layout.call_started_message,
CallStartedViewHolder::class.java,
payload,
R.layout.call_started_message,
this
)

messageHolders.registerContentType(
CONTENT_TYPE_SYSTEM_MESSAGE,
SystemMessageViewHolder::class.java,
Expand Down Expand Up @@ -3164,6 +3180,16 @@ class ChatActivity :
Integer.parseInt(it)
}

val last = adapter?.items!!.first {
it.item is ChatMessage &&
(it.item as ChatMessage).systemMessageType != null &&
(it.item as ChatMessage).systemMessageType!!.ordinal <= 11 &&
(it.item as ChatMessage).systemMessageType!!.ordinal >= 5
}.item

if (last != null)
processMostRecentMessage(last as ChatMessage, chatMessageList)

updateReadStatusOfAllMessages(newXChatLastCommonRead)
adapter?.notifyDataSetChanged()

Expand Down Expand Up @@ -4207,10 +4233,36 @@ class ChatActivity :
CONTENT_TYPE_LINK_PREVIEW -> message.isLinkPreview()
CONTENT_TYPE_SYSTEM_MESSAGE -> !TextUtils.isEmpty(message.systemMessage)
CONTENT_TYPE_UNREAD_NOTICE_MESSAGE -> message.id == "-1"
CONTENT_TYPE_CALL_STARTED -> message.id == "-2"

else -> false
}
}

private fun processMostRecentMessage(recent: ChatMessage, chatMessageList: List<ChatMessage>) {
when (recent.systemMessageType) {
ChatMessage.SystemMessageType.CALL_STARTED -> {
if (!callStarted) {
val unreadChatMessage = ChatMessage()
unreadChatMessage.jsonMessageId = -2
unreadChatMessage.actorId = "-2"
unreadChatMessage.actorDisplayName = recent.actorDisplayName
unreadChatMessage.timestamp = chatMessageList[0].timestamp
unreadChatMessage.message = null
adapter?.addToStart(unreadChatMessage, false)
callStarted = true
}
} // add CallStartedMessage with id -2
ChatMessage.SystemMessageType.CALL_ENDED,
ChatMessage.SystemMessageType.CALL_MISSED,
ChatMessage.SystemMessageType.CALL_ENDED_EVERYONE -> {
adapter?.deleteById("-2")
callStarted = false
} // remove message of id -2
else -> {}
}
}

@Subscribe(threadMode = ThreadMode.BACKGROUND)
fun onMessageEvent(webSocketCommunicationEvent: WebSocketCommunicationEvent) {
/*
Expand Down Expand Up @@ -4344,6 +4396,14 @@ class ChatActivity :
}
}

override fun joinAudioCall() {
startACall(true, false)
}

override fun joinVideoCall() {
startACall(false, false)
}

private fun logConversationInfos(methodName: String) {
Log.d(TAG, " |-----------------------------------------------")
Log.d(TAG, " | method: $methodName")
Expand All @@ -4356,12 +4416,13 @@ class ChatActivity :

companion object {
private val TAG = ChatActivity::class.simpleName
private const val CONTENT_TYPE_SYSTEM_MESSAGE: Byte = 1
private const val CONTENT_TYPE_UNREAD_NOTICE_MESSAGE: Byte = 2
private const val CONTENT_TYPE_LOCATION: Byte = 3
private const val CONTENT_TYPE_VOICE_MESSAGE: Byte = 4
private const val CONTENT_TYPE_POLL: Byte = 5
private const val CONTENT_TYPE_LINK_PREVIEW: Byte = 6
private const val CONTENT_TYPE_CALL_STARTED: Byte = 1
private const val CONTENT_TYPE_SYSTEM_MESSAGE: Byte = 2
private const val CONTENT_TYPE_UNREAD_NOTICE_MESSAGE: Byte = 3
private const val CONTENT_TYPE_LOCATION: Byte = 4
private const val CONTENT_TYPE_VOICE_MESSAGE: Byte = 5
private const val CONTENT_TYPE_POLL: Byte = 6
private const val CONTENT_TYPE_LINK_PREVIEW: Byte = 7
private const val NEW_MESSAGES_POPUP_BUBBLE_DELAY: Long = 200
private const val GET_ROOM_INFO_DELAY_NORMAL: Long = 30000
private const val GET_ROOM_INFO_DELAY_LOBBY: Long = 5000
Expand Down
79 changes: 79 additions & 0 deletions app/src/main/res/layout/call_started_message.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Nextcloud Talk application
~
~ @author Julius Linus
~ Copyright (C) 2023 Julius Linus <[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/>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/call_started_background"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/standard_double_margin"
android:padding="@dimen/standard_padding"
tools:background="@drawable/shape_grouped_outcoming_message"
tools:backgroundTint="@color/colorPrimaryDark">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/standard_margin"
android:orientation="horizontal"
android:gravity="center">

<com.google.android.material.textview.MaterialTextView
android:id="@+id/call_author_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="(( ) Ariel Fox) started a call" />

</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">

<com.google.android.material.button.MaterialButton
android:id="@+id/join_video_call"
style="@style/Widget.Material3.Button.Icon"
android:backgroundTint="@color/nc_darkGreen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/standard_half_margin"
app:icon="@drawable/ic_videocam_grey_600_24dp"
app:iconTint="@color/hwSecurityGreen"
android:alpha="0.8"
android:text="@string/video_call" />

<com.google.android.material.button.MaterialButton
android:id="@+id/join_audio_call"
style="@style/Widget.Material3.Button.Icon"
android:backgroundTint="@color/nc_darkGreen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/standard_half_margin"
android:alpha="0.8"
app:icon="@drawable/ic_phone"
app:iconTint="@color/hwSecurityGreen"
android:text="@string/audio_call" />
</LinearLayout>


</LinearLayout>
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -706,5 +706,8 @@ How to translate with transifex:
<string name="custom">Custom</string>
<string name="set">Set</string>
<string name="calendar">Calendar</string>
<string name="video_call">Video Call</string>
<string name="audio_call">Audio Call</string>
<string name="started_a_call">started a call</string>

</resources>

0 comments on commit 63ed6e8

Please sign in to comment.