mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-06-04 01:41:43 +00:00
core, ui: replace map of network statuses with subscription status of current chat (#6353)
* core: subscription status wip
* update
* update
* update
* remove statuses core
* cleanup ios
* comment
* plans
* remove NetworkStatus
* ios wip
* contact sub status
* Revert "contact sub status"
This reverts commit 50cf94beed.
* sub status
* set on connected
* kotlin
* rename
* layout
* member status
* kotlin
* fix chat subscription status
* string
* core: update simplexmq
* client notices
* update simplexmq
* update alert
* update simplexmq
* android/desktop
* formatting
* fix tests
* update plans and API docs
---------
Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
This commit is contained in:
+2
-40
@@ -96,11 +96,12 @@ object ChatModel {
|
||||
val dbMigrationInProgress = mutableStateOf(false)
|
||||
val incompleteInitializedDbRemoved = mutableStateOf(false)
|
||||
// map of connections network statuses, key is agent connection id
|
||||
val networkStatuses = mutableStateMapOf<String, NetworkStatus>()
|
||||
val switchingUsersAndHosts = mutableStateOf(false)
|
||||
|
||||
// current chat
|
||||
val chatId = mutableStateOf<String?>(null)
|
||||
val chatAgentConnId = mutableStateOf<String?>(null)
|
||||
val chatSubStatus = mutableStateOf<SubscriptionStatus?>(null)
|
||||
val openAroundItemId: MutableState<Long?> = mutableStateOf(null)
|
||||
val chatsContext = ChatsContext(null)
|
||||
val secondaryChatsContext = mutableStateOf<ChatsContext?>(null)
|
||||
@@ -1147,21 +1148,6 @@ object ChatModel {
|
||||
showingInvitation.value = showingInvitation.value?.copy(connChatUsed = true)
|
||||
}
|
||||
|
||||
fun setContactNetworkStatus(contact: Contact, status: NetworkStatus) {
|
||||
val conn = contact.activeConn
|
||||
if (conn != null) {
|
||||
networkStatuses[conn.agentConnId] = status
|
||||
}
|
||||
}
|
||||
|
||||
fun contactNetworkStatus(contact: Contact): NetworkStatus {
|
||||
val conn = contact.activeConn
|
||||
return if (conn != null)
|
||||
networkStatuses[conn.agentConnId] ?: NetworkStatus.Unknown()
|
||||
else
|
||||
NetworkStatus.Unknown()
|
||||
}
|
||||
|
||||
fun addTerminalItem(item: TerminalItem) {
|
||||
val maxItems = if (appPreferences.developerTools.get()) 500 else 200
|
||||
if (terminalsVisible.isNotEmpty()) {
|
||||
@@ -1721,30 +1707,6 @@ sealed class ChatInfo: SomeChat, NamedChat {
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
sealed class NetworkStatus {
|
||||
val statusString: String get() =
|
||||
when (this) {
|
||||
is Connected -> generalGetString(MR.strings.server_connected)
|
||||
is Error -> generalGetString(MR.strings.server_error)
|
||||
else -> generalGetString(MR.strings.server_connecting)
|
||||
}
|
||||
val statusExplanation: String get() =
|
||||
when (this) {
|
||||
is Connected -> generalGetString(MR.strings.connected_to_server_to_receive_messages_from_contact)
|
||||
is Error -> String.format(generalGetString(MR.strings.trying_to_connect_to_server_to_receive_messages_with_error), connectionError)
|
||||
else -> generalGetString(MR.strings.trying_to_connect_to_server_to_receive_messages)
|
||||
}
|
||||
|
||||
@Serializable @SerialName("unknown") class Unknown: NetworkStatus()
|
||||
@Serializable @SerialName("connected") class Connected: NetworkStatus()
|
||||
@Serializable @SerialName("disconnected") class Disconnected: NetworkStatus()
|
||||
@Serializable @SerialName("error") class Error(val connectionError: String): NetworkStatus()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class ConnNetworkStatus(val agentConnId: String, val networkStatus: NetworkStatus)
|
||||
|
||||
@Serializable
|
||||
data class Contact(
|
||||
val contactId: Long,
|
||||
|
||||
+103
-61
@@ -13,6 +13,7 @@ import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.platform.LocalClipboardManager
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -27,12 +28,14 @@ import dev.icerock.moko.resources.compose.painterResource
|
||||
import chat.simplex.common.platform.*
|
||||
import chat.simplex.common.ui.theme.*
|
||||
import chat.simplex.common.views.call.*
|
||||
import chat.simplex.common.views.chat.item.contentModerationPostLink
|
||||
import chat.simplex.common.views.chat.item.showContentBlockedAlert
|
||||
import chat.simplex.common.views.chat.item.showQuotedItemDoesNotExistAlert
|
||||
import chat.simplex.common.views.chatlist.openGroupChat
|
||||
import chat.simplex.common.views.migration.MigrationFileLinkData
|
||||
import chat.simplex.common.views.onboarding.OnboardingStage
|
||||
import chat.simplex.common.views.usersettings.*
|
||||
import chat.simplex.common.views.usersettings.networkAndServers.defaultConditionsLink
|
||||
import chat.simplex.common.views.usersettings.networkAndServers.serverHostname
|
||||
import com.charleskorn.kaml.Yaml
|
||||
import com.charleskorn.kaml.YamlConfiguration
|
||||
@@ -46,12 +49,17 @@ import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlinx.datetime.Instant
|
||||
import kotlinx.datetime.TimeZone
|
||||
import kotlinx.datetime.toJavaLocalDateTime
|
||||
import kotlinx.datetime.toLocalDateTime
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.builtins.*
|
||||
import kotlinx.serialization.descriptors.*
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
import kotlinx.serialization.json.*
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.format.FormatStyle
|
||||
import java.util.Date
|
||||
|
||||
typealias ChatCtrl = Long
|
||||
@@ -1709,6 +1717,11 @@ object ChatController {
|
||||
val userId = kotlin.runCatching { currentUserId("apiCreateUserAddress") }.getOrElse { return null }
|
||||
val r = sendCmdWithRetry(rh, CC.ApiCreateMyAddress(userId))
|
||||
if (r is API.Result && r.res is CR.UserContactLinkCreated) return r.res.connLinkContact
|
||||
if (r is API.Error && r.err is ChatError.ChatErrorAgent && r.err.agentError is AgentErrorType.NOTICE) {
|
||||
val e = r.err.agentError
|
||||
showClientNoticeAlert(e.server, e.preset, e.expiresAt)
|
||||
return null
|
||||
}
|
||||
if (r == null) return null
|
||||
if (!(networkErrorAlert(r))) {
|
||||
apiErrorAlert("apiCreateUserAddress", generalGetString(MR.strings.error_creating_address), r)
|
||||
@@ -1842,13 +1855,6 @@ object ChatController {
|
||||
return r.result is CR.CmdOk
|
||||
}
|
||||
|
||||
suspend fun apiGetNetworkStatuses(rh: Long?): List<ConnNetworkStatus>? {
|
||||
val r = sendCmd(rh, CC.ApiGetNetworkStatuses())
|
||||
if (r is API.Result && r.res is CR.NetworkStatuses) return r.res.networkStatuses
|
||||
Log.e(TAG, "apiGetNetworkStatuses bad response: ${r.responseType} ${r.details}")
|
||||
return null
|
||||
}
|
||||
|
||||
suspend fun apiChatRead(rh: Long?, type: ChatType, id: Long): Boolean {
|
||||
val r = sendCmd(rh, CC.ApiChatRead(type, id, scope = null))
|
||||
if (r.result is CR.CmdOk) return true
|
||||
@@ -2175,6 +2181,11 @@ object ChatController {
|
||||
suspend fun apiCreateGroupLink(rh: Long?, groupId: Long, memberRole: GroupMemberRole = GroupMemberRole.Member): GroupLink? {
|
||||
val r = sendCmdWithRetry(rh, CC.APICreateGroupLink(groupId, memberRole))
|
||||
if (r is API.Result && r.res is CR.GroupLinkCreated) return r.res.groupLink
|
||||
if (r is API.Error && r.err is ChatError.ChatErrorAgent && r.err.agentError is AgentErrorType.NOTICE) {
|
||||
val e = r.err.agentError
|
||||
showClientNoticeAlert(e.server, e.preset, e.expiresAt)
|
||||
return null
|
||||
}
|
||||
if (r == null) return null
|
||||
if (!(networkErrorAlert(r))) {
|
||||
apiErrorAlert("apiCreateGroupLink", generalGetString(MR.strings.error_creating_link_for_group), r)
|
||||
@@ -2546,12 +2557,15 @@ object ChatController {
|
||||
chatModel.replaceConnReqView(conn.id, "@${r.contact.contactId}")
|
||||
chatModel.chatsContext.removeChat(rhId, conn.id)
|
||||
}
|
||||
if (r.contact.id == chatModel.chatId.value && conn != null) {
|
||||
chatModel.chatAgentConnId.value = conn.agentConnId
|
||||
chatModel.chatSubStatus.value = SubscriptionStatus.Active
|
||||
}
|
||||
}
|
||||
}
|
||||
if (r.contact.directOrUsed) {
|
||||
ntfManager.notifyContactConnected(r.user, r.contact)
|
||||
}
|
||||
chatModel.setContactNetworkStatus(r.contact, NetworkStatus.Connected())
|
||||
}
|
||||
is CR.ContactConnecting -> {
|
||||
if (active(r.user) && r.contact.directOrUsed) {
|
||||
@@ -2576,7 +2590,6 @@ object ChatController {
|
||||
}
|
||||
}
|
||||
}
|
||||
chatModel.setContactNetworkStatus(r.contact, NetworkStatus.Connected())
|
||||
}
|
||||
is CR.ReceivedContactRequest -> {
|
||||
val contactRequest = r.contactRequest
|
||||
@@ -2618,18 +2631,12 @@ object ChatController {
|
||||
}
|
||||
}
|
||||
}
|
||||
// ContactsSubscribed, ContactsDisconnected are only used in CLI,
|
||||
// They have to be used here for remote desktop to process these status updates.
|
||||
is CR.ContactsSubscribed -> updateContactsStatus(r.contactRefs, NetworkStatus.Connected())
|
||||
is CR.ContactsDisconnected -> updateContactsStatus(r.contactRefs, NetworkStatus.Disconnected())
|
||||
is CR.NetworkStatusResp -> {
|
||||
for (cId in r.connections) {
|
||||
chatModel.networkStatuses[cId] = r.networkStatus
|
||||
}
|
||||
}
|
||||
is CR.NetworkStatuses -> {
|
||||
for (s in r.networkStatuses) {
|
||||
chatModel.networkStatuses[s.agentConnId] = s.networkStatus
|
||||
is CR.SubscriptionStatusEvt -> {
|
||||
val chatAgentConnId = chatModel.chatAgentConnId.value
|
||||
if (chatAgentConnId != null && r.connections.contains(chatAgentConnId)) {
|
||||
withContext(Dispatchers.Main) {
|
||||
chatModel.chatSubStatus.value = r.subscriptionStatus
|
||||
}
|
||||
}
|
||||
}
|
||||
is CR.ChatInfoUpdated ->
|
||||
@@ -2916,9 +2923,6 @@ object ChatController {
|
||||
chatModel.chatsContext.upsertGroupMember(rhId, r.groupInfo, r.member)
|
||||
}
|
||||
}
|
||||
if (r.memberContact != null) {
|
||||
chatModel.setContactNetworkStatus(r.memberContact, NetworkStatus.Connected())
|
||||
}
|
||||
}
|
||||
is CR.GroupUpdated ->
|
||||
if (active(r.user)) {
|
||||
@@ -3231,12 +3235,6 @@ object ChatController {
|
||||
m.users.clear()
|
||||
m.users.addAll(users)
|
||||
getUserChatData(null)
|
||||
val statuses = apiGetNetworkStatuses(null)
|
||||
if (statuses != null) {
|
||||
chatModel.networkStatuses.clear()
|
||||
val ss = statuses.associate { it.agentConnId to it.networkStatus }.toMap()
|
||||
chatModel.networkStatuses.putAll(ss)
|
||||
}
|
||||
}
|
||||
|
||||
private fun activeUser(rhId: Long?, user: UserLike): Boolean =
|
||||
@@ -3349,12 +3347,6 @@ object ChatController {
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateContactsStatus(contactRefs: List<ContactRef>, status: NetworkStatus) {
|
||||
for (c in contactRefs) {
|
||||
chatModel.networkStatuses[c.agentConnId] = status
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun switchUIRemoteHost(rhId: Long?) = showProgressIfNeeded {
|
||||
// TODO lock the switch so that two switches can't run concurrently?
|
||||
chatModel.chatId.value = null
|
||||
@@ -3381,12 +3373,6 @@ object ChatController {
|
||||
chatModel.secondaryChatsContext.value?.popChatCollector?.clear()
|
||||
}
|
||||
}
|
||||
val statuses = apiGetNetworkStatuses(rhId)
|
||||
if (statuses != null) {
|
||||
chatModel.networkStatuses.clear()
|
||||
val ss = statuses.associate { it.agentConnId to it.networkStatus }.toMap()
|
||||
chatModel.networkStatuses.putAll(ss)
|
||||
}
|
||||
getUserChatData(rhId)
|
||||
}
|
||||
|
||||
@@ -3645,7 +3631,6 @@ sealed class CC {
|
||||
class ApiSendCallExtraInfo(val contact: Contact, val extraInfo: WebRTCExtraInfo): CC()
|
||||
class ApiEndCall(val contact: Contact): CC()
|
||||
class ApiCallStatus(val contact: Contact, val callStatus: WebRTCCallStatus): CC()
|
||||
class ApiGetNetworkStatuses(): CC()
|
||||
class ApiAcceptContact(val incognito: Boolean, val contactReqId: Long): CC()
|
||||
class ApiRejectContact(val contactReqId: Long): CC()
|
||||
class ApiChatRead(val type: ChatType, val id: Long, val scope: GroupChatScope?): CC()
|
||||
@@ -3844,7 +3829,6 @@ sealed class CC {
|
||||
is ApiSendCallExtraInfo -> "/_call extra @${contact.apiId} ${json.encodeToString(extraInfo)}"
|
||||
is ApiEndCall -> "/_call end @${contact.apiId}"
|
||||
is ApiCallStatus -> "/_call status @${contact.apiId} ${callStatus.value}"
|
||||
is ApiGetNetworkStatuses -> "/_network_statuses"
|
||||
is ApiChatRead -> "/_read chat ${chatRef(type, id, scope)}"
|
||||
is ApiChatItemsRead -> "/_read chat items ${chatRef(type, id, scope)} ${itemIds.joinToString(",")}"
|
||||
is ApiChatUnread -> "/_unread chat ${chatRef(type, id, scope = null)} ${onOff(unreadChat)}"
|
||||
@@ -4019,7 +4003,6 @@ sealed class CC {
|
||||
is ApiSendCallExtraInfo -> "apiSendCallExtraInfo"
|
||||
is ApiEndCall -> "apiEndCall"
|
||||
is ApiCallStatus -> "apiCallStatus"
|
||||
is ApiGetNetworkStatuses -> "apiGetNetworkStatuses"
|
||||
is ApiChatRead -> "apiChatRead"
|
||||
is ApiChatItemsRead -> "apiChatItemsRead"
|
||||
is ApiChatUnread -> "apiChatUnread"
|
||||
@@ -6159,12 +6142,7 @@ sealed class CR {
|
||||
@Serializable @SerialName("contactRequestRejected") class ContactRequestRejected(val user: UserRef, val contactRequest: UserContactRequest, val contact_: Contact?): CR()
|
||||
@Serializable @SerialName("contactUpdated") class ContactUpdated(val user: UserRef, val toContact: Contact): CR()
|
||||
@Serializable @SerialName("groupMemberUpdated") class GroupMemberUpdated(val user: UserRef, val groupInfo: GroupInfo, val fromMember: GroupMember, val toMember: GroupMember): CR()
|
||||
// TODO remove below
|
||||
@Serializable @SerialName("contactsSubscribed") class ContactsSubscribed(val server: String, val contactRefs: List<ContactRef>): CR()
|
||||
@Serializable @SerialName("contactsDisconnected") class ContactsDisconnected(val server: String, val contactRefs: List<ContactRef>): CR()
|
||||
// TODO remove above
|
||||
@Serializable @SerialName("networkStatus") class NetworkStatusResp(val networkStatus: NetworkStatus, val connections: List<String>): CR()
|
||||
@Serializable @SerialName("networkStatuses") class NetworkStatuses(val user_: UserRef?, val networkStatuses: List<ConnNetworkStatus>): CR()
|
||||
@Serializable @SerialName("subscriptionStatus") class SubscriptionStatusEvt(val subscriptionStatus: SubscriptionStatus, val connections: List<String>): CR()
|
||||
@Serializable @SerialName("chatInfoUpdated") class ChatInfoUpdated(val user: UserRef, val chatInfo: ChatInfo): CR()
|
||||
@Serializable @SerialName("newChatItems") class NewChatItems(val user: UserRef, val chatItems: List<AChatItem>): CR()
|
||||
@Serializable @SerialName("chatItemsStatusesUpdated") class ChatItemsStatusesUpdated(val user: UserRef, val chatItems: List<AChatItem>): CR()
|
||||
@@ -6345,10 +6323,7 @@ sealed class CR {
|
||||
is ContactRequestRejected -> "contactRequestRejected"
|
||||
is ContactUpdated -> "contactUpdated"
|
||||
is GroupMemberUpdated -> "groupMemberUpdated"
|
||||
is ContactsSubscribed -> "contactsSubscribed"
|
||||
is ContactsDisconnected -> "contactsDisconnected"
|
||||
is NetworkStatusResp -> "networkStatus"
|
||||
is NetworkStatuses -> "networkStatuses"
|
||||
is SubscriptionStatusEvt -> "subscriptionStatus"
|
||||
is ChatInfoUpdated -> "chatInfoUpdated"
|
||||
is NewChatItems -> "newChatItems"
|
||||
is ChatItemsStatusesUpdated -> "chatItemsStatusesUpdated"
|
||||
@@ -6521,10 +6496,7 @@ sealed class CR {
|
||||
is ContactRequestRejected -> withUser(user, "contactRequest: ${json.encodeToString(contactRequest)}\ncontact_: ${json.encodeToString(contact_)}")
|
||||
is ContactUpdated -> withUser(user, json.encodeToString(toContact))
|
||||
is GroupMemberUpdated -> withUser(user, "groupInfo: $groupInfo\nfromMember: $fromMember\ntoMember: $toMember")
|
||||
is ContactsSubscribed -> "server: $server\ncontacts:\n${json.encodeToString(contactRefs)}"
|
||||
is ContactsDisconnected -> "server: $server\ncontacts:\n${json.encodeToString(contactRefs)}"
|
||||
is NetworkStatusResp -> "networkStatus $networkStatus\nconnections: $connections"
|
||||
is NetworkStatuses -> withUser(user_, json.encodeToString(networkStatuses))
|
||||
is SubscriptionStatusEvt -> "subscriptionStatus $subscriptionStatus\nconnections: $connections"
|
||||
is ChatInfoUpdated -> withUser(user, json.encodeToString(chatInfo))
|
||||
is NewChatItems -> withUser(user, chatItems.joinToString("\n") { json.encodeToString(it) })
|
||||
is ChatItemsStatusesUpdated -> withUser(user, chatItems.joinToString("\n") { json.encodeToString(it) })
|
||||
@@ -6747,7 +6719,8 @@ class ConnectionStats(
|
||||
val rcvQueuesInfo: List<RcvQueueInfo>,
|
||||
val sndQueuesInfo: List<SndQueueInfo>,
|
||||
val ratchetSyncState: RatchetSyncState,
|
||||
val ratchetSyncSupported: Boolean
|
||||
val ratchetSyncSupported: Boolean,
|
||||
var subStatus: SubscriptionStatus?
|
||||
) {
|
||||
val ratchetSyncAllowed: Boolean get() =
|
||||
ratchetSyncSupported && listOf(RatchetSyncState.Allowed, RatchetSyncState.Required).contains(ratchetSyncState)
|
||||
@@ -6762,8 +6735,10 @@ class ConnectionStats(
|
||||
@Serializable
|
||||
class RcvQueueInfo(
|
||||
val rcvServer: String,
|
||||
var status: QueueStatus,
|
||||
val rcvSwitchStatus: RcvSwitchStatus?,
|
||||
var canAbortSwitch: Boolean
|
||||
var canAbortSwitch: Boolean,
|
||||
var subStatus: SubscriptionStatus
|
||||
)
|
||||
|
||||
@Serializable
|
||||
@@ -6777,6 +6752,7 @@ enum class RcvSwitchStatus {
|
||||
@Serializable
|
||||
class SndQueueInfo(
|
||||
val sndServer: String,
|
||||
var status: QueueStatus,
|
||||
val sndSwitchStatus: SndSwitchStatus?
|
||||
)
|
||||
|
||||
@@ -6814,6 +6790,39 @@ enum class RatchetSyncState {
|
||||
@SerialName("agreed") Agreed
|
||||
}
|
||||
|
||||
@Serializable
|
||||
enum class QueueStatus {
|
||||
@SerialName("new") New,
|
||||
@SerialName("confirmed") Confirmed,
|
||||
@SerialName("secured") Secured,
|
||||
@SerialName("active") Active,
|
||||
@SerialName("disabled") Disabled
|
||||
}
|
||||
|
||||
@Serializable
|
||||
sealed class SubscriptionStatus {
|
||||
@Serializable @SerialName("active") object Active: SubscriptionStatus()
|
||||
@Serializable @SerialName("pending") object Pending: SubscriptionStatus()
|
||||
@Serializable @SerialName("removed") class Removed(val subError: String): SubscriptionStatus()
|
||||
@Serializable @SerialName("noSub") object NoSub: SubscriptionStatus()
|
||||
|
||||
val statusString: String get() =
|
||||
when (this) {
|
||||
is Active -> generalGetString(MR.strings.server_connected)
|
||||
is Pending -> generalGetString(MR.strings.server_connecting)
|
||||
is Removed -> generalGetString(MR.strings.server_error)
|
||||
is NoSub -> generalGetString(MR.strings.server_no_sub)
|
||||
}
|
||||
|
||||
val statusExplanation: String get() =
|
||||
when (this) {
|
||||
is Active -> generalGetString(MR.strings.connected_to_server_to_receive_messages_from_contact)
|
||||
is Pending -> generalGetString(MR.strings.trying_to_connect_to_server_to_receive_messages)
|
||||
is Removed -> String.format(generalGetString(MR.strings.error_connecting_to_server_to_receive_messages), subError)
|
||||
is NoSub -> generalGetString(MR.strings.not_connected_to_server_to_receive_messages_no_sub)
|
||||
}
|
||||
}
|
||||
|
||||
interface SimplexAddress {
|
||||
val connLinkContact: CreatedConnLink
|
||||
val shortLinkDataSet: Boolean
|
||||
@@ -7306,6 +7315,7 @@ sealed class AgentErrorType {
|
||||
is RCP -> "RCP ${rcpErr.string}"
|
||||
is BROKER -> "BROKER ${brokerErr.string}"
|
||||
is AGENT -> "AGENT ${agentErr.string}"
|
||||
is NOTICE -> "NOTICE $server $expiresAt"
|
||||
is INTERNAL -> "INTERNAL $internalErr"
|
||||
is CRITICAL -> "CRITICAL $offerRestart $criticalErr"
|
||||
is INACTIVE -> "INACTIVE"
|
||||
@@ -7319,6 +7329,7 @@ sealed class AgentErrorType {
|
||||
@Serializable @SerialName("RCP") class RCP(val rcpErr: RCErrorType): AgentErrorType()
|
||||
@Serializable @SerialName("BROKER") class BROKER(val brokerAddress: String, val brokerErr: BrokerErrorType): AgentErrorType()
|
||||
@Serializable @SerialName("AGENT") class AGENT(val agentErr: SMPAgentError): AgentErrorType()
|
||||
@Serializable @SerialName("NOTICE") class NOTICE(val server: String, val preset: Boolean, val expiresAt: Instant?): AgentErrorType()
|
||||
@Serializable @SerialName("INTERNAL") class INTERNAL(val internalErr: String): AgentErrorType()
|
||||
@Serializable @SerialName("CRITICAL") data class CRITICAL(val offerRestart: Boolean, val criticalErr: String): AgentErrorType()
|
||||
@Serializable @SerialName("INACTIVE") object INACTIVE: AgentErrorType()
|
||||
@@ -8046,3 +8057,34 @@ enum class MsgType {
|
||||
@SerialName("quota")
|
||||
QUOTA
|
||||
}
|
||||
|
||||
fun showClientNoticeAlert(server: String, preset: Boolean, expiresAt: Instant?) {
|
||||
var message = "Server: $server.\nConditions of use violation notice received from ${if (preset) "preset" else "this"} server.\nNo ID shared, see How it works."
|
||||
if (expiresAt != null) {
|
||||
val tz = TimeZone.currentSystemDefault()
|
||||
val formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT)
|
||||
message += "\n\nNew addresses can be created after ${expiresAt.toLocalDateTime(tz).toJavaLocalDateTime().format(formatter)}."
|
||||
}
|
||||
AlertManager.shared.showAlertDialogButtonsColumn(title = "Not allowed", text = AnnotatedString(message)) {
|
||||
val uriHandler = LocalUriHandler.current
|
||||
Column {
|
||||
SectionItemView({ AlertManager.shared.hideAlert() }) {
|
||||
Text(generalGetString(MR.strings.ok), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary)
|
||||
}
|
||||
if (preset) {
|
||||
SectionItemView({
|
||||
AlertManager.shared.hideAlert()
|
||||
uriHandler.openUriCatching(defaultConditionsLink)
|
||||
}) {
|
||||
Text(generalGetString(MR.strings.operator_conditions_of_use), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary)
|
||||
}
|
||||
}
|
||||
SectionItemView({
|
||||
AlertManager.shared.hideAlert()
|
||||
uriHandler.openUriCatching(contentModerationPostLink)
|
||||
}) {
|
||||
Text(generalGetString(MR.strings.how_it_works), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-22
@@ -72,9 +72,6 @@ fun ChatInfoView(
|
||||
val connStats = remember(contact.id, connectionStats) { mutableStateOf(connectionStats) }
|
||||
val developerTools = chatModel.controller.appPrefs.developerTools.get()
|
||||
if (chat != null && currentUser != null) {
|
||||
val contactNetworkStatus = remember(chatModel.networkStatuses.toMap(), contact) {
|
||||
mutableStateOf(chatModel.contactNetworkStatus(contact))
|
||||
}
|
||||
val chatRh = chat.remoteHostId
|
||||
val sendReceipts = remember(contact.id) { mutableStateOf(SendReceipts.fromBool(contact.chatSettings.sendRcpts, currentUser.sendRcptsContacts)) }
|
||||
val chatItemTTL = remember(contact.id) { mutableStateOf(if (contact.chatItemTTL != null) ChatItemTTL.fromSeconds(contact.chatItemTTL) else null) }
|
||||
@@ -101,7 +98,6 @@ fun ChatInfoView(
|
||||
setChatTTLAlert(chatsCtx, chat.remoteHostId, chat.chatInfo, chatItemTTL, previousChatTTL, deletingItems)
|
||||
},
|
||||
connStats = connStats,
|
||||
contactNetworkStatus.value,
|
||||
customUserProfile,
|
||||
localAlias,
|
||||
connectionCode,
|
||||
@@ -524,7 +520,6 @@ fun ChatInfoLayout(
|
||||
chatItemTTL: MutableState<ChatItemTTL?>,
|
||||
setChatItemTTL: (ChatItemTTL?) -> Unit,
|
||||
connStats: MutableState<ConnectionStats?>,
|
||||
contactNetworkStatus: NetworkStatus,
|
||||
customUserProfile: Profile?,
|
||||
localAlias: String,
|
||||
connectionCode: String?,
|
||||
@@ -643,13 +638,16 @@ fun ChatInfoLayout(
|
||||
|
||||
if (contact.ready && contact.active) {
|
||||
SectionView(title = stringResource(MR.strings.conn_stats_section_title_servers)) {
|
||||
SectionItemView({
|
||||
AlertManager.shared.showAlertMsg(
|
||||
generalGetString(MR.strings.network_status),
|
||||
contactNetworkStatus.statusExplanation
|
||||
)
|
||||
}) {
|
||||
NetworkStatusRow(contactNetworkStatus)
|
||||
val chatSubStatus = chatModel.chatSubStatus.value
|
||||
if (chatSubStatus != null) {
|
||||
SectionItemView({
|
||||
AlertManager.shared.showAlertMsg(
|
||||
generalGetString(MR.strings.network_status),
|
||||
chatSubStatus.statusExplanation
|
||||
)
|
||||
}) {
|
||||
SubStatusRow(chatSubStatus)
|
||||
}
|
||||
}
|
||||
if (cStats != null) {
|
||||
SwitchAddressButton(
|
||||
@@ -1063,7 +1061,7 @@ fun InfoViewActionButton(
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun NetworkStatusRow(networkStatus: NetworkStatus) {
|
||||
fun SubStatusRow(subStatus: SubscriptionStatus) {
|
||||
Row(
|
||||
Modifier.fillMaxSize(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
@@ -1086,25 +1084,24 @@ private fun NetworkStatusRow(networkStatus: NetworkStatus) {
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp)
|
||||
) {
|
||||
Text(
|
||||
networkStatus.statusString,
|
||||
subStatus.statusString,
|
||||
color = MaterialTheme.colors.secondary
|
||||
)
|
||||
ServerImage(networkStatus)
|
||||
ServerImage(subStatus)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ServerImage(networkStatus: NetworkStatus) {
|
||||
private fun ServerImage(subStatus: SubscriptionStatus) {
|
||||
Box(Modifier.size(18.dp)) {
|
||||
when (networkStatus) {
|
||||
is NetworkStatus.Connected ->
|
||||
when (subStatus) {
|
||||
is SubscriptionStatus.Active ->
|
||||
Icon(painterResource(MR.images.ic_circle_filled), stringResource(MR.strings.icon_descr_server_status_connected), tint = Color.Green)
|
||||
is NetworkStatus.Disconnected ->
|
||||
is SubscriptionStatus.Pending ->
|
||||
Icon(painterResource(MR.images.ic_pending_filled), stringResource(MR.strings.icon_descr_server_status_disconnected), tint = MaterialTheme.colors.secondary)
|
||||
is NetworkStatus.Error ->
|
||||
is SubscriptionStatus.Removed, SubscriptionStatus.NoSub ->
|
||||
Icon(painterResource(MR.images.ic_error_filled), stringResource(MR.strings.icon_descr_server_status_error), tint = MaterialTheme.colors.secondary)
|
||||
else -> Icon(painterResource(MR.images.ic_circle), stringResource(MR.strings.icon_descr_server_status_pending), tint = MaterialTheme.colors.secondary)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1455,7 +1452,6 @@ fun PreviewChatInfoLayout() {
|
||||
connectionCode = "123",
|
||||
developerTools = false,
|
||||
connStats = remember { mutableStateOf(null) },
|
||||
contactNetworkStatus = NetworkStatus.Connected(),
|
||||
onLocalAliasChanged = {},
|
||||
customUserProfile = null,
|
||||
openPreferences = {},
|
||||
|
||||
+65
-2
@@ -102,6 +102,7 @@ fun ChatView(
|
||||
val chat = chatModel.chats.value.firstOrNull { chat -> chat.chatInfo.id == staleChatId.value }
|
||||
// They have their own iterator inside for a reason to prevent crash "Reading a state that was created after the snapshot..."
|
||||
val remoteHostId = remember { derivedStateOf { chatModel.chats.value.firstOrNull { chat -> chat.chatInfo.id == staleChatId.value }?.remoteHostId } }
|
||||
val chatRh = remoteHostId.value
|
||||
val activeChat = remember { derivedStateOf {
|
||||
var chat = chatModel.chats.value.firstOrNull { chat -> chat.chatInfo.id == staleChatId.value }
|
||||
val chatInfo = chat?.chatInfo
|
||||
@@ -120,6 +121,8 @@ fun ChatView(
|
||||
if (chat == null || chatInfo == null || user == null) {
|
||||
LaunchedEffect(Unit) {
|
||||
chatModel.chatId.value = null
|
||||
chatModel.chatAgentConnId.value = null
|
||||
chatModel.chatSubStatus.value = null
|
||||
ModalManager.end.closeModals()
|
||||
}
|
||||
} else {
|
||||
@@ -168,6 +171,25 @@ fun ChatView(
|
||||
showSearch.value = false
|
||||
searchText.value = ""
|
||||
selectedChatItems.value = null
|
||||
if (chat.chatInfo is ChatInfo.Direct && chat.chatInfo.contact.activeConn != null) {
|
||||
withBGApi {
|
||||
val r = chatModel.controller.apiContactInfo(chatRh, chatInfo.apiId)
|
||||
if (r != null) {
|
||||
val contactStats = r.first
|
||||
if (contactStats != null)
|
||||
withContext(Dispatchers.Main) {
|
||||
chatModel.chatsContext.updateContactConnectionStats(chatRh, chat.chatInfo.contact, contactStats)
|
||||
chatModel.chatAgentConnId.value = chat.chatInfo.contact.activeConn.agentConnId
|
||||
chatModel.chatSubStatus.value = contactStats.subStatus
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
withContext(Dispatchers.Main) {
|
||||
chatModel.chatAgentConnId.value = null
|
||||
chatModel.chatSubStatus.value = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -184,7 +206,6 @@ fun ChatView(
|
||||
}
|
||||
}
|
||||
val view = LocalMultiplatformView()
|
||||
val chatRh = remoteHostId.value
|
||||
// We need to have real unreadCount value for displaying it inside top right button
|
||||
// Having activeChat reloaded on every change in it is inefficient (UI lags)
|
||||
val unreadCount = remember {
|
||||
@@ -356,7 +377,7 @@ fun ChatView(
|
||||
if (chatInfo is ChatInfo.Direct) {
|
||||
var contactInfo: Pair<ConnectionStats?, Profile?>? by remember { mutableStateOf(preloadedContactInfo) }
|
||||
var code: String? by remember { mutableStateOf(preloadedCode) }
|
||||
KeyChangeEffect(chatInfo.id, ChatModel.networkStatuses.toMap()) {
|
||||
KeyChangeEffect(chatInfo.id) {
|
||||
contactInfo = chatModel.controller.apiContactInfo(chatRh, chatInfo.apiId)
|
||||
preloadedContactInfo = contactInfo
|
||||
code = chatModel.controller.apiGetContactCode(chatRh, chatInfo.apiId)?.second
|
||||
@@ -1281,9 +1302,51 @@ fun ChatInfoToolbarTitle(cInfo: ChatInfo, imageSize: Dp = 40.dp, iconColor: Colo
|
||||
)
|
||||
}
|
||||
}
|
||||
val chatSubStatus = chatModel.chatSubStatus.value
|
||||
if (
|
||||
cInfo is ChatInfo.Direct &&
|
||||
cInfo.contact.ready &&
|
||||
cInfo.contact.active &&
|
||||
chatSubStatus != null &&
|
||||
chatSubStatus != SubscriptionStatus.Active
|
||||
) {
|
||||
Box(
|
||||
Modifier.padding(start = 10.dp)
|
||||
) {
|
||||
SubStatusView(chatSubStatus)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SubStatusView(status: SubscriptionStatus) {
|
||||
when (status) {
|
||||
SubscriptionStatus.Active ->
|
||||
Box {}
|
||||
SubscriptionStatus.Pending ->
|
||||
SubProgressView()
|
||||
is SubscriptionStatus.Removed, SubscriptionStatus.NoSub ->
|
||||
Icon(
|
||||
painterResource(MR.images.ic_error),
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colors.secondary,
|
||||
modifier = Modifier
|
||||
.size(19.sp.toDp())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SubProgressView() {
|
||||
CircularProgressIndicator(
|
||||
Modifier
|
||||
.size(15.sp.toDp()),
|
||||
color = MaterialTheme.colors.secondary,
|
||||
strokeWidth = 1.5.dp
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SupportChatsCountToolbar(
|
||||
chatInfo: ChatInfo,
|
||||
|
||||
-1
@@ -162,7 +162,6 @@ fun acceptMemberContact(
|
||||
chatModel.chatsContext.updateContact(rhId, contact)
|
||||
inProgress?.value = false
|
||||
}
|
||||
chatModel.setContactNetworkStatus(contact, NetworkStatus.Connected())
|
||||
val chat = Chat(remoteHostId = rhId, ChatInfo.Direct(contact), listOf())
|
||||
close?.invoke(chat)
|
||||
} else {
|
||||
|
||||
-2
@@ -533,7 +533,6 @@ fun ComposeView(
|
||||
withContext(Dispatchers.Main) {
|
||||
chatsCtx.updateContact(chat.remoteHostId, contact)
|
||||
clearState()
|
||||
chatModel.setContactNetworkStatus(contact, NetworkStatus.Connected())
|
||||
}
|
||||
} else {
|
||||
composeState.value = composeState.value.copy(inProgress = false)
|
||||
@@ -554,7 +553,6 @@ fun ComposeView(
|
||||
withContext(Dispatchers.Main) {
|
||||
chatsCtx.updateContact(chat.remoteHostId, contact)
|
||||
clearState()
|
||||
chatModel.setContactNetworkStatus(contact, NetworkStatus.Connected())
|
||||
}
|
||||
} else {
|
||||
composeState.value = composeState.value.copy(inProgress = false)
|
||||
|
||||
+11
-1
@@ -109,7 +109,6 @@ fun GroupMemberInfoView(
|
||||
}
|
||||
openDirectChat(rhId, memberContact.contactId)
|
||||
closeAll()
|
||||
chatModel.setContactNetworkStatus(memberContact, NetworkStatus.Connected())
|
||||
}
|
||||
progressIndicator = false
|
||||
}
|
||||
@@ -495,6 +494,17 @@ fun GroupMemberInfoLayout(
|
||||
if (cStats != null) {
|
||||
SectionDividerSpaced()
|
||||
SectionView(title = stringResource(MR.strings.conn_stats_section_title_servers)) {
|
||||
val subStatus = cStats.subStatus
|
||||
if (subStatus != null) {
|
||||
SectionItemView({
|
||||
AlertManager.shared.showAlertMsg(
|
||||
generalGetString(MR.strings.network_status),
|
||||
subStatus.statusExplanation
|
||||
)
|
||||
}) {
|
||||
SubStatusRow(subStatus)
|
||||
}
|
||||
}
|
||||
SwitchAddressButton(
|
||||
disabled = cStats.rcvQueuesInfo.any { it.rcvSwitchStatus != null } || !member.sendMsgEnabled,
|
||||
switchAddress = switchMemberAddress
|
||||
|
||||
+3
-7
@@ -62,12 +62,11 @@ fun ChatListNavLinkView(chat: Chat, nextChatSelected: State<Boolean>) {
|
||||
|
||||
when (chat.chatInfo) {
|
||||
is ChatInfo.Direct -> {
|
||||
val contactNetworkStatus = chatModel.contactNetworkStatus(chat.chatInfo.contact)
|
||||
val defaultClickAction = { if (chatModel.chatId.value != chat.id) scope.launch { directChatAction(chat.remoteHostId, chat.chatInfo.contact, chatModel) } }
|
||||
ChatListNavLinkLayout(
|
||||
chatLinkPreview = {
|
||||
tryOrShowError("${chat.id}ChatListNavLink", error = { ErrorChatListItem() }) {
|
||||
ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, contactNetworkStatus, disabled, linkMode, inProgress = false, progressByTimeout = false, defaultClickAction)
|
||||
ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, disabled, linkMode, inProgress = false, progressByTimeout = false, defaultClickAction)
|
||||
}
|
||||
},
|
||||
click = defaultClickAction,
|
||||
@@ -87,7 +86,7 @@ fun ChatListNavLinkView(chat: Chat, nextChatSelected: State<Boolean>) {
|
||||
ChatListNavLinkLayout(
|
||||
chatLinkPreview = {
|
||||
tryOrShowError("${chat.id}ChatListNavLink", error = { ErrorChatListItem() }) {
|
||||
ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, null, disabled, linkMode, inProgress.value, progressByTimeout, defaultClickAction)
|
||||
ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, disabled, linkMode, inProgress.value, progressByTimeout, defaultClickAction)
|
||||
}
|
||||
},
|
||||
click = defaultClickAction,
|
||||
@@ -107,7 +106,7 @@ fun ChatListNavLinkView(chat: Chat, nextChatSelected: State<Boolean>) {
|
||||
ChatListNavLinkLayout(
|
||||
chatLinkPreview = {
|
||||
tryOrShowError("${chat.id}ChatListNavLink", error = { ErrorChatListItem() }) {
|
||||
ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, null, disabled, linkMode, inProgress = false, progressByTimeout = false, defaultClickAction)
|
||||
ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, disabled, linkMode, inProgress = false, progressByTimeout = false, defaultClickAction)
|
||||
}
|
||||
},
|
||||
click = defaultClickAction,
|
||||
@@ -744,7 +743,6 @@ fun acceptContactRequest(
|
||||
}
|
||||
inProgress?.value = false
|
||||
}
|
||||
chatModel.setContactNetworkStatus(contact, NetworkStatus.Connected())
|
||||
close?.invoke(chat)
|
||||
} else {
|
||||
inProgress?.value = false
|
||||
@@ -1057,7 +1055,6 @@ fun PreviewChatListNavLinkDirect() {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
disabled = false,
|
||||
linkMode = SimplexLinkMode.DESCRIPTION,
|
||||
inProgress = false,
|
||||
@@ -1103,7 +1100,6 @@ fun PreviewChatListNavLinkGroup() {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
disabled = false,
|
||||
linkMode = SimplexLinkMode.DESCRIPTION,
|
||||
inProgress = false,
|
||||
|
||||
+2
-29
@@ -42,7 +42,6 @@ fun ChatPreviewView(
|
||||
chatModelDraft: ComposeState?,
|
||||
chatModelDraftChatId: ChatId?,
|
||||
currentUserProfileDisplayName: String?,
|
||||
contactNetworkStatus: NetworkStatus?,
|
||||
disabled: Boolean,
|
||||
linkMode: SimplexLinkMode,
|
||||
inProgress: Boolean,
|
||||
@@ -349,33 +348,7 @@ fun ChatPreviewView(
|
||||
|
||||
@Composable
|
||||
fun chatStatusImage() {
|
||||
if (cInfo is ChatInfo.Direct) {
|
||||
if (
|
||||
cInfo.contact.active &&
|
||||
(cInfo.contact.activeConn?.connStatus == ConnStatus.Ready || cInfo.contact.activeConn?.connStatus == ConnStatus.SndReady)
|
||||
) {
|
||||
val descr = contactNetworkStatus?.statusString
|
||||
when (contactNetworkStatus) {
|
||||
is NetworkStatus.Connected ->
|
||||
IncognitoIcon(chat.chatInfo.incognito)
|
||||
|
||||
is NetworkStatus.Error ->
|
||||
Icon(
|
||||
painterResource(MR.images.ic_error),
|
||||
contentDescription = descr,
|
||||
tint = MaterialTheme.colors.secondary,
|
||||
modifier = Modifier
|
||||
.size(19.sp.toDp())
|
||||
.offset(x = 2.sp.toDp())
|
||||
)
|
||||
|
||||
else ->
|
||||
progressView()
|
||||
}
|
||||
} else {
|
||||
IncognitoIcon(chat.chatInfo.incognito)
|
||||
}
|
||||
} else if (cInfo is ChatInfo.Group) {
|
||||
if (cInfo is ChatInfo.Group) {
|
||||
if (progressByTimeout) {
|
||||
progressView()
|
||||
} else if (chat.chatStats.reportsCount > 0) {
|
||||
@@ -636,6 +609,6 @@ private data class ActiveVoicePreview(
|
||||
@Composable
|
||||
fun PreviewChatPreviewView() {
|
||||
SimpleXTheme {
|
||||
ChatPreviewView(Chat.sampleData, true, null, null, "", contactNetworkStatus = NetworkStatus.Connected(), disabled = false, linkMode = SimplexLinkMode.DESCRIPTION, inProgress = false, progressByTimeout = false, {})
|
||||
ChatPreviewView(Chat.sampleData, true, null, null, "", disabled = false, linkMode = SimplexLinkMode.DESCRIPTION, inProgress = false, progressByTimeout = false, {})
|
||||
}
|
||||
}
|
||||
|
||||
+7
-7
@@ -64,7 +64,7 @@ enum class SubscriptionColorType {
|
||||
ACTIVE, ACTIVE_SOCKS_PROXY, DISCONNECTED, ACTIVE_DISCONNECTED
|
||||
}
|
||||
|
||||
data class SubscriptionStatus(
|
||||
data class AppSubscriptionStatus(
|
||||
val color: SubscriptionColorType,
|
||||
val variableValue: Float,
|
||||
val statusPercent: Float
|
||||
@@ -75,7 +75,7 @@ fun subscriptionStatusColorAndPercentage(
|
||||
socksProxy: String?,
|
||||
subs: SMPServerSubs,
|
||||
hasSess: Boolean
|
||||
): SubscriptionStatus {
|
||||
): AppSubscriptionStatus {
|
||||
fun roundedToQuarter(n: Float): Float = when {
|
||||
n >= 1 -> 1f
|
||||
n <= 0 -> 0f
|
||||
@@ -83,25 +83,25 @@ fun subscriptionStatusColorAndPercentage(
|
||||
}
|
||||
|
||||
val activeColor: SubscriptionColorType = if (socksProxy != null) SubscriptionColorType.ACTIVE_SOCKS_PROXY else SubscriptionColorType.ACTIVE
|
||||
val noConnColorAndPercent = SubscriptionStatus(SubscriptionColorType.DISCONNECTED, 1f, 0f)
|
||||
val noConnColorAndPercent = AppSubscriptionStatus(SubscriptionColorType.DISCONNECTED, 1f, 0f)
|
||||
val activeSubsRounded = roundedToQuarter(subs.shareOfActive)
|
||||
|
||||
return if (!online)
|
||||
noConnColorAndPercent
|
||||
else if (subs.total == 0 && !hasSess)
|
||||
// On freshly installed app (without chats) and on app start
|
||||
SubscriptionStatus(activeColor, 0f, 0f)
|
||||
AppSubscriptionStatus(activeColor, 0f, 0f)
|
||||
else if (subs.ssActive == 0) {
|
||||
if (hasSess)
|
||||
SubscriptionStatus(activeColor, activeSubsRounded, subs.shareOfActive)
|
||||
AppSubscriptionStatus(activeColor, activeSubsRounded, subs.shareOfActive)
|
||||
else
|
||||
noConnColorAndPercent
|
||||
} else { // ssActive > 0
|
||||
if (hasSess)
|
||||
SubscriptionStatus(activeColor, activeSubsRounded, subs.shareOfActive)
|
||||
AppSubscriptionStatus(activeColor, activeSubsRounded, subs.shareOfActive)
|
||||
else
|
||||
// This would mean implementation error
|
||||
SubscriptionStatus(SubscriptionColorType.ACTIVE_DISCONNECTED, activeSubsRounded, subs.shareOfActive)
|
||||
AppSubscriptionStatus(SubscriptionColorType.ACTIVE_DISCONNECTED, activeSubsRounded, subs.shareOfActive)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -612,13 +612,14 @@ private fun SingleOperatorUsageConditionsView(
|
||||
}
|
||||
}
|
||||
|
||||
val defaultConditionsLink = "https://github.com/simplex-chat/simplex-chat/blob/stable/PRIVACY.md"
|
||||
|
||||
@Composable
|
||||
fun ConditionsTextView(
|
||||
rhId: Long?
|
||||
) {
|
||||
val conditionsData = remember { mutableStateOf<Triple<UsageConditionsDetail, String?, UsageConditionsDetail?>?>(null) }
|
||||
val failedToLoad = remember { mutableStateOf(false) }
|
||||
val defaultConditionsLink = "https://github.com/simplex-chat/simplex-chat/blob/stable/PRIVACY.md"
|
||||
val scope = rememberCoroutineScope()
|
||||
// can show conditions when animation between modals finishes to prevent glitches
|
||||
val canShowConditionsAt = remember { System.currentTimeMillis() + 300 }
|
||||
|
||||
@@ -1131,7 +1131,7 @@
|
||||
<string name="trying_to_connect_to_server_to_receive_messages">محاولة الاتصال بالخادم المستخدم لاستلام الرسائل من جهة الاتصال هذه.</string>
|
||||
<string name="choose_file_title">اختيار ملف</string>
|
||||
<string name="icon_descr_sent_msg_status_unauthorized_send">إرسال غير مصرح به</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">محاولة الاتصال بالخادم المستخدم لاستلام الرسائل من جهة الاتصال هذه (خطأ: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">محاولة الاتصال بالخادم المستخدم لاستلام الرسائل من جهة الاتصال هذه (خطأ: %1$s).</string>
|
||||
<string name="la_notice_turn_on">تشغيل</string>
|
||||
<string name="webrtc_ice_servers">خوادم WebRTC ICE</string>
|
||||
<string name="alert_title_cant_invite_contacts_descr">أنت تستخدم ملف تعريف متخفي لهذه المجموعة - لمنع مشاركة ملفك التعريفي الرئيسي الذي يدعو جهات الاتصال غير مسموح به</string>
|
||||
|
||||
@@ -32,9 +32,11 @@
|
||||
<string name="server_connected">connected</string>
|
||||
<string name="server_error">error</string>
|
||||
<string name="server_connecting">connecting</string>
|
||||
<string name="connected_to_server_to_receive_messages_from_contact">You are connected to the server used to receive messages from this contact.</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Trying to connect to the server used to receive messages from this contact (error: %1$s).</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages">Trying to connect to the server used to receive messages from this contact.</string>
|
||||
<string name="server_no_sub">no subscription</string>
|
||||
<string name="connected_to_server_to_receive_messages_from_contact">You are connected to the server used to receive messages from this connection.</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages">Trying to connect to the server used to receive messages from this connection.</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">Error connecting to the server used to receive messages from this connection: %1$s.</string>
|
||||
<string name="not_connected_to_server_to_receive_messages_no_sub">You are not connected to the server used to receive messages from this connection (no subscription).</string>
|
||||
|
||||
<!-- Item Content - ChatModel.kt -->
|
||||
<string name="deleted_description">deleted</string>
|
||||
|
||||
@@ -1182,7 +1182,7 @@
|
||||
<string name="messages_section_description">Тази настройка се прилага за съобщения в текущия ви профил</string>
|
||||
<string name="to_protect_privacy_simplex_has_ids_for_queues">За да се защити поверителността, SimpleX използва идентификатори за опашки от съобщения, отделни за всеки от вашите контакти.</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages">Опит за свързване със сървъра, използван за получаване на съобщения от този контакт.</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Опит за свързване със сървъра, използван за получаване на съобщения от този контакт (грешка: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">Опит за свързване със сървъра, използван за получаване на съобщения от този контакт (грешка: %1$s).</string>
|
||||
<string name="error_smp_test_failed_at_step">Тестът е неуспешен на стъпка %s.</string>
|
||||
<string name="database_initialization_error_desc">Базата данни не работи правилно. Докоснете, за да научите повече</string>
|
||||
<string name="image_decoding_exception_desc">Изображението не може да бъде декодирано. Моля, опитайте с друго изображение или се свържете с разработчиците.</string>
|
||||
|
||||
@@ -1556,7 +1556,7 @@
|
||||
<string name="error_parsing_uri_desc">Comproveu que l\'enllaç SimpleX sigui correcte.</string>
|
||||
<string name="sending_files_not_yet_supported">l\'enviament de fitxers encara no està suportat</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages">Intentant connectar-se al servidor utilitzat per rebre missatges d\'aquest contacte.</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">S\'està provant de connectar-se al servidor utilitzat per rebre missatges d\'aquest contacte (error: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">S\'està provant de connectar-se al servidor utilitzat per rebre missatges d\'aquest contacte (error: %1$s).</string>
|
||||
<string name="connect_use_current_profile">Usar perfil actual</string>
|
||||
<string name="connect_use_new_incognito_profile">Usar nou perfil incògnit</string>
|
||||
<string name="app_was_crashed">Error aplicació</string>
|
||||
|
||||
@@ -493,7 +493,7 @@
|
||||
<string name="you_will_join_group">Připojtíte se ke všem členům skupiny.</string>
|
||||
<string name="connect_via_link_verb">Připojení</string>
|
||||
<string name="connected_to_server_to_receive_messages_from_contact">Jste připojeni k serveru, který se používá k přijímání zpráv od tohoto kontaktu.</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Pokoušíte se připojit k serveru používaném pro příjem zpráv od tohoto kontaktu (chyba: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">Pokoušíte se připojit k serveru používaném pro příjem zpráv od tohoto kontaktu (chyba: %1$s).</string>
|
||||
<string name="marked_deleted_description">označeno jako smazáno</string>
|
||||
<string name="sending_files_not_yet_supported">Odesílání souborů zatím není podporováno</string>
|
||||
<string name="receiving_files_not_yet_supported">přijímání souborů zatím není podporováno</string>
|
||||
|
||||
@@ -178,7 +178,7 @@
|
||||
<string name="server_error">fejl</string>
|
||||
<string name="server_connecting">forbinder</string>
|
||||
<string name="connected_to_server_to_receive_messages_from_contact">Du har forbindelse til den server, der bruges til at modtage beskeder fra denne kontakt.</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Forsøger at oprette forbindelse til den server, der bruges til at modtage beskeder fra denne kontakt (fejl: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">Forsøger at oprette forbindelse til den server, der bruges til at modtage beskeder fra denne kontakt (fejl: %1$s).</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages">Forsøger at oprette forbindelse til den server, der bruges til at modtage beskeder fra denne kontakt.</string>
|
||||
<string name="deleted_description">slettet</string>
|
||||
<string name="marked_deleted_description">markeret som slettet</string>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<string name="server_error">Fehler</string>
|
||||
<string name="server_connecting">Verbinde</string>
|
||||
<string name="connected_to_server_to_receive_messages_from_contact">Sie sind mit dem Server verbunden, der für den Empfang von Nachrichten mit diesem Kontakt genutzt wird.</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Beim Versuch, die Verbindung mit dem Server aufzunehmen, der für den Empfang von Nachrichten mit diesem Kontakt genutzt wird, ist ein Fehler aufgetreten (Fehler: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">Beim Versuch, die Verbindung mit dem Server aufzunehmen, der für den Empfang von Nachrichten mit diesem Kontakt genutzt wird, ist ein Fehler aufgetreten (Fehler: %1$s).</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages">Versuche die Verbindung mit dem Server aufzunehmen, der für den Empfang von Nachrichten mit diesem Kontakt genutzt wird.</string>
|
||||
<!-- Item Content - ChatModel.kt -->
|
||||
<string name="deleted_description">Gelöscht</string>
|
||||
|
||||
@@ -806,7 +806,7 @@
|
||||
<string name="update_network_settings_question">¿Actualizar la configuración de red\?</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages">Intentando conectar con el servidor para recibir mensajes de este contacto.</string>
|
||||
<string name="unknown_message_format">formato de mensaje desconocido</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Intentando conectar con el servidor para recibir mensajes de este contacto (error: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">Intentando conectar con el servidor para recibir mensajes de este contacto (error: %1$s).</string>
|
||||
<string name="error_smp_test_failed_at_step">Prueba no superada en el paso %s.</string>
|
||||
<string name="tap_to_start_new_chat">Pulsa para iniciar chat nuevo</string>
|
||||
<string name="share_message">Compartir mensaje…</string>
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<string name="connect_via_link_verb">متصل شدن</string>
|
||||
<string name="non_content_uri_alert_title">مسیر نامعتبر فایل</string>
|
||||
<string name="app_was_crashed">برنامه از کار افتاد</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">در حال تلاش برای اتصال به سرور مورد استفاده برای دریافت پیامها از این مخاطب (خطا: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">در حال تلاش برای اتصال به سرور مورد استفاده برای دریافت پیامها از این مخاطب (خطا: %1$s).</string>
|
||||
<string name="deleted_description">حذف شد</string>
|
||||
<string name="marked_deleted_description">علامت گذاشته شده به عنوان حذف شده</string>
|
||||
<string name="moderated_item_description">توسط %s حذف شد</string>
|
||||
|
||||
@@ -1036,7 +1036,7 @@
|
||||
<string name="profile_will_be_sent_to_contact_sending_link">Profiilisi lähetetään kontaktille, jolta sait tämän linkin.</string>
|
||||
<string name="you_will_join_group">Liityt ryhmään, johon tämä linkki viittaa, ja muodostat yhteyden sen ryhmän jäseniin.</string>
|
||||
<string name="connected_to_server_to_receive_messages_from_contact">Olet yhteydessä palvelimeen, jota käytetään vastaanottamaan viestejä tältä kontaktilta.</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Yritetään muodostaa yhteys palvelimeen, jota käytetään viestien vastaanottamiseen tältä kontaktilta (virhe: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">Yritetään muodostaa yhteys palvelimeen, jota käytetään viestien vastaanottamiseen tältä kontaktilta (virhe: %1$s).</string>
|
||||
<string name="sender_you_pronoun">sinä</string>
|
||||
<string name="description_via_one_time_link">kertalinkillä</string>
|
||||
<string name="simplex_link_connection">%1$s:n kautta</string>
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
<string name="please_check_correct_link_and_maybe_ask_for_a_new_one">Veuillez vérifier que vous avez utilisé le bon lien ou demandez à votre contact de vous en envoyer un autre.</string>
|
||||
<string name="connection_error">Erreur de connexion</string>
|
||||
<string name="error_adding_members">Erreur lors de l\'ajout de membre·s</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Tentative de connexion au serveur utilisé pour recevoir les messages de ce contact (erreur : %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">Tentative de connexion au serveur utilisé pour recevoir les messages de ce contact (erreur : %1$s).</string>
|
||||
<string name="invalid_message_format">format de message invalide</string>
|
||||
<string name="simplex_link_mode_full">Lien entier</string>
|
||||
<string name="error_saving_smp_servers">Erreur lors de la sauvegarde des serveurs SMP</string>
|
||||
|
||||
@@ -1317,7 +1317,7 @@
|
||||
<string name="image_decoding_exception_desc">A kép nem dekódolható. Próbálja meg egy másik képpel, vagy lépjen kapcsolatba a fejlesztőkkel.</string>
|
||||
<string name="non_content_uri_alert_text">Érvénytelen fájlelérési útvonalat osztott meg. Jelentse a problémát az alkalmazás fejlesztőinek.</string>
|
||||
<string name="failed_to_create_user_duplicate_desc">Már van egy csevegési profil ugyanezzel a megjelenítendő névvel. Válasszon egy másik nevet.</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Kapcsolódási kísérlet ahhoz a kiszolgálóhoz, amely az adott partnerétől érkező üzenetek fogadására szolgál (hiba: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">Kapcsolódási kísérlet ahhoz a kiszolgálóhoz, amely az adott partnerétől érkező üzenetek fogadására szolgál (hiba: %1$s).</string>
|
||||
<string name="stop_rcv_file__message">A fájl fogadása le fog állni.</string>
|
||||
<string name="la_please_remember_to_store_password">Ne felejtse el, vagy tárolja biztonságosan – az elveszett jelszót nem lehet visszaállítani!</string>
|
||||
<string name="video_will_be_received_when_contact_completes_uploading">A videó akkor érkezik meg, amikor a küldője befejezte annak feltöltését.</string>
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
<string name="error_parsing_uri_title">Tautan tidak valid</string>
|
||||
<string name="error_parsing_uri_desc">Periksa apakah tautan SimpleX sudah benar.</string>
|
||||
<string name="connected_to_server_to_receive_messages_from_contact">Anda terhubung ke server yang digunakan untuk menerima pesan dari kontak ini.</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Mencoba menyambung ke server yang digunakan untuk menerima pesan dari kontak ini (error: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">Mencoba menyambung ke server yang digunakan untuk menerima pesan dari kontak ini (error: %1$s).</string>
|
||||
<string name="database_migration_in_progress">Migrasi basis data sedang berlangsung,
|
||||
\nmemerlukan waktu beberapa menit.</string>
|
||||
<string name="server_connecting">menghubungkan</string>
|
||||
|
||||
@@ -201,7 +201,7 @@
|
||||
<string name="reset_verb">Ripristina</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="connect_via_contact_link">Connettere via indirizzo del contatto?</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Tentativo di connessione al server usato per ricevere messaggi da questo contatto (errore: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">Tentativo di connessione al server usato per ricevere messaggi da questo contatto (errore: %1$s).</string>
|
||||
<string name="you_will_join_group">Ti connetterai a tutti i membri del gruppo.</string>
|
||||
<string name="connection_local_display_name">connessione %1$d</string>
|
||||
<string name="simplex_link_mode_description">Descrizione</string>
|
||||
|
||||
@@ -1063,7 +1063,7 @@
|
||||
<string name="to_verify_compare">כדי לאמת הצפנה מקצה־לקצה עם איש הקשר שלכם, יש להשוות (או לסרוק) את הקוד במכשירים שלכם.</string>
|
||||
<string name="your_chat_profiles">פרופילי צ׳אט</string>
|
||||
<string name="update_network_session_mode_question">לעדכן מצב בידוד תעבורה\?</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">מנסה להתחבר לשרת המשמש לקבלת הודעות מאיש קשר זה (שגיאה: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">מנסה להתחבר לשרת המשמש לקבלת הודעות מאיש קשר זה (שגיאה: %1$s).</string>
|
||||
<string name="unknown_message_format">פורמט הודעה לא ידוע</string>
|
||||
<string name="simplex_link_mode_browser">דרך הדפדפן</string>
|
||||
<string name="unmute_chat">בטל השתקה</string>
|
||||
|
||||
@@ -887,7 +887,7 @@
|
||||
<string name="to_protect_privacy_simplex_has_ids_for_queues">あなたのプライバシーを守るために、他のアプリと違って、ユーザーIDの変わりに SimpleX メッセージ束毎にIDを配布し、各連絡先が別々と扱います。</string>
|
||||
<string name="group_main_profile_sent">あなたのチャットプロフィールが他のグループメンバーに公開されます。</string>
|
||||
<string name="to_verify_compare">エンドツーエンド暗号化を確認するには、ご自分の端末と連絡先の端末のコードを比べます (スキャンします)。</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">このコンタクトから受信するメッセージのサーバに接続しようとしてます。(エラー: %1$s)。</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">このコンタクトから受信するメッセージのサーバに接続しようとしてます。(エラー: %1$s)。</string>
|
||||
<string name="connection_error_auth_desc">使用済みリンク、または連絡先による接続の削除ではなければ、バッグの可能性があります。開発者にお伝えください。
|
||||
\n繋がるには、連絡先に新しくリンクを発行してもらって、電波が安定かどうかご確認ください。</string>
|
||||
<string name="alert_text_connection_pending_they_need_to_be_online_can_delete_and_retry">接続を完了するには、連絡相手がオンラインになる必要があります。
|
||||
|
||||
@@ -1404,7 +1404,7 @@
|
||||
<string name="profile_will_be_sent_to_contact_sending_link">Jūsų profilis bus išsiųstas kontaktui iš kurio gavote šią nuorodą.</string>
|
||||
<string name="you_will_join_group">Prisijungsite prie visų grupės narių.</string>
|
||||
<string name="connected_to_server_to_receive_messages_from_contact">Esate prisijungę prie serverio skirto gauti žinutes iš šio kontakto.</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Bandoma prisijungti prie serverio skirto žinučių gavimui iš šio kontakto (klaida: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">Bandoma prisijungti prie serverio skirto žinučių gavimui iš šio kontakto (klaida: %1$s).</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages">Bandoma prisijungti prie serverio skirto žinučių gavimui iš šio kontakto.</string>
|
||||
<string name="no_details">nėra detalių</string>
|
||||
<string name="to_preserve_privacy_simplex_has_background_service_instead_of_push_notifications_it_uses_a_few_pc_battery"><![CDATA[Kad išlaikyti jūsų privatumą, vietoj tiesioginių pranešimų, programėlė turi <b>SimpleX fono tarnybą</b> - ji naudoja kelis procentus akumuliatoriaus per dieną.]]></string>
|
||||
|
||||
@@ -913,7 +913,7 @@
|
||||
<string name="simplex_link_mode">SimpleX links</string>
|
||||
<string name="simplex_link_invitation">Eenmalige SimpleX uitnodiging</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages">Proberen verbinding te maken met de server die wordt gebruikt om berichten van dit contact te ontvangen.</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Er wordt geprobeerd verbinding te maken met de server die wordt gebruikt om berichten van dit contact te ontvangen (fout: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">Er wordt geprobeerd verbinding te maken met de server die wordt gebruikt om berichten van dit contact te ontvangen (fout: %1$s).</string>
|
||||
<string name="unknown_message_format">onbekend berichtformaat</string>
|
||||
<string name="simplex_link_mode_browser">Via browser</string>
|
||||
<string name="description_via_contact_address_link">via contact adres link</string>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<string name="sending_files_not_yet_supported">wysyłanie plików nie jest jeszcze obsługiwane</string>
|
||||
<string name="receiving_files_not_yet_supported">odbieranie plików nie jest jeszcze obsługiwane</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages">Próbowanie połączenia z serwerem używanym do odbierania wiadomości od tego kontaktu.</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Próbowanie połączenia z serwerem używanym do odbierania wiadomości od tego kontaktu (błąd: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">Próbowanie połączenia z serwerem używanym do odbierania wiadomości od tego kontaktu (błąd: %1$s).</string>
|
||||
<string name="unknown_message_format">nieznany format wiadomości</string>
|
||||
<string name="app_name">SimpleX</string>
|
||||
<string name="sender_you_pronoun">Ty</string>
|
||||
|
||||
@@ -971,7 +971,7 @@
|
||||
<string name="tap_to_activate_profile">Toque para ativar o perfil.</string>
|
||||
<string name="unhide_chat_profile">Mostrar perfil de chat</string>
|
||||
<string name="unhide_profile">Mostrar perfil</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Tentando se conectar ao servidor utilizado para receber mensagens deste contato (erro:%1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">Tentando se conectar ao servidor utilizado para receber mensagens deste contato (erro:%1$s).</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages">Tentando se conectar ao servidor utilizado para receber mensagens deste contato.</string>
|
||||
<string name="connected_to_server_to_receive_messages_from_contact">Você está conectado ao servidor usado para receber mensagens desse contato.</string>
|
||||
<string name="smp_servers_your_server">Seu servidor</string>
|
||||
|
||||
@@ -2077,7 +2077,7 @@
|
||||
<string name="image_decoding_exception_desc">Imaginea nu poate fi decodificată. Vă rugăm să încercați o altă imagine sau să contactați dezvoltatorii.</string>
|
||||
<string name="xftp_servers_per_user">Serverele pentru fișierele noi ale profilului tău de conversații actual</string>
|
||||
<string name="alert_message_no_group">Acest grup nu mai există.</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Se încearcă conectarea la serverul folosit pentru a primi mesaje de la acest contact (eroare: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">Se încearcă conectarea la serverul folosit pentru a primi mesaje de la acest contact (eroare: %1$s).</string>
|
||||
<string name="updating_settings_will_reconnect_client_to_all_servers">Actualizarea setărilor va reconecta clientul la toate serverele.</string>
|
||||
<string name="this_string_is_not_a_connection_link">Acest șir de caractere nu este un link!</string>
|
||||
<string name="remote_ctrl_error_timeout">S-a atins timpul de expirare la conectarea la desktop</string>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<string name="server_error">ошибка</string>
|
||||
<string name="server_connecting">соединяется</string>
|
||||
<string name="connected_to_server_to_receive_messages_from_contact">Установлено соединение с сервером, через который Вы получаете сообщения от этого контакта.</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Устанавливается соединение с сервером, через который Вы получаете сообщения от этого контакта (ошибка: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">Устанавливается соединение с сервером, через который Вы получаете сообщения от этого контакта (ошибка: %1$s).</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages">Устанавливается соединение с сервером, через который Вы получаете сообщения от этого контакта.</string>
|
||||
<!-- Item Content - ChatModel.kt -->
|
||||
<string name="deleted_description">удалено</string>
|
||||
|
||||
@@ -1043,7 +1043,7 @@
|
||||
<string name="you_are_invited_to_group">คุณได้รับเชิญให้เข้าร่วมกลุ่ม</string>
|
||||
<string name="incognito_random_profile">โปรไฟล์แบบสุ่มของคุณ</string>
|
||||
<string name="theme">ธีม</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">กำลังพยายามเชื่อมต่อกับเซิร์ฟเวอร์ที่ใช้รับข้อความจากผู้ติดต่อนี้ (ข้อผิดพลาด: %1$s)</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">กำลังพยายามเชื่อมต่อกับเซิร์ฟเวอร์ที่ใช้รับข้อความจากผู้ติดต่อนี้ (ข้อผิดพลาด: %1$s)</string>
|
||||
<string name="app_name">SimpleX</string>
|
||||
<string name="connected_to_server_to_receive_messages_from_contact">คุณเชื่อมต่อกับเซิร์ฟเวอร์ที่ใช้รับข้อความจากผู้ติดต่อนี้</string>
|
||||
<string name="profile_will_be_sent_to_contact_sending_link">โปรไฟล์ของคุณจะถูกส่งไปยังผู้ติดต่อที่ส่งลิงก์นี้มาให้คุณ</string>
|
||||
|
||||
@@ -1023,7 +1023,7 @@
|
||||
<string name="v4_6_hidden_chat_profiles_descr">Sohbet profillerini parola ile koru!</string>
|
||||
<string name="v4_5_reduced_battery_usage">Daha az pil kullanımı</string>
|
||||
<string name="to_protect_privacy_simplex_has_ids_for_queues">Gizliliği korumak için, SimpleX her bir konuşma için farklı bir ID kullanır.</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Bu kişiden mesaj almak için kullanılan sunucuya bağlanılmaya çalışılıyor (hata: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">Bu kişiden mesaj almak için kullanılan sunucuya bağlanılmaya çalışılıyor (hata: %1$s).</string>
|
||||
<string name="v4_4_live_messages_desc">Alıcılar güncellemeleri siz yazdıkça görürler.</string>
|
||||
<string name="auth_log_in_using_credential">Bilgilerinizi kullanarak giriş yapın</string>
|
||||
<string name="markdown_in_messages">Mesajlarda Markdown</string>
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
<string name="server_error">помилка</string>
|
||||
<string name="server_connecting">підключення</string>
|
||||
<string name="connected_to_server_to_receive_messages_from_contact">Ви підключені до сервера для отримання повідомлень від цього контакту.</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Спроба підключитися до сервера для отримання повідомлень від цього контакту (помилка: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">Спроба підключитися до сервера для отримання повідомлень від цього контакту (помилка: %1$s).</string>
|
||||
<string name="deleted_description">видалено</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages">Спроба підключитися до сервера для отримання повідомлень від цього контакту.</string>
|
||||
<string name="marked_deleted_description">відзначено як видалено</string>
|
||||
|
||||
@@ -2034,7 +2034,7 @@
|
||||
<string name="la_notice_turn_on">Bật</string>
|
||||
<string name="servers_info_subscriptions_total">Tổng</string>
|
||||
<string name="group_member_status_unknown_short">không xác định</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Đang cố gắng kết nối tới máy chủ dùng để nhận tin nhắn từ liên hệ này (lỗi: %1$s).</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">Đang cố gắng kết nối tới máy chủ dùng để nhận tin nhắn từ liên hệ này (lỗi: %1$s).</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages">Đang cố gắng kết nối tới máy chủ dùng để nhận tin nhắn từ liên hệ này.</string>
|
||||
<string name="to_verify_compare">Để xác minh mã hóa đầu cuối với liên hệ của bạn, so sánh (hoặc quét) mã trên các thiết bị của các bạn.</string>
|
||||
<string name="network_session_mode_transport_isolation">Cách ly truyền tải</string>
|
||||
|
||||
@@ -589,7 +589,7 @@
|
||||
<string name="rcv_group_event_member_deleted">已删除 %1$s</string>
|
||||
<string name="snd_group_event_member_deleted">你删除了 %1$s</string>
|
||||
<string name="profile_will_be_sent_to_contact_sending_link">你的个人资料将发送给你收到此链接的联系人。</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">正在尝试连接到用于从该联系人接收消息的服务器(错误:%1$s)。</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">正在尝试连接到用于从该联系人接收消息的服务器(错误:%1$s)。</string>
|
||||
<string name="connected_to_server_to_receive_messages_from_contact">你已连接到用于接收该联系人消息的服务器。</string>
|
||||
<string name="description_you_shared_one_time_link">你分享了一次性链接</string>
|
||||
<string name="message_delivery_error_desc">很可能此联系人已经删除了与你的联系。</string>
|
||||
|
||||
@@ -238,7 +238,7 @@
|
||||
<string name="server_error">錯誤</string>
|
||||
<string name="server_connecting">連接中</string>
|
||||
<string name="connected_to_server_to_receive_messages_from_contact">你已連接到此聯絡人使用的伺服器以接收訊息。</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages_with_error">嘗試連接至用於接收此聯絡人訊息的伺服器 (錯誤:%1$s)。</string>
|
||||
<string name="error_connecting_to_server_to_receive_messages">嘗試連接至用於接收此聯絡人訊息的伺服器 (錯誤:%1$s)。</string>
|
||||
<string name="trying_to_connect_to_server_to_receive_messages">正在嘗試連接到用於接收此聯絡人訊息伺服器。</string>
|
||||
<string name="deleted_description">已刪除</string>
|
||||
<string name="marked_deleted_description">已標記為已刪除</string>
|
||||
|
||||
Reference in New Issue
Block a user