Merge branch 'dev' into preformance-improvement

pull/541/head
Ryan Zhao 3 years ago
commit daf0705d42

@ -229,7 +229,7 @@ public class ConversationMessageMapping: NSObject {
let indexPtr: UnsafeMutablePointer<UInt> = UnsafeMutablePointer<UInt>.allocate(capacity: 1) let indexPtr: UnsafeMutablePointer<UInt> = UnsafeMutablePointer<UInt>.allocate(capacity: 1)
let wasFound = view.getGroup(nil, index: indexPtr, forKey: uniqueId, inCollection: TSInteraction.collection()) let wasFound = view.getGroup(nil, index: indexPtr, forKey: uniqueId, inCollection: TSInteraction.collection())
guard wasFound else { guard wasFound else {
owsFailDebug("Could not find interaction.") SNLog("Could not find interaction.")
return nil return nil
} }
let index = indexPtr.pointee let index = indexPtr.pointee

@ -2,6 +2,7 @@ import UIKit
import CoreServices import CoreServices
import Photos import Photos
import PhotosUI import PhotosUI
import PromiseKit
import SessionUtilitiesKit import SessionUtilitiesKit
import SignalUtilitiesKit import SignalUtilitiesKit
@ -262,41 +263,48 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc
let linkPreviewDraft = snInputView.linkPreviewInfo?.draft let linkPreviewDraft = snInputView.linkPreviewInfo?.draft
let tsMessage = TSOutgoingMessage.from(message, associatedWith: thread) let tsMessage = TSOutgoingMessage.from(message, associatedWith: thread)
viewModel.appendUnsavedOutgoingTextMessage(tsMessage)
Storage.write(with: { transaction in Storage.write(with: { transaction in
message.linkPreview = VisibleMessage.LinkPreview.from(linkPreviewDraft, using: transaction) let promise: Promise<Void> = self.approveMessageRequestIfNeeded(
}, completion: { [weak self] in for: self.thread,
tsMessage.linkPreview = OWSLinkPreview.from(message.linkPreview) with: transaction,
isNewThread: !oldThreadShouldBeVisible,
Storage.shared.write( timestamp: (sentTimestamp - 1) // Set 1ms earlier as this is used for sorting
with: { transaction in
tsMessage.save(with: transaction as! YapDatabaseReadWriteTransaction)
},
completion: { [weak self] in
// At this point the TSOutgoingMessage should have its link preview set, so we can scroll to the bottom knowing
// the height of the new message cell
self?.scrollToBottom(isAnimated: false)
}
) )
.map { [weak self] _ in
Storage.shared.write( self?.viewModel.appendUnsavedOutgoingTextMessage(tsMessage)
with: { transaction in
self?.approveMessageRequestIfNeeded( Storage.write(with: { transaction in
for: self?.thread, message.linkPreview = VisibleMessage.LinkPreview.from(linkPreviewDraft, using: transaction)
with: (transaction as! YapDatabaseReadWriteTransaction), }, completion: { [weak self] in
isNewThread: !oldThreadShouldBeVisible, tsMessage.linkPreview = OWSLinkPreview.from(message.linkPreview)
timestamp: (sentTimestamp - 1) // Set 1ms earlier as this is used for sorting
Storage.shared.write(
with: { transaction in
tsMessage.save(with: transaction as! YapDatabaseReadWriteTransaction)
},
completion: { [weak self] in
// At this point the TSOutgoingMessage should have its link preview set, so we can scroll to the bottom knowing
// the height of the new message cell
self?.scrollToBottom(isAnimated: false)
}
) )
},
completion: { [weak self] in
Storage.shared.write { transaction in Storage.shared.write { transaction in
MessageSender.send(message, with: [], in: thread, using: transaction as! YapDatabaseReadWriteTransaction) MessageSender.send(message, with: [], in: thread, using: transaction as! YapDatabaseReadWriteTransaction)
} }
self?.handleMessageSent() self?.handleMessageSent()
} })
) }
// Show an error indicating that approving the thread failed
promise.catch(on: DispatchQueue.main) { [weak self] _ in
let alert = UIAlertController(title: "Session", message: "An error occurred when trying to accept this message request", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self?.present(alert, animated: true, completion: nil)
}
promise.retainUntilComplete()
}) })
} }
@ -321,20 +329,18 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc
let oldThreadShouldBeVisible: Bool = thread.shouldBeVisible let oldThreadShouldBeVisible: Bool = thread.shouldBeVisible
let tsMessage = TSOutgoingMessage.from(message, associatedWith: thread) let tsMessage = TSOutgoingMessage.from(message, associatedWith: thread)
Storage.write( Storage.write(with: { transaction in
with: { transaction in let promise: Promise<Void> = self.approveMessageRequestIfNeeded(
tsMessage.save(with: transaction) for: self.thread,
// The new message cell is inserted at this point, but the TSOutgoingMessage doesn't have its attachment yet with: transaction,
}, isNewThread: !oldThreadShouldBeVisible,
completion: { [weak self] in timestamp: (sentTimestamp - 1) // Set 1ms earlier as this is used for sorting
Storage.shared.write( )
.map { [weak self] _ in
Storage.write(
with: { transaction in with: { transaction in
self?.approveMessageRequestIfNeeded( tsMessage.save(with: transaction)
for: self?.thread, // The new message cell is inserted at this point, but the TSOutgoingMessage doesn't have its attachment yet
with: (transaction as! YapDatabaseReadWriteTransaction),
isNewThread: !oldThreadShouldBeVisible,
timestamp: (sentTimestamp - 1) // Set 1ms earlier as this is used for sorting
)
}, },
completion: { [weak self] in completion: { [weak self] in
Storage.write(with: { transaction in Storage.write(with: { transaction in
@ -351,7 +357,16 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc
} }
) )
} }
)
// Show an error indicating that approving the thread failed
promise.catch(on: DispatchQueue.main) { [weak self] _ in
let alert = UIAlertController(title: "Session", message: "An error occurred when trying to accept this message request", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self?.present(alert, animated: true, completion: nil)
}
promise.retainUntilComplete()
})
} }
func handleMessageSent() { func handleMessageSent() {
@ -1098,8 +1113,8 @@ extension ConversationVC: UIDocumentInteractionControllerDelegate {
extension ConversationVC { extension ConversationVC {
fileprivate func approveMessageRequestIfNeeded(for thread: TSThread?, with transaction: YapDatabaseReadWriteTransaction, isNewThread: Bool, timestamp: UInt64) { fileprivate func approveMessageRequestIfNeeded(for thread: TSThread?, with transaction: YapDatabaseReadWriteTransaction, isNewThread: Bool, timestamp: UInt64) -> Promise<Void> {
guard let contactThread: TSContactThread = thread as? TSContactThread else { return } guard let contactThread: TSContactThread = thread as? TSContactThread else { return Promise.value(()) }
// If the contact doesn't exist then we should create it so we can store the 'isApproved' state // If the contact doesn't exist then we should create it so we can store the 'isApproved' state
// (it'll be updated with correct profile info if they accept the message request so this // (it'll be updated with correct profile info if they accept the message request so this
@ -1107,74 +1122,100 @@ extension ConversationVC {
let sessionId: String = contactThread.contactSessionID() let sessionId: String = contactThread.contactSessionID()
let contact: Contact = (Storage.shared.getContact(with: sessionId) ?? Contact(sessionID: sessionId)) let contact: Contact = (Storage.shared.getContact(with: sessionId) ?? Contact(sessionID: sessionId))
if !contact.isApproved { guard !contact.isApproved else { return Promise.value(()) }
// Default 'didApproveMe' to true for the person approving the message request
contact.isApproved = true return Promise.value(())
contact.didApproveMe = (contact.didApproveMe || !isNewThread) .then { [weak self] _ -> Promise<Void> in
Storage.shared.setContact(contact, using: transaction) guard !isNewThread else { return Promise.value(()) }
guard let strongSelf = self else { return Promise(error: MessageSender.Error.noThread) }
// If we aren't creating a new thread (ie. sending a message request) then send a
// messageRequestResponse back to the sender (this allows the sender to know that // If we aren't creating a new thread (ie. sending a message request) then send a
// they have been approved and can now use this contact in closed groups) // messageRequestResponse back to the sender (this allows the sender to know that
if !isNewThread { // they have been approved and can now use this contact in closed groups)
let (promise, seal) = Promise<Void>.pending()
let messageRequestResponse: MessageRequestResponse = MessageRequestResponse( let messageRequestResponse: MessageRequestResponse = MessageRequestResponse(
isApproved: true isApproved: true
) )
messageRequestResponse.sentTimestamp = timestamp messageRequestResponse.sentTimestamp = timestamp
MessageSender.send(messageRequestResponse, in: contactThread, using: transaction) // Show a loading indicator
ModalActivityIndicatorViewController.present(fromViewController: strongSelf, canCancel: false) { _ in
seal.fulfill(())
}
return promise
.then { MessageSender.sendNonDurably(messageRequestResponse, in: contactThread, using: transaction) }
.map { _ in
if self?.presentedViewController is ModalActivityIndicatorViewController {
self?.dismiss(animated: true, completion: nil) // Dismiss the loader
}
}
} }
.map { _ in
// Hide the 'messageRequestView' since the request has been approved and force a config // Default 'didApproveMe' to true for the person approving the message request
// sync to propagate the contact approval state (both must run on the main thread) contact.isApproved = true
DispatchQueue.main.async { [weak self] in contact.didApproveMe = (contact.didApproveMe || !isNewThread)
let messageRequestViewWasVisible: Bool = (self?.messageRequestView.isHidden == false) Storage.shared.setContact(contact, using: transaction)
UIView.animate(withDuration: 0.3) { // Hide the 'messageRequestView' since the request has been approved and force a config
self?.messageRequestView.isHidden = true // sync to propagate the contact approval state (both must run on the main thread)
self?.scrollButtonMessageRequestsBottomConstraint?.isActive = false DispatchQueue.main.async { [weak self] in
self?.scrollButtonBottomConstraint?.isActive = true let messageRequestViewWasVisible: Bool = (self?.messageRequestView.isHidden == false)
UIView.animate(withDuration: 0.3) {
self?.messageRequestView.isHidden = true
self?.scrollButtonMessageRequestsBottomConstraint?.isActive = false
self?.scrollButtonBottomConstraint?.isActive = true
// Update the table content inset and offset to account for the dissapearance of
// the messageRequestsView
if messageRequestViewWasVisible {
let messageRequestsOffset: CGFloat = ((self?.messageRequestView.bounds.height ?? 0) + 16)
let oldContentInset: UIEdgeInsets = (self?.messagesTableView.contentInset ?? UIEdgeInsets.zero)
self?.messagesTableView.contentInset = UIEdgeInsets(
top: 0,
leading: 0,
bottom: max(oldContentInset.bottom - messageRequestsOffset, 0),
trailing: 0
)
}
}
// Update the table content inset and offset to account for the dissapearance of // Update UI
// the messageRequestsView self?.updateNavBarButtons()
if messageRequestViewWasVisible { if let viewControllers: [UIViewController] = self?.navigationController?.viewControllers,
let messageRequestsOffset: CGFloat = ((self?.messageRequestView.bounds.height ?? 0) + 16) let messageRequestsIndex = viewControllers.firstIndex(where: { $0 is MessageRequestsViewController }),
let oldContentInset: UIEdgeInsets = (self?.messagesTableView.contentInset ?? UIEdgeInsets.zero) messageRequestsIndex > 0 {
self?.messagesTableView.contentInset = UIEdgeInsets( var newViewControllers = viewControllers
top: 0, newViewControllers.remove(at: messageRequestsIndex)
leading: 0, self?.navigationController?.setViewControllers(newViewControllers, animated: false)
bottom: max(oldContentInset.bottom - messageRequestsOffset, 0),
trailing: 0
)
} }
}
// Update UI // Send a sync message with the details of the contact
self?.updateNavBarButtons() if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
if let viewControllers: [UIViewController] = self?.navigationController?.viewControllers, appDelegate.forceSyncConfigurationNowIfNeeded(with: transaction).retainUntilComplete()
let messageRequestsIndex = viewControllers.firstIndex(where: { $0 is MessageRequestsViewController }), }
messageRequestsIndex > 0 {
var newViewControllers = viewControllers
newViewControllers.remove(at: messageRequestsIndex)
self?.navigationController?.setViewControllers(newViewControllers, animated: false)
}
// Send a sync message with the details of the contact
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
appDelegate.forceSyncConfigurationNowIfNeeded(with: transaction).retainUntilComplete()
} }
} }
}
} }
@objc func acceptMessageRequest() { @objc func acceptMessageRequest() {
Storage.write { [weak self] transaction in Storage.write { transaction in
self?.approveMessageRequestIfNeeded( let promise: Promise<Void> = self.approveMessageRequestIfNeeded(
for: self?.thread, for: self.thread,
with: transaction, with: transaction,
isNewThread: false, isNewThread: false,
timestamp: NSDate.millisecondTimestamp() timestamp: NSDate.millisecondTimestamp()
) )
// Show an error indicating that approving the thread failed
promise.catch(on: DispatchQueue.main) { [weak self] _ in
let alert = UIAlertController(title: "Session", message: NSLocalizedString("MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE", comment: ""), preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("BUTTON_OK", comment: ""), style: .default, handler: nil))
self?.present(alert, animated: true, completion: nil)
}
promise.retainUntilComplete()
} }
} }

@ -722,9 +722,12 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat
} }
func markAllAsRead() { func markAllAsRead() {
guard !thread.isMessageRequest() else { return }
guard let lastSortID = viewItems.last?.interaction.sortId else { return } guard let lastSortID = viewItems.last?.interaction.sortId else { return }
OWSReadReceiptManager.shared().markAsReadLocally(beforeSortId: lastSortID, thread: thread) OWSReadReceiptManager.shared().markAsReadLocally(
beforeSortId: lastSortID,
thread: thread,
trySendReadReceipt: !thread.isMessageRequest()
)
SSKEnvironment.shared.disappearingMessagesJob.cleanupMessagesWhichFailedToStartExpiringFromNow() SSKEnvironment.shared.disappearingMessagesJob.cleanupMessagesWhichFailedToStartExpiringFromNow()
} }

@ -6,6 +6,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv
private var threads: YapDatabaseViewMappings! private var threads: YapDatabaseViewMappings!
private var threadViewModelCache: [String:ThreadViewModel] = [:] // Thread ID to ThreadViewModel private var threadViewModelCache: [String:ThreadViewModel] = [:] // Thread ID to ThreadViewModel
private var tableViewTopConstraint: NSLayoutConstraint! private var tableViewTopConstraint: NSLayoutConstraint!
private var unreadMessageRequestCount: UInt = 0
private var messageRequestCount: UInt { private var messageRequestCount: UInt {
threads.numberOfItems(inGroup: TSMessageRequestGroup) threads.numberOfItems(inGroup: TSMessageRequestGroup)
@ -203,7 +204,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv
switch indexPath.section { switch indexPath.section {
case 0: case 0:
let cell = tableView.dequeueReusableCell(withIdentifier: MessageRequestsCell.reuseIdentifier) as! MessageRequestsCell let cell = tableView.dequeueReusableCell(withIdentifier: MessageRequestsCell.reuseIdentifier) as! MessageRequestsCell
cell.update(with: Int(messageRequestCount)) cell.update(with: Int(unreadMessageRequestCount))
return cell return cell
default: default:
@ -273,6 +274,14 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv
} }
} }
// Update the number of unread message requests
unreadMessageRequestCount = OWSMessageUtils.sharedManager().unreadMessageRequestCount()
// If there are no unread message requests then hide the message request banner
if unreadMessageRequestCount == 0 {
CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] = true
}
return reload() return reload()
} }
} }
@ -296,11 +305,21 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv
// If we need to unhide the message request row and then re-insert it // If we need to unhide the message request row and then re-insert it
if !messageRequestChanges.isEmpty { if !messageRequestChanges.isEmpty {
if tableView.numberOfRows(inSection: 0) == 1 && Int(messageRequestCount) <= 0 { // Update the number of unread message requests
unreadMessageRequestCount = OWSMessageUtils.sharedManager().unreadMessageRequestCount()
// If there are no unread message requests then hide the message request banner
if unreadMessageRequestCount == 0 && tableView.numberOfRows(inSection: 0) == 1 {
CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] = true
tableView.deleteRows(at: [IndexPath(row: 0, section: 0)], with: .automatic) tableView.deleteRows(at: [IndexPath(row: 0, section: 0)], with: .automatic)
} }
else if tableView.numberOfRows(inSection: 0) == 0 && Int(messageRequestCount) > 0 && !CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] { else {
tableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .automatic) if tableView.numberOfRows(inSection: 0) == 1 && Int(messageRequestCount) <= 0 {
tableView.deleteRows(at: [IndexPath(row: 0, section: 0)], with: .automatic)
}
else if tableView.numberOfRows(inSection: 0) == 0 && Int(messageRequestCount) > 0 && !CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] {
tableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .automatic)
}
} }
} }
@ -554,6 +573,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv
@objc private func openSettings() { @objc private func openSettings() {
let settingsVC = SettingsVC() let settingsVC = SettingsVC()
let navigationController = OWSNavigationController(rootViewController: settingsVC) let navigationController = OWSNavigationController(rootViewController: settingsVC)
navigationController.modalPresentationStyle = .fullScreen
present(navigationController, animated: true, completion: nil) present(navigationController, animated: true, completion: nil)
} }

