Add fcm push notifications

This commit is contained in:
Jon Staab
2025-06-24 14:15:36 -07:00
parent 6cca823ed4
commit 3655790e5f
19 changed files with 236 additions and 608 deletions
+1
View File
@@ -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')
}
+1
View File
@@ -34,4 +34,5 @@
<!-- Permissions -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
</manifest>
+3
View File
@@ -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')
+9
View File
@@ -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)
}
}
+4
View File
@@ -49,5 +49,9 @@
<true/>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
</dict>
</plist>
+1
View File
@@ -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
+1
View File
@@ -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",
+47 -541
View File
@@ -4,6 +4,19 @@ settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
overrides:
'@welshman/app': ../welshman/packages/app
'@welshman/content': ../welshman/packages/content
'@welshman/editor': ../welshman/packages/editor
'@welshman/feeds': ../welshman/packages/feeds
'@welshman/lib': ../welshman/packages/lib
'@welshman/net': ../welshman/packages/net
'@welshman/relay': ../welshman/packages/relay
'@welshman/router': ../welshman/packages/router
'@welshman/signer': ../welshman/packages/signer
'@welshman/store': ../welshman/packages/store
'@welshman/util': ../welshman/packages/util
importers:
.:
@@ -29,6 +42,9 @@ importers:
'@capacitor/keyboard':
specifier: ^7.0.0
version: 7.0.1(@capacitor/core@7.2.0)
'@capacitor/push-notifications':
specifier: ^7.0.1
version: 7.0.1(@capacitor/core@7.2.0)
'@poppanator/sveltekit-svg':
specifier: ^4.2.1
version: 4.2.1(rollup@2.79.2)(svelte@5.25.10)(svgo@3.3.2)(vite@5.4.17(@types/node@22.14.0)(terser@5.39.0))
@@ -51,38 +67,38 @@ importers:
specifier: ^0.6.6
version: 0.6.8(@sveltejs/kit@2.20.5(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.25.10)(vite@5.4.17(@types/node@22.14.0)(terser@5.39.0)))(svelte@5.25.10)(vite@5.4.17(@types/node@22.14.0)(terser@5.39.0)))(@vite-pwa/assets-generator@0.2.6)(vite-plugin-pwa@0.21.2(@vite-pwa/assets-generator@0.2.6)(vite@5.4.17(@types/node@22.14.0)(terser@5.39.0))(workbox-build@7.3.0)(workbox-window@7.3.0))
'@welshman/app':
specifier: ^0.3.7
version: 0.3.7(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.2.0))(typescript@5.8.3)(ws@8.18.2)
specifier: ../welshman/packages/app
version: link:../welshman/packages/app
'@welshman/content':
specifier: ^0.3.7
version: 0.3.7(typescript@5.8.3)
specifier: ../welshman/packages/content
version: link:../welshman/packages/content
'@welshman/editor':
specifier: ^0.3.7
version: 0.3.7(@tiptap/extension-image@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0)))(@tiptap/extension-link@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))(@tiptap/pm@2.12.0))(linkifyjs@4.3.1)(prosemirror-markdown@1.13.2)(prosemirror-model@1.25.1)(prosemirror-state@1.4.3)(prosemirror-view@1.39.3)(tiptap-markdown@0.8.10(@tiptap/core@2.12.0(@tiptap/pm@2.12.0)))(typescript@5.8.3)
specifier: ../welshman/packages/editor
version: link:../welshman/packages/editor
'@welshman/feeds':
specifier: ^0.3.7
version: 0.3.7(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.2.0))(typescript@5.8.3)(ws@8.18.2)
specifier: ../welshman/packages/feeds
version: link:../welshman/packages/feeds
'@welshman/lib':
specifier: ^0.3.7
version: 0.3.7
specifier: ../welshman/packages/lib
version: link:../welshman/packages/lib
'@welshman/net':
specifier: ^0.3.7
version: 0.3.7(typescript@5.8.3)(ws@8.18.2)
specifier: ../welshman/packages/net
version: link:../welshman/packages/net
'@welshman/relay':
specifier: ^0.3.7
version: 0.3.7(typescript@5.8.3)
specifier: ../welshman/packages/relay
version: link:../welshman/packages/relay
'@welshman/router':
specifier: ^0.3.7
version: 0.3.7(typescript@5.8.3)
specifier: ../welshman/packages/router
version: link:../welshman/packages/router
'@welshman/signer':
specifier: ^0.3.7
version: 0.3.7(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.2.0))(typescript@5.8.3)(ws@8.18.2)
specifier: ../welshman/packages/signer
version: link:../welshman/packages/signer
'@welshman/store':
specifier: ^0.3.7
version: 0.3.7(typescript@5.8.3)
specifier: ../welshman/packages/store
version: link:../welshman/packages/store
'@welshman/util':
specifier: ^0.3.7
version: 0.3.7(typescript@5.8.3)
specifier: ../welshman/packages/util
version: link:../welshman/packages/util
compressorjs:
specifier: ^1.2.1
version: 1.2.1
@@ -691,9 +707,6 @@ packages:
resolution: {integrity: sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==}
engines: {node: '>=6.9.0'}
'@braintree/sanitize-url@7.1.1':
resolution: {integrity: sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw==}
'@canvas/image-data@1.0.0':
resolution: {integrity: sha512-BxOqI5LgsIQP1odU5KMwV9yoijleOPzHL18/YvNqF9KFSGF2K/DLlYAbDQsWqd/1nbaFuSkYD/191dpMtNh4vw==}
@@ -740,6 +753,11 @@ packages:
peerDependencies:
'@capacitor/core': '>=7.0.0'
'@capacitor/push-notifications@7.0.1':
resolution: {integrity: sha512-nSHsMSrTHX5pOkX1Khse75/uvSx/JTcXG+9aT6a66CvzalH6MCs0ha8Jv+xu0k9xW8caO+qSUMjfj5Oy82Uxmw==}
peerDependencies:
'@capacitor/core': '>=7.0.0'
'@cspotcode/source-map-support@0.8.1':
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'}
@@ -1037,10 +1055,6 @@ packages:
'@noble/curves@1.2.0':
resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==}
'@noble/curves@1.9.2':
resolution: {integrity: sha512-HxngEd2XUcg9xi20JkwlLCtYwfoFw4JGkuZpT+WlsPD4gB/cxkvTD8fSsoAnphGZhFdZYKeQIPCuFlWPm1uE0g==}
engines: {node: ^14.21.3 || >=16}
'@noble/hashes@1.3.1':
resolution: {integrity: sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==}
engines: {node: '>= 16'}
@@ -1049,10 +1063,6 @@ packages:
resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==}
engines: {node: '>= 16'}
'@noble/hashes@1.8.0':
resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==}
engines: {node: ^14.21.3 || >=16}
'@nodelib/fs.scandir@2.1.5':
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
@@ -1240,9 +1250,6 @@ packages:
'@scure/base@1.1.1':
resolution: {integrity: sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==}
'@scure/base@1.2.6':
resolution: {integrity: sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==}
'@scure/bip32@1.3.1':
resolution: {integrity: sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==}
@@ -1367,81 +1374,9 @@ packages:
peerDependencies:
'@tiptap/pm': ^2.7.0
'@tiptap/extension-code-block@2.14.0':
resolution: {integrity: sha512-LRYYZeh8U2XgfTsJ4houB9s9cVRt7PRfVa4MaCeOYKfowVOKQh67yV5oom8Azk9XrMPkPxDmMmdPAEPxeVYFvw==}
peerDependencies:
'@tiptap/core': ^2.7.0
'@tiptap/pm': ^2.7.0
'@tiptap/extension-code@2.14.0':
resolution: {integrity: sha512-kyo02mnzqgwXayMcyRA/fHQgb+nMmQQpIt1irZwjtEoFZshA7NnY/6b5SJmRcxQ4/X4r2Y2Ha2sWmOcEkLmt4A==}
peerDependencies:
'@tiptap/core': ^2.7.0
'@tiptap/extension-document@2.14.0':
resolution: {integrity: sha512-qwEgpPIJ3AgXdEtRTr88hODbXRdt14VAwLj27PTSqexB5V7Ra1Jy7iQDhqRwBCoUomVywBsWYxkSuDisSRG+9w==}
peerDependencies:
'@tiptap/core': ^2.7.0
'@tiptap/extension-dropcursor@2.14.0':
resolution: {integrity: sha512-FIh5cdPuoPKvZ0GqSKhzMZGixm05ac3hSgqhMNCBZmXX459qBUI9CvDl/uzSnY9koBDeLVV3HYMthWQQLSXl9A==}
peerDependencies:
'@tiptap/core': ^2.7.0
'@tiptap/pm': ^2.7.0
'@tiptap/extension-gapcursor@2.14.0':
resolution: {integrity: sha512-as+SqC39FRshw4Fm1XVlrdSXveiusf5xiC4nuefLmXsUxO7Yx67x8jS0/VQbxWTLHZ6R1YEW8prLtnxGmVLCAQ==}
peerDependencies:
'@tiptap/core': ^2.7.0
'@tiptap/pm': ^2.7.0
'@tiptap/extension-hard-break@2.14.0':
resolution: {integrity: sha512-A8c8n8881iBq3AusNqibh6Hloybr+FgYdg4Lg4jNxbbEaL0WhyLFge1bWlGVpbHXFqdv5YldMUAu6Rop3FhNvw==}
peerDependencies:
'@tiptap/core': ^2.7.0
'@tiptap/extension-history@2.14.0':
resolution: {integrity: sha512-/qnOHQFCEPfkb3caykqd+sqzEC2gx30EQB/mM7+5kIG7CQy7XXaGjFAEaqzE1xJ783Q2E7GVk4JxWM+3NhYSLw==}
peerDependencies:
'@tiptap/core': ^2.7.0
'@tiptap/pm': ^2.7.0
'@tiptap/extension-image@2.14.0':
resolution: {integrity: sha512-pYCUzZBgsxIvVGTzuW03cPz6PIrAo26xpoxqq4W090uMVoK0SgY5W5y0IqCdw4QyLkJ2/oNSFNc2EP9jVi1CcQ==}
peerDependencies:
'@tiptap/core': ^2.7.0
'@tiptap/extension-link@2.14.0':
resolution: {integrity: sha512-fsqW7eRD2xoD6xy7eFrNPAdIuZ3eicA4jKC45Vcft/Xky0DJoIehlVBLxsPbfmv3f27EBrtPkg5+msLXkLyzJA==}
peerDependencies:
'@tiptap/core': ^2.7.0
'@tiptap/pm': ^2.7.0
'@tiptap/extension-paragraph@2.14.0':
resolution: {integrity: sha512-bsQesVpgvDS2e+wr2fp59QO7rWRp2FqcJvBafwXS3Br9U5Mx3eFYryx4wC7cUnhlhUwX5pmaoA7zISgV9dZDgg==}
peerDependencies:
'@tiptap/core': ^2.7.0
'@tiptap/extension-placeholder@2.14.0':
resolution: {integrity: sha512-xzfjHvuukbch4i5O/5uyS2K2QgNEaMKi6e6GExTTgVwnFjKfJmgTqee33tt5JCqSItBvtSZlU3SX/vpiaIof+w==}
peerDependencies:
'@tiptap/core': ^2.7.0
'@tiptap/pm': ^2.7.0
'@tiptap/extension-text@2.14.0':
resolution: {integrity: sha512-rHny566nGZHq61zRLwQ9BPG55W/O+eDKwUJl+LhrLiVWwzpvAl9QQYixtoxJKOY48VK41PKwxe3bgDYgNs/Fhg==}
peerDependencies:
'@tiptap/core': ^2.7.0
'@tiptap/pm@2.12.0':
resolution: {integrity: sha512-TNzVwpeNzFfHAcYTOKqX9iU4fRxliyoZrCnERR+RRzeg7gWrXrCLubQt1WEx0sojMAfznshSL3M5HGsYjEbYwA==}
'@tiptap/suggestion@2.14.0':
resolution: {integrity: sha512-AXzEw0KYIyg5id8gz5geIffnBtkZqan5MWe29rGo3gXTfKH+Ik8tWbZdnlMVheycsUCllrymDRei4zw9DqVqkQ==}
peerDependencies:
'@tiptap/core': ^2.7.0
'@tiptap/pm': ^2.7.0
'@trapezedev/gradle-parse@7.1.3':
resolution: {integrity: sha512-WQVF5pEJ5o/mUyvfGTG9nBKx9Te/ilKM3r2IT69GlbaooItT5ao7RyF1MUTBNjHLPk/xpGUY3c6PyVnjDlz0Vw==}
@@ -1476,30 +1411,18 @@ packages:
'@types/estree@1.0.7':
resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==}
'@types/events@3.0.3':
resolution: {integrity: sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==}
'@types/fs-extra@8.1.5':
resolution: {integrity: sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==}
'@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
'@types/linkify-it@3.0.5':
resolution: {integrity: sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==}
'@types/linkify-it@5.0.0':
resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==}
'@types/markdown-it@13.0.9':
resolution: {integrity: sha512-1XPwR0+MgXLWfTn9gCsZ55AHOKW1WN+P9vr0PaQh5aerR9LLQXUbjfEAFhjmEmyoYFWAyuN2Mqkn40MZ4ukjBw==}
'@types/markdown-it@14.1.2':
resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==}
'@types/mdurl@1.0.5':
resolution: {integrity: sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==}
'@types/mdurl@2.0.0':
resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==}
@@ -1521,15 +1444,9 @@ packages:
'@types/slice-ansi@4.0.0':
resolution: {integrity: sha512-+OpjSaq85gvlZAYINyzKpLeiFkSC4EsC6IIiT6v6TLSU5k5U83fHGj9Lel8oKEXM0HqgrMVCjXPDPVICtxF7EQ==}
'@types/throttle-debounce@5.0.2':
resolution: {integrity: sha512-pDzSNulqooSKvSNcksnV72nk8p7gRqN8As71Sp28nov1IgmPKWbOEIwAWvBME5pPTtaXJAvG3O4oc76HlQ4kqQ==}
'@types/trusted-types@2.0.7':
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
'@types/ws@8.18.1':
resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==}
'@typescript-eslint/eslint-plugin@8.29.1':
resolution: {integrity: sha512-ba0rr4Wfvg23vERs3eB+P3lfj2E+2g3lhWcCVukUuhtcdUx5lSIFZlGFEBHKr+3zizDa/TvZTptdNHVZWAkSBg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -1593,42 +1510,6 @@ packages:
'@vite-pwa/assets-generator':
optional: true
'@welshman/app@0.3.7':
resolution: {integrity: sha512-YaI1J/N5H1jmmvbNNfGijclr6kaOpECcPMFG/ts2e2j04/4n78oMbJCOIaRuN8N9tpyVs130A9SP9GdMiQfH/A==}
'@welshman/content@0.3.7':
resolution: {integrity: sha512-wC6rN8KoVJ7iAFmGZ6LtPe32SjKOnBjRIwuSL3GiFS34D1wiBmLWeSXijksf0SZevGj+cgVm/N3+frhNuku4Gg==}
'@welshman/editor@0.3.7':
resolution: {integrity: sha512-HZsSLthhzXTUFkg+mwuev9hwIFPV+OzZDGyavKE8Y4Oof6hVLWSbTMmV9Kko6qSpyhJ+p5jWS1pYdkIlijBXAA==}
'@welshman/feeds@0.3.7':
resolution: {integrity: sha512-R4MDnfOLLHvRmHS5CNcCsORPLtk0DtdPGXQG5cwrkHs801JDEJUfiV3jCH5F7SBc0cBDV5VGaoUBUeVzBkuSpA==}
'@welshman/lib@0.3.7':
resolution: {integrity: sha512-Zx0xVNwqUNS2+oAjgpUKF2TYcwCnbCku83B2w2immlzy84Lb8pGbeD5WgJpilSbSPjMrzg9uQ7QjyYRj8xc7DA==}
engines: {node: '>=12.0.0'}
'@welshman/net@0.3.7':
resolution: {integrity: sha512-vDjKhT4mpDPoNNwtAnIgsn/5yKhfzHtsseF/xq8JtvdvJ5KULmTkntMk9Lug1MkaUYa7QOBmuDsl87WlSJYGew==}
'@welshman/relay@0.3.7':
resolution: {integrity: sha512-aF0jeeUWn93iRF5HucrlFw1Sqfi1K4q+ofQ8+XBYULTkiOYWybDb+P139fOq/NzIESoTIxSMAzjTrSzNFUqmag==}
'@welshman/router@0.3.7':
resolution: {integrity: sha512-A/n4SiMTzpRt8HjhLwtiZ9kiCynt/fDuKSjnPsfNw9b6t/ayLEjRICF6x0X9tlzAMUp4SXsfe0dqA9kGb1Ic/A==}
'@welshman/signer@0.3.7':
resolution: {integrity: sha512-OSnP5vmZkhquh1aapW7r15seunbojcfYD90HvX3IWWiIq6Oldsu0/djQUhEv4wg9fi9h6+zClU+QZkB6lfMTfw==}
peerDependencies:
nostr-signer-capacitor-plugin: ~0.0.4
'@welshman/store@0.3.7':
resolution: {integrity: sha512-fE9PAMQvvgAzZ9soRm5QERpMAMD4D4GflOX1VAIo6gSm6WO8EUxy4mGjUD/k6kmFOt39txZsOdjvV0CfMru2Lg==}
'@welshman/util@0.3.7':
resolution: {integrity: sha512-loKAc2V182PCln9typ94wF7NeHmz2UYwiudB/DCFUGogKDtziZn6eIolL7A5Bvo3aVUs+BbaRUA18kL35Uq9jg==}
'@xml-tools/parser@1.0.11':
resolution: {integrity: sha512-aKqQ077XnR+oQtHJlrAflaZaL7qZsulWc/i/ZEooar5JiWj1eLt0+Wg28cpa+XLney107wXqneC+oG1IZvxkTA==}
@@ -1956,9 +1837,6 @@ packages:
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
engines: {node: '>=6'}
code-red@1.0.4:
resolution: {integrity: sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==}
color-convert@1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
@@ -2473,17 +2351,10 @@ packages:
estree-walker@2.0.2:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
estree-walker@3.0.3:
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
esutils@2.0.3:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'}
events@3.3.0:
resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
engines: {node: '>=0.8.x'}
expand-template@2.0.3:
resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==}
engines: {node: '>=6'}
@@ -3003,11 +2874,6 @@ packages:
isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
isomorphic-ws@5.0.0:
resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==}
peerDependencies:
ws: '*'
jackspeak@3.4.3:
resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
@@ -3024,9 +2890,6 @@ packages:
resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==}
hasBin: true
js-base64@3.7.7:
resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==}
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
@@ -3113,9 +2976,6 @@ packages:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'}
light-bolt11-decoder@3.2.0:
resolution: {integrity: sha512-3QEofgiBOP4Ehs9BI+RkZdXZNtSys0nsJ6fyGeSiAGCBsMwHGUDS/JQlY/sTnWs91A2Nh0S9XXfA8Sy9g6QpuQ==}
lilconfig@2.1.0:
resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==}
engines: {node: '>=10'}
@@ -3130,9 +2990,6 @@ packages:
linkify-it@5.0.0:
resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==}
linkifyjs@4.3.1:
resolution: {integrity: sha512-DRSlB9DKVW04c4SUdGvKK5FR6be45lTU9M76JnngqPeeGDqPwYc0zdUErtsNVMtxPXgUWV4HbXbnC4sNyBxkYg==}
load-json-file@4.0.0:
resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==}
engines: {node: '>=4'}
@@ -3198,9 +3055,6 @@ packages:
resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==}
engines: {node: '>=8'}
markdown-it-task-lists@2.1.1:
resolution: {integrity: sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA==}
markdown-it@14.1.0:
resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==}
hasBin: true
@@ -3375,22 +3229,6 @@ packages:
resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==}
engines: {node: '>=0.10.0'}
nostr-editor@1.0.0:
resolution: {integrity: sha512-+TL3G0m7WsXeEAitxzQhun7hyARxqRANjGIS2z9CBbniCGvT/Wz6YLgUnUysnBg3tmSgMZg5FWhaDPwfvdvbSw==}
engines: {node: '>=18.16.1'}
peerDependencies:
'@tiptap/core': ^2.6.6
'@tiptap/extension-image': ^2.6.6
'@tiptap/extension-link': ^2.6.6
'@tiptap/pm': ^2.6.6
linkifyjs: ^4.1.3
nostr-tools: ~2.14.2
prosemirror-markdown: ^1.13.0
prosemirror-model: ^1.22.3
prosemirror-state: ^1.4.3
prosemirror-view: ^1.39.3
tiptap-markdown: ^0.8.10
nostr-signer-capacitor-plugin@0.0.4:
resolution: {integrity: sha512-cuoTUULKE6g+CQmFgz3R5yP6OD4o5owvU1LdS+GdO5ElMdaBPlwiBzWSQpl6eYOFCqkGukhnXNEUWhgvUpgymg==}
peerDependencies:
@@ -3537,9 +3375,6 @@ packages:
pend@1.2.0:
resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
periscopic@3.1.0:
resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==}
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@@ -4245,10 +4080,6 @@ packages:
svelte:
optional: true
svelte@4.2.20:
resolution: {integrity: sha512-eeEgGc2DtiUil5ANdtd8vPwt9AgaMdnuUFnPft9F5oMvU/FHu5IHFic+p1dR/UOB7XU2mX2yHW+NcTch4DCh5Q==}
engines: {node: '>=16'}
svelte@5.25.10:
resolution: {integrity: sha512-tOUlvm3goAhmELYKWYX3SchYeqlVlIcUfKA4qIgd6Urm7qDw3KiZP/wJtoRv3ZeRUHPorM9f6+lOlbFxUN8QoA==}
engines: {node: '>=18'}
@@ -4311,10 +4142,6 @@ packages:
thenify@3.3.1:
resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
throttle-debounce@5.0.2:
resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==}
engines: {node: '>=12.22'}
through2@2.0.5:
resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==}
@@ -4331,11 +4158,6 @@ packages:
tippy.js@6.3.7:
resolution: {integrity: sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==}
tiptap-markdown@0.8.10:
resolution: {integrity: sha512-iDVkR2BjAqkTDtFX0h94yVvE2AihCXlF0Q7RIXSJPRSR5I0PA1TMuAg6FHFpmqTn4tPxJ0by0CK7PUMlnFLGEQ==}
peerDependencies:
'@tiptap/core': ^2.0.3
tmp@0.2.3:
resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==}
engines: {node: '>=14.14'}
@@ -4357,10 +4179,6 @@ packages:
tr46@1.0.1:
resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==}
trava@1.2.1:
resolution: {integrity: sha512-2dt4qJEVtYIwCoihoO+HfVLN+uid7ibtKnZ4pjLF4YqyDOwGuP0uTGLTUnvNkAp92qh3YmgRv4wojxnj5yBPAQ==}
engines: {node: '>=6.0.0', npm: '>=4.0.0'}
tree-kill@1.2.2:
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
hasBin: true
@@ -4682,18 +4500,6 @@ packages:
wrappy@1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
ws@8.18.2:
resolution: {integrity: sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==}
engines: {node: '>=10.0.0'}
peerDependencies:
bufferutil: ^4.0.1
utf-8-validate: '>=5.0.2'
peerDependenciesMeta:
bufferutil:
optional: true
utf-8-validate:
optional: true
xcode@3.0.1:
resolution: {integrity: sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==}
engines: {node: '>=10.0.0'}
@@ -5447,8 +5253,6 @@ snapshots:
'@babel/helper-string-parser': 7.25.9
'@babel/helper-validator-identifier': 7.25.9
'@braintree/sanitize-url@7.1.1': {}
'@canvas/image-data@1.0.0': {}
'@capacitor-community/safe-area@7.0.0-alpha.1(@capacitor/core@7.2.0)':
@@ -5542,6 +5346,10 @@ snapshots:
dependencies:
'@capacitor/core': 7.2.0
'@capacitor/push-notifications@7.0.1(@capacitor/core@7.2.0)':
dependencies:
'@capacitor/core': 7.2.0
'@cspotcode/source-map-support@0.8.1':
dependencies:
'@jridgewell/trace-mapping': 0.3.9
@@ -5847,16 +5655,10 @@ snapshots:
dependencies:
'@noble/hashes': 1.3.2
'@noble/curves@1.9.2':
dependencies:
'@noble/hashes': 1.8.0
'@noble/hashes@1.3.1': {}
'@noble/hashes@1.3.2': {}
'@noble/hashes@1.8.0': {}
'@nodelib/fs.scandir@2.1.5':
dependencies:
'@nodelib/fs.stat': 2.0.5
@@ -6002,8 +5804,6 @@ snapshots:
'@scure/base@1.1.1': {}
'@scure/base@1.2.6': {}
'@scure/bip32@1.3.1':
dependencies:
'@noble/curves': 1.1.0
@@ -6145,61 +5945,6 @@ snapshots:
dependencies:
'@tiptap/pm': 2.12.0
'@tiptap/extension-code-block@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))(@tiptap/pm@2.12.0)':
dependencies:
'@tiptap/core': 2.12.0(@tiptap/pm@2.12.0)
'@tiptap/pm': 2.12.0
'@tiptap/extension-code@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))':
dependencies:
'@tiptap/core': 2.12.0(@tiptap/pm@2.12.0)
'@tiptap/extension-document@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))':
dependencies:
'@tiptap/core': 2.12.0(@tiptap/pm@2.12.0)
'@tiptap/extension-dropcursor@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))(@tiptap/pm@2.12.0)':
dependencies:
'@tiptap/core': 2.12.0(@tiptap/pm@2.12.0)
'@tiptap/pm': 2.12.0
'@tiptap/extension-gapcursor@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))(@tiptap/pm@2.12.0)':
dependencies:
'@tiptap/core': 2.12.0(@tiptap/pm@2.12.0)
'@tiptap/pm': 2.12.0
'@tiptap/extension-hard-break@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))':
dependencies:
'@tiptap/core': 2.12.0(@tiptap/pm@2.12.0)
'@tiptap/extension-history@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))(@tiptap/pm@2.12.0)':
dependencies:
'@tiptap/core': 2.12.0(@tiptap/pm@2.12.0)
'@tiptap/pm': 2.12.0
'@tiptap/extension-image@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))':
dependencies:
'@tiptap/core': 2.12.0(@tiptap/pm@2.12.0)
'@tiptap/extension-link@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))(@tiptap/pm@2.12.0)':
dependencies:
'@tiptap/core': 2.12.0(@tiptap/pm@2.12.0)
'@tiptap/pm': 2.12.0
linkifyjs: 4.3.1
'@tiptap/extension-paragraph@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))':
dependencies:
'@tiptap/core': 2.12.0(@tiptap/pm@2.12.0)
'@tiptap/extension-placeholder@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))(@tiptap/pm@2.12.0)':
dependencies:
'@tiptap/core': 2.12.0(@tiptap/pm@2.12.0)
'@tiptap/pm': 2.12.0
'@tiptap/extension-text@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))':
dependencies:
'@tiptap/core': 2.12.0(@tiptap/pm@2.12.0)
'@tiptap/pm@2.12.0':
dependencies:
prosemirror-changeset: 2.3.0
@@ -6221,11 +5966,6 @@ snapshots:
prosemirror-transform: 1.10.4
prosemirror-view: 1.39.3
'@tiptap/suggestion@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))(@tiptap/pm@2.12.0)':
dependencies:
'@tiptap/core': 2.12.0(@tiptap/pm@2.12.0)
'@tiptap/pm': 2.12.0
'@trapezedev/gradle-parse@7.1.3': {}
'@trapezedev/project@7.1.3(@types/node@22.14.0)(typescript@5.8.3)':
@@ -6283,30 +6023,19 @@ snapshots:
'@types/estree@1.0.7': {}
'@types/events@3.0.3': {}
'@types/fs-extra@8.1.5':
dependencies:
'@types/node': 22.14.0
'@types/json-schema@7.0.15': {}
'@types/linkify-it@3.0.5': {}
'@types/linkify-it@5.0.0': {}
'@types/markdown-it@13.0.9':
dependencies:
'@types/linkify-it': 3.0.5
'@types/mdurl': 1.0.5
'@types/markdown-it@14.1.2':
dependencies:
'@types/linkify-it': 5.0.0
'@types/mdurl': 2.0.0
'@types/mdurl@1.0.5': {}
'@types/mdurl@2.0.0': {}
'@types/minimist@1.2.5': {}
@@ -6325,14 +6054,8 @@ snapshots:
'@types/slice-ansi@4.0.0': {}
'@types/throttle-debounce@5.0.2': {}
'@types/trusted-types@2.0.7': {}
'@types/ws@8.18.1':
dependencies:
'@types/node': 22.14.0
'@typescript-eslint/eslint-plugin@8.29.1(@typescript-eslint/parser@8.29.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3)':
dependencies:
'@eslint-community/regexpp': 4.12.1
@@ -6430,142 +6153,6 @@ snapshots:
optionalDependencies:
'@vite-pwa/assets-generator': 0.2.6
'@welshman/app@0.3.7(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.2.0))(typescript@5.8.3)(ws@8.18.2)':
dependencies:
'@types/throttle-debounce': 5.0.2
'@welshman/feeds': 0.3.7(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.2.0))(typescript@5.8.3)(ws@8.18.2)
'@welshman/lib': 0.3.7
'@welshman/net': 0.3.7(typescript@5.8.3)(ws@8.18.2)
'@welshman/relay': 0.3.7(typescript@5.8.3)
'@welshman/router': 0.3.7(typescript@5.8.3)
'@welshman/signer': 0.3.7(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.2.0))(typescript@5.8.3)(ws@8.18.2)
'@welshman/store': 0.3.7(typescript@5.8.3)
'@welshman/util': 0.3.7(typescript@5.8.3)
fuse.js: 7.1.0
idb: 8.0.2
svelte: 4.2.20
throttle-debounce: 5.0.2
transitivePeerDependencies:
- nostr-signer-capacitor-plugin
- typescript
- ws
'@welshman/content@0.3.7(typescript@5.8.3)':
dependencies:
'@braintree/sanitize-url': 7.1.1
nostr-tools: 2.14.2(typescript@5.8.3)
transitivePeerDependencies:
- typescript
'@welshman/editor@0.3.7(@tiptap/extension-image@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0)))(@tiptap/extension-link@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))(@tiptap/pm@2.12.0))(linkifyjs@4.3.1)(prosemirror-markdown@1.13.2)(prosemirror-model@1.25.1)(prosemirror-state@1.4.3)(prosemirror-view@1.39.3)(tiptap-markdown@0.8.10(@tiptap/core@2.12.0(@tiptap/pm@2.12.0)))(typescript@5.8.3)':
dependencies:
'@tiptap/core': 2.12.0(@tiptap/pm@2.12.0)
'@tiptap/extension-code': 2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))
'@tiptap/extension-code-block': 2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))(@tiptap/pm@2.12.0)
'@tiptap/extension-document': 2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))
'@tiptap/extension-dropcursor': 2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))(@tiptap/pm@2.12.0)
'@tiptap/extension-gapcursor': 2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))(@tiptap/pm@2.12.0)
'@tiptap/extension-hard-break': 2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))
'@tiptap/extension-history': 2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))(@tiptap/pm@2.12.0)
'@tiptap/extension-paragraph': 2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))
'@tiptap/extension-placeholder': 2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))(@tiptap/pm@2.12.0)
'@tiptap/extension-text': 2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))
'@tiptap/pm': 2.12.0
'@tiptap/suggestion': 2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))(@tiptap/pm@2.12.0)
'@welshman/lib': 0.3.7
'@welshman/util': 0.3.7(typescript@5.8.3)
nostr-editor: 1.0.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))(@tiptap/extension-image@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0)))(@tiptap/extension-link@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))(@tiptap/pm@2.12.0))(@tiptap/pm@2.12.0)(linkifyjs@4.3.1)(nostr-tools@2.14.2(typescript@5.8.3))(prosemirror-markdown@1.13.2)(prosemirror-model@1.25.1)(prosemirror-state@1.4.3)(prosemirror-view@1.39.3)(tiptap-markdown@0.8.10(@tiptap/core@2.12.0(@tiptap/pm@2.12.0)))
nostr-tools: 2.14.2(typescript@5.8.3)
tippy.js: 6.3.7
transitivePeerDependencies:
- '@tiptap/extension-image'
- '@tiptap/extension-link'
- linkifyjs
- prosemirror-markdown
- prosemirror-model
- prosemirror-state
- prosemirror-view
- tiptap-markdown
- typescript
'@welshman/feeds@0.3.7(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.2.0))(typescript@5.8.3)(ws@8.18.2)':
dependencies:
'@welshman/lib': 0.3.7
'@welshman/net': 0.3.7(typescript@5.8.3)(ws@8.18.2)
'@welshman/relay': 0.3.7(typescript@5.8.3)
'@welshman/router': 0.3.7(typescript@5.8.3)
'@welshman/signer': 0.3.7(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.2.0))(typescript@5.8.3)(ws@8.18.2)
'@welshman/util': 0.3.7(typescript@5.8.3)
trava: 1.2.1
transitivePeerDependencies:
- nostr-signer-capacitor-plugin
- typescript
- ws
'@welshman/lib@0.3.7':
dependencies:
'@scure/base': 1.2.6
'@types/events': 3.0.3
events: 3.3.0
'@welshman/net@0.3.7(typescript@5.8.3)(ws@8.18.2)':
dependencies:
'@welshman/lib': 0.3.7
'@welshman/relay': 0.3.7(typescript@5.8.3)
'@welshman/util': 0.3.7(typescript@5.8.3)
events: 3.3.0
isomorphic-ws: 5.0.0(ws@8.18.2)
transitivePeerDependencies:
- typescript
- ws
'@welshman/relay@0.3.7(typescript@5.8.3)':
dependencies:
'@welshman/lib': 0.3.7
'@welshman/util': 0.3.7(typescript@5.8.3)
transitivePeerDependencies:
- typescript
'@welshman/router@0.3.7(typescript@5.8.3)':
dependencies:
'@welshman/lib': 0.3.7
'@welshman/relay': 0.3.7(typescript@5.8.3)
'@welshman/util': 0.3.7(typescript@5.8.3)
transitivePeerDependencies:
- typescript
'@welshman/signer@0.3.7(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.2.0))(typescript@5.8.3)(ws@8.18.2)':
dependencies:
'@noble/curves': 1.9.2
'@noble/hashes': 1.8.0
'@welshman/lib': 0.3.7
'@welshman/net': 0.3.7(typescript@5.8.3)(ws@8.18.2)
'@welshman/util': 0.3.7(typescript@5.8.3)
nostr-signer-capacitor-plugin: 0.0.4(@capacitor/core@7.2.0)
nostr-tools: 2.14.2(typescript@5.8.3)
transitivePeerDependencies:
- typescript
- ws
'@welshman/store@0.3.7(typescript@5.8.3)':
dependencies:
'@welshman/lib': 0.3.7
'@welshman/relay': 0.3.7(typescript@5.8.3)
'@welshman/util': 0.3.7(typescript@5.8.3)
svelte: 4.2.20
transitivePeerDependencies:
- typescript
'@welshman/util@0.3.7(typescript@5.8.3)':
dependencies:
'@types/ws': 8.18.1
'@welshman/lib': 0.3.7
js-base64: 3.7.7
nostr-tools: 2.14.2(typescript@5.8.3)
nostr-wasm: 0.1.0
transitivePeerDependencies:
- typescript
'@xml-tools/parser@1.0.11':
dependencies:
chevrotain: 7.1.1
@@ -6894,14 +6481,6 @@ snapshots:
clsx@2.1.1: {}
code-red@1.0.4:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.0
'@types/estree': 1.0.7
acorn: 8.14.1
estree-walker: 3.0.3
periscopic: 3.1.0
color-convert@1.9.3:
dependencies:
color-name: 1.1.3
@@ -7540,14 +7119,8 @@ snapshots:
estree-walker@2.0.2: {}
estree-walker@3.0.3:
dependencies:
'@types/estree': 1.0.7
esutils@2.0.3: {}
events@3.3.0: {}
expand-template@2.0.3: {}
fast-deep-equal@3.1.3: {}
@@ -8057,10 +7630,6 @@ snapshots:
isexe@2.0.0: {}
isomorphic-ws@5.0.0(ws@8.18.2):
dependencies:
ws: 8.18.2
jackspeak@3.4.3:
dependencies:
'@isaacs/cliui': 8.0.2
@@ -8080,8 +7649,6 @@ snapshots:
jiti@1.21.7: {}
js-base64@3.7.7: {}
js-tokens@4.0.0: {}
js-yaml@4.1.0:
@@ -8141,10 +7708,6 @@ snapshots:
prelude-ls: 1.2.1
type-check: 0.4.0
light-bolt11-decoder@3.2.0:
dependencies:
'@scure/base': 1.1.1
lilconfig@2.1.0: {}
lilconfig@3.1.3: {}
@@ -8155,8 +7718,6 @@ snapshots:
dependencies:
uc.micro: 2.1.0
linkifyjs@4.3.1: {}
load-json-file@4.0.0:
dependencies:
graceful-fs: 4.2.11
@@ -8215,8 +7776,6 @@ snapshots:
map-obj@4.3.0: {}
markdown-it-task-lists@2.1.1: {}
markdown-it@14.1.0:
dependencies:
argparse: 2.0.1
@@ -8391,22 +7950,6 @@ snapshots:
normalize-range@0.1.2: {}
nostr-editor@1.0.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))(@tiptap/extension-image@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0)))(@tiptap/extension-link@2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))(@tiptap/pm@2.12.0))(@tiptap/pm@2.12.0)(linkifyjs@4.3.1)(nostr-tools@2.14.2(typescript@5.8.3))(prosemirror-markdown@1.13.2)(prosemirror-model@1.25.1)(prosemirror-state@1.4.3)(prosemirror-view@1.39.3)(tiptap-markdown@0.8.10(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))):
dependencies:
'@tiptap/core': 2.12.0(@tiptap/pm@2.12.0)
'@tiptap/extension-image': 2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))
'@tiptap/extension-link': 2.14.0(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))(@tiptap/pm@2.12.0)
'@tiptap/pm': 2.12.0
js-base64: 3.7.7
light-bolt11-decoder: 3.2.0
linkifyjs: 4.3.1
nostr-tools: 2.14.2(typescript@5.8.3)
prosemirror-markdown: 1.13.2
prosemirror-model: 1.25.1
prosemirror-state: 1.4.3
prosemirror-view: 1.39.3
tiptap-markdown: 0.8.10(@tiptap/core@2.12.0(@tiptap/pm@2.12.0))
nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.2.0):
dependencies:
'@capacitor/core': 7.2.0
@@ -8551,12 +8094,6 @@ snapshots:
pend@1.2.0: {}
periscopic@3.1.0:
dependencies:
'@types/estree': 1.0.7
estree-walker: 3.0.3
is-reference: 3.0.3
picocolors@1.1.1: {}
picomatch@2.3.1: {}
@@ -9327,23 +8864,6 @@ snapshots:
optionalDependencies:
svelte: 5.25.10
svelte@4.2.20:
dependencies:
'@ampproject/remapping': 2.3.0
'@jridgewell/sourcemap-codec': 1.5.0
'@jridgewell/trace-mapping': 0.3.25
'@types/estree': 1.0.7
acorn: 8.14.1
aria-query: 5.3.2
axobject-query: 4.1.0
code-red: 1.0.4
css-tree: 2.3.1
estree-walker: 3.0.3
is-reference: 3.0.3
locate-character: 3.0.0
magic-string: 0.30.17
periscopic: 3.1.0
svelte@5.25.10:
dependencies:
'@ampproject/remapping': 2.3.0
@@ -9476,8 +8996,6 @@ snapshots:
dependencies:
any-promise: 1.3.0
throttle-debounce@5.0.2: {}
through2@2.0.5:
dependencies:
readable-stream: 2.3.8
@@ -9498,14 +9016,6 @@ snapshots:
dependencies:
'@popperjs/core': 2.11.8
tiptap-markdown@0.8.10(@tiptap/core@2.12.0(@tiptap/pm@2.12.0)):
dependencies:
'@tiptap/core': 2.12.0(@tiptap/pm@2.12.0)
'@types/markdown-it': 13.0.9
markdown-it: 14.1.0
markdown-it-task-lists: 2.1.1
prosemirror-markdown: 1.13.2
tmp@0.2.3: {}
to-data-view@1.1.0: {}
@@ -9522,8 +9032,6 @@ snapshots:
dependencies:
punycode: 2.3.1
trava@1.2.1: {}
tree-kill@1.2.2: {}
trim-newlines@3.0.1: {}
@@ -9907,8 +9415,6 @@ snapshots:
wrappy@1.0.2: {}
ws@8.18.2: {}
xcode@3.0.1:
dependencies:
simple-plist: 1.3.1
+11 -6
View File
@@ -1,6 +1,5 @@
import * as nip19 from "nostr-tools/nip19"
import {get} from "svelte/store"
import {Capacitor} from "@capacitor/core"
import {randomId, flatten, poll, uniq, equals, TIMEZONE, LOCALE} from "@welshman/lib"
import type {Feed} from "@welshman/feeds"
import type {TrustedEvent, EventContent} from "@welshman/util"
@@ -21,6 +20,7 @@ import {
ALERT_ANDROID,
isSignedEvent,
makeEvent,
getAddress,
displayProfile,
normalizeRelayUrl,
makeList,
@@ -62,8 +62,8 @@ import {
NOTIFIER_PUBKEY,
NOTIFIER_RELAY,
userRoomsByUrl,
deviceAlertAddresses,
} from "@app/state"
import {getPushInfo} from "@app/push"
// Utils
@@ -388,10 +388,10 @@ export type AlertParams = {
auth: string
}
ios?: {
nothing: string
device_token: string
}
android?: {
nothing: string
device_token: string
}
}
@@ -433,5 +433,10 @@ export const makeAlert = async (params: AlertParams) => {
})
}
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]})
}
+40 -9
View File
@@ -1,18 +1,28 @@
<script lang="ts">
import {onMount} from "svelte"
import {preventDefault} from "@lib/html"
import {randomInt, displayList, TIMEZONE, identity} from "@welshman/lib"
import {displayRelayUrl, getTagValue, THREAD, MESSAGE, EVENT_TIME, COMMENT} from "@welshman/util"
import {ucFirst} from "@lib/util"
import {decrypt} from "@welshman/signer"
import {randomInt, parseJson, fromPairs, displayList, TIMEZONE, identity} from "@welshman/lib"
import {
displayRelayUrl,
getTagValue,
getAddress,
THREAD,
MESSAGE,
EVENT_TIME,
COMMENT,
} from "@welshman/util"
import type {Filter} from "@welshman/util"
import {makeIntersectionFeed, makeRelayFeed, feedFromFilters} from "@welshman/feeds"
import {pubkey} from "@welshman/app"
import {pubkey, signer, getThunkError} from "@welshman/app"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import FieldInline from "@lib/components/FieldInline.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte"
import {alerts, getMembershipUrls, getMembershipRoomsByUrl, userMembership} from "@app/state"
import {alerts, getMembershipUrls, userMembership, NOTIFIER_PUBKEY} from "@app/state"
import {loadAlertStatuses, requestRelayClaims} from "@app/requests"
import {publishAlert} from "@app/commands"
import type {AlertParams} from "@app/commands"
@@ -114,20 +124,41 @@
try {
// @ts-ignore
params[platform] = await getPushInfo()
params.description = `${ucFirst(platform)} push notification ${description}.`
} catch (e: any) {
return pushToast({
theme: "error",
message: String(e),
})
}
params.description = `Push notification alert ${description}.`
}
const thunk = await publishAlert(params)
// If we don't do this we'll get an event rejection
await Pool.get().get(NOTIFIER_RELAY).auth.attemptAuth()
await thunk.result
await loadAlertStatuses($pubkey!)
const thunk = await publishAlert(params)
const error = await getThunkError(thunk)
if (error) {
return pushToast({
theme: "error",
message: `Failed to send your alert to the notification server (${error}).`,
})
}
// Fetch our new status to make sure it's active
const address = getAddress(thunk.event)
const statusEvents = await loadAlertStatuses($pubkey!)
const statusEvent = statusEvents.find(event => getTagValue("d", event.tags) === address)
const statusTags = statusEvent
? parseJson(await decrypt(signer.get(), NOTIFIER_PUBKEY, statusEvent.content))
: []
const {status = "error", message = "Your alert was not activated"}: Record<string, string> =
fromPairs(statusTags)
if (status === "error") {
return pushToast({theme: "error", message})
}
pushToast({message: "Your alert has been successfully created!"})
back()
+8 -9
View File
@@ -1,12 +1,12 @@
<script lang="ts">
import {parseJson, nthEq} from "@welshman/lib"
import {parseJson} from "@welshman/lib"
import {displayFeeds} from "@welshman/feeds"
import {getAddress, getTagValue, getTagValues} from "@welshman/util"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import AlertDelete from "@app/components/AlertDelete.svelte"
import type {Alert} from "@app/state"
import {alertStatuses} from "@app/state"
import {deriveAlertStatus} from "@app/state"
import {pushModal} from "@app/modal"
type Props = {
@@ -15,8 +15,7 @@
const {alert}: Props = $props()
const address = $derived(getAddress(alert.event))
const status = $derived($alertStatuses.find(s => s.event.tags.some(nthEq(1, address))))
const status = deriveAlertStatus(getAddress(alert.event))
const cron = $derived(getTagValue("cron", alert.tags))
const channel = $derived(getTagValue("channel", alert.tags))
const feeds = $derived(getTagValues("feed", alert.tags))
@@ -39,24 +38,24 @@
</Button>
<div class="flex-inline gap-1">{description}</div>
</div>
{#if status}
{@const statusText = getTagValue("status", status.tags) || "error"}
{#if $status}
{@const statusText = getTagValue("status", $status.tags) || "error"}
{#if statusText === "ok"}
<span
class="tooltip tooltip-left cursor-pointer rounded-full border border-solid border-base-content px-3 py-1 text-sm"
data-tip={getTagValue("message", status.tags)}>
data-tip={getTagValue("message", $status.tags)}>
Active
</span>
{:else if statusText === "pending"}
<span
class="tooltip tooltip-left cursor-pointer rounded-full border border-solid border-base-content border-yellow-500 px-3 py-1 text-sm text-yellow-500"
data-tip={getTagValue("message", status.tags)}>
data-tip={getTagValue("message", $status.tags)}>
Pending
</span>
{:else}
<span
class="tooltip tooltip-left cursor-pointer rounded-full border border-solid border-error px-3 py-1 text-sm text-error"
data-tip={getTagValue("message", status.tags)}>
data-tip={getTagValue("message", $status.tags)}>
{statusText.replace("-", " ").replace(/^(.)/, x => x.toUpperCase())}
</span>
{/if}
+2 -2
View File
@@ -24,8 +24,8 @@
memberships,
deriveUserRooms,
deriveOtherRooms,
deviceAlerts,
hasNip29,
alerts,
} from "@app/state"
import {loadAlerts} from "@app/requests"
import {notifications} from "@app/notifications"
@@ -40,7 +40,7 @@
const calendarPath = makeSpacePath(url, "calendar")
const userRooms = deriveUserRooms(url)
const otherRooms = deriveOtherRooms(url)
const alert = $derived($alerts.find(a => getTagValue("feed", a.tags)?.includes(url)))
const alert = $derived($deviceAlerts.find(a => getTagValue("feed", a.tags)?.includes(url)))
const openMenu = () => {
showMenu = true
+51 -8
View File
@@ -1,8 +1,28 @@
import * as nip19 from "nostr-tools/nip19"
import {Capacitor} from "@capacitor/core"
import type {ActionPerformed, RegistrationError, Token} from "@capacitor/push-notifications"
import {PushNotifications} from "@capacitor/push-notifications"
import {sleep, parseJson} from "@welshman/lib"
import {isSignedEvent} from "@welshman/util"
import {goto} from "$app/navigation"
import {VAPID_PUBLIC_KEY} from "@app/state"
export const platform = Capacitor.getPlatform()
export const initializePushNotifications = () => {
if (platform === "web") return
PushNotifications.addListener("pushNotificationActionPerformed", (action: ActionPerformed) => {
const event = parseJson(action.notification.data.event)
const parsedRelays = parseJson(action.notification.data.relays)
const relays = Array.isArray(parsedRelays) ? parsedRelays : []
if (isSignedEvent(event)) {
goto("/" + nip19.neventEncode({id: event.id, relays}))
}
})
}
export const canSendPushNotifications = () => ["web", "android", "ios"].includes(platform)
export const getWebPushInfo = async () => {
@@ -36,7 +56,7 @@ export const getWebPushInfo = async () => {
})
}
const {endpoint, keys} = subscription.toJSON()
const {keys} = subscription.toJSON()
if (!keys) {
throw new Error(`Failed to get push info: no keys were returned`)
@@ -49,12 +69,36 @@ export const getWebPushInfo = async () => {
}
}
export const getIosPushInfo = async () => {
return {}
}
export const getCapacitorPushInfo = async () => {
let status = await PushNotifications.checkPermissions()
export const getAndroidPushInfo = async () => {
return {}
if (status.receive === "prompt") {
status = await PushNotifications.requestPermissions()
}
if (status.receive !== "granted") {
throw new Error("Failed to register for push notifications")
}
let device_token = ""
let error = "Failed to register for push notifications"
PushNotifications.addListener("registration", (token: Token) => {
device_token = token.value
})
PushNotifications.addListener("registrationError", (_error: RegistrationError) => {
error = _error.error
})
await PushNotifications.register()
await sleep(100)
if (!device_token) {
throw new Error(error)
}
return {device_token}
}
export const getPushInfo = (): Promise<Record<string, string>> => {
@@ -62,9 +106,8 @@ export const getPushInfo = (): Promise<Record<string, string>> => {
case "web":
return getWebPushInfo()
case "ios":
return getIosPushInfo()
case "android":
return getAndroidPushInfo()
return getCapacitorPushInfo()
default:
throw new Error(`Invalid push platform: ${platform}`)
}
+3 -1
View File
@@ -367,7 +367,7 @@ export const listenForNotifications = () => {
for (const [url, allRooms] of userRoomsByUrl.get()) {
// Limit how many rooms we load at a time, since we have to send a separate filter
// for each one due to nip 29 breaking postel's law
// for each one due to relay29 being picky
const rooms = shuffle(Array.from(allRooms)).slice(0, 30)
load({
@@ -375,6 +375,7 @@ export const listenForNotifications = () => {
relays: [url],
filters: [
{kinds: [THREAD], limit: 1},
{kinds: [MESSAGE], limit: 1},
{kinds: [COMMENT], "#K": [String(THREAD)], limit: 1},
...rooms.map(room => ({kinds: [MESSAGE], "#h": [room], limit: 1})),
],
@@ -385,6 +386,7 @@ export const listenForNotifications = () => {
relays: [url],
filters: [
{kinds: [THREAD], since: now()},
{kinds: [MESSAGE], since: now()},
{kinds: [COMMENT], "#K": [String(THREAD)], since: now()},
...rooms.map(room => ({kinds: [MESSAGE], "#h": [room], since: now()})),
],
+3 -3
View File
@@ -69,7 +69,7 @@ export const goToEvent = async (event: TrustedEvent, options: Record<string, any
const urls = Array.from(tracker.getRelays(event.id))
const path = await getEventPath(event, urls)
if (path.includes('://')) {
if (path.includes("://")) {
window.open(path)
} else {
goto(path, options)
@@ -94,7 +94,7 @@ export const getEventPath = async (event: TrustedEvent, urls: string[]) => {
}
if (event.kind === MESSAGE) {
return room ? makeRoomPath(url, room) : makeSpacePath(url, 'chat')
return room ? makeRoomPath(url, room) : makeSpacePath(url, "chat")
}
const kind = event.tags.find(nthEq(0, "K"))?.[1]
@@ -110,7 +110,7 @@ export const getEventPath = async (event: TrustedEvent, urls: string[]) => {
}
if (parseInt(kind) === MESSAGE) {
return room ? makeRoomPath(url, room) : makeSpacePath(url, 'chat')
return room ? makeRoomPath(url, room) : makeSpacePath(url, "chat")
}
}
}
+21 -2
View File
@@ -23,7 +23,14 @@ import {
} from "@welshman/lib"
import type {Socket} from "@welshman/net"
import {Pool, load, AuthStateEvent, SocketEvent} from "@welshman/net"
import {collection, custom} from "@welshman/store"
import {
collection,
custom,
deriveEvents,
deriveEventsMapped,
withGetter,
synced,
} from "@welshman/store"
import {
getIdFilters,
WRAP,
@@ -56,7 +63,9 @@ import {
asDecryptedEvent,
normalizeRelayUrl,
getTag,
getTagValue,
getTagValues,
getAddress,
} from "@welshman/util"
import type {TrustedEvent, SignedEvent, PublishedList, List, Filter} from "@welshman/util"
import {Nip59, decrypt} from "@welshman/signer"
@@ -81,7 +90,6 @@ import {
appContext,
} from "@welshman/app"
import type {Thunk, Relay} from "@welshman/app"
import {deriveEvents, deriveEventsMapped, withGetter, synced} from "@welshman/store"
export const fromCsv = (s: string) => (s || "").split(",").filter(identity)
@@ -341,6 +349,8 @@ export const {
// Alerts
export const deviceAlertAddresses = synced<string[]>("deviceAlertAddresses", [])
export type Alert = {
event: TrustedEvent
tags: string[][]
@@ -356,6 +366,12 @@ export const alerts = deriveEventsMapped<Alert>(repository, {
},
})
export const deviceAlerts = derived(
[deviceAlertAddresses, alerts],
([$deviceAlertAddresses, $alerts]) =>
$alerts.filter(a => $deviceAlertAddresses.includes(getAddress(a.event))),
)
// Alert Statuses
export type AlertStatus = {
@@ -373,6 +389,9 @@ export const alertStatuses = deriveEventsMapped<AlertStatus>(repository, {
},
})
export const deriveAlertStatus = (address: string) =>
derived(alertStatuses, statuses => statuses.find(s => getTagValue("d", s.event.tags) === address))
// Membership
export const hasMembershipUrl = (list: List | undefined, url: string) =>
+6 -2
View File
@@ -63,6 +63,7 @@
} from "@app/state"
import {loadUserData, listenForNotifications} from "@app/requests"
import {theme} from "@app/theme"
import {initializePushNotifications} from "@app/push"
import * as commands from "@app/commands"
import * as requests from "@app/requests"
import * as notifications from "@app/notifications"
@@ -73,6 +74,9 @@
dropSession($session.pubkey)
}
// Initialize push notification handler asap
initializePushNotifications()
const {children} = $props()
const ready = $state(defer<void>())
@@ -95,8 +99,8 @@
})
// Listen for navigation messages from service worker
navigator.serviceWorker?.addEventListener('message', (event) => {
if (event.data && event.data.type === 'NAVIGATE') {
navigator.serviceWorker?.addEventListener("message", event => {
if (event.data && event.data.type === "NAVIGATE") {
goto(event.data.url)
}
})
+1 -1
View File
@@ -2,7 +2,7 @@
import {onMount} from "svelte"
import * as nip19 from "nostr-tools/nip19"
import type {TrustedEvent} from "@welshman/util"
import {Address, getIdFilters, getTagValue} from "@welshman/util"
import {Address, getIdFilters} from "@welshman/util"
import {LOCAL_RELAY_URL} from "@welshman/relay"
import {load} from "@welshman/net"
import {page} from "$app/stores"
+23 -24
View File
@@ -1,24 +1,12 @@
import * as nip19 from 'nostr-tools/nip19'
import {parse, renderAsText} from '@welshman/content'
import {MESSAGE, THREAD, COMMENT, EVENT_TIME} from '@welshman/util'
/* global clients */
const renderOptions = {
createElement: tag => ({
_text: "",
set innerText(text) {
this._text = text
},
get innerHTML() {
return this._text
},
})
}
import * as nip19 from "nostr-tools/nip19"
self.addEventListener('install', event => {
self.addEventListener("install", event => {
self.skipWaiting()
})
self.addEventListener('activate', event => {
self.addEventListener("activate", event => {
event.waitUntil(self.clients.claim())
})
@@ -26,26 +14,37 @@ self.addEventListener("push", e => {
console.log("Service Worker: Push event received", e)
let url = "/"
let title = "New activity"
let body = "You have a new message"
try {
const {event, relays = []} = e.data?.json() || {}
const data = e.data?.json()
if (event) {
url += nip19.neventEncode({id: event.id, relays})
body = renderAsText(parse(event), renderOptions).toString()
if (data?.event) {
url += nip19.neventEncode({
id: data.event.id,
relays: data.relays || []
})
}
if (data?.title) {
title = data.title
}
if (data?.body) {
body = data.body
}
} catch (e) {
console.log("Service Worker: Failed to parse push data", e)
}
e.waitUntil(
self.registration.showNotification("New message", {
self.registration.showNotification(title, {
body,
data: {url},
icon: "/pwa-192x192.png",
badge: "/pwa-64x64.png",
tag: 'flotilla-notification',
tag: "flotilla-notification",
requireInteraction: false,
}),
)
@@ -74,8 +73,8 @@ self.addEventListener("notificationclick", e => {
for (const client of clientList) {
if (client.url.includes(location.origin)) {
client.postMessage({
type: 'NAVIGATE',
url: url
type: "NAVIGATE",
url: url,
})
return client.focus()