From 7f864ce285cf0e0027173631635a25d430380a02 Mon Sep 17 00:00:00 2001 From: Julius Linus Date: Fri, 3 Nov 2023 07:45:40 -0500 Subject: [PATCH] WIP file caption - Reverted Changes + Added Camera Implementation Signed-off-by: rapterjet2004 --- .../IncomingPreviewMessageViewHolder.java | 7 - .../OutcomingPreviewMessageViewHolder.java | 8 - .../messages/PreviewMessageViewHolder.kt | 4 - .../com/nextcloud/talk/chat/ChatActivity.kt | 114 ++++++------- .../nextcloud/talk/ui/ImageStackContainer.kt | 156 ------------------ .../item_custom_incoming_preview_message.xml | 14 -- .../item_custom_outcoming_preview_message.xml | 14 -- 7 files changed, 47 insertions(+), 270 deletions(-) delete mode 100644 app/src/main/java/com/nextcloud/talk/ui/ImageStackContainer.kt diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingPreviewMessageViewHolder.java b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingPreviewMessageViewHolder.java index b33ee4c3653..ec89cd7b761 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingPreviewMessageViewHolder.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingPreviewMessageViewHolder.java @@ -35,7 +35,6 @@ import com.nextcloud.talk.databinding.ItemCustomIncomingPreviewMessageBinding; import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding; import com.nextcloud.talk.models.json.chat.ChatMessage; -import com.nextcloud.talk.ui.ImageStackContainer; import com.nextcloud.talk.utils.TextMatchers; import java.util.HashMap; @@ -140,10 +139,4 @@ public ProgressBar getPreviewContactProgressBar() { @Override public ReactionsInsideMessageBinding getReactionsBinding(){ return binding.reactions; } - - @NonNull - @Override - public ImageStackContainer getImageStack() { - return binding.imageStack; - } } diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPreviewMessageViewHolder.java b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPreviewMessageViewHolder.java index 0630677c9c0..b148254fbbb 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPreviewMessageViewHolder.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPreviewMessageViewHolder.java @@ -33,12 +33,10 @@ import com.nextcloud.talk.databinding.ItemCustomOutcomingPreviewMessageBinding; import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding; import com.nextcloud.talk.models.json.chat.ChatMessage; -import com.nextcloud.talk.ui.ImageStackContainer; import com.nextcloud.talk.utils.TextMatchers; import java.util.HashMap; -import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; import androidx.emoji2.widget.EmojiTextView; @@ -133,10 +131,4 @@ public ProgressBar getPreviewContactProgressBar() { @Override public EmojiTextView getMessageCaption() { return binding.messageCaption; } - - @NonNull - @Override - public ImageStackContainer getImageStack() { - return binding.imageStack; - } } diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/PreviewMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/PreviewMessageViewHolder.kt index d65f2467fb0..e5f302bc037 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/PreviewMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/PreviewMessageViewHolder.kt @@ -50,7 +50,6 @@ import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding import com.nextcloud.talk.extensions.loadChangelogBotAvatar import com.nextcloud.talk.models.json.chat.ChatMessage -import com.nextcloud.talk.ui.ImageStackContainer import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.users.UserManager import com.nextcloud.talk.utils.DateUtils @@ -121,7 +120,6 @@ abstract class PreviewMessageViewHolder(itemView: View?, payload: Any?) : fileViewerUtils = FileViewerUtils(context!!, message.activeUser!!) val fileName = message.selectedIndividualHashMap!![KEY_NAME] - imageStack.resetFilePaths(message.filePathList) messageCaption.visibility = if (message.message != "{file}") { View.VISIBLE } else { @@ -240,7 +238,6 @@ abstract class PreviewMessageViewHolder(itemView: View?, payload: Any?) : image.setImageDrawable(ContextCompat.getDrawable(context!!, R.drawable.ic_mimetype_text_vcard)) } } else if (message.displayImageStack()) { - imageStack.visibility = View.VISIBLE previewContainer.visibility = View.GONE previewContactContainer.visibility = View.GONE } @@ -335,7 +332,6 @@ abstract class PreviewMessageViewHolder(itemView: View?, payload: Any?) : abstract val messageText: EmojiTextView abstract val messageCaption: EmojiTextView abstract val previewContainer: View - abstract val imageStack: ImageStackContainer abstract val previewContactContainer: MaterialCardView abstract val previewContactPhoto: ImageView abstract val previewContactName: EmojiTextView diff --git a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt index 834cbfe4c88..af87d250689 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt @@ -2477,7 +2477,19 @@ class ChatActivity : } if (permissionUtil.isFilesPermissionGranted()) { - uploadFiles(filesToUpload) + val filenamesWithLineBreaks = StringBuilder("\n") + + for (file in filesToUpload) { + val filename = FileUtils.getFileName(Uri.parse(file), context) + filenamesWithLineBreaks.append(filename).append("\n") + } + + val newFragment: DialogFragment = FileAttachmentPreviewFragment.newInstance( + filenamesWithLineBreaks.toString(), + filesToUpload, + this::uploadFiles + ) + newFragment.show(supportFragmentManager, FileAttachmentPreviewFragment.TAG) } else { UploadAndShareFilesWorker.requestStoragePermission(this) } @@ -2602,12 +2614,12 @@ class ChatActivity : } private fun uploadFiles(files: MutableList, caption: String = "") { - // TODO for now all files are uploaded with a caption. In the future, set only one, and just don't render the - // rest, cuz it'll be a group message - val groupKey = SystemClock.elapsedRealtime().toString() - var newCaption = "$groupKey:" + "${files.size}:" + caption - for (file in files) { - uploadFile(file, false, newCaption) + for (i in 0 until files.size) { + if(i == files.size-1) { + uploadFile(files[i], false, caption) + } else { + uploadFile(files[i], false) + } } } @@ -3168,8 +3180,6 @@ class ChatActivity : handleExpandableSystemMessages(chatMessageList) - processGroupedFiles(chatMessageList) - processHeaderChatLastGiven(response, lookIntoFuture) if (chatMessageList.isNotEmpty() && @@ -3191,30 +3201,7 @@ class ChatActivity : Integer.parseInt(it) } - try { - val mostRecentCallSystemMessage = adapter?.items?.first { - it.item is ChatMessage && - (it.item as ChatMessage).systemMessageType in - listOf( - ChatMessage.SystemMessageType.CALL_STARTED, - ChatMessage.SystemMessageType.CALL_JOINED, - ChatMessage.SystemMessageType.CALL_LEFT, - ChatMessage.SystemMessageType.CALL_ENDED, - ChatMessage.SystemMessageType.CALL_TRIED, - ChatMessage.SystemMessageType.CALL_ENDED_EVERYONE, - ChatMessage.SystemMessageType.CALL_MISSED - ) - }?.item - - if (mostRecentCallSystemMessage != null) { - processMostRecentMessage( - mostRecentCallSystemMessage as ChatMessage, - chatMessageList - ) - } - } catch (e: java.util.NoSuchElementException) { - Log.d(TAG, "No System messages found $e") - } + processCallStartedMessages(chatMessageList) updateReadStatusOfAllMessages(newXChatLastCommonRead) adapter?.notifyDataSetChanged() @@ -3249,6 +3236,33 @@ class ChatActivity : }) } + private fun processCallStartedMessages(chatMessageList: List) { + try { + val mostRecentCallSystemMessage = adapter?.items?.first { + it.item is ChatMessage && + (it.item as ChatMessage).systemMessageType in + listOf( + ChatMessage.SystemMessageType.CALL_STARTED, + ChatMessage.SystemMessageType.CALL_JOINED, + ChatMessage.SystemMessageType.CALL_LEFT, + ChatMessage.SystemMessageType.CALL_ENDED, + ChatMessage.SystemMessageType.CALL_TRIED, + ChatMessage.SystemMessageType.CALL_ENDED_EVERYONE, + ChatMessage.SystemMessageType.CALL_MISSED + ) + }?.item + + if (mostRecentCallSystemMessage != null) { + processMostRecentMessage( + mostRecentCallSystemMessage as ChatMessage, + chatMessageList + ) + } + } catch (e: NoSuchElementException) { + Log.d(TAG, "No System messages found $e") + } + } + private fun setupFieldsForPullChatMessages( lookIntoFuture: Boolean, xChatLastCommonRead: Int?, @@ -3324,40 +3338,6 @@ class ChatActivity : } } - private fun processGroupedFiles(chatMessageList: List) { - val map = mutableMapOf() - for (message in chatMessageList) { - if (message.getCalculateMessageType() == ChatMessage.MessageType.SINGLE_NC_ATTACHMENT_MESSAGE && - message.message!!.isNotBlank() && message.message != "{file}" - ) { - val groupKey = message.message!!.substringBefore(':') - message.message = message.message!!.substringAfter(':') - val size = message.message!!.substringBefore(':').toInt() - message.message = message.message!!.substringAfter(':') - if (!map.contains(groupKey)) { - map.put(groupKey, message) - message.message = message.message!!.substringAfter(':') - val name = message.messageParameters?.get("file")?.get(PreviewMessageViewHolder.KEY_NAME) - if (name != null) { - val path = applicationContext.cacheDir.absolutePath + "/" + name - message.filePathList.add(path) - adapter?.notifyDataSetChanged() - } - } else { - message.displayedElseWhere = true - val name = message.messageParameters?.get("file")?.get(PreviewMessageViewHolder.KEY_NAME) - if (name != null) { - val path = applicationContext.cacheDir.absolutePath + "/" + name - map[groupKey]!!.filePathList.add(path) - adapter?.notifyDataSetChanged() - } - // TODO for now, both files will be displayed, but I just want to get this to work - // later on I can work on "hiding" the non rendered messages - } - } - } - } - private fun updateReadStatusOfAllMessages(xChatLastCommonRead: Int?) { if (adapter != null) { for (message in adapter!!.items) { diff --git a/app/src/main/java/com/nextcloud/talk/ui/ImageStackContainer.kt b/app/src/main/java/com/nextcloud/talk/ui/ImageStackContainer.kt deleted file mode 100644 index da50cdeaafb..00000000000 --- a/app/src/main/java/com/nextcloud/talk/ui/ImageStackContainer.kt +++ /dev/null @@ -1,156 +0,0 @@ -package com.nextcloud.talk.ui - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.BitmapFactory -import android.graphics.Canvas -import android.graphics.Paint -import android.graphics.Path -import android.graphics.PorterDuff -import android.graphics.PorterDuffXfermode -import android.graphics.Rect -import android.util.AttributeSet -import android.util.Log -import android.view.View -import androidx.core.graphics.toRectF - -class ImageStackContainer(context: Context, attrs: AttributeSet) : View(context, attrs) { - private var filePathList = mutableListOf() - private var image1: Bitmap? = null - private var image1Bounds: Rect = Rect() - private var image1Path = Path() - private var image1Paint = Paint(Paint.ANTI_ALIAS_FLAG) - private var image2: Bitmap? = null - private var image2Bounds: Rect = Rect() - private var image2Path = Path() - private var image2Paint = Paint(Paint.ANTI_ALIAS_FLAG) - private var image3: Bitmap? = null - private var image3Bounds: Rect = Rect() - private var image3Path = Path() - private var image3Paint = Paint(Paint.ANTI_ALIAS_FLAG) - - @Suppress("ArgumentListWrapping") - private val corners = floatArrayOf( - RADIUS, - RADIUS, // Top left radius in px - RADIUS, - RADIUS, // Top right radius in px - RADIUS, - RADIUS, // Top left radius in px - RADIUS, - RADIUS // Bottom left radius in px - ) - private var clippingRect: Rect? = null - - init { - Log.d(TAG, "ImageStackContainer Initialized with list $filePathList") - image1Paint.apply { - color = 0xff424242.toInt() - } - - image2Paint.apply { - color = 0xff555242.toInt() - } - - image3Paint.apply { - color = 0xfe464742.toInt() - } - } - - // TODO add some shadow effects to show elevation - override fun onDraw(canvas: Canvas) { - super.onDraw(canvas) - - // TODO deal with BitmapFactory loading from url before it's downloaded to Cache - @Suppress("MagicNumber") - if (filePathList.size >= 3 && image3 == null) { - image3 = BitmapFactory.decodeFile(filePathList[2]) - } - - if (filePathList.size >= 2 && image2 == null) { - image2 = BitmapFactory.decodeFile(filePathList[1]) - } - - if (filePathList.size >= 1 && image1 == null) { - image1 = BitmapFactory.decodeFile(filePathList[0]) - } - canvas.apply { - clippingRect = clipBounds - val left = (clipBounds.right - WIDTH) / 2 - val top = (clipBounds.bottom - HEIGHT) / 2 - val right = (clipBounds.right - left) - val bottom = (clipBounds.bottom - top) - - if (image3 != null) { - save() - image3Bounds.apply { - set(left, top, right, bottom) - offset(OFFSET_X, -OFFSET_Y) - } - val bitmap3 = getCroppedBitmap(image3!!, image3Bounds, image3Paint, image3Path) - drawBitmap(bitmap3, image3Bounds, image3Bounds, image3Paint) - restore() - } - - if (image2 != null) { - save() - image2Bounds.apply { - set(left, top, right, bottom) - offset(-OFFSET_X, OFFSET_Y) - } - val bitmap2 = getCroppedBitmap(image2!!, image2Bounds, image2Paint, image2Path) - drawBitmap(bitmap2, image2Bounds, image2Bounds, image2Paint) - restore() - } - - if (image1 != null) { - save() - image1Bounds.apply { - set(left, top, right, bottom) - } - val bitmap = getCroppedBitmap(image1!!, image1Bounds, image1Paint, image1Path) - drawBitmap(bitmap, image1Bounds, image1Bounds, image1Paint) - restore() - } - } - } - - private fun getCroppedBitmap(original: Bitmap, bounds: Rect, paint: Paint, path: Path): Bitmap { - // TODO error with Image Scaling. Crop it to fit instead - // val scaleW = (clippingRect!!.right / ZOOM) - // val scaleH = (clippingRect!!.bottom / ZOOM) - // val original = bitmap.scale(bounds.width() * scaleW, bounds.height() * scaleH) - val output = Bitmap.createBitmap( - original.width, - original.height, - Bitmap.Config.ARGB_8888 - ) - val canvas = Canvas(output) // canvas draws onto output - val color = -0xbdbdbe // preview color if no image - paint.apply { - this.color = color - } - path.apply { - addRoundRect(bounds.toRectF(), corners, Path.Direction.CCW) - } - canvas.drawPath(path, paint) - paint.setXfermode(PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP)) - canvas.drawBitmap(original, bounds, bounds, paint) - return output - } - - fun resetFilePaths(paths: List) { - filePathList = paths.toMutableList() - invalidate() - } - - companion object { - val TAG: String? = ImageStackContainer::class.java.simpleName - private const val WIDTH = 100 - private const val HEIGHT = 150 - private const val RADIUS = 25f - private const val ZOOM = 100 - private const val OFFSET_X = 15 - private const val OFFSET_Y = 20 - } -} diff --git a/app/src/main/res/layout/item_custom_incoming_preview_message.xml b/app/src/main/res/layout/item_custom_incoming_preview_message.xml index fd686e16bcf..c74ba83d036 100644 --- a/app/src/main/res/layout/item_custom_incoming_preview_message.xml +++ b/app/src/main/res/layout/item_custom_incoming_preview_message.xml @@ -158,20 +158,6 @@ - - - - - - - - - - - -