Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Animated GIFS in Chat #4030

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,35 +22,46 @@ import android.widget.ImageView
import android.widget.ProgressBar
import androidx.core.content.ContextCompat
import androidx.emoji2.widget.EmojiTextView
import androidx.work.Data
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkInfo
import androidx.work.WorkManager
import autodagger.AutoInjector
import com.google.android.material.card.MaterialCardView
import com.nextcloud.android.common.ui.theme.utils.ColorRole
import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
import com.nextcloud.talk.chat.ChatActivity
import com.nextcloud.talk.components.filebrowser.models.BrowserFile
import com.nextcloud.talk.components.filebrowser.webdav.ReadFilesystemOperation
import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding
import com.nextcloud.talk.extensions.loadChangelogBotAvatar
import com.nextcloud.talk.extensions.loadFederatedUserAvatar
import com.nextcloud.talk.jobs.DownloadFileToCacheWorker
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.CapabilitiesUtil
import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.DrawableUtils.getDrawableResourceIdForMimeType
import com.nextcloud.talk.utils.FileViewerUtils
import com.nextcloud.talk.utils.FileViewerUtils.ProgressUi
import com.nextcloud.talk.utils.MimetypeUtils.isGif
import com.nextcloud.talk.utils.message.MessageUtils
import com.stfalcon.chatkit.messages.MessageHolders.IncomingImageMessageViewHolder
import io.reactivex.Single
import io.reactivex.SingleObserver
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import okhttp3.OkHttpClient
import pl.droidsonroids.gif.GifDrawable
import java.io.ByteArrayInputStream
import java.io.File
import java.io.IOException
import java.util.concurrent.ExecutionException
import javax.inject.Inject

@AutoInjector(NextcloudTalkApplication::class)
Expand Down Expand Up @@ -101,10 +112,25 @@ abstract class PreviewMessageViewHolder(itemView: View?, payload: Any?) :
viewThemeUtils!!.platform.colorCircularProgressBar(progressBar!!, ColorRole.PRIMARY)
clickView = image
messageText.visibility = View.VISIBLE

if (message.getCalculateMessageType() === ChatMessage.MessageType.SINGLE_NC_ATTACHMENT_MESSAGE) {
fileViewerUtils = FileViewerUtils(context!!, message.activeUser!!)
val fileName = message.selectedIndividualHashMap!![KEY_NAME]

if (message.selectedIndividualHashMap!!.containsKey(KEY_MIMETYPE)) {
val mimetype = message.selectedIndividualHashMap!![KEY_MIMETYPE]
if (isGif(mimetype!!)) {
val file = File(context!!.cacheDir, fileName!!)
if (file.exists()) {
setGif(fileName)
} else {
// downloads the file to cache
downloadFileToCache(message, openWhenDownloaded = false) {
setGif(fileName)
}
}
}
}
messageText.text = fileName

if (message.activeUser != null &&
Expand Down Expand Up @@ -192,6 +218,15 @@ abstract class PreviewMessageViewHolder(itemView: View?, payload: Any?) :
}
}

private fun setGif(fileName: String?) {
val path = context!!.cacheDir.absolutePath + "/" + fileName
val gifFromUri = GifDrawable(path)
(clickView as ImageView).setImageDrawable(gifFromUri)
(clickView as ImageView).scaleType = ImageView.ScaleType.CENTER_CROP
(clickView as ImageView).layoutParams.width = 800
(clickView as ImageView).layoutParams.height = 800
}

private fun longClickOnReaction(chatMessage: ChatMessage) {
commonMessageInterface.onLongClickReactions(chatMessage)
}
Expand Down Expand Up @@ -232,6 +267,10 @@ abstract class PreviewMessageViewHolder(itemView: View?, payload: Any?) :

