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:
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user