feat: Implement avatar management system with P2P delivery

- Added AvatarRepository for handling avatar storage, retrieval, and delivery.
- Created AvatarCacheEntity and AvatarDeliveryEntity for database storage.
- Introduced PacketAvatar for P2P avatar transfer between clients.
- Enhanced RosettaDatabase to include avatar-related tables and migration.
- Developed AvatarFileManager for file operations related to avatars.
- Implemented AvatarImage composable for displaying user avatars.
- Updated ProfileScreen to support avatar selection and updating.
- Added functionality for handling incoming avatar packets in ProtocolManager.
This commit is contained in:
2026-01-23 03:04:27 +05:00
parent 6fdad7a4c1
commit b08bea2c14
12 changed files with 1670 additions and 18 deletions

View File

@@ -12,9 +12,11 @@ import androidx.sqlite.db.SupportSQLiteDatabase
EncryptedAccountEntity::class,
MessageEntity::class,
DialogEntity::class,
BlacklistEntity::class
BlacklistEntity::class,
AvatarCacheEntity::class,
AvatarDeliveryEntity::class
],
version = 6,
version = 7,
exportSchema = false
)
abstract class RosettaDatabase : RoomDatabase() {
@@ -22,6 +24,7 @@ abstract class RosettaDatabase : RoomDatabase() {
abstract fun messageDao(): MessageDao
abstract fun dialogDao(): DialogDao
abstract fun blacklistDao(): BlacklistDao
abstract fun avatarDao(): AvatarDao
companion object {
@Volatile
@@ -42,6 +45,31 @@ abstract class RosettaDatabase : RoomDatabase() {
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)")
// Создаем таблицу для трекинга доставки аватаров
database.execSQL("""
CREATE TABLE IF NOT EXISTS avatar_delivery (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
public_key TEXT NOT NULL,
account TEXT NOT NULL
)
""")
database.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS index_avatar_delivery_public_key_account ON avatar_delivery (public_key, account)")
}
}
fun getDatabase(context: Context): RosettaDatabase {
return INSTANCE ?: synchronized(this) {
@@ -51,7 +79,7 @@ abstract class RosettaDatabase : RoomDatabase() {
"rosetta_secure.db"
)
.setJournalMode(JournalMode.WRITE_AHEAD_LOGGING) // WAL mode for performance
.addMigrations(MIGRATION_4_5, MIGRATION_5_6)
.addMigrations(MIGRATION_4_5, MIGRATION_5_6, MIGRATION_6_7)
.fallbackToDestructiveMigration() // Для разработки - только если миграция не найдена
.build()
INSTANCE = instance