Refactor code structure for improved readability and maintainability
This commit is contained in:
1
app/src/main/assets/lottie/saved.json
Normal file
1
app/src/main/assets/lottie/saved.json
Normal file
File diff suppressed because one or more lines are too long
@@ -151,8 +151,10 @@ class MessageRepository private constructor(private val context: Context) {
|
|||||||
attachments: List<MessageAttachment> = emptyList(),
|
attachments: List<MessageAttachment> = emptyList(),
|
||||||
replyToMessageId: String? = null
|
replyToMessageId: String? = null
|
||||||
): Message {
|
): Message {
|
||||||
|
android.util.Log.d("MessageRepo", "📤 sendMessage START: to=${toPublicKey.take(16)}...")
|
||||||
val account = currentAccount ?: throw IllegalStateException("Not initialized")
|
val account = currentAccount ?: throw IllegalStateException("Not initialized")
|
||||||
val privateKey = currentPrivateKey ?: throw IllegalStateException("Not initialized")
|
val privateKey = currentPrivateKey ?: throw IllegalStateException("Not initialized")
|
||||||
|
android.util.Log.d("MessageRepo", "📤 sendMessage: account=${account.take(16)}...")
|
||||||
|
|
||||||
val messageId = UUID.randomUUID().toString().replace("-", "").take(32)
|
val messageId = UUID.randomUUID().toString().replace("-", "").take(32)
|
||||||
val timestamp = System.currentTimeMillis()
|
val timestamp = System.currentTimeMillis()
|
||||||
@@ -217,7 +219,8 @@ class MessageRepository private constructor(private val context: Context) {
|
|||||||
updateDialog(toPublicKey, text.trim(), timestamp)
|
updateDialog(toPublicKey, text.trim(), timestamp)
|
||||||
|
|
||||||
// 🔥 Отмечаем что я отправлял сообщения в этот диалог (перемещает из requests в chats)
|
// 🔥 Отмечаем что я отправлял сообщения в этот диалог (перемещает из requests в chats)
|
||||||
dialogDao.markIHaveSent(account, toPublicKey)
|
val updatedRows = dialogDao.markIHaveSent(account, toPublicKey)
|
||||||
|
android.util.Log.d("MessageRepo", "📤 MARKED i_have_sent=1 for opponent=${toPublicKey.take(16)}..., updatedRows=$updatedRows")
|
||||||
|
|
||||||
// Отправляем пакет
|
// Отправляем пакет
|
||||||
val packet = PacketMessage().apply {
|
val packet = PacketMessage().apply {
|
||||||
@@ -536,10 +539,15 @@ class MessageRepository private constructor(private val context: Context) {
|
|||||||
suspend fun updateDialogUserInfo(publicKey: String, title: String, username: String, verified: Int) {
|
suspend fun updateDialogUserInfo(publicKey: String, title: String, username: String, verified: Int) {
|
||||||
val account = currentAccount ?: return
|
val account = currentAccount ?: return
|
||||||
|
|
||||||
|
android.util.Log.d("MessageRepo", "📋 updateDialogUserInfo: publicKey=${publicKey.take(16)}..., title=$title, username=$username")
|
||||||
|
|
||||||
// Проверяем существует ли диалог с этим пользователем
|
// Проверяем существует ли диалог с этим пользователем
|
||||||
val existing = dialogDao.getDialog(account, publicKey)
|
val existing = dialogDao.getDialog(account, publicKey)
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
|
android.util.Log.d("MessageRepo", "📋 Updating existing dialog info for ${publicKey.take(16)}...")
|
||||||
dialogDao.updateOpponentInfo(account, publicKey, title, username, verified)
|
dialogDao.updateOpponentInfo(account, publicKey, title, username, verified)
|
||||||
|
} else {
|
||||||
|
android.util.Log.d("MessageRepo", "📋 Dialog not found for ${publicKey.take(16)}..., skipping")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -361,9 +361,10 @@ interface DialogDao {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Отметить что я отправлял сообщения в этот диалог
|
* Отметить что я отправлял сообщения в этот диалог
|
||||||
|
* Возвращает количество обновлённых строк
|
||||||
*/
|
*/
|
||||||
@Query("UPDATE dialogs SET i_have_sent = 1 WHERE account = :account AND opponent_key = :opponentKey")
|
@Query("UPDATE dialogs SET i_have_sent = 1 WHERE account = :account AND opponent_key = :opponentKey")
|
||||||
suspend fun markIHaveSent(account: String, opponentKey: String)
|
suspend fun markIHaveSent(account: String, opponentKey: String): Int
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Обновить онлайн статус
|
* Обновить онлайн статус
|
||||||
@@ -417,7 +418,8 @@ interface DialogDao {
|
|||||||
* Логика:
|
* Логика:
|
||||||
* 1. Берем последнее сообщение (по timestamp DESC)
|
* 1. Берем последнее сообщение (по timestamp DESC)
|
||||||
* 2. Считаем количество непрочитанных сообщений (from_me = 0 AND read = 0)
|
* 2. Считаем количество непрочитанных сообщений (from_me = 0 AND read = 0)
|
||||||
* 3. Обновляем диалог или создаем новый
|
* 3. Вычисляем i_have_sent = 1 если есть исходящие сообщения (from_me = 1) - как sended в Архиве
|
||||||
|
* 4. Обновляем диалог или создаем новый
|
||||||
*/
|
*/
|
||||||
@Query("""
|
@Query("""
|
||||||
INSERT OR REPLACE INTO dialogs (
|
INSERT OR REPLACE INTO dialogs (
|
||||||
@@ -430,7 +432,8 @@ interface DialogDao {
|
|||||||
unread_count,
|
unread_count,
|
||||||
is_online,
|
is_online,
|
||||||
last_seen,
|
last_seen,
|
||||||
verified
|
verified,
|
||||||
|
i_have_sent
|
||||||
)
|
)
|
||||||
SELECT
|
SELECT
|
||||||
:account AS account,
|
:account AS account,
|
||||||
@@ -478,7 +481,19 @@ interface DialogDao {
|
|||||||
COALESCE(
|
COALESCE(
|
||||||
(SELECT verified FROM dialogs WHERE account = :account AND opponent_key = :opponentKey),
|
(SELECT verified FROM dialogs WHERE account = :account AND opponent_key = :opponentKey),
|
||||||
0
|
0
|
||||||
) AS verified
|
) AS verified,
|
||||||
|
CASE
|
||||||
|
WHEN (SELECT COUNT(*) FROM messages
|
||||||
|
WHERE account = :account
|
||||||
|
AND from_public_key = :account
|
||||||
|
AND to_public_key = :opponentKey
|
||||||
|
AND from_me = 1) > 0
|
||||||
|
THEN 1
|
||||||
|
ELSE COALESCE(
|
||||||
|
(SELECT i_have_sent FROM dialogs WHERE account = :account AND opponent_key = :opponentKey),
|
||||||
|
0
|
||||||
|
)
|
||||||
|
END AS i_have_sent
|
||||||
""")
|
""")
|
||||||
suspend fun updateDialogFromMessages(account: String, opponentKey: String)
|
suspend fun updateDialogFromMessages(account: String, opponentKey: String)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -810,6 +810,9 @@ fun ChatDetailScreen(
|
|||||||
// Кнопка меню - открывает bottom sheet
|
// Кнопка меню - открывает bottom sheet
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
|
// Закрываем клавиатуру перед открытием меню
|
||||||
|
keyboardController?.hide()
|
||||||
|
focusManager.clearFocus()
|
||||||
showMenu = true
|
showMenu = true
|
||||||
},
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -1087,11 +1090,15 @@ fun ChatDetailScreen(
|
|||||||
verticalArrangement = Arrangement.Center
|
verticalArrangement = Arrangement.Center
|
||||||
) {
|
) {
|
||||||
if (isSavedMessages) {
|
if (isSavedMessages) {
|
||||||
Icon(
|
val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.saved))
|
||||||
Icons.Default.Bookmark,
|
val progress by animateLottieCompositionAsState(
|
||||||
contentDescription = null,
|
composition = composition,
|
||||||
tint = secondaryTextColor.copy(alpha = 0.5f),
|
iterations = LottieConstants.IterateForever
|
||||||
modifier = Modifier.size(64.dp)
|
)
|
||||||
|
LottieAnimation(
|
||||||
|
composition = composition,
|
||||||
|
progress = { progress },
|
||||||
|
modifier = Modifier.size(120.dp)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.speech))
|
val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.speech))
|
||||||
|
|||||||
@@ -704,7 +704,35 @@ fun ChatsListScreen(
|
|||||||
val requestsCount by chatsViewModel.requestsCount.collectAsState()
|
val requestsCount by chatsViewModel.requestsCount.collectAsState()
|
||||||
val requests by chatsViewModel.requests.collectAsState()
|
val requests by chatsViewModel.requests.collectAsState()
|
||||||
|
|
||||||
if (showRequestsScreen) {
|
// 🎬 Animated content transition between main list and requests
|
||||||
|
AnimatedContent(
|
||||||
|
targetState = showRequestsScreen,
|
||||||
|
transitionSpec = {
|
||||||
|
if (targetState) {
|
||||||
|
// Переход на Requests: slide in from right + fade
|
||||||
|
(slideInHorizontally(
|
||||||
|
animationSpec = tween(300, easing = FastOutSlowInEasing),
|
||||||
|
initialOffsetX = { it }
|
||||||
|
) + fadeIn(tween(300))) togetherWith
|
||||||
|
(slideOutHorizontally(
|
||||||
|
animationSpec = tween(300, easing = FastOutSlowInEasing),
|
||||||
|
targetOffsetX = { -it / 3 }
|
||||||
|
) + fadeOut(tween(200)))
|
||||||
|
} else {
|
||||||
|
// Возврат из Requests: slide out to right
|
||||||
|
(slideInHorizontally(
|
||||||
|
animationSpec = tween(300, easing = FastOutSlowInEasing),
|
||||||
|
initialOffsetX = { -it / 3 }
|
||||||
|
) + fadeIn(tween(300))) togetherWith
|
||||||
|
(slideOutHorizontally(
|
||||||
|
animationSpec = tween(300, easing = FastOutSlowInEasing),
|
||||||
|
targetOffsetX = { it }
|
||||||
|
) + fadeOut(tween(200)))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
label = "RequestsTransition"
|
||||||
|
) { isRequestsScreen ->
|
||||||
|
if (isRequestsScreen) {
|
||||||
// 📬 Show Requests Screen
|
// 📬 Show Requests Screen
|
||||||
RequestsScreen(
|
RequestsScreen(
|
||||||
requests = requests,
|
requests = requests,
|
||||||
@@ -782,6 +810,7 @@ fun ChatsListScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} // Close AnimatedContent
|
||||||
|
|
||||||
// Console button removed
|
// Console button removed
|
||||||
}
|
}
|
||||||
|
|||||||
1
app/src/main/res/raw/saved.json
Normal file
1
app/src/main/res/raw/saved.json
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user