@ -609,6 +609,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -619,6 +619,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -609,6 +609,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -609,6 +609,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -609,6 +609,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -609,6 +609,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -609,6 +609,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -609,6 +609,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -609,6 +609,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -609,6 +609,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -609,6 +609,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -609,6 +609,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -609,6 +609,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -609,6 +609,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -609,6 +609,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -610,6 +610,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -609,6 +609,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -609,6 +609,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -609,6 +609,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -609,6 +609,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -609,6 +609,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -609,6 +609,7 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "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_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their 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_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";

@ -140,16 +140,16 @@ NS_ASSUME_NONNULL_BEGIN
return YES; return YES;
} }
- (void)markAsReadNowWithSendReadReceipt:(BOOL)sendReadReceipt - (void)markAsReadNowWithTrySendReadReceipt:(BOOL)trySendReadReceipt
transaction:(YapDatabaseReadWriteTransaction *)transaction; transaction:(YapDatabaseReadWriteTransaction *)transaction;
{ {
[self markAsReadAtTimestamp:[NSDate millisecondTimestamp] [self markAsReadAtTimestamp:[NSDate millisecondTimestamp]
sendReadReceipt:sendReadReceipt trySendReadReceipt:trySendReadReceipt
transaction:transaction]; transaction:transaction];
} }
- (void)markAsReadAtTimestamp:(uint64_t)readTimestamp - (void)markAsReadAtTimestamp:(uint64_t)readTimestamp
sendReadReceipt:(BOOL)sendReadReceipt trySendReadReceipt:(BOOL)trySendReadReceipt
transaction:(YapDatabaseReadWriteTransaction *)transaction; transaction:(YapDatabaseReadWriteTransaction *)transaction;
{ {
if (_read && readTimestamp >= self.expireStartedAt) { if (_read && readTimestamp >= self.expireStartedAt) {
@ -174,7 +174,7 @@ NS_ASSUME_NONNULL_BEGIN
expirationStartedAt:readTimestamp expirationStartedAt:readTimestamp
transaction:transaction]; transaction:transaction];
if (sendReadReceipt) { if (trySendReadReceipt) {
[OWSReadReceiptManager.sharedManager messageWasReadLocally:self]; [OWSReadReceiptManager.sharedManager messageWasReadLocally:self];
} }
} }

