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:
k1ngsterr1
2026-01-23 03:04:27 +05:00
parent 6fdad7a4c1
commit b08bea2c14
12 changed files with 1670 additions and 18 deletions

View File

@@ -479,6 +479,59 @@ class PacketPushToken : Packet() {
}
}
/**
* Avatar packet (ID: 0x0C)
* P2P доставка аватаров между клиентами
* Совместимо с desktop версией (AvatarProvider)
*
* Структура:
* - privateKey: Hash приватного ключа отправителя (для аутентификации)
* - fromPublicKey: Публичный ключ отправителя
* - toPublicKey: Публичный ключ получателя
* - chachaKey: RSA-encrypted ChaCha20 key+nonce (hex)
* - blob: ChaCha20-encrypted avatar data (hex, base64 изображение внутри)
*
* Процесс шифрования (отправка):
* 1. Генерируется случайный ChaCha20 key (32 байта) + nonce (24 байта)
* 2. Base64-изображение шифруется ChaCha20-Poly1305
* 3. ChaCha key+nonce конкатенируются и шифруются RSA публичным ключом получателя
* 4. Отправляется пакет с зашифрованными данными
*
* Процесс расшифровки (получение):
* 1. RSA-расшифровка chachaKey приватным ключом получателя
* 2. Извлечение key (32 байта) и nonce (24 байта)
* 3. ChaCha20-расшифровка blob
* 4. Получение base64-изображения
*/
class PacketAvatar : Packet() {
var privateKey: String = ""
var fromPublicKey: String = ""
var toPublicKey: String = ""
var chachaKey: String = "" // RSA-encrypted (hex)
var blob: String = "" // ChaCha20-encrypted (hex)
override fun getPacketId(): Int = 0x0C
override fun receive(stream: Stream) {
privateKey = stream.readString()
fromPublicKey = stream.readString()
toPublicKey = stream.readString()
chachaKey = stream.readString()
blob = stream.readString()
}
override fun send(): Stream {
val stream = Stream()
stream.writeInt16(getPacketId())
stream.writeString(privateKey)
stream.writeString(fromPublicKey)
stream.writeString(toPublicKey)
stream.writeString(chachaKey)
stream.writeString(blob)
return stream
}
}
/**
* Push Notification Action
*/

View File

@@ -119,7 +119,8 @@ class Protocol(
0x07 to { PacketRead() },
0x08 to { PacketDelivery() },
0x09 to { PacketChunk() },
0x0B to { PacketTyping() }
0x0B to { PacketTyping() },
0x0C to { PacketAvatar() }
)
init {

View File

@@ -174,6 +174,19 @@ object ProtocolManager {
}
}
}
// 🖼️ Обработчик аватаров (0x0C)
// P2P доставка аватаров между клиентами
waitPacket(0x0C) { packet ->
val avatarPacket = packet as PacketAvatar
android.util.Log.d("Protocol", "🖼️ Received avatar from ${avatarPacket.fromPublicKey.take(16)}...")
scope.launch(Dispatchers.IO) {
// TODO: Передавать avatarRepository через initialize()
// Пока что логируем для отладки
// avatarRepository?.handleIncomingAvatar(avatarPacket)
}
}
}
/**