Группы: восстановление ключей по инвайту и Apple Emoji

- Добавлено восстановление локального ключа группы из инвайта при повторном нажатии, даже если на сервере статус уже JOINED.
- В карточке приглашения сначала восстанавливается ключ, затем открывается группа.
- Включено отображение Apple Emoji для названия/описания группы в GroupInfo и в заголовке группы в чате.
- Обновлён превью-заголовок в GroupSetup на Apple Emoji рендер.
This commit is contained in:
2026-03-06 17:23:11 +05:00
parent 5de0777063
commit e9944b3c67
5 changed files with 94 additions and 22 deletions

View File

@@ -284,6 +284,47 @@ class GroupRepository private constructor(context: Context) {
)
}
/**
* Desktop parity fix:
* if user is already joined on server, repeated invite click should still restore local group key.
*/
suspend fun ensureLocalGroupFromInvite(
accountPublicKey: String,
accountPrivateKey: String,
inviteString: String
): GroupJoinResult {
val parsed = parseInviteString(inviteString)
?: return GroupJoinResult(
success = false,
status = GroupStatus.INVALID,
error = "Invalid invite string"
)
val existingGroupKey = getGroupKey(accountPublicKey, accountPrivateKey, parsed.groupId)
if (!existingGroupKey.isNullOrBlank()) {
return GroupJoinResult(
success = true,
status = GroupStatus.JOINED,
dialogPublicKey = toGroupDialogPublicKey(parsed.groupId),
title = parsed.title
)
}
persistJoinedGroup(
accountPublicKey = accountPublicKey,
accountPrivateKey = accountPrivateKey,
parsedInvite = parsed,
emitSystemJoinMessage = false
)
return GroupJoinResult(
success = true,
status = GroupStatus.JOINED,
dialogPublicKey = toGroupDialogPublicKey(parsed.groupId),
title = parsed.title
)
}
suspend fun synchronizeJoinedGroup(
accountPublicKey: String,
accountPrivateKey: String,

View File

@@ -90,6 +90,7 @@ import com.rosetta.messenger.ui.chats.components.MultiImageEditorScreen
import com.rosetta.messenger.ui.chats.input.*
import com.rosetta.messenger.ui.chats.models.*
import com.rosetta.messenger.ui.chats.utils.*
import com.rosetta.messenger.ui.components.AppleEmojiText
import com.rosetta.messenger.ui.components.AvatarImage
import com.rosetta.messenger.ui.components.VerifiedBadge
import com.rosetta.messenger.ui.onboarding.PrimaryBlue
@@ -1133,21 +1134,14 @@ fun ChatDetailScreen(
Alignment
.CenterVertically
) {
Text(
text =
chatTitle,
fontSize =
16.sp,
fontWeight =
FontWeight
.SemiBold,
color =
Color.White,
maxLines =
1,
overflow =
TextOverflow
.Ellipsis
AppleEmojiText(
text = chatTitle,
fontSize = 16.sp,
fontWeight = FontWeight.SemiBold,
color = Color.White,
maxLines = 1,
overflow = android.text.TextUtils.TruncateAt.END,
enableLinks = false
)
if (!isSavedMessages &&
!isGroupChat &&

View File

@@ -122,6 +122,7 @@ import com.rosetta.messenger.ui.chats.components.ImageAttachment
import com.rosetta.messenger.ui.chats.components.ImageSourceBounds
import com.rosetta.messenger.ui.chats.components.ImageViewerScreen
import com.rosetta.messenger.ui.chats.components.ViewableImage
import com.rosetta.messenger.ui.components.AppleEmojiText
import com.rosetta.messenger.ui.components.AvatarImage
import com.rosetta.messenger.ui.components.VerifiedBadge
import com.rosetta.messenger.ui.icons.TelegramIcons
@@ -854,13 +855,14 @@ fun GroupInfoScreen(
Spacer(modifier = Modifier.height(14.dp))
Text(
AppleEmojiText(
text = groupTitle,
color = Color.White,
fontSize = 24.sp,
fontWeight = FontWeight.SemiBold,
maxLines = 1,
overflow = TextOverflow.Ellipsis
overflow = android.text.TextUtils.TruncateAt.END,
enableLinks = false
)
Text(
@@ -917,12 +919,13 @@ fun GroupInfoScreen(
if (groupDescription.isNotBlank()) {
Spacer(modifier = Modifier.height(10.dp))
Text(
AppleEmojiText(
text = groupDescription,
color = Color.White.copy(alpha = 0.7f),
fontSize = 12.sp,
maxLines = 2,
overflow = TextOverflow.Ellipsis
overflow = android.text.TextUtils.TruncateAt.END,
enableLinks = false
)
}
}

View File

@@ -81,6 +81,7 @@ import com.rosetta.messenger.network.SearchUser
import com.rosetta.messenger.repository.AvatarRepository
import com.rosetta.messenger.ui.components.KeyboardHeightProvider
import com.rosetta.messenger.ui.components.OptimizedEmojiPicker
import com.rosetta.messenger.ui.components.AppleEmojiText
import com.rosetta.messenger.ui.components.AvatarImage
import com.rosetta.messenger.ui.icons.TelegramIcons
import com.rosetta.messenger.utils.AvatarFileManager
@@ -622,13 +623,14 @@ fun GroupSetupScreen(
Spacer(modifier = Modifier.size(12.dp))
Column(modifier = Modifier.weight(1f)) {
Text(
AppleEmojiText(
text = title.trim(),
color = primaryTextColor,
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
maxLines = 1,
overflow = TextOverflow.Ellipsis
overflow = android.text.TextUtils.TruncateAt.END,
enableLinks = false
)
Spacer(modifier = Modifier.height(2.dp))
Text(

View File

@@ -1452,7 +1452,39 @@ private fun GroupInviteInlineCard(
if (parsedInvite == null) return
if (status == GroupStatus.JOINED) {
openParsedGroup()
if (accountPublicKey.isBlank() || accountPrivateKey.isBlank()) {
openParsedGroup()
return
}
scope.launch {
actionLoading = true
val restoreResult =
withContext(Dispatchers.IO) {
groupRepository.ensureLocalGroupFromInvite(
accountPublicKey = accountPublicKey,
accountPrivateKey = accountPrivateKey,
inviteString = normalizedInvite
)
}
actionLoading = false
if (restoreResult.success) {
status = GroupStatus.JOINED
groupRepository.cacheInviteInfo(
parsedInvite.groupId,
GroupStatus.JOINED,
membersCount
)
openParsedGroup()
} else {
Toast.makeText(
context,
restoreResult.error ?: "Failed to restore group access",
Toast.LENGTH_SHORT
).show()
}
}
return
}