From 3655790e5f37750e099d3a65ce3acd81703fafe4 Mon Sep 17 00:00:00 2001 From: Jon Staab Date: Tue, 24 Jun 2025 14:15:36 -0700 Subject: [PATCH] Add fcm push notifications --- android/app/capacitor.build.gradle | 1 + android/app/src/main/AndroidManifest.xml | 1 + android/capacitor.settings.gradle | 3 ++ ios/App/App/AppDelegate.swift | 9 ++++ ios/App/App/Info.plist | 4 ++ ios/App/Podfile | 1 + package.json | 1 + pnpm-lock.yaml | Bin 335780 -> 315937 bytes src/app/commands.ts | 17 ++++--- src/app/components/AlertAdd.svelte | 49 +++++++++++++++---- src/app/components/AlertItem.svelte | 17 +++---- src/app/components/MenuSpace.svelte | 4 +- src/app/push.ts | 59 ++++++++++++++++++++--- src/app/requests.ts | 4 +- src/app/routes.ts | 6 +-- src/app/state.ts | 23 ++++++++- src/routes/+layout.svelte | 8 ++- src/routes/[bech32]/+page.svelte | 2 +- src/service-worker.js | 47 +++++++++--------- 19 files changed, 189 insertions(+), 67 deletions(-) diff --git a/android/app/capacitor.build.gradle b/android/app/capacitor.build.gradle index 60f2508d..b02acc84 100644 --- a/android/app/capacitor.build.gradle +++ b/android/app/capacitor.build.gradle @@ -12,6 +12,7 @@ dependencies { implementation project(':capacitor-community-safe-area') implementation project(':capacitor-app') implementation project(':capacitor-keyboard') + implementation project(':capacitor-push-notifications') implementation project(':nostr-signer-capacitor-plugin') } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index ec92f268..65a9dbe7 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -34,4 +34,5 @@ + diff --git a/android/capacitor.settings.gradle b/android/capacitor.settings.gradle index 89572353..a9c2e179 100644 --- a/android/capacitor.settings.gradle +++ b/android/capacitor.settings.gradle @@ -11,5 +11,8 @@ project(':capacitor-app').projectDir = new File('../node_modules/.pnpm/@capacito include ':capacitor-keyboard' project(':capacitor-keyboard').projectDir = new File('../node_modules/.pnpm/@capacitor+keyboard@7.0.1_@capacitor+core@7.2.0/node_modules/@capacitor/keyboard/android') +include ':capacitor-push-notifications' +project(':capacitor-push-notifications').projectDir = new File('../node_modules/.pnpm/@capacitor+push-notifications@7.0.1_@capacitor+core@7.2.0/node_modules/@capacitor/push-notifications/android') + include ':nostr-signer-capacitor-plugin' project(':nostr-signer-capacitor-plugin').projectDir = new File('../node_modules/.pnpm/nostr-signer-capacitor-plugin@0.0.4_@capacitor+core@7.2.0/node_modules/nostr-signer-capacitor-plugin/android') diff --git a/ios/App/App/AppDelegate.swift b/ios/App/App/AppDelegate.swift index c3cd83b5..eac186ae 100644 --- a/ios/App/App/AppDelegate.swift +++ b/ios/App/App/AppDelegate.swift @@ -46,4 +46,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate { return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler) } + func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { + // Enable push notifications https://capacitorjs.com/docs/apis/push-notifications + NotificationCenter.default.post(name: .capacitorDidRegisterForRemoteNotifications, object: deviceToken) + } + + func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { + // Enable push notifications https://capacitorjs.com/docs/apis/push-notifications + NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error) + } } diff --git a/ios/App/App/Info.plist b/ios/App/App/Info.plist index e3674ac7..79214e9f 100644 --- a/ios/App/App/Info.plist +++ b/ios/App/App/Info.plist @@ -49,5 +49,9 @@ ITSAppUsesNonExemptEncryption + UIBackgroundModes + + remote-notification + diff --git a/ios/App/Podfile b/ios/App/Podfile index 397e79d9..737c8d89 100644 --- a/ios/App/Podfile +++ b/ios/App/Podfile @@ -14,6 +14,7 @@ def capacitor_pods pod 'CapacitorCommunitySafeArea', :path => '../../node_modules/.pnpm/@capacitor-community+safe-area@7.0.0-alpha.1_@capacitor+core@7.2.0/node_modules/@capacitor-community/safe-area' pod 'CapacitorApp', :path => '../../node_modules/.pnpm/@capacitor+app@7.0.1_@capacitor+core@7.2.0/node_modules/@capacitor/app' pod 'CapacitorKeyboard', :path => '../../node_modules/.pnpm/@capacitor+keyboard@7.0.1_@capacitor+core@7.2.0/node_modules/@capacitor/keyboard' + pod 'CapacitorPushNotifications', :path => '../../node_modules/.pnpm/@capacitor+push-notifications@7.0.1_@capacitor+core@7.2.0/node_modules/@capacitor/push-notifications' pod 'NostrSignerCapacitorPlugin', :path => '../../node_modules/.pnpm/nostr-signer-capacitor-plugin@0.0.4_@capacitor+core@7.2.0/node_modules/nostr-signer-capacitor-plugin' end diff --git a/package.json b/package.json index 112dbac9..46fdae66 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "@capacitor/core": "^7.0.1", "@capacitor/ios": "^7.0.0", "@capacitor/keyboard": "^7.0.0", + "@capacitor/push-notifications": "^7.0.1", "@poppanator/sveltekit-svg": "^4.2.1", "@sentry/browser": "^8.35.0", "@sveltejs/adapter-static": "^3.0.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8f03d2da473725fbed3292d086280d009f934eb5..17515a1151e13001c9a0736a347e73438286accd 100644 GIT binary patch delta 2113 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 { }) } -export const publishAlert = async (params: AlertParams) => - publishThunk({event: await makeAlert(params), relays: [NOTIFIER_RELAY]}) +export const publishAlert = async (params: AlertParams) => { + const event = await signer.get().sign(await makeAlert(params)) + + deviceAlertAddresses.update($addresses => [...$addresses, getAddress(event)]) + + return publishThunk({event, relays: [NOTIFIER_RELAY]}) +} diff --git a/src/app/components/AlertAdd.svelte b/src/app/components/AlertAdd.svelte index 58d56df8..697d0256 100644 --- a/src/app/components/AlertAdd.svelte +++ b/src/app/components/AlertAdd.svelte @@ -1,18 +1,28 @@