mirror of
git://jb55.com/damus
synced 2024-09-30 00:40:45 +00:00
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:
parent
878b1caa95
commit
ad75d8546c
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>group.com.damus</string>
|
||||
</array>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
13
DamusNotificationService/Info.plist
Normal file
13
DamusNotificationService/Info.plist
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.usernotifications.service</string>
|
||||
<key>NSExtensionPrincipalClass</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).NotificationService</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,49 @@
|
||||
//
|
||||
// NostrEventInfoFromPushNotification.swift
|
||||
// DamusNotificationService
|
||||
//
|
||||
// Created by Daniel D’Aquino on 2023-11-13.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// The representation of a JSON-encoded Nostr Event used by the push notification server
|
||||
/// Needs to match with https://gitlab.com/soapbox-pub/strfry-policies/-/raw/433459d8084d1f2d6500fdf916f22caa3b4d7be5/src/types.ts
|
||||
struct NostrEventInfoFromPushNotification: Codable {
|
||||
let id: String // Hex-encoded
|
||||
let sig: String // Hex-encoded
|
||||
let kind: NostrKind
|
||||
let tags: [[String]]
|
||||
let pubkey: String // Hex-encoded
|
||||
let content: String
|
||||
let created_at: Int
|
||||
|
||||
static func from(dictionary: [AnyHashable: Any]) -> NostrEventInfoFromPushNotification? {
|
||||
guard let id = dictionary["id"] as? String,
|
||||
let sig = dictionary["sig"] as? String,
|
||||
let kind_int = dictionary["kind"] as? UInt32,
|
||||
let kind = NostrKind(rawValue: kind_int),
|
||||
let tags = dictionary["tags"] as? [[String]],
|
||||
let pubkey = dictionary["pubkey"] as? String,
|
||||
let content = dictionary["content"] as? String,
|
||||
let created_at = dictionary["created_at"] as? Int else {
|
||||
return nil
|
||||
}
|
||||
return NostrEventInfoFromPushNotification(id: id, sig: sig, kind: kind, tags: tags, pubkey: pubkey, content: content, created_at: created_at)
|
||||
}
|
||||
|
||||
func reactionEmoji() -> String? {
|
||||
guard self.kind == NostrKind.like else {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch self.content {
|
||||
case "", "+":
|
||||
return "❤️"
|
||||
case "-":
|
||||
return "👎"
|
||||
default:
|
||||
return self.content
|
||||
}
|
||||
}
|
||||
}
|
48
DamusNotificationService/NotificationFormatter.swift
Normal file
48
DamusNotificationService/NotificationFormatter.swift
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// NotificationFormatter.swift
|
||||
// DamusNotificationService
|
||||
//
|
||||
// Created by Daniel D’Aquino on 2023-11-13.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UserNotifications
|
||||
|
||||
struct NotificationFormatter {
|
||||
static var shared = NotificationFormatter()
|
||||
|
||||
// TODO: These is a very generic notification formatter. Once we integrate NostrDB into the extension, we should reuse various functions present in `HomeModel.swift`
|
||||
func formatMessage(event: NostrEventInfoFromPushNotification) -> UNNotificationContent? {
|
||||
let content = UNMutableNotificationContent()
|
||||
if let event_json_data = try? JSONEncoder().encode(event), // Must be encoded, as the notification completion handler requires this object to conform to `NSSecureCoding`
|
||||
let event_json_string = String(data: event_json_data, encoding: .utf8) {
|
||||
content.userInfo = [
|
||||
"nostr_event_info": event_json_string
|
||||
]
|
||||
}
|
||||
switch event.kind {
|
||||
case .text:
|
||||
content.title = NSLocalizedString("Someone posted a note", comment: "Title label for push notification where someone posted a note")
|
||||
content.body = event.content
|
||||
break
|
||||
case .dm:
|
||||
content.title = NSLocalizedString("New message", comment: "Title label for push notifications where a direct message was sent to the user")
|
||||
content.body = NSLocalizedString("(Contents are encrypted)", comment: "Label on push notification indicating that the contents of the message are encrypted")
|
||||
break
|
||||
case .like:
|
||||
guard let reactionEmoji = event.reactionEmoji() else {
|
||||
content.title = NSLocalizedString("Someone reacted to your note", comment: "Generic title label for push notifications where someone reacted to the user's post")
|
||||
break
|
||||
}
|
||||
content.title = NSLocalizedString("New note reaction", comment: "Title label for push notifications where someone reacted to the user's post with a specific emoji")
|
||||
content.body = String(format: NSLocalizedString("Someone reacted to your note with %@", comment: "Body label for push notifications where someone reacted to the user's post with a specific emoji"), reactionEmoji)
|
||||
break
|
||||
case .zap:
|
||||
content.title = NSLocalizedString("Someone zapped you ⚡️", comment: "Title label for a push notification where someone zapped the user")
|
||||
break
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
return content
|
||||
}
|
||||
}
|
39
DamusNotificationService/NotificationService.swift
Normal file
39
DamusNotificationService/NotificationService.swift
Normal file
@ -0,0 +1,39 @@
|
||||
//
|
||||
// NotificationService.swift
|
||||
// DamusNotificationService
|
||||
//
|
||||
// Created by Daniel D’Aquino on 2023-11-10.
|
||||
//
|
||||
|
||||
import UserNotifications
|
||||
import Foundation
|
||||
|
||||
class NotificationService: UNNotificationServiceExtension {
|
||||
|
||||
var contentHandler: ((UNNotificationContent) -> Void)?
|
||||
var bestAttemptContent: UNMutableNotificationContent?
|
||||
|
||||
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
|
||||
self.contentHandler = contentHandler
|
||||
|
||||
// Modify the notification content here...
|
||||
guard let nostrEventInfoDictionary = request.content.userInfo["nostr_event"] as? [AnyHashable: Any],
|
||||
let nostrEventInfo = NostrEventInfoFromPushNotification.from(dictionary: nostrEventInfoDictionary) else {
|
||||
contentHandler(request.content)
|
||||
return;
|
||||
}
|
||||
|
||||
if let improvedContent = NotificationFormatter.shared.formatMessage(event: nostrEventInfo) {
|
||||
contentHandler(improvedContent)
|
||||
}
|
||||
}
|
||||
|
||||
override func 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 = contentHandler, let bestAttemptContent = bestAttemptContent {
|
||||
contentHandler(bestAttemptContent)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -429,6 +429,8 @@
|
||||
BA693074295D649800ADDB87 /* UserSettingsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA693073295D649800ADDB87 /* UserSettingsStore.swift */; };
|
||||
BAB68BED29543FA3007BA466 /* SelectWalletView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAB68BEC29543FA3007BA466 /* SelectWalletView.swift */; };
|
||||
D2277EEA2A089BD5006C3807 /* Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2277EE92A089BD5006C3807 /* Router.swift */; };
|
||||
D70A3B172B02DCE5008BD568 /* NotificationFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D70A3B162B02DCE5008BD568 /* NotificationFormatter.swift */; };
|
||||
D70A3B192B02DD2D008BD568 /* NostrEventInfoFromPushNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D70A3B182B02DD2D008BD568 /* NostrEventInfoFromPushNotification.swift */; };
|
||||
D71DC1EC2A9129C3006E207C /* PostViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D71DC1EB2A9129C3006E207C /* PostViewTests.swift */; };
|
||||
D723C38E2AB8D83400065664 /* ContentFilters.swift in Sources */ = {isa = PBXBuildFile; fileRef = D723C38D2AB8D83400065664 /* ContentFilters.swift */; };
|
||||
D72A2D022AD9C136002AFF62 /* EventViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72A2CFF2AD9B66B002AFF62 /* EventViewTests.swift */; };
|
||||
@ -442,8 +444,13 @@
|
||||
D78525252A7B2EA4002FA637 /* NoteContentViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D78525242A7B2EA4002FA637 /* NoteContentViewTests.swift */; };
|
||||
D7870BC12AC4750B0080BA88 /* MentionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7870BC02AC4750B0080BA88 /* MentionView.swift */; };
|
||||
D7870BC32AC47EBC0080BA88 /* EventLoaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7870BC22AC47EBC0080BA88 /* EventLoaderView.swift */; };
|
||||
D789D1202AFEFBF20083A7AB /* secp256k1 in Frameworks */ = {isa = PBXBuildFile; productRef = D789D11F2AFEFBF20083A7AB /* secp256k1 */; };
|
||||
D79C4C172AFEB061003A41B4 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D79C4C162AFEB061003A41B4 /* NotificationService.swift */; };
|
||||
D79C4C1B2AFEB061003A41B4 /* DamusNotificationService.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D79C4C142AFEB061003A41B4 /* DamusNotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
D7A343EE2AD0D77C00CED48B /* InlineSnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = D7A343ED2AD0D77C00CED48B /* InlineSnapshotTesting */; };
|
||||
D7A343F02AD0D77C00CED48B /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = D7A343EF2AD0D77C00CED48B /* SnapshotTesting */; };
|
||||
D7DBD41F2B02F15E002A6197 /* NostrKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFD32819DE8F00B3DE84 /* NostrKind.swift */; };
|
||||
D7DBD4202B0307C7002A6197 /* NostrEventInfoFromPushNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D70A3B182B02DD2D008BD568 /* NostrEventInfoFromPushNotification.swift */; };
|
||||
D7DEEF2F2A8C021E00E0C99F /* NostrEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7DEEF2E2A8C021E00E0C99F /* NostrEventTests.swift */; };
|
||||
D7FF94002AC7AC5300FD969D /* RelayURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7FF93FF2AC7AC5200FD969D /* RelayURL.swift */; };
|
||||
E4FA1C032A24BB7F00482697 /* SearchSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4FA1C022A24BB7F00482697 /* SearchSettingsView.swift */; };
|
||||
@ -481,8 +488,29 @@
|
||||
remoteGlobalIDString = 4CE6DEE227F7A08100C66700;
|
||||
remoteInfo = damus;
|
||||
};
|
||||
D79C4C192AFEB061003A41B4 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 4CE6DEDB27F7A08100C66700 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D79C4C132AFEB061003A41B4;
|
||||
remoteInfo = DamusNotificationService;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
D79C4C1D2AFEB061003A41B4 /* Embed Foundation Extensions */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 13;
|
||||
files = (
|
||||
D79C4C1B2AFEB061003A41B4 /* DamusNotificationService.appex in Embed Foundation Extensions */,
|
||||
);
|
||||
name = "Embed Foundation Extensions";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0E8A4BB62AE4359200065E81 /* NostrFilter+Hashable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NostrFilter+Hashable.swift"; sourceTree = "<group>"; };
|
||||
3165648A295B70D500C64604 /* LinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkView.swift; sourceTree = "<group>"; };
|
||||
@ -1130,6 +1158,8 @@
|
||||
BA693073295D649800ADDB87 /* UserSettingsStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSettingsStore.swift; sourceTree = "<group>"; };
|
||||
BAB68BEC29543FA3007BA466 /* SelectWalletView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectWalletView.swift; sourceTree = "<group>"; };
|
||||
D2277EE92A089BD5006C3807 /* Router.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Router.swift; sourceTree = "<group>"; };
|
||||
D70A3B162B02DCE5008BD568 /* NotificationFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationFormatter.swift; sourceTree = "<group>"; };
|
||||
D70A3B182B02DD2D008BD568 /* NostrEventInfoFromPushNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NostrEventInfoFromPushNotification.swift; sourceTree = "<group>"; };
|
||||
D71DC1EB2A9129C3006E207C /* PostViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostViewTests.swift; sourceTree = "<group>"; };
|
||||
D723C38D2AB8D83400065664 /* ContentFilters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentFilters.swift; sourceTree = "<group>"; };
|
||||
D72A2CFF2AD9B66B002AFF62 /* EventViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventViewTests.swift; sourceTree = "<group>"; };
|
||||
@ -1143,6 +1173,10 @@
|
||||
D78525242A7B2EA4002FA637 /* NoteContentViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoteContentViewTests.swift; sourceTree = "<group>"; };
|
||||
D7870BC02AC4750B0080BA88 /* MentionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MentionView.swift; sourceTree = "<group>"; };
|
||||
D7870BC22AC47EBC0080BA88 /* EventLoaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventLoaderView.swift; sourceTree = "<group>"; };
|
||||
D79C4C142AFEB061003A41B4 /* DamusNotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = DamusNotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D79C4C162AFEB061003A41B4 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; };
|
||||
D79C4C182AFEB061003A41B4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
D79C4C1C2AFEB061003A41B4 /* DamusNotificationService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DamusNotificationService.entitlements; sourceTree = "<group>"; };
|
||||
D7DEEF2E2A8C021E00E0C99F /* NostrEventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NostrEventTests.swift; sourceTree = "<group>"; };
|
||||
D7FF93FF2AC7AC5200FD969D /* RelayURL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayURL.swift; sourceTree = "<group>"; };
|
||||
E4FA1C022A24BB7F00482697 /* SearchSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSettingsView.swift; sourceTree = "<group>"; };
|
||||
@ -1192,6 +1226,14 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D79C4C112AFEB061003A41B4 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D789D1202AFEFBF20083A7AB /* secp256k1 in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
@ -2114,6 +2156,7 @@
|
||||
4CE6DEE527F7A08100C66700 /* damus */,
|
||||
4CE6DEF627F7A08200C66700 /* damusTests */,
|
||||
4CE6DF0027F7A08200C66700 /* damusUITests */,
|
||||
D79C4C152AFEB061003A41B4 /* DamusNotificationService */,
|
||||
4CE6DEE427F7A08100C66700 /* Products */,
|
||||
4CEE2AE62804F57B00AB5EEF /* Frameworks */,
|
||||
);
|
||||
@ -2127,6 +2170,7 @@
|
||||
4CE6DEE327F7A08100C66700 /* damus.app */,
|
||||
4CE6DEF327F7A08200C66700 /* damusTests.xctest */,
|
||||
4CE6DEFD27F7A08200C66700 /* damusUITests.xctest */,
|
||||
D79C4C142AFEB061003A41B4 /* DamusNotificationService.appex */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@ -2339,6 +2383,18 @@
|
||||
path = Mocking;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D79C4C152AFEB061003A41B4 /* DamusNotificationService */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D79C4C1C2AFEB061003A41B4 /* DamusNotificationService.entitlements */,
|
||||
D79C4C162AFEB061003A41B4 /* NotificationService.swift */,
|
||||
D79C4C182AFEB061003A41B4 /* Info.plist */,
|
||||
D70A3B162B02DCE5008BD568 /* NotificationFormatter.swift */,
|
||||
D70A3B182B02DD2D008BD568 /* NostrEventInfoFromPushNotification.swift */,
|
||||
);
|
||||
path = DamusNotificationService;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F71694E82A66221E001F4053 /* Onboarding */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -2378,10 +2434,12 @@
|
||||
4CE6DEE027F7A08100C66700 /* Frameworks */,
|
||||
4C1D4FB22A7965230024F453 /* ShellScript */,
|
||||
4CE6DEE127F7A08100C66700 /* Resources */,
|
||||
D79C4C1D2AFEB061003A41B4 /* Embed Foundation Extensions */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
D79C4C1A2AFEB061003A41B4 /* PBXTargetDependency */,
|
||||
);
|
||||
name = damus;
|
||||
packageProductDependencies = (
|
||||
@ -2433,6 +2491,26 @@
|
||||
productReference = 4CE6DEFD27F7A08200C66700 /* damusUITests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.ui-testing";
|
||||
};
|
||||
D79C4C132AFEB061003A41B4 /* DamusNotificationService */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D79C4C202AFEB061003A41B4 /* Build configuration list for PBXNativeTarget "DamusNotificationService" */;
|
||||
buildPhases = (
|
||||
D79C4C102AFEB061003A41B4 /* Sources */,
|
||||
D79C4C112AFEB061003A41B4 /* Frameworks */,
|
||||
D79C4C122AFEB061003A41B4 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = DamusNotificationService;
|
||||
packageProductDependencies = (
|
||||
D789D11F2AFEFBF20083A7AB /* secp256k1 */,
|
||||
);
|
||||
productName = DamusNotificationService;
|
||||
productReference = D79C4C142AFEB061003A41B4 /* DamusNotificationService.appex */;
|
||||
productType = "com.apple.product-type.app-extension";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
@ -2440,7 +2518,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = 1;
|
||||
LastSwiftUpdateCheck = 1330;
|
||||
LastSwiftUpdateCheck = 1500;
|
||||
LastUpgradeCheck = 1500;
|
||||
TargetAttributes = {
|
||||
4CE6DEE227F7A08100C66700 = {
|
||||
@ -2455,6 +2533,9 @@
|
||||
CreatedOnToolsVersion = 13.3;
|
||||
TestTargetID = 4CE6DEE227F7A08100C66700;
|
||||
};
|
||||
D79C4C132AFEB061003A41B4 = {
|
||||
CreatedOnToolsVersion = 15.0.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 4CE6DEDE27F7A08100C66700 /* Build configuration list for PBXProject "damus" */;
|
||||
@ -2508,6 +2589,7 @@
|
||||
4CE6DEE227F7A08100C66700 /* damus */,
|
||||
4CE6DEF227F7A08200C66700 /* damusTests */,
|
||||
4CE6DEFC27F7A08200C66700 /* damusUITests */,
|
||||
D79C4C132AFEB061003A41B4 /* DamusNotificationService */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@ -2546,6 +2628,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D79C4C122AFEB061003A41B4 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
@ -2713,6 +2802,7 @@
|
||||
9C83F89329A937B900136C08 /* TextViewWrapper.swift in Sources */,
|
||||
4C1253502A76C5B20004F4B8 /* UnfollowedNotify.swift in Sources */,
|
||||
4C86F7C62A76C51100EC0817 /* AttachedWalletNotify.swift in Sources */,
|
||||
D7DBD4202B0307C7002A6197 /* NostrEventInfoFromPushNotification.swift in Sources */,
|
||||
4CF0ABE12981A83900D66079 /* MutelistView.swift in Sources */,
|
||||
4CB883A82975FC1800DC99E7 /* Zaps.swift in Sources */,
|
||||
4C75EFB128049D510006080F /* NostrResponse.swift in Sources */,
|
||||
@ -3032,6 +3122,17 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D79C4C102AFEB061003A41B4 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D79C4C172AFEB061003A41B4 /* NotificationService.swift in Sources */,
|
||||
D70A3B192B02DD2D008BD568 /* NostrEventInfoFromPushNotification.swift in Sources */,
|
||||
D7DBD41F2B02F15E002A6197 /* NostrKind.swift in Sources */,
|
||||
D70A3B172B02DCE5008BD568 /* NotificationFormatter.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
@ -3045,6 +3146,11 @@
|
||||
target = 4CE6DEE227F7A08100C66700 /* damus */;
|
||||
targetProxy = 4CE6DEFE27F7A08200C66700 /* PBXContainerItemProxy */;
|
||||
};
|
||||
D79C4C1A2AFEB061003A41B4 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D79C4C132AFEB061003A41B4 /* DamusNotificationService */;
|
||||
targetProxy = D79C4C192AFEB061003A41B4 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
@ -3284,6 +3390,7 @@
|
||||
4CE6DF0827F7A08200C66700 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
@ -3333,6 +3440,7 @@
|
||||
4CE6DF0927F7A08200C66700 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
@ -3454,6 +3562,73 @@
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
D79C4C1E2AFEB061003A41B4 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CODE_SIGN_ENTITLEMENTS = DamusNotificationService/DamusNotificationService.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = XK7H4JAB3D;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = DamusNotificationService/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = DamusNotificationService;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jb55.damus2.DamusNotificationService;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
D79C4C1F2AFEB061003A41B4 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CODE_SIGN_ENTITLEMENTS = DamusNotificationService/DamusNotificationService.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = XK7H4JAB3D;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = DamusNotificationService/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = DamusNotificationService;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jb55.damus2.DamusNotificationService;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
@ -3493,6 +3668,15 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
D79C4C202AFEB061003A41B4 /* Build configuration list for PBXNativeTarget "DamusNotificationService" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D79C4C1E2AFEB061003A41B4 /* Debug */,
|
||||
D79C4C1F2AFEB061003A41B4 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
@ -3554,6 +3738,11 @@
|
||||
package = 4C64987F286E0EE300EAE2B3 /* XCRemoteSwiftPackageReference "secp256k1" */;
|
||||
productName = secp256k1;
|
||||
};
|
||||
D789D11F2AFEFBF20083A7AB /* secp256k1 */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 4C64987F286E0EE300EAE2B3 /* XCRemoteSwiftPackageReference "secp256k1" */;
|
||||
productName = secp256k1;
|
||||
};
|
||||
D7A343ED2AD0D77C00CED48B /* InlineSnapshotTesting */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D7A343EC2AD0D77C00CED48B /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */;
|
||||
|
@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1500"
|
||||
wasCreatedForAppExtension = "YES"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "D79C4C132AFEB061003A41B4"
|
||||
BuildableName = "DamusNotificationService.appex"
|
||||
BlueprintName = "DamusNotificationService"
|
||||
ReferencedContainer = "container:damus.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "4CE6DEE227F7A08100C66700"
|
||||
BuildableName = "damus.app"
|
||||
BlueprintName = "damus"
|
||||
ReferencedContainer = "container:damus.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = ""
|
||||
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
|
||||
launchStyle = "0"
|
||||
askForAppToLaunch = "Yes"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES"
|
||||
launchAutomaticallySubstyle = "2">
|
||||
<RemoteRunnable
|
||||
runnableDebuggingMode = "1"
|
||||
BundleIdentifier = "com.jb55.damus2"
|
||||
RemotePath = "/Users/danielnogueira/Library/Developer/CoreSimulator/Devices/99E60B35-CE5D-4B45-AC35-00818C0AF3CB/data/Containers/Bundle/Application/5A083DD0-FDE2-43D7-9172-2F97FAD18F20/damus.app">
|
||||
</RemoteRunnable>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "4CE6DEE227F7A08100C66700"
|
||||
BuildableName = "damus.app"
|
||||
BlueprintName = "damus"
|
||||
ReferencedContainer = "container:damus.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
askForAppToLaunch = "Yes"
|
||||
launchAutomaticallySubstyle = "2">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "4CE6DEE227F7A08100C66700"
|
||||
BuildableName = "damus.app"
|
||||
BlueprintName = "damus"
|
||||
ReferencedContainer = "container:damus.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
@ -54,6 +54,7 @@ enum Sheets: Identifiable {
|
||||
|
||||
struct ContentView: View {
|
||||
let keypair: Keypair
|
||||
let appDelegate: AppDelegate?
|
||||
|
||||
var pubkey: Pubkey {
|
||||
return keypair.pubkey
|
||||
@ -303,6 +304,7 @@ struct ContentView: View {
|
||||
active_sheet = .onboardingSuggestions
|
||||
hasSeenOnboardingSuggestions = true
|
||||
}
|
||||
self.appDelegate?.settings = damus_state?.settings
|
||||
}
|
||||
.sheet(item: $active_sheet) { item in
|
||||
switch item {
|
||||
@ -694,7 +696,7 @@ struct ContentView: View {
|
||||
|
||||
struct ContentView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ContentView(keypair: Keypair(pubkey: test_pubkey, privkey: nil))
|
||||
ContentView(keypair: Keypair(pubkey: test_pubkey, privkey: nil), appDelegate: nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,6 +191,12 @@ class UserSettingsStore: ObservableObject {
|
||||
|
||||
@Setting(key: "always_show_onboarding_suggestions", default_value: false)
|
||||
var always_show_onboarding_suggestions: Bool
|
||||
|
||||
@Setting(key: "enable_experimental_push_notifications", default_value: false)
|
||||
var enable_experimental_push_notifications: Bool
|
||||
|
||||
@Setting(key: "send_device_token_to_localhost", default_value: false)
|
||||
var send_device_token_to_localhost: Bool
|
||||
|
||||
@Setting(key: "emoji_reactions", default_value: default_emoji_reactions)
|
||||
var emoji_reactions: [String]
|
||||
|
@ -19,6 +19,9 @@ struct LossyLocalNotification {
|
||||
}
|
||||
|
||||
static func from_user_info(user_info: [AnyHashable: Any]) -> LossyLocalNotification? {
|
||||
if let encoded_nostr_event_push_data = user_info["nostr_event_info"] as? String {
|
||||
return self.from(encoded_nostr_event_push_data: encoded_nostr_event_push_data)
|
||||
}
|
||||
guard let id = user_info["id"] as? String,
|
||||
let target_id = MentionRef.from_bech32(str: id) else {
|
||||
return nil
|
||||
@ -28,6 +31,21 @@ struct LossyLocalNotification {
|
||||
|
||||
return LossyLocalNotification(type: type, mention: target_id)
|
||||
}
|
||||
|
||||
static func from(encoded_nostr_event_push_data: String) -> LossyLocalNotification? {
|
||||
guard let json_data = encoded_nostr_event_push_data.data(using: .utf8),
|
||||
let nostr_event_push_data = try? JSONDecoder().decode(NostrEventInfoFromPushNotification.self, from: json_data) else {
|
||||
return nil
|
||||
}
|
||||
return self.from(nostr_event_push_data: nostr_event_push_data)
|
||||
}
|
||||
|
||||
static func from(nostr_event_push_data: NostrEventInfoFromPushNotification) -> LossyLocalNotification? {
|
||||
guard let type = LocalNotificationType.from(nostr_kind: nostr_event_push_data.kind) else { return nil }
|
||||
guard let note_id: NoteId = NoteId.init(hex: nostr_event_push_data.id) else { return nil }
|
||||
let target: MentionRef = .note(note_id)
|
||||
return LossyLocalNotification(type: type, mention: target)
|
||||
}
|
||||
}
|
||||
|
||||
struct LocalNotification {
|
||||
@ -48,4 +66,21 @@ enum LocalNotificationType: String {
|
||||
case repost
|
||||
case zap
|
||||
case profile_zap
|
||||
|
||||
static func from(nostr_kind: NostrKind) -> Self? {
|
||||
switch nostr_kind {
|
||||
case .text:
|
||||
return .mention
|
||||
case .dm:
|
||||
return .dm
|
||||
case .like:
|
||||
return .like
|
||||
case .longform:
|
||||
return .mention
|
||||
case .zap:
|
||||
return .zap
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,12 @@ struct DeveloperSettingsView: View {
|
||||
Toggle(NSLocalizedString("Developer Mode", comment: "Setting to enable developer mode"), isOn: $settings.developer_mode)
|
||||
.toggleStyle(.switch)
|
||||
if settings.developer_mode {
|
||||
Toggle(NSLocalizedString("Always show onboarding", comment: "Setting to always show onboarding suggestions, for developers who need to test onboarding"), isOn: $settings.always_show_onboarding_suggestions)
|
||||
Toggle("Always show onboarding", isOn: $settings.always_show_onboarding_suggestions)
|
||||
|
||||
Toggle("Enable experimental push notifications", isOn: $settings.enable_experimental_push_notifications)
|
||||
.toggleStyle(.switch)
|
||||
|
||||
Toggle("Send device token to localhost", isOn: $settings.send_device_token_to_localhost)
|
||||
.toggleStyle(.switch)
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,10 @@
|
||||
<true/>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>group.com.damus</string>
|
||||
</array>
|
||||
<key>com.apple.security.device.audio-input</key>
|
||||
<true/>
|
||||
<key>com.apple.security.device.camera</key>
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user