forked from shadowfacts/Tusker
Custom emoji in push notifications, behind a feature flag
This commit is contained in:
parent
1bd4d144a3
commit
59fb69525b
|
@ -15,9 +15,13 @@ import Pachyderm
|
||||||
import Intents
|
import Intents
|
||||||
import HTMLStreamer
|
import HTMLStreamer
|
||||||
import WebURL
|
import WebURL
|
||||||
|
import UIKit
|
||||||
|
import TuskerPreferences
|
||||||
|
|
||||||
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "NotificationService")
|
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "NotificationService")
|
||||||
|
|
||||||
|
private let emojiRegex = try! NSRegularExpression(pattern: ":(\\w+):", options: [])
|
||||||
|
|
||||||
class NotificationService: UNNotificationServiceExtension {
|
class NotificationService: UNNotificationServiceExtension {
|
||||||
|
|
||||||
private static let textConverter = TextConverter(configuration: .init(insertNewlines: false), callbacks: HTMLCallbacks.self)
|
private static let textConverter = TextConverter(configuration: .init(insertNewlines: false), callbacks: HTMLCallbacks.self)
|
||||||
|
@ -225,8 +229,33 @@ class NotificationService: UNNotificationServiceExtension {
|
||||||
}
|
}
|
||||||
|
|
||||||
let updatedContent: UNMutableNotificationContent
|
let updatedContent: UNMutableNotificationContent
|
||||||
|
|
||||||
|
let contentProviding: any UNNotificationContentProviding
|
||||||
|
if #available(iOS 18.0, *),
|
||||||
|
await Preferences.shared.hasFeatureFlag(.pushNotifCustomEmoji) {
|
||||||
|
let attributedString = NSMutableAttributedString(string: content.body)
|
||||||
|
|
||||||
|
for match in emojiRegex.matches(in: content.body, range: NSRange(location: 0, length: content.body.utf16.count)).reversed() {
|
||||||
|
let emojiName = (content.body as NSString).substring(with: match.range(at: 1))
|
||||||
|
guard let emoji = notification.status?.emojis.first(where: { $0.shortcode == emojiName }),
|
||||||
|
let url = URL(emoji.url),
|
||||||
|
let (data, _) = try? await URLSession.shared.data(from: url),
|
||||||
|
let image = UIImage(data: data) else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
let attachment = NSTextAttachment(image: image)
|
||||||
|
let attachmentStr = NSAttributedString(attachment: attachment)
|
||||||
|
attributedString.replaceCharacters(in: match.range, with: attachmentStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
let attributedCtx = UNNotificationAttributedMessageContext(sendMessageIntent: intent, attributedContent: attributedString)
|
||||||
|
contentProviding = attributedCtx
|
||||||
|
} else {
|
||||||
|
contentProviding = intent
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let newContent = try content.updating(from: intent)
|
let newContent = try content.updating(from: contentProviding)
|
||||||
if let newMutableContent = newContent.mutableCopy() as? UNMutableNotificationContent {
|
if let newMutableContent = newContent.mutableCopy() as? UNMutableNotificationContent {
|
||||||
pendingRequest?.0 = newMutableContent
|
pendingRequest?.0 = newMutableContent
|
||||||
updatedContent = newMutableContent
|
updatedContent = newMutableContent
|
||||||
|
|
|
@ -9,4 +9,5 @@ import Foundation
|
||||||
|
|
||||||
public enum FeatureFlag: String, Codable {
|
public enum FeatureFlag: String, Codable {
|
||||||
case iPadBrowserNavigation = "ipad-browser-navigation"
|
case iPadBrowserNavigation = "ipad-browser-navigation"
|
||||||
|
case pushNotifCustomEmoji = "push-notif-custom-emoji"
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,7 @@
|
||||||
D620483823D38190008A63EF /* StatusContentTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D620483723D38190008A63EF /* StatusContentTextView.swift */; };
|
D620483823D38190008A63EF /* StatusContentTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D620483723D38190008A63EF /* StatusContentTextView.swift */; };
|
||||||
D6210D762C0B924F009BB569 /* RemoveProfileSuggestionService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6210D752C0B924F009BB569 /* RemoveProfileSuggestionService.swift */; };
|
D6210D762C0B924F009BB569 /* RemoveProfileSuggestionService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6210D752C0B924F009BB569 /* RemoveProfileSuggestionService.swift */; };
|
||||||
D621733328F1D5ED004C7DB1 /* ReblogService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D621733228F1D5ED004C7DB1 /* ReblogService.swift */; };
|
D621733328F1D5ED004C7DB1 /* ReblogService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D621733228F1D5ED004C7DB1 /* ReblogService.swift */; };
|
||||||
|
D62220472C7EA8DF003E43B7 /* TuskerPreferences in Frameworks */ = {isa = PBXBuildFile; productRef = D62220462C7EA8DF003E43B7 /* TuskerPreferences */; };
|
||||||
D62275A824F1CA2800B82A16 /* ComposeReplyContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62275A724F1CA2800B82A16 /* ComposeReplyContentView.swift */; };
|
D62275A824F1CA2800B82A16 /* ComposeReplyContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62275A724F1CA2800B82A16 /* ComposeReplyContentView.swift */; };
|
||||||
D623A53D2635F5590095BD04 /* StatusPollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D623A53C2635F5590095BD04 /* StatusPollView.swift */; };
|
D623A53D2635F5590095BD04 /* StatusPollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D623A53C2635F5590095BD04 /* StatusPollView.swift */; };
|
||||||
D623A5412635FB3C0095BD04 /* PollOptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D623A5402635FB3C0095BD04 /* PollOptionView.swift */; };
|
D623A5412635FB3C0095BD04 /* PollOptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D623A5402635FB3C0095BD04 /* PollOptionView.swift */; };
|
||||||
|
@ -828,6 +829,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
D630C4252BC7845800208903 /* WebURL in Frameworks */,
|
D630C4252BC7845800208903 /* WebURL in Frameworks */,
|
||||||
|
D62220472C7EA8DF003E43B7 /* TuskerPreferences in Frameworks */,
|
||||||
D630C4232BC7842C00208903 /* HTMLStreamer in Frameworks */,
|
D630C4232BC7842C00208903 /* HTMLStreamer in Frameworks */,
|
||||||
D630C3E52BC6313400208903 /* Pachyderm in Frameworks */,
|
D630C3E52BC6313400208903 /* Pachyderm in Frameworks */,
|
||||||
D630C3DF2BC61C4900208903 /* PushNotifications in Frameworks */,
|
D630C3DF2BC61C4900208903 /* PushNotifications in Frameworks */,
|
||||||
|
@ -1795,6 +1797,7 @@
|
||||||
D630C3E42BC6313400208903 /* Pachyderm */,
|
D630C3E42BC6313400208903 /* Pachyderm */,
|
||||||
D630C4222BC7842C00208903 /* HTMLStreamer */,
|
D630C4222BC7842C00208903 /* HTMLStreamer */,
|
||||||
D630C4242BC7845800208903 /* WebURL */,
|
D630C4242BC7845800208903 /* WebURL */,
|
||||||
|
D62220462C7EA8DF003E43B7 /* TuskerPreferences */,
|
||||||
);
|
);
|
||||||
productName = NotificationExtension;
|
productName = NotificationExtension;
|
||||||
productReference = D630C3D12BC61B6000208903 /* NotificationExtension.appex */;
|
productReference = D630C3D12BC61B6000208903 /* NotificationExtension.appex */;
|
||||||
|
@ -3299,6 +3302,10 @@
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
productName = Pachyderm;
|
productName = Pachyderm;
|
||||||
};
|
};
|
||||||
|
D62220462C7EA8DF003E43B7 /* TuskerPreferences */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = TuskerPreferences;
|
||||||
|
};
|
||||||
D630C3C72BC43AFD00208903 /* PushNotifications */ = {
|
D630C3C72BC43AFD00208903 /* PushNotifications */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
productName = PushNotifications;
|
productName = PushNotifications;
|
||||||
|
|
Loading…
Reference in New Issue