if (message.selectedIndividualHashMap!!.containsKey(KEY_MIMETYPE)) {
val mimetype = message.selectedIndividualHashMap!![KEY_MIMETYPE]
if (isGif(mimetype!!)) {
return message
}

val drawableResourceId = getDrawableResourceIdForMimeType(mimetype)
var drawable = ContextCompat.getDrawable(context!!, drawableResourceId)
if (drawable != null &&
Expand Down Expand Up @@ -313,6 +352,70 @@ abstract class PreviewMessageViewHolder(itemView: View?, payload: Any?) :
this.previewMessageInterface = previewMessageInterface
}

private fun downloadFileToCache(
message: ChatMessage,
openWhenDownloaded: Boolean,
funToCallWhenDownloadSuccessful: (() -> Unit)
) {
message.isDownloadingVoiceMessage = true
message.openWhenDownloaded = openWhenDownloaded

val baseUrl = message.activeUser!!.baseUrl
val userId = message.activeUser!!.userId
val attachmentFolder = CapabilitiesUtil.getAttachmentFolder(
message.activeUser!!.capabilities!!
.spreedCapability!!
)
val fileName = message.selectedIndividualHashMap!!["name"]
var size = message.selectedIndividualHashMap!!["size"]
if (size == null) {
size = "-1"
}
val fileSize = size.toLong()
val fileId = message.selectedIndividualHashMap!!["id"]
val path = message.selectedIndividualHashMap!!["path"]

// check if download worker is already running
val workers = WorkManager.getInstance(
context!!
).getWorkInfosByTag(fileId!!)
try {
for (workInfo in workers.get()) {
if (workInfo.state == WorkInfo.State.RUNNING || workInfo.state == WorkInfo.State.ENQUEUED) {
Log.d(ChatActivity.TAG, "Download worker for $fileId is already running or scheduled")
return
}
}
} catch (e: ExecutionException) {
Log.e(ChatActivity.TAG, "Error when checking if worker already exists", e)
} catch (e: InterruptedException) {
Log.e(ChatActivity.TAG, "Error when checking if worker already exists", e)
}

val data: Data = Data.Builder()
.putString(DownloadFileToCacheWorker.KEY_BASE_URL, baseUrl)
.putString(DownloadFileToCacheWorker.KEY_USER_ID, userId)
.putString(DownloadFileToCacheWorker.KEY_ATTACHMENT_FOLDER, attachmentFolder)
.putString(DownloadFileToCacheWorker.KEY_FILE_NAME, fileName)
.putString(DownloadFileToCacheWorker.KEY_FILE_PATH, path)
.putLong(DownloadFileToCacheWorker.KEY_FILE_SIZE, fileSize)
.build()

val downloadWorker: OneTimeWorkRequest = OneTimeWorkRequest.Builder(DownloadFileToCacheWorker::class.java)
.setInputData(data)
.addTag(fileId)
.build()

WorkManager.getInstance().enqueue(downloadWorker)

WorkManager.getInstance(context!!).getWorkInfoByIdLiveData(downloadWorker.id)
.observeForever { workInfo: WorkInfo ->
if (workInfo.state == WorkInfo.State.SUCCEEDED) {
funToCallWhenDownloadSuccessful()
}
}
}

abstract val messageText: EmojiTextView
abstract val messageCaption: EmojiTextView
abstract val previewContainer: View
Expand Down
14 changes: 8 additions & 6 deletions app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1073,8 +1073,14 @@ class ChatActivity :
adapter = TalkMessagesListAdapter(
senderId,
initMessageHolders(),
ImageLoader { imageView, url, placeholder ->
imageView.loadAvatarOrImagePreview(url!!, conversationUser!!, placeholder as Drawable?)
ImageLoader { imageView, url, data ->
try {
if ((data !is ChatMessage)) { // It's Not a GIF
imageView.loadAvatarOrImagePreview(url!!, conversationUser!!, data as Drawable?)
}
} catch (e: Exception) {
Log.e(TAG, "Error in ImageLoading in initAdapter $e")
}
},
this
)
Expand Down Expand Up @@ -3384,10 +3390,6 @@ class ChatActivity :
val messageTemp = message as ChatMessage
messageTemp.lastEditTimestamp = message.lastEditTimestamp

val index = adapter?.getMessagePositionById(messageTemp.id) ?: 0
val adapterMsg = adapter?.items?.get(index)?.item as ChatMessage

messageTemp.parentMessage = adapterMsg.parentMessage
messageTemp.isOneToOneConversation =
currentConversation?.type == ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL
messageTemp.activeUser = conversationUser
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,10 @@
app:layout_wrapBefore="true"
tools:visibility="gone">

<ImageView
<pl.droidsonroids.gif.GifImageView
android:id="@id/image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitStart"
tools:src="@drawable/ic_call_black_24dp"
tools:ignore="ContentDescription" />

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,10 @@
app:layout_flexGrow="1"
app:layout_wrapBefore="true">

<ImageView
<pl.droidsonroids.gif.GifImageView
android:id="@id/image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitStart"
tools:src="@drawable/ic_call_black_24dp"
tools:ignore="ContentDescription" />

Expand Down
Loading