diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000000000000000000000000000000000000..713686c3887249af92040d13f067198fe10ec161
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+radio2
\ No newline at end of file
diff --git a/.idea/AndroidProjectSystem.xml b/.idea/AndroidProjectSystem.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4a53bee8cb948a6e677a1a320d0ecfbe26d4062e
--- /dev/null
+++ b/.idea/AndroidProjectSystem.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="AndroidProjectSystem">
+    <option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml
index 545740a654bc72f4e98998fdfe9c657cb0248e56..2bba3d39194e864580b1a25f1a94c54852be8482 100644
--- a/.idea/deploymentTargetSelector.xml
+++ b/.idea/deploymentTargetSelector.xml
@@ -4,7 +4,7 @@
     <selectionStates>
       <SelectionState runConfigName="app">
         <option name="selectionMode" value="DROPDOWN" />
-        <DropdownSelection timestamp="2025-01-16T11:45:29.800994600Z">
+        <DropdownSelection timestamp="2025-03-24T15:09:15.860193100Z">
           <Target type="DEFAULT_BOOT">
             <handle>
               <DeviceId pluginId="PhysicalDevice" identifier="serial=R58R84SRAZX" />
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c9b1536a6bae0f38a046f0562d246adc835aed54
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,5 @@
+<project version="4">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/build/classes" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 4e595641e6c287342877b35407595987399c176f..22a6be9698b639175bf34bc77ce64a106999b863 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -50,6 +50,7 @@ android {
 }
 val ktor_version = "3.0.1"
 dependencies {
+
     implementation(libs.androidx.core.ktx)
     implementation(libs.androidx.appcompat)
     implementation(libs.material)
@@ -92,4 +93,5 @@ dependencies {
     implementation("com.google.code.gson:gson:2.10.1")
     implementation("androidx.room:room-runtime:2.6.1")
     ksp ("androidx.room:room-compiler:2.6.1")
+    implementation ("androidx.room:room-runtime:2.4.2")
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/example/radio2/AppDatabase.kt b/app/src/main/java/com/example/radio2/AppDatabase.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c4d1852801b2218b426d962c58d5d17e6978d4b7
--- /dev/null
+++ b/app/src/main/java/com/example/radio2/AppDatabase.kt
@@ -0,0 +1,74 @@
+package com.example.radio2
+
+import androidx.room.Database
+import androidx.room.Room
+import androidx.room.RoomDatabase
+import android.content.Context
+import androidx.room.Dao
+import androidx.room.Entity
+import androidx.room.Insert
+import androidx.room.OnConflictStrategy
+import androidx.room.PrimaryKey
+import androidx.room.Query
+
+// Определение сущности Chat
+@Entity(tableName = "Chats")
+data class Chat(
+    @PrimaryKey val id: Long,
+    val title: String
+)
+
+// Определение сущности Message
+@Entity(tableName = "Messages")
+data class Message(
+    @PrimaryKey(autoGenerate = true) val id: Long = 0,
+    val chatId: Long,
+    val text: String
+)
+
+// DAO для работы с чатами
+@Dao
+interface ChatDao {
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insertChat(chat: Chat)
+
+    @Query("SELECT * FROM Chats WHERE id = :chatId LIMIT 1")
+    suspend fun getChatById(chatId: Long): Chat?
+
+    @Query("SELECT * FROM Chats WHERE title = :title LIMIT 1")
+    suspend fun getChatByTitle(title: String): Chat?
+}
+
+// DAO для работы с сообщениями
+@Dao
+interface MessageDao {
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insertMessage(message: Message)
+
+    @Query("SELECT * FROM Messages WHERE chatId = :chatId")
+    suspend fun getMessagesForChat(chatId: Long): List<Message>
+}
+
+// База данных
+@Database(entities = [Chat::class, Message::class], version = 1, exportSchema = false)
+abstract class AppDatabase : RoomDatabase() {
+    abstract fun chatDao(): ChatDao
+    abstract fun messageDao(): MessageDao
+
+    companion object {
+        @Volatile
+        private var INSTANCE: AppDatabase? = null
+
+        fun getDatabase(context: Context): AppDatabase {
+            return INSTANCE ?: synchronized(this) {
+                val instance = Room.databaseBuilder(
+                    context.applicationContext,
+                    AppDatabase::class.java,
+                    "chat_database"
+                ).build()
+                INSTANCE = instance
+                instance
+            }
+        }
+    }
+}
diff --git a/app/src/main/java/com/example/radio2/ChatActivity.kt b/app/src/main/java/com/example/radio2/ChatActivity.kt
index f3917ba440dd139a489222c7b213dcacee912c4c..29d9d175d3178f30f4a569db652cd7b5fe2f1f7c 100644
--- a/app/src/main/java/com/example/radio2/ChatActivity.kt
+++ b/app/src/main/java/com/example/radio2/ChatActivity.kt
@@ -1,10 +1,12 @@
 package com.example.radio2
 
+import android.annotation.SuppressLint
 import android.content.*
 import android.os.*
 import android.util.Log
 import android.view.KeyEvent
 import android.view.MenuItem
+import android.view.MotionEvent
 import android.view.inputmethod.EditorInfo
 import android.widget.Button
 import android.widget.TextView
@@ -13,24 +15,32 @@ import androidx.appcompat.app.AppCompatActivity
 import androidx.lifecycle.lifecycleScope
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
+import androidx.room.Room
 import com.example.radio2.Data.userDataStorage
-import com.example.radio2.com.example.radio2.AppDatabase
-import com.example.radio2.com.example.radio2.ChatRepository
+import com.example.radio2.AppDatabase
+import com.example.radio2.ChatRepository
 import com.example.radio2.service.WebSocketService
+import com.example.radio2.Rtp.AudioProcessor
+import com.example.radio2.Rtp.VoicePacketSender
 import com.google.android.material.textfield.TextInputEditText
+import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import java.security.MessageDigest
 
-class ChatActivity : AppCompatActivity() {
+class ChatActivity : AppCompatActivity(), VoicePacketSender {
+    private lateinit var chatRepository: ChatRepository
     private var webSocketService: WebSocketService? = null
     private lateinit var chatAdapter: ChatAdapter
     private val messages = mutableListOf<MessageTo>()
     private lateinit var recyclerView: RecyclerView
     private lateinit var messageInput: TextInputEditText
-    private lateinit var sharedPreferences: SharedPreferences
-    private lateinit var database: AppDatabase
-    private lateinit var chatRepository: ChatRepository
-    private var chatId: String? = null  // chatId теперь строка
-    private var userId: String? = null  // userId теперь строка
+    private lateinit var audioProcessor: AudioProcessor
+    private var isPttStarted = false
+
+    private var chatId: Long? = null
+    private var userId: Long? = null
+    private var selectedUserId: String? = null
 
     private val connection = object : ServiceConnection {
         override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
@@ -39,7 +49,6 @@ class ChatActivity : AppCompatActivity() {
             webSocketService?.setCurrentActivity(this@ChatActivity)
         }
 
-
         override fun onServiceDisconnected(name: ComponentName?) {
             webSocketService = null
         }
@@ -50,18 +59,7 @@ class ChatActivity : AppCompatActivity() {
         Intent(this, WebSocketService::class.java).also { intent ->
             bindService(intent, connection, BIND_AUTO_CREATE)
         }
-        val database = AppDatabase.getInstance(this)
-        chatRepository = ChatRepository(
-            userDao = database.userDao(),
-            chatDao = database.chatDao(),
-            chatMemberDao = database.chatMemberDao(),
-            messageDao = database.messageDao()
-        )
-
-        // Загрузка истории чата
-        getMessagesForChat()
-
-        // Загружаем данные пользователя и чата
+
         loadUserData()
     }
 
@@ -70,27 +68,56 @@ class ChatActivity : AppCompatActivity() {
         unbindService(connection)
     }
 
+    @SuppressLint("ClickableViewAccessibility")
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         supportActionBar?.setDisplayHomeAsUpEnabled(true)
         setContentView(R.layout.activity_chat)
-
+        val db = Room.databaseBuilder(applicationContext, AppDatabase::class.java, "chat_database").build()
+        chatRepository = ChatRepository(db)
         recyclerView = findViewById(R.id.recycler_message)
         messageInput = findViewById<TextInputEditText>(R.id.et_chat)
 
         val userId = intent.getStringExtra("USER_ID")
-        val userName = intent.getStringExtra("USER_NAME")
+        val userName = intent.getStringExtra("USER_NAME")?: "Default User"
         if (userName != null && userId != null) {
+            selectedUserId = userId
             loadChat(userId, userName)
         }
 
-
         recyclerView.layoutManager = LinearLayoutManager(this)
         chatAdapter = ChatAdapter(this, messages)
         recyclerView.adapter = chatAdapter
 
         val sendMessageButton = findViewById<Button>(R.id.button)
         val backButton = findViewById<Button>(R.id.backButton)
+        val activateVoiceButton = findViewById<Button>(R.id.activateVoice2)
+
+        audioProcessor = AudioProcessor(this, this)
+
+        activateVoiceButton.setOnTouchListener { view, event ->
+            when (event.action) {
+                MotionEvent.ACTION_DOWN -> {
+                    if (!isPttStarted) {
+                        isPttStarted = true
+                        selectedUserId?.let { userId ->
+                            webSocketService?.startPTT(userId, "User")
+                        }
+                    }
+                    audioProcessor.startRecording()
+                    true
+                }
+                MotionEvent.ACTION_UP -> {
+                    isPttStarted = false
+                    audioProcessor.stopRecording()
+                    selectedUserId?.let { userId ->
+                        webSocketService?.stopPTT(userId, "User")
+                    }
+                    true
+                }
+                else -> false
+            }
+        }
 
         backButton.setOnClickListener {
             finish()
@@ -113,86 +140,99 @@ class ChatActivity : AppCompatActivity() {
     private fun loadUserData() {
         lifecycleScope.launch {
             try {
-                // Получаем текущего пользователя
-                val userIdString = userDataStorage.userId  // Получаем userId как строку
-                if (userIdString.isNullOrBlank()) {
-                    Log.e("ChatActivity", "Ошибка: userId не найден или пуст")
-                    return@launch
-                }
-
-                userId = userIdString  // userId теперь строка
-                Log.d("ChatActivity", "Успешно получен userId: $userId")
-
-                // Получаем ID чата
-                chatId = getChatIdForUser(userId!!)
-                if (chatId.isNullOrBlank()) {
-                    Log.e("ChatActivity", "Ошибка: chatId не найден для userId: $userId")
-                    return@launch
+                val userName = intent.getStringExtra("USER_NAME") ?: "Неизвестный пользователь"
+                userId = intent.getLongExtra("USER_ID", 0) // Получаем userId из Intent
+
+                // Проверяем наличие чата и создаем его, если необходимо
+                chatId = chatRepository.getChatForUser (userId!!) ?: run {
+                    // Создаем новый чат
+                    val newChat = Chat(id = System.currentTimeMillis(), title = userName) // Используем текущее время как уникальный ID
+                    chatRepository.insertChat(newChat)
+                    newChat.id // Возвращаем ID нового чата
                 }
 
                 Log.d("ChatActivity", "Успешно получен chatId: $chatId")
 
-                val userName = getUserName(userId!!)
-                Log.d("ChatActivity", "Получено имя пользователя: $userName")
-
-                loadChat(userId!!, userName)
+                loadChat(userId!!.toString(), userName)
                 getMessagesForChat()
 
-                // Логирование базы данных
-                logAllUsers()
-                logAllChats()
-
             } catch (e: Exception) {
                 Log.e("ChatActivity", "Ошибка при загрузке данных: ${e.message}")
             }
         }
     }
 
-    private suspend fun getChatIdForUser(userId: String): String? {
-        return chatRepository.getChatForUser(userId)
+    private fun loadChat(userId: String, userName: String) {
+        lifecycleScope.launch {
+            // Генерация ID чата на основе имени пользователя
+            val chatId = generateChatId(userName)
+            val chat = chatRepository.getChatById(chatId)
+
+            if (chat != null) {
+                // Если чат существует, загружаем сообщения
+                loadMessages(chat.id)
+                Log.d("ChatActivity", "Успешно получен chatId: $chatId")
+            } else {
+                // Если чат не существует, создаем новый чат
+                chatRepository.createChat(chatId, userName)
+            }
+
+            // Установка имени пользователя
+            val name = findViewById<TextView>(R.id.userName)
+            name.text = userName
+            Log.d("ChatActivity", "установлен chatId: $chatId")
+        }
+    }
+
+    private suspend fun loadMessages(chatId: Long) {
+        withContext(Dispatchers.IO) {
+            val messages = chatRepository.getMessagesForChat(chatId)
+            messages.forEach { message ->
+                addReceivedMessage(message.text) // Предполагается, что вы добавите этот метод
+            }
+        }
     }
 
-    private suspend fun getUserName(userId: String): String {
-        return chatRepository.getUserName(userId) ?: "Неизвестный пользователь"
+    private fun generateChatId(userName: String): Long {
+        // Генерация хэш-значения на основе имени пользователя
+        val bytes = MessageDigest.getInstance("SHA-256").digest(userName.toByteArray())
+        return bytes.fold(0L) { acc, byte -> acc * 31 + byte }
     }
 
-    private fun loadChat(userId: String, userName: String) {
-        val name = findViewById<TextView>(R.id.userName)
-        name.text = userName
+    private suspend fun getMessagesForChat() {
+        chatId?.let {
+            val messagesList = chatRepository.getMessagesForChat(it)
+            messages.clear()
+            messages.addAll(messagesList.map { msg -> MessageTo(msg.text, MessageType.RECEIVED) })
+            chatAdapter.notifyDataSetChanged()
+        }
     }
 
     private fun sendMessage() {
         val text = messageInput.text.toString().trim()
         if (text.isNotEmpty()) {
             addUserMessage(text)
-            webSocketService?.sendMessage(text, "0", "23", "0", "test", "test", "0")
+
+
+//            webSocketService?.sendMessage(
+//
+//                text,
+//                userId ?: "0",
+//                chatId ?: "0",
+//                "0",
+//                "test",
+//                "test",
+//                "0"
+//            )
+
+
             messageInput.hint = "Message"
             messageInput.text = null
         } else {
             messageInput.hint = "Enter Message"
         }
     }
-    private fun getMessagesForChat() {
-        lifecycleScope.launch {
-            val currentUserId = userId
-            val currentChatId = chatId
-
-            if (currentUserId != null && currentChatId != null) {
-                try {
-                    val chatMessages =
-                        chatRepository.getMessagesForChat(currentChatId, currentUserId)
-                    messages.clear()
-                    messages.addAll(chatMessages.map { MessageTo(it.text, MessageType.RECEIVED) })
-                    chatAdapter.notifyDataSetChanged()
-                    recyclerView.scrollToPosition(messages.size - 1)
-                } catch (e: Exception) {
-                    Log.e("ChatActivity", "Ошибка при загрузке сообщений: ${e.message}")
-                }
-            } else {
-                Log.e("ChatActivity", "Ошибка: userId или chatId не инициализированы")
-            }
-        }
-    }
+
     private fun addUserMessage(message: String) {
         messages.add(MessageTo(message, MessageType.SENT))
         chatAdapter.notifyItemInserted(messages.size - 1)
@@ -200,151 +240,24 @@ class ChatActivity : AppCompatActivity() {
         messageInput.setText("")
     }
 
-    private fun logAllUsers() {
-        lifecycleScope.launch {
-            val users = chatRepository.getAllUsers()
-            if (users.isEmpty()) {
-                Log.d("Database", "В базе данных нет пользователей")
-            } else {
-                users.forEach { user ->
-                    Log.d("Database", "User: id=${user.id}, name=${user.username}")
-                }
-            }
-        }
-    }
-
-    private fun logAllChats() {
-        lifecycleScope.launch {
-            val chats = chatRepository.getAllChats()
-            if (chats.isEmpty()) {
-                Log.d("Database", "В базе данных нет чатов")
-            } else {
-                chats.forEach { chat ->
-                    Log.d("Database", "Chat: id=${chat.id}, title=${chat.title}")
-                }
-            }
-        }
-    }
-
-//        val editor = otherChatsPreferences.edit()
-//        val key = "messages_$senderName"
-//        Log.d("chat_prefs2", "Сохраняем для: $key, $senderName")
-//
-//
-//        val existingMessages = otherChatsPreferences.getString(key, "") ?: ""
-//        val updatedMessages = if (existingMessages.isNotEmpty()) {
-//            "$existingMessages,$message"
-//        } else {
-//            message
-//        }
-//
-//        editor.putString(key, updatedMessages)
-//        editor.apply()
-//    }
-    //private fun loadMessages() {
-
-        //val userName = intent.getStringExtra("USER_NAME") ?: return
-        //val key = "messages_$userName"
-//        uploadLoadMessages(key)
-        //val savedMessages = currentChatPreferences.getString(key, "")
-        //savedMessages?.let {
-           // if (it.isNotEmpty()) {
-                //val loadedMessages = it.split(",").map { msg ->
-                    //val parts = msg.split(":")
-//                    if (parts.size == 2) {
-                      //  val type = MessageType.valueOf(parts[0])
-                    //    val text = parts[1]
-                  //      MessageTo(text, type)
-//                    } else null
-                //}
-
-              //  messages.clear()
-            //    messages.addAll(loadedMessages)
-
-          //  }
-        //}
-
-       // chatAdapter.setList(messages)
-        //chatAdapter.notifyItemInserted(messages.size - 1)
-      //  recyclerView.scrollToPosition(messages.size - 1)
-    //}
-
-  //  private fun uploadLoadMessages(key: String) {
-
-        //val serializedMessages = otherChatsPreferences.getString(key, "")
-        //serializedMessages?.let {
-            //if (it.isNotEmpty()) {
-               // val loadedMessages = it.split(",").map { msg ->
-                    //val parts = msg.split(":")
-                    //val type = MessageType.valueOf(parts[0])
-                  //  val text = parts[1]
-                //    MessageTo(text, type)
-
-              //  }
-            //
-          //      }
-        //    }
-      //  }
-
-//        val otherMessages = otherChatsPreferences.getStringSet(key, emptySet()) ?: emptySet()
-//
-//        // Сохранение сообщений в текущем чате
-//        val currentMessages = currentChatPreferences.getStringSet(key, mutableSetOf()) ?: mutableSetOf()
-//        currentMessages.addAll(otherMessages)
-//
-//        // Сохранение обновленных сообщений в текущем чате
-//        currentChatPreferences.edit().putStringSet(key, currentMessages).apply()
-
-//        removeData(key)
-
-
-//    private fun removeData(key: String) {
-//        otherChatsPreferences.edit().remove(key).apply()
-//    }
     override fun onOptionsItemSelected(item: MenuItem): Boolean {
         return when (item.itemId) {
             android.R.id.home -> {
                 finish()
                 true
             }
+
             else -> super.onOptionsItemSelected(item)
         }
     }
 
-
-
-//    fun addReceived1Message(message: String) {messages.add(MessageTo(message, MessageType.RECEIVED))}
-    fun addReceivedMessage(message: String ) {
-//        val selectedUserName = intent.getStringExtra("USER_NAME")?: return
-//        Log.d("chat_prefs3", "Received message from $senderName: $message")
-    //            addReceived1Message(message)
-
-//        if (selectedUserName == senderName) {
-
-            messages.add(MessageTo(message, MessageType.RECEIVED))
-            chatAdapter.notifyItemInserted(messages.size - 1)
-            recyclerView.scrollToPosition(messages.size - 1)
-//            saveMessages()
-//            Log.d("chat_prefs2",  "Added message to current chat: $message")
-
-
-//        }
-
-//        else {
-//            otherSaveMessages(senderName)
-//            Log.d("chat_prefs3",  "???: $message")
-//        }
-
-
-    }
-//    fun addUser1Message(message: String) {messages.add(MessageTo(message, MessageType.SENT))}
-//    fun addUserMessage(message: String) {
-//
-////        addUser1Message(message)
-//        messages.add(MessageTo(message, MessageType.SENT))
-//        chatAdapter.notifyItemInserted(messages.size - 1)
-//        recyclerView.scrollToPosition(messages.size - 1)
-//        messageInput.setText("")
-//        saveMessages()
+    fun addReceivedMessage(message: String) {
+        messages.add(MessageTo(message, MessageType.RECEIVED))
+        chatAdapter.notifyItemInserted(messages.size - 1)
+        recyclerView.scrollToPosition(messages.size - 1)
     }
 
+    override fun sendVoicePacket(base64Str: String) {
+        webSocketService?.sendVoicePacket(base64Str)
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/radio2/ChatRepository.kt b/app/src/main/java/com/example/radio2/ChatRepository.kt
new file mode 100644
index 0000000000000000000000000000000000000000..f8ee8461ac8b6fdd2ddfbab1eb6b8e0fd6f17f4e
--- /dev/null
+++ b/app/src/main/java/com/example/radio2/ChatRepository.kt
@@ -0,0 +1,53 @@
+package com.example.radio2
+
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+
+class ChatRepository(private val db: AppDatabase) {
+
+    // Вставка нового чата
+    suspend fun insertChat(chat: Chat) {
+        withContext(Dispatchers.IO) {
+            db.chatDao().insertChat(chat)
+        }
+    }
+
+    // Получение чата по ID
+    suspend fun getChatById(chatId: Long): Chat? {
+        return withContext(Dispatchers.IO) {
+            db.chatDao().getChatById(chatId)
+        }
+    }
+
+    // Получение чата по названию
+    suspend fun getChatByTitle(title: String): Chat? {
+        return withContext(Dispatchers.IO) {
+            db.chatDao().getChatByTitle(title)
+        }
+    }
+
+    // Вставка нового сообщения
+    suspend fun insertMessage(message: Message) {
+        withContext(Dispatchers.IO) {
+            db.messageDao().insertMessage(message)
+        }
+    }
+
+    // Получение сообщений для конкретного чата
+    suspend fun getMessagesForChat(chatId: Long): List<Message> {
+        return withContext(Dispatchers.IO) {
+            db.messageDao().getMessagesForChat(chatId)
+        }
+    }
+    suspend fun getChatForUser (userId: Long): Long? {
+        return withContext(Dispatchers.IO) {
+            val chat = db.chatDao().getChatByTitle(userId.toString())
+            chat?.id
+        }
+    }
+    suspend fun createChat(chatId: Long, title: String): Long {
+        val chat = Chat(id = chatId, title = title)
+        db.chatDao().insertChat(chat)
+        return chat.id
+    }
+}
diff --git a/app/src/main/java/com/example/radio2/DataBase.kt b/app/src/main/java/com/example/radio2/DataBase.kt
index fcd7af25ee19eb736954ae614a3ec109507088df..40e33df5edb3ad7973cf0e4974f0c5ee255e7f2a 100644
--- a/app/src/main/java/com/example/radio2/DataBase.kt
+++ b/app/src/main/java/com/example/radio2/DataBase.kt
@@ -1,336 +1,335 @@
-package com.example.radio2.com.example.radio2
-
-import android.content.Context
-import androidx.lifecycle.ViewModel
-import androidx.lifecycle.viewModelScope
-import androidx.room.Dao
-import androidx.room.Database
-import androidx.room.Entity
-import androidx.room.Insert
-import androidx.room.PrimaryKey
-import androidx.room.Query
-import androidx.room.ForeignKey
-import androidx.room.OnConflictStrategy
-import androidx.room.Room
-import androidx.room.RoomDatabase
-import androidx.room.migration.Migration
-import androidx.sqlite.db.SupportSQLiteDatabase
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
-import java.util.UUID
-
-// Таблица юзера
-@Entity(tableName = "users")
-data class User(
-    @PrimaryKey val id: String, // id теперь строка
-    val username: String // Название юзера
-)
-
-//Таблица с чатами
-@Entity(tableName = "chats")
-data class Chat(
-    @PrimaryKey val id: String, // chatId теперь строка
-    val title: String? = null // Название чата
-)
-
-// Таблица с участниками чата, где главные id чата и id юзера
-@Entity(
-    tableName = "chat_members",
-    primaryKeys = ["chatId", "userId"],
-    foreignKeys = [
-        ForeignKey(entity = Chat::class, parentColumns = ["id"], childColumns = ["chatId"]),
-        ForeignKey(entity = User::class, parentColumns = ["id"], childColumns = ["userId"])
-    ]
-)
-data class ChatMember(
-    val chatId: String, // chatId теперь строка
-    val userId: String  // userId теперь строка
-)
-
-@Entity(
-    tableName = "messages",
-    foreignKeys = [
-        ForeignKey(entity = Chat::class, parentColumns = ["id"], childColumns = ["chatId"])
-    ]
-)
-data class Message(
-    @PrimaryKey(autoGenerate = true) val id: Int = 0, // уникальный id сообщения
-    val chatId: String, // chatId теперь строка
-    val senderId: String, // senderId теперь строка
-    val text: String, // Сам текст
-    val timestamp: Long = System.currentTimeMillis() // Метка со временем
-)
-
-
-//Data Access Objects - управление пользователями
-@Dao
-interface UserDao {
-    @Insert
-    suspend fun insertUser(user: User): Long
-
-    @Query("SELECT * FROM users WHERE id = :userId")
-    suspend fun getUserById(userId: String): User // userId теперь строка
-
-    @Query("SELECT * FROM users")
-    suspend fun getAllUsers(): List<User>
-
-    @Query("SELECT username FROM users WHERE id = :userId LIMIT 1")
-    suspend fun getUserNameById(userId: String): String? // userId теперь строка
-}
-
-//Data Access Objects - управление чатами
-@Dao
-interface ChatDao {
-    @Insert
-    suspend fun insertChat(chat: Chat): Long
-
-    @Query("SELECT * FROM chats WHERE id = :chatId")
-    suspend fun getChatById(chatId: Int): Chat
-
-    @Query("SELECT * FROM chats")
-    suspend fun getAllChats(): List<Chat>
-}
-
-//Data Access Objects - управление юзерами чата
-@Dao
-interface ChatMemberDao {
-    @Insert
-    suspend fun addMember(chatMember: ChatMember)
-
-    @Query("""
-        SELECT * FROM chats 
-        WHERE id IN (SELECT chatId FROM chat_members WHERE userId = :userId)
-    """)
-    suspend fun getChatsForUser(userId: String): List<Chat> // userId теперь строка
-
-    @Query("""
-        SELECT * FROM users 
-        WHERE id IN (SELECT userId FROM chat_members WHERE chatId = :chatId)
-    """)
-    suspend fun getUsersInChat(chatId: String): List<User> // chatId теперь строка
-
-    @Query("SELECT chatId FROM chat_members WHERE userId = :userId LIMIT 1")
-    suspend fun getChatIdByUserId(userId: String): String? // userId теперь строка
-}
-
-//Data Access Objects - управление сообщениями
-@Dao
-interface MessageDao {
-    @Insert(onConflict = OnConflictStrategy.REPLACE)
-    suspend fun insertMessage(message: Message)
-
-    @Query("SELECT * FROM messages WHERE chatId = :chatId ORDER BY timestamp ASC")
-    suspend fun getMessagesForChat(chatId: String): List<Message> // chatId теперь строка
-}
-
-val MIGRATION_1_2 = object : Migration(1, 2) {
-    override fun migrate(database: SupportSQLiteDatabase) {
-        // Миграция для users
-        database.execSQL("""
-            CREATE TABLE IF NOT EXISTS `users_temp` (
-                `id` TEXT NOT NULL PRIMARY KEY,
-                `username` TEXT NOT NULL
-            )
-        """)
-        database.execSQL("""
-            INSERT INTO `users_temp` (`id`, `username`)
-            SELECT `id`, `username` FROM `users`
-        """)
-        database.execSQL("DROP TABLE `users`")
-        database.execSQL("ALTER TABLE `users_temp` RENAME TO `users`")
-
-        // Миграция для chats
-        database.execSQL("""
-            CREATE TABLE IF NOT EXISTS `chats_temp` (
-                `id` TEXT NOT NULL PRIMARY KEY,
-                `title` TEXT
-            )
-        """)
-        database.execSQL("""
-            INSERT INTO `chats_temp` (`id`, `title`)
-            SELECT `id`, `title` FROM `chats`
-        """)
-        database.execSQL("DROP TABLE `chats`")
-        database.execSQL("ALTER TABLE `chats_temp` RENAME TO `chats`")
-
-        // Миграция для chat_members
-        database.execSQL("""
-            CREATE TABLE IF NOT EXISTS `chat_members_temp` (
-                `chatId` TEXT NOT NULL,
-                `userId` TEXT NOT NULL,
-                PRIMARY KEY(`chatId`, `userId`),
-                FOREIGN KEY(`chatId`) REFERENCES `chats`(`id`) ON DELETE NO ACTION,
-                FOREIGN KEY(`userId`) REFERENCES `users`(`id`) ON DELETE NO ACTION
-            )
-        """)
-
-        // Копируем данные из старой таблицы в новую для chat_members
-        database.execSQL("""
-            INSERT INTO `chat_members_temp` (`chatId`, `userId`)
-            SELECT `chatId`, `userId` FROM `chat_members`
-        """)
-
-        // Удаляем старую таблицу
-        database.execSQL("DROP TABLE `chat_members`")
-
-        // Переименовываем новую таблицу в старое имя
-        database.execSQL("ALTER TABLE `chat_members_temp` RENAME TO `chat_members`")
-
-        // Миграция для messages
-        database.execSQL("""
-            CREATE TABLE IF NOT EXISTS `messages_temp` (
-                `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
-                `chatId` TEXT NOT NULL,
-                `senderId` TEXT NOT NULL,
-                `text` TEXT NOT NULL,
-                `timestamp` INTEGER NOT NULL,
-                FOREIGN KEY(`chatId`) REFERENCES `chats`(`id`) ON DELETE NO ACTION
-            )
-        """)
-
-        // Копируем данные из старой таблицы в новую для messages
-        database.execSQL("""
-            INSERT INTO `messages_temp` (`id`, `chatId`, `senderId`, `text`, `timestamp`)
-            SELECT `id`, `chatId`, `senderId`, `text`, `timestamp` FROM `messages`
-        """)
-
-        // Удаляем старую таблицу
-        database.execSQL("DROP TABLE `messages`")
-
-        // Переименовываем новую таблицу в старое имя
-        database.execSQL("ALTER TABLE `messages_temp` RENAME TO `messages`")
-    }
-}
-
-// Сама база данных
-@Database(entities = [User::class, Chat::class, ChatMember::class, Message::class], version = 2)
-abstract class AppDatabase : RoomDatabase() {
-    abstract fun userDao(): UserDao
-    abstract fun chatDao(): ChatDao
-    abstract fun chatMemberDao(): ChatMemberDao
-    abstract fun messageDao(): MessageDao
-
-    companion object {
-        @Volatile
-        private var INSTANCE: AppDatabase? = null
-
-        fun getInstance(context: Context): AppDatabase {
-            return INSTANCE ?: synchronized(this) {
-                val instance = Room.databaseBuilder(
-                    context.applicationContext,
-                    AppDatabase::class.java,
-                    "app_database"
-                ).build()
-                INSTANCE = instance
-                instance
-            }
-        }
-    }
-}
-
-class ChatRepository(
-    private val userDao: UserDao,
-    private val chatDao: ChatDao,
-    private val chatMemberDao: ChatMemberDao,
-    private val messageDao: MessageDao
-) {
-
-    // 1. Создать нового пользователя
-    suspend fun createUser(username: String): Long {
-        return withContext(Dispatchers.IO) {
-            val user = User(id = generateRandomId(), username = username)  // Генерация id теперь строка
-            userDao.insertUser(user)
-        }
-    }
-
-    // Создать новый чат между несколькими пользователями
-    suspend fun createChat(chatTitle: String?, userIds: List<String>): String { // chatId теперь строка
-        return withContext(Dispatchers.IO) {
-            // Делаем чат
-            val chatId = generateRandomId()  // Генерация chatId теперь строка
-
-            // Добавляем чат в базу
-            chatDao.insertChat(Chat(id = chatId, title = chatTitle))
-
-            // Добавляем юзера в чат
-            userIds.forEach { userId ->
-                chatMemberDao.addMember(ChatMember(chatId = chatId, userId = userId))
-            }
-            chatId
-        }
-    }
-
-
-    // Отправить сообщение в чат
-    suspend fun sendMessage(chatId: String, senderId: String, text: String) { // chatId и senderId теперь строки
-        withContext(Dispatchers.IO) {
-            // Проверяем, является ли отправитель юзером чата
-            val usersInChat = chatMemberDao.getUsersInChat(chatId).map { it.id }
-            if (senderId !in usersInChat) {
-                throw IllegalArgumentException("Пользователь с ID $senderId не является участником этого диалога")
-            }
-
-            // Добавить сообщение
-            messageDao.insertMessage(
-                Message(chatId = chatId, senderId = senderId, text = text)
-            )
-        }
-    }
-
-    // Получить список чатов для юзера
-    suspend fun getChatsForUser(userId: String): List<Chat> { // userId теперь строка
-        return withContext(Dispatchers.IO) {
-            chatMemberDao.getChatsForUser(userId)
-        }
-    }
-
-    // Получить сообщения для чата
-    suspend fun getMessagesForChat(chatId: String, userId: String): List<Message> { // chatId и userId теперь строки
-        return withContext(Dispatchers.IO) {
-            // Проверяем, является ли юзер участником чата
-            val usersInChat = chatMemberDao.getUsersInChat(chatId).map { it.id }
-            if (userId !in usersInChat) {
-                throw IllegalArgumentException("Пользователь с ID $userId не имеет доступа к этому чату")
-            }
-
-            // Возврат
-            messageDao.getMessagesForChat(chatId)
-        }
-    }
-
-    // Если надо добавить участника в уже существующий чат
-    suspend fun addUserToChat(chatId: String, userId: String) { // chatId и userId теперь строки
-        withContext(Dispatchers.IO) {
-            // Проверка, есть ли юзер в этом чате
-            val usersInChat = chatMemberDao.getUsersInChat(chatId).map { it.id }
-            if (userId in usersInChat) {
-                throw IllegalArgumentException("Пользователь с ID $userId уже участник чата")
-            }
-
-            // Добавление
-            chatMemberDao.addMember(ChatMember(chatId = chatId, userId = userId))
-        }
-    }
-
-    suspend fun getChatForUser(userId: String): String? { // userId теперь строка
-        return chatMemberDao.getChatIdByUserId(userId)
-    }
-
-    suspend fun getUserName(userId: String): String? { // userId теперь строка
-        return userDao.getUserNameById(userId)
-    }
-
-    suspend fun getAllUsers(): List<User> {
-        return userDao.getAllUsers()
-    }
-
-    suspend fun getAllChats(): List<Chat> {
-        return chatDao.getAllChats()
-    }
-
-    // Функция для генерации случайного строкового ID
-    fun generateRandomId(): String {
-        return UUID.randomUUID().toString()
-    }
-}
\ No newline at end of file
+//package com.example.radio2
+//
+//import android.content.Context
+//import androidx.room.Dao
+//import androidx.room.Database
+//import androidx.room.Entity
+//import androidx.room.Insert
+//import androidx.room.PrimaryKey
+//import androidx.room.Query
+//import androidx.room.ForeignKey
+//import androidx.room.OnConflictStrategy
+//import androidx.room.Room
+//import androidx.room.RoomDatabase
+//import androidx.room.migration.Migration
+//import androidx.sqlite.db.SupportSQLiteDatabase
+//import kotlinx.coroutines.Dispatchers
+//import kotlinx.coroutines.withContext
+//import java.util.UUID
+//
+//// Таблица юзера
+//@Entity(tableName = "users")
+//data class User(
+//    @PrimaryKey val id: String, // id теперь строка
+//    val username: String // Название юзера
+//)
+//
+////Таблица с чатами
+//@Entity(tableName = "chats")
+//data class Chat(
+//    @PrimaryKey val id: String, // chatId теперь строка
+//    val title: String? = null // Название чата
+//)
+//
+//// Таблица с участниками чата, где главные id чата и id юзера
+//@Entity(
+//    tableName = "chat_members",
+//    primaryKeys = ["chatId", "userId"],
+//    foreignKeys = [
+//        ForeignKey(entity = Chat::class, parentColumns = ["id"], childColumns = ["chatId"]),
+//        ForeignKey(entity = User::class, parentColumns = ["id"], childColumns = ["userId"])
+//    ]
+//)
+//data class ChatMember(
+//    val chatId: String, // chatId теперь строка
+//    val userId: String  // userId теперь строка
+//)
+//
+//@Entity(
+//    tableName = "messages",
+//    foreignKeys = [
+//        ForeignKey(entity = Chat::class, parentColumns = ["id"], childColumns = ["chatId"])
+//    ]
+//)
+//data class Message(
+//    @PrimaryKey(autoGenerate = true) val id: Int = 0, // уникальный id сообщения
+//    val chatId: String, // chatId теперь строка
+//    val senderId: String, // senderId теперь строка
+//    val text: String, // Сам текст
+//    val timestamp: Long = System.currentTimeMillis() // Метка со временем
+//)
+//
+//
+////Data Access Objects - управление пользователями
+//@Dao
+//interface UserDao {
+//    @Insert
+//    suspend fun insertUser(user: User): Long
+//
+//    @Query("SELECT * FROM users WHERE id = :userId")
+//    suspend fun getUserById(userId: String): User // userId теперь строка
+//
+//    @Query("SELECT * FROM users")
+//    suspend fun getAllUsers(): List<User>
+//
+//    @Query("SELECT username FROM users WHERE id = :userId LIMIT 1")
+//    suspend fun getUserNameById(userId: String): String? // userId теперь строка
+//}
+//
+////Data Access Objects - управление чатами
+//@Dao
+//interface ChatDao {
+//    @Insert
+//    suspend fun insertChat(chat: Chat): Long
+//
+//    @Query("SELECT * FROM chats WHERE id = :chatId")
+//    suspend fun getChatById(chatId: Int): Chat
+//
+//    @Query("SELECT * FROM chats")
+//    suspend fun getAllChats(): List<Chat>
+//}
+//
+////Data Access Objects - управление юзерами чата
+//@Dao
+//interface ChatMemberDao {
+//    @Insert
+//    suspend fun addMember(chatMember: ChatMember)
+//
+//    @Query("""
+//        SELECT * FROM chats
+//        WHERE id IN (SELECT chatId FROM chat_members WHERE userId = :userId)
+//    """)
+//    suspend fun getChatsForUser(userId: String): List<Chat> // userId теперь строка
+//
+//    @Query("""
+//        SELECT * FROM users
+//        WHERE id IN (SELECT userId FROM chat_members WHERE chatId = :chatId)
+//    """)
+//    suspend fun getUsersInChat(chatId: String): List<User> // chatId теперь строка
+//
+//    @Query("SELECT chatId FROM chat_members WHERE userId = :userId LIMIT 1")
+//    suspend fun getChatIdByUserId(userId: String): String? // userId теперь строка
+//}
+//
+////Data Access Objects - управление сообщениями
+//@Dao
+//interface MessageDao {
+//    @Insert(onConflict = OnConflictStrategy.REPLACE)
+//    suspend fun insertMessage(message: Message)
+//
+//    @Query("SELECT * FROM messages WHERE chatId = :chatId ORDER BY timestamp ASC")
+//    suspend fun getMessagesForChat(chatId: String): List<Message> // chatId теперь строка
+//}
+//
+//val MIGRATION_1_2 = object : Migration(1, 2) {
+//    override fun migrate(database: SupportSQLiteDatabase) {
+//        // Миграция для users
+//        database.execSQL("""
+//            CREATE TABLE IF NOT EXISTS `users_temp` (
+//                `id` TEXT NOT NULL PRIMARY KEY,
+//                `username` TEXT NOT NULL
+//            )
+//        """)
+//        database.execSQL("""
+//            INSERT INTO `users_temp` (`id`, `username`)
+//            SELECT `id`, `username` FROM `users`
+//        """)
+//        database.execSQL("DROP TABLE `users`")
+//        database.execSQL("ALTER TABLE `users_temp` RENAME TO `users`")
+//
+//        // Миграция для chats
+//        database.execSQL("""
+//            CREATE TABLE IF NOT EXISTS `chats_temp` (
+//                `id` TEXT NOT NULL PRIMARY KEY,
+//                `title` TEXT
+//            )
+//        """)
+//        database.execSQL("""
+//            INSERT INTO `chats_temp` (`id`, `title`)
+//            SELECT `id`, `title` FROM `chats`
+//        """)
+//        database.execSQL("DROP TABLE `chats`")
+//        database.execSQL("ALTER TABLE `chats_temp` RENAME TO `chats`")
+//
+//        // Миграция для chat_members
+//        database.execSQL("""
+//            CREATE TABLE IF NOT EXISTS `chat_members_temp` (
+//                `chatId` TEXT NOT NULL,
+//                `userId` TEXT NOT NULL,
+//                PRIMARY KEY(`chatId`, `userId`),
+//                FOREIGN KEY(`chatId`) REFERENCES `chats`(`id`) ON DELETE NO ACTION,
+//                FOREIGN KEY(`userId`) REFERENCES `users`(`id`) ON DELETE NO ACTION
+//            )
+//        """)
+//
+//        // Копируем данные из старой таблицы в новую для chat_members
+//        database.execSQL("""
+//            INSERT INTO `chat_members_temp` (`chatId`, `userId`)
+//            SELECT `chatId`, `userId` FROM `chat_members`
+//        """)
+//
+//        // Удаляем старую таблицу
+//        database.execSQL("DROP TABLE `chat_members`")
+//
+//        // Переименовываем новую таблицу в старое имя
+//        database.execSQL("ALTER TABLE `chat_members_temp` RENAME TO `chat_members`")
+//
+//        // Миграция для messages
+//        database.execSQL("""
+//            CREATE TABLE IF NOT EXISTS `messages_temp` (
+//                `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+//                `chatId` TEXT NOT NULL,
+//                `senderId` TEXT NOT NULL,
+//                `text` TEXT NOT NULL,
+//                `timestamp` INTEGER NOT NULL,
+//                FOREIGN KEY(`chatId`) REFERENCES `chats`(`id`) ON DELETE NO ACTION
+//            )
+//        """)
+//
+//        // Копируем данные из старой таблицы в новую для messages
+//        database.execSQL("""
+//            INSERT INTO `messages_temp` (`id`, `chatId`, `senderId`, `text`, `timestamp`)
+//            SELECT `id`, `chatId`, `senderId`, `text`, `timestamp` FROM `messages`
+//        """)
+//
+//        // Удаляем старую таблицу
+//        database.execSQL("DROP TABLE `messages`")
+//
+//        // Переименовываем новую таблицу в старое имя
+//        database.execSQL("ALTER TABLE `messages_temp` RENAME TO `messages`")
+//    }
+//}
+//
+//// Сама база данных
+//@Database(entities = [User::class, Chat::class, ChatMember::class, Message::class], version = 2)
+//abstract class AppDatabase : RoomDatabase() {
+//    abstract fun userDao(): UserDao
+//    abstract fun chatDao(): ChatDao
+//    abstract fun chatMemberDao(): ChatMemberDao
+//    abstract fun messageDao(): MessageDao
+//
+//    companion object {
+//        @Volatile
+//        private var INSTANCE: AppDatabase? = null
+//
+//        fun getInstance(context: Context): AppDatabase {
+//            return INSTANCE ?: synchronized(this) {
+//                val instance = Room.databaseBuilder(
+//                    context.applicationContext,
+//                    AppDatabase::class.java,
+//                    "app_database"
+//                ).build()
+//                INSTANCE = instance
+//                instance
+//            }
+//        }
+//    }
+//}
+//
+//class ChatRepository(
+//    private val userDao: UserDao,
+//    private val chatDao: ChatDao,
+//    private val chatMemberDao: ChatMemberDao,
+//    private val messageDao: MessageDao
+//) {
+//
+//    // 1. Создать нового пользователя
+//    suspend fun createUser(username: String): Long {
+//        return withContext(Dispatchers.IO) {
+//            val user = User(id = generateRandomId(), username = username)  // Генерация id теперь строка
+//            userDao.insertUser(user)
+//        }
+//    }
+//
+//    // Создать новый чат между несколькими пользователями
+//    suspend fun createChat(chatTitle: String?,userId: String)
+//    { // chatId теперь строка
+//        return withContext(Dispatchers.IO) {
+//            // Делаем чат
+//            val chatId = generateRandomId()  // Генерация chatId теперь строка
+//
+//
+//            // Добавляем чат в базу
+//            chatDao.insertChat(Chat(id = chatId, title = chatTitle))
+//
+//            // Добавляем юзера в чат
+//
+//              chatMemberDao.addMember(ChatMember(chatId = chatId, userId = userId))
+//
+//            chatId
+//        }
+//    }
+//
+//
+//    // Отправить сообщение в чат
+//    suspend fun sendMessage(chatId: String, senderId: String, text: String) { // chatId и senderId теперь строки
+//        withContext(Dispatchers.IO) {
+//            // Проверяем, является ли отправитель юзером чата
+//            val usersInChat = chatMemberDao.getUsersInChat(chatId).map { it.id }
+//            if (senderId !in usersInChat) {
+//                throw IllegalArgumentException("Пользователь с ID $senderId не является участником этого диалога")
+//            }
+//
+//            // Добавить сообщение
+//            messageDao.insertMessage(
+//                Message(chatId = chatId, senderId = senderId, text = text)
+//            )
+//        }
+//    }
+//
+//    // Получить список чатов для юзера
+//    suspend fun getChatsForUser(userId: String): List<Chat> { // userId теперь строка
+//        return withContext(Dispatchers.IO) {
+//            chatMemberDao.getChatsForUser(userId)
+//        }
+//    }
+//
+//    // Получить сообщения для чата
+//    suspend fun getMessagesForChat(chatId: String, userId: String): List<Message> { // chatId и userId теперь строки
+//        return withContext(Dispatchers.IO) {
+//            // Проверяем, является ли юзер участником чата
+//            val usersInChat = chatMemberDao.getUsersInChat(chatId).map { it.id }
+//            if (userId !in usersInChat) {
+//                throw IllegalArgumentException("Пользователь с ID $userId не имеет доступа к этому чату")
+//            }
+//
+//            // Возврат
+//            messageDao.getMessagesForChat(chatId)
+//        }
+//    }
+//
+//    // Если надо добавить участника в уже существующий чат
+//    suspend fun addUserToChat(chatId: String, userId: String) { // chatId и userId теперь строки
+//        withContext(Dispatchers.IO) {
+//            // Проверка, есть ли юзер в этом чате
+//            val usersInChat = chatMemberDao.getUsersInChat(chatId).map { it.id }
+//            if (userId in usersInChat) {
+//                throw IllegalArgumentException("Пользователь с ID $userId уже участник чата")
+//            }
+//
+//            // Добавление
+//            chatMemberDao.addMember(ChatMember(chatId = chatId, userId = userId))
+//        }
+//    }
+//
+//    suspend fun getChatForUser(userId: String): String? { // userId теперь строка
+//        return chatMemberDao.getChatIdByUserId(userId)
+//    }
+//
+//    suspend fun getUserName(userId: String): String? { // userId теперь строка
+//        return userDao.getUserNameById(userId)
+//    }
+//
+//    suspend fun getAllUsers(): List<User> {
+//        return userDao.getAllUsers()
+//    }
+//
+//    suspend fun getAllChats(): List<Chat> {
+//        return chatDao.getAllChats()
+//    }
+//
+//    // Функция для генерации случайного строкового ID
+//    fun generateRandomId(): String {
+//        return UUID.randomUUID().toString()
+//    }
+//}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/radio2/FixDataBase.kt b/app/src/main/java/com/example/radio2/FixDataBase.kt
new file mode 100644
index 0000000000000000000000000000000000000000..f7d9f25a5966321d027445214d15e2e42e8c51af
--- /dev/null
+++ b/app/src/main/java/com/example/radio2/FixDataBase.kt
@@ -0,0 +1,84 @@
+package com.example.radio2//package com.example.radio2
+//
+//import androidx.room.Dao
+//import androidx.room.Entity
+//import androidx.room.PrimaryKey
+//import androidx.room.ForeignKey
+//import androidx.room.Insert
+//import androidx.room.Query
+//
+//
+//@Entity(tableName = "Users")
+//data class User(
+//    @PrimaryKey val id: Long,
+//    val userName: String
+//)
+//
+//
+//@Entity(tableName = "Chats")
+//data class Chat(
+//    @PrimaryKey val id: Long,
+//    val title: String
+//)
+//
+//
+//@Entity(
+//    tableName = "Chat_members",
+//    foreignKeys = [
+//        ForeignKey(entity = Chat::class, parentColumns = ["id"], childColumns = ["chatId"]),
+//        ForeignKey(entity = User::class, parentColumns = ["id"], childColumns = ["userId"])
+//    ]
+//)
+//data class ChatMember(
+//    val chatId: Long,
+//    val userId: Long
+//)
+//
+//
+//@Entity(
+//    tableName = "Message",
+//    foreignKeys = [
+//        ForeignKey(entity = Chat::class, parentColumns = ["id"], childColumns = ["chatId"]),
+//        ForeignKey(entity = User::class, parentColumns = ["id"], childColumns = ["senderId"])
+//    ]
+//)
+//data class Message(
+//    val chatId: Long,
+//    val senderId: Long,
+//    val text: String,
+//    val timestamp: Long // Можно использовать тип Date, если вы хотите
+//)
+//interface ChatDao1 {
+//    @Insert
+//    suspend fun insertChat(chat: Chat)
+//
+//    @Query("SELECT * FROM Chats WHERE id = :chatId LIMIT 1")
+//    suspend fun getChatById(chatId: Long): Chat?
+//}
+//
+//@Dao
+//interface MessageDao {
+//    @Insert
+//    suspend fun insertMessage(message: Message)
+//
+//    @Query("SELECT * FROM Message WHERE chatId = :chatId")
+//    suspend fun getMessagesForChat(chatId: Long): List<Message>
+//}
+//
+//
+//class ChatRepository(private val db: FixDataBase) {
+//
+//    suspend fun getChatByTitle(title: String): Chat? {
+//        return db.chatDao().getChatByTitle(title)
+//    }
+//
+//    suspend fun createChat(title: String): Long {
+//        val chat = Chat(id = System.currentTimeMillis(), title = title) // Используйте текущее время как ID
+//        db.chatDao().insertChat(chat)
+//        return chat.id
+//    }
+//
+//    suspend fun getMessagesForChat(chatId: Long): List<Message> {
+//        return db.messageDao().getMessagesForChat(chatId)
+//    }
+//}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/radio2/Rtp/AlawMulaw.kt b/app/src/main/java/com/example/radio2/Rtp/AlawMulaw.kt
index b37fb74f024b68a520844e96b619c2cc7db75a9e..dd9f8dea1e983f9a4c0f84c6c7cd347881c5e6ba 100644
--- a/app/src/main/java/com/example/radio2/Rtp/AlawMulaw.kt
+++ b/app/src/main/java/com/example/radio2/Rtp/AlawMulaw.kt
@@ -1,77 +1,132 @@
-package com.example.radio2.Rtp
+package org.example.radio2.Rtp
 
-class AlawMulaw {
+object AlawMulawEncoder1 {
+    private val muLawCompressTable = shortArrayOf(
+        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+        16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+        32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+        48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+        64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+        80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+        96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+        112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+        -128, -127, -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, -116, -115, -114, -113,
+        -112, -111, -110, -109, -108, -107, -106, -105, -104, -103, -102, -101, -100, -99, -98, -97,
+        -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, -86, -85, -84, -83, -82, -81,
+        -80, -79, -78, -77, -76, -75, -74, -73, -72, -71, -70, -69, -68, -67, -66, -65,
+        -64, -63, -62, -61, -60, -59, -58, -57, -56, -55, -54, -53, -52, -51, -50, -49,
+        -48, -47, -46, -45, -44, -43, -42, -41, -40, -39, -38, -37, -36, -35, -34, -33,
+        -32, -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17,
+        -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1
+    )
 
-    companion object {
-        private val k = intArrayOf(
-            1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-            6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-            7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-            7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-            7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-            7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
-        )
+    private val muLawDecompressTable = shortArrayOf(
+        -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
+        -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
+        -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
+        -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316,
+        -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
+        -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
+        -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
+        -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
+        -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
+        -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
+        -876, -844, -812, -780, -748, -716, -684, -652,
+        -620, -588, -556, -524, -492, -460, -428, -396,
+        -372, -356, -340, -324, -308, -292, -276, -260,
+        -244, -228, -212, -196, -180, -164, -148, -132,
+        -120, -112, -104, -96, -88, -80, -72, -64,
+        -56, -48, -40, -32, -24, -16, -8, 0,
+        32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
+        23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
+        15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
+        11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
+        7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
+        5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
+        3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
+        2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
+        1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
+        1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
+        876, 844, 812, 780, 748, 716, 684, 652,
+        620, 588, 556, 524, 492, 460, 428, 396,
+        372, 356, 340, 324, 308, 292, 276, 260,
+        244, 228, 212, 196, 180, 164, 148, 132,
+        120, 112, 104, 96, 88, 80, 72, 64,
+        56, 48, 40, 32, 24, 16, 8, 0
+    )
 
-        private val l = intArrayOf(
-            0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-            6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
-        )
+    // Таблицы для A-law (перенесены из companion object)
+    private val k = intArrayOf(
+        1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
+        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+        6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+        6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+        7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+        7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+        7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+        7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+    )
 
-        private val m = intArrayOf(0, 132, 396, 924, 1980, 4092, 8316, 16764)
+    private val l = intArrayOf(
+        0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+        4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+        6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+        6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
+    )
 
-        fun encodeSample(input: Int): Int {
-            var a = if (input == -32768) -32767 else input
-            val c = (a.inv() shr 8) and 128
-            if (c == 0) a *= -1
-            if (a > 32635) a = 32635
-            return if (a >= 256) {
-                val b = k[(a shr 8) and 127]
-                (b shl 4) or ((a shr (b + 3)) and 15)
-            } else {
-                a shr 4
-            } xor c xor 85
-        }
+    private val m = intArrayOf(0, 132, 396, 924, 1980, 4092, 8316, 16764)
 
-        fun decodeSample(input: Int): Int {
-            var a = input xor 85
-            val c = if (a and 128 != 0) -1 else 0
-            a = if (a and 128 != 0) a and 127 else a
-            val b = ((a and 240) shr 4) + 4
-            return -8 * if (c == 0) {
-                if (b != 4) {
-                    (1 shl b) or ((a and 15) shl (b - 4)) or (1 shl (b - 5))
-                } else {
-                    (a shl 1) or 1
-                }
-            } else {
-                if (b != 4) {
-                    -((1 shl b) or ((a and 15) shl (b - 4)) or (1 shl (b - 5)))
-                } else {
-                    -(a shl 1) - 1
-                }
-            }
-        }
+    // μ-law методы
+    fun encodeMuLaw(data: ShortArray): ByteArray {
+        return ByteArray(data.size) { encodeSampleMuLaw(data[it].toInt()).toByte() }
+    }
 
-        fun encode(input: ShortArray): ByteArray {
-            val output = ByteArray(input.size)
-            for (i in input.indices) {
-                output[i] = encodeSample(input[i].toInt()).toByte()
-            }
-            return output
-        }
+    fun decodeMuLaw(data: ByteArray): ShortArray {
+        return ShortArray(data.size) { decodeSampleMuLaw(data[it]) }
+    }
+
+    private fun encodeSampleMuLaw(a: Int): Int {
+        var a = a
+        val c = a shr 8 and 128
+        if (c != 0) a = -a
+        if (a > 32635) a = 32635
+        a += 132
+        val b = l[a shr 7 and 255]
+        return (c or (b shl 4) or (a shr (b + 3) and 15)).inv()
+    }
 
-        fun decode(input: ByteArray): IntArray {
-            val output = IntArray(input.size)
-            for (i in input.indices) {
-                output[i] = decodeSample(input[i].toInt())
-            }
-            return output
+    private fun decodeSampleMuLaw(encoded: Byte): Short {
+        val temp = encoded.toInt().inv()
+        val sign = temp and 0x80
+        val exponent = (temp shr 4) and 0x07
+        val mantissa = temp and 0x0F
+
+        var sample = (mantissa shl 4) + 0x08
+        if (exponent != 0) {
+            sample = (sample + 0x100) shl (exponent - 1)
         }
+
+        return if (sign == 0) sample.toShort() else (-sample).toShort()
+    }
+
+    // A-law методы
+    fun encodeALaw(data: ShortArray): ByteArray {
+        return ByteArray(data.size) { encodeSampleALaw(data[it].toInt()).toByte() }
+    }
+
+    private fun encodeSampleALaw(a: Int): Int {
+        var a = a
+        a = if (a == -32768) -32767 else a
+        val c = if ((a.inv() shr 8) and 128 != 0) 128 else 0
+        if (c == 0) a *= -1
+        if (a > 32635) a = 32635
+        return if (a >= 256) {
+            val b = k[a shr 8 and 127]
+            (b shl 4) or (a shr (b + 3) and 15)
+        } else {
+            a shr 4
+        } xor c xor 85
     }
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/radio2/Rtp/AudioProcessor.kt b/app/src/main/java/com/example/radio2/Rtp/AudioProcessor.kt
index 69a2524e6627e7b3a6e30d679833cf5d9f4b88b6..e14a4468ce6361ceeaf947cb3a91c06f03bfcb2a 100644
--- a/app/src/main/java/com/example/radio2/Rtp/AudioProcessor.kt
+++ b/app/src/main/java/com/example/radio2/Rtp/AudioProcessor.kt
@@ -1,18 +1,29 @@
 package com.example.radio2.Rtp
 
+import android.Manifest
+import android.content.Context
 import android.media.AudioAttributes
 import android.media.AudioFormat
 import android.media.AudioFormat.CHANNEL_OUT_MONO
 import android.media.AudioFormat.ENCODING_PCM_16BIT
 import android.media.AudioManager
+import android.media.AudioRecord
 import android.media.AudioTrack
+import android.media.MediaRecorder
 import android.util.Log
+import androidx.core.content.ContextCompat
 import com.example.radio2.Data.AudioConfigStorage
 import com.example.radio2.Rtp.ArrayUtils.chunkFloatArrayWithPadding
 import com.example.radio2.service.WebSocketService
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.launch
 import org.example.radio2.Rtp.AlawMulawEncoder
 import org.json.JSONArray
 import org.json.JSONObject
+import java.nio.ByteBuffer
+import java.nio.ByteOrder
 import java.util.Base64
 import java.util.Base64.getEncoder
 import kotlin.math.PI
@@ -43,64 +54,76 @@ interface VoicePacketSender {
     fun sendVoicePacket(base64Str: String)
 }
 
-class AudioProcessor(private val packetSender: VoicePacketSender?, private val sampleRate: Int = 26000, private val bufferSize: Int = 1440) {
-    val frequency = 1000 // Частота 20 кГц
-    val duration = 1.0 // Длительность 0.5 секунды
-
+class AudioProcessor(
+    private val packetSender: VoicePacketSender?,
+    private val context: Context,
+    private val sampleRate: Int = 26000,
+    private val bufferSize: Int = 1440
+) {
+    private var isRecording = false
+    private lateinit var recordingThread: Thread
+    private var audioRecord: AudioRecord? = null
 
     fun startRecording() {
-        Log.d("AudioRecorder ssrc", "ssrc: $ssrc")
-        val signal = generateToneArray(frequency, duration, sampleRate)
-        /*Log.d("AudioRecorder signal", "signal: ${signal.contentToString()}")*/
-
-        val chunks = chunkFloatArrayWithPadding(signal, bufferSamplesCount)
+        if (isRecording) return
+
+        isRecording = true
+        recordingThread = Thread {
+            val minBufferSize = AudioRecord.getMinBufferSize(
+                sampleRate,
+                AudioFormat.CHANNEL_IN_MONO,
+                AudioFormat.ENCODING_PCM_16BIT
+            )
+
+            val recordBufferSize = maxOf(minBufferSize, bufferSize * 2)
+
+            if (ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) !=
+                android.content.pm.PackageManager.PERMISSION_GRANTED
+            ) {
+                throw SecurityException("Permission RECORD_AUDIO is not granted.")
+            }
 
-        /*Log.d(
-            TAG,
-            """
-            Количество чанков: ${chunks.size}
-            Чанки:
-            ${chunks.joinToString("\n") { "Длина: ${it.size} | Данные: ${formatChunkData(it)}" }}
-            """.trimIndent()
-        )*/
+            audioRecord = AudioRecord(
+                MediaRecorder.AudioSource.MIC,
+                sampleRate,
+                AudioFormat.CHANNEL_IN_MONO,
+                AudioFormat.ENCODING_PCM_16BIT,
+                recordBufferSize
+            )
 
-        /*playBuffer(signal, sampleRate)*/
+            audioRecord?.startRecording()
 
-        Log.d(TAG, "Длина исходного массива: ${signal.size}")
+            val buffer = ShortArray(bufferSize)
 
-        val encodedChunks = mutableListOf<String>()
+            while (isRecording) {
+                val bytesRead = audioRecord?.read(buffer, 0, bufferSize) ?: 0
 
-        for (chunk in chunks) {
-            // Преобразуем FloatArray в ShortArray
-            val chunkShort = ShortArray(chunk.size)
-            for (i in chunk.indices) {
-                chunkShort[i] = (chunk[i] * 32767).toInt().toShort()
+                if (bytesRead > 0) {
+                    val (base64Packet, _) = processMicrophoneFrame(buffer)
+                    packetSender?.sendVoicePacket(base64Packet)
+                }
             }
 
-            // Кодируем чанк и добавляем в список
-            val (base64Packet, voicePacket) = processMicrophoneFrame(chunkShort)
-            encodedChunks.add(base64Packet)
-
-            packetSender?.sendVoicePacket(base64Packet)
+            audioRecord?.stop()
+            audioRecord?.release()
+            audioRecord = null
         }
+        recordingThread.start()
+    }
 
-        /*val decodedSignal = mutableListOf<Float>()
-        for (base64Packet in encodedChunks) {
-            val decodedBase64 = voicePacketProcessor.processVoicePacket(base64Packet)
-            val decodedFloatArray = voicePacketProcessor.convertPCMToFloatArray(decodedBase64)
-            decodedSignal.addAll(decodedFloatArray.toList())
+    fun stopRecording() {
+        isRecording = false
+        try {
+            if (::recordingThread.isInitialized) {
+                recordingThread.join(500) // Даем потоку 500ms на завершение
+            }
+        } catch (e: InterruptedException) {
+            Log.e(TAG, "Error stopping recording thread", e)
         }
-
-        val finalDecodedSignal = decodedSignal.toFloatArray()
-
-
-        Thread.sleep(1000)
-        playBuffer(finalDecodedSignal, sampleRate)*/
     }
 
 
-
-    fun processMicrophoneFrame(wave: ShortArray) : Pair<String, JSONArray> {
+    fun processMicrophoneFrame(wave: ShortArray): Pair<String, JSONArray> {
         udpPacketBuffer[0] = (2 shl 6).toByte()
         udpPacketBuffer[1] = 106.toByte()
         sequenceNumber++
@@ -117,7 +140,7 @@ class AudioProcessor(private val packetSender: VoicePacketSender?, private val s
         val copySize = encodedWave.size.coerceAtMost(maxPayloadSize)
         System.arraycopy(encodedWave, 0, udpPacketBuffer, 12, copySize)
 
-        val base64Str = Base64.getEncoder().encodeToString(udpPacketBuffer.copyOf(12     + copySize))
+        val base64Str = Base64.getEncoder().encodeToString(udpPacketBuffer.copyOf(12 + copySize))
         val voicePacket = JSONArray().apply {
             put(JSONObject().apply {
                 put("MessageID", "VOICE_PACKET")
@@ -158,7 +181,8 @@ class AudioProcessor(private val packetSender: VoicePacketSender?, private val s
 
         val byteBuffer = ByteArray(bufferSize)
         for (i in signal.indices) {
-            val sample = (signal[i] * Short.MAX_VALUE).toInt().coerceIn(Short.MIN_VALUE.toInt(), Short.MAX_VALUE.toInt())
+            val sample = (signal[i] * Short.MAX_VALUE).toInt()
+                .coerceIn(Short.MIN_VALUE.toInt(), Short.MAX_VALUE.toInt())
 
             byteBuffer[i * 2] = sample.toByte()          // Младший байт
             byteBuffer[i * 2 + 1] = (sample shr 8).toByte() // Старший байт
@@ -184,4 +208,51 @@ class AudioProcessor(private val packetSender: VoicePacketSender?, private val s
             "[$firstThree, ..., $lastThree]"
         }
     }
+
+    fun recordAudio(duration: Double, sampleRate: Int): FloatArray {
+        val channelConfig = AudioFormat.CHANNEL_IN_MONO
+        val audioFormat = AudioFormat.ENCODING_PCM_16BIT
+        val minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat)
+        val bufferSize = maxOf(minBufferSize, (sampleRate * duration * 2).toInt())
+
+        if (ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) !=
+            android.content.pm.PackageManager.PERMISSION_GRANTED
+        ) {
+            throw SecurityException("Permission RECORD_AUDIO is not granted.")
+        }
+
+
+        val audioRecord = AudioRecord(
+            MediaRecorder.AudioSource.MIC,
+            sampleRate,
+            channelConfig,
+            audioFormat,
+            bufferSize
+        )
+
+        val buffer = ByteArray(bufferSize)
+        audioRecord.startRecording()
+
+        var bytesRead = 0
+        while (bytesRead < bufferSize) {
+            val read = audioRecord.read(buffer, bytesRead, bufferSize - bytesRead)
+            if (read == AudioRecord.ERROR_INVALID_OPERATION || read == AudioRecord.ERROR_BAD_VALUE) break
+            bytesRead += read
+        }
+
+        audioRecord.stop()
+        audioRecord.release()
+
+        // Конвертация ByteArray в FloatArray
+        return ByteBuffer.wrap(buffer)
+            .order(ByteOrder.LITTLE_ENDIAN)
+            .asShortBuffer()
+            .let { shorts ->
+                FloatArray(shorts.remaining()) {
+                    shorts[it] / 32768f // Нормализация в диапазон [-1.0, 1.0]
+                }
+            }
+
+    }
+
 }
diff --git a/app/src/main/java/com/example/radio2/Rtp/VoicePacketProcessor.kt b/app/src/main/java/com/example/radio2/Rtp/VoicePacketProcessor.kt
index f853d23608990d5f60aae50d267cb6d1b144c6fb..2ac5487306c3ad33aa7a542bf7b6644b54a400c5 100644
--- a/app/src/main/java/com/example/radio2/Rtp/VoicePacketProcessor.kt
+++ b/app/src/main/java/com/example/radio2/Rtp/VoicePacketProcessor.kt
@@ -56,7 +56,6 @@ class VoicePacketProcessor {
         }
 
         val pcm = decodeMuLawToPCM(Mulaw)
-
         return pcm
     }
 
diff --git a/app/src/main/java/com/example/radio2/SubscriberGroupActivity.kt b/app/src/main/java/com/example/radio2/SubscriberGroupActivity.kt
index 7b1dd0972b5f5393e2a8f9e28a7193890e34115e..cb7ebcd89d1a70abaceed1f1ef68ed334dae232b 100644
--- a/app/src/main/java/com/example/radio2/SubscriberGroupActivity.kt
+++ b/app/src/main/java/com/example/radio2/SubscriberGroupActivity.kt
@@ -166,20 +166,25 @@ class SubscriberGroupActivity : ComponentActivity(), VoicePacketSender {
         enableEdgeToEdge()
         val button = findViewById<Button>(R.id.activateVoice)
             var buttonActionCount = 0
-        audioProcessor = AudioProcessor(this)
+        audioProcessor = AudioProcessor(this, this)
 
         button.setOnTouchListener { view, event ->
             when (event.action) {
                 MotionEvent.ACTION_DOWN -> {
                     buttonActionCount++
-                    if(buttonActionCount == 1) {
-                        webSocketService?.startPTT(selectedUser!!.ID, "User")
+                    if (buttonActionCount == 1) {
+                        if (selectedUser != null) {
+                            webSocketService?.startPTT(selectedUser!!.ID, "User")
+                        } else if (selectedGroup != null) {
+                            webSocketService?.startPTT(selectedGroup!!.ID, "Group")
+                        }
                     }
                     audioProcessor.startRecording()
                     true
                 }
                 MotionEvent.ACTION_UP -> {
                     buttonActionCount = 0
+                    audioProcessor.stopRecording()
                     webSocketService?.stopPTT(selectedUser!!.ID, "User")
                     true
                 }
@@ -189,6 +194,7 @@ class SubscriberGroupActivity : ComponentActivity(), VoicePacketSender {
 
 
 
+
         val recyclerViewGroup: RecyclerView = findViewById(R.id.groupsRecyclerView)
             val recyclerViewSubscriber: RecyclerView = findViewById(R.id.subscribersRecyclerView)
             recyclerViewGroup.layoutManager = LinearLayoutManager(this)
diff --git a/app/src/main/java/com/example/radio2/service/WebSocketService.kt b/app/src/main/java/com/example/radio2/service/WebSocketService.kt
index 2c71ea5f37b318888012d658370af69c0b3a743e..fa067bd4241c197512b35d42f49d33316c475624 100644
--- a/app/src/main/java/com/example/radio2/service/WebSocketService.kt
+++ b/app/src/main/java/com/example/radio2/service/WebSocketService.kt
@@ -41,6 +41,9 @@ import com.example.radio2.Data.AudioConfigStorage
 import com.example.radio2.Data.DeviceData2
 import kotlinx.coroutines.delay
 import kotlinx.serialization.json.JsonArray
+import kotlinx.serialization.json.JsonObject
+import kotlinx.serialization.json.int
+import kotlinx.serialization.json.long
 import java.util.UUID
 
 class WebSocketService : Service() {
@@ -76,7 +79,7 @@ class WebSocketService : Service() {
 
     companion object {
         private const val NOTIFICATION_CHANNEL_ID = "WebSocketServiceChannel"
-        private const val NOTIFICATION_ID = 1
+        private var notificationId = 0
     }
 
     override fun onBind(intent: Intent?): IBinder {
@@ -170,37 +173,28 @@ class WebSocketService : Service() {
                         when (message) {
                             is Frame.Text -> {
                                 val serverMessage = message.readText()
+                                Log.d("WebSocketService", "Received raw message: $serverMessage")
                                 handleMessage(serverMessage)
                                 val jsonArray = Json.parseToJsonElement(serverMessage).jsonArray
 
                                 jsonArray.forEach() { message ->
                                     if (message is kotlinx.serialization.json.JsonObject) {
-                                        val messageID =
-                                            message["MessageID"]?.jsonPrimitive?.content
+                                        val messageID = message["MessageID"]?.jsonPrimitive?.content
                                         if (messageID != null) {
-                                            val handler =
-                                                messageHandlerFactory.getHandler(messageID)
+                                            Log.d("WebSocketService", "Processing message with ID: $messageID")
+                                            val handler = messageHandlerFactory.getHandler(messageID)
                                             if (handler != null) {
                                                 handler.handle(message, this)
                                             } else {
-                                                Log.w(
-                                                    "MessageHandlerFactory",
-                                                    "No handler found for MessageID: $messageID"
-                                                )
+                                                Log.w("MessageHandlerFactory", "No handler found for MessageID: $messageID")
                                             }
                                         }
-
                                     }
                                 }
                             }
-
                             is Frame.Binary -> {
-                                Log.d(
-                                    "WebSocketService",
-                                    "Received binary frame of size: ${message.data.size}"
-                                )
+                                Log.d("WebSocketService", "Received binary frame of size: ${message.data.size}")
                             }
-
                             else -> Log.w("WebSocketService", "Unhandled frame: $message")
                         }
                     }
@@ -208,15 +202,15 @@ class WebSocketService : Service() {
             } catch (e: Exception) {
                 isConnected = false
                 Log.e("WebSocketService", "Error connecting WebSocket: ${e.message}")
-                /*retryConnection(url)*/
             }
         }
     }
 
     private fun handleMessage(message: String) {
-        Log.d("WebSocketService", "Received: $message")
+        Log.d("WebSocketService", "handleMessage called with: $message")
         messageCallback?.invoke(message)
         showNotification(message)
+        Log.d("WebSocketService", "handleMessage completed")
     }
 
     fun disconnectWebSocket() {
@@ -234,7 +228,7 @@ class WebSocketService : Service() {
             .setSmallIcon(android.R.drawable.stat_notify_sync)
             .build()
 
-        startForeground(NOTIFICATION_ID, notification)
+        startForeground(notificationId, notification)
     }
 
     private fun createNotificationChannel() {
@@ -383,12 +377,12 @@ class WebSocketService : Service() {
                             put("MessageID", "STORAGE_JOB_REQUEST")
                             put("JobID", generateJobId())
                             put("ConversationID", generateJobId())
-                            put("Sequence", sequence.toInt())
+                            put("Sequence", sequence.toIntOrNull()?:0)
                             put("FromDeviceID", id)
                             put("FromUserID", userId)
                             put("ToDeviceID", "Y2w6TGPtWaO5SsKDLMMZqw==")
                             put("ToUserID", "EREREREREREREREREREREQ==")
-                            put("JobType", jobType.toInt())
+                            put("JobType", jobType.toIntOrNull()?:0)
                             put("JobState", 20)
                             put("FileName", "")
                             put("Title", title)
@@ -431,27 +425,63 @@ class WebSocketService : Service() {
     }
 
     private fun showNotification(message: String) {
-        val notificationIntent = Intent(this, SubscriberGroupActivity::class.java)
-        notificationIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
-        val pendingIntent = PendingIntent.getActivity(
-            this,
-            0,
-            notificationIntent,
-            PendingIntent.FLAG_IMMUTABLE
-        )
-
-        val notification = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
-            .setContentTitle("Новое сообщение")
-            .setContentText(message)
-            .setSmallIcon(android.R.drawable.stat_notify_sync)
-            .setPriority(NotificationCompat.PRIORITY_HIGH)
-            .setContentIntent(pendingIntent)
-            .setAutoCancel(true)
-            .build()
-
-        val notificationManager =
-            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
-        notificationManager.notify(NOTIFICATION_ID, notification)
+        try {
+            Log.d("WebSocketService", "Attempting to show notification for message: $message")
+            val jsonArray = Json.parseToJsonElement(message).jsonArray
+            // Обрабатываем только первое сообщение в массиве
+            if (jsonArray.isNotEmpty()) {
+                val jsonElement = jsonArray[0]
+                if (jsonElement is JsonObject) {
+                    val messageId = jsonElement["MessageID"]?.jsonPrimitive?.content
+                    Log.d("WebSocketService", "Processing message with ID: $messageId")
+                    
+                    if (messageId == "STORAGE_JOB_REQUEST") {
+                        val fromName = jsonElement["FromName"]?.jsonPrimitive?.content
+                        val title = jsonElement["Title"]?.jsonPrimitive?.content
+                        val jobType = jsonElement["JobType"]?.jsonPrimitive?.int
+                        val jobId = jsonElement["JobID"]?.jsonPrimitive?.content
+                        val time = jsonElement["Time"]?.jsonPrimitive?.long ?: System.currentTimeMillis()
+                        val sequence = jsonElement["Sequence"]?.jsonPrimitive?.int
+
+                        if (jobId != null && sequence != null) {
+                            readMessage(jobId, sequence)
+                        }
+                        
+                        Log.d("WebSocketService", "Message details - From: $fromName, Title: $title, JobType: $jobType, JobID: $jobId")
+                        
+                        // Показываем уведомление только для текстовых сообщений (JobType = 0)
+                        if (jobType == 0 && fromName != null && title != null && jobId != null) {
+                            val notificationIntent = Intent(this, SubscriberGroupActivity::class.java)
+                            notificationIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
+                            val pendingIntent = PendingIntent.getActivity(
+                                this,
+                                0,
+                                notificationIntent,
+                                PendingIntent.FLAG_IMMUTABLE
+                            )
+
+                            val notification = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
+                                .setContentTitle("Сообщение от $fromName")
+                                .setContentText(title)
+                                .setSmallIcon(android.R.drawable.stat_notify_sync)
+                                .setPriority(NotificationCompat.PRIORITY_HIGH)
+                                .setContentIntent(pendingIntent)
+                                .setAutoCancel(true)
+                                .build()
+
+                            val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+                            val uniqueNotificationId = (time.toString() + jobId).hashCode()
+                            notificationManager.notify(uniqueNotificationId, notification)
+                            Log.d("WebSocketService", "Notification shown with ID: $uniqueNotificationId")
+                        } else {
+                            Log.d("WebSocketService", "Skipping notification - conditions not met")
+                        }
+                    }
+                }
+            }
+        } catch (e: Exception) {
+            Log.e("WebSocketService", "Error parsing notification message: ${e.message}")
+        }
     }
 
 
diff --git a/h origin working_version b/h origin working_version
new file mode 100644
index 0000000000000000000000000000000000000000..736525599ce5e07953d7ac2303a50c9bc9ef8e70
--- /dev/null
+++ b/h origin working_version	
@@ -0,0 +1,170 @@
+commit 2f3c07e875cdcf72e4984e1f25132776dba0abcc (HEAD -> working_version, origin/main, origin/HEAD, main, database)
+Author: алеша <alex288got@gmail.com>
+Date:   Thu Mar 6 14:32:22 2025 +0300
+
+    фикс кода
+
+diff --git a/app/src/main/java/com/example/radio2/ChatActivity.kt b/app/src/main/java/com/example/radio2/ChatActivity.kt
+index 0ab7dde..f3917ba 100644
+--- a/app/src/main/java/com/example/radio2/ChatActivity.kt
++++ b/app/src/main/java/com/example/radio2/ChatActivity.kt
+@@ -83,7 +83,7 @@ class ChatActivity : AppCompatActivity() {
+         if (userName != null && userId != null) {
+             loadChat(userId, userName)
+         }
+-        val sendMessageButton = findViewById<Button>(R.id.button)
++
+ 
+         recyclerView.layoutManager = LinearLayoutManager(this)
+         chatAdapter = ChatAdapter(this, messages)
+@@ -172,11 +172,32 @@ class ChatActivity : AppCompatActivity() {
+             messageInput.hint = "Enter Message"
+         }
+     }
+-
++    private fun getMessagesForChat() {
++        lifecycleScope.launch {
++            val currentUserId = userId
++            val currentChatId = chatId
++
++            if (currentUserId != null && currentChatId != null) {
++                try {
++                    val chatMessages =
++                        chatRepository.getMessagesForChat(currentChatId, currentUserId)
++                    messages.clear()
++                    messages.addAll(chatMessages.map { MessageTo(it.text, MessageType.RECEIVED) })
++                    chatAdapter.notifyDataSetChanged()
++                    recyclerView.scrollToPosition(messages.size - 1)
++                } catch (e: Exception) {
++                    Log.e("ChatActivity", "Ошибка при загрузке сообщений: ${e.message}")
++                }
++            } else {
++                Log.e("ChatActivity", "Ошибка: userId или chatId не инициализированы")
++            }
++        }
++    }
+     private fun addUserMessage(message: String) {
+         messages.add(MessageTo(message, MessageType.SENT))
+         chatAdapter.notifyItemInserted(messages.size - 1)
+         recyclerView.scrollToPosition(messages.size - 1)
++        messageInput.setText("")
+     }
+ 
+     private fun logAllUsers() {
+@@ -293,7 +314,7 @@ class ChatActivity : AppCompatActivity() {
+ 
+ 
+ //    fun addReceived1Message(message: String) {messages.add(MessageTo(message, MessageType.RECEIVED))}
+-    fun addReceivedMessage(message: String , senderName: String ) {
++    fun addReceivedMessage(message: String ) {
+ //        val selectedUserName = intent.getStringExtra("USER_NAME")?: return
+ //        Log.d("chat_prefs3", "Received message from $senderName: $message")
+     //            addReceived1Message(message)
+@@ -317,13 +338,13 @@ class ChatActivity : AppCompatActivity() {
+ 
+     }
+ //    fun addUser1Message(message: String) {messages.add(MessageTo(message, MessageType.SENT))}
+-    fun addUserMessage(message: String) {
+-
+-//        addUser1Message(message)
+-        messages.add(MessageTo(message, MessageType.SENT))
+-        chatAdapter.notifyItemInserted(messages.size - 1)
+-        recyclerView.scrollToPosition(messages.size - 1)
+-        messageInput.setText("")
++//    fun addUserMessage(message: String) {
++//
++////        addUser1Message(message)
++//        messages.add(MessageTo(message, MessageType.SENT))
++//        chatAdapter.notifyItemInserted(messages.size - 1)
++//        recyclerView.scrollToPosition(messages.size - 1)
++//        messageInput.setText("")
+ //        saveMessages()
+     }
+-}
++
+diff --git a/app/src/main/java/com/example/radio2/ChatAdapter.kt b/app/src/main/java/com/example/radio2/ChatAdapter.kt
+index 7c943f0..4ff2da8 100644
+--- a/app/src/main/java/com/example/radio2/ChatAdapter.kt
++++ b/app/src/main/java/com/example/radio2/ChatAdapter.kt
+@@ -33,16 +33,12 @@ class ChatAdapter(private val context: Context, private var items: MutableList<M
+                 holder.blocUserMessage.visibility = View.VISIBLE
+                 holder.blocReceivedMessage.visibility = View.GONE
+                 holder.userMessage.text = message.text
+-
+-
+             }
+ 
+-            MessageType.RECEIVED ->{
++            MessageType.RECEIVED -> {
+                 holder.blocUserMessage.visibility = View.GONE
+                 holder.blocReceivedMessage.visibility = View.VISIBLE
+                 holder.receivedMessage.text = message.text
+-
+-
+             }
+         }
+     }
+@@ -59,10 +55,3 @@ data class MessageTo(val text: String, val type: MessageType, )
+ enum class MessageType () {
+     SENT, RECEIVED
+ }
+-
+-
+-
+-
+-
+-
+-
+diff --git a/app/src/main/java/com/example/radio2/DataBase.kt b/app/src/main/java/com/example/radio2/DataBase.kt
+index 5b34958..fcd7af2 100644
+--- a/app/src/main/java/com/example/radio2/DataBase.kt
++++ b/app/src/main/java/com/example/radio2/DataBase.kt
+@@ -206,10 +206,14 @@ val MIGRATION_1_2 = object : Migration(1, 2) {
+ // Сама база данных
+ @Database(entities = [User::class, Chat::class, ChatMember::class, Message::class], version = 2)
+ abstract class AppDatabase : RoomDatabase() {
++    abstract fun userDao(): UserDao
++    abstract fun chatDao(): ChatDao
++    abstract fun chatMemberDao(): ChatMemberDao
+     abstract fun messageDao(): MessageDao
+ 
+     companion object {
+-        @Volatile private var INSTANCE: AppDatabase? = null
++        @Volatile
++        private var INSTANCE: AppDatabase? = null
+ 
+         fun getInstance(context: Context): AppDatabase {
+             return INSTANCE ?: synchronized(this) {
+@@ -217,9 +221,7 @@ abstract class AppDatabase : RoomDatabase() {
+                     context.applicationContext,
+                     AppDatabase::class.java,
+                     "app_database"
+-                )
+-                    .addMigrations(MIGRATION_1_2)  // Применение миграции
+-                    .build()
++                ).build()
+                 INSTANCE = instance
+                 instance
+             }
+@@ -258,7 +260,7 @@ class ChatRepository(
+             chatId
+         }
+     }
+-}
++
+ 
+     // Отправить сообщение в чат
+     suspend fun sendMessage(chatId: String, senderId: String, text: String) { // chatId и senderId теперь строки
+diff --git a/app/src/main/java/com/example/radio2/MessageHandlers.kt b/app/src/main/java/com/example/radio2/MessageHandlers.kt
+index fc04df4..138564c 100644
+--- a/app/src/main/java/com/example/radio2/MessageHandlers.kt
++++ b/app/src/main/java/com/example/radio2/MessageHandlers.kt
+@@ -250,7 +250,7 @@ class StorageJobRequestHandler(private val webSocketService: WebSocketService) :
+         webSocketService.executeWhenActivityAvailable { activity ->
+             if (activity is ChatActivity) {
+                 activity.runOnUiThread {
+-                    activity.addReceivedMessage(title.toString(), fromName.toString())
++                    activity.addReceivedMessage(title.toString(),)
+                     if (jobId != null) {
+                         webSocketService.readMessage(jobId, sequence!!)
+                     }