Refactor image blurring to use RenderScript for improved performance and quality
- Replaced custom fast blur implementation with RenderScript-based Gaussian blur in BlurredAvatarBackground and AppearanceScreen. - Updated image processing logic to scale down bitmaps before applying blur for efficiency. - Simplified blur logic by removing unnecessary pixel manipulation methods. - Enhanced media preview handling in OtherProfileScreen to utilize new Gaussian blur function. - Improved code readability and maintainability by consolidating blur functionality.
This commit is contained in:
@@ -3,6 +3,70 @@ package com.rosetta.messenger.database
|
||||
import androidx.room.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// 📌 PINNED MESSAGES
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/** Entity для закреплённых сообщений в чате (Telegram-style pinned messages) */
|
||||
@Entity(
|
||||
tableName = "pinned_messages",
|
||||
indices =
|
||||
[
|
||||
Index(
|
||||
value = ["account", "dialog_key", "message_id"],
|
||||
unique = true
|
||||
),
|
||||
Index(value = ["account", "dialog_key", "pinned_at"])]
|
||||
)
|
||||
data class PinnedMessageEntity(
|
||||
@PrimaryKey(autoGenerate = true) val id: Long = 0,
|
||||
@ColumnInfo(name = "account") val account: String,
|
||||
@ColumnInfo(name = "dialog_key") val dialogKey: String,
|
||||
@ColumnInfo(name = "message_id") val messageId: String,
|
||||
@ColumnInfo(name = "pinned_at") val pinnedAt: Long = System.currentTimeMillis()
|
||||
)
|
||||
|
||||
/** DAO для работы с закреплёнными сообщениями */
|
||||
@Dao
|
||||
interface PinnedMessageDao {
|
||||
|
||||
/** Закрепить сообщение (IGNORE если уже закреплено) */
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
suspend fun insertPin(pin: PinnedMessageEntity): Long
|
||||
|
||||
/** Открепить конкретное сообщение */
|
||||
@Query(
|
||||
"DELETE FROM pinned_messages WHERE account = :account AND dialog_key = :dialogKey AND message_id = :messageId"
|
||||
)
|
||||
suspend fun removePin(account: String, dialogKey: String, messageId: String)
|
||||
|
||||
/** Получить все закреплённые сообщения диалога (Flow для реактивных обновлений) */
|
||||
@Query(
|
||||
"""
|
||||
SELECT * FROM pinned_messages
|
||||
WHERE account = :account AND dialog_key = :dialogKey
|
||||
ORDER BY pinned_at DESC
|
||||
"""
|
||||
)
|
||||
fun getPinnedMessages(account: String, dialogKey: String): Flow<List<PinnedMessageEntity>>
|
||||
|
||||
/** Проверить, закреплено ли сообщение */
|
||||
@Query(
|
||||
"SELECT EXISTS(SELECT 1 FROM pinned_messages WHERE account = :account AND dialog_key = :dialogKey AND message_id = :messageId)"
|
||||
)
|
||||
suspend fun isPinned(account: String, dialogKey: String, messageId: String): Boolean
|
||||
|
||||
/** Открепить все сообщения диалога */
|
||||
@Query("DELETE FROM pinned_messages WHERE account = :account AND dialog_key = :dialogKey")
|
||||
suspend fun unpinAll(account: String, dialogKey: String): Int
|
||||
|
||||
/** Количество закреплённых сообщений в диалоге */
|
||||
@Query(
|
||||
"SELECT COUNT(*) FROM pinned_messages WHERE account = :account AND dialog_key = :dialogKey"
|
||||
)
|
||||
suspend fun getPinnedCount(account: String, dialogKey: String): Int
|
||||
}
|
||||
|
||||
/** 🔥 Data class для статуса последнего сообщения */
|
||||
data class LastMessageStatus(
|
||||
@ColumnInfo(name = "from_me") val fromMe: Int,
|
||||
|
||||
@@ -15,8 +15,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
DialogEntity::class,
|
||||
BlacklistEntity::class,
|
||||
AvatarCacheEntity::class,
|
||||
AccountSyncTimeEntity::class],
|
||||
version = 12,
|
||||
AccountSyncTimeEntity::class,
|
||||
PinnedMessageEntity::class],
|
||||
version = 13,
|
||||
exportSchema = false
|
||||
)
|
||||
abstract class RosettaDatabase : RoomDatabase() {
|
||||
@@ -26,6 +27,7 @@ abstract class RosettaDatabase : RoomDatabase() {
|
||||
abstract fun blacklistDao(): BlacklistDao
|
||||
abstract fun avatarDao(): AvatarDao
|
||||
abstract fun syncTimeDao(): SyncTimeDao
|
||||
abstract fun pinnedMessageDao(): PinnedMessageDao
|
||||
|
||||
companion object {
|
||||
@Volatile private var INSTANCE: RosettaDatabase? = null
|
||||
@@ -148,6 +150,32 @@ abstract class RosettaDatabase : RoomDatabase() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 📌 МИГРАЦИЯ 12->13: Таблица pinned_messages для закреплённых сообщений (Telegram-style)
|
||||
*/
|
||||
private val MIGRATION_12_13 =
|
||||
object : Migration(12, 13) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS pinned_messages (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
account TEXT NOT NULL,
|
||||
dialog_key TEXT NOT NULL,
|
||||
message_id TEXT NOT NULL,
|
||||
pinned_at INTEGER NOT NULL
|
||||
)
|
||||
"""
|
||||
)
|
||||
database.execSQL(
|
||||
"CREATE UNIQUE INDEX IF NOT EXISTS index_pinned_messages_account_dialog_key_message_id ON pinned_messages (account, dialog_key, message_id)"
|
||||
)
|
||||
database.execSQL(
|
||||
"CREATE INDEX IF NOT EXISTS index_pinned_messages_account_dialog_key_pinned_at ON pinned_messages (account, dialog_key, pinned_at)"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun getDatabase(context: Context): RosettaDatabase {
|
||||
return INSTANCE
|
||||
?: synchronized(this) {
|
||||
@@ -168,7 +196,8 @@ abstract class RosettaDatabase : RoomDatabase() {
|
||||
MIGRATION_8_9,
|
||||
MIGRATION_9_10,
|
||||
MIGRATION_10_11,
|
||||
MIGRATION_11_12
|
||||
MIGRATION_11_12,
|
||||
MIGRATION_12_13
|
||||
)
|
||||
.fallbackToDestructiveMigration() // Для разработки - только
|
||||
// если миграция не
|
||||
|
||||
Reference in New Issue
Block a user