@ -134,7 +134,7 @@ NSUInteger TSInfoMessageSchemaVersion = 1;
} }
- (void)markAsReadAtTimestamp:(uint64_t)readTimestamp - (void)markAsReadAtTimestamp:(uint64_t)readTimestamp
sendReadReceipt:(BOOL)sendReadReceipt trySendReadReceipt:(BOOL)trySendReadReceipt
transaction:(YapDatabaseReadWriteTransaction *)transaction transaction:(YapDatabaseReadWriteTransaction *)transaction
{ {
if (_read) { if (_read) {
@ -144,7 +144,7 @@ NSUInteger TSInfoMessageSchemaVersion = 1;
_read = YES; _read = YES;
[self saveWithTransaction:transaction]; [self saveWithTransaction:transaction];
// Ignore sendReadReceipt, it doesn't apply to info messages. // Ignore trySendReadReceipt, it doesn't apply to info messages.
} }
@end @end

@ -390,7 +390,7 @@ extension MessageReceiver {
if let tsOutgoingMessage = TSMessage.fetch(uniqueId: tsMessageID, transaction: transaction) as? TSOutgoingMessage, if let tsOutgoingMessage = TSMessage.fetch(uniqueId: tsMessageID, transaction: transaction) as? TSOutgoingMessage,
let thread = TSThread.fetch(uniqueId: threadID, transaction: transaction) { let thread = TSThread.fetch(uniqueId: threadID, transaction: transaction) {
// Mark previous messages as read if there is a sync message // Mark previous messages as read if there is a sync message
OWSReadReceiptManager.shared().markAsReadLocally(beforeSortId: tsOutgoingMessage.sortId, thread: thread) OWSReadReceiptManager.shared().markAsReadLocally(beforeSortId: tsOutgoingMessage.sortId, thread: thread, trySendReadReceipt: true)
} }
// Update the contact's approval status of the current user if needed (if we are getting messages from // Update the contact's approval status of the current user if needed (if we are getting messages from

@ -45,7 +45,7 @@ extern NSString *const kIncomingMessageMarkedAsReadNotification;
// This method can be called from any thread. // This method can be called from any thread.
- (void)messageWasReadLocally:(TSIncomingMessage *)message; - (void)messageWasReadLocally:(TSIncomingMessage *)message;
- (void)markAsReadLocallyBeforeSortId:(uint64_t)sortId thread:(TSThread *)thread; - (void)markAsReadLocallyBeforeSortId:(uint64_t)sortId thread:(TSThread *)thread trySendReadReceipt:(BOOL)trySendReadReceipt;
#pragma mark - Settings #pragma mark - Settings

@ -180,13 +180,13 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE
#pragma mark - Mark as Read Locally #pragma mark - Mark as Read Locally
- (void)markAsReadLocallyBeforeSortId:(uint64_t)sortId thread:(TSThread *)thread - (void)markAsReadLocallyBeforeSortId:(uint64_t)sortId thread:(TSThread *)thread trySendReadReceipt:(BOOL)trySendReadReceipt
{ {
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { [LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self markAsReadBeforeSortId:sortId [self markAsReadBeforeSortId:sortId
thread:thread thread:thread
readTimestamp:[NSDate millisecondTimestamp] readTimestamp:[NSDate millisecondTimestamp]
wasLocal:YES trySendReadReceipt:trySendReadReceipt
transaction:transaction]; transaction:transaction];
}]; }];
} }
@ -254,7 +254,7 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE
- (void)markAsReadBeforeSortId:(uint64_t)sortId - (void)markAsReadBeforeSortId:(uint64_t)sortId
thread:(TSThread *)thread thread:(TSThread *)thread
readTimestamp:(uint64_t)readTimestamp readTimestamp:(uint64_t)readTimestamp
wasLocal:(BOOL)wasLocal trySendReadReceipt:(BOOL)trySendReadReceipt
transaction:(YapDatabaseReadWriteTransaction *)transaction transaction:(YapDatabaseReadWriteTransaction *)transaction
{ {
NSMutableArray<id<OWSReadTracking>> *newlyReadList = [NSMutableArray new]; NSMutableArray<id<OWSReadTracking>> *newlyReadList = [NSMutableArray new];
@ -285,7 +285,7 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE
} }
for (id<OWSReadTracking> readItem in newlyReadList) { for (id<OWSReadTracking> readItem in newlyReadList) {
[readItem markAsReadAtTimestamp:readTimestamp sendReadReceipt:wasLocal transaction:transaction]; [readItem markAsReadAtTimestamp:readTimestamp trySendReadReceipt:trySendReadReceipt transaction:transaction];
} }
// Update unread mention. // Update unread mention.

