Add experimental push notification support
I added support for the experimental push notifications feature. There are many improvements to be made, so this feature is currently opt-in only. If the user does not opt-in, their device tokens will not be sent out and thus they will receive no push notifications. We should perform more testing on real-life staging environments before fully releasing this feature. Testing ------- Testing was done gradually during development. Device: iOS simulators iOS: 17 Damus version: A few different but recent prototypes Rough coverage: 1. Checked that no device tokens are sent out when setting is off 2. Checked that I can successfully receive device tokens when feature is ON and set to localhost. 3. Checked sending test push notifications of types "note" (kind: 1), reaction (kind: 7) and DMs (kind 4) works and shows a generic but reasonable push notification message 4. Checked that clicking on the notifications above take the user to the correct screen Closes: https://github.com/damus-io/damus/issues/67 Changelog-Added: Add experimental push notification support Signed-off-by: Daniel D’Aquino <daniel@daquino.me> Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
committed by
William Casarin
parent
878b1caa95
commit
ad75d8546c
@@ -12,7 +12,7 @@ struct damusApp: App {
|
||||
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
MainView()
|
||||
MainView(appDelegate: appDelegate)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,11 +21,12 @@ struct MainView: View {
|
||||
@State var needs_setup = false;
|
||||
@State var keypair: Keypair? = nil;
|
||||
@StateObject private var orientationTracker = OrientationTracker()
|
||||
var appDelegate: AppDelegate
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
if let kp = keypair, !needs_setup {
|
||||
ContentView(keypair: kp)
|
||||
ContentView(keypair: kp, appDelegate: appDelegate)
|
||||
.environmentObject(orientationTracker)
|
||||
} else {
|
||||
SetupView()
|
||||
@@ -49,15 +50,67 @@ struct MainView: View {
|
||||
.onAppear {
|
||||
orientationTracker.setDeviceMajorAxis()
|
||||
keypair = get_saved_keypair()
|
||||
appDelegate.keypair = keypair
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
|
||||
var keypair: Keypair? = nil
|
||||
var settings: UserSettingsStore? = nil
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
|
||||
UNUserNotificationCenter.current().delegate = self
|
||||
return true
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
|
||||
// Return if this feature is disabled
|
||||
guard let settings = self.settings else { return }
|
||||
if !settings.enable_experimental_push_notifications {
|
||||
return
|
||||
}
|
||||
|
||||
// Send the device token and pubkey to the server
|
||||
let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
|
||||
|
||||
print("Received device token: \(token)")
|
||||
|
||||
guard let pubkey = keypair?.pubkey else {
|
||||
return
|
||||
}
|
||||
|
||||
// Send those as JSON to the server
|
||||
let json: [String: Any] = ["deviceToken": token, "pubkey": pubkey.hex()]
|
||||
|
||||
// create post request
|
||||
let url = URL(string: settings.send_device_token_to_localhost ? "http://localhost:8000/user-info" : "https://notify.damus.io:8000/user-info")!
|
||||
var request = URLRequest(url: url)
|
||||
request.httpMethod = "POST"
|
||||
|
||||
// insert json data to the request
|
||||
request.httpBody = try? JSONSerialization.data(withJSONObject: json, options: [])
|
||||
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||
|
||||
let task = URLSession.shared.dataTask(with: request) { data, response, error in
|
||||
guard let data = data, error == nil else {
|
||||
print(error?.localizedDescription ?? "No data")
|
||||
return
|
||||
}
|
||||
|
||||
if let response = response as? HTTPURLResponse, !(200...299).contains(response.statusCode) {
|
||||
print("Unexpected status code: \(response.statusCode)")
|
||||
return
|
||||
}
|
||||
|
||||
let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
|
||||
if let responseJSON = responseJSON as? [String: Any] {
|
||||
print(responseJSON)
|
||||
}
|
||||
}
|
||||
|
||||
task.resume()
|
||||
}
|
||||
|
||||
// Handle the notification in the foreground state
|
||||
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
||||
|
||||
Reference in New Issue
Block a user