ios: notification preview mode, show connection entity notification (#781)
* ios: notification preview mode, show connection entity notification * prepare connection entity notification as best attempt
This commit is contained in:
committed by
GitHub
parent
36dc66d5d5
commit
ab6301c3e9
@@ -33,7 +33,7 @@ final class ChatModel: ObservableObject {
|
||||
@Published var savedToken: DeviceToken?
|
||||
@Published var tokenStatus: NtfTknStatus?
|
||||
@Published var notificationMode = NotificationsMode.off
|
||||
@Published var notificationPreview: NotificationPreviewMode? = .message
|
||||
@Published var notificationPreview: NotificationPreviewMode? = ntfPreviewModeGroupDefault.get()
|
||||
// current WebRTC call
|
||||
@Published var callInvitations: Dictionary<ChatId, RcvCallInvitation> = [:]
|
||||
@Published var activeCall: Call?
|
||||
|
||||
@@ -136,12 +136,11 @@ class NtfManager: NSObject, UNUserNotificationCenterDelegate, ObservableObject {
|
||||
intentIdentifiers: [],
|
||||
hiddenPreviewsBodyPlaceholder: NSLocalizedString("Incoming call", comment: "notification")
|
||||
),
|
||||
// TODO remove
|
||||
UNNotificationCategory(
|
||||
identifier: ntfCategoryCheckingMessages,
|
||||
identifier: ntfCategoryConnectionEvent,
|
||||
actions: [],
|
||||
intentIdentifiers: [],
|
||||
hiddenPreviewsBodyPlaceholder: NSLocalizedString("Checking new messages...", comment: "notification")
|
||||
hiddenPreviewsBodyPlaceholder: NSLocalizedString("SimpleX encrypted message or connection event", comment: "notification")
|
||||
)
|
||||
])
|
||||
}
|
||||
@@ -189,16 +188,6 @@ class NtfManager: NSObject, UNUserNotificationCenterDelegate, ObservableObject {
|
||||
addNotification(createCallInvitationNtf(invitation))
|
||||
}
|
||||
|
||||
// TODO remove
|
||||
func notifyCheckingMessages() {
|
||||
logger.debug("NtfManager.notifyCheckingMessages")
|
||||
let content = createNotification(
|
||||
categoryIdentifier: ntfCategoryCheckingMessages,
|
||||
title: NSLocalizedString("Checking new messages...", comment: "notification")
|
||||
)
|
||||
addNotification(content)
|
||||
}
|
||||
|
||||
private func addNotification(_ content: UNMutableNotificationContent) {
|
||||
if !granted { return }
|
||||
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: ntfTimeInterval, repeats: false)
|
||||
|
||||
@@ -55,9 +55,19 @@ struct NotificationsView: View {
|
||||
NavigationLink {
|
||||
List {
|
||||
Section {
|
||||
SelectionListView(list: NotificationPreviewMode.values, selection: $m.notificationPreview)
|
||||
SelectionListView(list: NotificationPreviewMode.values, selection: $m.notificationPreview) { previewMode in
|
||||
ntfPreviewModeGroupDefault.set(previewMode)
|
||||
m.notificationPreview = previewMode
|
||||
}
|
||||
} footer: {
|
||||
|
||||
VStack(alignment: .leading, spacing: 1) {
|
||||
Text("You can set lock screen notification preview via settings.")
|
||||
Button("Open Settings") {
|
||||
DispatchQueue.main.async {
|
||||
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Show preview")
|
||||
|
||||
@@ -45,23 +45,14 @@ class NotificationService: UNNotificationServiceExtension {
|
||||
let encNtfInfo = ntfData["message"] as? String,
|
||||
let _ = startChat() {
|
||||
if let ntfMsgInfo = apiGetNtfMessage(nonce: nonce, encNtfInfo: encNtfInfo) {
|
||||
if let content = receiveMessageForNotification() {
|
||||
contentHandler(content)
|
||||
} else if let connEntity = ntfMsgInfo.connEntity {
|
||||
switch connEntity {
|
||||
case let .rcvDirectMsgConnection(_, contact):
|
||||
()
|
||||
case let .rcvGroupMsgConnection(_, groupInfo, groupMember):
|
||||
()
|
||||
case let .sndFileConnection(_, sndFileTransfer):
|
||||
()
|
||||
case let .rcvFileConnection(_, rcvFileTransfer):
|
||||
()
|
||||
case let .userContactConnection(_, userContact):
|
||||
()
|
||||
}
|
||||
contentHandler(request.content)
|
||||
}
|
||||
if let connEntity = ntfMsgInfo.connEntity {
|
||||
bestAttemptContent = createConnectionEventNtf(connEntity)
|
||||
}
|
||||
if let content = receiveMessageForNotification() {
|
||||
contentHandler(content)
|
||||
} else if let content = bestAttemptContent {
|
||||
contentHandler(content)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,8 +61,8 @@ class NotificationService: UNNotificationServiceExtension {
|
||||
logger.debug("NotificationService.serviceExtensionTimeWillExpire")
|
||||
// Called just before the extension will be terminated by the system.
|
||||
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
|
||||
if let contentHandler = self.contentHandler, let bestAttemptContent = self.bestAttemptContent {
|
||||
contentHandler(bestAttemptContent)
|
||||
if let contentHandler = self.contentHandler, let content = bestAttemptContent {
|
||||
contentHandler(content)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,8 +452,8 @@ public enum NotificationPreviewMode: String, SelectableItem {
|
||||
public var label: LocalizedStringKey {
|
||||
switch self {
|
||||
case .hidden: return "Hidden"
|
||||
case .contact: return "Contact"
|
||||
case .message: return "Message"
|
||||
case .contact: return "Contact name"
|
||||
case .message: return "Message text"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import SwiftUI
|
||||
let GROUP_DEFAULT_APP_STATE = "appState"
|
||||
let GROUP_DEFAULT_DB_CONTAINER = "dbContainer"
|
||||
public let GROUP_DEFAULT_CHAT_LAST_START = "chatLastStart"
|
||||
let GROUP_DEFAULT_NTF_PREVIEW_MODE = "ntfPreviewMode"
|
||||
|
||||
let APP_GROUP_NAME = "group.chat.simplex.app"
|
||||
|
||||
@@ -51,6 +52,12 @@ public let dbContainerGroupDefault = EnumDefault<DBContainer>(
|
||||
|
||||
public let chatLastStartGroupDefault = DateDefault(defaults: groupDefaults, forKey: GROUP_DEFAULT_CHAT_LAST_START)
|
||||
|
||||
public let ntfPreviewModeGroupDefault = EnumDefault<NotificationPreviewMode>(
|
||||
defaults: groupDefaults,
|
||||
forKey: GROUP_DEFAULT_NTF_PREVIEW_MODE,
|
||||
withDefault: .message
|
||||
)
|
||||
|
||||
public class DateDefault {
|
||||
var defaults: UserDefaults
|
||||
var key: String
|
||||
|
||||
@@ -426,6 +426,13 @@ public struct GroupMember: Decodable {
|
||||
}
|
||||
}
|
||||
|
||||
public var chatViewName: String {
|
||||
get {
|
||||
let p = memberProfile
|
||||
return p.displayName + (p.fullName == "" || p.fullName == p.displayName ? "" : " / \(p.fullName)")
|
||||
}
|
||||
}
|
||||
|
||||
public static let sampleData = GroupMember(
|
||||
groupMemberId: 1,
|
||||
memberId: "abcd",
|
||||
|
||||
@@ -14,37 +14,59 @@ public let ntfCategoryContactRequest = "NTF_CAT_CONTACT_REQUEST"
|
||||
public let ntfCategoryContactConnected = "NTF_CAT_CONTACT_CONNECTED"
|
||||
public let ntfCategoryMessageReceived = "NTF_CAT_MESSAGE_RECEIVED"
|
||||
public let ntfCategoryCallInvitation = "NTF_CAT_CALL_INVITATION"
|
||||
public let ntfCategoryConnectionEvent = "NTF_CAT_CONNECTION_EVENT"
|
||||
public let ntfCategoryCheckMessage = "NTF_CAT_CHECK_MESSAGE"
|
||||
// TODO remove
|
||||
public let ntfCategoryCheckingMessages = "NTF_CAT_CHECKING_MESSAGES"
|
||||
|
||||
public let appNotificationId = "chat.simplex.app.notification"
|
||||
|
||||
let contactHidden = NSLocalizedString("Contact hidden:", comment: "notification")
|
||||
|
||||
public func createContactRequestNtf(_ contactRequest: UserContactRequest) -> UNMutableNotificationContent {
|
||||
createNotification(
|
||||
let hideContent = ntfPreviewModeGroupDefault.get() == .hidden
|
||||
return createNotification(
|
||||
categoryIdentifier: ntfCategoryContactRequest,
|
||||
title: String.localizedStringWithFormat(NSLocalizedString("%@ wants to connect!", comment: "notification title"), contactRequest.displayName),
|
||||
body: String.localizedStringWithFormat(NSLocalizedString("Accept contact request from %@?", comment: "notification body"), contactRequest.chatViewName),
|
||||
title: String.localizedStringWithFormat(
|
||||
NSLocalizedString("%@ wants to connect!", comment: "notification title"),
|
||||
hideContent ? NSLocalizedString("Somebody", comment: "notification title") : contactRequest.displayName
|
||||
),
|
||||
body: String.localizedStringWithFormat(
|
||||
NSLocalizedString("Accept contact request from %@?", comment: "notification body"),
|
||||
hideContent ? NSLocalizedString("this contact", comment: "notification title") : contactRequest.chatViewName
|
||||
),
|
||||
targetContentIdentifier: nil,
|
||||
userInfo: ["chatId": contactRequest.id, "contactRequestId": contactRequest.apiId]
|
||||
)
|
||||
}
|
||||
|
||||
public func createContactConnectedNtf(_ contact: Contact) -> UNMutableNotificationContent {
|
||||
createNotification(
|
||||
let hideContent = ntfPreviewModeGroupDefault.get() == .hidden
|
||||
return createNotification(
|
||||
categoryIdentifier: ntfCategoryContactConnected,
|
||||
title: String.localizedStringWithFormat(NSLocalizedString("%@ is connected!", comment: "notification title"), contact.displayName),
|
||||
body: String.localizedStringWithFormat(NSLocalizedString("You can now send messages to %@", comment: "notification body"), contact.chatViewName),
|
||||
title: String.localizedStringWithFormat(
|
||||
NSLocalizedString("%@ is connected!", comment: "notification title"),
|
||||
hideContent ? NSLocalizedString("A new contact", comment: "notification title") : contact.displayName
|
||||
),
|
||||
body: String.localizedStringWithFormat(
|
||||
NSLocalizedString("You can now send messages to %@", comment: "notification body"),
|
||||
hideContent ? NSLocalizedString("this contact", comment: "notification title") : contact.chatViewName
|
||||
),
|
||||
targetContentIdentifier: contact.id
|
||||
// userInfo: ["chatId": contact.id, "contactId": contact.apiId]
|
||||
)
|
||||
}
|
||||
|
||||
public func createMessageReceivedNtf(_ cInfo: ChatInfo, _ cItem: ChatItem) -> UNMutableNotificationContent {
|
||||
createNotification(
|
||||
let previewMode = ntfPreviewModeGroupDefault.get()
|
||||
var title: String
|
||||
if case let .group(groupInfo) = cInfo, case let .groupRcv(groupMember) = cItem.chatDir {
|
||||
title = groupMsgNtfTitle(groupInfo, groupMember, hideContent: previewMode == .hidden)
|
||||
} else {
|
||||
title = previewMode == .hidden ? contactHidden : "\(cInfo.chatViewName):"
|
||||
}
|
||||
return createNotification(
|
||||
categoryIdentifier: ntfCategoryMessageReceived,
|
||||
title: "\(cInfo.chatViewName):",
|
||||
body: hideSecrets(cItem),
|
||||
title: title,
|
||||
body: previewMode == .message ? hideSecrets(cItem) : NSLocalizedString("new message", comment: "notification"),
|
||||
targetContentIdentifier: cInfo.id
|
||||
// userInfo: ["chatId": cInfo.id, "chatItemId": cItem.id]
|
||||
)
|
||||
@@ -54,15 +76,55 @@ public func createCallInvitationNtf(_ invitation: RcvCallInvitation) -> UNMutabl
|
||||
let text = invitation.callType.media == .video
|
||||
? NSLocalizedString("Incoming video call", comment: "notification")
|
||||
: NSLocalizedString("Incoming audio call", comment: "notification")
|
||||
let hideContent = ntfPreviewModeGroupDefault.get() == .hidden
|
||||
return createNotification(
|
||||
categoryIdentifier: ntfCategoryCallInvitation,
|
||||
title: "\(invitation.contact.chatViewName):",
|
||||
title: hideContent ? contactHidden : "\(invitation.contact.chatViewName):",
|
||||
body: text,
|
||||
targetContentIdentifier: nil,
|
||||
userInfo: ["chatId": invitation.contact.id]
|
||||
)
|
||||
}
|
||||
|
||||
public func createConnectionEventNtf(_ connEntity: ConnectionEntity) -> UNMutableNotificationContent {
|
||||
let hideContent = ntfPreviewModeGroupDefault.get() == .hidden
|
||||
var title: String
|
||||
var body: String? = nil
|
||||
var targetContentIdentifier: String? = nil
|
||||
switch connEntity {
|
||||
case let .rcvDirectMsgConnection(_, contact):
|
||||
if let contact = contact {
|
||||
title = hideContent ? contactHidden : "\(contact.chatViewName):"
|
||||
targetContentIdentifier = contact.id
|
||||
} else {
|
||||
title = NSLocalizedString("New contact:", comment: "notification")
|
||||
}
|
||||
body = NSLocalizedString("message received", comment: "notification")
|
||||
case let .rcvGroupMsgConnection(_, groupInfo, groupMember):
|
||||
title = groupMsgNtfTitle(groupInfo, groupMember, hideContent: hideContent)
|
||||
body = NSLocalizedString("message received", comment: "notification")
|
||||
targetContentIdentifier = groupInfo.id
|
||||
case .sndFileConnection:
|
||||
title = NSLocalizedString("Sent file event", comment: "notification")
|
||||
case .rcvFileConnection:
|
||||
title = NSLocalizedString("Received file event", comment: "notification")
|
||||
case .userContactConnection:
|
||||
title = NSLocalizedString("New contact request", comment: "notification")
|
||||
}
|
||||
return createNotification(
|
||||
categoryIdentifier: ntfCategoryCallInvitation,
|
||||
title: title,
|
||||
body: body,
|
||||
targetContentIdentifier: targetContentIdentifier
|
||||
)
|
||||
}
|
||||
|
||||
private func groupMsgNtfTitle(_ groupInfo: GroupInfo, _ groupMember: GroupMember, hideContent: Bool) -> String {
|
||||
hideContent
|
||||
? NSLocalizedString("Group message:", comment: "notification")
|
||||
: "#\(groupInfo.displayName) \(groupMember.chatViewName):"
|
||||
}
|
||||
|
||||
public func createNotification(categoryIdentifier: String, title: String, subtitle: String? = nil, body: String? = nil,
|
||||
targetContentIdentifier: String? = nil, userInfo: [AnyHashable : Any] = [:]) -> UNMutableNotificationContent {
|
||||
let content = UNMutableNotificationContent()
|
||||
|
||||
Reference in New Issue
Block a user