@ -29,7 +29,7 @@ NS_ASSUME_NONNULL_BEGIN
* Used both for *responding* to a remote read receipt and in response to the local user's activity. * Used both for *responding* to a remote read receipt and in response to the local user's activity.
*/ */
- (void)markAsReadAtTimestamp:(uint64_t)readTimestamp - (void)markAsReadAtTimestamp:(uint64_t)readTimestamp
sendReadReceipt:(BOOL)sendReadReceipt trySendReadReceipt:(BOOL)trySendReadReceipt
transaction:(YapDatabaseReadWriteTransaction *)transaction; transaction:(YapDatabaseReadWriteTransaction *)transaction;
@end @end

@ -288,7 +288,7 @@ BOOL IsNoteToSelfEnabled(void)
- (void)markAllAsReadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction - (void)markAllAsReadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
{ {
for (id<OWSReadTracking> message in [self unseenMessagesWithTransaction:transaction]) { for (id<OWSReadTracking> message in [self unseenMessagesWithTransaction:transaction]) {
[message markAsReadAtTimestamp:[NSDate ows_millisecondTimeStamp] sendReadReceipt:YES transaction:transaction]; [message markAsReadAtTimestamp:[NSDate ows_millisecondTimeStamp] trySendReadReceipt:YES transaction:transaction];
} }
// Update unread mention. // Update unread mention.

@ -16,6 +16,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (instancetype)sharedManager; + (instancetype)sharedManager;
- (NSUInteger)unreadMessagesCount; - (NSUInteger)unreadMessagesCount;
- (NSUInteger)unreadMessageRequestCount;
- (NSUInteger)unreadMessagesCountExcept:(TSThread *)thread; - (NSUInteger)unreadMessagesCountExcept:(TSThread *)thread;
- (void)updateApplicationBadgeCount; - (void)updateApplicationBadgeCount;

@ -112,6 +112,38 @@ NS_ASSUME_NONNULL_BEGIN
return numberOfItems; return numberOfItems;
} }
- (NSUInteger)unreadMessageRequestCount {
__block NSUInteger count = 0;
[LKStorage readWithBlock:^(YapDatabaseReadTransaction *transaction) {
YapDatabaseViewTransaction *unreadMessages = [transaction ext:TSUnreadDatabaseViewExtensionName];
NSArray<NSString *> *allGroups = [unreadMessages allGroups];
// FIXME: Confusingly, `allGroups` includes contact threads as well
for (NSString *groupID in allGroups) {
TSThread *thread = [TSThread fetchObjectWithUniqueID:groupID transaction:transaction];
// Only increase the count for message requests
if (!thread.isMessageRequest) { continue; }
[unreadMessages enumerateKeysAndObjectsInGroup:groupID
usingBlock:^(NSString *collection, NSString *key, id object, NSUInteger index, BOOL *stop) {
if (![object conformsToProtocol:@protocol(OWSReadTracking)]) {
return;
}
id<OWSReadTracking> unread = (id<OWSReadTracking>)object;
if (unread.read) {
NSLog(@"Found an already read message in the * unread * messages list.");
return;
}
count += 1;
*stop = YES;
}];
}
}];
return count;
}
- (NSUInteger)unreadMessagesCountExcept:(TSThread *)thread - (NSUInteger)unreadMessagesCountExcept:(TSThread *)thread
{ {
__block NSUInteger numberOfItems; __block NSUInteger numberOfItems;

@ -25,8 +25,6 @@ public class ModalActivityIndicatorViewController: OWSViewController {
return result return result
}() }()
var presentTimer: Timer?
var wasDimissed: Bool = false var wasDimissed: Bool = false
// MARK: Initializers // MARK: Initializers
@ -127,41 +125,7 @@ public class ModalActivityIndicatorViewController: OWSViewController {
self.spinner.startAnimating() self.spinner.startAnimating()
// Hide the the modal and wait for a second before revealing it, // Fade in the modal
// to avoid "blipping" in the modal during short blocking operations.
//
// NOTE: It will still intercept user interactions while hidden, as it
// should.
let kPresentationDelaySeconds = TimeInterval(1)
self.presentTimer?.invalidate()
self.presentTimer = Timer.weakScheduledTimer(withTimeInterval: kPresentationDelaySeconds, target: self, selector: #selector(presentTimerFired), userInfo: nil, repeats: false)
}
public override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
clearTimer()
}
public override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
self.spinner.stopAnimating()
clearTimer()
}
private func clearTimer() {
self.presentTimer?.invalidate()
self.presentTimer = nil
}
@objc func presentTimerFired() {
AssertIsOnMainThread()
clearTimer()
// Fade in the modal.
UIView.animate(withDuration: 0.35) { UIView.animate(withDuration: 0.35) {
self.view.layer.opacity = 1.0 self.view.layer.opacity = 1.0
} }

Loading…
Cancel
Save