Merge branch 'master' into master-ghc8107

This commit is contained in:
Evgeny Poberezkin
2024-01-20 15:07:20 +00:00
161 changed files with 10816 additions and 6167 deletions
@@ -66,7 +66,7 @@ fun MainScreen() {
!chatModel.controller.appPrefs.laNoticeShown.get()
&& showAdvertiseLAAlert
&& chatModel.controller.appPrefs.onboardingStage.get() == OnboardingStage.OnboardingComplete
&& chatModel.chats.count() > 1
&& chatModel.chats.size > 2
&& chatModel.activeCallInvitation.value == null
) {
AppLock.showLANotice(ChatModel.controller.appPrefs.laNoticeShown) }
@@ -152,7 +152,7 @@ object ChatModel {
fun removeUser(user: User) {
val i = getUserIndex(user)
if (i != -1 && users[i].user.userId != currentUser.value?.userId) {
if (i != -1) {
users.removeAt(i)
}
}
@@ -663,6 +663,7 @@ data class ShowingInvitation(
enum class ChatType(val type: String) {
Direct("@"),
Group("#"),
Local("*"),
ContactRequest("<@"),
ContactConnection(":");
}
@@ -782,6 +783,7 @@ data class Chat(
get() = when (chatInfo) {
is ChatInfo.Direct -> true
is ChatInfo.Group -> chatInfo.groupInfo.membership.memberRole >= GroupMemberRole.Member
is ChatInfo.Local -> true
else -> false
}
@@ -864,6 +866,30 @@ sealed class ChatInfo: SomeChat, NamedChat {
}
}
@Serializable @SerialName("local")
data class Local(val noteFolder: NoteFolder): ChatInfo() {
override val chatType get() = ChatType.Local
override val localDisplayName get() = noteFolder.localDisplayName
override val id get() = noteFolder.id
override val apiId get() = noteFolder.apiId
override val ready get() = noteFolder.ready
override val sendMsgEnabled get() = noteFolder.sendMsgEnabled
override val ntfsEnabled get() = noteFolder.ntfsEnabled
override val incognito get() = noteFolder.incognito
override fun featureEnabled(feature: ChatFeature) = noteFolder.featureEnabled(feature)
override val timedMessagesTTL: Int? get() = noteFolder.timedMessagesTTL
override val createdAt get() = noteFolder.createdAt
override val updatedAt get() = noteFolder.updatedAt
override val displayName get() = noteFolder.displayName
override val fullName get() = noteFolder.fullName
override val image get() = noteFolder.image
override val localAlias get() = noteFolder.localAlias
companion object {
val sampleData = Local(NoteFolder.sampleData)
}
}
@Serializable @SerialName("contactRequest")
class ContactRequest(val contactRequest: UserContactRequest): ChatInfo() {
override val chatType get() = ChatType.ContactRequest
@@ -1253,6 +1279,7 @@ data class GroupMember (
val memberCategory: GroupMemberCategory,
val memberStatus: GroupMemberStatus,
val memberSettings: GroupMemberSettings,
val blockedByAdmin: Boolean,
val invitedBy: InvitedBy,
val localDisplayName: String,
val memberProfile: LocalProfile,
@@ -1271,6 +1298,7 @@ data class GroupMember (
val image: String? get() = memberProfile.image
val contactLink: String? = memberProfile.contactLink
val verified get() = activeConn?.connectionCode != null
val blocked get() = blockedByAdmin || !memberSettings.showMessages
val chatViewName: String
get() {
@@ -1319,7 +1347,7 @@ data class GroupMember (
fun canBeRemoved(groupInfo: GroupInfo): Boolean {
val userRole = groupInfo.membership.memberRole
return memberStatus != GroupMemberStatus.MemRemoved && memberStatus != GroupMemberStatus.MemLeft
&& userRole >= GroupMemberRole.Admin && userRole >= memberRole && groupInfo.membership.memberCurrent
&& userRole >= GroupMemberRole.Admin && userRole >= memberRole && groupInfo.membership.memberActive
}
fun canChangeRoleTo(groupInfo: GroupInfo): List<GroupMemberRole>? =
@@ -1328,6 +1356,12 @@ data class GroupMember (
GroupMemberRole.values().filter { it <= userRole && it != GroupMemberRole.Author }
}
fun canBlockForAll(groupInfo: GroupInfo): Boolean {
val userRole = groupInfo.membership.memberRole
return memberStatus != GroupMemberStatus.MemRemoved && memberStatus != GroupMemberStatus.MemLeft && memberRole < GroupMemberRole.Admin
&& userRole >= GroupMemberRole.Admin && userRole >= memberRole && groupInfo.membership.memberActive
}
val memberIncognito = memberProfile.profileId != memberContactProfileId
companion object {
@@ -1339,6 +1373,7 @@ data class GroupMember (
memberCategory = GroupMemberCategory.InviteeMember,
memberStatus = GroupMemberStatus.MemComplete,
memberSettings = GroupMemberSettings(showMessages = true),
blockedByAdmin = false,
invitedBy = InvitedBy.IBUser(),
localDisplayName = "alice",
memberProfile = LocalProfile.sampleData,
@@ -1466,6 +1501,40 @@ class MemberSubError (
val memberError: ChatError
)
@Serializable
class NoteFolder(
val noteFolderId: Long,
val favorite: Boolean,
val unread: Boolean,
override val createdAt: Instant,
override val updatedAt: Instant
): SomeChat, NamedChat {
override val chatType get() = ChatType.Local
override val id get() = "*$noteFolderId"
override val apiId get() = noteFolderId
override val ready get() = true
override val sendMsgEnabled get() = true
override val ntfsEnabled get() = false
override val incognito get() = false
override fun featureEnabled(feature: ChatFeature) = feature == ChatFeature.Voice
override val timedMessagesTTL: Int? get() = null
override val displayName get() = generalGetString(MR.strings.note_folder_local_display_name)
override val fullName get() = ""
override val image get() = null
override val localAlias get() = ""
override val localDisplayName: String get() = ""
companion object {
val sampleData = NoteFolder(
noteFolderId = 1,
favorite = false,
unread = false,
createdAt = Clock.System.now(),
updatedAt = Clock.System.now()
)
}
}
@Serializable
class UserContactRequest (
val contactRequestId: Long,
@@ -1645,8 +1714,28 @@ data class ChatItem (
val encryptedFile: Boolean? = if (file?.fileSource == null) null else file.fileSource.cryptoArgs != null
val memberDisplayName: String? get() =
if (chatDir is CIDirection.GroupRcv) chatDir.groupMember.chatViewName
else null
when (chatDir) {
is CIDirection.GroupRcv -> when (content) {
is CIContent.RcvGroupEventContent -> when (val event = content.rcvGroupEvent) {
is RcvGroupEvent.MemberProfileUpdated -> {
val to = event.toProfile
val from = event.fromProfile
when {
to.displayName != from.displayName || to.fullName != from.fullName -> null
else -> chatDir.groupMember.chatViewName
}
}
else -> chatDir.groupMember.chatViewName
}
else -> chatDir.groupMember.chatViewName
}
else -> null
}
val localNote: Boolean = chatDir is CIDirection.LocalSnd || chatDir is CIDirection.LocalRcv
val isDeletedContent: Boolean get() =
when (content) {
@@ -1654,6 +1743,7 @@ data class ChatItem (
is CIContent.RcvDeleted -> true
is CIContent.SndModerated -> true
is CIContent.RcvModerated -> true
is CIContent.RcvBlocked -> true
else -> false
}
@@ -1705,47 +1795,51 @@ data class ChatItem (
}
}
private val showNtfDir: Boolean get() = !chatDir.sent
val showNotification: Boolean get() =
when (content) {
is CIContent.SndMsgContent -> showNtfDir
is CIContent.RcvMsgContent -> showNtfDir
is CIContent.SndDeleted -> showNtfDir
is CIContent.RcvDeleted -> showNtfDir
is CIContent.SndCall -> showNtfDir
is CIContent.SndMsgContent -> false
is CIContent.RcvMsgContent -> meta.itemDeleted == null
is CIContent.SndDeleted -> false
is CIContent.RcvDeleted -> false
is CIContent.SndCall -> false
is CIContent.RcvCall -> false // notification is shown on CallInvitation instead
is CIContent.RcvIntegrityError -> showNtfDir
is CIContent.RcvDecryptionError -> showNtfDir
is CIContent.RcvGroupInvitation -> showNtfDir
is CIContent.SndGroupInvitation -> showNtfDir
is CIContent.RcvDirectEventContent -> false
is CIContent.RcvIntegrityError -> false
is CIContent.RcvDecryptionError -> false
is CIContent.RcvGroupInvitation -> true
is CIContent.SndGroupInvitation -> false
is CIContent.RcvDirectEventContent -> when (content.rcvDirectEvent) {
is RcvDirectEvent.ContactDeleted -> false
is RcvDirectEvent.ProfileUpdated -> true
}
is CIContent.RcvGroupEventContent -> when (content.rcvGroupEvent) {
is RcvGroupEvent.MemberAdded -> false
is RcvGroupEvent.MemberConnected -> false
is RcvGroupEvent.MemberLeft -> false
is RcvGroupEvent.MemberRole -> false
is RcvGroupEvent.UserRole -> showNtfDir
is RcvGroupEvent.MemberBlocked -> false
is RcvGroupEvent.UserRole -> true
is RcvGroupEvent.MemberDeleted -> false
is RcvGroupEvent.UserDeleted -> showNtfDir
is RcvGroupEvent.GroupDeleted -> showNtfDir
is RcvGroupEvent.UserDeleted -> true
is RcvGroupEvent.GroupDeleted -> true
is RcvGroupEvent.GroupUpdated -> false
is RcvGroupEvent.InvitedViaGroupLink -> false
is RcvGroupEvent.MemberCreatedContact -> false
is RcvGroupEvent.MemberProfileUpdated -> false
}
is CIContent.SndGroupEventContent -> showNtfDir
is CIContent.SndGroupEventContent -> false
is CIContent.RcvConnEventContent -> false
is CIContent.SndConnEventContent -> showNtfDir
is CIContent.SndConnEventContent -> false
is CIContent.RcvChatFeature -> false
is CIContent.SndChatFeature -> showNtfDir
is CIContent.SndChatFeature -> false
is CIContent.RcvChatPreference -> false
is CIContent.SndChatPreference -> showNtfDir
is CIContent.SndChatPreference -> false
is CIContent.RcvGroupFeature -> false
is CIContent.SndGroupFeature -> showNtfDir
is CIContent.RcvChatFeatureRejected -> showNtfDir
is CIContent.RcvGroupFeatureRejected -> showNtfDir
is CIContent.SndModerated -> true
is CIContent.RcvModerated -> true
is CIContent.SndGroupFeature -> false
is CIContent.RcvChatFeatureRejected -> true
is CIContent.RcvGroupFeatureRejected -> false
is CIContent.SndModerated -> false
is CIContent.RcvModerated -> false
is CIContent.RcvBlocked -> false
is CIContent.InvalidJSON -> false
}
@@ -1911,12 +2005,16 @@ sealed class CIDirection {
@Serializable @SerialName("directRcv") class DirectRcv: CIDirection()
@Serializable @SerialName("groupSnd") class GroupSnd: CIDirection()
@Serializable @SerialName("groupRcv") class GroupRcv(val groupMember: GroupMember): CIDirection()
@Serializable @SerialName("localSnd") class LocalSnd: CIDirection()
@Serializable @SerialName("localRcv") class LocalRcv: CIDirection()
val sent: Boolean get() = when(this) {
is DirectSnd -> true
is DirectRcv -> false
is GroupSnd -> true
is GroupRcv -> false
is LocalSnd -> true
is LocalRcv -> false
}
}
@@ -2086,6 +2184,7 @@ enum class SndCIStatusProgress {
sealed class CIDeleted {
@Serializable @SerialName("deleted") class Deleted(val deletedTs: Instant?): CIDeleted()
@Serializable @SerialName("blocked") class Blocked(val deletedTs: Instant?): CIDeleted()
@Serializable @SerialName("blockedByAdmin") class BlockedByAdmin(val deletedTs: Instant?): CIDeleted()
@Serializable @SerialName("moderated") class Moderated(val deletedTs: Instant?, val byGroupMember: GroupMember): CIDeleted()
}
@@ -2130,6 +2229,7 @@ sealed class CIContent: ItemContent {
@Serializable @SerialName("rcvGroupFeatureRejected") class RcvGroupFeatureRejected(val groupFeature: GroupFeature): CIContent() { override val msgContent: MsgContent? get() = null }
@Serializable @SerialName("sndModerated") object SndModerated: CIContent() { override val msgContent: MsgContent? get() = null }
@Serializable @SerialName("rcvModerated") object RcvModerated: CIContent() { override val msgContent: MsgContent? get() = null }
@Serializable @SerialName("rcvBlocked") object RcvBlocked: CIContent() { override val msgContent: MsgContent? get() = null }
@Serializable @SerialName("invalidJSON") data class InvalidJSON(val json: String): CIContent() { override val msgContent: MsgContent? get() = null }
override val text: String get() = when (this) {
@@ -2158,6 +2258,7 @@ sealed class CIContent: ItemContent {
is RcvGroupFeatureRejected -> "${groupFeature.text}: ${generalGetString(MR.strings.feature_received_prohibited)}"
is SndModerated -> generalGetString(MR.strings.moderated_description)
is RcvModerated -> generalGetString(MR.strings.moderated_description)
is RcvBlocked -> generalGetString(MR.strings.blocked_by_admin_item_description)
is InvalidJSON -> "invalid data"
}
@@ -2170,6 +2271,7 @@ sealed class CIContent: ItemContent {
is RcvDecryptionError -> true
is RcvGroupInvitation -> true
is RcvModerated -> true
is RcvBlocked -> true
is InvalidJSON -> true
else -> false
}
@@ -2232,6 +2334,8 @@ class CIQuote (
is CIDirection.DirectRcv -> null
is CIDirection.GroupSnd -> membership?.displayName ?: generalGetString(MR.strings.sender_you_pronoun)
is CIDirection.GroupRcv -> chatDir.groupMember.displayName
is CIDirection.LocalSnd -> generalGetString(MR.strings.sender_you_pronoun)
is CIDirection.LocalRcv -> null
null -> null
}
@@ -2503,7 +2607,8 @@ private val rcvCancelAction: CancelAction = CancelAction(
@Serializable
enum class FileProtocol {
@SerialName("smp") SMP,
@SerialName("xftp") XFTP;
@SerialName("xftp") XFTP,
@SerialName("local") LOCAL;
}
@Serializable
@@ -2835,10 +2940,30 @@ sealed class MsgErrorType() {
@Serializable
sealed class RcvDirectEvent() {
@Serializable @SerialName("contactDeleted") class ContactDeleted(): RcvDirectEvent()
@Serializable @SerialName("profileUpdated") class ProfileUpdated(val fromProfile: Profile, val toProfile: Profile): RcvDirectEvent()
val text: String get() = when (this) {
is ContactDeleted -> generalGetString(MR.strings.rcv_direct_event_contact_deleted)
is ProfileUpdated -> profileUpdatedText(fromProfile, toProfile)
}
private fun profileUpdatedText(from: Profile, to: Profile): String =
when {
to.displayName != from.displayName || to.fullName != from.fullName ->
generalGetString(MR.strings.profile_update_event_contact_name_changed).format(from.profileViewName, to.profileViewName)
to.image != from.image -> when (to.image) {
null -> generalGetString(MR.strings.profile_update_event_removed_picture)
else -> generalGetString(MR.strings.profile_update_event_set_new_picture)
}
to.contactLink != from.contactLink -> when (to.contactLink) {
null -> generalGetString(MR.strings.profile_update_event_removed_address)
else -> generalGetString(MR.strings.profile_update_event_set_new_address)
}
// shouldn't happen if backend correctly creates item; UI should be synchronized with backend
else -> generalGetString(MR.strings.profile_update_event_updated_profile)
}
}
@Serializable
@@ -2847,6 +2972,7 @@ sealed class RcvGroupEvent() {
@Serializable @SerialName("memberConnected") class MemberConnected(): RcvGroupEvent()
@Serializable @SerialName("memberLeft") class MemberLeft(): RcvGroupEvent()
@Serializable @SerialName("memberRole") class MemberRole(val groupMemberId: Long, val profile: Profile, val role: GroupMemberRole): RcvGroupEvent()
@Serializable @SerialName("memberBlocked") class MemberBlocked(val groupMemberId: Long, val profile: Profile, val blocked: Boolean): RcvGroupEvent()
@Serializable @SerialName("userRole") class UserRole(val role: GroupMemberRole): RcvGroupEvent()
@Serializable @SerialName("memberDeleted") class MemberDeleted(val groupMemberId: Long, val profile: Profile): RcvGroupEvent()
@Serializable @SerialName("userDeleted") class UserDeleted(): RcvGroupEvent()
@@ -2854,12 +2980,18 @@ sealed class RcvGroupEvent() {
@Serializable @SerialName("groupUpdated") class GroupUpdated(val groupProfile: GroupProfile): RcvGroupEvent()
@Serializable @SerialName("invitedViaGroupLink") class InvitedViaGroupLink(): RcvGroupEvent()
@Serializable @SerialName("memberCreatedContact") class MemberCreatedContact(): RcvGroupEvent()
@Serializable @SerialName("memberProfileUpdated") class MemberProfileUpdated(val fromProfile: Profile, val toProfile: Profile): RcvGroupEvent()
val text: String get() = when (this) {
is MemberAdded -> String.format(generalGetString(MR.strings.rcv_group_event_member_added), profile.profileViewName)
is MemberConnected -> generalGetString(MR.strings.rcv_group_event_member_connected)
is MemberLeft -> generalGetString(MR.strings.rcv_group_event_member_left)
is MemberRole -> String.format(generalGetString(MR.strings.rcv_group_event_changed_member_role), profile.profileViewName, role.text)
is MemberBlocked -> if (blocked) {
String.format(generalGetString(MR.strings.rcv_group_event_member_blocked), profile.profileViewName)
} else {
String.format(generalGetString(MR.strings.rcv_group_event_member_unblocked), profile.profileViewName)
}
is UserRole -> String.format(generalGetString(MR.strings.rcv_group_event_changed_your_role), role.text)
is MemberDeleted -> String.format(generalGetString(MR.strings.rcv_group_event_member_deleted), profile.profileViewName)
is UserDeleted -> generalGetString(MR.strings.rcv_group_event_user_deleted)
@@ -2867,13 +2999,28 @@ sealed class RcvGroupEvent() {
is GroupUpdated -> generalGetString(MR.strings.rcv_group_event_updated_group_profile)
is InvitedViaGroupLink -> generalGetString(MR.strings.rcv_group_event_invited_via_your_group_link)
is MemberCreatedContact -> generalGetString(MR.strings.rcv_group_event_member_created_contact)
is MemberProfileUpdated -> profileUpdatedText(fromProfile, toProfile)
}
private fun profileUpdatedText(from: Profile, to: Profile): String =
when {
to.displayName != from.displayName || to.fullName != from.fullName ->
generalGetString(MR.strings.profile_update_event_member_name_changed).format(from.profileViewName, to.profileViewName)
to.image != from.image -> when (to.image) {
null -> generalGetString(MR.strings.profile_update_event_removed_picture)
else -> generalGetString(MR.strings.profile_update_event_set_new_picture)
}
// shouldn't happen if backend correctly creates item; UI should be synchronized with backend
else -> generalGetString(MR.strings.profile_update_event_updated_profile)
}
}
@Serializable
sealed class SndGroupEvent() {
@Serializable @SerialName("memberRole") class MemberRole(val groupMemberId: Long, val profile: Profile, val role: GroupMemberRole): SndGroupEvent()
@Serializable @SerialName("userRole") class UserRole(val role: GroupMemberRole): SndGroupEvent()
@Serializable @SerialName("memberBlocked") class MemberBlocked(val groupMemberId: Long, val profile: Profile, val blocked: Boolean): SndGroupEvent()
@Serializable @SerialName("memberDeleted") class MemberDeleted(val groupMemberId: Long, val profile: Profile): SndGroupEvent()
@Serializable @SerialName("userLeft") class UserLeft(): SndGroupEvent()
@Serializable @SerialName("groupUpdated") class GroupUpdated(val groupProfile: GroupProfile): SndGroupEvent()
@@ -2881,6 +3028,11 @@ sealed class SndGroupEvent() {
val text: String get() = when (this) {
is MemberRole -> String.format(generalGetString(MR.strings.snd_group_event_changed_member_role), profile.profileViewName, role.text)
is UserRole -> String.format(generalGetString(MR.strings.snd_group_event_changed_role_for_yourself), role.text)
is MemberBlocked -> if (blocked) {
String.format(generalGetString(MR.strings.snd_group_event_member_blocked), profile.profileViewName)
} else {
String.format(generalGetString(MR.strings.snd_group_event_member_unblocked), profile.profileViewName)
}
is MemberDeleted -> String.format(generalGetString(MR.strings.snd_group_event_member_deleted), profile.profileViewName)
is UserLeft -> generalGetString(MR.strings.snd_group_event_user_left)
is GroupUpdated -> generalGetString(MR.strings.snd_group_event_group_profile_updated)
@@ -351,7 +351,6 @@ object ChatController {
suspend fun startChat(user: User) {
Log.d(TAG, "user: $user")
try {
if (chatModel.chatRunning.value == true) return
apiSetNetworkConfig(getNetCfg())
val justStarted = apiStartChat()
appPrefs.chatStopped.set(false)
@@ -410,9 +409,9 @@ object ChatController {
}
}
suspend fun changeActiveUser_(rhId: Long?, toUserId: Long, viewPwd: String?) {
suspend fun changeActiveUser_(rhId: Long?, toUserId: Long?, viewPwd: String?) {
val currentUser = changingActiveUserMutex.withLock {
apiSetActiveUser(rhId, toUserId, viewPwd).also {
(if (toUserId != null) apiSetActiveUser(rhId, toUserId, viewPwd) else apiGetActiveUser(rhId)).also {
chatModel.currentUser.value = it
}
}
@@ -421,7 +420,7 @@ object ChatController {
chatModel.users.addAll(users)
getUserChatData(rhId)
val invitation = chatModel.callInvitations.values.firstOrNull { inv -> inv.user.userId == toUserId }
if (invitation != null) {
if (invitation != null && currentUser != null) {
chatModel.callManager.reportNewIncomingCall(invitation.copy(user = currentUser))
}
}
@@ -681,6 +680,17 @@ object ChatController {
}
}
}
suspend fun apiCreateChatItem(rh: Long?, noteFolderId: Long, file: CryptoFile? = null, mc: MsgContent): AChatItem? {
val cmd = CC.ApiCreateChatItem(noteFolderId, file, mc)
val r = sendCmd(rh, cmd)
return when (r) {
is CR.NewChatItem -> r.chatItem
else -> {
apiErrorAlert("apiCreateChatItem", generalGetString(MR.strings.error_creating_message), r)
null
}
}
}
suspend fun apiGetChatItemInfo(rh: Long?, type: ChatType, id: Long, itemId: Long): ChatItemInfo? {
return when (val r = sendCmd(rh, CC.ApiGetChatItemInfo(type, id, itemId))) {
@@ -991,6 +1001,7 @@ object ChatController {
val titleId = when (type) {
ChatType.Direct -> MR.strings.error_deleting_contact
ChatType.Group -> MR.strings.error_deleting_group
ChatType.Local -> MR.strings.error_deleting_note_folder
ChatType.ContactRequest -> MR.strings.error_deleting_contact_request
ChatType.ContactConnection -> MR.strings.error_deleting_pending_contact_connection
}
@@ -1002,6 +1013,17 @@ object ChatController {
return success
}
fun clearChat(chat: Chat, close: (() -> Unit)? = null) {
withBGApi {
val updatedChatInfo = apiClearChat(chat.remoteHostId, chat.chatInfo.chatType, chat.chatInfo.apiId)
if (updatedChatInfo != null) {
chatModel.clearChat(chat.remoteHostId, updatedChatInfo)
ntfManager.cancelNotificationsForChat(chat.chatInfo.id)
close?.invoke()
}
}
}
suspend fun apiClearChat(rh: Long?, type: ChatType, id: Long): ChatInfo? {
val r = sendCmd(rh, CC.ApiClearChat(type, id))
if (r is CR.ChatCleared) return r.chatInfo
@@ -1310,6 +1332,17 @@ object ChatController {
}
}
suspend fun apiBlockMemberForAll(rh: Long?, groupId: Long, memberId: Long, blocked: Boolean): GroupMember =
when (val r = sendCmd(rh, CC.ApiBlockMemberForAll(groupId, memberId, blocked))) {
is CR.MemberBlockedForAllUser -> r.member
else -> {
if (!(networkErrorAlert(r))) {
apiErrorAlert("apiBlockMemberForAll", generalGetString(MR.strings.error_blocking_member_for_all), r)
}
throw Exception("failed to block member for all: ${r.responseType} ${r.details}")
}
}
suspend fun apiLeaveGroup(rh: Long?, groupId: Long): GroupInfo? {
val r = sendCmd(rh, CC.ApiLeaveGroup(groupId))
if (r is CR.LeftMemberUser) return r.groupInfo
@@ -1764,6 +1797,10 @@ object ChatController {
if (active(r.user)) {
chatModel.upsertGroupMember(rhId, r.groupInfo, r.member)
}
is CR.MemberBlockedForAll ->
if (active(r.user)) {
chatModel.upsertGroupMember(rhId, r.groupInfo, r.member)
}
is CR.GroupDeleted -> // TODO update user member
if (active(r.user)) {
chatModel.updateGroup(rhId, r.groupInfo)
@@ -2244,6 +2281,7 @@ sealed class CC {
class ApiGetChat(val type: ChatType, val id: Long, val pagination: ChatPagination, val search: String = ""): CC()
class ApiGetChatItemInfo(val type: ChatType, val id: Long, val itemId: Long): CC()
class ApiSendMessage(val type: ChatType, val id: Long, val file: CryptoFile?, val quotedItemId: Long?, val mc: MsgContent, val live: Boolean, val ttl: Int?): CC()
class ApiCreateChatItem(val noteFolderId: Long, val file: CryptoFile?, val mc: MsgContent): CC()
class ApiUpdateChatItem(val type: ChatType, val id: Long, val itemId: Long, val mc: MsgContent, val live: Boolean): CC()
class ApiDeleteChatItem(val type: ChatType, val id: Long, val itemId: Long, val mode: CIDeleteMode): CC()
class ApiDeleteMemberChatItem(val groupId: Long, val groupMemberId: Long, val itemId: Long): CC()
@@ -2252,6 +2290,7 @@ sealed class CC {
class ApiAddMember(val groupId: Long, val contactId: Long, val memberRole: GroupMemberRole): CC()
class ApiJoinGroup(val groupId: Long): CC()
class ApiMemberRole(val groupId: Long, val memberId: Long, val memberRole: GroupMemberRole): CC()
class ApiBlockMemberForAll(val groupId: Long, val memberId: Long, val blocked: Boolean): CC()
class ApiRemoveMember(val groupId: Long, val memberId: Long): CC()
class ApiLeaveGroup(val groupId: Long): CC()
class ApiListMembers(val groupId: Long): CC()
@@ -2375,6 +2414,9 @@ sealed class CC {
val ttlStr = if (ttl != null) "$ttl" else "default"
"/_send ${chatRef(type, id)} live=${onOff(live)} ttl=${ttlStr} json ${json.encodeToString(ComposedMessage(file, quotedItemId, mc))}"
}
is ApiCreateChatItem -> {
"/_create *$noteFolderId json ${json.encodeToString(ComposedMessage(file, null, mc))}"
}
is ApiUpdateChatItem -> "/_update item ${chatRef(type, id)} $itemId live=${onOff(live)} ${mc.cmdString}"
is ApiDeleteChatItem -> "/_delete item ${chatRef(type, id)} $itemId ${mode.deleteMode}"
is ApiDeleteMemberChatItem -> "/_delete member item #$groupId $groupMemberId $itemId"
@@ -2383,6 +2425,7 @@ sealed class CC {
is ApiAddMember -> "/_add #$groupId $contactId ${memberRole.memberRole}"
is ApiJoinGroup -> "/_join #$groupId"
is ApiMemberRole -> "/_member role #$groupId $memberId ${memberRole.memberRole}"
is ApiBlockMemberForAll -> "/_block #$groupId $memberId blocked=${onOff(blocked)}"
is ApiRemoveMember -> "/_remove #$groupId $memberId"
is ApiLeaveGroup -> "/_leave #$groupId"
is ApiListMembers -> "/_members #$groupId"
@@ -2503,6 +2546,7 @@ sealed class CC {
is ApiGetChat -> "apiGetChat"
is ApiGetChatItemInfo -> "apiGetChatItemInfo"
is ApiSendMessage -> "apiSendMessage"
is ApiCreateChatItem -> "apiCreateChatItem"
is ApiUpdateChatItem -> "apiUpdateChatItem"
is ApiDeleteChatItem -> "apiDeleteChatItem"
is ApiDeleteMemberChatItem -> "apiDeleteMemberChatItem"
@@ -2511,6 +2555,7 @@ sealed class CC {
is ApiAddMember -> "apiAddMember"
is ApiJoinGroup -> "apiJoinGroup"
is ApiMemberRole -> "apiMemberRole"
is ApiBlockMemberForAll -> "apiBlockMemberForAll"
is ApiRemoveMember -> "apiRemoveMember"
is ApiLeaveGroup -> "apiLeaveGroup"
is ApiListMembers -> "apiListMembers"
@@ -3901,6 +3946,8 @@ sealed class CR {
@Serializable @SerialName("joinedGroupMemberConnecting") class JoinedGroupMemberConnecting(val user: UserRef, val groupInfo: GroupInfo, val hostMember: GroupMember, val member: GroupMember): CR()
@Serializable @SerialName("memberRole") class MemberRole(val user: UserRef, val groupInfo: GroupInfo, val byMember: GroupMember, val member: GroupMember, val fromRole: GroupMemberRole, val toRole: GroupMemberRole): CR()
@Serializable @SerialName("memberRoleUser") class MemberRoleUser(val user: UserRef, val groupInfo: GroupInfo, val member: GroupMember, val fromRole: GroupMemberRole, val toRole: GroupMemberRole): CR()
@Serializable @SerialName("memberBlockedForAll") class MemberBlockedForAll(val user: UserRef, val groupInfo: GroupInfo, val byMember: GroupMember, val member: GroupMember, val blocked: Boolean): CR()
@Serializable @SerialName("memberBlockedForAllUser") class MemberBlockedForAllUser(val user: UserRef, val groupInfo: GroupInfo, val member: GroupMember, val blocked: Boolean): CR()
@Serializable @SerialName("deletedMemberUser") class DeletedMemberUser(val user: UserRef, val groupInfo: GroupInfo, val member: GroupMember): CR()
@Serializable @SerialName("deletedMember") class DeletedMember(val user: UserRef, val groupInfo: GroupInfo, val byMember: GroupMember, val deletedMember: GroupMember): CR()
@Serializable @SerialName("leftMember") class LeftMember(val user: UserRef, val groupInfo: GroupInfo, val member: GroupMember): CR()
@@ -4053,6 +4100,8 @@ sealed class CR {
is JoinedGroupMemberConnecting -> "joinedGroupMemberConnecting"
is MemberRole -> "memberRole"
is MemberRoleUser -> "memberRoleUser"
is MemberBlockedForAll -> "memberBlockedForAll"
is MemberBlockedForAllUser -> "memberBlockedForAllUser"
is DeletedMemberUser -> "deletedMemberUser"
is DeletedMember -> "deletedMember"
is LeftMember -> "leftMember"
@@ -4200,6 +4249,8 @@ sealed class CR {
is JoinedGroupMemberConnecting -> withUser(user, "groupInfo: $groupInfo\nhostMember: $hostMember\nmember: $member")
is MemberRole -> withUser(user, "groupInfo: $groupInfo\nbyMember: $byMember\nmember: $member\nfromRole: $fromRole\ntoRole: $toRole")
is MemberRoleUser -> withUser(user, "groupInfo: $groupInfo\nmember: $member\nfromRole: $fromRole\ntoRole: $toRole")
is MemberBlockedForAll -> withUser(user, "groupInfo: $groupInfo\nbyMember: $byMember\nmember: $member\nblocked: $blocked")
is MemberBlockedForAllUser -> withUser(user, "groupInfo: $groupInfo\nmember: $member\nblocked: $blocked")
is DeletedMemberUser -> withUser(user, "groupInfo: $groupInfo\nmember: $member")
is DeletedMember -> withUser(user, "groupInfo: $groupInfo\nbyMember: $byMember\ndeletedMember: $deletedMember")
is LeftMember -> withUser(user, "groupInfo: $groupInfo\nmember: $member")
@@ -55,7 +55,7 @@ abstract class NtfManager {
}
fun openChatAction(userId: Long?, chatId: ChatId) {
withBGApi {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
awaitChatStartedIfNeeded(chatModel)
if (userId != null && userId != chatModel.currentUser.value?.userId && chatModel.currentUser.value != null) {
// TODO include remote host ID in desktop notifications?
@@ -70,7 +70,7 @@ abstract class NtfManager {
}
fun showChatsAction(userId: Long?) {
withBGApi {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
awaitChatStartedIfNeeded(chatModel)
if (userId != null && userId != chatModel.currentUser.value?.userId && chatModel.currentUser.value != null) {
// TODO include remote host ID in desktop notifications?
@@ -1,8 +1,12 @@
package chat.simplex.common.ui.theme
import androidx.compose.material.LocalContentColor
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.graphics.*
import chat.simplex.common.views.helpers.mixWith
import kotlin.math.min
val Purple200 = Color(0xFFBB86FC)
val Purple500 = Color(0xFF6200EE)
@@ -27,5 +31,17 @@ val WarningOrange = Color(255, 127, 0, 255)
val WarningYellow = Color(255, 192, 0, 255)
val FileLight = Color(183, 190, 199, 255)
val FileDark = Color(101, 101, 106, 255)
val SentMessageColor = Color(0x1E45B8FF)
val MenuTextColor: Color @Composable get () = if (isInDarkTheme()) LocalContentColor.current.copy(alpha = 0.8f) else Color.Black
val NoteFolderIconColor: Color @Composable get() = with(CurrentColors.collectAsState().value.appColors.sentMessage) {
// Default color looks too light and better to have it here a little bit brighter
if (alpha == SentMessageColor.alpha) {
copy(min(SentMessageColor.alpha + 0.1f, 1f))
} else {
// Color is non-standard and theme maker can choose color without alpha at all since the theme bound to dark/light variant,
// and it shouldn't be universal
this
}
}
@@ -212,7 +212,7 @@ val DarkColorPalette = darkColors(
)
val DarkColorPaletteApp = AppColors(
title = SimplexBlue,
sentMessage = Color(0x1E45B8FF),
sentMessage = SentMessageColor,
receivedMessage = Color(0x20B1B0B5)
)
@@ -231,7 +231,7 @@ val LightColorPalette = lightColors(
)
val LightColorPaletteApp = AppColors(
title = SimplexBlue,
sentMessage = Color(0x1E45B8FF),
sentMessage = SentMessageColor,
receivedMessage = Color(0x20B1B0B5)
)
@@ -251,7 +251,7 @@ val SimplexColorPalette = darkColors(
)
val SimplexColorPaletteApp = AppColors(
title = Color(0xFF267BE5),
sentMessage = Color(0x1E45B8FF),
sentMessage = SentMessageColor,
receivedMessage = Color(0x20B1B0B5)
)
@@ -177,8 +177,10 @@ fun CreateFirstProfile(chatModel: ChatModel, close: () -> Unit) {
fun createProfileInNoProfileSetup(displayName: String, close: () -> Unit) {
withBGApi {
val user = controller.apiCreateActiveUser(null, Profile(displayName.trim(), "", null)) ?: return@withBGApi
if (!chatModel.connectedToRemote()) {
chatModel.localUserCreated.value = true
}
controller.appPrefs.onboardingStage.set(OnboardingStage.Step3_CreateSimpleXAddress)
chatModel.chatRunning.value = false
controller.startChat(user)
controller.switchUIRemoteHost(null)
close()
@@ -210,6 +212,7 @@ fun createProfileOnboarding(chatModel: ChatModel, displayName: String, close: ()
chatModel.currentUser.value = chatModel.controller.apiCreateActiveUser(
null, Profile(displayName.trim(), "", null)
) ?: return@withBGApi
chatModel.localUserCreated.value = true
val onboardingStage = chatModel.controller.appPrefs.onboardingStage
if (chatModel.users.isEmpty()) {
onboardingStage.set(if (appPlatform.isDesktop && chatModel.controller.appPrefs.initialRandomDBPassphrase.get() && !chatModel.desktopOnboardingRandomPassword.value) {
@@ -29,6 +29,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import chat.simplex.common.model.*
import chat.simplex.common.model.ChatModel.controller
import chat.simplex.common.ui.theme.*
import chat.simplex.common.views.helpers.*
import chat.simplex.common.views.usersettings.*
@@ -91,7 +92,7 @@ fun ChatInfoView(
}
},
deleteContact = { deleteContactDialog(chat, chatModel, close) },
clearChat = { clearChatDialog(chat, chatModel, close) },
clearChat = { clearChatDialog(chat, close) },
switchContactAddress = {
showSwitchAddressAlert(switchAddress = {
withBGApi {
@@ -254,23 +255,22 @@ fun deleteContact(chat: Chat, chatModel: ChatModel, close: (() -> Unit)?, notify
}
}
fun clearChatDialog(chat: Chat, chatModel: ChatModel, close: (() -> Unit)? = null) {
val chatInfo = chat.chatInfo
fun clearChatDialog(chat: Chat, close: (() -> Unit)? = null) {
AlertManager.shared.showAlertDialog(
title = generalGetString(MR.strings.clear_chat_question),
text = generalGetString(MR.strings.clear_chat_warning),
confirmText = generalGetString(MR.strings.clear_verb),
onConfirm = {
withBGApi {
val chatRh = chat.remoteHostId
val updatedChatInfo = chatModel.controller.apiClearChat(chatRh, chatInfo.chatType, chatInfo.apiId)
if (updatedChatInfo != null) {
chatModel.clearChat(chatRh, updatedChatInfo)
ntfManager.cancelNotificationsForChat(chatInfo.id)
close?.invoke()
}
}
},
onConfirm = { controller.clearChat(chat, close) },
destructive = true,
)
}
fun clearNoteFolderDialog(chat: Chat, close: (() -> Unit)? = null) {
AlertManager.shared.showAlertDialog(
title = generalGetString(MR.strings.clear_note_folder_question),
text = generalGetString(MR.strings.clear_note_folder_warning),
confirmText = generalGetString(MR.strings.clear_verb),
onConfirm = { controller.clearChat(chat, close) },
destructive = true,
)
}
@@ -154,9 +154,9 @@ fun ChatItemInfoView(chatModel: ChatModel, ci: ChatItem, ciInfo: ChatItemInfo, d
@Composable
fun Details() {
AppBarTitle(stringResource(if (sent) MR.strings.sent_message else MR.strings.received_message))
AppBarTitle(stringResource(if (ci.localNote) MR.strings.saved_message_title else if (sent) MR.strings.sent_message else MR.strings.received_message))
SectionView {
InfoRow(stringResource(MR.strings.info_row_sent_at), localTimestamp(ci.meta.itemTs))
InfoRow(stringResource(if (!ci.localNote) MR.strings.info_row_sent_at else MR.strings.info_row_created_at), localTimestamp(ci.meta.itemTs))
if (!sent) {
InfoRow(stringResource(MR.strings.info_row_received_at), localTimestamp(ci.meta.createdAt))
}
@@ -393,9 +393,9 @@ private fun membersStatuses(chatModel: ChatModel, memberDeliveryStatuses: List<M
fun itemInfoShareText(chatModel: ChatModel, ci: ChatItem, chatItemInfo: ChatItemInfo, devTools: Boolean): String {
val meta = ci.meta
val sent = ci.chatDir.sent
val shareText = mutableListOf<String>("# " + generalGetString(if (sent) MR.strings.sent_message else MR.strings.received_message), "")
val shareText = mutableListOf<String>("# " + generalGetString(if (ci.localNote) MR.strings.saved_message_title else if (sent) MR.strings.sent_message else MR.strings.received_message), "")
shareText.add(String.format(generalGetString(MR.strings.share_text_sent_at), localTimestamp(meta.itemTs)))
shareText.add(String.format(generalGetString(if (ci.localNote) MR.strings.share_text_created_at else MR.strings.share_text_sent_at), localTimestamp(meta.itemTs)))
if (!ci.chatDir.sent) {
shareText.add(String.format(generalGetString(MR.strings.share_text_received_at), localTimestamp(meta.createdAt)))
}
@@ -117,7 +117,7 @@ fun ChatView(chatId: String, chatModel: ChatModel, onComposed: suspend (chatId:
}
val clipboard = LocalClipboardManager.current
when (chat.chatInfo) {
is ChatInfo.Direct, is ChatInfo.Group -> {
is ChatInfo.Direct, is ChatInfo.Group, is ChatInfo.Local -> {
ChatLayout(
chat,
unreadCount,
@@ -624,11 +624,27 @@ fun ChatInfoToolbar(
val barButtons = arrayListOf<@Composable RowScope.() -> Unit>()
val menuItems = arrayListOf<@Composable () -> Unit>()
val activeCall by remember { chatModel.activeCall }
menuItems.add {
ItemAction(stringResource(MR.strings.search_verb), painterResource(MR.images.ic_search), onClick = {
showMenu.value = false
showSearch = true
})
if (chat.chatInfo is ChatInfo.Local) {
barButtons.add {
IconButton({
showMenu.value = false
showSearch = true
}, enabled = chat.chatInfo.noteFolder.ready
) {
Icon(
painterResource(MR.images.ic_search),
stringResource(MR.strings.search_verb).capitalize(Locale.current),
tint = if (chat.chatInfo.noteFolder.ready) MaterialTheme.colors.primary else MaterialTheme.colors.secondary
)
}
}
} else {
menuItems.add {
ItemAction(stringResource(MR.strings.search_verb), painterResource(MR.images.ic_search), onClick = {
showMenu.value = false
showSearch = true
})
}
}
if (chat.chatInfo is ChatInfo.Direct && chat.chatInfo.contact.allowsFeature(ChatFeature.Calls)) {
@@ -743,16 +759,18 @@ fun ChatInfoToolbar(
}
}
barButtons.add {
IconButton({ showMenu.value = true }) {
Icon(MoreVertFilled, stringResource(MR.strings.icon_descr_more_button), tint = MaterialTheme.colors.primary)
if (menuItems.isNotEmpty()) {
barButtons.add {
IconButton({ showMenu.value = true }) {
Icon(MoreVertFilled, stringResource(MR.strings.icon_descr_more_button), tint = MaterialTheme.colors.primary)
}
}
}
DefaultTopAppBar(
navigationButton = { if (appPlatform.isAndroid || showSearch) { NavigationButtonBack(onBackClicked) } },
title = { ChatInfoToolbarTitle(chat.chatInfo) },
onTitleClick = info,
onTitleClick = if (chat.chatInfo is ChatInfo.Local) null else info,
showSearch = showSearch,
onSearchValueChanged = onSearchValueChanged,
buttons = barButtons
@@ -910,7 +928,7 @@ fun BoxWithConstraintsScope.ChatItemsList(
if (dismissState.isAnimationRunning && (swipedToStart || swipedToEnd)) {
LaunchedEffect(Unit) {
scope.launch {
if (cItem.content is CIContent.SndMsgContent || cItem.content is CIContent.RcvMsgContent) {
if ((cItem.content is CIContent.SndMsgContent || cItem.content is CIContent.RcvMsgContent) && chat.chatInfo !is ChatInfo.Local) {
if (composeState.value.editing) {
composeState.value = ComposeState(contextItem = ComposeContextItem.QuotedItem(cItem), useLinkPreviews = useLinkPreviews)
} else if (cItem.id != ChatItem.TEMP_LIVE_CHAT_ITEM_ID) {
@@ -267,7 +267,7 @@ fun ComposeView(
fun loadLinkPreview(url: String, wait: Long? = null) {
if (pendingLinkUrl.value == url) {
composeState.value = composeState.value.copy(preview = ComposePreview.CLinkPreview(null))
withBGApi {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
if (wait != null) delay(wait)
val lp = getLinkPreview(url)
if (lp != null && pendingLinkUrl.value == url) {
@@ -353,7 +353,10 @@ fun ComposeView(
suspend fun send(chat: Chat, mc: MsgContent, quoted: Long?, file: CryptoFile? = null, live: Boolean = false, ttl: Int?): ChatItem? {
val cInfo = chat.chatInfo
val aChatItem = chatModel.controller.apiSendMessage(
val aChatItem = if (chat.chatInfo.chatType == ChatType.Local)
chatModel.controller.apiCreateChatItem(rh = chat.remoteHostId, noteFolderId = chat.chatInfo.apiId, file = file, mc = mc)
else
chatModel.controller.apiSendMessage(
rh = chat.remoteHostId,
type = cInfo.chatType,
id = cInfo.apiId,
@@ -548,7 +551,7 @@ fun ComposeView(
}
fun sendMessage(ttl: Int?) {
withBGApi {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
sendMessageAsync(null, false, ttl)
}
}
@@ -877,7 +880,7 @@ fun ComposeView(
sendMessage(ttl)
resetLinkPreview()
},
sendLiveMessage = ::sendLiveMessage,
sendLiveMessage = if (chat.chatInfo.chatType != ChatType.Local) ::sendLiveMessage else null,
updateLiveMessage = ::updateLiveMessage,
cancelLiveMessage = {
composeState.value = composeState.value.copy(liveMessage = null)
@@ -54,7 +54,7 @@ fun AddGroupMembersView(rhId: Long?, groupInfo: GroupInfo, creatingGroup: Boolea
},
inviteMembers = {
allowModifyMembers = false
withBGApi {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
for (contactId in selectedContacts) {
val member = chatModel.controller.apiAddMember(rhId, groupInfo.groupId, contactId, selectedRole.value)
if (member != null) {
@@ -110,7 +110,7 @@ fun GroupChatInfoView(chatModel: ChatModel, rhId: Long?, chatId: String, groupLi
}
},
deleteGroup = { deleteGroupDialog(chat, groupInfo, chatModel, close) },
clearChat = { clearChatDialog(chat, chatModel, close) },
clearChat = { clearChatDialog(chat, close) },
leaveGroup = { leaveGroupDialog(rhId, groupInfo, chatModel, close) },
manageGroupLink = {
ModalManager.end.showModal { GroupLinkView(chatModel, rhId, groupInfo, groupLink, groupLinkMemberRole, onGroupLinkUpdated) }
@@ -368,6 +368,18 @@ private fun AddMembersButton(tint: Color = MaterialTheme.colors.primary, onClick
@Composable
private fun MemberRow(member: GroupMember, user: Boolean = false, onClick: (() -> Unit)? = null) {
@Composable
fun MemberInfo() {
if (member.blocked) {
Text(stringResource(MR.strings.member_info_member_blocked), color = MaterialTheme.colors.secondary)
} else {
val role = member.memberRole
if (role in listOf(GroupMemberRole.Owner, GroupMemberRole.Admin, GroupMemberRole.Observer)) {
Text(role.text, color = MaterialTheme.colors.secondary)
}
}
}
Row(
Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
@@ -401,10 +413,7 @@ private fun MemberRow(member: GroupMember, user: Boolean = false, onClick: (() -
)
}
}
val role = member.memberRole
if (role in listOf(GroupMemberRole.Owner, GroupMemberRole.Admin, GroupMemberRole.Observer)) {
Text(role.text, color = MaterialTheme.colors.secondary)
}
MemberInfo()
}
}
@@ -415,6 +424,7 @@ private fun MemberVerifiedShield() {
@Composable
private fun DropDownMenuForMember(rhId: Long?, member: GroupMember, groupInfo: GroupInfo, showMenu: MutableState<Boolean>) {
// revert from this:
DefaultDropdownMenu(showMenu) {
if (member.canBeRemoved(groupInfo)) {
ItemAction(stringResource(MR.strings.remove_member_button), painterResource(MR.images.ic_delete), color = MaterialTheme.colors.error, onClick = {
@@ -434,6 +444,49 @@ private fun DropDownMenuForMember(rhId: Long?, member: GroupMember, groupInfo: G
})
}
}
// revert to this: vvv
// if (groupInfo.membership.memberRole >= GroupMemberRole.Admin) {
// val canBlockForAll = member.canBlockForAll(groupInfo)
// val canRemove = member.canBeRemoved(groupInfo)
// if (canBlockForAll || canRemove) {
// DefaultDropdownMenu(showMenu) {
// if (canBlockForAll) {
// if (member.blockedByAdmin) {
// ItemAction(stringResource(MR.strings.unblock_for_all), painterResource(MR.images.ic_do_not_touch), onClick = {
// unblockForAllAlert(rhId, groupInfo, member)
// showMenu.value = false
// })
// } else {
// ItemAction(stringResource(MR.strings.block_for_all), painterResource(MR.images.ic_back_hand), color = MaterialTheme.colors.error, onClick = {
// blockForAllAlert(rhId, groupInfo, member)
// showMenu.value = false
// })
// }
// }
// if (canRemove) {
// ItemAction(stringResource(MR.strings.remove_member_button), painterResource(MR.images.ic_delete), color = MaterialTheme.colors.error, onClick = {
// removeMemberAlert(rhId, groupInfo, member)
// showMenu.value = false
// })
// }
// }
// }
// } else if (!member.blockedByAdmin) {
// DefaultDropdownMenu(showMenu) {
// if (member.memberSettings.showMessages) {
// ItemAction(stringResource(MR.strings.block_member_button), painterResource(MR.images.ic_back_hand), color = MaterialTheme.colors.error, onClick = {
// blockMemberAlert(rhId, groupInfo, member)
// showMenu.value = false
// })
// } else {
// ItemAction(stringResource(MR.strings.unblock_member_button), painterResource(MR.images.ic_do_not_touch), onClick = {
// unblockMemberAlert(rhId, groupInfo, member)
// showMenu.value = false
// })
// }
// }
// }
// ^^^
}
@Composable
@@ -3,9 +3,11 @@ package chat.simplex.common.views.chat.group
import InfoRow
import SectionBottomSpacer
import SectionDividerSpaced
import SectionItemView
import SectionSpacer
import SectionTextFooter
import SectionView
import TextIconSpaced
import androidx.compose.desktop.ui.tooling.preview.Preview
import java.net.URI
import androidx.compose.foundation.*
@@ -99,6 +101,8 @@ fun GroupMemberInfoView(
},
blockMember = { blockMemberAlert(rhId, groupInfo, member) },
unblockMember = { unblockMemberAlert(rhId, groupInfo, member) },
blockForAll = { blockForAllAlert(rhId, groupInfo, member) },
unblockForAll = { unblockForAllAlert(rhId, groupInfo, member) },
removeMember = { removeMemberDialog(rhId, groupInfo, member, chatModel, close) },
onRoleSelected = {
if (it == newRole.value) return@GroupMemberInfoLayout
@@ -230,6 +234,8 @@ fun GroupMemberInfoLayout(
connectViaAddress: (String) -> Unit,
blockMember: () -> Unit,
unblockMember: () -> Unit,
blockForAll: () -> Unit,
unblockForAll: () -> Unit,
removeMember: () -> Unit,
onRoleSelected: (GroupMemberRole) -> Unit,
switchMemberAddress: () -> Unit,
@@ -248,6 +254,46 @@ fun GroupMemberInfoLayout(
}
}
@Composable
fun AdminDestructiveSection() {
val canBlockForAll = member.canBlockForAll(groupInfo)
val canRemove = member.canBeRemoved(groupInfo)
if (canBlockForAll || canRemove) {
SectionDividerSpaced(maxBottomPadding = false)
SectionView {
if (canBlockForAll) {
if (member.blockedByAdmin) {
UnblockForAllButton(unblockForAll)
} else {
BlockForAllButton(blockForAll)
}
}
if (canRemove) {
RemoveMemberButton(removeMember)
}
}
}
}
@Composable
fun NonAdminBlockSection() {
SectionDividerSpaced(maxBottomPadding = false)
SectionView {
if (member.blockedByAdmin) {
SettingsActionItem(
painterResource(MR.images.ic_back_hand),
stringResource(MR.strings.member_blocked_by_admin),
click = null,
disabled = true
)
} else if (member.memberSettings.showMessages) {
BlockMemberButton(blockMember)
} else {
UnblockMemberButton(unblockMember)
}
}
}
Column(
Modifier
.fillMaxWidth()
@@ -344,6 +390,7 @@ fun GroupMemberInfoLayout(
}
}
// revert from this:
SectionDividerSpaced(maxBottomPadding = false)
SectionView {
if (member.memberSettings.showMessages) {
@@ -355,6 +402,13 @@ fun GroupMemberInfoLayout(
RemoveMemberButton(removeMember)
}
}
// revert to this: vvv
// if (groupInfo.membership.memberRole >= GroupMemberRole.Admin) {
// AdminDestructiveSection()
// } else {
// NonAdminBlockSection()
// }
// ^^^
if (developerTools) {
SectionDividerSpaced()
@@ -427,6 +481,26 @@ fun UnblockMemberButton(onClick: () -> Unit) {
)
}
@Composable
fun BlockForAllButton(onClick: () -> Unit) {
SettingsActionItem(
painterResource(MR.images.ic_back_hand),
stringResource(MR.strings.block_for_all),
click = onClick,
textColor = Color.Red,
iconColor = Color.Red,
)
}
@Composable
fun UnblockForAllButton(onClick: () -> Unit) {
SettingsActionItem(
painterResource(MR.images.ic_do_not_touch),
stringResource(MR.strings.unblock_for_all),
click = onClick
)
}
@Composable
fun RemoveMemberButton(onClick: () -> Unit) {
SettingsActionItem(
@@ -553,6 +627,36 @@ fun updateMemberSettings(rhId: Long?, gInfo: GroupInfo, member: GroupMember, mem
}
}
fun blockForAllAlert(rhId: Long?, gInfo: GroupInfo, mem: GroupMember) {
AlertManager.shared.showAlertDialog(
title = generalGetString(MR.strings.block_for_all_question),
text = generalGetString(MR.strings.block_member_desc).format(mem.chatViewName),
confirmText = generalGetString(MR.strings.block_for_all),
onConfirm = {
blockMemberForAll(rhId, gInfo, mem, true)
},
destructive = true,
)
}
fun unblockForAllAlert(rhId: Long?, gInfo: GroupInfo, mem: GroupMember) {
AlertManager.shared.showAlertDialog(
title = generalGetString(MR.strings.unblock_for_all_question),
text = generalGetString(MR.strings.unblock_member_desc).format(mem.chatViewName),
confirmText = generalGetString(MR.strings.unblock_for_all),
onConfirm = {
blockMemberForAll(rhId, gInfo, mem, false)
},
)
}
fun blockMemberForAll(rhId: Long?, gInfo: GroupInfo, member: GroupMember, blocked: Boolean) {
withBGApi {
val updatedMember = ChatController.apiBlockMemberForAll(rhId, gInfo.groupId, member.groupMemberId, blocked)
chatModel.upsertGroupMember(rhId, gInfo, updatedMember)
}
}
@Preview
@Composable
fun PreviewGroupMemberInfoLayout() {
@@ -570,6 +674,8 @@ fun PreviewGroupMemberInfoLayout() {
connectViaAddress = {},
blockMember = {},
unblockMember = {},
blockForAll = {},
unblockForAll = {},
removeMember = {},
onRoleSelected = {},
switchMemberAddress = {},
@@ -68,8 +68,8 @@ fun CIFileView(
fun fileAction() {
if (file != null) {
when (file.fileStatus) {
is CIFileStatus.RcvInvitation -> {
when {
file.fileStatus is CIFileStatus.RcvInvitation -> {
if (fileSizeValid()) {
receiveFile(file.fileId)
} else {
@@ -79,7 +79,7 @@ fun CIFileView(
)
}
}
is CIFileStatus.RcvAccepted ->
file.fileStatus is CIFileStatus.RcvAccepted ->
when (file.fileProtocol) {
FileProtocol.XFTP ->
AlertManager.shared.showAlertMsg(
@@ -91,9 +91,10 @@ fun CIFileView(
generalGetString(MR.strings.waiting_for_file),
generalGetString(MR.strings.file_will_be_received_when_contact_is_online)
)
FileProtocol.LOCAL -> {}
}
is CIFileStatus.RcvComplete -> {
withBGApi {
file.fileStatus is CIFileStatus.RcvComplete || (file.fileStatus is CIFileStatus.SndStored && file.fileProtocol == FileProtocol.LOCAL) -> {
withLongRunningApi(slow = 60_000, deadlock = 600_000) {
var filePath = getLoadedFilePath(file)
if (chatModel.connectedToRemote() && filePath == null) {
file.loadRemoteFile(true)
@@ -152,11 +153,13 @@ fun CIFileView(
when (file.fileProtocol) {
FileProtocol.XFTP -> progressIndicator()
FileProtocol.SMP -> fileIcon()
FileProtocol.LOCAL -> fileIcon()
}
is CIFileStatus.SndTransfer ->
when (file.fileProtocol) {
FileProtocol.XFTP -> progressCircle(file.fileStatus.sndProgress, file.fileStatus.sndTotal)
FileProtocol.SMP -> progressIndicator()
FileProtocol.LOCAL -> {}
}
is CIFileStatus.SndComplete -> fileIcon(innerIcon = painterResource(MR.images.ic_check_filled))
is CIFileStatus.SndCancelled -> fileIcon(innerIcon = painterResource(MR.images.ic_close))
@@ -70,6 +70,7 @@ fun CIImageView(
when (file.fileProtocol) {
FileProtocol.XFTP -> progressIndicator()
FileProtocol.SMP -> {}
FileProtocol.LOCAL -> {}
}
is CIFileStatus.SndTransfer -> progressIndicator()
is CIFileStatus.SndComplete -> fileIcon(painterResource(MR.images.ic_check_filled), MR.strings.icon_descr_image_snd_complete)
@@ -199,6 +200,7 @@ fun CIImageView(
generalGetString(MR.strings.waiting_for_image),
generalGetString(MR.strings.image_will_be_received_when_contact_is_online)
)
FileProtocol.LOCAL -> {}
}
CIFileStatus.RcvTransfer(rcvProgress = 7, rcvTotal = 10) -> {} // ?
CIFileStatus.RcvComplete -> {} // ?
@@ -41,7 +41,7 @@ fun CIVideoView(
val filePath = remember(file, CIFile.cachedRemoteFileRequests.toList()) { mutableStateOf(getLoadedFilePath(file)) }
if (chatModel.connectedToRemote()) {
LaunchedEffect(file) {
withBGApi {
withLongRunningApi(slow = 60_000, deadlock = 600_000) {
if (file != null && file.loaded && getLoadedFilePath(file) == null) {
file.loadRemoteFile(false)
filePath.value = getLoadedFilePath(file)
@@ -82,12 +82,12 @@ fun CIVideoView(
generalGetString(MR.strings.waiting_for_video),
generalGetString(MR.strings.video_will_be_received_when_contact_completes_uploading)
)
FileProtocol.SMP ->
AlertManager.shared.showAlertMsg(
generalGetString(MR.strings.waiting_for_video),
generalGetString(MR.strings.video_will_be_received_when_contact_is_online)
)
FileProtocol.LOCAL -> {}
}
CIFileStatus.RcvTransfer(rcvProgress = 7, rcvTotal = 10) -> {} // ?
CIFileStatus.RcvComplete -> {} // ?
@@ -377,11 +377,13 @@ private fun loadingIndicator(file: CIFile?) {
when (file.fileProtocol) {
FileProtocol.XFTP -> progressIndicator()
FileProtocol.SMP -> {}
FileProtocol.LOCAL -> {}
}
is CIFileStatus.SndTransfer ->
when (file.fileProtocol) {
FileProtocol.XFTP -> progressCircle(file.fileStatus.sndProgress, file.fileStatus.sndTotal)
FileProtocol.SMP -> progressIndicator()
FileProtocol.LOCAL -> {}
}
is CIFileStatus.SndComplete -> fileIcon(painterResource(MR.images.ic_check_filled), MR.strings.icon_descr_video_snd_complete)
is CIFileStatus.SndCancelled -> fileIcon(painterResource(MR.images.ic_close), MR.strings.icon_descr_file)
@@ -183,7 +183,7 @@ fun ChatItemView(
if (cInfo.featureEnabled(ChatFeature.Reactions) && cItem.allowAddReaction) {
MsgReactionsMenu()
}
if (cItem.meta.itemDeleted == null && !live) {
if (cItem.meta.itemDeleted == null && !live && !cItem.localNote) {
ItemAction(stringResource(MR.strings.reply_verb), painterResource(MR.images.ic_reply), onClick = {
if (composeState.value.editing) {
composeState.value = ComposeState(contextItem = ComposeContextItem.QuotedItem(cItem), useLinkPreviews = useLinkPreviews)
@@ -213,7 +213,7 @@ fun ChatItemView(
showMenu.value = false
}
if (chatModel.connectedToRemote() && fileSource == null) {
withBGApi {
withLongRunningApi(slow = 60_000, deadlock = 600_000) {
cItem.file?.loadRemoteFile(true)
fileSource = getLoadedFileSource(cItem.file)
shareIfExists()
@@ -240,7 +240,7 @@ fun ChatItemView(
if (revealed.value) {
HideItemAction(revealed, showMenu)
}
if (cItem.meta.itemDeleted == null && cItem.file != null && cItem.file.cancelAction != null) {
if (cItem.meta.itemDeleted == null && cItem.file != null && cItem.file.cancelAction != null && !cItem.localNote) {
CancelFileItemAction(cItem.file.fileId, showMenu, cancelFile = cancelFile, cancelAction = cItem.file.cancelAction)
}
if (!(live && cItem.meta.isLive)) {
@@ -319,7 +319,7 @@ fun ChatItemView(
}
}
@Composable fun DeletedItem() {
@Composable fun LegacyDeletedItem() {
DeletedItemView(cItem, cInfo.timedMessagesTTL)
DefaultDropdownMenu(showMenu) {
ItemInfoAction(cInfo, cItem, showItemDetails, showMenu)
@@ -371,7 +371,7 @@ fun ChatItemView(
}
@Composable
fun ModeratedItem() {
fun DeletedItem() {
MarkedDeletedItemView(cItem, cInfo.timedMessagesTTL, revealed)
DefaultDropdownMenu(showMenu) {
ItemInfoAction(cInfo, cItem, showItemDetails, showMenu)
@@ -382,8 +382,8 @@ fun ChatItemView(
when (val c = cItem.content) {
is CIContent.SndMsgContent -> ContentItem()
is CIContent.RcvMsgContent -> ContentItem()
is CIContent.SndDeleted -> DeletedItem()
is CIContent.RcvDeleted -> DeletedItem()
is CIContent.SndDeleted -> LegacyDeletedItem()
is CIContent.RcvDeleted -> LegacyDeletedItem()
is CIContent.SndCall -> CallItem(c.status, c.duration)
is CIContent.RcvCall -> CallItem(c.status, c.duration)
is CIContent.RcvIntegrityError -> if (developerTools) {
@@ -449,8 +449,9 @@ fun ChatItemView(
CIChatFeatureView(cItem, c.groupFeature, Color.Red, revealed = revealed, showMenu = showMenu)
MsgContentItemDropdownMenu()
}
is CIContent.SndModerated -> ModeratedItem()
is CIContent.RcvModerated -> ModeratedItem()
is CIContent.SndModerated -> DeletedItem()
is CIContent.RcvModerated -> DeletedItem()
is CIContent.RcvBlocked -> DeletedItem()
is CIContent.InvalidJSON -> CIInvalidJSONView(c.json)
}
}
@@ -677,7 +678,7 @@ fun deleteMessageAlertDialog(chatItem: ChatItem, questionText: String, deleteMes
deleteMessage(chatItem.id, CIDeleteMode.cidmInternal)
AlertManager.shared.hideAlert()
}) { Text(stringResource(MR.strings.for_me_only), color = MaterialTheme.colors.error) }
if (chatItem.meta.editable) {
if (chatItem.meta.editable && !chatItem.localNote) {
Spacer(Modifier.padding(horizontal = 4.dp))
TextButton(onClick = {
deleteMessage(chatItem.id, CIDeleteMode.cidmBroadcast)
@@ -209,7 +209,10 @@ fun FramedItemView(
is CIDeleted.Blocked -> {
FramedItemHeader(stringResource(MR.strings.blocked_item_description), true, painterResource(MR.images.ic_back_hand))
}
else -> {
is CIDeleted.BlockedByAdmin -> {
FramedItemHeader(stringResource(MR.strings.blocked_by_admin_item_description), true, painterResource(MR.images.ic_back_hand))
}
is CIDeleted.Deleted -> {
FramedItemHeader(stringResource(MR.strings.marked_deleted_description), true, painterResource(MR.images.ic_delete))
}
}
@@ -48,6 +48,7 @@ private fun MergedMarkedDeletedText(chatItem: ChatItem, revealed: MutableState<B
val reversedChatItems = ChatModel.chatItems.asReversed()
var moderated = 0
var blocked = 0
var blockedByAdmin = 0
var deleted = 0
val moderatedBy: MutableSet<String> = mutableSetOf()
while (i < reversedChatItems.size) {
@@ -59,16 +60,19 @@ private fun MergedMarkedDeletedText(chatItem: ChatItem, revealed: MutableState<B
moderatedBy.add(itemDeleted.byGroupMember.displayName)
}
is CIDeleted.Blocked -> blocked += 1
is CIDeleted.BlockedByAdmin -> blockedByAdmin +=1
is CIDeleted.Deleted -> deleted += 1
}
i++
}
val total = moderated + blocked + deleted
val total = moderated + blocked + blockedByAdmin + deleted
if (total <= 1)
markedDeletedText(chatItem.meta)
else if (total == moderated)
stringResource(MR.strings.moderated_items_description).format(total, moderatedBy.joinToString(", "))
else if (total == blocked)
else if (total == blockedByAdmin)
stringResource(MR.strings.blocked_by_admin_items_description).format(total)
else if (total == blocked + blockedByAdmin)
stringResource(MR.strings.blocked_items_description).format(total)
else
stringResource(MR.strings.marked_deleted_items_description).format(total)
@@ -93,7 +97,9 @@ private fun markedDeletedText(meta: CIMeta): String =
String.format(generalGetString(MR.strings.moderated_item_description), meta.itemDeleted.byGroupMember.displayName)
is CIDeleted.Blocked ->
generalGetString(MR.strings.blocked_item_description)
else ->
is CIDeleted.BlockedByAdmin ->
generalGetString(MR.strings.blocked_by_admin_item_description)
is CIDeleted.Deleted, null ->
generalGetString(MR.strings.marked_deleted_description)
}
@@ -95,6 +95,25 @@ fun ChatListNavLinkView(chat: Chat, nextChatSelected: State<Boolean>) {
selectedChat,
nextChatSelected,
)
is ChatInfo.Local -> {
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)
}
},
click = { noteFolderChatAction(chat.remoteHostId, chat.chatInfo.noteFolder) },
dropdownMenuItems = {
tryOrShowError("${chat.id}ChatListNavLinkDropdown", error = {}) {
NoteFolderMenuItems(chat, showMenu, showMarkRead)
}
},
showMenu,
disabled,
selectedChat,
nextChatSelected,
)
}
is ChatInfo.ContactRequest ->
ChatListNavLinkLayout(
chatLinkPreview = {
@@ -174,6 +193,10 @@ fun groupChatAction(rhId: Long?, groupInfo: GroupInfo, chatModel: ChatModel, inP
}
}
fun noteFolderChatAction(rhId: Long?, noteFolder: NoteFolder) {
withBGApi { openChat(rhId, ChatInfo.Local(noteFolder), chatModel) }
}
suspend fun openDirectChat(rhId: Long?, contactId: Long, chatModel: ChatModel) {
val chat = chatModel.controller.apiGetChat(rhId, ChatType.Direct, contactId)
if (chat != null) {
@@ -247,7 +270,7 @@ fun ContactMenuItems(chat: Chat, contact: Contact, chatModel: ChatModel, showMen
}
ToggleFavoritesChatAction(chat, chatModel, chat.chatInfo.chatSettings?.favorite == true, showMenu)
ToggleNotificationsChatAction(chat, chatModel, chat.chatInfo.ntfsEnabled, showMenu)
ClearChatAction(chat, chatModel, showMenu)
ClearChatAction(chat, showMenu)
}
DeleteContactAction(chat, chatModel, showMenu)
}
@@ -286,7 +309,7 @@ fun GroupMenuItems(
}
ToggleFavoritesChatAction(chat, chatModel, chat.chatInfo.chatSettings?.favorite == true, showMenu)
ToggleNotificationsChatAction(chat, chatModel, chat.chatInfo.ntfsEnabled, showMenu)
ClearChatAction(chat, chatModel, showMenu)
ClearChatAction(chat, showMenu)
if (groupInfo.membership.memberCurrent) {
LeaveGroupAction(chat.remoteHostId, groupInfo, chatModel, showMenu)
}
@@ -297,6 +320,16 @@ fun GroupMenuItems(
}
}
@Composable
fun NoteFolderMenuItems(chat: Chat, showMenu: MutableState<Boolean>, showMarkRead: Boolean) {
if (showMarkRead) {
MarkReadChatAction(chat, chatModel, showMenu)
} else {
MarkUnreadChatAction(chat, chatModel, showMenu)
}
ClearNoteFolderAction(chat, showMenu)
}
@Composable
fun MarkReadChatAction(chat: Chat, chatModel: ChatModel, showMenu: MutableState<Boolean>) {
ItemAction(
@@ -347,12 +380,25 @@ fun ToggleNotificationsChatAction(chat: Chat, chatModel: ChatModel, ntfsEnabled:
}
@Composable
fun ClearChatAction(chat: Chat, chatModel: ChatModel, showMenu: MutableState<Boolean>) {
fun ClearChatAction(chat: Chat, showMenu: MutableState<Boolean>) {
ItemAction(
stringResource(MR.strings.clear_chat_menu_action),
painterResource(MR.images.ic_settings_backup_restore),
onClick = {
clearChatDialog(chat, chatModel)
clearChatDialog(chat)
showMenu.value = false
},
color = WarningOrange
)
}
@Composable
fun ClearNoteFolderAction(chat: Chat, showMenu: MutableState<Boolean>) {
ItemAction(
stringResource(MR.strings.clear_chat_menu_action),
painterResource(MR.images.ic_settings_backup_restore),
onClick = {
clearNoteFolderDialog(chat)
showMenu.value = false
},
color = WarningOrange
@@ -107,7 +107,9 @@ fun ChatListView(chatModel: ChatModel, settingsState: SettingsViewState, setPerf
modifier = Modifier
.fillMaxSize()
) {
ChatList(chatModel, searchText = searchText)
if (!chatModel.desktopNoUserNoRemote) {
ChatList(chatModel, searchText = searchText)
}
if (chatModel.chats.isEmpty() && !chatModel.switchingUsersAndHosts.value && !chatModel.desktopNoUserNoRemote) {
Text(stringResource(
if (chatModel.chatRunning.value == null) MR.strings.loading_chats else MR.strings.you_have_no_chats), Modifier.align(Alignment.Center), color = MaterialTheme.colors.secondary)
@@ -516,6 +518,7 @@ private fun filteredChats(
} else {
viewNameContains(cInfo, s)
}
is ChatInfo.Local -> s.isEmpty() || viewNameContains(cInfo, s)
is ChatInfo.ContactRequest -> s.isEmpty() || viewNameContains(cInfo, s)
is ChatInfo.ContactConnection -> (s.isNotEmpty() && cInfo.contactConnection.localAlias.lowercase().contains(s)) || (s.isEmpty() && chat.id == chatModel.chatId.value)
is ChatInfo.InvalidJSON -> chat.id == chatModel.chatId.value
@@ -9,9 +9,10 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import chat.simplex.common.ui.theme.Indigo
import chat.simplex.common.views.helpers.ProfileImage
import chat.simplex.common.model.*
import chat.simplex.common.ui.theme.*
import chat.simplex.res.MR
@Composable
fun ShareListNavLinkView(chat: Chat, chatModel: ChatModel) {
@@ -29,6 +30,12 @@ fun ShareListNavLinkView(chat: Chat, chatModel: ChatModel) {
click = { groupChatAction(chat.remoteHostId, chat.chatInfo.groupInfo, chatModel) },
stopped
)
is ChatInfo.Local ->
ShareListNavLinkLayout(
chatLinkPreview = { SharePreviewView(chat) },
click = { noteFolderChatAction(chat.remoteHostId, chat.chatInfo.noteFolder) },
stopped
)
is ChatInfo.ContactRequest, is ChatInfo.ContactConnection, is ChatInfo.InvalidJSON -> {}
}
}
@@ -56,7 +63,11 @@ private fun SharePreviewView(chat: Chat) {
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(4.dp)
) {
ProfileImage(size = 46.dp, chat.chatInfo.image)
if (chat.chatInfo is ChatInfo.Local) {
ProfileImage(size = 46.dp, null, icon = MR.images.ic_folder_filled, color = NoteFolderIconColor)
} else {
ProfileImage(size = 46.dp, chat.chatInfo.image)
}
Text(
chat.chatInfo.chatViewName, maxLines = 1, overflow = TextOverflow.Ellipsis,
color = if (chat.chatInfo.incognito) Indigo else Color.Unspecified
@@ -213,26 +213,29 @@ fun UserPicker(
userPickerState.value = AnimatedViewState.GONE
}
Divider(Modifier.requiredHeight(1.dp))
} else if (remoteHosts.isEmpty()) {
LinkAMobilePickerItem {
ModalManager.start.showModal {
ConnectMobileView()
} else {
if (remoteHosts.isEmpty()) {
LinkAMobilePickerItem {
ModalManager.start.showModal {
ConnectMobileView()
}
userPickerState.value = AnimatedViewState.GONE
}
userPickerState.value = AnimatedViewState.GONE
Divider(Modifier.requiredHeight(1.dp))
}
Divider(Modifier.requiredHeight(1.dp))
} else if (chatModel.desktopNoUserNoRemote) {
CreateInitialProfile {
doWithAuth(generalGetString(MR.strings.auth_open_chat_profiles), generalGetString(MR.strings.auth_log_in_using_credential)) {
ModalManager.center.showModalCloseable { close ->
LaunchedEffect(Unit) {
userPickerState.value = AnimatedViewState.HIDING
if (chatModel.desktopNoUserNoRemote) {
CreateInitialProfile {
doWithAuth(generalGetString(MR.strings.auth_open_chat_profiles), generalGetString(MR.strings.auth_log_in_using_credential)) {
ModalManager.center.showModalCloseable { close ->
LaunchedEffect(Unit) {
userPickerState.value = AnimatedViewState.HIDING
}
CreateProfile(chat.simplex.common.platform.chatModel, close)
}
CreateProfile(chat.simplex.common.platform.chatModel, close)
}
}
Divider(Modifier.requiredHeight(1.dp))
}
Divider(Modifier.requiredHeight(1.dp))
}
if (showSettings) {
SettingsPickerItem(settingsClicked)
@@ -62,7 +62,7 @@ fun DatabaseEncryptionView(m: ChatModel) {
initialRandomDBPassphrase,
progressIndicator,
onConfirmEncrypt = {
withBGApi {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
encryptDatabase(currentKey, newKey, confirmNewKey, initialRandomDBPassphrase, useKeychain, storedKey, progressIndicator)
}
}
@@ -368,7 +368,7 @@ fun chatArchiveTitle(chatArchiveTime: Instant, chatLastStart: Instant): String {
}
fun startChat(m: ChatModel, chatLastStart: MutableState<Instant?>, chatDbChanged: MutableState<Boolean>, progressIndicator: MutableState<Boolean>? = null) {
withBGApi {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
try {
progressIndicator?.value = true
if (chatDbChanged.value) {
@@ -378,12 +378,12 @@ fun startChat(m: ChatModel, chatLastStart: MutableState<Instant?>, chatDbChanged
if (m.chatDbStatus.value !is DBMigrationResult.OK) {
/** Hide current view and show [DatabaseErrorView] */
ModalManager.closeAllModalsEverywhere()
return@withBGApi
return@withLongRunningApi
}
val user = m.currentUser.value
if (user == null) {
ModalManager.closeAllModalsEverywhere()
return@withBGApi
return@withLongRunningApi
} else {
m.controller.startChat(user)
}
@@ -470,10 +470,10 @@ suspend fun deleteChatAsync(m: ChatModel) {
m.controller.apiDeleteStorage()
DatabaseUtils.ksDatabasePassword.remove()
m.controller.appPrefs.storeDBPassphrase.set(true)
deleteAppDatabaseAndFiles()
deleteChatDatabaseFilesAndState()
}
fun deleteAppDatabaseAndFiles() {
fun deleteChatDatabaseFilesAndState() {
val chat = File(dataDir, chatDatabaseFileName)
val chatBak = File(dataDir, "$chatDatabaseFileName.bak")
val agent = File(dataDir, agentDatabaseFileName)
@@ -489,6 +489,13 @@ fun deleteAppDatabaseAndFiles() {
tmpDir.mkdir()
DatabaseUtils.ksDatabasePassword.remove()
controller.appPrefs.storeDBPassphrase.set(true)
controller.ctrl = null
// Clear sensitive data on screen just in case ModalManager will fail to prevent hiding its modals while database encrypts itself
chatModel.chatId.value = null
chatModel.chatItems.clear()
chatModel.chats.clear()
chatModel.users.clear()
}
private fun exportArchive(
@@ -574,7 +581,7 @@ private fun importArchive(
progressIndicator.value = true
val archivePath = saveArchiveFromURI(importedArchiveURI)
if (archivePath != null) {
withBGApi {
withLongRunningApi(slow = 60_000, deadlock = 180_000) {
try {
m.controller.apiDeleteStorage()
try {
@@ -17,6 +17,7 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import chat.simplex.common.model.ChatInfo
import chat.simplex.common.platform.base64ToBitmap
import chat.simplex.common.ui.theme.NoteFolderIconColor
import chat.simplex.common.ui.theme.SimpleXTheme
import chat.simplex.res.MR
import dev.icerock.moko.resources.ImageResource
@@ -24,9 +25,12 @@ import dev.icerock.moko.resources.ImageResource
@Composable
fun ChatInfoImage(chatInfo: ChatInfo, size: Dp, iconColor: Color = MaterialTheme.colors.secondaryVariant) {
val icon =
if (chatInfo is ChatInfo.Group) MR.images.ic_supervised_user_circle_filled
else MR.images.ic_account_circle_filled
ProfileImage(size, chatInfo.image, icon, iconColor)
when (chatInfo) {
is ChatInfo.Group -> MR.images.ic_supervised_user_circle_filled
is ChatInfo.Direct -> MR.images.ic_account_circle_filled
else -> MR.images.ic_folder_filled
}
ProfileImage(size, chatInfo.image, icon, if (chatInfo is ChatInfo.Local) NoteFolderIconColor else iconColor)
}
@Composable
@@ -16,7 +16,7 @@ class ProcessedErrors <T: AgentErrorType>(val interval: Long) {
fun newError(error: T, offerRestart: Boolean) {
timer.cancel()
timer = withBGApi {
timer = withLongRunningApi(slow = 70_000, deadlock = 130_000) {
val delayBeforeNext = (lastShownTimestamp + interval) - System.currentTimeMillis()
if ((lastShownOfferRestart || !offerRestart) && delayBeforeNext >= 0) {
delay(delayBeforeNext)
@@ -27,11 +27,9 @@ import kotlin.math.*
private val singleThreadDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
fun withApi(action: suspend CoroutineScope.() -> Unit): Job = withScope(GlobalScope, action)
fun withScope(scope: CoroutineScope, action: suspend CoroutineScope.() -> Unit): Job =
fun withApi(action: suspend CoroutineScope.() -> Unit): Job =
Exception().let {
scope.launch { withContext(Dispatchers.Main, block = { wrapWithLogging(action, it) }) }
CoroutineScope(Dispatchers.Main).launch(block = { wrapWithLogging(action, it) })
}
fun withBGApi(action: suspend CoroutineScope.() -> Unit): Job =
@@ -132,6 +130,8 @@ const val MAX_FILE_SIZE_SMP: Long = 8000000
const val MAX_FILE_SIZE_XFTP: Long = 1_073_741_824 // 1GB
const val MAX_FILE_SIZE_LOCAL: Long = Long.MAX_VALUE
expect fun getAppFileUri(fileName: String): URI
// https://developer.android.com/training/data-storage/shared/documents-files#bitmap
@@ -357,6 +357,7 @@ fun getMaxFileSize(fileProtocol: FileProtocol): Long {
return when (fileProtocol) {
FileProtocol.XFTP -> MAX_FILE_SIZE_XFTP
FileProtocol.SMP -> MAX_FILE_SIZE_SMP
FileProtocol.LOCAL -> MAX_FILE_SIZE_LOCAL
}
}
@@ -49,7 +49,7 @@ fun LocalAuthView(m: ChatModel, authRequest: LocalAuthRequest) {
}
private fun deleteStorageAndRestart(m: ChatModel, password: String, completed: (LAResult) -> Unit) {
withBGApi {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
try {
/** Waiting until [initChatController] finishes */
while (m.ctrlInitInProgress.value) {
@@ -67,12 +67,7 @@ private fun deleteStorageAndRestart(m: ChatModel, password: String, completed: (
* */
chatCloseStore(ctrl)
}
deleteAppDatabaseAndFiles()
// Clear sensitive data on screen just in case ModalManager fails to hide its modals while new database is created
m.chatId.value = null
m.chatItems.clear()
m.chats.clear()
m.users.clear()
deleteChatDatabaseFilesAndState()
ksAppPassword.set(password)
ksSelfDestructPassword.remove()
ntfManager.cancelAllNotifications()
@@ -81,16 +76,9 @@ private fun deleteStorageAndRestart(m: ChatModel, password: String, completed: (
val displayName = displayNamePref.get()
selfDestructPref.set(false)
displayNamePref.set(null)
m.chatDbChanged.value = true
m.chatDbStatus.value = null
try {
initChatController()
} catch (e: Exception) {
Log.d(TAG, "initializeChat ${e.stackTraceToString()}")
}
m.chatDbChanged.value = false
reinitChatController()
if (m.currentUser.value != null) {
return@withBGApi
return@withLongRunningApi
}
var profile: Profile? = null
if (!displayName.isNullOrEmpty()) {
@@ -100,7 +88,6 @@ private fun deleteStorageAndRestart(m: ChatModel, password: String, completed: (
m.currentUser.value = createdUser
m.controller.appPrefs.onboardingStage.set(OnboardingStage.OnboardingComplete)
if (createdUser != null) {
controller.chatModel.chatRunning.value = false
m.controller.startChat(createdUser)
}
ModalManager.closeAllModalsEverywhere()
@@ -113,3 +100,14 @@ private fun deleteStorageAndRestart(m: ChatModel, password: String, completed: (
}
}
}
suspend fun reinitChatController() {
chatModel.chatDbChanged.value = true
chatModel.chatDbStatus.value = null
try {
initChatController()
} catch (e: Exception) {
Log.d(TAG, "initializeChat ${e.stackTraceToString()}")
}
chatModel.chatDbChanged.value = false
}
@@ -173,17 +173,6 @@ private fun prepareChatBeforeAddressCreation(rhId: Long?) {
withBGApi {
val user = chatModel.controller.apiGetActiveUser(rhId) ?: return@withBGApi
chatModel.currentUser.value = user
if (chatModel.users.isEmpty()) {
if (appPlatform.isDesktop) {
// Make possible to use chat after going to remote device linking and returning back to local profile creation
chatModel.chatRunning.value = false
}
chatModel.controller.startChat(user)
} else {
val users = chatModel.controller.listUsers(rhId)
chatModel.users.clear()
chatModel.users.addAll(users)
chatModel.controller.getUserChatData(rhId)
}
chatModel.controller.startChat(user)
}
}
@@ -50,7 +50,7 @@ fun SetupDatabasePassphrase(m: ChatModel) {
confirmNewKey,
progressIndicator,
onConfirmEncrypt = {
withBGApi {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
if (m.chatRunning.value == true) {
// Stop chat if it's started before doing anything
stopChatAsync(m)
@@ -462,6 +462,39 @@ private val versionDescriptions: List<VersionDescription> = listOf(
)
)
),
VersionDescription(
version = "v5.5",
post = "https://simplex.chat/blog/20240124-simplex-chat-infrastructure-costs-v5-5-simplex-ux-private-notes-group-history.html",
features = listOf(
FeatureDescription(
icon = MR.images.ic_folder_pen,
titleId = MR.strings.v5_5_private_notes,
descrId = MR.strings.v5_5_private_notes_descr
),
FeatureDescription(
icon = MR.images.ic_link,
titleId = MR.strings.v5_5_simpler_connect_ui,
descrId = MR.strings.v5_5_simpler_connect_ui_descr
),
FeatureDescription(
icon = MR.images.ic_forum,
titleId = MR.strings.v5_5_join_group_conversation,
descrId = MR.strings.v5_5_join_group_conversation_descr,
link = "simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion"
),
FeatureDescription(
icon = MR.images.ic_battery_3_bar,
titleId = MR.strings.v5_5_message_delivery,
descrId = MR.strings.v5_5_message_delivery_descr
),
FeatureDescription(
icon = MR.images.ic_translate,
titleId = MR.strings.v5_5_new_interface_languages,
descrId = MR.strings.whats_new_thanks_to_users_contribute_weblate,
link = "https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat"
)
)
),
)
private val lastVersion = versionDescriptions.last().version
@@ -96,7 +96,7 @@ fun PrivacySettingsView(
val currentUser = chatModel.currentUser.value
if (currentUser != null) {
fun setSendReceiptsContacts(enable: Boolean, clearOverrides: Boolean) {
withBGApi {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
val mrs = UserMsgReceiptSettings(enable, clearOverrides)
chatModel.controller.apiSetUserContactReceipts(currentUser, mrs)
chatModel.controller.appPrefs.privacyDeliveryReceiptsSet.set(true)
@@ -119,7 +119,7 @@ fun PrivacySettingsView(
}
fun setSendReceiptsGroups(enable: Boolean, clearOverrides: Boolean) {
withBGApi {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
val mrs = UserMsgReceiptSettings(enable, clearOverrides)
chatModel.controller.apiSetUserGroupReceipts(currentUser, mrs)
chatModel.controller.appPrefs.privacyDeliveryReceiptsSet.set(true)
@@ -33,7 +33,7 @@ import chat.simplex.common.views.onboarding.WhatsNewView
import chat.simplex.common.views.remote.ConnectDesktopView
import chat.simplex.common.views.remote.ConnectMobileView
import chat.simplex.res.MR
import kotlinx.coroutines.launch
import kotlinx.coroutines.*
@Composable
fun SettingsView(chatModel: ChatModel, setPerformLA: (Boolean) -> Unit, drawerState: DrawerState) {
@@ -119,7 +119,7 @@ fun SettingsLayout(
SectionItemView(showCustomModal { chatModel, close -> UserProfileView(chatModel, close) }, 80.dp, padding = PaddingValues(start = 16.dp, end = DEFAULT_PADDING), disabled = stopped) {
ProfilePreview(profile, stopped = stopped)
}
SettingsActionItem(painterResource(MR.images.ic_manage_accounts), stringResource(MR.strings.your_chat_profiles), { withAuth(generalGetString(MR.strings.auth_open_chat_profiles), generalGetString(MR.strings.auth_log_in_using_credential)) { showSettingsModalWithSearch { it, search -> UserProfilesView(it, search, profileHidden) } } }, disabled = stopped, extraPadding = true)
SettingsActionItem(painterResource(MR.images.ic_manage_accounts), stringResource(MR.strings.your_chat_profiles), { withAuth(generalGetString(MR.strings.auth_open_chat_profiles), generalGetString(MR.strings.auth_log_in_using_credential)) { showSettingsModalWithSearch { it, search -> UserProfilesView(it, search, profileHidden, drawerState) } } }, disabled = stopped, extraPadding = true)
SettingsActionItem(painterResource(MR.images.ic_qr_code), stringResource(MR.strings.your_simplex_contact_address), showCustomModal { it, close -> UserAddressView(it, shareViaProfile = it.currentUser.value!!.addressShared, close = close) }, disabled = stopped, extraPadding = true)
ChatPreferencesItem(showCustomModal, stopped = stopped)
} else if (chatModel.localUserCreated.value == false) {
@@ -27,18 +27,20 @@ import chat.simplex.common.ui.theme.*
import chat.simplex.common.views.chat.item.ItemAction
import chat.simplex.common.views.chatlist.UserProfilePickerItem
import chat.simplex.common.views.chatlist.UserProfileRow
import chat.simplex.common.views.database.PassphraseField
import chat.simplex.common.views.helpers.*
import chat.simplex.common.views.CreateProfile
import chat.simplex.common.views.database.*
import chat.simplex.common.views.onboarding.OnboardingStage
import chat.simplex.res.MR
import dev.icerock.moko.resources.StringResource
import kotlinx.coroutines.delay
import kotlinx.coroutines.*
@Composable
fun UserProfilesView(m: ChatModel, search: MutableState<String>, profileHidden: MutableState<Boolean>) {
fun UserProfilesView(m: ChatModel, search: MutableState<String>, profileHidden: MutableState<Boolean>, drawerState: DrawerState) {
val searchTextOrPassword = rememberSaveable { search }
val users by remember { derivedStateOf { m.users.map { it.user } } }
val filteredUsers by remember { derivedStateOf { filteredUsers(m, searchTextOrPassword.value) } }
val scope = rememberCoroutineScope()
UserProfilesLayout(
users = users,
filteredUsers = filteredUsers,
@@ -49,6 +51,12 @@ fun UserProfilesView(m: ChatModel, search: MutableState<String>, profileHidden:
addUser = {
ModalManager.center.showModalCloseable { close ->
CreateProfile(m, close)
if (appPlatform.isDesktop) {
// Hide settings to allow clicks to pass through to CreateProfile view
DisposableEffectOnGone(always = { scope.launch { drawerState.close() } }) {
// Show settings again to allow intercept clicks to close modals after profile creation finishes
scope.launch(NonCancellable) { drawerState.open() } }
}
}
},
activateUser = { user ->
@@ -63,45 +71,34 @@ fun UserProfilesView(m: ChatModel, search: MutableState<String>, profileHidden:
}
},
removeUser = { user ->
if (m.users.size > 1 && (user.hidden || visibleUsersCount(m) > 1)) {
val text = buildAnnotatedString {
append(generalGetString(MR.strings.users_delete_all_chats_deleted) + "\n\n" + generalGetString(MR.strings.users_delete_profile_for) + " ")
withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
append(user.displayName)
}
append(":")
val text = buildAnnotatedString {
append(generalGetString(MR.strings.users_delete_all_chats_deleted) + "\n\n" + generalGetString(MR.strings.users_delete_profile_for) + " ")
withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
append(user.displayName)
}
AlertManager.shared.showAlertDialogButtonsColumn(
title = generalGetString(MR.strings.users_delete_question),
text = text,
buttons = {
Column {
SectionItemView({
AlertManager.shared.hideAlert()
removeUser(m, user, users, true, searchTextOrPassword.value.trim())
}) {
Text(stringResource(MR.strings.users_delete_with_connections), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = Color.Red)
}
SectionItemView({
AlertManager.shared.hideAlert()
removeUser(m, user, users, false, searchTextOrPassword.value.trim())
}
) {
Text(stringResource(MR.strings.users_delete_data_only), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = Color.Red)
}
append(":")
}
AlertManager.shared.showAlertDialogButtonsColumn(
title = generalGetString(MR.strings.users_delete_question),
text = text,
buttons = {
Column {
SectionItemView({
AlertManager.shared.hideAlert()
removeUser(m, user, users, true, searchTextOrPassword.value.trim())
}) {
Text(stringResource(MR.strings.users_delete_with_connections), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = Color.Red)
}
SectionItemView({
AlertManager.shared.hideAlert()
removeUser(m, user, users, false, searchTextOrPassword.value.trim())
}
) {
Text(stringResource(MR.strings.users_delete_data_only), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = Color.Red)
}
}
)
} else {
AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.cant_delete_user_profile),
text = if (m.users.size > 1) {
generalGetString(MR.strings.should_be_at_least_one_visible_profile)
} else {
generalGetString(MR.strings.should_be_at_least_one_profile)
}
)
}
}
)
},
unhideUser = { user ->
if (passwordEntryRequired(user, searchTextOrPassword.value)) {
@@ -178,7 +175,7 @@ private fun UserProfilesLayout(
SectionView {
for (user in filteredUsers) {
UserView(user, users, visibleUsersCount, activateUser, removeUser, unhideUser, muteUser, unmuteUser, showHiddenProfile)
UserView(user, visibleUsersCount, activateUser, removeUser, unhideUser, muteUser, unmuteUser, showHiddenProfile)
SectionDivider()
}
if (searchTextOrPassword.value.trim().isEmpty()) {
@@ -210,7 +207,6 @@ private fun UserProfilesLayout(
@Composable
private fun UserView(
user: User,
users: List<User>,
visibleUsersCount: Int,
activateUser: (User) -> Unit,
removeUser: (User) -> Unit,
@@ -220,7 +216,7 @@ private fun UserView(
showHiddenProfile: (User) -> Unit,
) {
val showMenu = remember { mutableStateOf(false) }
UserProfilePickerItem(user, onLongClick = { if (users.size > 1) showMenu.value = true }) {
UserProfilePickerItem(user, onLongClick = { showMenu.value = true }) {
activateUser(user)
}
Box(Modifier.padding(horizontal = DEFAULT_PADDING)) {
@@ -350,22 +346,28 @@ private fun removeUser(m: ChatModel, user: User, users: List<User>, delSMPQueues
}
private suspend fun doRemoveUser(m: ChatModel, user: User, users: List<User>, delSMPQueues: Boolean, viewPwd: String?) {
if (users.size < 2) return
suspend fun deleteUser(user: User) {
m.controller.apiDeleteUser(user, delSMPQueues, viewPwd)
m.removeUser(user)
}
try {
if (user.activeUser) {
val newActive = users.firstOrNull { u -> !u.activeUser && !u.hidden }
if (newActive != null) {
m.controller.changeActiveUser_(newActive.remoteHostId, newActive.userId, null)
deleteUser(user.copy(activeUser = false))
when {
user.activeUser -> {
val newActive = users.firstOrNull { u -> !u.activeUser && !u.hidden }
if (newActive != null) {
m.controller.changeActiveUser_(user.remoteHostId, newActive.userId, null)
m.controller.apiDeleteUser(user, delSMPQueues, viewPwd)
} else {
// Deleting the last visible user while having hidden one(s)
m.controller.apiDeleteUser(user, delSMPQueues, viewPwd)
m.controller.changeActiveUser_(user.remoteHostId, null, null)
if (appPlatform.isAndroid) {
controller.appPrefs.onboardingStage.set(OnboardingStage.Step1_SimpleXInfo)
ModalManager.closeAllModalsEverywhere()
}
}
}
else -> {
m.controller.apiDeleteUser(user, delSMPQueues, viewPwd)
}
} else {
deleteUser(user)
}
m.removeUser(user)
} catch (e: Exception) {
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_deleting_user), e.stackTraceToString())
}
@@ -99,7 +99,7 @@
<string name="cannot_receive_file">لا يمكن استقبال الملف</string>
<string name="onboarding_notifications_mode_periodic_desc"><![CDATA[<b> جيد للبطارية </b>. خدمة الخلفية تتحقق من الرسائل كل 10 دقائق. قد تفوتك مكالمات أو رسائل عاجلة.]]></string>
<string name="bold_text">عريض</string>
<string name="audio_call_no_encryption">مكالمات الصوت (ليست مشفرة بين الطرفين)</string>
<string name="audio_call_no_encryption">مكالمات الصوت (ليست مُعمّاة بين الطرفين)</string>
<string name="onboarding_notifications_mode_off_desc"><![CDATA[<b> الأفضل للبطارية </b>. ستتلقى إشعارات فقط عندما يكون التطبيق قيد التشغيل (لا توجد خدمة في الخلفية).]]></string>
<string name="onboarding_notifications_mode_service_desc"><![CDATA[<b> تستهلك المزيد من البطارية </b>! تعمل خدمة الخلفية دائمًا - تظهر الإشعارات بمجرد توفر الرسائل.]]></string>
<string name="call_already_ended">انتهت المكالمة بالفعل!</string>
@@ -145,7 +145,6 @@
<string name="settings_section_title_calls">المكالمات</string>
<string name="alert_title_cant_invite_contacts">لا يمكن دعوة جهات الاتصال!</string>
<string name="rcv_conn_event_switch_queue_phase_completed">تم تغيير العنوان من أجلك</string>
<string name="cant_delete_user_profile">لا يمكن حذف ملف تعريف المستخدم!</string>
<string name="icon_descr_video_asked_to_receive">طلب لاستلام الفيديو</string>
<string name="callstatus_in_progress">مكالمتك تحت الإجراء</string>
<string name="change_database_passphrase_question">تغيير عبارة مرور قاعدة البيانات؟</string>
@@ -180,8 +179,8 @@
<string name="create_address">إنشاء عنوان</string>
<string name="settings_section_title_chats">الدردشات</string>
<string name="confirm_new_passphrase">تأكيد عبارة المرور الجديدة…</string>
<string name="encrypt_database_question">تشفير قاعدة بيانات</string>
<string name="encrypted_database">قاعدة بيانات مشفرة</string>
<string name="encrypt_database_question">تعمية قاعدة البيانات؟</string>
<string name="encrypted_database">قاعدة البيانات مُعمّاة</string>
<string name="rcv_group_event_changed_member_role">غيرت دور %s إلى %s</string>
<string name="switch_receiving_address">تغيير عنوان الاستلام</string>
<string name="failed_to_create_user_title">خطأ في إنشاء الملف الشخصي!</string>
@@ -220,7 +219,7 @@
<string name="enable_lock">تفعيل القفل</string>
<string name="confirm_passcode">تأكيد رمز المرور</string>
<string name="error_deleting_database">خطأ في حذف قاعدة بيانات الدردشة</string>
<string name="error_encrypting_database">خطأ في تشفير قاعدة بيانات</string>
<string name="error_encrypting_database">خطأ في تعمية قاعدة البيانات</string>
<string name="chat_is_stopped_indication">توقفت الدردشة</string>
<string name="group_member_status_complete">مكتمل</string>
<string name="group_member_status_announced">جاري الاتصال (أعلن)</string>
@@ -235,10 +234,10 @@
<string name="snd_conn_event_switch_queue_phase_changing_for_member">جارِ تغيير العنوان ل%s…</string>
<string name="allow_to_send_files">السماح بإرسال الملفات والوسائط.</string>
<string name="enter_welcome_message_optional">أدخل رسالة ترحيب… (اختياري)</string>
<string name="snd_conn_event_ratchet_sync_agreed">وافق التشفير ل%s</string>
<string name="snd_conn_event_ratchet_sync_allowed">سمح بإعادة التفاوض على التشفير ل%s</string>
<string name="snd_conn_event_ratchet_sync_agreed">وافق التعمية ل%s</string>
<string name="snd_conn_event_ratchet_sync_allowed">سمح بإعادة التفاوض على التعمية ل%s</string>
<string name="error_accepting_contact_request">خطأ في قبول طلب جهة الاتصال</string>
<string name="status_contact_has_no_e2e_encryption">ليس لدى جهة الاتصال التشفير بين الطريفين</string>
<string name="status_contact_has_no_e2e_encryption">ليس لدى جهة الاتصال التعمية بين الطريفين</string>
<string name="change_self_destruct_mode">تغيير وضع التدمير الذاتي</string>
<string name="change_self_destruct_passcode">تغيير رمز المرور التدمير الذاتي</string>
<string name="confirm_database_upgrades">تأكيد ترقيات قاعدة البيانات</string>
@@ -291,7 +290,7 @@
<string name="connection_local_display_name">الاتصال %1$d</string>
<string name="display_name_connection_established">انشأت الاتصال</string>
<string name="callstatus_connecting">مكالمة جارية…</string>
<string name="encrypt_database">تشفير</string>
<string name="encrypt_database">عَمِّ</string>
<string name="enter_passphrase">أدخل عبارة المرور…</string>
<string name="group_member_status_creator">المنشئ</string>
<string name="error_adding_members">خطأ في إضافة الأعضاء</string>
@@ -317,20 +316,20 @@
<string name="create_address_and_let_people_connect">أنشئ عنوانًا للسماح للأشخاص بالتواصل معك.</string>
<string name="smp_servers_enter_manually">أدخل الخادم يدويًا</string>
<string name="colored_text">ملون</string>
<string name="status_contact_has_e2e_encryption">لدى جهة الاتصال التشفير بين الطريفين</string>
<string name="status_contact_has_e2e_encryption">لدى جهة الاتصال التعمية بين الطريفين</string>
<string name="create_profile_button">إنشاء</string>
<string name="create_your_profile">إنشاء حسابك الشخصي</string>
<string name="icon_descr_call_connecting">مكالمة جارية...</string>
<string name="enable_self_destruct">تفعيل التدمير الذاتي</string>
<string name="conn_event_ratchet_sync_started">الموافقة على التشفير…</string>
<string name="snd_conn_event_ratchet_sync_started">الموافقة على التشفير لـ%s…</string>
<string name="conn_event_ratchet_sync_started">الموافقة على التعمية…</string>
<string name="snd_conn_event_ratchet_sync_started">الموافقة على التعمية لـ%s…</string>
<string name="group_member_status_introduced">متصل (مقدم)</string>
<string name="conn_event_ratchet_sync_agreed">وافق التشفير</string>
<string name="conn_event_ratchet_sync_ok">التشفير نعم</string>
<string name="snd_conn_event_ratchet_sync_ok">التشفير نعم ل%s</string>
<string name="conn_event_ratchet_sync_allowed">سمح بإعادة التفاوض على التشفير</string>
<string name="conn_event_ratchet_sync_required">مطلوب إعادة التفاوض على التشفير</string>
<string name="snd_conn_event_ratchet_sync_required">مطلوب إعادة التفاوض على التشفير ل%s</string>
<string name="conn_event_ratchet_sync_agreed">وافق التعمية</string>
<string name="conn_event_ratchet_sync_ok">التعمية نعم</string>
<string name="snd_conn_event_ratchet_sync_ok">التعمية نعم ل%s</string>
<string name="conn_event_ratchet_sync_allowed">سمح بإعادة التفاوض على التعمية</string>
<string name="conn_event_ratchet_sync_required">مطلوب إعادة التفاوض على التعمية</string>
<string name="snd_conn_event_ratchet_sync_required">مطلوب إعادة التفاوض على التعمية ل%s</string>
<string name="error_changing_message_deletion">خطأ في تغيير الإعداد</string>
<string name="error_changing_role">خطأ في تغيير الدور</string>
<string name="alert_text_decryption_error_n_messages_failed_to_decrypt">%1$d فشل فك تشفير الرسائل.</string>
@@ -345,7 +344,7 @@
<string name="delete_group_menu_action">حذف</string>
<string name="delete_messages">حذف الرسائل</string>
<string name="delete_messages_after">حذف الرسائل بعد</string>
<string name="database_encrypted">قاعدة بيانات مشفرة!</string>
<string name="database_encrypted">قاعدة البيانات مُعمّاة!</string>
<string name="passphrase_is_different">تختلف عبارة مرور قاعدة البيانات عن تلك المحفوظة في Keystore.</string>
<string name="database_error">خطأ في قاعدة البيانات</string>
<string name="database_upgrade">ترقية قاعدة البيانات</string>
@@ -361,8 +360,8 @@
<string name="delete_database">حذف قاعدة البيانات</string>
<string name="delete_chat_profile_question">حذف ملف تعريف الدردشة؟</string>
<string name="delete_files_and_media_for_all_users">حذف الملفات لجميع ملفات تعريف الدردشة</string>
<string name="encrypted_with_random_passphrase">قاعدة البيانات مشفرة باستخدام عبارة مرور عشوائية، يمكنك تغييرها.</string>
<string name="database_will_be_encrypted_and_passphrase_stored">سيتم تشفير قاعدة البيانات وتخزين عبارة المرور في Keystore.</string>
<string name="encrypted_with_random_passphrase">قاعدة البيانات مُعمّاة باستخدام عبارة مرور عشوائية، يمكنك تغييرها.</string>
<string name="database_will_be_encrypted_and_passphrase_stored">سيتم تعمية قاعدة البيانات وتخزين عبارة المرور في Keystore.</string>
<string name="database_passphrase_is_required">عبارة مرور قاعدة البيانات مطلوبة لفتح الدردشة.</string>
<string name="mtr_error_no_down_migration">إصدار قاعدة البيانات أحدث من التطبيق، ولكن لا يوجد ترحيل لأسفل ل%s</string>
<string name="share_text_database_id">معرّف قاعدة البيانات: %d</string>
@@ -371,13 +370,13 @@
<string name="full_deletion">حذف للجميع</string>
<string name="custom_time_unit_days">أيام</string>
<string name="delete_address">حذف العنوان</string>
<string name="database_passphrase_will_be_updated">سيتم تحديث عبارة مرور تشفير قاعدة البيانات.</string>
<string name="database_passphrase_will_be_updated">سيتم تحديث عبارة مرور تعمية قاعدة البيانات.</string>
<string name="delete_archive">حذف الأرشيف</string>
<string name="delete_link_question">حذف الرابط؟</string>
<string name="database_downgrade">الرجوع إلى إصدار سابق من قاعدة البيانات</string>
<string name="set_password_to_export_desc">يتم تشفير قاعدة البيانات باستخدام عبارة مرور عشوائية. يرجى تغييره قبل التصدير.</string>
<string name="set_password_to_export_desc">قاعدة البيانات مُعمّاة باستخدام عبارة مرور عشوائية. يُرجى تغييره قبل التصدير.</string>
<string name="ttl_day">%d يوم</string>
<string name="database_will_be_encrypted">سيتم تشفير قاعدة البيانات.</string>
<string name="database_will_be_encrypted">سيتم تعمية قاعدة البيانات.</string>
<string name="delete_contact_menu_action">حذف</string>
<string name="delete_files_and_media_question">حذف الملفات والوسائط؟</string>
<string name="button_delete_contact">حذف جهة الاتصال</string>
@@ -397,7 +396,7 @@
<string name="decentralized">لامركزي</string>
<string name="database_passphrase">عبارة مرور قاعدة البيانات</string>
<string name="current_passphrase">عبارة المرور الحالية…</string>
<string name="database_encryption_will_be_updated">سيتم تحديث عبارة مرور تشفير قاعدة البيانات وتخزينها في Keystore.</string>
<string name="database_encryption_will_be_updated">سيتم تحديث عبارة مرور تعمية قاعدة البيانات وتخزينها في Keystore.</string>
<string name="info_row_database_id">معرّف قاعدة البيانات</string>
<string name="info_row_deleted_at">حُذِفت في</string>
<string name="ttl_d">%d يوم</string>
@@ -553,7 +552,7 @@
\n2. فشل فك تشفير الرسالة، لأنك أو جهة اتصالك استخدمت نسخة احتياطية قديمة من قاعدة البيانات.
\n3. اُخترق الاتصال.</string>
<string name="v5_1_japanese_portuguese_interface">واجهة أستخدام يابانية وبرتغالية</string>
<string name="alert_text_fragment_encryption_out_of_sync_old_database">يمكن أن يحدث ذلك عندما تستخدم أنت أو اتصالك النسخة الاحتياطية القديمة لقاعدة البيانات.</string>
<string name="alert_text_fragment_encryption_out_of_sync_old_database">يمكن أن يحدث ذلك عندما تستخدم أنت أو اتصالك النُسخة الاحتياطية القديمة لقاعدة البيانات.</string>
<string name="group_preview_join_as">انضمام ك%s</string>
<string name="invalid_QR_code">رمز QR غير صالح</string>
<string name="v4_5_italian_interface">الواجهة الإيطالية</string>
@@ -616,7 +615,7 @@
<string name="integrity_msg_duplicate">كرر الرسالة</string>
<string name="share_text_disappears_at">يختفي في: %s</string>
<string name="disappearing_prohibited_in_this_chat">الرسائل المختفية ممنوعة في هذه الدردشة.</string>
<string name="status_e2e_encrypted">مشفر بين الطريفين</string>
<string name="status_e2e_encrypted">مُعمّى بين الطريفين</string>
<string name="icon_descr_edited">حُرر</string>
<string name="downgrade_and_open_chat">الرجوع إلى إصدار سابق وفتح الدردشة</string>
<string name="direct_messages">رسائل مباشرة</string>
@@ -626,7 +625,7 @@
<string name="settings_section_title_device">الجهاز</string>
<string name="ttl_week">%d أسبوع</string>
<string name="display_name_cannot_contain_whitespace">لا يمكن أن يحتوي اسم العرض على مسافة فارغة.</string>
<string name="encrypted_video_call">مكالمة فيديو مشفرة بين الطريفين</string>
<string name="encrypted_video_call">مكالمة فيديو مُعمّاة بين الطريفين</string>
<string name="direct_messages_are_prohibited_in_chat">الرسائل المباشرة بين الأعضاء ممنوعة في هذه المجموعة.</string>
<string name="ttl_hour">%d ساعة</string>
<string name="ttl_h">%d ساعة</string>
@@ -651,7 +650,7 @@
<string name="dont_enable_receipts">لا تُفعل</string>
<string name="la_minutes">%d دقائق</string>
<string name="la_seconds">%d ثواني</string>
<string name="encrypted_audio_call">مكالمة صوتية مشفرة بين الطريفين</string>
<string name="encrypted_audio_call">مكالمة صوتية مُعمّاة بين الطريفين</string>
<string name="ttl_sec">%d ثانية</string>
<string name="icon_descr_server_status_disconnected">قُطع الاتصال</string>
<string name="disappearing_message">رسالة تختفي</string>
@@ -695,7 +694,7 @@
<string name="v5_2_favourites_filter">البحث عن الدردشات بشكل أسرع</string>
<string name="enable_receipts_all">تفعيل</string>
<string name="v5_2_disappear_one_message_descr">حتى عندما يتم تعطيله في المحادثة.</string>
<string name="v5_2_fix_encryption_descr">إصلاح التشفير بعد استعادة النسخ الاحتياطية.</string>
<string name="v5_2_fix_encryption_descr">إصلاح التعمية بعد استعادة النُسخ الاحتياطية.</string>
<string name="v5_2_disappear_one_message">اجعل رسالة واحدة تختفي</string>
<string name="error_enabling_delivery_receipts">خطأ في تفعيل إيصالات التسليم!</string>
<string name="error_saving_smp_servers">خطأ في حفظ خوادم SMP</string>
@@ -749,7 +748,7 @@
<string name="v4_5_message_draft">مسودة الرسالة</string>
<string name="v4_5_multiple_chat_profiles">ملفات تعريف دردشة متعددة</string>
<string name="settings_notification_preview_title">معاينة الإشعار</string>
<string name="status_no_e2e_encryption">لا يوجد تشفير بين الطريفين</string>
<string name="status_no_e2e_encryption">لا يوجد تعمية بين الطريفين</string>
<string name="chat_preferences_no">لا</string>
<string name="notification_preview_new_message">رسالة جديدة</string>
<string name="images_limit_desc">يمكن إرسال 10 صور فقط في نفس الوقت</string>
@@ -830,7 +829,7 @@
<string name="call_connection_peer_to_peer">ندّ لِندّ</string>
<string name="people_can_connect_only_via_links_you_share">يمكن للناس التواصل معك فقط عبر الرابط الذي تقوم بمشاركته</string>
<string name="icon_descr_call_pending_sent">مكالمة في الانتظار</string>
<string name="only_client_devices_store_contacts_groups_e2e_encrypted_messages"><![CDATA[تقوم أجهزة العميل فقط بتخزين ملفات تعريف المستخدمين وجهات الاتصال والمجموعات والرسائل المرسلة باستخدام <b>تشفير ثنائي الطبقات من بين الطريفين</b>.]]></string>
<string name="only_client_devices_store_contacts_groups_e2e_encrypted_messages"><![CDATA[تقوم أجهزة العميل فقط بتخزين ملفات تعريف المستخدمين وجهات الاتصال والمجموعات والرسائل المُرسلة باستخدام <b>تعمية ثنائية الطبقات من بين الطريفين</b>.]]></string>
<string name="reset_color">إعادة تعيين الألوان</string>
<string name="save_verb">حفظ</string>
<string name="smp_servers_preset_address">عنوان الخادم المحدد مسبقًا</string>
@@ -933,7 +932,7 @@
<string name="simplex_service_notification_text">يتم استلام الرسائل…</string>
<string name="observer_cant_send_message_desc">يرجى الاتصال بمسؤول المجموعة.</string>
<string name="sync_connection_force_confirm">أعد التفاوض</string>
<string name="sync_connection_force_question">إعادة تفاوض التشفير</string>
<string name="sync_connection_force_question">إعادة تفاوض التعمية</string>
<string name="revoke_file__action">سحب وصول الملف</string>
<string name="revoke_file__title">سحب وصول الملف؟</string>
<string name="toast_permission_denied">رٌفض الإذن!</string>
@@ -948,7 +947,7 @@
<string name="save_and_notify_contact">حفظ وإشعار جهة الاتصال</string>
<string name="settings_restart_app">إعادة التشغيل</string>
<string name="share_text_received_at">استلمت في: %s</string>
<string name="renegotiate_encryption">إعادة تفاوض التشفير</string>
<string name="renegotiate_encryption">إعادة تفاوض التعمية</string>
<string name="sender_at_ts">%s في %s</string>
<string name="save_group_profile">حفظ ملف المجموعة</string>
<string name="color_secondary">ثانوي</string>
@@ -1091,7 +1090,7 @@
<string name="language_system">النظام</string>
<string name="theme">السمة</string>
<string name="to_start_a_new_chat_help_header">لبدء محادثة جديدة</string>
<string name="to_verify_compare">للتحقق من التشفير بين الطريفين مع جهة اتصالك، قارن (أو امسح) الرمز الموجود على أجهزتك.</string>
<string name="to_verify_compare">للتحقق من التعمية بين الطريفين مع جهة اتصالك، قارن (أو امسح) الرمز الموجود على أجهزتك.</string>
<string name="group_is_decentralized">لامركزية بالكامل – مرئية للأعضاء فقط.</string>
<string name="theme_system">النظام</string>
<string name="error_smp_test_failed_at_step">فشل الاختبار في الخطوة %s.</string>
@@ -1127,7 +1126,6 @@
<string name="database_initialization_error_desc">قاعدة البيانات لا تعمل بشكل صحيح. انقر لمعرفة المزيد</string>
<string name="theme_colors_section_title">ألوان السمة</string>
<string name="tap_to_activate_profile">انقر لتنشيط الملف الشخصي.</string>
<string name="should_be_at_least_one_profile">يجب أن يكون هناك ملف تعريف مستخدم واحد على الأقل.</string>
<string name="v4_5_transport_isolation">عزل النقل</string>
<string name="this_string_is_not_a_connection_link">هذه السلسلة ليست رابط اتصال!</string>
<string name="receipts_section_description">هذه الإعدادات لملف التعريف الحالي الخاص بك</string>
@@ -1138,9 +1136,8 @@
<string name="whats_new_thanks_to_users_contribute_weblate">بفضل المستخدمين - المساهمة عبر Weblate!</string>
<string name="database_backup_can_be_restored">لم تكتمل محاولة تغيير عبارة مرور قاعدة البيانات.</string>
<string name="enter_passphrase_notification_desc">لتلقي الإشعارات، يرجى إدخال عبارة مرور قاعدة البيانات</string>
<string name="should_be_at_least_one_visible_profile">يجب أن يكون هناك ملف تعريف مستخدم مرئي واحد على الأقل.</string>
<string name="la_lock_mode_system">مصادقة النظام</string>
<string name="sync_connection_force_desc">يعمل التشفير واتفاقية التشفير الجديدة غير مطلوبة. قد ينتج عن ذلك أخطاء في الاتصال!</string>
<string name="sync_connection_force_desc">يعمل التعمية واتفاقية التعمية الجديدة غير مطلوبة. قد ينتج عن ذلك أخطاء في الاتصال!</string>
<string name="image_decoding_exception_desc">لا يمكن فك ترميز الصورة. من فضلك، جرب صورة مختلفة أو تواصل مع المطورين.</string>
<string name="moderate_message_will_be_deleted_warning">سيتم حذف الرسالة لجميع الأعضاء.</string>
<string name="images_limit_title">الصور كثيرة!</string>
@@ -1223,7 +1220,7 @@
<string name="v4_3_irreversible_message_deletion_desc">يمكن أن تسمح جهات اتصالك بحذف الرسائل بالكامل.</string>
<string name="unknown_message_format">تنسيق رسالة غير معروف</string>
<string name="description_via_one_time_link">عبر رابط لمرة واحدة</string>
<string name="video_call_no_encryption">مكالمة الفيديو ليست مشفرة بين الطريفين</string>
<string name="video_call_no_encryption">مكالمة الفيديو ليست مُعمّاة بين الطريفين</string>
<string name="snd_conn_event_switch_queue_phase_completed">غيّرتَ العنوان</string>
<string name="you_will_be_connected_when_your_contacts_device_is_online">سوف تكون متصلاً عندما يكون جهاز جهة الاتصال الخاصة بك متصلاً بالإنترنت، يرجى الانتظار أو التحقق لاحقًا!</string>
<string name="snd_group_event_user_left">غادرت</string>
@@ -1233,7 +1230,7 @@
<string name="you_can_share_this_address_with_your_contacts">يمكنك مشاركة هذا العنوان مع جهات اتصالك للسماح لهم بالاتصال بـ%s.</string>
<string name="snd_group_event_member_deleted">أُزيلت %1$s</string>
<string name="update_database">تحديث</string>
<string name="database_is_not_encrypted">قاعدة بيانات الدردشة الخاصة بك غير مشفرة - قم بتعيين عبارة المرور لحمايتها.</string>
<string name="database_is_not_encrypted">قاعدة بيانات الدردشة الخاصة بك غير مُعمّاة - عيّن عبارة مرور لحمايتها.</string>
<string name="wrong_passphrase">عبارة مرور قاعدة بيانات خاطئة</string>
<string name="group_main_profile_sent">سيتم إرسال ملف تعريف الدردشة الخاص بك إلى أعضاء المجموعة</string>
<string name="personal_welcome">مرحبًا! %1$s</string>
@@ -1367,10 +1364,10 @@
<string name="privacy_show_last_messages">إظهار الرسائل الأخيرة</string>
<string name="rcv_group_event_n_members_connected">%s، %s و %d أعضاء آخرين متصلون</string>
<string name="rcv_group_event_3_members_connected">%s، %s و %s متصل</string>
<string name="database_will_be_encrypted_and_passphrase_stored_in_settings">سيتم تشفير قاعدة البيانات وتخزين عبارة المرور في الإعدادات.</string>
<string name="database_will_be_encrypted_and_passphrase_stored_in_settings">سيتم تعمية قاعدة البيانات وتخزين عبارة المرور في الإعدادات.</string>
<string name="you_can_change_it_later">يُخزين عبارة المرور العشوائية في الإعدادات كنص عادي.
\nيمكنك تغييره لاحقا.</string>
<string name="database_encryption_will_be_updated_in_settings">سيتم تحديث عبارة مرور تشفير قاعدة البيانات وتخزينها في الإعدادات.</string>
<string name="database_encryption_will_be_updated_in_settings">سيتم تحديث عبارة مرور تعمية قاعدة البيانات وتخزينها في الإعدادات.</string>
<string name="remove_passphrase_from_settings">هل تريد إزالة عبارة المرور من الإعدادات؟</string>
<string name="use_random_passphrase">استخدم عبارة مرور عشوائية</string>
<string name="save_passphrase_in_settings">حفظ عبارة المرور في الإعدادات</string>
@@ -1380,11 +1377,11 @@
<string name="passphrase_will_be_saved_in_settings">سيتم تخزين عبارة المرور في الإعدادات كنص عادي بعد تغييرها أو إعادة تشغيل التطبيق.</string>
<string name="settings_is_storing_in_clear_text">يُخزين عبارة المرور في الإعدادات كنص عادي.</string>
<string name="socks_proxy_setting_limitations"><![CDATA[<b>يُرجى الملاحظة</b>: يتم توصيل مرحلات الرسائل والملفات عبر وكيل SOCKS. تستخدم المكالمات وإرسال معاينات الارتباط الاتصال المباشر.]]></string>
<string name="encrypt_local_files">تشفير الملفات المحلية</string>
<string name="v5_3_encrypt_local_files">تشفير الملفات والوسائط المخزنة</string>
<string name="encrypt_local_files">عَمِّ الملفات المحلية</string>
<string name="v5_3_encrypt_local_files">عَمِّ الملفات والوسائط المخزنة</string>
<string name="v5_3_new_desktop_app">تطبيق سطح المكتب الجديد!</string>
<string name="v5_3_new_interface_languages">6 لغات واجهة جديدة</string>
<string name="v5_3_encrypt_local_files_descr">يقوم التطبيق بتشفير الملفات المحلية الجديدة (باستثناء مقاطع الفيديو).</string>
<string name="v5_3_encrypt_local_files_descr">يُعمِّي الملفات المحلية الجديدة (باستثناء مقاطع الفيديو).</string>
<string name="v5_3_discover_join_groups">اكتشاف والانضمام إلى المجموعات</string>
<string name="v5_3_new_interface_languages_descr">العربية والبلغارية والفنلندية والعبرية والتايلاندية والأوكرانية - شكرًا للمستخدمين و Weblate.</string>
<string name="v5_3_new_desktop_app_descr">إنشاء ملف تعريف جديد في تطبيق سطح المكتب. 💻</string>
@@ -1442,7 +1439,7 @@
<string name="desktop_app_version_is_incompatible">إصدار تطبيق سطح المكتب %s غير متوافق مع هذا التطبيق.</string>
<string name="expand_verb">توسيع</string>
<string name="connect_plan_repeat_connection_request">هل تريد تكرار طلب الاتصال؟</string>
<string name="encryption_renegotiation_error">خطأ في إعادة التفاوض بشأن التشفير</string>
<string name="encryption_renegotiation_error">خطأ في إعادة التفاوض بشأن التعمية</string>
<string name="connect_plan_you_are_already_connecting_to_vName"><![CDATA[أنت متصل بالفعل بـ <b>%1$s</b>.]]></string>
<string name="error_alert_title">خطأ</string>
<string name="connect_plan_you_are_already_joining_the_group_via_this_link">لقد انضممت بالفعل إلى المجموعة عبر هذا الرابط.</string>
@@ -1479,7 +1476,7 @@
<string name="connect_plan_this_is_your_own_simplex_address">هذا هو عنوان SimpleX الخاص بك!</string>
<string name="loading_remote_file_title">جارِ تحميل الملف</string>
<string name="found_desktop">وجدت سطح المكتب</string>
<string name="alert_text_encryption_renegotiation_failed">فشلت إعادة التفاوض على التشفير.</string>
<string name="alert_text_encryption_renegotiation_failed">فشلت إعادة التفاوض على التعمية.</string>
<string name="not_compatible">غير متوافق!</string>
<string name="link_a_mobile">ربط الجوّال</string>
<string name="remove_member_button">إزالة العضو</string>
@@ -1567,4 +1564,57 @@
\n
\nيوصى بإعادة تشغيل التطبيق.</string>
<string name="restart_chat_button">أعد تشغيل الدردشة</string>
<string name="remote_host_error_inactive"><![CDATA[الجوال <b>%s</b> غير نشط]]></string>
<string name="show_slow_api_calls">أظهر مكالمات API البطيئة</string>
<string name="group_member_status_unknown_short">غير معروف</string>
<string name="profile_update_event_updated_profile">حدّثت الملف الشخصي</string>
<string name="remote_host_error_missing"><![CDATA[الجوال <b>%s</b> مفقود]]></string>
<string name="remote_host_error_bad_version"><![CDATA[الجوال <b>%s</b> لديه إصدار غير مدعوم. يُرجى التأكد من استخدام نفس الإصدار على كلا الجهازين]]></string>
<string name="remote_host_error_bad_state"><![CDATA[الاتصال بالجوال <b>%s</b> في حالة سيئة]]></string>
<string name="failed_to_create_user_invalid_title">اسم العرض غير صالح!</string>
<string name="failed_to_create_user_invalid_desc">اسم العرض هذا غير صالح. الرجاء اختيار اسم آخر.</string>
<string name="remote_host_was_disconnected_title">توقف الاتصال</string>
<string name="remote_ctrl_was_disconnected_title">توقف الاتصال</string>
<string name="remote_host_disconnected_from"><![CDATA[قُطع الاتصال بالجوال <b>%s</b> بسبب: %s]]></string>
<string name="remote_ctrl_disconnected_with_reason">قُطع الاتصال بسبب: %s</string>
<string name="remote_host_error_disconnected"><![CDATA[قُطع اتصال الجوال <b>%s</b>]]></string>
<string name="remote_host_error_timeout"><![CDATA[انتهت المهلة أثناء الاتصال بالجوال <b>%s</b>]]></string>
<string name="remote_ctrl_error_inactive">سطح المكتب غير نشط</string>
<string name="remote_host_error_busy"><![CDATA[الجوال <b>%s</b> مشغول]]></string>
<string name="remote_ctrl_error_timeout">انتهت المهلة أثناء الاتصال بسطح المكتب</string>
<string name="remote_ctrl_error_disconnected">قُطع اتصال سطح المكتب</string>
<string name="remote_ctrl_error_bad_state">الاتصال بسطح المكتب في حالة سيئة</string>
<string name="remote_ctrl_error_bad_invitation">يحتوي سطح المكتب على رمز دعوة خاطئ</string>
<string name="remote_ctrl_error_busy">سطح المكتب مشغول</string>
<string name="remote_ctrl_error_bad_version">يحتوي سطح المكتب على إصدار غير مدعوم. يُرجى التأكد من استخدام نفس الإصدار على كلا الجهازين</string>
<string name="past_member_vName">العضو السابق %1$s</string>
<string name="possible_deadlock_title">مأزق</string>
<string name="possible_deadlock_desc">يستغرق تنفيذ التعليمات البرمجية وقتًا طويلاً جدًا: %1$d ثانية. من المحتمل أن التطبيق مجمّد: %2$s</string>
<string name="possible_slow_function_title">وظيفة بطيئة</string>
<string name="developer_options_section">خيارات المطور</string>
<string name="profile_update_event_member_name_changed">تغيّر العضو %1$s إلى %2$s</string>
<string name="profile_update_event_removed_address">أزلت عنوان الاتصال</string>
<string name="profile_update_event_removed_picture">أزلت الصورة الشخصية</string>
<string name="profile_update_event_set_new_address">عيّن عنوان جهة اتصال جديد</string>
<string name="profile_update_event_set_new_picture">عيّن صورة شخصية جديدة</string>
<string name="group_member_status_unknown">حالة غير معروفة</string>
<string name="profile_update_event_contact_name_changed">تغيّر جهة الاتصال %1$s إلى %2$s</string>
<string name="possible_slow_function_desc">يستغرق تنفيذ الوظيفة وقتًا طويلاً جدًا: %1$d ثانية: %2$s</string>
<string name="v5_5_private_notes">ملاحظات خاصة</string>
<string name="v5_5_join_group_conversation">انضم إلى المحادثات الجماعية</string>
<string name="v5_5_simpler_connect_ui_descr">يقبل شريط البحث روابط الدعوة.</string>
<string name="v5_5_message_delivery">تحسّن تسليم الرسائل</string>
<string name="v5_5_message_delivery_descr">مع انخفاض استخدام البطارية.</string>
<string name="clear_note_folder_warning">سيتم حذف كافة الرسائل - لا يمكن التراجع عن هذا!</string>
<string name="info_row_created_at">أُنشئ في</string>
<string name="v5_5_new_interface_languages">واجهة المستخدم المجرية والتركية</string>
<string name="v5_5_simpler_connect_ui">الصق الرابط للاتصال!</string>
<string name="v5_5_join_group_conversation_descr">التاريخ الحديث وبوت الدليل المحسن.</string>
<string name="v5_5_private_notes_descr">مع الملفات والوسائط المُعمّاة.</string>
<string name="error_creating_message">حدث خطأ أثناء إنشاء الرسالة</string>
<string name="error_deleting_note_folder">حدث خطأ أثناء حذف الملاحظات الخاصة</string>
<string name="note_folder_local_display_name">ملاحظات خاصة</string>
<string name="clear_note_folder_question">مسح الملاحظات الخاصة؟</string>
<string name="share_text_created_at">أُنشئ في: %s</string>
<string name="saved_message_title">رسالة محفوظة</string>
</resources>
@@ -35,7 +35,9 @@
<string name="moderated_item_description">moderated by %s</string>
<string name="moderated_items_description">%1$d messages moderated by %2$s</string>
<string name="blocked_item_description">blocked</string>
<string name="blocked_by_admin_item_description">blocked by admin</string>
<string name="blocked_items_description">%d messages blocked</string>
<string name="blocked_by_admin_items_description">%d messages blocked by admin</string>
<string name="sending_files_not_yet_supported">sending files is not supported yet</string>
<string name="receiving_files_not_yet_supported">receiving files is not supported yet</string>
<string name="sender_you_pronoun">you</string>
@@ -51,6 +53,9 @@
<string name="decryption_error">Decryption error</string>
<string name="encryption_renegotiation_error">Encryption re-negotiation error</string>
<!-- NoteFolder - ChatModel.kt -->
<string name="note_folder_local_display_name">Private notes</string>
<!-- PendingContactConnection - ChatModel.kt -->
<string name="connection_local_display_name">connection %1$d</string>
<string name="display_name_connection_established">connection established</string>
@@ -99,6 +104,7 @@
<string name="connection_error">Connection error</string>
<string name="network_error_desc">Please check your network connection with %1$s and try again.</string>
<string name="error_sending_message">Error sending message</string>
<string name="error_creating_message">Error creating message</string>
<string name="error_loading_details">Error loading details</string>
<string name="error_adding_members">Error adding member(s)</string>
<string name="error_joining_group">Error joining group</string>
@@ -116,6 +122,7 @@
<string name="sender_may_have_deleted_the_connection_request">Sender may have deleted the connection request.</string>
<string name="error_deleting_contact">Error deleting contact</string>
<string name="error_deleting_group">Error deleting group</string>
<string name="error_deleting_note_folder">Error deleting private notes</string>
<string name="error_deleting_contact_request">Error deleting contact request</string>
<string name="error_deleting_pending_contact_connection">Error deleting pending contact connection</string>
<string name="error_changing_address">Error changing address</string>
@@ -471,7 +478,9 @@
<!-- Clear Chat - ChatListNavLinkView.kt -->
<string name="clear_chat_question">Clear chat?</string>
<string name="clear_note_folder_question">Clear private notes?</string>
<string name="clear_chat_warning">All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</string>
<string name="clear_note_folder_warning">All messages will be deleted - this cannot be undone!</string>
<string name="clear_verb">Clear</string>
<string name="clear_chat_button">Clear chat</string>
<string name="clear_chat_menu_action">Clear</string>
@@ -1169,6 +1178,8 @@
<string name="rcv_group_event_member_connected">connected</string>
<string name="rcv_group_event_member_left">left</string>
<string name="rcv_group_event_changed_member_role">changed role of %s to %s</string>
<string name="rcv_group_event_member_blocked">blocked %s</string>
<string name="rcv_group_event_member_unblocked">unblocked %s</string>
<string name="rcv_group_event_changed_your_role">changed your role to %s</string>
<string name="rcv_group_event_member_deleted">removed %1$s</string>
<string name="rcv_group_event_user_deleted">removed you</string>
@@ -1178,6 +1189,8 @@
<string name="rcv_group_event_member_created_contact">connected directly</string>
<string name="snd_group_event_changed_member_role">you changed role of %s to %s</string>
<string name="snd_group_event_changed_role_for_yourself">you changed role for yourself to %s</string>
<string name="snd_group_event_member_blocked">you blocked %s</string>
<string name="snd_group_event_member_unblocked">you unblocked %s</string>
<string name="snd_group_event_member_deleted">you removed %1$s</string>
<string name="snd_group_event_user_left">you left</string>
<string name="snd_group_event_group_profile_updated">group profile updated</string>
@@ -1193,6 +1206,15 @@
<string name="rcv_group_event_open_chat">Open</string>
<!-- Profile update event chat items -->
<string name="profile_update_event_contact_name_changed">contact %1$s changed to %2$s</string>
<string name="profile_update_event_removed_picture">removed profile picture</string>
<string name="profile_update_event_set_new_picture">set new profile picture</string>
<string name="profile_update_event_removed_address">removed contact address</string>
<string name="profile_update_event_set_new_address">set new contact address</string>
<string name="profile_update_event_updated_profile">updated profile</string>
<string name="profile_update_event_member_name_changed">member %1$s changed to %2$s</string>
<!-- Conn event chat items -->
<string name="rcv_conn_event_switch_queue_phase_completed">changed address for you</string>
<string name="rcv_conn_event_switch_queue_phase_changing">changing address…</string>
@@ -1292,6 +1314,7 @@
<string name="info_row_database_id">Database ID</string>
<string name="info_row_updated_at">Record updated at</string>
<string name="info_row_sent_at">Sent at</string>
<string name="info_row_created_at">Created at</string>
<string name="info_row_received_at">Received at</string>
<string name="info_row_deleted_at">Deleted at</string>
<string name="info_row_moderated_at">Moderated at</string>
@@ -1299,6 +1322,7 @@
<string name="share_text_database_id">Database ID: %d</string>
<string name="share_text_updated_at">Record updated at: %s</string>
<string name="share_text_sent_at">Sent at: %s</string>
<string name="share_text_created_at">Created at: %s</string>
<string name="share_text_received_at">Received at: %s</string>
<string name="share_text_deleted_at">Deleted at: %s</string>
<string name="share_text_moderated_at">Moderated at: %s</string>
@@ -1308,6 +1332,7 @@
<string name="current_version_timestamp">%s (current)</string>
<string name="item_info_no_text">no text</string>
<string name="recipient_colon_delivery_status">%s: %s</string>
<string name="saved_message_title">Saved message</string>
<!-- GroupMemberInfoView.kt -->
<string name="button_remove_member_question">Remove member?</string>
@@ -1320,11 +1345,17 @@
<string name="block_member_question">Block member?</string>
<string name="block_member_button">Block member</string>
<string name="block_member_confirmation">Block</string>
<string name="block_for_all_question">Block member for all?</string>
<string name="block_for_all">Block for all</string>
<string name="block_member_desc">All new messages from %s will be hidden!</string>
<string name="unblock_member_question">Unblock member?</string>
<string name="unblock_member_button">Unblock member</string>
<string name="unblock_member_confirmation">Unblock</string>
<string name="unblock_for_all_question">Unblock member for all?</string>
<string name="unblock_for_all">Unblock for all</string>
<string name="unblock_member_desc">Messages from %s will be shown!</string>
<string name="member_blocked_by_admin">Blocked by admin</string>
<string name="member_info_member_blocked">blocked</string>
<string name="member_info_section_title_member">MEMBER</string>
<string name="role_in_group">Role</string>
<string name="change_role">Change role</string>
@@ -1337,6 +1368,7 @@
<string name="connect_via_member_address_alert_desc">Сonnection request will be sent to this group member.</string>
<string name="error_removing_member">Error removing member</string>
<string name="error_changing_role">Error changing role</string>
<string name="error_blocking_member_for_all">Error blocking member for all</string>
<string name="info_row_group">Group</string>
<string name="info_row_connection">Connection</string>
<string name="conn_level_desc_direct">direct</string>
@@ -1404,9 +1436,6 @@
<string name="user_unmute">Unmute</string>
<string name="enter_password_to_show">Enter password in search</string>
<string name="tap_to_activate_profile">Tap to activate profile.</string>
<string name="cant_delete_user_profile">Can\'t delete user profile!</string>
<string name="should_be_at_least_one_visible_profile">There should be at least one visible user profile.</string>
<string name="should_be_at_least_one_profile">There should be at least one user profile.</string>
<string name="make_profile_private">Make profile private!</string>
<string name="you_can_hide_or_mute_user_profile">You can hide or mute a user profile - hold it for the menu.</string>
<string name="dont_show_again">Don\'t show again</string>
@@ -1663,6 +1692,15 @@
<string name="v5_4_block_group_members">Block group members</string>
<string name="v5_4_block_group_members_descr">To hide unwanted messages.</string>
<string name="v5_4_more_things_descr">- optionally notify deleted contacts.\n- profile names with spaces.\n- and more!</string>
<string name="v5_5_private_notes">Private notes</string>
<string name="v5_5_private_notes_descr">With encrypted files and media.</string>
<string name="v5_5_simpler_connect_ui">Paste link to connect!</string>
<string name="v5_5_simpler_connect_ui_descr">Search bar accepts invitation links.</string>
<string name="v5_5_join_group_conversation">Join group conversations</string>
<string name="v5_5_join_group_conversation_descr">Recent history and improved directory bot.</string>
<string name="v5_5_message_delivery">Improved message delivery</string>
<string name="v5_5_message_delivery_descr">With reduced battery usage.</string>
<string name="v5_5_new_interface_languages">Hungarian and Turkish UI</string>
<!-- CustomTimePicker -->
<string name="custom_time_unit_seconds">seconds</string>
@@ -185,7 +185,6 @@
<string name="change_verb">Промени</string>
<string name="change_member_role_question">Промяна на груповата роля\?</string>
<string name="you_will_still_receive_calls_and_ntfs">Все още ще получавате обаждания и известия от заглушени профили, когато са активни.</string>
<string name="cant_delete_user_profile">Потребителският профил не може да се изтрие!</string>
<string name="allow_disappearing_messages_only_if">Позволи изчезващи съобщения само ако вашият контакт ги разрешава.</string>
<string name="allow_your_contacts_irreversibly_delete">Позволи на вашите контакти да изтриват необратимо изпратените съобщения. (24 часа)</string>
<string name="allow_your_contacts_to_send_disappearing_messages">Позволи на вашите контакти да изпращат изчезващи съобщения.</string>
@@ -476,7 +475,7 @@
<string name="scan_qr_to_connect_to_contact">За да се свърже, вашият контакт може да сканира QR код или да използва линка в приложението.</string>
<string name="direct_messages">Лични съобщения</string>
<string name="display_name">Въведи своето име:</string>
<string name="display_name_cannot_contain_whitespace">Показваното име не може да съдържа интервал.</string>
<string name="display_name_cannot_contain_whitespace">Името не може да съдържа интервал.</string>
<string name="sending_delivery_receipts_will_be_enabled">Изпращането на потвърждениe за доставка ще бъде активирано за всички контакти.</string>
<string name="receipts_contacts_enable_for_all">Активиране за всички</string>
<string name="error_enabling_delivery_receipts">Грешка при активирането на потвърждениeто за доставка!</string>
@@ -547,8 +546,8 @@
<string name="smp_server_test_delete_queue">Изтрий опашка</string>
<string name="smp_server_test_disconnect">Прекъсни връзката</string>
<string name="smp_server_test_download_file">Свали файл</string>
<string name="failed_to_create_user_duplicate_title">Дублирано показвано име!</string>
<string name="failed_to_create_user_duplicate_desc">Вече имате чат профил със същото показвано име. Моля, изберете друго име.</string>
<string name="failed_to_create_user_duplicate_title">Дублирано име!</string>
<string name="failed_to_create_user_duplicate_desc">Вече имате чат профил със същото име. Моля, изберете друго име.</string>
<string name="la_minutes">%d минути</string>
<string name="la_seconds">%d секунди</string>
<string name="edit_verb">Редактирай</string>
@@ -567,7 +566,7 @@
<string name="integrity_msg_duplicate">дублирано съобщение</string>
<string name="privacy_and_security">Поверителност и сигурност</string>
<string name="alert_text_fragment_encryption_out_of_sync_old_database">Това може да се случи, когато вие или вашата връзка използвате старо резервно копие на базата данни.</string>
<string name="self_destruct_new_display_name">Ново показвано име:</string>
<string name="self_destruct_new_display_name">Ново име:</string>
<string name="enable_lock">Активирай заключване</string>
<string name="enable_self_destruct">Активирай самоунищожение</string>
<string name="chat_item_ttl_none">никога</string>
@@ -1165,8 +1164,6 @@
<string name="profile_is_only_shared_with_your_contacts">Профилът се споделя само с вашите контакти.</string>
<string name="delete_files_and_media_desc">Това действие не може да бъде отменено - всички получени и изпратени файлове и медия ще бъдат изтрити. Снимките с ниска разделителна способност ще бъдат запазени.</string>
<string name="tap_to_activate_profile">Докосни за активиране на профил.</string>
<string name="should_be_at_least_one_profile">Трябва да има поне един потребителски профил.</string>
<string name="should_be_at_least_one_visible_profile">Трябва да има поне един видим потребителски профил.</string>
<string name="language_system">Системен</string>
<string name="color_title">Заглавие</string>
<string name="to_share_with_your_contact">(за споделяне с вашия контакт)</string>
@@ -1556,4 +1553,43 @@
<string name="search_or_paste_simplex_link">Търсене или поставяне на SimpleX линк</string>
<string name="start_chat_question">Стартирай чата?</string>
<string name="chat_is_stopped_you_should_transfer_database">Чатът е спрян. Ако вече сте използвали тази база данни на друго устройство, трябва да я прехвърлите обратно, преди да стартирате чата отново.</string>
<string name="remote_ctrl_error_bad_invitation">Настолното устройство има грешен код за връзка</string>
<string name="remote_ctrl_error_bad_version">Настолното устройство е с неподдържана версия. Моля, уверете се, че използвате една и съща версия и на двете устройства</string>
<string name="possible_deadlock_desc">Изпълнението на кода отнема твърде много време: %1$d секунди. Вероятно приложението е замразено: %2$s</string>
<string name="possible_slow_function_title">Бавна функция</string>
<string name="possible_slow_function_desc">Изпълнението на функцията отнема твърде много време: %1$d секунди: %2$s</string>
<string name="show_internal_errors">Покажи вътрешните грешки</string>
<string name="remote_host_disconnected_from"><![CDATA[Прекъсната е връзката с мобилното устройство <b>%s</b> с причина: %s]]></string>
<string name="remote_ctrl_was_disconnected_title">Връзката е прекъсната</string>
<string name="failed_to_create_user_invalid_title">Невалидно име!</string>
<string name="failed_to_create_user_invalid_desc">Това име е невалидно. Моля, изберете друго име.</string>
<string name="remote_host_was_disconnected_title">Връзката е прекъсната</string>
<string name="remote_ctrl_disconnected_with_reason">Прекъсната е връзката с причината: %s</string>
<string name="remote_host_error_missing"><![CDATA[Мобилното устройство <b>%s</b> липсва]]></string>
<string name="remote_host_error_inactive"><![CDATA[Мобилното устройство <b>%s</b> е неактивно]]></string>
<string name="remote_host_error_busy"><![CDATA[Мобилното устройство <b>%s</b> е заето]]></string>
<string name="remote_host_error_timeout"><![CDATA[Времето за изчакване е достигнато при свързване с мобилното устройство <b>%s</b>]]></string>
<string name="remote_host_error_bad_state"><![CDATA[Връзката с мобилното устройство <b>%s</b> е в лошо състояние]]></string>
<string name="remote_host_error_bad_version"><![CDATA[Мобилното устройство <b>%s</b> е с неподдържана версия. Моля, уверете се, че използвате една и съща версия и на двете устройства]]></string>
<string name="remote_host_error_disconnected"><![CDATA[Връзката с мобилното устройство <b>%s</b> бе прекъсната]]></string>
<string name="remote_ctrl_error_inactive">Настолното устройство е неактивно</string>
<string name="remote_ctrl_error_timeout">Времето за изчакване е достигнато при свързване с настолното устройство</string>
<string name="remote_ctrl_error_bad_state">Връзката с настолното устройство е в лошо състояние</string>
<string name="remote_ctrl_error_busy">Настолното устройство е заето</string>
<string name="remote_ctrl_error_disconnected">Връзката с настолното устройство бе прекъсната</string>
<string name="agent_critical_error_title">Критична грешка</string>
<string name="past_member_vName">Бивш член %1$s</string>
<string name="group_member_status_unknown">неизвестен статус</string>
<string name="group_member_status_unknown_short">неизвестен</string>
<string name="agent_internal_error_title">Вътрешна грешка</string>
<string name="agent_internal_error_desc">Моля, докладвайте го на разработчиците:
\n%s</string>
<string name="restart_chat_button">Рестартирай чата</string>
<string name="agent_critical_error_desc">Моля, докладвайте го на разработчиците:
\n%s
\n
\nПрепоръчително е да рестартирате приложението.</string>
<string name="developer_options_section">Опции за разработчици</string>
<string name="show_slow_api_calls">Показване на бавни API заявки</string>
<string name="possible_deadlock_title">Грешка в заключено положение</string>
</resources>
@@ -960,7 +960,6 @@
<string name="language_system">Systém</string>
<string name="smp_save_servers_question">Uložit servery\?</string>
<string name="dont_show_again">Znovu neukazuj</string>
<string name="cant_delete_user_profile">Nemohu smazat uživatelský profil!</string>
<string name="button_add_welcome_message">Přidat uvítací zprávu</string>
<string name="v4_6_chinese_spanish_interface">Čínské a Španělské rozhranní</string>
<string name="v4_6_audio_video_calls">Hlasové a video hovory</string>
@@ -991,12 +990,10 @@
<string name="v4_6_audio_video_calls_descr">Podpora bluetooth a další vylepšení.</string>
<string name="tap_to_activate_profile">Klepnutím aktivujete profil.</string>
<string name="v4_6_chinese_spanish_interface_descr">Díky uživatelům - překládejte prostřednictvím Weblate!</string>
<string name="should_be_at_least_one_profile">Měl by tam být alespoň jeden uživatelský profil.</string>
<string name="button_welcome_message">Uvítací zpráva</string>
<string name="group_welcome_title">Uvítací zpráva</string>
<string name="user_unmute">Zrušit ztlumení</string>
<string name="to_reveal_profile_enter_password">Chcete-li odhalit svůj skrytý profil, zadejte celé heslo do vyhledávacího pole na stránce Chat profily.</string>
<string name="should_be_at_least_one_visible_profile">Měl by tam být alespoň jeden viditelný uživatelský profil.</string>
<string name="you_will_still_receive_calls_and_ntfs">Stále budete přijímat volání a upozornění od umlčených profilů pokud budou aktivní.</string>
<string name="you_can_hide_or_mute_user_profile">Můžete skrýt nebo ztlumit uživatelský profil - Podržte pro menu.</string>
<string name="user_unhide">Odkrýt</string>
@@ -690,7 +690,7 @@
<string name="youve_accepted_group_invitation_connecting_to_inviting_group_member">Sie sind dieser Gruppe beigetreten. Sie werden mit dem einladenden Gruppenmitglied verbunden.</string>
<string name="leave_group_button">Verlassen</string>
<string name="leave_group_question">Die Gruppe verlassen?</string>
<string name="you_will_stop_receiving_messages_from_this_group_chat_history_will_be_preserved">Sie werden von dieser Gruppe keine Nachrichten mehr erhalten. Der Chatverlauf wird beibehalten.</string>
<string name="you_will_stop_receiving_messages_from_this_group_chat_history_will_be_preserved">Sie werden von dieser Gruppe keine Nachrichten mehr erhalten. Der Nachrichtenverlauf wird beibehalten.</string>
<string name="icon_descr_add_members">Mitglieder einladen</string>
<string name="icon_descr_group_inactive">Gruppe inaktiv</string>
<string name="alert_title_group_invitation_expired">Die Einladung ist abgelaufen!</string>
@@ -1041,7 +1041,6 @@
<string name="moderate_message_will_be_deleted_warning">Diese Nachricht wird für alle Gruppenmitglieder gelöscht.</string>
<string name="language_system">System</string>
<string name="confirm_password">Passwort bestätigen</string>
<string name="cant_delete_user_profile">Das Benutzerprofil kann nicht gelöscht werden!</string>
<string name="dont_show_again">Nicht nochmals anzeigen</string>
<string name="v4_6_chinese_spanish_interface">Chinesische und spanische Bedienoberfläche</string>
<string name="v4_6_audio_video_calls">Audio- und Videoanrufe</string>
@@ -1060,8 +1059,6 @@
<string name="make_profile_private">Privates Profil erzeugen!</string>
<string name="user_mute">Stummschalten</string>
<string name="tap_to_activate_profile">Zum Aktivieren des Profils tippen.</string>
<string name="should_be_at_least_one_profile">Es muss mindestens ein Benutzer-Profil vorhanden sein.</string>
<string name="should_be_at_least_one_visible_profile">Es muss mindestens ein sichtbares Benutzer-Profil vorhanden sein.</string>
<string name="user_unmute">Stummschaltung aufheben</string>
<string name="muted_when_inactive">Bei Inaktivität stummgeschaltet!</string>
<string name="v4_6_hidden_chat_profiles_descr">Schützen Sie Ihre Chat-Profile mit einem Passwort!</string>
@@ -1316,7 +1313,7 @@
<string name="custom_time_unit_hours">Stunden</string>
<string name="v5_1_better_messages_descr">- Bis zu 5 Minuten lange Sprachnachrichten
\n- Zeitdauer für verschwindende Nachrichten anpassen
\n- Nachrichten-Verlauf bearbeiten</string>
\n- Nachrichtenverlauf bearbeiten</string>
<string name="custom_time_picker_custom">benutzerdefiniert</string>
<string name="custom_time_unit_months">Monate</string>
<string name="custom_time_picker_select">Auswählen</string>
@@ -1327,7 +1324,7 @@
<string name="share_text_deleted_at">Gelöscht um: %s</string>
<string name="info_row_disappears_at">Verschwindet um</string>
<string name="share_text_disappears_at">Verschwindet um: %s</string>
<string name="edit_history">Verlauf bearbeiten</string>
<string name="edit_history">Nachrichtenverlauf bearbeiten</string>
<string name="message_reactions_prohibited_in_this_chat">In diesem Chat sind Reaktionen auf Nachrichten nicht erlaubt.</string>
<string name="item_info_no_text">Kein Text</string>
<string name="non_fatal_errors_occured_during_import">Während des Imports sind einige nicht schwerwiegende Fehler aufgetreten – weitere Details finden Sie in der Chat-Konsole.</string>
@@ -1359,7 +1356,7 @@
<string name="error_synchronizing_connection">Fehler beim Synchronisieren der Verbindung</string>
<string name="sync_connection_force_question">Verschlüsselung neu aushandeln\?</string>
<string name="fix_connection_question">Verbindung reparieren\?</string>
<string name="no_history">Kein Verlauf</string>
<string name="no_history">Kein Nachrichtenverlauf</string>
<string name="sync_connection_force_confirm">Neu aushandeln</string>
<string name="sync_connection_force_desc">Die Verschlüsselung funktioniert und ein neues Verschlüsselungsabkommen ist nicht erforderlich. Es kann zu Verbindungsfehlern kommen!</string>
<string name="renegotiate_encryption">Verschlüsselung neu aushandeln</string>
@@ -1611,12 +1608,12 @@
<string name="error_showing_content">Fehler beim Anzeigen des Inhalts</string>
<string name="error_showing_message">Fehler beim Anzeigen der Nachricht</string>
<string name="you_can_make_address_visible_via_settings">Sie können sie über Einstellungen für Ihre SimpleX-Kontakte sichtbar machen.</string>
<string name="recent_history_is_not_sent_to_new_members">Der Verlauf wird nicht an neue Gruppenmitglieder gesendet.</string>
<string name="recent_history_is_not_sent_to_new_members">Der Nachrichtenverlauf wird nicht an neue Gruppenmitglieder gesendet.</string>
<string name="retry_verb">Wiederholen</string>
<string name="camera_not_available">Kamera nicht verfügbar</string>
<string name="enable_sending_recent_history">Bis zu 100 der letzten Nachrichten an neue Gruppenmitglieder senden.</string>
<string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>Kontakt hinzufügen</b>: Um einen neuen Einladungslink zu erstellen oder eine Verbindung über einen Link herzustellen, den Sie erhalten haben.]]></string>
<string name="disable_sending_recent_history">Den Verlauf nicht an neue Mitglieder senden.</string>
<string name="disable_sending_recent_history">Den Nachrichtenverlauf nicht an neue Mitglieder senden.</string>
<string name="or_show_this_qr_code">Oder diesen QR-Code anzeigen</string>
<string name="recent_history_is_sent_to_new_members">Bis zu 100 der letzten Nachrichten werden an neue Mitglieder gesendet.</string>
<string name="code_you_scanned_is_not_simplex_link_qr_code">Der von Ihnen gescannte Code ist kein SimpleX-Link-QR-Code.</string>
@@ -1626,7 +1623,7 @@
<string name="keep_unused_invitation_question">Nicht genutzte Einladung behalten?</string>
<string name="share_this_1_time_link">Teilen Sie diesen Einmal-Einladungslink</string>
<string name="create_group_button_to_create_new_group"><![CDATA[<b>Gruppe erstellen</b>: Um eine neue Gruppe zu erstellen.]]></string>
<string name="recent_history">Sichtbarer Verlauf</string>
<string name="recent_history">Sichtbarer Nachrichtenverlauf</string>
<string name="la_app_passcode">App-Zugangscode</string>
<string name="new_chat">Neuer Chat</string>
<string name="loading_chats">Chats werden geladen…</string>
@@ -1670,4 +1667,13 @@
<string name="agent_internal_error_title">Interner Fehler</string>
<string name="remote_host_error_bad_version"><![CDATA[Auf dem Mobiltelefon <b>%s</b> wird eine nicht unterstützte Version verwendet. Bitte stellen Sie sicher, dass beide Geräte die selbe Version nutzen]]></string>
<string name="remote_host_error_busy"><![CDATA[Mobiltelefon <b>%s</b> ist besetzt]]></string>
<string name="past_member_vName">Ehemaliges Mitglied %1$s</string>
<string name="possible_slow_function_desc">Die Ausführung dieser Funktion dauert zu lange: %1$d Sekunden: %2$s</string>
<string name="possible_slow_function_title">Langsame Funktion</string>
<string name="show_slow_api_calls">Zeige langsame API-Aufrufe an</string>
<string name="group_member_status_unknown_short">unbekannt</string>
<string name="possible_deadlock_title">Blockade</string>
<string name="developer_options_section">Optionen für Entwickler</string>
<string name="possible_deadlock_desc">Die Code-Ausführung dauert zu lange: %1$d Sekunden. Wahrscheinlich ist die App eingefroren: %2$s</string>
<string name="group_member_status_unknown">unbekannter Gruppenmitglieds-Status</string>
</resources>
@@ -680,7 +680,7 @@
<string name="run_chat_section">EJECUTAR CHAT</string>
<string name="restart_the_app_to_use_imported_chat_database">Reinicia la aplicación para poder usar la base de datos importada.</string>
<string name="enter_correct_current_passphrase">Introduce la contraseña actual correcta.</string>
<string name="feature_received_prohibited">recepción prohibida</string>
<string name="feature_received_prohibited">recepción no permitida</string>
<string name="only_you_can_delete_messages">Sólo tú puedes eliminar mensajes de forma irreversible (tu contacto puede marcarlos para eliminar). (24 horas)</string>
<string name="prohibit_direct_messages">No se permiten mensajes directos entre miembros.</string>
<string name="prohibit_sending_disappearing">No se permiten mensajes temporales.</string>
@@ -967,17 +967,14 @@
<string name="error_saving_user_password">Error al guardar contraseña de usuario</string>
<string name="relay_server_if_necessary">El retransmisor sólo se usa en caso de necesidad. Un tercero podría ver tu IP.</string>
<string name="relay_server_protects_ip">El servidor de retransmisión protege tu IP pero puede ver la duración de la llamada.</string>
<string name="cant_delete_user_profile">¡No se puede eliminar el perfil!</string>
<string name="enter_password_to_show">Introduce la contraseña</string>
<string name="user_hide">Ocultar</string>
<string name="user_mute">Silenciar</string>
<string name="save_and_update_group_profile">Guardar y actualizar perfil del grupo</string>
<string name="tap_to_activate_profile">Pulsa sobre un perfil para activarlo.</string>
<string name="should_be_at_least_one_visible_profile">Debe haber al menos un perfil de usuario visible.</string>
<string name="user_unhide">Mostrar</string>
<string name="button_welcome_message">Mensaje de bienvenida</string>
<string name="group_welcome_title">Mensaje de bienvenida</string>
<string name="should_be_at_least_one_profile">Debe haber al menos un perfil de usuario.</string>
<string name="make_profile_private">¡Hacer perfil privado!</string>
<string name="dont_show_again">No mostrar de nuevo</string>
<string name="muted_when_inactive">¡Silenciado cuando está inactivo!</string>
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="alert_text_decryption_error_n_messages_failed_to_decrypt">رمزگشایی %1$d پیام ناموفق بود.</string>
<string name="moderated_items_description">%1$d پیام توسط %2$s حذف شد</string>
<string name="integrity_msg_skipped">%1$d پیام از قلم افتاده</string>
<string name="group_info_section_title_num_members">%1$s عضو</string>
<string name="contact_wants_to_connect_via_call">%1$s می‌خواهد به شما متصل شود، به وسیله</string>
<string name="chat_item_ttl_day">1 روز</string>
<string name="send_disappearing_message_1_minute">1 دقیقه</string>
<string name="abort_switch_receiving_address_confirm">لغو</string>
<string name="abort_switch_receiving_address">لغو تغییر نشانی</string>
<string name="abort_switch_receiving_address_question">تغییر نشانی را لغو می‌کنید؟</string>
<string name="about_simplex">درباره سیمپل‌اکس(SimpleX)</string>
<string name="connect_via_contact_link">به وسیله نشانی مخاطب متصل می‌شوید؟</string>
<string name="connect_via_invitation_link">به وسیله لینک یک بار مصرف متصل می‌شوید؟</string>
<string name="connect_use_new_incognito_profile">از نمایه ناشناس جدید استفاده کن</string>
<string name="opening_database">در حال گشودن پایگاه داده…</string>
<string name="profile_will_be_sent_to_contact_sending_link">نمایه شما به مخاطبی که این لینک را از او دریافت کردید، فرستاده خواهد شد.</string>
<string name="connect_via_link_incognito">متصل شدن به صورت ناشناس</string>
<string name="non_content_uri_alert_text">شما یک مسیر نامعتبر پرونده به اشتراک گذاشتید. موضوع را به توسعه‌دهندگان برنامه گزارش دهید.</string>
<string name="receiving_files_not_yet_supported">هنوز از دریافت پرونده پشتیبانی نمی‌شود</string>
<string name="invalid_message_format">قالب پیام نامعتبر</string>
<string name="moderated_description">حذف شده</string>
<string name="error_showing_message">خطا در نمایش پیام</string>
<string name="trying_to_connect_to_server_to_receive_messages">در حال تلاش برای اتصال به سرور مورد استفاده برای دریافت پیام‌ها از این مخاطب.</string>
<string name="marked_deleted_items_description">%d پیام به عنوان حذف شده علامت گذاشته شد</string>
<string name="connected_to_server_to_receive_messages_from_contact">به سرور مورد استفاده برای دریافت پیام‌ها از این مخاطب متصل شده‌اید.</string>
<string name="server_connected">متصل</string>
<string name="server_error">خطا</string>
<string name="server_connecting">در حال اتصال</string>
<string name="thousand_abbreviation">k</string>
<string name="connect_via_group_link">به گروه می‌پیوندید؟</string>
<string name="connect_use_current_profile">از نمایه کنونی استفاده کن</string>
<string name="you_will_join_group">به تمام اعضای گروه متصل خواهید شد.</string>
<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="deleted_description">حذف شده</string>
<string name="marked_deleted_description">علامت گذاشته شده به عنوان حذف شده</string>
<string name="moderated_item_description">توسط %s حذف شد</string>
<string name="blocked_item_description">مسدود</string>
<string name="blocked_items_description">%d پیام مسدود شده</string>
<string name="sending_files_not_yet_supported">هنوز از ارسال پرونده پشتیبانی نمی‌شود</string>
<string name="sender_you_pronoun">شما</string>
<string name="unknown_message_format">قالب پیام ناشناخته</string>
<string name="live">زنده</string>
<string name="invalid_chat">گپ نامعتبر</string>
<string name="invalid_data">داده نامعتبر</string>
<string name="error_showing_content">خطا در نمایش محتوا</string>
<string name="decryption_error">خطا در رمزگشایی</string>
<string name="send_disappearing_message_5_minutes">5 دقیقه</string>
<string name="learn_more_about_address">درباره نشانی سیمپل‌اکس(SimpleX)</string>
<string name="one_time_link_short">لینک یک بار مصرف</string>
<string name="about_simplex_chat">درباره سیمپل‌اکس چت(SimpleX Chat)</string>
<string name="alert_text_decryption_error_too_many_skipped">%1$d پیام از قلم افتاد.</string>
<string name="chat_item_ttl_month">1 ماه</string>
<string name="chat_item_ttl_week">1 هفته</string>
<string name="v5_3_new_interface_languages">6 زبان جدید برای رابط کاربری</string>
<string name="send_disappearing_message_30_seconds">30 ثانیه</string>
<string name="description_you_shared_one_time_link_incognito">شما لینک یک بار مصرف ناشناس به اشتراک گذاشتید</string>
<string name="description_via_group_link">به وسیله لینک گروه</string>
<string name="description_via_group_link_incognito">ناشناس به وسیله لینک گروه</string>
<string name="description_via_contact_address_link">به وسیله لینک نشانی مخاطب</string>
<string name="description_via_one_time_link_incognito">ناشناس به وسیله لینک یک بار مصرف</string>
<string name="simplex_link_mode_description">توصیف</string>
<string name="simplex_link_mode_full">لینک کامل</string>
<string name="simplex_link_mode">لینک‌های SimpleX</string>
<string name="error_saving_smp_servers">خطا در ذخیره کردن سرورهای SMP</string>
<string name="error_saving_xftp_servers">خطا در ذخیره کردن سرورهای XFTP</string>
<string name="encryption_renegotiation_error">خطا در مذاکره مجدد رمزگذاری</string>
<string name="connection_local_display_name">اتصال %1$d</string>
<string name="display_name_connection_established">اتصال برقرار شد</string>
<string name="description_you_shared_one_time_link">شما لینک یک بار مصرف به اشتراک گذاشتید</string>
<string name="display_name_invited_to_connect">برای اتصال دعوت شده</string>
<string name="description_via_contact_address_link_incognito">ناشناس به وسیله لینک نشانی مخاطب</string>
<string name="description_via_one_time_link">به وسیله لینک یک بار مصرف</string>
<string name="simplex_link_group">لینک گروه SimpleX</string>
<string name="simplex_link_connection">به وسیله %1$s</string>
<string name="simplex_link_mode_browser">به وسیله مرورگر</string>
<string name="simplex_link_contact">نشانی مخاطب SimpleX</string>
<string name="simplex_link_invitation">دعوت یک بار مصرف SimpleX</string>
<string name="display_name_connecting">در حال اتصال…</string>
<string name="simplex_link_mode_browser_warning">باز کردن لینک در مرورگر ممکن است حریم خصوصی و امنیت اتصال را کاهش دهد. لینک‌های SimpleX ناموثق قرمز خواهند بود.</string>
</resources>
@@ -335,7 +335,6 @@
<string name="share_text_disappears_at">Katoaa klo: %s</string>
<string name="create_secret_group_title">Luo salainen ryhmä</string>
<string name="chat_preferences_always">aina</string>
<string name="cant_delete_user_profile">Käyttäjäprofiilia ei voi poistaa!</string>
<string name="allow_your_contacts_to_call">Salli kontaktiesi soittaa sinulle.</string>
<string name="allow_your_contacts_irreversibly_delete">Salli kontaktiesi poistaa lähetetyt viestit peruuttamattomasti.</string>
<string name="allow_your_contacts_to_send_voice_messages">Salli kontaktiesi lähettää ääniviestejä.</string>
@@ -1238,8 +1237,6 @@
<string name="snd_conn_event_switch_queue_phase_completed_for_member">muutit osoitteeksi %s</string>
<string name="invite_prohibited_description">Yrität kutsua kontaktia, jonka kanssa olet jakanut inkognito-profiilin, ryhmään, jossa käytät pääprofiiliasi</string>
<string name="group_welcome_title">Tervetuloviesti</string>
<string name="should_be_at_least_one_profile">Käyttäjäprofiileja tulee olla vähintään yksi.</string>
<string name="should_be_at_least_one_visible_profile">Näkyviä käyttäjäprofiileja tulee olla vähintään yksi.</string>
<string name="incognito_info_share">Kun jaat inkognitoprofiilin jonkun kanssa, tätä profiilia käytetään ryhmissä, joihin tämä sinut kutsuu.</string>
<string name="group_main_profile_sent">Keskusteluprofiilisi lähetetään ryhmän jäsenille</string>
<string name="incognito_random_profile">Satunnainen profiilisi</string>
@@ -962,7 +962,6 @@
<string name="smp_save_servers_question">Enregistrer les serveurs ?</string>
<string name="dont_show_again">Ne plus afficher</string>
<string name="button_add_welcome_message">Ajouter un message d\'accueil</string>
<string name="cant_delete_user_profile">Impossible de supprimer le profil d\'utilisateur !</string>
<string name="v4_6_group_moderation">Modération de groupe</string>
<string name="user_hide">Cacher</string>
<string name="muted_when_inactive">Mute en cas d\'inactivité !</string>
@@ -993,8 +992,6 @@
<string name="to_reveal_profile_enter_password">Pour révéler votre profil caché, entrez le mot de passe dans le champ de recherche de la page Profils de chat.</string>
<string name="v4_6_audio_video_calls_descr">Prise en charge du Bluetooth et autres améliorations.</string>
<string name="v4_6_chinese_spanish_interface_descr">Merci aux utilisateurs - contribuez via Weblate !</string>
<string name="should_be_at_least_one_profile">Il doit y avoir au moins un profil d\'utilisateur.</string>
<string name="should_be_at_least_one_visible_profile">Il doit y avoir au moins un profil d\'utilisateur visible.</string>
<string name="user_unhide">Dévoiler</string>
<string name="user_unmute">Démute</string>
<string name="button_welcome_message">Message d\'accueil</string>
@@ -1559,4 +1556,67 @@
<string name="search_or_paste_simplex_link">Rechercher ou coller un lien SimpleX</string>
<string name="chat_is_stopped_you_should_transfer_database">Le chat est arrêté. Si vous avez déjà utilisé cette base de données sur un autre appareil, vous devez la transférer à nouveau avant de démarrer le chat.</string>
<string name="start_chat_question">Lancer le chat ?</string>
<string name="remote_host_error_bad_state"><![CDATA[État médiocre de la connexion au mobile <b>%s</b>.]]></string>
<string name="remote_ctrl_was_disconnected_title">Connexion interrompue</string>
<string name="remote_ctrl_error_bad_state">État médiocre de la connexion avec le bureau</string>
<string name="possible_deadlock_title">Impasse</string>
<string name="remote_ctrl_error_bad_version">La version de l\'ordinateur de bureau n\'est pas prise en charge. Veillez à utiliser la même version sur les deux appareils.</string>
<string name="remote_ctrl_error_disconnected">Le bureau a été déconnecté</string>
<string name="developer_options_section">Options pour les développeurs</string>
<string name="possible_deadlock_desc">Le code prend trop de temps à s\'exécuter : %1$d secondes. Il est probable que l\'application soit figée : %2$s</string>
<string name="agent_internal_error_title">Erreur interne</string>
<string name="remote_host_error_bad_version"><![CDATA[La version du mobile <b>%s</b> n\'est pas prise en charge. Veillez à utiliser la même version sur les deux appareils.]]></string>
<string name="show_internal_errors">Afficher les erreurs internes</string>
<string name="remote_ctrl_disconnected_with_reason">Déconnecté pour la raison suivante : %s</string>
<string name="failed_to_create_user_invalid_title">Nom d\'affichage invalide !</string>
<string name="failed_to_create_user_invalid_desc">Ce nom d\'affichage est invalide. Veuillez choisir un autre nom.</string>
<string name="remote_ctrl_error_timeout">Délai d\'attente dépassé lors de la connexion au bureau</string>
<string name="agent_critical_error_title">Erreur critique</string>
<string name="agent_critical_error_desc">Veuillez le signaler aux développeurs :
\n%s
\n
\nIl est recommandé de redémarrer l\'application.</string>
<string name="agent_internal_error_desc">Veuillez le signaler aux développeurs :
\n%s</string>
<string name="restart_chat_button">Redémarrer le chat</string>
<string name="group_member_status_unknown_short">inconnu</string>
<string name="group_member_status_unknown">statut inconnu</string>
<string name="remote_host_was_disconnected_title">Connexion interrompue</string>
<string name="past_member_vName">Ancien membre %1$s</string>
<string name="possible_slow_function_desc">La fonctions prend trop de temps à s\'exécuter : %1$d secondes : %2$s</string>
<string name="possible_slow_function_title">Fonction lente</string>
<string name="show_slow_api_calls">Afficher les appels d\'API lents</string>
<string name="remote_host_disconnected_from"><![CDATA[Déconnecté du mobile <b>%s</b> en raison de : %s]]></string>
<string name="remote_host_error_busy"><![CDATA[Mobile <b>%s</b> est occupé]]></string>
<string name="remote_host_error_inactive"><![CDATA[Le mobile <b>%s</b> est inactif]]></string>
<string name="remote_host_error_missing"><![CDATA[Mobile <b>%s</b> est manquant]]></string>
<string name="remote_host_error_disconnected"><![CDATA[Le mobile <b>%s</b> a été déconnecté]]></string>
<string name="remote_host_error_timeout"><![CDATA[Délai d\'attente expiré lors de la connexion au mobile <b>%s</b>]]></string>
<string name="remote_ctrl_error_bad_invitation">Le bureau ne possède pas le bon code d\'invitation</string>
<string name="remote_ctrl_error_busy">Le bureau est occupé</string>
<string name="remote_ctrl_error_inactive">Le bureau est inactif</string>
<string name="v5_5_private_notes_descr">Avec les fichiers et les médias chiffrés.</string>
<string name="v5_5_join_group_conversation_descr">Historique récent et bot d\'annuaire amélioré.</string>
<string name="v5_5_simpler_connect_ui_descr">La barre de recherche accepte les liens d\'invitation.</string>
<string name="v5_5_message_delivery_descr">Consommation réduite de la batterie.</string>
<string name="clear_note_folder_warning">Tous les messages seront supprimés - il n\'est pas possible de revenir en arrière !</string>
<string name="v5_5_new_interface_languages">Interface utilisateur en hongrois et en turc</string>
<string name="v5_5_private_notes">Notes privées</string>
<string name="info_row_created_at">Créé à</string>
<string name="error_creating_message">Erreur lors de la création du message</string>
<string name="v5_5_message_delivery">Amélioration de la transmission des messages</string>
<string name="v5_5_join_group_conversation">Participez aux conversations de groupe</string>
<string name="share_text_created_at">Créé à : %s</string>
<string name="error_deleting_note_folder">Erreur lors de la suppression de notes privées</string>
<string name="v5_5_simpler_connect_ui">Collez le lien pour vous connecter !</string>
<string name="note_folder_local_display_name">Notes privées</string>
<string name="profile_update_event_contact_name_changed">le contact %1$s est devenu %2$s</string>
<string name="profile_update_event_member_name_changed">le membre %1$s est devenu %2$s</string>
<string name="profile_update_event_removed_address">suppression de l\'adresse de contact</string>
<string name="profile_update_event_removed_picture">suppression de la photo de profil</string>
<string name="profile_update_event_set_new_address">définir une nouvelle adresse de contact</string>
<string name="profile_update_event_set_new_picture">définir une nouvelle image de profil</string>
<string name="profile_update_event_updated_profile">profil mis à jour</string>
<string name="clear_note_folder_question">Effacer les notes privées ?</string>
<string name="saved_message_title">Message enregistré</string>
</resources>
@@ -45,7 +45,6 @@
<string name="both_you_and_your_contact_can_send_disappearing">Mindketten, te is és az ismerősöd is küldhet eltűnő üzeneteket.</string>
<string name="keychain_is_storing_securely">Az Android Keystore-t a jelmondat biztonságos tárolására használják - lehetővé teszi az értesítési szolgáltatás működését.</string>
<string name="alert_title_msg_bad_hash">Téves üzenet hash</string>
<string name="cant_delete_user_profile">Felhasználói profil törlése nem lehetséges!</string>
<string name="color_background">Háttér</string>
<string name="socks_proxy_setting_limitations"><![CDATA[<b>Tudnivaló</b>: az üzenet- és fájl relay szerverek SOCKS proxy által vannak kapcsolatban. A hívások és URL link előnézetek közvetlen kapcsolatot használnak.]]></string>
<string name="full_backup">App adatmentés</string>
@@ -1493,7 +1492,6 @@
<string name="the_messaging_and_app_platform_protecting_your_privacy_and_security">A Te adatvédelmedet és biztonságodat védő üzenetküldő és alkalmazásplatform.</string>
<string name="tap_to_activate_profile">Érintsd meg a profil aktiválásához.</string>
<string name="receipts_contacts_override_disabled">A kézbesítési jelentés le van tiltva %d ismerősödnél</string>
<string name="should_be_at_least_one_profile">Legalább egy felhasználói profilnak kell lennie.</string>
<string name="session_code">Munkamenet kód</string>
<string name="v4_4_french_interface_descr">Köszönet a felhasználóknak - hozzájárulás a Weblaten!</string>
<string name="receipts_section_groups">Kis csoportok (max. 20 tag)</string>
@@ -1510,7 +1508,6 @@
<string name="receiving_via">Fogadás a</string>
<string name="store_passphrase_securely_without_recover">Kérjük, hogy a jelmondatot biztonságosan tárold, ha elveszíted, NEM fogsz tudni hozzáférni a chathez.</string>
<string name="member_role_will_be_changed_with_invitation">A szerepkör \"%s\"-re fog változni. A tag új meghívót kap.</string>
<string name="should_be_at_least_one_visible_profile">Legalább egy látható felhasználói profilnak kell lennie.</string>
<string name="icon_descr_profile_image_placeholder">profilkép helyőrző</string>
<string name="sync_connection_force_desc">A titkosítás működik, és új titkosítási egyezményre nincs szükség. Ez kapcsolati hibákat eredményezhet!</string>
<string name="delete_chat_profile_action_cannot_be_undone_warning">Ez a művelet nem vonható vissza - profilod, ismerőseid, üzeneteid és fájljaid visszafordíthatatlanul törlésre kerülnek.</string>
@@ -1567,4 +1564,54 @@
<string name="remote_host_was_disconnected_title">A kapcsolat megszakadt</string>
<string name="remote_ctrl_was_disconnected_title">A kapcsolat megszakadt</string>
<string name="remote_ctrl_error_bad_state">Az asztali kliens kapcsolata rossz állapotban van</string>
<string name="agent_critical_error_desc">Kérjük, jelezd ezt a fejlesztőknek:
\n%s
\n
\nJavasoljuk, hogy indítsd újra az alkalmazást.</string>
<string name="agent_internal_error_desc">Kérjük, jelezd a fejlesztőknek:
\n%s</string>
<string name="remote_host_error_bad_version"><![CDATA[A(z) <b>%s</b> mobil eszköz verziója nem támogatott. Kérlek, győződj meg róla, hogy mindkét eszközön ugyanazt a verziót használod]]></string>
<string name="remote_host_error_disconnected"><![CDATA[Megszakadt a kapcsolat a(z) <b>%s</b> mobil eszközzel]]></string>
<string name="failed_to_create_user_invalid_title">Érvénytelen megjelenítendő felhaszálónév!</string>
<string name="failed_to_create_user_invalid_desc">Ez a megjelenített felhasználónév érvénytelen. Kérjük, válassz másikat.</string>
<string name="remote_host_disconnected_from"><![CDATA[Megszakadt a kapcsolat a <b>%s</b> mobil eszközzel, a(z) %s probléma miatt.]]></string>
<string name="remote_ctrl_disconnected_with_reason">%s probléma miatt megszakadt a kapcsolat</string>
<string name="remote_host_error_missing"><![CDATA[A(z) <b>%s</b> mobil eszköz nem található]]></string>
<string name="remote_host_error_bad_state"><![CDATA[A kapcsolat a(z) <b>%s</b> mobil eszközzel rossz állapotban van]]></string>
<string name="remote_host_error_timeout"><![CDATA[Időtúllépés a(z) <b>%s</b> mobil eszközhöz való csatlakozás közben]]></string>
<string name="group_member_status_unknown_short">ismeretlen</string>
<string name="possible_slow_function_title">Lassú funkció</string>
<string name="show_slow_api_calls">Lassú API-hívások megjelenítése</string>
<string name="remote_host_error_inactive"><![CDATA[A(z) <b>%s</b> mobil eszköz inaktív]]></string>
<string name="possible_deadlock_title">Elakadt</string>
<string name="developer_options_section">Fejlesztői beállítások</string>
<string name="possible_deadlock_desc">A kód végrehajtása túl sokáig tart: %1$d másodperc. Valószínűleg az alkalmazás lefagyott: %2$s</string>
<string name="possible_slow_function_desc">A funkció végrehajtása túl sokáig tart: %1$d másodperc: %2$s</string>
<string name="remote_host_error_busy"><![CDATA[A(z) <b>%s</b> mobil eszköz elfoglalt]]></string>
<string name="past_member_vName">Legutóbbi tag %1$s</string>
<string name="group_member_status_unknown">ismeretlen státusz</string>
<string name="profile_update_event_member_name_changed">%1$s tag %2$s-ra/re változott</string>
<string name="profile_update_event_removed_address">törölt csatlakozási cím</string>
<string name="profile_update_event_removed_picture">törölt profilkép</string>
<string name="profile_update_event_set_new_address">új kapcsolattartási cím beállítása</string>
<string name="profile_update_event_set_new_picture">új profilkép beállítása</string>
<string name="profile_update_event_updated_profile">frissített profil</string>
<string name="profile_update_event_contact_name_changed">%1$s ismerős %2$s-ra/re változott</string>
<string name="note_folder_local_display_name">Privát jegyzetek</string>
<string name="error_deleting_note_folder">Hiba a privát jegyzetek törlésekor</string>
<string name="error_creating_message">Hiba az üzenet létrehozásakor</string>
<string name="clear_note_folder_question">Törlöd a privát jegyzeteket?</string>
<string name="info_row_created_at">Létrehozva ekkor:</string>
<string name="saved_message_title">Mentett üzenet</string>
<string name="share_text_created_at">Létrehozva ekkor: %s</string>
<string name="clear_note_folder_warning">Az összes üzenet törlődik – ez nem vonható vissza!</string>
<string name="v5_5_message_delivery">Továbbfejlesztett üzenetküldés</string>
<string name="v5_5_join_group_conversation">Csatlakozás csoportos beszélgetésekhez</string>
<string name="v5_5_simpler_connect_ui">A link beillesztése a csatlakozáshoz!</string>
<string name="v5_5_private_notes">Privát jegyzetek</string>
<string name="v5_5_simpler_connect_ui_descr">A keresősáv fogadja a meghívó hivatkozásokat.</string>
<string name="v5_5_private_notes_descr">Titkosított fájlokkal és média állományokkal.</string>
<string name="v5_5_message_delivery_descr">Csökkentett akkumulátorhasználattal.</string>
<string name="v5_5_new_interface_languages">Magyar és török felhasználói felület</string>
<string name="v5_5_join_group_conversation_descr">A közelmúlt eseményei és továbbfejlesztett Jegyzék Bot.</string>
</resources>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="24"
viewBox="0 -960 960 960"
width="24"
xmlns="http://www.w3.org/2000/svg">
<path
id="path151"
style="display:inline;fill:#ffffff;stroke-width:58"
d="M 480,-880 A 400,400 0 0 0 80,-480 400,400 0 0 0 480,-80 400,400 0 0 0 880,-480 400,400 0 0 0 480,-880 Z m -194.65461,218.29769 h 162.0477 l 33.18257,33.18257 h 194.07895 c 8.44741,0 16.07203,3.40719 22.90296,10.23849 6.83129,6.83091 10.2796,14.49667 10.2796,22.94408 v 263.85691 c 0,8.44742 -3.44831,16.07205 -10.2796,22.90295 -6.83093,6.83132 -14.45555,10.27962 -22.90296,10.27962 H 285.34539 c -8.83193,0 -16.59324,-3.4483 -23.23191,-10.27962 -6.63903,-6.8309 -9.95065,-14.45553 -9.95065,-22.90295 v -297.03948 c 0,-8.44742 3.31162,-16.07205 9.95065,-22.90295 6.63867,-6.83132 14.39998,-10.27962 23.23191,-10.27962 z" />
<rect
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:19.9532;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
id="rect151"
width="500"
height="30"
x="220"
y="-540" />
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M142.5-222.5v-515 515Zm0 57.5q-22.969 0-40.234-17.266Q85-199.531 85-222.5v-515q0-22.969 17.266-40.234Q119.531-795 142.5-795h257q11.943 0 22.766 4.739 10.823 4.739 18.727 12.754L481-737.5h336.5q22.969 0 40.234 17.266Q875-702.969 875-680v193.5q-13.5-7.5-27.672-10.5t-29.828-3.5V-680H457l-57.5-57.5h-257v515h358-.5v57.5H142.5Zm415 51v-81q0-5.013 2-9.964 2-4.95 6.5-10.036l211.612-210.773q9.113-8.62 20.004-12.674 10.891-4.053 21.645-4.053 11.732 0 22.485 4.25Q852.5-434 861.5-425l37 37q8.765 8.855 12.632 19.677Q915-357.5 915-346.75t-4.382 22.031q-4.383 11.281-13.201 19.843L687.5-93.5q-5.086 4.5-9.949 6.5-4.864 2-10.051 2h-81q-12.25 0-20.625-8.375T557.5-114Zm299-233-37-37 37 37Zm-240 203h37.761L776.5-267l-17.887-19-18.88-18L616.5-182v38Zm142-142-19-18 37 37-18-19Z"/></svg>

After

Width:  |  Height:  |  Size: 871 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M283-245.5q-14 0-27.25-13.75T242.5-287v-98H735v-333.5h100q14 0 26.75 14T874.5-676v517.5q0 19.5-17.75 26.5t-31.25-6.5l-107-107H283Zm-40.5-197-108 108Q121-321 103.25-328T85.5-354.5V-834q0-14 12.75-27.75T125-875.5h512q14.5 0 27.5 13.5t13 28v350q0 14-13 27.75T637-442.5H242.5ZM620-500v-318H143v318h477Zm-477 0v-318 318Z"/></svg>

After

Width:  |  Height:  |  Size: 421 B

@@ -678,7 +678,7 @@
<string name="video_call_no_encryption">videochiamata (non crittografata e2e)</string>
<string name="onboarding_notifications_mode_off">Quando l\'app è in esecuzione</string>
<string name="contact_wants_to_connect_via_call">%1$s vuole connettersi con te via</string>
<string name="you_control_servers_to_receive_your_contacts_to_send"><![CDATA[Puoi controllare attraverso quale/i server <b>ricevere</b> i messaggi, i tuoi contatti – i server che usi per inviare loro i messaggi.]]></string>
<string name="you_control_servers_to_receive_your_contacts_to_send"><![CDATA[Tu decidi attraverso quale/i server <b>ricevere</b> i messaggi, i tuoi contatti quali server usi per inviare loro i messaggi.]]></string>
<string name="alert_text_skipped_messages_it_can_happen_when">Può accadere quando:
\n1. I messaggi sono scaduti sul client mittente dopo 2 giorni o sul server dopo 30 giorni.
\n2. La decifrazione del messaggio è fallita, perché tu o il tuo contatto avete usato un backup del database vecchio.
@@ -969,8 +969,6 @@
<string name="tap_to_activate_profile">Tocca per attivare il profilo.</string>
<string name="user_unhide">Svela</string>
<string name="make_profile_private">Rendi privato il profilo!</string>
<string name="should_be_at_least_one_profile">Deve esserci almeno un profilo utente.</string>
<string name="should_be_at_least_one_visible_profile">Deve esserci almeno un profilo utente visibile.</string>
<string name="you_can_hide_or_mute_user_profile">Puoi nascondere o silenziare un profilo utente - tienilo premuto per il menu.</string>
<string name="dont_show_again">Non mostrare più</string>
<string name="muted_when_inactive">Silenzioso quando inattivo!</string>
@@ -990,7 +988,6 @@
<string name="v4_6_group_moderation_descr">Ora gli amministratori possono:
\n- eliminare i messaggi dei membri.
\n- disattivare i membri (ruolo \"osservatore\")</string>
<string name="cant_delete_user_profile">Impossibile eliminare il profilo utente!</string>
<string name="hide_profile">Nascondi il profilo</string>
<string name="confirm_password">Conferma password</string>
<string name="error_updating_user_privacy">Errore nell\'aggiornamento della privacy dell\'utente</string>
@@ -1569,4 +1566,57 @@
\n%s</string>
<string name="restart_chat_button">Riavvia la chat</string>
<string name="show_internal_errors">Mostra errori interni</string>
<string name="remote_host_disconnected_from"><![CDATA[Disconnesso dal telefono <b>%s</b> per il motivo: %s]]></string>
<string name="remote_ctrl_disconnected_with_reason">Disconnesso per il motivo: %s</string>
<string name="remote_host_was_disconnected_title">Connessione interrotta</string>
<string name="remote_ctrl_was_disconnected_title">Connessione interrotta</string>
<string name="remote_host_error_missing"><![CDATA[Telefono <b>%s</b> non trovato]]></string>
<string name="remote_ctrl_error_busy">Il desktop è occupato</string>
<string name="remote_ctrl_error_bad_version">Il desktop ha una versione non supportata. Assicurati di usare la stessa versione su entrambi i dispositivi</string>
<string name="failed_to_create_user_invalid_title">Nome da mostrare non valido!</string>
<string name="failed_to_create_user_invalid_desc">Questo nome da mostrare non è valido. Scegline un altro.</string>
<string name="remote_host_error_bad_state"><![CDATA[La connessione al telefono <b>%s</b> è in cattivo stato]]></string>
<string name="remote_host_error_bad_version"><![CDATA[Il telefono <b>%s</b> ha una versione non supportata. Assicurati di usare la stessa versione su entrambi i dispositivi]]></string>
<string name="remote_host_error_busy"><![CDATA[Il telefono <b>%s</b> è occupato]]></string>
<string name="remote_host_error_inactive"><![CDATA[Il telefono <b>%s</b> è inattivo]]></string>
<string name="remote_host_error_disconnected"><![CDATA[Il telefono <b>%s</b> è stato disconnesso]]></string>
<string name="remote_host_error_timeout"><![CDATA[Tempo scaduto durante la connessione al telefono <b>%s</b>]]></string>
<string name="remote_ctrl_error_bad_state">La connessione al desktop è in cattivo stato</string>
<string name="remote_ctrl_error_bad_invitation">Il desktop ha un codice di invito sbagliato</string>
<string name="remote_ctrl_error_inactive">Il desktop è inattivo</string>
<string name="remote_ctrl_error_disconnected">Il desktop è stato disconnesso</string>
<string name="remote_ctrl_error_timeout">Tempo scaduto durante la connessione al desktop</string>
<string name="past_member_vName">Membro passato %1$s</string>
<string name="possible_slow_function_desc">L\'esecuzione della funzione impiega troppo tempo: %1$d secondi: %2$s</string>
<string name="possible_slow_function_title">Funzione lenta</string>
<string name="show_slow_api_calls">Mostra chiamate API lente</string>
<string name="group_member_status_unknown_short">sconosciuto</string>
<string name="possible_deadlock_desc">L\'esecuzione del codice impiega troppo tempo: %1$d secondi. Probabilmente l\'app è congelata: %2$s</string>
<string name="group_member_status_unknown">stato sconosciuto</string>
<string name="possible_deadlock_title">Stallo</string>
<string name="developer_options_section">Opzioni sviluppatore</string>
<string name="v5_5_private_notes">Note private</string>
<string name="v5_5_new_interface_languages">Interfaccia in ungherese e turco</string>
<string name="v5_5_join_group_conversation_descr">Cronologia recente e bot della directory migliorato.</string>
<string name="info_row_created_at">Creato il</string>
<string name="clear_note_folder_warning">Tutti i messaggi verranno eliminati, non è reversibile!</string>
<string name="share_text_created_at">Creato il: %s</string>
<string name="error_creating_message">Errore di creazione del messaggio</string>
<string name="error_deleting_note_folder">Errore di eliminazione delle note private</string>
<string name="v5_5_message_delivery">Consegna dei messaggi migliorata</string>
<string name="v5_5_join_group_conversation">Entra in conversazioni di gruppo</string>
<string name="profile_update_event_member_name_changed">membro %1$s cambiato in %2$s</string>
<string name="v5_5_simpler_connect_ui">Incolla un link per connettere!</string>
<string name="profile_update_event_removed_address">indirizzo di contatto rimosso</string>
<string name="profile_update_event_contact_name_changed">contatto %1$s cambiato in %2$s</string>
<string name="note_folder_local_display_name">Note private</string>
<string name="clear_note_folder_question">Svuotare le note private?</string>
<string name="profile_update_event_removed_picture">immagine del profilo rimossa</string>
<string name="v5_5_private_notes_descr">Con file e multimediali criptati.</string>
<string name="v5_5_simpler_connect_ui_descr">La barra di ricerca accetta i link di invito.</string>
<string name="profile_update_event_set_new_picture">impostata nuova immagine del profilo</string>
<string name="profile_update_event_set_new_address">impostato nuovo indirizzo di contatto</string>
<string name="profile_update_event_updated_profile">profilo aggiornato</string>
<string name="saved_message_title">Messaggio salvato</string>
<string name="v5_5_message_delivery_descr">Con consumo di batteria ridotto.</string>
</resources>
@@ -112,7 +112,6 @@
<string name="icon_descr_call_progress">שיחה מתמשכת</string>
<string name="settings_section_title_calls">שיחות</string>
<string name="cannot_access_keychain">לא ניתן לגשת ל־Keystore כדי לאחסן את סיסמת מסד הנתונים</string>
<string name="cant_delete_user_profile">לא ניתן למחוק פרופיל משתמש!</string>
<string name="feature_cancelled_item">בוטל %s</string>
<string name="v4_5_transport_isolation_descr">לפי פרופיל צ׳אט (ברירת מחדל) או לפי חיבור (בביטא).</string>
<string name="callstatus_calling">מתקשר…</string>
@@ -1055,8 +1054,6 @@
<string name="messages_section_description">הגדרה זו חלה על הודעות בפרופיל הצ׳אט הנוכחי שלך</string>
<string name="database_backup_can_be_restored">הניסיון לשנות את סיסמת מסד הנתונים לא הושלם.</string>
<string name="color_title">כותרת</string>
<string name="should_be_at_least_one_profile">נדרש לפחות פרופיל משתמש אחד.</string>
<string name="should_be_at_least_one_visible_profile">נדרש לפחות פרופיל משתמש אחד גלוי.</string>
<string name="group_is_decentralized">הקבוצה מבוזרת לחלוטין - היא גלויה רק לחברי הקבוצה.</string>
<string name="to_protect_privacy_simplex_has_ids_for_queues">כדי לשמור על הפרטיות, במקום מזהי משתמש הקיימים בכל הפלטפורמות האחרות, ל־SimpleX יש מזהים לתורי הודעות, נפרדים עבור כל אחד מאנשי הקשר שלך.</string>
<string name="using_simplex_chat_servers">משתמש בשרתי SimpleX Chatז</string>
@@ -328,7 +328,7 @@
<string name="callstatus_connecting">発信中…</string>
<string name="callstate_ended">終了</string>
<string name="opensource_protocol_and_code_anybody_can_run_servers">プロトコル技術とコードはオープンソースで、どなたでもご自分のサーバを運用できます。</string>
<string name="privacy_redefined">プライバシーの基準を新境地に</string>
<string name="privacy_redefined">プライバシーを再定義</string>
<string name="how_it_works">技術の説明</string>
<string name="make_private_connection">プライベートな接続をする</string>
<string name="onboarding_notifications_mode_title">プライベートな通知</string>
@@ -530,7 +530,7 @@
<string name="network_use_onion_hosts_required_desc">接続にオニオンのホストが必要となります。
\n注意: .onion アドレスがないとサーバーに接続できません。</string>
<string name="create_address">アドレスを作成</string>
<string name="delete_address__question">アドレスの削除?</string>
<string name="delete_address__question">アドレスを削除?</string>
<string name="display_name__field">プロフィール名:</string>
<string name="full_name__field">フルネーム:</string>
<string name="create_profile_button">作成</string>
@@ -566,7 +566,7 @@
<string name="theme_light">ライトテーマ</string>
<string name="chat_preferences_default">デフォルト (%s)</string>
<string name="prohibit_sending_disappearing_messages">消えるメッセージを使用禁止にする。</string>
<string name="contacts_can_mark_messages_for_deletion">連絡先はメッセージを削除対象とすることができます。あなたには閲覧可能です。</string>
<string name="contacts_can_mark_messages_for_deletion">連絡先はメッセージを削除対象としてマークを付けられます。あなたには閲覧可能です。</string>
<string name="only_you_can_send_disappearing">消えるメッセージを送れるのはあなただけです。</string>
<string name="prohibit_message_deletion">メッセージの完全削除を使用禁止にする。</string>
<string name="prohibit_sending_voice">音声メッセージを使用禁止にする。</string>
@@ -582,7 +582,7 @@
<string name="v4_5_private_filenames">プライベートなファイル名</string>
<string name="v4_5_reduced_battery_usage">電池使用量低減</string>
<string name="error_removing_member">メンバー削除でエラー発生</string>
<string name="conn_level_desc_indirect">間接 (%1$s)</string>
<string name="conn_level_desc_indirect">間接 (%1$s)</string>
<string name="incognito">シークレットモード</string>
<string name="incognito_info_protects">シークレット モードでは、連絡先ごとに新しいランダムなプロファイルを使用してプライバシーを保護します。</string>
<string name="chat_preferences_no">いいえ</string>
@@ -620,7 +620,7 @@
<string name="rcv_group_event_changed_member_role">%s の役割を %s に変えました。</string>
<string name="rcv_group_event_changed_your_role">役割を %s に変えました。</string>
<string name="rcv_group_event_member_added">招待された %1$s</string>
<string name="snd_conn_event_switch_queue_phase_changing_for_member">アドレスを変更いたします: %s</string>
<string name="snd_conn_event_switch_queue_phase_changing_for_member">アドレスを変更しています: %s</string>
<string name="group_member_role_owner">オーナー</string>
<string name="group_member_status_connecting">接続待ち</string>
<string name="icon_descr_expand_role">役割の選択を拡大</string>
@@ -716,7 +716,7 @@
<string name="you_will_be_connected_when_group_host_device_is_online">グループのホスト端末がオンラインになったら、接続されます。後でチェックするか、しばらくお待ちください。</string>
<string name="you_will_be_connected_when_your_contacts_device_is_online">連絡先がオンラインになったら、接続されます。後でチェックするか、しばらくお待ちください。</string>
<string name="your_chat_profile_will_be_sent_to_your_contact">あなたのチャットプロフィールが
\n連絡相手に送られます。</string>
\n連絡先に公開されます。</string>
<string name="share_invitation_link">ワンタイムリンクを送る</string>
<string name="scan_code">コードを読み込む</string>
<string name="scan_code_from_contacts_app">連絡相手のアプリからセキュリティコードを読み込む</string>
@@ -739,9 +739,9 @@
<string name="network_use_onion_hosts">.onionホストを使う</string>
<string name="network_use_onion_hosts_prefer">利用可能時に</string>
<string name="network_session_mode_transport_isolation">トランスポート隔離</string>
<string name="save_and_notify_contact">保存して、連絡先にに知らせる</string>
<string name="save_and_notify_contact">保存して、連絡先に公開</string>
<string name="your_current_profile">現在のプロフィール</string>
<string name="save_and_notify_contacts">保存して、連絡先にに知らせる</string>
<string name="save_and_notify_contacts">保存して、連絡先に公開</string>
<string name="the_messaging_and_app_platform_protecting_your_privacy_and_security">あなたのプライバシーとセキュリティを守るメッセージとアプリのプラットフォーム</string>
<string name="we_do_not_store_contacts_or_messages_on_servers">連絡先情報と届けたメッセージをサーバに保存することは一切ありません。</string>
<string name="you_control_your_chat">あなたのチャットはあなたが決めます!</string>
@@ -809,8 +809,8 @@
<string name="ntf_channel_messages">SimpleX Chatメッセージ</string>
<string name="ntf_channel_calls">SimpleX Chat通話</string>
<string name="settings_notification_preview_mode_title">プレビューを表示</string>
<string name="notifications_mode_periodic">定期的に起動</string>
<string name="notifications_mode_off">アプリがアクティブ時に実行</string>
<string name="notifications_mode_periodic">定期的に更新</string>
<string name="notifications_mode_off">アプリがアクティブ時に通知を受ける</string>
<string name="icon_descr_sent_msg_status_sent">送信済み</string>
<string name="you_have_no_chats">あなたはチャットがありません。</string>
<string name="share_message">メッセージを送る…</string>
@@ -848,7 +848,7 @@
\nオンにするには、認証ステップが行われます。</string>
<string name="la_notice_turn_on">オンにする</string>
<string name="auth_unlock">ロック解除</string>
<string name="save_verb">保存する</string>
<string name="save_verb">保存</string>
<string name="reveal_verb">開示する</string>
<string name="tap_to_start_new_chat">タップして新しいチャットを始める</string>
<string name="image_decoding_exception_desc">画像が解読できません。別のイメージで試すか、開発者に伝えてください。</string>
@@ -864,7 +864,7 @@
<string name="set_contact_name">連絡先を設定</string>
<string name="contact_wants_to_connect_with_you">あなたと接続を希望しています!</string>
<string name="you_can_also_connect_by_clicking_the_link"><![CDATA[リンクをクリックすることでも接続できます。ブラウザが起動すれば <b>Open in mobile app (アプリで開く)</b>ボタンをクリックしてください。]]></string>
<string name="your_chat_profiles">あなたのチャットプロフィール</string>
<string name="your_chat_profiles">チャットプロフィール</string>
<string name="smp_servers_scan_qr">サーバのQRコードを読み込む</string>
<string name="smp_servers_test_some_failed">テストに失敗したサーバがあります:</string>
<string name="use_simplex_chat_servers__question">SimpleX Chatサーバを使いますか?</string>
@@ -873,7 +873,7 @@
<string name="core_simplexmq_version">simplexmq: バージョン%s (%2s)</string>
<string name="callstate_waiting_for_answer">応答を待機中…</string>
<string name="callstate_waiting_for_confirmation">確認を待機中…</string>
<string name="first_platform_without_user_ids">世界初のユーザーIDのないプラットフォーム|設計も元からプライベート</string>
<string name="first_platform_without_user_ids">世界初のユーザーIDのないプラットフォーム - プライバシーに配慮した設計</string>
<string name="use_chat">チャット</string>
<string name="contact_wants_to_connect_via_call">%1$sは次の方法であなたと繋がりたいです:</string>
<string name="video_call_no_encryption">ビデオ通話 (非エンドツーエンド暗号化)</string>
@@ -901,7 +901,7 @@
<string name="smp_servers_test_servers">テストサーバ</string>
<string name="switch_receiving_address_desc">受信アドレスは別のサーバーに変更されます。アドレス変更は送信者がオンラインになった後に完了します。</string>
<string name="to_protect_privacy_simplex_has_ids_for_queues">あなたのプライバシーを守るために、他のアプリと違って、ユーザーIDの変わりに SimpleX メッセージ束毎にIDを配布し、各連絡先が別々と扱います。</string>
<string name="group_main_profile_sent">あなたのチャットプロフィールが他のグループメンバーに送られます。</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="connection_error_auth_desc">使用済みリンク、または連絡先による接続の削除ではなければ、バッグの可能性があります。開発者にお伝えください。
@@ -944,7 +944,6 @@
<string name="la_lock_mode_passcode">パスコード入力</string>
<string name="la_auth_failed">認証失敗</string>
<string name="la_enter_app_passcode">パスコードを入力</string>
<string name="cant_delete_user_profile">ユーザープロフィールが削除できません。</string>
<string name="la_mode_system">システム</string>
<string name="change_lock_mode">ロックモードを変更</string>
<string name="v4_6_chinese_spanish_interface">中国語とスペイン語UI</string>
@@ -961,7 +960,7 @@
<string name="read_more_in_user_guide_with_link"><![CDATA[<font color="#0088ff">ユーザーガイド</font>で詳細を見る]]></string>
<string name="simplex_address">SimpleXアドレス</string>
<string name="network_proxy_port">ポート %d</string>
<string name="enter_welcome_message_optional">ウェルカムメッセージを入力…(オプション)</string>
<string name="enter_welcome_message_optional">ウェルカムメッセージを入力…(任意)</string>
<string name="save_settings_question">設定を保存しますか?</string>
<string name="confirm_passcode">パスコードを確認</string>
<string name="la_mode_passcode">パスコード</string>
@@ -973,7 +972,7 @@
<string name="one_time_link_short">使い捨てのリンク</string>
<string name="address_section_title">アドレス</string>
<string name="color_background">背景色</string>
<string name="confirm_password">パスワードを確認</string>
<string name="confirm_password">ご確認のため、再度ご入力ください。</string>
<string name="settings_section_title_experimenta">β機能</string>
<string name="decryption_error">復号化エラー</string>
<string name="button_add_welcome_message">ウェルカムメッセージを追加</string>
@@ -1040,7 +1039,7 @@
<string name="stop_sharing">共有を停止</string>
<string name="invite_friends">友人を招待する</string>
<string name="you_can_create_it_later">後からでも作成できます</string>
<string name="password_to_show">パスワードを表示する</string>
<string name="password_to_show">ここにパスワードを入力してください。</string>
<string name="authentication_cancelled">認証がキャンセルされました</string>
<string name="share_address">アドレスを共有する</string>
<string name="theme_simplex">SimpleX</string>
@@ -1101,20 +1100,18 @@
<string name="downgrade_and_open_chat">ダウングレードしてチャットを開く</string>
<string name="la_please_remember_to_store_password">パスワードを覚えるか、安全に保管してください。失われたパスワードを回復する方法はありません。</string>
<string name="smp_server_test_download_file">ファイルをダウンロード</string>
<string name="you_can_hide_or_mute_user_profile">ユーザープロフィールを非表示またはミュートすることができます(メニューを長押し)。</string>
<string name="you_can_hide_or_mute_user_profile">ユーザープロフィールを非表示またはミュートすることができます(名前を長押し)。</string>
<string name="v4_6_group_moderation">グループのモデレーション</string>
<string name="email_invite_body">こんにちは!
\nSimpleX Chatの招待が届いています: %s</string>
<string name="v4_6_group_welcome_message">グループのウェルカムメッセージ</string>
<string name="tap_to_activate_profile">タップしてプロフィールを有効化する。</string>
<string name="tap_to_activate_profile">タップでプロフィールを切り替え</string>
<string name="profile_password">プロフィールのパスワード</string>
<string name="v4_6_hidden_chat_profiles_descr">チャットのプロフィールをパスワードで保護します!</string>
<string name="group_member_role_observer">オブザーバー</string>
<string name="v5_0_large_files_support_descr">送信者がオンラインになるまでの待ち時間がなく、速い!</string>
<string name="v5_0_app_passcode">アプリのパスコード</string>
<string name="v5_0_app_passcode_descr">システム認証の代わりに設定します。</string>
<string name="should_be_at_least_one_visible_profile">少なくとも1つのユーザープロフィールが表示されている必要があります。</string>
<string name="should_be_at_least_one_profile">少なくとも1つのユーザープロファイルが必要です。</string>
<string name="make_profile_private">プロフィールを非表示にできます!</string>
<string name="relay_server_protects_ip">リレー サーバーは IP アドレスを保護しますが、通話時間は監視されます。</string>
<string name="share_address_with_contacts_question">アドレスを連絡先と共有しますか\?</string>
@@ -1153,16 +1150,16 @@
<string name="mtr_error_different">アプリ/データベースの異なる移行: %s / %s</string>
<string name="user_hide">非表示</string>
<string name="user_unhide">表示にする</string>
<string name="hidden_profile_password">非表示のプロフィール パスワード</string>
<string name="hidden_profile_password">非表示プロフィールのパスワード</string>
<string name="show_dev_options">表示する:</string>
<string name="create_address_and_let_people_connect">人々があなたとつながるためのアドレスを作成します。</string>
<string name="error_setting_address">アドレス設定エラー</string>
<string name="you_can_share_your_address">アドレスをリンクまたは QR コードとして共有すると、誰でもあなたに接続できます。</string>
<string name="you_wont_lose_your_contacts_if_delete_address">後でアドレスを削除しても、連絡先が失われることはありません。</string>
<string name="your_contacts_will_remain_connected">連絡先は接続されたままになります。</string>
<string name="all_your_contacts_will_remain_connected_update_sent">すべての連絡先は接続されたままになります。 プロフィールの更新が連絡先に送信されます。</string>
<string name="your_contacts_will_remain_connected">連絡先との接続がそのまま続きます。</string>
<string name="all_your_contacts_will_remain_connected_update_sent">連絡先との接続がそのまま続きます。 プロフィールの更新が連絡先に共有されます。</string>
<string name="create_simplex_address">SimpleX のアドレスを作成</string>
<string name="share_with_contacts">連絡先と共有する</string>
<string name="share_with_contacts">連絡先に公開する</string>
<string name="profile_update_will_be_sent_to_contacts">プロフィールの更新は連絡先に送信されます。</string>
<string name="dont_create_address">アドレスを作成しない</string>
<string name="email_invite_subject">SimpleXチャットで会話しよう</string>
@@ -1170,7 +1167,7 @@
<string name="save_profile_password">プロフィールのパスワードを保存する</string>
<string name="you_can_share_this_address_with_your_contacts">このアドレスを連絡先と共有して、%s に接続できるようにすることができます。</string>
<string name="save_and_update_group_profile">グループプロフィールの保存と更新</string>
<string name="to_reveal_profile_enter_password">非表示のプロフィールを表示するには、チャット プロフィール ページの検索フィールドに完全なパスワードを入力します。</string>
<string name="to_reveal_profile_enter_password">非表示のプロフィールを戻すには、プロフィールページの検索欄にパスワードを入力します。</string>
<string name="hide_dev_options">非表示 :</string>
<string name="delete_chat_profile">チャット プロフィールを削除する</string>
<string name="delete_profile">プロフィールの削除</string>
@@ -1354,11 +1351,11 @@
<string name="rcv_group_event_3_members_connected">%s, %s と %s は接続中</string>
<string name="in_developing_desc">この機能はまだサポートされていません。次のリリースをお試しください。</string>
<string name="receipts_contacts_enable_keep_overrides">有効にする(設定の優先を維持)</string>
<string name="receipts_groups_disable_keep_overrides">無効にする(グループの設定の優先を維持)</string>
<string name="receipts_groups_disable_keep_overrides">無効にする (グループの上書きを維持)</string>
<string name="receipts_groups_enable_keep_overrides">有効にする(グループの設定の優先を維持)</string>
<string name="receipts_contacts_disable_keep_overrides">無効にする(設定の優先を維持)</string>
<string name="receipts_contacts_disable_keep_overrides">無効化(設定の優先を維持)</string>
<string name="v5_2_disappear_one_message_descr">会話中に無効になっている場合でも。</string>
<string name="v5_2_message_delivery_receipts">メッセージ配信の通知!</string>
<string name="v5_2_message_delivery_receipts">メッセージの配送通知</string>
<string name="delivery_receipts_title">配信通知!</string>
<string name="sending_delivery_receipts_will_be_enabled_all_profiles">配信通知の送信はすべてのチャットプロフィールのすべての連絡先に対して有効になります。</string>
<string name="message_delivery_error_title">メッセージ配信でエラー発生</string>
@@ -1559,4 +1556,43 @@
<string name="no_connected_mobile">未接続のモバイル</string>
<string name="search_or_paste_simplex_link">検索またはSimpleXリンクをペースト</string>
<string name="blocked_item_description">ブロック済</string>
<string name="agent_internal_error_title">内部エラー</string>
<string name="agent_critical_error_title">重大エラー</string>
<string name="failed_to_create_user_invalid_title">表示名が無効です!</string>
<string name="remote_host_was_disconnected_title">切断されました。</string>
<string name="remote_ctrl_was_disconnected_title">切断されました。</string>
<string name="remote_host_disconnected_from"><![CDATA[携帯 <b>%s</b> が次の理由で切断されました: %s]]></string>
<string name="remote_ctrl_disconnected_with_reason">次の理由で切断されました: %s</string>
<string name="remote_ctrl_error_bad_state">PC版との接続が不安定</string>
<string name="remote_host_error_bad_state"><![CDATA[携帯 <b>%s</b> との接続が不安定]]></string>
<string name="remote_ctrl_error_inactive">PC版が非アクティブ</string>
<string name="remote_host_error_bad_version"><![CDATA[携帯版 <b>%s</b> のバージョンがサポートされてません。。両端末のバージョンが同じかどうか、ご確認ください。]]></string>
<string name="remote_ctrl_error_bad_invitation">PC版の招待コードが正しくない</string>
<string name="remote_ctrl_error_busy">PC版が処理中</string>
<string name="remote_ctrl_error_disconnected">PC版が切断されました</string>
<string name="remote_ctrl_error_bad_version">ご利用のPC版のバージョンがサポートされてません。両端末が同じバージョンかどうか、ご確認ください。</string>
<string name="possible_deadlock_title">デッドロック状態</string>
<string name="developer_options_section">開発者向けの設定</string>
<string name="possible_deadlock_desc">処理時間が異常にかかるようです: %1$d 秒。アプリが固まった恐れがあります: %2$s</string>
<string name="remote_host_error_busy"><![CDATA[携帯版 <b>%s</b> がただいま処理中]]></string>
<string name="possible_slow_function_desc">機能の処理時間が以上にかかってます: %1$d 秒: %2$s</string>
<string name="show_internal_errors">内部エラーを表示</string>
<string name="agent_internal_error_desc">開発側にお伝えください:
\n%s</string>
<string name="agent_critical_error_desc">開発側にお伝えください:
\n%s
\n
\nアプリを再起動してください。</string>
<string name="failed_to_create_user_invalid_desc">表示名が無効です。別の名前にしてください。</string>
<string name="remote_host_error_inactive"><![CDATA[携帯版 <b>%s</b> が非アクティブ]]></string>
<string name="remote_host_error_missing"><![CDATA[携帯版 <b>%s</b> が見つかりません]]></string>
<string name="remote_host_error_timeout"><![CDATA[携帯版に接続する段階で時間切れになりました <b>%s</b>]]></string>
<string name="remote_ctrl_error_timeout">PC版に接続する段階で時間切れになりました</string>
<string name="restart_chat_button">チャットを再起動</string>
<string name="remote_host_error_disconnected"><![CDATA[携帯版 <b>%s</b> が切断されました]]></string>
<string name="group_member_status_unknown_short">不明</string>
<string name="past_member_vName">過去のメンバー %1$s</string>
<string name="possible_slow_function_title">遅延が発生した機能</string>
<string name="show_slow_api_calls">遅いAPIコールを表示</string>
<string name="group_member_status_unknown">ステータス不明</string>
</resources>
@@ -111,7 +111,6 @@
<string name="change_member_role_question">그룹 역할을 바꾸시겠습니까\?</string>
<string name="info_row_connection">연결</string>
<string name="users_add">프로필 추가</string>
<string name="cant_delete_user_profile">사용자 프로필을 삭제할 수 없습니다!</string>
<string name="chat_preferences_always">항상</string>
<string name="chat_preferences_contact_allows">대화 상대가 허용함</string>
<string name="contact_preferences">연락처 개별 설정</string>
@@ -826,12 +825,10 @@
<string name="stop_chat_confirmation">멈추기</string>
<string name="snd_group_event_changed_member_role">%s의 역할을 %s로 변경했어요.</string>
<string name="section_title_for_console">콘솔용</string>
<string name="should_be_at_least_one_visible_profile">적어도 하나의 숨겨지지 않은 사용자 프로필이 있어야 해요.</string>
<string name="set_group_preferences">그룹 설정 지정하기</string>
<string name="snd_conn_event_switch_queue_phase_completed_for_member">%s의 주소를 바꿨어요</string>
<string name="snd_conn_event_switch_queue_phase_completed">주소를 바꿨어요</string>
<string name="snd_group_event_group_profile_updated">그룹 프로필 업데이트됨</string>
<string name="should_be_at_least_one_profile">적어도 하나의 사용자 프로필이 있어야 해요.</string>
<string name="smp_servers_test_server">서버 테스트하기</string>
<string name="smp_servers_use_server">서버 사용하기</string>
<string name="smp_servers_use_server_for_new_conn">새로운 대화에 사용</string>
@@ -447,8 +447,6 @@
<string name="group_members_can_send_dms">Grupės nariai gali siųsti tiesiogines žinutes.</string>
<string name="group_members_can_send_disappearing">Grupės nariai gali siųsti išnykstančias žinutes.</string>
<string name="v4_3_improved_privacy_and_security_desc">Slėpti programėlės ekraną paskiausių programėlių sąraše.</string>
<string name="should_be_at_least_one_profile">Turėtų būti bent vienas naudotojo profilis.</string>
<string name="should_be_at_least_one_visible_profile">Turėtų būti matomas bent vienas naudotojo profilis.</string>
<string name="chat_preferences_contact_allows">Adresatas leidžia</string>
<string name="voice_prohibited_in_this_chat">Balso žinutės šiame pokalbyje yra uždraustos.</string>
<string name="v4_4_disappearing_messages_desc">Išsiųstos žinutės bus ištrintos po nustatyto laiko.</string>
@@ -469,7 +467,6 @@
<string name="join_group_button">Prisijungti</string>
<string name="change_verb">Keisti</string>
<string name="conn_stats_section_title_servers">SERVERIAI</string>
<string name="cant_delete_user_profile">Nepavyksta ištrinti naudotojo profilio!</string>
<string name="clear_chat_menu_action">Išvalyti</string>
<string name="unhide_profile">Nebeslėpti profilio</string>
<string name="videos_limit_title">Per daug vaizdo įrašų!</string>
@@ -958,7 +958,6 @@
<string name="you_are_observer">jij bent waarnemer</string>
<string name="language_system">Systeem</string>
<string name="v4_6_audio_video_calls">Audio en video oproepen</string>
<string name="cant_delete_user_profile">Kan gebruikers profiel niet verwijderen!</string>
<string name="confirm_password">Bevestig wachtwoord</string>
<string name="v4_6_chinese_spanish_interface">Chinese en Spaanse interface</string>
<string name="enter_password_to_show">Voer wachtwoord in bij zoeken</string>
@@ -990,12 +989,10 @@
<string name="v4_6_audio_video_calls_descr">Ondersteuning voor bluetooth en andere verbeteringen.</string>
<string name="tap_to_activate_profile">Tik om profiel te activeren.</string>
<string name="v4_6_chinese_spanish_interface_descr">Dank aan de gebruikers – draag bij via Weblate!</string>
<string name="should_be_at_least_one_profile">Er moet ten minste één gebruikers profiel zijn.</string>
<string name="you_can_hide_or_mute_user_profile">U kunt een gebruikers profiel verbergen of dempen - houd het vast voor het menu.</string>
<string name="user_unhide">zichtbaar maken</string>
<string name="user_unmute">Dempen opheffen</string>
<string name="group_welcome_title">Welkomst bericht</string>
<string name="should_be_at_least_one_visible_profile">"Er moet ten minste één zichtbaar gebruikers profiel zijn."</string>
<string name="to_reveal_profile_enter_password">Om uw verborgen profiel te onthullen, voert u een volledig wachtwoord in een zoekveld in op de pagina Uw chat profielen.</string>
<string name="button_welcome_message">Welkomst bericht</string>
<string name="you_will_still_receive_calls_and_ntfs">U ontvangt nog steeds oproepen en meldingen van gedempte profielen wanneer deze actief zijn.</string>
@@ -1555,4 +1552,69 @@
<string name="keep_invitation_link">Bewaar</string>
<string name="tap_to_paste_link">Tik om de link te plakken</string>
<string name="search_or_paste_simplex_link">Zoek of plak de SimpleX link</string>
<string name="chat_is_stopped_you_should_transfer_database">De chat is gestopt. Als u deze database al op een ander apparaat heeft gebruikt, moet u deze terugzetten voordat u met chatten begint.</string>
<string name="start_chat_question">Begin chat?</string>
<string name="show_internal_errors">Toon interne fouten</string>
<string name="agent_critical_error_title">Kritische fout</string>
<string name="agent_internal_error_title">Interne fout</string>
<string name="agent_internal_error_desc">Rapporteer dit alstublieft aan de ontwikkelaars:
\n%s</string>
<string name="agent_critical_error_desc">Rapporteer dit alstublieft aan de ontwikkelaars:
\n%s
\n
\nHet wordt aanbevolen om de app opnieuw te starten.</string>
<string name="remote_ctrl_error_bad_version">Desktop heeft een niet-ondersteunde versie. Zorg ervoor dat u op beide apparaten dezelfde versie gebruikt</string>
<string name="failed_to_create_user_invalid_title">Ongeldige weergavenaam!</string>
<string name="failed_to_create_user_invalid_desc">Deze weergavenaam is ongeldig. Kies een andere naam.</string>
<string name="remote_host_was_disconnected_title">Verbinding gestopt</string>
<string name="remote_ctrl_was_disconnected_title">Verbinding gestopt</string>
<string name="remote_host_disconnected_from"><![CDATA[Verbinding met mobiel <b>%s</b> \u0020is verbroken met als reden: %s]]></string>
<string name="remote_host_error_busy"><![CDATA[Mobiel <b>%s</b> is bezet]]></string>
<string name="remote_host_error_inactive"><![CDATA[Mobiel <b>%s</b> is inactief]]></string>
<string name="remote_host_error_missing"><![CDATA[Mobiel <b>%s</b> ontbreekt]]></string>
<string name="remote_host_error_bad_state"><![CDATA[De verbinding met de mobiel <b>%s</b> is in slechte staat]]></string>
<string name="remote_ctrl_error_disconnected">De verbinding met desktop is verbroken</string>
<string name="possible_deadlock_title">Impasse</string>
<string name="possible_slow_function_desc">Uitvoering van functie duurt te lang: %1$d seconden: %2$s</string>
<string name="possible_slow_function_title">Langzame functie</string>
<string name="developer_options_section">Ontwikkelaars opties</string>
<string name="show_slow_api_calls">Toon langzame API aanroepen</string>
<string name="past_member_vName">Voormalig lid %1$s</string>
<string name="group_member_status_unknown_short">onbekend</string>
<string name="remote_ctrl_disconnected_with_reason">Verbinding verbroken met als reden: %s</string>
<string name="remote_ctrl_error_busy">Desktop is bezet</string>
<string name="remote_ctrl_error_inactive">Desktop is inactief</string>
<string name="remote_host_error_disconnected"><![CDATA[Mobiele verbinding <b>%s</b> is verbroken]]></string>
<string name="restart_chat_button">Chat opnieuw starten</string>
<string name="remote_host_error_timeout"><![CDATA[Time-out bereikt tijdens het verbinden met de mobiel <b>%s</b>]]></string>
<string name="remote_ctrl_error_bad_state">De verbinding met de desktop is in slechte staat</string>
<string name="possible_deadlock_desc">Het uitvoeren van de code duurt te lang: %1$d seconden. Waarschijnlijk is de app vastgelopen: %2$s</string>
<string name="remote_ctrl_error_bad_invitation">Desktop heeft verkeerde uitnodigingscode</string>
<string name="remote_host_error_bad_version"><![CDATA[Mobiel <b>%s</b> heeft een niet-ondersteunde versie. Zorg ervoor dat u op beide apparaten dezelfde versie gebruikt]]></string>
<string name="remote_ctrl_error_timeout">Time-out bereikt tijdens het verbinden met de desktop</string>
<string name="group_member_status_unknown">onbekende status</string>
<string name="v5_5_message_delivery">Verbeterde berichtbezorging</string>
<string name="v5_5_join_group_conversation">Neem deel aan groep gesprekken</string>
<string name="v5_5_simpler_connect_ui">Plak link om te verbinden!</string>
<string name="v5_5_private_notes">Privé notities</string>
<string name="clear_note_folder_warning">Alle berichten worden verwijderd. Dit kan niet ongedaan worden gemaakt!</string>
<string name="info_row_created_at">Gemaakt op</string>
<string name="error_creating_message">Fout bij het maken van een bericht</string>
<string name="v5_5_new_interface_languages">Hongaarse en Turkse gebruikersinterface</string>
<string name="v5_5_join_group_conversation_descr">Recente geschiedenis en verbeterde directory-bot.</string>
<string name="note_folder_local_display_name">Privé notities</string>
<string name="share_text_created_at">Gemaakt op: %s</string>
<string name="profile_update_event_member_name_changed">lid %1$s gewijzigd in %2$s</string>
<string name="profile_update_event_contact_name_changed">contactpersoon %1$s gewijzigd in %2$s</string>
<string name="error_deleting_note_folder">Fout bij verwijderen van privénotities</string>
<string name="clear_note_folder_question">Privénotities verwijderen?</string>
<string name="v5_5_simpler_connect_ui_descr">Zoekbalk accepteert uitnodigingslinks.</string>
<string name="v5_5_private_notes_descr">‐Met versleutelde bestanden en media.</string>
<string name="v5_5_message_delivery_descr">Met verminderd batterijgebruik.</string>
<string name="saved_message_title">Opgeslagen bericht</string>
<string name="profile_update_event_updated_profile">bijgewerkt profiel</string>
<string name="profile_update_event_removed_address">contactadres verwijderd</string>
<string name="profile_update_event_removed_picture">profielfoto verwijderd</string>
<string name="profile_update_event_set_new_address">nieuw contactadres instellen</string>
<string name="profile_update_event_set_new_picture">nieuwe profielfoto instellen</string>
</resources>
@@ -743,7 +743,6 @@
<string name="group_is_decentralized">W pełni zdecentralizowana – widoczna tylko dla członków.</string>
<string name="member_role_will_be_changed_with_invitation">Rola zostanie zmieniona na \"%s\". Członek otrzyma nowe zaproszenie.</string>
<string name="group_welcome_title">Wiadomość powitalna</string>
<string name="cant_delete_user_profile">Nie można usunąć profilu użytkownika!</string>
<string name="users_delete_question">Usunąć profil czatu\?</string>
<string name="users_delete_profile_for">Usuń profil czatu dla</string>
<string name="dont_show_again">Nie pokazuj ponownie</string>
@@ -997,9 +996,7 @@
<string name="simplex_link_contact">Adres kontaktowy SimpleX</string>
<string name="stop_chat_to_export_import_or_delete_chat_database">Zatrzymaj czat, aby wyeksportować, zaimportować lub usunąć bazę danych czatu. Podczas zatrzymania chatu nie będzie można odbierać ani wysyłać wiadomości.</string>
<string name="smp_servers_test_some_failed">Niektóre serwery nie przeszły testu:</string>
<string name="should_be_at_least_one_profile">Powinien istnieć co najmniej jeden profil użytkownika.</string>
<string name="thank_you_for_installing_simplex">Dziękujemy za zainstalowanie SimpleX Chat!</string>
<string name="should_be_at_least_one_visible_profile">Powinien istnieć co najmniej jeden widoczny profil użytkownika.</string>
<string name="moderate_message_will_be_marked_warning">Wiadomość zostanie oznaczona jako moderowana dla wszystkich członków.</string>
<string name="member_role_will_be_changed_with_notification">Rola zostanie zmieniona na \"%s\". Wszyscy w grupie zostaną powiadomieni.</string>
<string name="delete_files_and_media_desc">Tego działania nie można cofnąć - wszystkie odebrane i wysłane pliki oraz media zostaną usunięte. Obrazy o niskiej rozdzielczości pozostaną.</string>
@@ -706,7 +706,6 @@
<string name="no_contacts_to_add">Sem contatos para adicionar</string>
<string name="member_role_will_be_changed_with_notification">A função será alterada para \"%s\". Todos no grupo serão notificados.</string>
<string name="user_mute">Mutar</string>
<string name="should_be_at_least_one_visible_profile">Deve haver pelo menos um perfil de usuário visível.</string>
<string name="only_you_can_send_voice">Somente você pode enviar mensagens de voz.</string>
<string name="only_your_contact_can_send_voice">Somente seu contato pode enviar mensagens de voz.</string>
<string name="prohibit_message_deletion">Proibir a exclusão irreversível de mensagens.</string>
@@ -739,9 +738,7 @@
<string name="incompatible_database_version">Versão do banco de dados incompatível</string>
<string name="button_remove_member">Remover membro</string>
<string name="group_main_profile_sent">Seu perfil de chat será enviado aos membros do grupo</string>
<string name="cant_delete_user_profile">Não é possível excluir o perfil do usuário!</string>
<string name="make_profile_private">Torne o perfil privado!</string>
<string name="should_be_at_least_one_profile">Deve haver pelo menos um perfil de usuário.</string>
<string name="v4_2_security_assessment">Avaliação de segurança</string>
<string name="v4_5_multiple_chat_profiles_descr">Nomes diferentes, avatares e isolamento de transporte.</string>
<string name="v4_2_auto_accept_contact_requests_desc">Com mensagem de boas-vindas opcional.</string>
@@ -239,7 +239,6 @@
<string name="call_on_lock_screen">Chamadas no ecrã de bloqueio:</string>
<string name="alert_title_cant_invite_contacts">Não é possível convidar contatos!</string>
<string name="change_verb">Alterar</string>
<string name="cant_delete_user_profile">Não é possível eliminar o perfil do utilizador!</string>
<string name="feature_cancelled_item">cancelado %s</string>
<string name="cannot_receive_file">Não é possível receber o ficheiro</string>
<string name="icon_descr_cancel_image_preview">Cancelar pré-visualização da imagem</string>
@@ -299,7 +299,8 @@
<string name="connection_you_accepted_will_be_cancelled">Подтвержденное соединение будет отменено!</string>
<!-- Connection Pending Alert Dialogue - ChatListNavLinkView.kt -->
<string name="alert_title_contact_connection_pending">Соединение еще не установлено!</string>
<string name="alert_text_connection_pending_they_need_to_be_online_can_delete_and_retry">Ваш контакт должен быть в сети чтобы установить соединение.\nВы можете отменить соединение и удалить контакт (и попробовать позже с другой ссылкой).</string>
<string name="alert_text_connection_pending_they_need_to_be_online_can_delete_and_retry">Ваш контакт должен быть в сети, чтобы установить соединение.
\nВы можете отменить соединение и удалить контакт (и попробовать позже с другой ссылкой).</string>
<!-- Contact Request Information - ContactRequestView.kt -->
<string name="contact_wants_to_connect_with_you">хочет соединиться с Вами!</string>
<!-- Image Placeholder - ChatInfoImage.kt -->
@@ -487,7 +488,7 @@
<!-- SetNotificationsMode.kt -->
<string name="use_chat">Использовать чат</string>
<!-- MakeConnection -->
<string name="paste_the_link_you_received">Вставить полученную ссылку</string>
<string name="paste_the_link_you_received">Вставьте полученную ссылку</string>
<!-- Call -->
<string name="incoming_video_call">Входящий видеозвонок</string>
<string name="incoming_audio_call">Входящий аудиозвонок</string>
@@ -872,15 +873,15 @@
<string name="feature_enabled_for_contact">включено для контакта</string>
<string name="feature_off">выключено</string>
<string name="feature_received_prohibited">получено, не разрешено</string>
<string name="allow_your_contacts_irreversibly_delete">Разрешить Вашим контактам необратимо удалять отправленные сообщения.</string>
<string name="allow_irreversible_message_deletion_only_if">Разрешить необратимое удаление сообщений, только если Ваш контакт разрешает это Вам.</string>
<string name="allow_your_contacts_irreversibly_delete">Разрешить Вашим контактам необратимо удалять отправленные сообщения. (24 часа)</string>
<string name="allow_irreversible_message_deletion_only_if">Разрешить необратимое удаление сообщений, только если Ваш контакт разрешает это Вам. (24 часа)</string>
<string name="contacts_can_mark_messages_for_deletion">Контакты могут помечать сообщения для удаления; Вы сможете просмотреть их.</string>
<string name="allow_your_contacts_to_send_voice_messages">Разрешить Вашим контактам отправлять голосовые сообщения.</string>
<string name="allow_voice_messages_only_if">Разрешить голосовые сообщения, только если их разрешает Ваш контакт.</string>
<string name="prohibit_sending_voice_messages">Запретить отправлять голосовые сообщений.</string>
<string name="both_you_and_your_contacts_can_delete">Вы и Ваш контакт можете необратимо удалять отправленные сообщения.</string>
<string name="only_you_can_delete_messages">Только Вы можете необратимо удалять сообщения (Ваш контакт может помечать их на удаление).</string>
<string name="only_your_contact_can_delete">Только Ваш контакт может необратимо удалять сообщения (Вы можете помечать их на удаление).</string>
<string name="both_you_and_your_contacts_can_delete">Вы и Ваш контакт можете необратимо удалять отправленные сообщения. (24 часа)</string>
<string name="only_you_can_delete_messages">Только Вы можете необратимо удалять сообщения (Ваш контакт может помечать их на удаление). (24 часа)</string>
<string name="only_your_contact_can_delete">Только Ваш контакт может необратимо удалять сообщения (Вы можете помечать их на удаление). (24 часа)</string>
<string name="message_deletion_prohibited">Необратимое удаление сообщений запрещено в этой группе.</string>
<string name="both_you_and_your_contact_can_send_voice">Вы и Ваш контакт можете отправлять голосовые сообщения.</string>
<string name="only_you_can_send_voice">Только Вы можете отправлять голосовые сообщения.</string>
@@ -888,13 +889,13 @@
<string name="voice_prohibited_in_this_chat">Голосовые сообщения запрещены в этом чате.</string>
<string name="allow_direct_messages">Разрешить посылать прямые сообщения членам группы.</string>
<string name="prohibit_direct_messages">Запретить посылать прямые сообщения членам группы.</string>
<string name="allow_to_delete_messages">Разрешить необратимо удалять отправленные сообщения.</string>
<string name="allow_to_delete_messages">Разрешить необратимо удалять отправленные сообщения. (24 часа)</string>
<string name="prohibit_message_deletion">Запретить необратимое удаление сообщений.</string>
<string name="allow_to_send_voice">Разрешить отправлять голосовые сообщения.</string>
<string name="prohibit_sending_voice">Запретить отправлять голосовые сообщений.</string>
<string name="group_members_can_send_dms">Члены группы могут посылать прямые сообщения.</string>
<string name="direct_messages_are_prohibited_in_chat">Прямые сообщения между членами группы запрещены.</string>
<string name="group_members_can_delete">Члены группы могут необратимо удалять отправленные сообщения.</string>
<string name="group_members_can_delete">Члены группы могут необратимо удалять отправленные сообщения. (24 часа)</string>
<string name="message_deletion_prohibited_in_chat">Необратимое удаление сообщений запрещено в этой группе.</string>
<string name="group_members_can_send_voice">Члены группы могут отправлять голосовые сообщения.</string>
<string name="voice_messages_are_prohibited">Голосовые сообщения запрещены в этой группе.</string>
@@ -1044,8 +1045,6 @@
<string name="v4_6_audio_video_calls">Аудио и видео звонки</string>
<string name="error_saving_user_password">Ошибка при сохранении пароля пользователя</string>
<string name="smp_save_servers_question">Сохранить серверы\?</string>
<string name="should_be_at_least_one_profile">Должен быть хотя бы один профиль пользователя.</string>
<string name="should_be_at_least_one_visible_profile">Должен быть хотя бы один открытый профиль пользователя.</string>
<string name="to_reveal_profile_enter_password">Чтобы показать Ваш скрытый профиль, введите пароль в поле поиска на странице Ваши профили.</string>
<string name="user_unmute">Уведомлять</string>
<string name="group_welcome_title">Приветственное сообщение</string>
@@ -1054,7 +1053,6 @@
<string name="button_welcome_message">Приветственное сообщение</string>
<string name="save_and_update_group_profile">Сохранить сообщение и обновить группу</string>
<string name="muted_when_inactive">Без звука, когда не активный!</string>
<string name="cant_delete_user_profile">Нельзя удалить профиль пользователя!</string>
<string name="enter_password_to_show">Введите пароль в поиске!</string>
<string name="save_profile_password">Сохранить пароль профиля</string>
<string name="v4_6_chinese_spanish_interface">Китайский и Испанский интерфейс</string>
@@ -1575,7 +1573,7 @@
<string name="group_members_n">%s, %s и %d членов группы</string>
<string name="this_device">Это устройство</string>
<string name="unblock_member_button">Разблокировать члена группы</string>
<string name="contact_tap_to_connect">Нажмите чтобы соединиться</string>
<string name="contact_tap_to_connect">Нажмите, чтобы соединиться</string>
<string name="this_device_name">Имя этого устройства</string>
<string name="connect_plan_you_are_already_in_group_vName"><![CDATA[Вы уже состоите в группе <b>%1$s</b>.]]></string>
<string name="connect_plan_this_is_your_own_simplex_address">Это ваш собственный адрес SimpleX!</string>
@@ -1610,4 +1608,98 @@
<string name="disconnect_remote_hosts">Отключить мобильные</string>
<string name="no_connected_mobile">Нет подключённых мобильных</string>
<string name="add_contact_tab">Добавить контакт</string>
<string name="v5_5_private_notes">Личные заметки</string>
<string name="v5_5_join_group_conversation">Присоединяйтесь к разговорам в группах</string>
<string name="v5_5_simpler_connect_ui">Вставьте ссылку, чтобы соединиться!</string>
<string name="v5_5_simpler_connect_ui_descr">Поле поиска поддерживает ссылки-приглашения.</string>
<string name="v5_5_join_group_conversation_descr">История сообщений и улучшенный каталог групп.</string>
<string name="remote_host_error_inactive"><![CDATA[Мобильный <b>%s</b> неактивен]]></string>
<string name="remote_ctrl_error_timeout">Превышено максимальное время соединения с компьютером.</string>
<string name="remote_ctrl_error_disconnected">Компьютер отсоединён</string>
<string name="remote_ctrl_error_bad_invitation">Неверный код приглашения у компьютера</string>
<string name="loading_chats">Загрузка чатов…</string>
<string name="enable_camera_access">Включить доступ к камере</string>
<string name="tap_to_scan">Нажмите, чтобы сканировать</string>
<string name="create_group_button_to_create_new_group"><![CDATA[<b>Создать группу</b>: создать новую группу.]]></string>
<string name="disable_sending_recent_history">Не отправлять историю новым членам.</string>
<string name="enable_sending_recent_history">Отправить до 100 последних сообщений новым членам.</string>
<string name="clear_note_folder_warning">Все сообщения будут удалены - это нельзя отменить!</string>
<string name="camera_not_available">Камера недоступна</string>
<string name="la_app_passcode">Код доступа в приложение</string>
<string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>Добавить контакт</b>: создать новую ссылку-приглашение или подключиться через полученную ссылку.]]></string>
<string name="chat_is_stopped_you_should_transfer_database">Чат остановлен. Если вы уже использовали эту базу данных на другом устройстве, перенесите ее обратно до запуска чата.</string>
<string name="remote_host_was_disconnected_title">Соединение остановлено</string>
<string name="info_row_created_at">Создано</string>
<string name="keep_invitation_link">Оставить</string>
<string name="share_text_created_at">Создано: %s</string>
<string name="remote_host_error_missing"><![CDATA[Мобильный <b>%s</b> отсутствует]]></string>
<string name="or_show_this_qr_code">Или покажите этот код</string>
<string name="agent_internal_error_desc">Пожалуйста, сообщите об этом разработчикам:
\n%s</string>
<string name="developer_options_section">Опции разработчика</string>
<string name="remote_host_disconnected_from"><![CDATA[Отсоединён от мобильного <b>%s</b> по причине: %s]]></string>
<string name="error_creating_message">Ошибка создания сообщения</string>
<string name="error_deleting_note_folder">Ошибка удаления заметки</string>
<string name="v5_5_new_interface_languages">Венгерский и Турецкий интерфейс</string>
<string name="search_or_paste_simplex_link">Искать или вставьте ссылку SimpleX</string>
<string name="code_you_scanned_is_not_simplex_link_qr_code">Этот QR код не является SimpleX-ccылкой.</string>
<string name="v5_5_private_notes_descr">С зашифрованными файлами и медиа.</string>
<string name="v5_5_message_delivery_descr">С уменьшенным потреблением батареи.</string>
<string name="keep_unused_invitation_question">Оставить неиспользованное приглашение?</string>
<string name="v5_5_message_delivery">Улучшенная доставка сообщений</string>
<string name="remote_ctrl_was_disconnected_title">Соединение остановлено</string>
<string name="restart_chat_button">Перезапустить чат</string>
<string name="start_chat_question">Запустить чат?</string>
<string name="note_folder_local_display_name">Личные заметки</string>
<string name="recent_history">Доступ к истории</string>
<string name="recent_history_is_not_sent_to_new_members">История не отправляется новым членам.</string>
<string name="recent_history_is_sent_to_new_members">До 100 последних сообщений отправляются новым членам.</string>
<string name="show_internal_errors">Показывать внутренние ошибки</string>
<string name="remote_ctrl_error_bad_state">Ошибка соединения с компьютером</string>
<string name="remote_host_error_bad_state"><![CDATA[Ошибка соединения с мобильным <b>%s</b>]]></string>
<string name="remote_ctrl_error_busy">Компьютер занят</string>
<string name="remote_ctrl_error_inactive">Компьютер неактивен</string>
<string name="remote_host_error_bad_version"><![CDATA[Версия приложения на мобильном <b>%s</b> не поддерживается. Пожалуйста, установите одинаковую версию на оба устройства.]]></string>
<string name="remote_host_error_busy"><![CDATA[Мобильный <b>%s</b> занят]]></string>
<string name="remote_host_error_disconnected"><![CDATA[Мобильный <b>%s</b> отсоединён]]></string>
<string name="remote_host_error_timeout"><![CDATA[Превышено максимальное время соединения с мобильным <b>%s</b>]]></string>
<string name="agent_critical_error_title">Критическая ошибка</string>
<string name="agent_critical_error_desc">Пожалуйста, сообщите об этом разработчикам:
\n%s
\n
\nРекомендовано перезапустить приложение.</string>
<string name="failed_to_create_user_invalid_title">Ошибка имени!</string>
<string name="failed_to_create_user_invalid_desc">Ошибка имени профиля. Пожалуйста, выберите другое имя.</string>
<string name="the_text_you_pasted_is_not_a_link">Вставленный текст не является SimpleX-ссылкой.</string>
<string name="creating_link">Создаётся ссылка…</string>
<string name="tap_to_paste_link">Нажмите, чтобы вставить ссылку</string>
<string name="invalid_qr_code">Ошибка QR кода</string>
<string name="share_this_1_time_link">Поделиться одноразовой ссылкой-приглашением</string>
<string name="retry_verb">Повторить</string>
<string name="app_was_crashed">Ошибка приложения</string>
<string name="error_showing_message">ошибка отображения сообщения</string>
<string name="error_showing_content">ошибка отображения содержания</string>
<string name="remote_ctrl_disconnected_with_reason">Отсоединён по причине: %s</string>
<string name="possible_deadlock_title">Взаимная блокировка</string>
<string name="possible_deadlock_desc">Выполнение задачи занимает долгое время: %1$d секунд. Возможно, приложение заблокировано: %2$s</string>
<string name="possible_slow_function_desc">Выполнение задачи занимает долгое время: %1$d секунд: %2$s</string>
<string name="possible_slow_function_title">Медленный вызов</string>
<string name="profile_update_event_contact_name_changed">контакт %1$s изменён на %2$s</string>
<string name="profile_update_event_member_name_changed">член %1$s изменился на %2$s</string>
<string name="profile_update_event_removed_address">удалён адрес контакта</string>
<string name="profile_update_event_removed_picture">удалена картинка профиля</string>
<string name="profile_update_event_set_new_address">установлен новый адрес контакта</string>
<string name="profile_update_event_set_new_picture">установлена новая картинка профиля</string>
<string name="profile_update_event_updated_profile">профиль обновлён</string>
<string name="remote_ctrl_error_bad_version">Версия приложения на компьютере не поддерживается. Пожалуйста, установите одинаковую версию на оба устройства.</string>
<string name="agent_internal_error_title">Внутренняя ошибка</string>
<string name="clear_note_folder_question">Очистить личные заметки?</string>
<string name="new_chat">Новый чат</string>
<string name="or_scan_qr_code">Или отсканируйте QR код</string>
<string name="you_can_view_invitation_link_again">Вы можете увидеть ссылку-приглашение снова открыв соединение.</string>
<string name="show_slow_api_calls">Показывать медленные вызовы API</string>
<string name="past_member_vName">Бывший член %1$s</string>
<string name="saved_message_title">Сохраненное сообщение</string>
<string name="group_member_status_unknown_short">неизвестно</string>
<string name="group_member_status_unknown">неизвестный статус</string>
</resources>
@@ -142,7 +142,6 @@
<string name="change_member_role_question">เปลี่ยนบทบาทกลุ่ม\?</string>
<string name="icon_descr_cancel_live_message">ยกเลิกข้อความสด</string>
<string name="feature_cancelled_item">ยกเลิกเรียบร้อยแล้ว %s</string>
<string name="cant_delete_user_profile">ไม่สามารถลบโปรไฟล์ผู้ใช้ได้!</string>
<string name="alert_title_cant_invite_contacts">ไม่สามารถเชิญผู้ติดต่อได้!</string>
<string name="change_verb">เปลี่ยน</string>
<string name="change_database_passphrase_question">เปลี่ยนรหัสผ่านฐานข้อมูล\?</string>
@@ -1213,8 +1212,6 @@
<string name="updating_settings_will_reconnect_client_to_all_servers">การอัปเดตการตั้งค่าจะเชื่อมต่อไคลเอนต์กับเซิร์ฟเวอร์ทั้งหมดอีกครั้ง</string>
<string name="user_unhide">ยกเลิกการซ่อน</string>
<string name="user_unmute">เปิดเสียง</string>
<string name="should_be_at_least_one_profile">ควรมีโปรไฟล์ผู้ใช้อย่างน้อยหนึ่งโปรไฟล์</string>
<string name="should_be_at_least_one_visible_profile">ควรมีอย่างน้อยหนึ่งโปรไฟล์ผู้ใช้ที่มองเห็นได้</string>
<string name="you_can_hide_or_mute_user_profile">คุณสามารถซ่อนหรือปิดเสียงโปรไฟล์ผู้ใช้ - กดค้างไว้เพื่อที่จะแสดงเมนู</string>
<string name="unhide_profile">เลิกซ่อนโปรไฟล์</string>
<string name="chat_preferences_you_allow">คุณอนุญาต</string>
@@ -114,8 +114,6 @@
<string name="save_group_profile">Grup profilini kaydet</string>
<string name="network_option_seconds_label">sn</string>
<string name="network_options_save">Kaydet</string>
<string name="should_be_at_least_one_visible_profile">There should be at least one visible user profile.</string>
<string name="should_be_at_least_one_profile">En az bir kullanıcı profili olmalıdır.</string>
<string name="incognito_info_protects">Gizli mod her farklı kişi için yeni rasgele profil kullanarak gizliliğini korur.</string>
<string name="theme_system">Sistem</string>
<string name="language_system">Sistem</string>
@@ -753,7 +751,6 @@
<string name="invite_to_group_button">Gruba davet edin</string>
<string name="invite_prohibited">Kişi davet edilemiyor!</string>
<string name="button_add_members">Üyeleri davet edin</string>
<string name="cant_delete_user_profile">Kullanıcı profili silinemiyor!</string>
<string name="color_background">Arka plan</string>
<string name="message_deletion_prohibited">Bu sohbette geri alınamaz mesaj silme yasaktır.</string>
<string name="delete_contact_question">Kişiyi sil\?</string>
@@ -517,7 +517,6 @@
<string name="role_in_group">Роль</string>
<string name="conn_level_desc_indirect">непряме (%1$s)</string>
<string name="user_unmute">Відглушити</string>
<string name="should_be_at_least_one_profile">Повинен бути принаймні один профіль користувача.</string>
<string name="make_profile_private">Зробіть профіль приватним!</string>
<string name="feature_offered_item">запропоновано %s</string>
<string name="v4_5_message_draft">Чернетка повідомлення</string>
@@ -900,7 +899,6 @@
<string name="delete_files_and_media_all">Видалити всі файли</string>
<string name="delete_messages_after">Видаляйте повідомлення після</string>
<string name="enable_automatic_deletion_question">Увімкнути автоматичне видалення повідомлень\?</string>
<string name="should_be_at_least_one_visible_profile">Повинен бути принаймні один видимий профіль користувача.</string>
<string name="v4_6_hidden_chat_profiles">Приховані профілі чату</string>
<string name="v4_6_group_welcome_message">Повідомлення вітання групи</string>
<string name="v4_6_chinese_spanish_interface_descr">Дякуємо користувачам – приєднуйтеся через Weblate!</string>
@@ -933,7 +931,6 @@
<string name="icon_descr_group_inactive">Група неактивна</string>
<string name="snd_group_event_member_deleted">ви видалили %1$s</string>
<string name="tap_to_activate_profile">Торкніться для активації профілю.</string>
<string name="cant_delete_user_profile">Не вдається видалити профіль користувача!</string>
<string name="prohibit_sending_voice">Забороняйте надсилання голосових повідомлень.</string>
<string name="group_members_can_send_disappearing">Учасники групи можуть надсилати самознищувальні повідомлення.</string>
<string name="ttl_min">%d хв</string>
@@ -978,7 +978,6 @@
<string name="v4_6_hidden_chat_profiles_descr">使用密码保护您的聊天资料!</string>
<string name="confirm_password">确认密码</string>
<string name="error_updating_user_privacy">更新用户隐私错误</string>
<string name="cant_delete_user_profile">无法删除用户资料!</string>
<string name="error_saving_user_password">保存用户密码错误</string>
<string name="enter_password_to_show">在搜索中输入密码</string>
<string name="v4_6_group_welcome_message">群组欢迎消息</string>
@@ -990,12 +989,10 @@
<string name="to_reveal_profile_enter_password">要显示您的隐藏的个人资料,请在您的聊天个人资料页面的搜索字段中输入完整密码。</string>
<string name="save_welcome_message_question">保存欢迎信息?</string>
<string name="tap_to_activate_profile">点击以激活个人资料。</string>
<string name="should_be_at_least_one_profile">应该至少有一个用户资料。</string>
<string name="user_unhide">取消隐藏</string>
<string name="v4_6_group_welcome_message_descr">设置向新成员显示的消息!</string>
<string name="v4_6_audio_video_calls_descr">支持蓝牙和其他改进。</string>
<string name="v4_6_chinese_spanish_interface_descr">感谢用户——通过 Weblate 做出贡献!</string>
<string name="should_be_at_least_one_visible_profile">应该至少有一个可见的用户资料。</string>
<string name="user_unmute">解除静音</string>
<string name="button_welcome_message">欢迎消息</string>
<string name="you_will_still_receive_calls_and_ntfs">当静音配置文件处于活动状态时,您仍会收到来自静音配置文件的电话和通知。</string>
@@ -1506,7 +1503,7 @@
<string name="v5_4_block_group_members_descr">隐藏不需要的信息。</string>
<string name="v5_4_better_groups">更佳的群组</string>
<string name="v5_4_incognito_groups">匿名群组</string>
<string name="remote_host_was_disconnected_toast"><![CDATA[远程主机 <b>%s</b> 已断开连接]]></string>
<string name="remote_host_was_disconnected_toast"><![CDATA[移动主机 <b>%s</b> 连接断开]]></string>
<string name="v5_4_better_groups_descr">加入速度更快、信息更可靠。</string>
<string name="v5_4_more_things_descr">- 可选择通知已删除的联系人。
\n- 带空格的个人资料名称。
@@ -1569,7 +1566,7 @@
<string name="agent_critical_error_title">严重错误</string>
<string name="restart_chat_button">重启聊天</string>
<string name="show_internal_errors">显示内部错误</string>
<string name="remote_host_disconnected_from"><![CDATA[和移动设备<b>%s</b>的连接已断开,原因是:%s]]></string>
<string name="remote_host_disconnected_from"><![CDATA[和移动主机<b>%s</b>的连接断开,原因是:%s]]></string>
<string name="remote_ctrl_disconnected_with_reason">断连原因:%s</string>
<string name="remote_ctrl_error_timeout">连接到桌面时超时</string>
<string name="remote_ctrl_error_busy">桌面繁忙</string>
@@ -1580,13 +1577,46 @@
<string name="remote_ctrl_error_disconnected">桌面连接已断开</string>
<string name="failed_to_create_user_invalid_title">无效的显示名!</string>
<string name="remote_ctrl_was_disconnected_title">连接停止</string>
<string name="remote_host_error_bad_version"><![CDATA[移动设备 <b>%s</b> 的版本不受支持。请确保两台设备安装的版本相同]]></string>
<string name="remote_host_error_busy"><![CDATA[移动设备 <b>%s</b> 繁忙]]></string>
<string name="remote_host_error_inactive"><![CDATA[移动设备 <b>%s</b>不活跃]]></string>
<string name="remote_host_error_missing"><![CDATA[移动设备 <b>%s</b> 缺失]]></string>
<string name="remote_host_error_disconnected"><![CDATA[未与移动设备<b>%s</b>建立连接]]></string>
<string name="remote_host_error_bad_version"><![CDATA[移动主机 <b>%s</b> 有一个不受支持的版本。请确保两台设备安装的版本相同]]></string>
<string name="remote_host_error_busy"><![CDATA[移动主机 <b>%s</b> 繁忙]]></string>
<string name="remote_host_error_inactive"><![CDATA[移动主机 <b>%s</b>不活跃]]></string>
<string name="remote_host_error_missing"><![CDATA[移动主机 <b>%s</b> 缺失]]></string>
<string name="remote_host_error_disconnected"><![CDATA[移动主机<b>%s</b>连接断开]]></string>
<string name="remote_host_was_disconnected_title">连接停止</string>
<string name="remote_host_error_bad_state"><![CDATA[到移动设备 <b>%s</b>的连接处于糟糕状态]]></string>
<string name="remote_host_error_timeout"><![CDATA[连接到移动设备<b>%s</b>时超时]]></string>
<string name="remote_host_error_bad_state"><![CDATA[到移动主机 <b>%s</b>的连接状态不佳]]></string>
<string name="remote_host_error_timeout"><![CDATA[连接到移动主机<b>%s</b>时超时]]></string>
<string name="failed_to_create_user_invalid_desc">显示名无效。请另选一个名称。</string>
<string name="possible_deadlock_title">死锁</string>
<string name="possible_deadlock_desc">代码执行花费的时间过久:%1$d秒。应用可能卡住了:%2$s</string>
<string name="possible_slow_function_title">慢函数</string>
<string name="show_slow_api_calls">显示缓慢的 API 调用</string>
<string name="past_member_vName">过往成员 %1$s</string>
<string name="group_member_status_unknown_short">未知</string>
<string name="group_member_status_unknown">未知状态</string>
<string name="developer_options_section">开发者选项</string>
<string name="possible_slow_function_desc">函数执行花费的时间过久:%1$d 秒: %2$s</string>
<string name="v5_5_message_delivery">改进了消息传递</string>
<string name="v5_5_join_group_conversation">加入群对话</string>
<string name="v5_5_simpler_connect_ui">粘贴链接以连接!</string>
<string name="v5_5_simpler_connect_ui_descr">搜索栏接受邀请链接。</string>
<string name="v5_5_private_notes_descr">加密的文件和媒体。</string>
<string name="v5_5_message_delivery_descr">降低了电量使用。</string>
<string name="clear_note_folder_warning">所有消息都将被删除 - 这无法被撤销!</string>
<string name="info_row_created_at">创建于</string>
<string name="share_text_created_at">创建于:%s</string>
<string name="v5_5_new_interface_languages">匈牙利语和土耳其语用户界面</string>
<string name="v5_5_private_notes">私密笔记</string>
<string name="v5_5_join_group_conversation_descr">最近历史和改进的目录机器人。</string>
<string name="profile_update_event_contact_name_changed">联系人姓名从 %1$s 改为了 %2$s</string>
<string name="profile_update_event_member_name_changed">成员姓名从 %1$s 改为了 %2$s</string>
<string name="profile_update_event_removed_address">删除了联系地址</string>
<string name="profile_update_event_removed_picture">删除了资料图片</string>
<string name="profile_update_event_set_new_address">设置新的联系地址</string>
<string name="profile_update_event_set_new_picture">设置新的资料图片</string>
<string name="profile_update_event_updated_profile">更新了资料</string>
<string name="error_creating_message">创建消息出错</string>
<string name="error_deleting_note_folder">删除私密笔记出错</string>
<string name="note_folder_local_display_name">私密笔记</string>
<string name="clear_note_folder_question">清除私密笔记?</string>
<string name="saved_message_title">已保存的消息</string>
</resources>
@@ -965,7 +965,6 @@
<string name="button_welcome_message">歡迎訊息</string>
<string name="save_and_update_group_profile">儲存和更新群組配置檔案</string>
<string name="save_welcome_message_question">儲存歡迎訊息?</string>
<string name="cant_delete_user_profile">無法刪除個人檔案!</string>
<string name="user_hide">隱藏</string>
<string name="make_profile_private">將個人資料設為私密!</string>
<string name="v4_6_audio_video_calls">語音和視訊通話</string>
@@ -991,10 +990,8 @@
<string name="v4_6_group_welcome_message_descr">設定向新成員顯示的訊息!</string>
<string name="tap_to_activate_profile">點擊以激活配置檔案。</string>
<string name="v4_6_audio_video_calls_descr">支援藍牙和其他改進。</string>
<string name="should_be_at_least_one_visible_profile">至少要有一個可見的個人檔案。</string>
<string name="group_welcome_title">歡迎訊息</string>
<string name="v4_6_chinese_spanish_interface_descr">感謝用戶-透過 Weblate 做出貢獻!</string>
<string name="should_be_at_least_one_profile">應該至少有一個個人檔案。</string>
<string name="user_unmute">解除靜音</string>
<string name="you_will_still_receive_calls_and_ntfs">當靜音配置檔案處於活動狀態時,你仍會接收來自靜音配置檔案的通話和通知。</string>
<string name="user_unhide">取消隱藏</string>