Simple attachments in messages history (#164)

* new attachments in messages history - photo, video, audio, file, link
* improve attachments in messages history and adjusted font size for logo's text in auth screen
* audio duration, file preview and url preview are now visible in attachments in messages history screen
* make MessageBubble width adapt to attachments container width
* topbar back icon crossfade animation
* implement rich text for message input
* handle click and long click on attachments
* added click and long click handlers for attachments in message bubbles
* enabled opening photos, files, and links when clicked.
* implemented basic long-click logging for photos.
* handled back press to return to Conversations from other tabs.
* corrected the logic for filtering and selecting video images.
* updated string resources for attachments, including a new "Clip" string.
* make MessageBubble mention text underline on out messages
This commit is contained in:
2025-05-10 03:10:07 +03:00
committed by GitHub
parent f45a106ed8
commit 43539139e8
46 changed files with 2296 additions and 369 deletions
@@ -3,7 +3,7 @@ package dev.meloda.fast.ui.util
import androidx.compose.runtime.Immutable
@Immutable
class ImmutableList<T>(val values: List<T>) : Iterable<T> {
class ImmutableList<T>(val values: List<T>) : Collection<T> {
constructor(size: Int, init: (index: Int) -> T) : this(MutableList(size, init))
@@ -25,30 +25,18 @@ class ImmutableList<T>(val values: List<T>) : Iterable<T> {
return values.mapIndexed(transform).toImmutableList()
}
fun singleOrNull(): T? {
return if (values.size == 1) this[0] else null
override fun isEmpty(): Boolean = values.isEmpty()
override val size: Int get() = values.size
override fun containsAll(elements: Collection<T>): Boolean {
return values.containsAll(elements)
}
fun isEmpty(): Boolean = values.isEmpty()
fun isNotEmpty(): Boolean = !isEmpty()
inline fun singleOrNull(predicate: (T) -> Boolean): T? {
var single: T? = null
var found = false
for (element in this) {
if (predicate(element)) {
if (found) return null
single = element
found = true
}
}
if (!found) return null
return single
override fun contains(element: T): Boolean {
return values.contains(element)
}
val size: Int get() = values.size
companion object {
fun <T> copyOf(collection: Collection<T>): ImmutableList<T> =
ImmutableList(collection.toList())
@@ -67,3 +55,7 @@ class ImmutableList<T>(val values: List<T>) : Iterable<T> {
}
fun <T> emptyImmutableList(): ImmutableList<T> = ImmutableList(emptyList())
fun <T> immutableListOf(vararg elements: T) = ImmutableList(listOf(elements = elements))
fun <T> ImmutableList<T>?.orEmpty(): ImmutableList<T> = this ?: emptyImmutableList()
@@ -107,6 +107,7 @@
<string name="message_attachments_files_few">%1$d файла</string>
<string name="message_attachments_files_many">%1$d файлов</string>
<string name="message_attachments_files_other">%1$d файлов</string>
<string name="message_attachments_clip">Клип</string>
<string name="message_attachments_audio_message">Голосовое сообщение</string>
<string name="message_attachments_link">Ссылка</string>
<string name="message_attachments_mini_app">Мини-приложение</string>
@@ -263,4 +264,9 @@
<string name="conversation_context_action_archive">В архив</string>
<string name="confirm_archive_conversation">Архивировать чат?</string>
<string name="action_archive">В архив</string>
<string name="autofill">Автозаполнение</string>
<string name="bold">Жирный</string>
<string name="italic">Курсив</string>
<string name="underline">Подчёркнутый</string>
<string name="link">Ссылка</string>
</resources>
+7
View File
@@ -83,6 +83,7 @@
<string name="message_attachments_files_many">%1$d files</string>
<string name="message_attachments_files_other">%1$d files</string>
<string name="message_attachments_clip">Clip</string>
<string name="message_attachments_audio_message">Voice message</string>
<string name="message_attachments_link">Link</string>
<string name="message_attachments_mini_app">Mini App</string>
@@ -338,4 +339,10 @@
<string name="unspam_message_title">Unmark as spam</string>
<string name="unspam_message_text">Are you sure you want to unmark this message as spam?</string>
<string name="copied_to_clipboard">Copied to clipboard</string>
<string name="autofill">Autofill</string>
<string name="bold">Bold</string>
<string name="italic">Italic</string>
<string name="underline">Underline</string>
<string name="link">Link</string>
</resources>