Refactor SwipeBackContainer for improved performance and readability
- Added lazy composition to skip setup until the screen is first opened, reducing allocations. - Cleaned up code formatting for better readability. - Enhanced comments for clarity on functionality. - Streamlined gesture handling logic for swipe detection and animation.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -8,15 +8,15 @@ import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
@Database(
|
||||
entities = [
|
||||
EncryptedAccountEntity::class,
|
||||
MessageEntity::class,
|
||||
DialogEntity::class,
|
||||
BlacklistEntity::class,
|
||||
AvatarCacheEntity::class
|
||||
],
|
||||
version = 10,
|
||||
exportSchema = false
|
||||
entities =
|
||||
[
|
||||
EncryptedAccountEntity::class,
|
||||
MessageEntity::class,
|
||||
DialogEntity::class,
|
||||
BlacklistEntity::class,
|
||||
AvatarCacheEntity::class],
|
||||
version = 11,
|
||||
exportSchema = false
|
||||
)
|
||||
abstract class RosettaDatabase : RoomDatabase() {
|
||||
abstract fun accountDao(): AccountDao
|
||||
@@ -26,93 +26,140 @@ abstract class RosettaDatabase : RoomDatabase() {
|
||||
abstract fun avatarDao(): AvatarDao
|
||||
|
||||
companion object {
|
||||
@Volatile
|
||||
private var INSTANCE: RosettaDatabase? = null
|
||||
|
||||
private val MIGRATION_4_5 = object : Migration(4, 5) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
// Добавляем новые столбцы для индикаторов прочтения
|
||||
database.execSQL("ALTER TABLE dialogs ADD COLUMN last_message_from_me INTEGER NOT NULL DEFAULT 0")
|
||||
database.execSQL("ALTER TABLE dialogs ADD COLUMN last_message_delivered INTEGER NOT NULL DEFAULT 0")
|
||||
database.execSQL("ALTER TABLE dialogs ADD COLUMN last_message_read INTEGER NOT NULL DEFAULT 0")
|
||||
}
|
||||
}
|
||||
|
||||
private val MIGRATION_5_6 = object : Migration(5, 6) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
// Добавляем поле username в encrypted_accounts
|
||||
database.execSQL("ALTER TABLE encrypted_accounts ADD COLUMN username TEXT")
|
||||
}
|
||||
}
|
||||
|
||||
private val MIGRATION_6_7 = object : Migration(6, 7) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
// Создаем таблицу для кэша аватаров
|
||||
database.execSQL("""
|
||||
@Volatile private var INSTANCE: RosettaDatabase? = null
|
||||
|
||||
private val MIGRATION_4_5 =
|
||||
object : Migration(4, 5) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
// Добавляем новые столбцы для индикаторов прочтения
|
||||
database.execSQL(
|
||||
"ALTER TABLE dialogs ADD COLUMN last_message_from_me INTEGER NOT NULL DEFAULT 0"
|
||||
)
|
||||
database.execSQL(
|
||||
"ALTER TABLE dialogs ADD COLUMN last_message_delivered INTEGER NOT NULL DEFAULT 0"
|
||||
)
|
||||
database.execSQL(
|
||||
"ALTER TABLE dialogs ADD COLUMN last_message_read INTEGER NOT NULL DEFAULT 0"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private val MIGRATION_5_6 =
|
||||
object : Migration(5, 6) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
// Добавляем поле username в encrypted_accounts
|
||||
database.execSQL("ALTER TABLE encrypted_accounts ADD COLUMN username TEXT")
|
||||
}
|
||||
}
|
||||
|
||||
private val MIGRATION_6_7 =
|
||||
object : Migration(6, 7) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
// Создаем таблицу для кэша аватаров
|
||||
database.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS avatar_cache (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
public_key TEXT NOT NULL,
|
||||
avatar TEXT NOT NULL,
|
||||
timestamp INTEGER NOT NULL
|
||||
)
|
||||
""")
|
||||
database.execSQL("CREATE INDEX IF NOT EXISTS index_avatar_cache_public_key_timestamp ON avatar_cache (public_key, timestamp)")
|
||||
}
|
||||
}
|
||||
|
||||
private val MIGRATION_7_8 = object : Migration(7, 8) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
// Удаляем таблицу avatar_delivery (больше не нужна)
|
||||
database.execSQL("DROP TABLE IF EXISTS avatar_delivery")
|
||||
}
|
||||
}
|
||||
|
||||
"""
|
||||
)
|
||||
database.execSQL(
|
||||
"CREATE INDEX IF NOT EXISTS index_avatar_cache_public_key_timestamp ON avatar_cache (public_key, timestamp)"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private val MIGRATION_7_8 =
|
||||
object : Migration(7, 8) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
// Удаляем таблицу avatar_delivery (больше не нужна)
|
||||
database.execSQL("DROP TABLE IF EXISTS avatar_delivery")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 🔥 МИГРАЦИЯ 8->9: Очищаем blob из attachments (как в desktop)
|
||||
* Blob слишком большой для SQLite CursorWindow (2MB лимит)
|
||||
* Просто обнуляем attachments - изображения перескачаются с CDN
|
||||
* 🔥 МИГРАЦИЯ 8->9: Очищаем blob из attachments (как в desktop) Blob слишком большой для
|
||||
* SQLite CursorWindow (2MB лимит) Просто обнуляем attachments - изображения перескачаются с
|
||||
* CDN
|
||||
*/
|
||||
private val MIGRATION_8_9 = object : Migration(8, 9) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
// Очищаем все attachments с большими blob'ами
|
||||
// Они будут перескачаны с CDN при открытии
|
||||
database.execSQL("""
|
||||
private val MIGRATION_8_9 =
|
||||
object : Migration(8, 9) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
// Очищаем все attachments с большими blob'ами
|
||||
// Они будут перескачаны с CDN при открытии
|
||||
database.execSQL(
|
||||
"""
|
||||
UPDATE messages
|
||||
SET attachments = '[]'
|
||||
WHERE length(attachments) > 10000
|
||||
""")
|
||||
}
|
||||
}
|
||||
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 🔥 МИГРАЦИЯ 9->10: Повторная очистка blob из attachments
|
||||
* Для пользователей которые уже были на версии 9
|
||||
* 🔥 МИГРАЦИЯ 9->10: Повторная очистка blob из attachments Для пользователей которые уже
|
||||
* были на версии 9
|
||||
*/
|
||||
private val MIGRATION_9_10 = object : Migration(9, 10) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
// Очищаем все attachments с большими blob'ами
|
||||
database.execSQL("""
|
||||
private val MIGRATION_9_10 =
|
||||
object : Migration(9, 10) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
// Очищаем все attachments с большими blob'ами
|
||||
database.execSQL(
|
||||
"""
|
||||
UPDATE messages
|
||||
SET attachments = '[]'
|
||||
WHERE length(attachments) > 10000
|
||||
""")
|
||||
}
|
||||
}
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 🚀 МИГРАЦИЯ 10->11: Денормализация — кэш attachments последнего сообщения в dialogs
|
||||
* Устраняет N+1 проблему: ранее для каждого диалога делался отдельный запрос к messages
|
||||
*/
|
||||
private val MIGRATION_10_11 =
|
||||
object : Migration(10, 11) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
// Добавляем столбец для кэша attachments последнего сообщения
|
||||
database.execSQL(
|
||||
"ALTER TABLE dialogs ADD COLUMN last_message_attachments TEXT NOT NULL DEFAULT '[]'"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun getDatabase(context: Context): RosettaDatabase {
|
||||
return INSTANCE ?: synchronized(this) {
|
||||
val instance = Room.databaseBuilder(
|
||||
context.applicationContext,
|
||||
RosettaDatabase::class.java,
|
||||
"rosetta_secure.db"
|
||||
)
|
||||
.setJournalMode(JournalMode.WRITE_AHEAD_LOGGING) // WAL mode for performance
|
||||
.addMigrations(MIGRATION_4_5, MIGRATION_5_6, MIGRATION_6_7, MIGRATION_7_8, MIGRATION_8_9, MIGRATION_9_10)
|
||||
.fallbackToDestructiveMigration() // Для разработки - только если миграция не найдена
|
||||
.build()
|
||||
INSTANCE = instance
|
||||
instance
|
||||
}
|
||||
return INSTANCE
|
||||
?: synchronized(this) {
|
||||
val instance =
|
||||
Room.databaseBuilder(
|
||||
context.applicationContext,
|
||||
RosettaDatabase::class.java,
|
||||
"rosetta_secure.db"
|
||||
)
|
||||
.setJournalMode(
|
||||
JournalMode.WRITE_AHEAD_LOGGING
|
||||
) // WAL mode for performance
|
||||
.addMigrations(
|
||||
MIGRATION_4_5,
|
||||
MIGRATION_5_6,
|
||||
MIGRATION_6_7,
|
||||
MIGRATION_7_8,
|
||||
MIGRATION_8_9,
|
||||
MIGRATION_9_10,
|
||||
MIGRATION_10_11
|
||||
)
|
||||
.fallbackToDestructiveMigration() // Для разработки - только
|
||||
// если миграция не
|
||||
// найдена
|
||||
.build()
|
||||
INSTANCE = instance
|
||||
instance
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user