Fixed bugs raised by QA

Added some missing localised strings
Prevented 'Read' and 'Typing' indicators from functioning on Message Requests
Prevented link previews on the first message of a message request
Added a confirmation alert when trying to clear all message requests
Added a confirmation alert when trying to delete a message request
Added an empty state to the MessageRequestsViewController
Updated the back behaviour of the ConversationVC to behave more nicely with approving/declining message requests
Updated the OWSBlockingManager to also update the stored contacts 'isBlocked' flag to match
pull/559/head
Morgan Pretty 2 years ago
parent 999d4a1082
commit 3639a21bc8

@ -36,6 +36,13 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc
UIView.animate(withDuration: 0.25, animations: {
self.blockedBanner.alpha = 0
}, completion: { _ in
if let contact: Contact = Storage.shared.getContact(with: publicKey) {
Storage.shared.write { transaction in
contact.isBlocked = false
Storage.shared.setContact(contact, using: transaction)
}
}
OWSBlockingManager.shared().removeBlockedPhoneNumber(publicKey)
})
}
@ -1062,6 +1069,23 @@ extension ConversationVC: UIDocumentInteractionControllerDelegate {
// MARK: - Message Request Actions
extension ConversationVC {
@objc func handleBackPressed() {
// If this thread started as a message request but isn't one anymore then we want to skip the
// `MessageRequestsViewController` when going back
guard
threadStartedAsMessageRequest,
!thread.isMessageRequest(),
let viewControllers: [UIViewController] = navigationController?.viewControllers,
let messageRequestsIndex = viewControllers.firstIndex(where: { $0 is MessageRequestsViewController }),
messageRequestsIndex > 0
else {
navigationController?.popViewController(animated: true)
return
}
navigationController?.popToViewController(viewControllers[messageRequestsIndex - 1], animated: true)
}
fileprivate func approveMessageRequestIfNeeded(for thread: TSThread?, with transaction: YapDatabaseReadWriteTransaction, isNewThread: Bool, timestamp: UInt64) {
guard let contactThread: TSContactThread = thread as? TSContactThread else { return }
@ -1115,41 +1139,60 @@ extension ConversationVC {
@objc func deleteMessageRequest() {
guard let uniqueId: String = thread.uniqueId else { return }
Storage.write(
with: { [weak self] transaction in
Storage.shared.cancelPendingMessageSendJobs(for: uniqueId, using: transaction)
// Update the contact
if let contactThread: TSContactThread = self?.thread as? TSContactThread {
let sessionId: String = contactThread.contactSessionID()
let alertVC: UIAlertController = UIAlertController(title: NSLocalizedString("MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON", comment: ""), message: nil, preferredStyle: .actionSheet)
alertVC.addAction(UIAlertAction(title: NSLocalizedString("TXT_DELETE_TITLE", comment: ""), style: .destructive) { _ in
// Delete the request
Storage.write(
with: { [weak self] transaction in
Storage.shared.cancelPendingMessageSendJobs(for: uniqueId, using: transaction)
if let contact: Contact = Storage.shared.getContact(with: sessionId) {
contact.isApproved = false
contact.isBlocked = true
Storage.shared.setContact(contact, using: transaction)
// Update the contact
if let contactThread: TSContactThread = self?.thread as? TSContactThread {
let sessionId: String = contactThread.contactSessionID()
if let contact: Contact = Storage.shared.getContact(with: sessionId) {
contact.isApproved = false
contact.isBlocked = true
// Note: We set this to true so the current user will be able to send a
// message to the person who originally sent them the message request in
// the future if they unblock them
contact.didApproveMe = true
Storage.shared.setContact(contact, using: transaction)
}
}
}
// Delete all thread content
self?.thread.removeAllThreadInteractions(with: transaction)
self?.thread.remove(with: transaction)
},
completion: { [weak self] in
// Block the contact
if let sessionId: String = (self?.thread as? TSContactThread)?.contactSessionID(), !OWSBlockingManager.shared().isRecipientIdBlocked(sessionId) {
OWSBlockingManager.shared().addBlockedPhoneNumber(sessionId)
}
// Force a config sync and pop to the previous screen (both must run on the main thread)
DispatchQueue.main.async {
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
appDelegate.forceSyncConfigurationNowIfNeeded().retainUntilComplete()
// Delete all thread content
self?.thread.removeAllThreadInteractions(with: transaction)
self?.thread.remove(with: transaction)
},
completion: { [weak self] in
// Block the contact
if let sessionId: String = (self?.thread as? TSContactThread)?.contactSessionID(), !OWSBlockingManager.shared().isRecipientIdBlocked(sessionId) {
// Stop observing the `BlockListDidChange` notification (we are about to pop the screen
// so showing the banner just looks buggy)
if let strongSelf = self {
NotificationCenter.default.removeObserver(strongSelf, name: NSNotification.Name(rawValue: kNSNotificationName_BlockListDidChange), object: nil)
}
OWSBlockingManager.shared().addBlockedPhoneNumber(sessionId)
}
self?.navigationController?.popViewController(animated: true)
// Force a config sync and pop to the previous screen (both must run on the main thread)
DispatchQueue.main.async {
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
appDelegate.forceSyncConfigurationNowIfNeeded().retainUntilComplete()
}
self?.navigationController?.popViewController(animated: true)
}
}
}
)
)
})
alertVC.addAction(UIAlertAction(title: NSLocalizedString("TXT_CANCEL_TITLE", comment: ""), style: .cancel, handler: nil))
self.present(alertVC, animated: true, completion: nil)
}
}

@ -8,6 +8,7 @@ import SessionUIKit
final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversationSettingsViewDelegate, ConversationSearchControllerDelegate, UITableViewDataSource, UITableViewDelegate {
let isUnsendRequestsEnabled = true // Set to true once unsend requests are done on all platforms
let thread: TSThread
let threadStartedAsMessageRequest: Bool
let focusedMessageID: String? // This is used for global search
var focusedMessageIndexPath: IndexPath?
var unreadViewItems: [ConversationViewItem] = []
@ -271,6 +272,7 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat
// MARK: Lifecycle
init(thread: TSThread, focusedMessageID: String? = nil) {
self.thread = thread
self.threadStartedAsMessageRequest = thread.isMessageRequest()
self.focusedMessageID = focusedMessageID
super.init(nibName: nil, bundle: nil)
var unreadCount: UInt = 0
@ -378,7 +380,7 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat
self.snInputView.setEnabledMessageTypes(
(thread.isNoteToSelf() || contact?.didApproveMe == true || thread.isMessageRequest() ?
.all :
(contact != nil ? .none : .textOnly)
(contact != nil && thread.shouldBeVisible ? .none : .textOnly)
),
message: "MESSAGE_REQUESTS_DISABLED_INPUT".localized()
)
@ -459,11 +461,14 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat
}
// MARK: Updating
func updateNavBarButtons() {
navigationItem.hidesBackButton = isShowingSearchUI
if isShowingSearchUI {
navigationItem.leftBarButtonItem = nil
navigationItem.rightBarButtonItems = []
} else {
navigationItem.leftBarButtonItem = UIViewController.createOWSBackButton(withTarget: self, selector: #selector(handleBackPressed))
let rightBarButtonItem: UIBarButtonItem
if thread is TSContactThread {
let size = Values.verySmallProfilePictureSize
@ -635,7 +640,7 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat
self.snInputView.setEnabledMessageTypes(
(thread.isNoteToSelf() || contact?.didApproveMe == true || thread.isMessageRequest() ?
.all :
(contact != nil ? .none : .textOnly)
(contact != nil && thread.shouldBeVisible ? .none : .textOnly)
),
message: "MESSAGE_REQUESTS_DISABLED_INPUT".localized()
)
@ -705,6 +710,7 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat
}
func markAllAsRead() {
guard !thread.isMessageRequest() else { return }
guard let lastSortID = viewItems.last?.interaction.sortId else { return }
OWSReadReceiptManager.shared().markAsReadLocally(beforeSortId: lastSortID, thread: thread)
SSKEnvironment.shared.disappearingMessagesJob.cleanupMessagesWhichFailedToStartExpiringFromNow()

@ -205,6 +205,9 @@ final class InputView : UIView, InputViewButtonDelegate, InputTextViewDelegate,
}
private func autoGenerateLinkPreviewIfPossible() {
// Don't allow link previews on 'none' or 'textOnly' input
guard enabledMessageTypes == .all else { return }
// Suggest that the user enable link previews if they haven't already and we haven't
// told them about link previews yet
let text = inputTextView.text!

@ -40,6 +40,20 @@ class MessageRequestsViewController: BaseVC, UITableViewDelegate, UITableViewDat
return result
}()
private lazy var emptyStateLabel: UILabel = {
let result: UILabel = UILabel()
result.translatesAutoresizingMaskIntoConstraints = false
result.isUserInteractionEnabled = false
result.font = UIFont.systemFont(ofSize: Values.smallFontSize)
result.text = NSLocalizedString("MESSAGE_REQUESTS_EMPTY_TEXT", comment: "")
result.textColor = Colors.text
result.textAlignment = .center
result.numberOfLines = 0
result.isHidden = true
return result
}()
private lazy var fadeView: UIView = {
let result: UIView = UIView()
result.translatesAutoresizingMaskIntoConstraints = false
@ -62,6 +76,7 @@ class MessageRequestsViewController: BaseVC, UITableViewDelegate, UITableViewDat
.toImage(isDarkMode: isDarkMode),
for: .highlighted
)
result.isHidden = true
result.layer.cornerRadius = (NewConversationButtonSet.collapsedButtonSize / 2)
result.layer.borderColor = Colors.destructive.cgColor
result.layer.borderWidth = 1.5
@ -84,6 +99,7 @@ class MessageRequestsViewController: BaseVC, UITableViewDelegate, UITableViewDat
// Add the UI (MUST be done after the thread freeze so the 'tableView' creation and setting
// the dataSource has the correct data)
view.addSubview(tableView)
view.addSubview(emptyStateLabel)
view.addSubview(fadeView)
view.addSubview(clearAllButton)
@ -135,6 +151,11 @@ class MessageRequestsViewController: BaseVC, UITableViewDelegate, UITableViewDat
tableView.rightAnchor.constraint(equalTo: view.rightAnchor),
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
emptyStateLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: Values.massiveSpacing),
emptyStateLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: Values.mediumSpacing),
emptyStateLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -Values.mediumSpacing),
emptyStateLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
fadeView.topAnchor.constraint(equalTo: view.topAnchor, constant: (0.15 * view.bounds.height)),
fadeView.leftAnchor.constraint(equalTo: view.leftAnchor),
fadeView.rightAnchor.constraint(equalTo: view.rightAnchor),
@ -173,6 +194,8 @@ class MessageRequestsViewController: BaseVC, UITableViewDelegate, UITableViewDat
threadViewModelCache.removeAll()
tableView.reloadData()
clearAllButton.isHidden = (messageRequestCount == 0)
emptyStateLabel.isHidden = (messageRequestCount != 0)
emptyStateLabel.isHidden = (messageRequestCount != 0)
}
@objc private func handleYapDatabaseModifiedNotification(_ yapDatabase: YapDatabase) {
@ -245,6 +268,7 @@ class MessageRequestsViewController: BaseVC, UITableViewDelegate, UITableViewDat
tableView.endUpdates()
clearAllButton.isHidden = (messageRequestCount == 0)
emptyStateLabel.isHidden = (messageRequestCount != 0)
}
@objc private func handleProfileDidChangeNotification(_ notification: Notification) {
@ -282,17 +306,7 @@ class MessageRequestsViewController: BaseVC, UITableViewDelegate, UITableViewDat
guard let thread = self.thread(at: indexPath.row) else { return [] }
let delete = UITableViewRowAction(style: .destructive, title: NSLocalizedString("TXT_DELETE_TITLE", comment: "")) { [weak self] _, _ in
var message = NSLocalizedString("CONVERSATION_DELETE_CONFIRMATION_ALERT_MESSAGE", comment: "")
if let thread = thread as? TSGroupThread, thread.isClosedGroup, thread.groupModel.groupAdminIds.contains(getUserHexEncodedPublicKey()) {
message = NSLocalizedString("admin_group_leave_warning", comment: "")
}
let alert = UIAlertController(title: NSLocalizedString("CONVERSATION_DELETE_CONFIRMATION_ALERT_TITLE", comment: ""), message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("TXT_DELETE_TITLE", comment: ""), style: .destructive) { [weak self] _ in
self?.delete(thread)
})
alert.addAction(UIAlertAction(title: NSLocalizedString("TXT_CANCEL_TITLE", comment: ""), style: .default) { _ in })
guard let self = self else { return }
self.present(alert, animated: true, completion: nil)
self?.delete(thread)
}
delete.backgroundColor = Colors.destructive
@ -332,62 +346,73 @@ class MessageRequestsViewController: BaseVC, UITableViewDelegate, UITableViewDat
let threads: [TSThread] = (0..<threadCount).compactMap { self.thread(at: $0) }
var needsSync: Bool = false
Storage.write(
with: { [weak self] transaction in
threads.forEach { thread in
if let uniqueId: String = thread.uniqueId {
Storage.shared.cancelPendingMessageSendJobs(for: uniqueId, using: transaction)
}
self?.updateContactAndThread(thread: thread, with: transaction) { threadNeedsSync in
if threadNeedsSync {
needsSync = true
let alertVC: UIAlertController = UIAlertController(title: NSLocalizedString("MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE", comment: ""), message: nil, preferredStyle: .actionSheet)
alertVC.addAction(UIAlertAction(title: NSLocalizedString("MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON", comment: ""), style: .destructive) { _ in
// Clear the requests
Storage.write(
with: { [weak self] transaction in
threads.forEach { thread in
if let uniqueId: String = thread.uniqueId {
Storage.shared.cancelPendingMessageSendJobs(for: uniqueId, using: transaction)
}
self?.updateContactAndThread(thread: thread, with: transaction) { threadNeedsSync in
if threadNeedsSync {
needsSync = true
}
}
}
}
},
completion: {
// Block all the contacts
threads.forEach { thread in
if let sessionId: String = (thread as? TSContactThread)?.contactSessionID(), !OWSBlockingManager.shared().isRecipientIdBlocked(sessionId) {
OWSBlockingManager.shared().addBlockedPhoneNumber(sessionId)
},
completion: {
// Block all the contacts
threads.forEach { thread in
if let sessionId: String = (thread as? TSContactThread)?.contactSessionID(), !OWSBlockingManager.shared().isRecipientIdBlocked(sessionId) {
OWSBlockingManager.shared().addBlockedPhoneNumber(sessionId)
}
}
}
// Force a config sync (must run on the main thread)
if needsSync {
DispatchQueue.main.async {
(UIApplication.shared.delegate as? AppDelegate)?
.forceSyncConfigurationNowIfNeeded()
.retainUntilComplete()
// Force a config sync (must run on the main thread)
if needsSync {
DispatchQueue.main.async {
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
appDelegate.forceSyncConfigurationNowIfNeeded().retainUntilComplete()
}
}
}
}
}
)
)
})
alertVC.addAction(UIAlertAction(title: NSLocalizedString("TXT_CANCEL_TITLE", comment: ""), style: .cancel, handler: nil))
self.present(alertVC, animated: true, completion: nil)
}
private func delete(_ thread: TSThread) {
guard let uniqueId: String = thread.uniqueId else { return }
Storage.write(
with: { [weak self] transaction in
Storage.shared.cancelPendingMessageSendJobs(for: uniqueId, using: transaction)
self?.updateContactAndThread(thread: thread, with: transaction)
},
completion: {
// Block the contact
if let sessionId: String = (thread as? TSContactThread)?.contactSessionID(), !OWSBlockingManager.shared().isRecipientIdBlocked(sessionId) {
OWSBlockingManager.shared().addBlockedPhoneNumber(sessionId)
}
// Force a config sync (must run on the main thread)
DispatchQueue.main.async {
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
appDelegate.forceSyncConfigurationNowIfNeeded().retainUntilComplete()
let alertVC: UIAlertController = UIAlertController(title: NSLocalizedString("MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON", comment: ""), message: nil, preferredStyle: .actionSheet)
alertVC.addAction(UIAlertAction(title: NSLocalizedString("TXT_DELETE_TITLE", comment: ""), style: .destructive) { _ in
Storage.write(
with: { [weak self] transaction in
Storage.shared.cancelPendingMessageSendJobs(for: uniqueId, using: transaction)
self?.updateContactAndThread(thread: thread, with: transaction)
},
completion: {
// Block the contact
if let sessionId: String = (thread as? TSContactThread)?.contactSessionID(), !OWSBlockingManager.shared().isRecipientIdBlocked(sessionId) {
OWSBlockingManager.shared().addBlockedPhoneNumber(sessionId)
}
// Force a config sync (must run on the main thread)
DispatchQueue.main.async {
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
appDelegate.forceSyncConfigurationNowIfNeeded().retainUntilComplete()
}
}
}
}
)
)
})
alertVC.addAction(UIAlertAction(title: NSLocalizedString("TXT_CANCEL_TITLE", comment: ""), style: .cancel, handler: nil))
self.present(alertVC, animated: true, completion: nil)
}
// MARK: - Convenience

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ wurde blockiert.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Benutzer blockiert";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ wurde freigegeben.";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "Vorhandene Mitglieder können dich jetzt wieder zur Gruppe hinzufügen.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Blockierte Benutzer können dich nicht mehr anrufen oder dir Nachrichten senden.";
/* Label for generic done button. */
@ -598,7 +602,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ has been blocked.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "User Blocked";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ has been unblocked.";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "Existing members can now add you to the group again.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Blocked users will not be able to call you or send you messages.";
/* Label for generic done button. */
@ -608,7 +612,11 @@
"SEARCH_SECTION_RECENT" = "Recent";
"RECENT_SEARCH_LAST_MESSAGE_DATETIME" = "last message: %@";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ ha sido bloqueado.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Usuario Bloqueado";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ ha sido desbloqueado.";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "Los miembros pueden añadirte de nuevo al grupo.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Los contactos bloqueados no podrán llamarte ni enviarte mensajes.";
/* Label for generic done button. */
@ -598,7 +602,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -99,7 +99,11 @@
/* The message format of the 'conversation blocked' alert. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ has been blocked.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "User Blocked";
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "کاربر مسدود شده است";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ از حالت مسدودی خارج شد.";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "اعضای موجود می‌توانند شما را دوباره به گروه اضافه کنند.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "کاربری که مسدود شده است، امکان تماس یا ارسال پیام به شما را ندارد.";
/* Label for generic done button. */
@ -598,7 +602,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ on estetty.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Käyttäjä estetty";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ esto on poistettu.";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "Ryhmän jäsenet voivat nyt lisätä sinut takaisin ryhmään.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Estetyt käyttäjät eivät voi soittaa sinulle tai lähettää sinulle viestejä.";
/* Label for generic done button. */
@ -598,7 +602,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ a été bloqué.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Utilisateur Bloqué";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ a été débloqué.";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "Les membres actuels peuvent désormais vous ajouter au groupe de nouveau.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Les utilisateurs bloqués ne pourront ni vous appeler ni vous envoyer des messages.";
/* Label for generic done button. */
@ -598,7 +602,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ को ब्लॉक कर दिया गया है";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "यूजर ब्लॉक किया हुआ है";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ has been unblocked.";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "Existing members can now add you to the group again.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "अवरुद्ध उपयोगकर्ता आपको कॉल नहीं कर पाएंगे या आपको संदेश नहीं भेज पाएंगे।";
/* Label for generic done button. */
@ -598,7 +602,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ je blokiran.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Korisnik blokiran";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ je deblokiran.";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "Sadašnji članovi sada vas mogu dodati u grupu.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Blokirani korisnici neće vas moći nazvati niti poslati poruke.";
/* Label for generic done button. */
@ -598,7 +602,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ telah diblokir.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Pengguna diblokir";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ telah dibuka blokirnya";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "Existing members can now add you to the group again.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Pengguna terblokir tidak bisa menghubungi atau mengirimkan pesan kepada Anda.";
/* Label for generic done button. */
@ -598,7 +602,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ è stato bloccato.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Utente bloccato";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ buvo atblokuota(-as).";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "Dabar, esami dalyviai gali ir vėl pridėti jus į grupę.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Gli utenti bloccati non potranno chiamarti o inviarti messaggi.";
/* Label for generic done button. */
@ -598,7 +602,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@はブロックされました。";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "ユーザがブロックされました";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ のブロックは解除されています。";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "既存のメンバーは、あなたをグループに再加入させることができます。";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "ブロックされたユーザは、あなたにメッセージや通話を発信することができなくなります。";
/* Label for generic done button. */
@ -598,7 +602,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ is geblokkeerd.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Gebruiker Geblokkeerd";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ is gedeblokkeerd.";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "Bestaande leden kunnen je nu opnieuw toevoegen aan de groep.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Geblokkeerde gebruikers zijn niet in staat om u te bellen of berichten te sturen.";
/* Label for generic done button. */
@ -598,7 +602,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ został zablokowany.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Użytkownik zablokowany";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "Odblokowano %@.";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "Istniejący członkowie mogą teraz ponownie dodać Cię do grupy.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Zablokowani użytkownicy nie będą mogli do Ciebie dzwonić ani wysyłać Ci wiadomości.";
/* Label for generic done button. */
@ -598,7 +602,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ foi bloqueado.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Usuário Bloqueado";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "Você desbloqueou %@.";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "Membros existentes podem te adicionar ap grupo novamente.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Você não receberá mais ligações e mensagens de quem bloquear.";
/* Label for generic done button. */
@ -598,7 +602,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "Пользователь %@ был заблокирован.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Пользователь заблокирован";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ был(-a) разблокирован(-a).";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "Теперь участники группы могут снова добавить вас в группу.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Заблокированные пользователи не смогут звонить или отправлять сообщения Вам.";
/* Label for generic done button. */
@ -598,7 +602,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ has been blocked.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "User Blocked";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "Oseba %@ je bila odblokirana";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "Existing members can now add you to the group again.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Blocked users will not be able to call you or send you messages.";
/* Label for generic done button. */
@ -599,7 +603,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ bol/a zablokovaný/á.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Používateľ blokovaný";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ has been unblocked.";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "Existing members can now add you to the group again.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Blokovaný používateľ vám nebude mocť volať ani posielať správy.";
/* Label for generic done button. */
@ -598,7 +602,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ har blockerats.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Användare blockerad";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@har blivit avblockerad.";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "Befintliga medlemmar kan nu lägga dig till gruppen igen.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Blockerade användare kommer inte att kunna ringa dig eller skicka meddelanden.";
/* Label for generic done button. */
@ -598,7 +602,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ บล็อกแล้ว";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "คนบล็อกแล้ว";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ has been unblocked.";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "Existing members can now add you to the group again.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "คนที่บล็อกแล้วส่งข้อความและโทรมาหาไม่ได้";
/* Label for generic done button. */
@ -598,7 +602,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ has been blocked.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "User Blocked";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ has been unblocked.";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "Existing members can now add you to the group again.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Blocked users will not be able to call you or send you messages.";
/* Label for generic done button. */
@ -598,7 +602,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "已封鎖 %@。";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "使用者已封鎖";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ has been unblocked.";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "Existing members can now add you to the group again.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "被您封鎖的使用者將無法傳送訊息與撥打電話給您";
/* Label for generic done button. */
@ -598,7 +602,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -100,6 +100,10 @@
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "已屏蔽 %@。";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "用户已屏蔽";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "已取消屏蔽 %@。";
/* Alert body after unblocking a group. */
"BLOCK_LIST_VIEW_UNBLOCKED_GROUP_ALERT_BODY" = "现有成员可再次将您加入群组。";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "被屏蔽的用户将无法向您发起通话,或发送消息。";
/* Label for generic done button. */
@ -598,7 +602,11 @@
"dark_mode_theme" = "Dark";
"light_mode_theme" = "Light";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_DISABLED_INPUT" = "Your message request is currently pending.";

@ -12,6 +12,7 @@
#import "TSGroupThread.h"
#import "YapDatabaseConnection+OWS.h"
#import <SessionMessagingKit/SessionMessagingKit-Swift.h>
#import <SessionUtilitiesKit/SessionUtilitiesKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
@ -250,7 +251,27 @@ NSString *const kOWSBlockingManager_SyncedBlockedGroupIdsKey = @"kOWSBlockingMan
forKey:kOWSBlockingManager_BlockedGroupMapKey
inCollection:kOWSBlockingManager_BlockListCollection];
// Update the contact blocked state (so sync'ing won't be busted)
NSMutableArray<SNContact *> *contactsToUpdate = [[NSMutableArray alloc] init];
[[[LKStorage shared] getAllContacts] enumerateObjectsUsingBlock:^(SNContact * _Nonnull obj, BOOL * _Nonnull stop) {
// If the blocked flag doesn't match then add it to the array to be saved
BOOL contactInBlockedList = [blockedPhoneNumbers containsObject:obj.sessionID];
if (obj.isBlocked != contactInBlockedList) {
obj.isBlocked = contactInBlockedList;
[contactsToUpdate addObject:obj];
}
}];
if ([contactsToUpdate count] > 0) {
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction * _Nonnull transaction) {
[contactsToUpdate enumerateObjectsUsingBlock:^(SNContact * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[[LKStorage shared] setContact:obj usingTransaction:transaction];
}];
}];
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (sendSyncMessage) {

@ -221,17 +221,26 @@ extension MessageReceiver {
let thread = TSContactThread.getOrCreateThread(withContactSessionID: sessionID, transaction: transaction)
thread.shouldBeVisible = true
thread.save(with: transaction)
// Make sure to sync the contact blocked state
if contact.isBlocked != OWSBlockingManager.shared().isRecipientIdBlocked(contact.sessionID) {
if contact.isBlocked {
OWSBlockingManager.shared().addBlockedPhoneNumber(contact.sessionID)
}
else {
OWSBlockingManager.shared().removeBlockedPhoneNumber(contact.sessionID)
}
// Contacts blocked state
// FIXME: 'OWSBlockingManager' manages it's own dbConnection and transactions so we have to dispatch this to prevent deadlocks
DispatchQueue.global(qos: .background).async {
for contactInfo in message.contacts {
let sessionID = contactInfo.publicKey!
let contact = Contact(sessionID: sessionID)
if contact.isBlocked != OWSBlockingManager.shared().isRecipientIdBlocked(contact.sessionID) {
if contact.isBlocked {
OWSBlockingManager.shared().addBlockedPhoneNumber(contact.sessionID)
}
else {
OWSBlockingManager.shared().removeBlockedPhoneNumber(contact.sessionID)
}
}
}
}
// Closed groups
let allClosedGroupPublicKeys = storage.getUserClosedGroupPublicKeys()
for closedGroup in message.closedGroups {

@ -86,7 +86,7 @@ public class TypingIndicatorsImpl : NSObject, TypingIndicators {
@objc
public func didStartTypingOutgoingInput(inThread thread: TSThread) {
guard let outgoingIndicators = ensureOutgoingIndicators(forThread: thread) else {
guard let outgoingIndicators = ensureOutgoingIndicators(forThread: thread), !thread.isMessageRequest() else {
return
}
outgoingIndicators.didStartTypingOutgoingInput()
@ -94,7 +94,7 @@ public class TypingIndicatorsImpl : NSObject, TypingIndicators {
@objc
public func didStopTypingOutgoingInput(inThread thread: TSThread) {
guard let outgoingIndicators = ensureOutgoingIndicators(forThread: thread) else {
guard let outgoingIndicators = ensureOutgoingIndicators(forThread: thread), !thread.isMessageRequest() else {
return
}
outgoingIndicators.didStopTypingOutgoingInput()

Loading…
Cancel
Save