Merge pull request #531 from RyanRory/1.11.19
1.11.19 bug fixes and improvements
This commit is contained in:
commit
2a26eda36b
|
@ -27,6 +27,7 @@ DerivedData
|
|||
*.ipa
|
||||
*.xcuserstate
|
||||
Index/
|
||||
Session-Turn-Server
|
||||
|
||||
# CocoaPods
|
||||
Pods
|
||||
|
|
|
@ -762,6 +762,8 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc
|
|||
requestMicrophonePermissionIfNeeded() { [weak self] in
|
||||
self?.cancelVoiceMessageRecording()
|
||||
}
|
||||
// Keep screen on
|
||||
UIApplication.shared.isIdleTimerDisabled = false
|
||||
guard AVAudioSession.sharedInstance().recordPermission == .granted else { return }
|
||||
// Cancel any current audio playback
|
||||
audioPlayer?.stop()
|
||||
|
@ -810,6 +812,7 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc
|
|||
}
|
||||
|
||||
func endVoiceMessageRecording() {
|
||||
UIApplication.shared.isIdleTimerDisabled = true
|
||||
// Hide the UI
|
||||
snInputView.hideVoiceMessageUI()
|
||||
// Cancel the timer
|
||||
|
|
|
@ -593,7 +593,11 @@ class PhotoCaptureOutputAdaptee: NSObject, ImageCaptureOutput {
|
|||
|
||||
@available(iOS 11.0, *)
|
||||
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
|
||||
let data = photo.fileDataRepresentation()!
|
||||
var data = photo.fileDataRepresentation()!
|
||||
// Call normalized here to fix the orientation
|
||||
if let srcImage = UIImage(data: data) {
|
||||
data = srcImage.normalized().jpegData(compressionQuality: 1.0)!
|
||||
}
|
||||
DispatchQueue.main.async {
|
||||
self.delegate?.captureOutputDidFinishProcessing(photoData: data, error: error)
|
||||
}
|
||||
|
|
|
@ -740,7 +740,6 @@ static NSTimeInterval launchStartedAt;
|
|||
- (LKAppMode)getCurrentAppMode
|
||||
{
|
||||
LKAppMode appMode = [self getAppModeOrSystemDefault];
|
||||
UIWindow *window = UIApplication.sharedApplication.keyWindow;
|
||||
return appMode;
|
||||
}
|
||||
|
||||
|
|
|
@ -572,7 +572,8 @@
|
|||
"DISMISS_BUTTON_TEXT" = "Dismiss";
|
||||
/* Button text which opens the settings app */
|
||||
"OPEN_SETTINGS_BUTTON" = "Settings";
|
||||
"APN_Message" = "You've got a new message";
|
||||
"APN_Message" = "You've got a new message.";
|
||||
"APN_Collapsed_Messages" = "You've got %@ new messages.";
|
||||
"system_mode_theme" = "System";
|
||||
"dark_mode_theme" = "Dark";
|
||||
"light_mode_theme" = "Light";
|
||||
|
|
|
@ -37,6 +37,7 @@ struct AppNotificationUserInfoKey {
|
|||
static let threadId = "Signal.AppNotificationsUserInfoKey.threadId"
|
||||
static let callBackNumber = "Signal.AppNotificationsUserInfoKey.callBackNumber"
|
||||
static let localCallId = "Signal.AppNotificationsUserInfoKey.localCallId"
|
||||
static let threadNotificationCounter = "Session.AppNotificationsUserInfoKey.threadNotificationCounter"
|
||||
}
|
||||
|
||||
extension AppNotificationCategory {
|
||||
|
@ -80,9 +81,9 @@ extension AppNotificationAction {
|
|||
}
|
||||
}
|
||||
|
||||
// Delay notification of incoming messages when it's likely to be read by a linked device to
|
||||
// avoid notifying a user on their phone while a conversation is actively happening on desktop.
|
||||
let kNotificationDelayForRemoteRead: TimeInterval = 5
|
||||
// Delay notification of incoming messages when it's a background polling to
|
||||
// avoid too many notifications fired at the same time
|
||||
let kNotificationDelayForBackgroumdPoll: TimeInterval = 5
|
||||
|
||||
let kAudioNotificationsThrottleCount = 2
|
||||
let kAudioNotificationsThrottleInterval: TimeInterval = 5
|
||||
|
@ -157,9 +158,12 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
|
|||
|
||||
public func notifyUser(for incomingMessage: TSIncomingMessage, in thread: TSThread, transaction: YapDatabaseReadTransaction) {
|
||||
|
||||
guard !thread.isMuted else {
|
||||
return
|
||||
}
|
||||
guard !thread.isMuted else { return }
|
||||
guard let threadId = thread.uniqueId else { return }
|
||||
|
||||
let identifier: String = incomingMessage.notificationIdentifier ?? UUID().uuidString
|
||||
|
||||
let isBackgroudPoll = identifier == threadId
|
||||
|
||||
// While batch processing, some of the necessary changes have not been commited.
|
||||
let rawMessageText = incomingMessage.previewText(with: transaction)
|
||||
|
@ -194,13 +198,13 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
|
|||
if groupName.count < 1 {
|
||||
groupName = MessageStrings.newGroupDefaultTitle
|
||||
}
|
||||
notificationTitle = String(format: NotificationStrings.incomingGroupMessageTitleFormat,
|
||||
senderName,
|
||||
groupName)
|
||||
notificationTitle = isBackgroudPoll ? groupName : String(format: NotificationStrings.incomingGroupMessageTitleFormat, senderName, groupName)
|
||||
default:
|
||||
owsFailDebug("unexpected thread: \(thread)")
|
||||
return
|
||||
}
|
||||
default:
|
||||
notificationTitle = "Session"
|
||||
}
|
||||
|
||||
var notificationBody: String?
|
||||
|
@ -209,24 +213,19 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
|
|||
notificationBody = NotificationStrings.incomingMessageBody
|
||||
case .namePreview:
|
||||
notificationBody = messageText
|
||||
}
|
||||
|
||||
guard let threadId = thread.uniqueId else {
|
||||
owsFailDebug("threadId was unexpectedly nil")
|
||||
return
|
||||
default:
|
||||
notificationBody = NotificationStrings.incomingMessageBody
|
||||
}
|
||||
|
||||
assert((notificationBody ?? notificationTitle) != nil)
|
||||
|
||||
// Don't reply from lockscreen if anyone in this conversation is
|
||||
// "no longer verified".
|
||||
var category = AppNotificationCategory.incomingMessage
|
||||
let category = AppNotificationCategory.incomingMessage
|
||||
|
||||
let userInfo = [
|
||||
AppNotificationUserInfoKey.threadId: threadId
|
||||
]
|
||||
|
||||
let identifier: String = incomingMessage.notificationIdentifier ?? UUID().uuidString
|
||||
|
||||
DispatchQueue.main.async {
|
||||
notificationBody = MentionUtilities.highlightMentions(in: notificationBody!, threadID: thread.uniqueId!)
|
||||
|
@ -247,6 +246,8 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
|
|||
notificationTitle = nil
|
||||
case .nameNoPreview, .namePreview:
|
||||
notificationTitle = thread.name()
|
||||
default:
|
||||
notificationTitle = nil
|
||||
}
|
||||
|
||||
let notificationBody = NotificationStrings.failedToSendBody
|
||||
|
|
|
@ -96,17 +96,18 @@ extension UserNotificationPresenterAdaptee: NotificationPresenterAdaptee {
|
|||
let content = UNMutableNotificationContent()
|
||||
content.categoryIdentifier = category.identifier
|
||||
content.userInfo = userInfo
|
||||
let isReplacingNotification = replacingIdentifier != nil
|
||||
var isBackgroudPoll = false
|
||||
if let threadIdentifier = userInfo[AppNotificationUserInfoKey.threadId] as? String {
|
||||
content.threadIdentifier = threadIdentifier
|
||||
isBackgroudPoll = replacingIdentifier == threadIdentifier
|
||||
}
|
||||
let isAppActive = UIApplication.shared.applicationState == .active
|
||||
if let sound = sound, sound != OWSSound.none {
|
||||
content.sound = sound.notificationSound(isQuiet: isAppActive)
|
||||
}
|
||||
|
||||
var notificationIdentifier: String = UUID().uuidString
|
||||
if let replacingIdentifier = replacingIdentifier {
|
||||
notificationIdentifier = replacingIdentifier
|
||||
Logger.debug("replacing notification with identifier: \(notificationIdentifier)")
|
||||
cancelNotification(identifier: notificationIdentifier)
|
||||
}
|
||||
|
||||
let notificationIdentifier = isReplacingNotification ? replacingIdentifier! : UUID().uuidString
|
||||
|
||||
if shouldPresentNotification(category: category, userInfo: userInfo) {
|
||||
if let displayableTitle = title?.filterForDisplay {
|
||||
|
@ -119,10 +120,26 @@ extension UserNotificationPresenterAdaptee: NotificationPresenterAdaptee {
|
|||
// Play sound and vibrate, but without a `body` no banner will show.
|
||||
Logger.debug("supressing notification body")
|
||||
}
|
||||
|
||||
let trigger: UNNotificationTrigger?
|
||||
if isBackgroudPoll {
|
||||
trigger = UNTimeIntervalNotificationTrigger(timeInterval: kNotificationDelayForBackgroumdPoll, repeats: false)
|
||||
let numberOfNotifications: Int
|
||||
if let lastRequest = notifications[notificationIdentifier], let counter = lastRequest.content.userInfo[AppNotificationUserInfoKey.threadNotificationCounter] as? Int {
|
||||
numberOfNotifications = counter + 1
|
||||
content.body = String(format: NotificationStrings.incomingCollapsedMessagesBody, "\(numberOfNotifications)")
|
||||
} else {
|
||||
numberOfNotifications = 1
|
||||
}
|
||||
content.userInfo[AppNotificationUserInfoKey.threadNotificationCounter] = numberOfNotifications
|
||||
} else {
|
||||
trigger = nil
|
||||
}
|
||||
|
||||
let request = UNNotificationRequest(identifier: notificationIdentifier, content: content, trigger: nil)
|
||||
let request = UNNotificationRequest(identifier: notificationIdentifier, content: content, trigger: trigger)
|
||||
|
||||
Logger.debug("presenting notification with identifier: \(notificationIdentifier)")
|
||||
if isReplacingNotification { cancelNotification(identifier: notificationIdentifier) }
|
||||
notificationCenter.add(request)
|
||||
notifications[notificationIdentifier] = request
|
||||
}
|
||||
|
|
|
@ -90,7 +90,9 @@ class BaseVC : UIViewController {
|
|||
}
|
||||
|
||||
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
|
||||
NotificationCenter.default.post(name: .appModeChanged, object: nil)
|
||||
if LKAppModeUtilities.isSystemDefault {
|
||||
NotificationCenter.default.post(name: .appModeChanged, object: nil)
|
||||
}
|
||||
}
|
||||
|
||||
@objc internal func handleAppModeChangedNotification(_ notification: Notification) {
|
||||
|
|
|
@ -28,6 +28,7 @@ extension Storage {
|
|||
let thread = TSThread.fetch(uniqueId: threadID, transaction: transaction) else { return nil }
|
||||
let tsMessage: TSMessage
|
||||
if message.sender == getUserPublicKey() {
|
||||
if let _ = TSOutgoingMessage.find(withTimestamp: message.sentTimestamp!) { return nil }
|
||||
let tsOutgoingMessage = TSOutgoingMessage.from(message, associatedWith: thread, using: transaction)
|
||||
var recipients: [String] = []
|
||||
if let syncTarget = message.syncTarget {
|
||||
|
|
|
@ -342,7 +342,9 @@ extension MessageReceiver {
|
|||
// Notify the user if needed
|
||||
guard (isMainAppAndActive || isBackgroundPoll), let tsIncomingMessage = TSMessage.fetch(uniqueId: tsMessageID, transaction: transaction) as? TSIncomingMessage,
|
||||
let thread = TSThread.fetch(uniqueId: threadID, transaction: transaction) else { return tsMessageID }
|
||||
tsIncomingMessage.setNotificationIdentifier(UUID().uuidString, transaction: transaction)
|
||||
// Use the same identifier for notifications when in backgroud polling to prevent spam
|
||||
let notificationIdentifier = isBackgroundPoll ? thread.uniqueId : UUID().uuidString
|
||||
tsIncomingMessage.setNotificationIdentifier(notificationIdentifier, transaction: transaction)
|
||||
DispatchQueue.main.async {
|
||||
Storage.read { transaction in
|
||||
SSKEnvironment.shared.notificationsManager!.notifyUser(for: tsIncomingMessage, in: thread, transaction: transaction)
|
||||
|
|
|
@ -116,8 +116,6 @@ public final class MessageSender : NSObject {
|
|||
if message.sentTimestamp == nil { // Visible messages will already have their sent timestamp set
|
||||
message.sentTimestamp = NSDate.millisecondTimestamp()
|
||||
}
|
||||
// Ignore future self-sends
|
||||
Storage.shared.addReceivedMessageTimestamp(message.sentTimestamp!, using: transaction)
|
||||
message.sender = userPublicKey
|
||||
switch destination {
|
||||
case .contact(let publicKey): message.recipient = publicKey
|
||||
|
@ -268,8 +266,6 @@ public final class MessageSender : NSObject {
|
|||
if message.sentTimestamp == nil { // Visible messages will already have their sent timestamp set
|
||||
message.sentTimestamp = NSDate.millisecondTimestamp()
|
||||
}
|
||||
// Ignore future self-sends
|
||||
Storage.shared.addReceivedMessageTimestamp(message.sentTimestamp!, using: transaction)
|
||||
message.sender = storage.getUserPublicKey()
|
||||
switch destination {
|
||||
case .contact(_): preconditionFailure()
|
||||
|
@ -366,7 +362,11 @@ public final class MessageSender : NSObject {
|
|||
let userPublicKey = getUserHexEncodedPublicKey()
|
||||
if case .contact(let publicKey) = destination, !isSyncMessage {
|
||||
if let message = message as? VisibleMessage { message.syncTarget = publicKey }
|
||||
if let message = message as? ExpirationTimerUpdate { message.syncTarget = publicKey }
|
||||
if let message = message as? ExpirationTimerUpdate {
|
||||
message.syncTarget = publicKey
|
||||
// Prevent the same ExpirationTimerUpdate to be handled twice
|
||||
Storage.shared.addReceivedMessageTimestamp(message.sentTimestamp!, using: transaction)
|
||||
}
|
||||
// FIXME: Make this a job
|
||||
sendToSnodeDestination(.contact(publicKey: userPublicKey), message: message, using: transaction, isSyncMessage: true).retainUntilComplete()
|
||||
}
|
||||
|
|
|
@ -166,7 +166,7 @@ public class ImageEditorCanvasView: UIView {
|
|||
// of code simplicity. We could modify the image layer's
|
||||
// transform to handle the normalization, which would
|
||||
// have perf benefits.
|
||||
return srcImage.normalized()
|
||||
return srcImage
|
||||
}
|
||||
|
||||
// MARK: - Content
|
||||
|
|
|
@ -50,6 +50,9 @@ public class NotificationStrings: NSObject {
|
|||
|
||||
@objc
|
||||
static public let incomingMessageBody = NSLocalizedString("APN_Message", comment: "notification body")
|
||||
|
||||
@objc
|
||||
static public let incomingCollapsedMessagesBody = NSLocalizedString("APN_Collapsed_Messages", comment: "collapsed notification body for background polling")
|
||||
|
||||
@objc
|
||||
static public let incomingGroupMessageTitleFormat = NSLocalizedString("NEW_GROUP_MESSAGE_NOTIFICATION_TITLE", comment: "notification title. Embeds {{author name}} and {{group name}}")
|
||||
|
|
Loading…
Reference in New Issue