Compare commits

...

11 Commits

Author SHA1 Message Date
Jon Staab c691400630 Update version 2026-03-09 16:46:47 -07:00
Jon Staab 6acbfb1181 Fix classified images 2026-03-06 15:01:15 -08:00
Jon Staab 5f7474140f Add StringMultiInput for OTPs 2026-03-06 15:00:17 -08:00
Jon Staab c56d6f4c75 Fix up edit 2026-03-06 14:46:04 -08:00
Jon Staab c874ae50e5 Handle prompt-with-rationale 2026-03-06 14:40:58 -08:00
Jon Staab 25e7cc97f9 Handle profile update errors 2026-03-06 14:18:05 -08:00
Jon Staab 837e4bc537 Move from .env to .env.local 2026-03-06 13:58:03 -08:00
Jon Staab 65fa93d853 Tweak some error messages 2026-03-06 13:37:16 -08:00
Jon Staab 28b0276f17 Refactor pomade, add password reset flow 2026-03-06 11:48:57 -08:00
Jon Staab 10ac15f8a2 Add LogInSelect step for disambiguating pomade sessions 2026-03-06 09:38:36 -08:00
Jon Staab a45633e214 Update pomade implementation 2026-03-05 17:12:40 -08:00
35 changed files with 1134 additions and 376 deletions
+1
View File
@@ -1,5 +1,6 @@
# Env # Env
.env .env
.env.local
# Vite # Vite
vite.config.js.timestamp-* vite.config.js.timestamp-*
+26
View File
@@ -1,5 +1,31 @@
# Changelog # Changelog
# 1.6.5
* Attempt to fix permission grant for notifications
* Make sync logic more robust
* Add unban/unallow support
* Improve support for downloading/opening protected images
* Add manual send/receive to wallet
* Show wallet status when wallet is unreachable
* Update nostr signer capacitor plugin
* Fix some safe area insets
* Update NIP 55 signer plugin (fixes Primal login)
* Refine space join dialogs and discover page
* Reopen the last DM that was open when navigating back to chat
* Get rid of ChatEnable interstitial
* Enable auth for relays we're publishing to
* Drag and drop space icons
* Add better muting support
* Add back button to settings menu
* Add page titles
* Improve scroll to event behavior
* Add in-memory search to rooms
* Fix editing messages with html tags
* Fix DM media detection
* Clean up reporting dialogs
* Improve room detail
# 1.6.4 # 1.6.4
* Clean up modal design * Clean up modal design
+2 -2
View File
@@ -7,8 +7,8 @@ android {
applicationId "social.flotilla" applicationId "social.flotilla"
minSdk rootProject.ext.minSdkVersion minSdk rootProject.ext.minSdkVersion
targetSdk rootProject.ext.targetSdkVersion targetSdk rootProject.ext.targetSdkVersion
versionCode 40 versionCode 41
versionName "1.6.4" versionName "1.6.5"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions { aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
+2 -2
View File
@@ -5,8 +5,8 @@ temp_env=$(declare -p -x)
if [ -f .env.template ]; then if [ -f .env.template ]; then
source .env.template source .env.template
fi fi
if [ -f .env ]; then if [ -f .env.local ]; then
source .env source .env.local
fi fi
# Avoid overwriting env vars provided directly # Avoid overwriting env vars provided directly
+4 -4
View File
@@ -358,14 +358,14 @@
CODE_SIGN_ENTITLEMENTS = "Flotilla Chat.entitlements"; CODE_SIGN_ENTITLEMENTS = "Flotilla Chat.entitlements";
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 31; CURRENT_PROJECT_VERSION = 32;
DEVELOPMENT_TEAM = S26U9DYW3A; DEVELOPMENT_TEAM = S26U9DYW3A;
INFOPLIST_FILE = App/Info.plist; INFOPLIST_FILE = App/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Flotilla Chat"; INFOPLIST_KEY_CFBundleDisplayName = "Flotilla Chat";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
IPHONEOS_DEPLOYMENT_TARGET = 15.0; IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.6.4; MARKETING_VERSION = 1.6.5;
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
PRODUCT_BUNDLE_IDENTIFIER = social.flotilla; PRODUCT_BUNDLE_IDENTIFIER = social.flotilla;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@@ -385,14 +385,14 @@
CODE_SIGN_ENTITLEMENTS = "Flotilla Chat.entitlements"; CODE_SIGN_ENTITLEMENTS = "Flotilla Chat.entitlements";
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 31; CURRENT_PROJECT_VERSION = 32;
DEVELOPMENT_TEAM = S26U9DYW3A; DEVELOPMENT_TEAM = S26U9DYW3A;
INFOPLIST_FILE = App/Info.plist; INFOPLIST_FILE = App/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Flotilla Chat"; INFOPLIST_KEY_CFBundleDisplayName = "Flotilla Chat";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
IPHONEOS_DEPLOYMENT_TARGET = 15.0; IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.6.4; MARKETING_VERSION = 1.6.5;
PRODUCT_BUNDLE_IDENTIFIER = social.flotilla; PRODUCT_BUNDLE_IDENTIFIER = social.flotilla;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
+13 -13
View File
@@ -1,6 +1,6 @@
{ {
"name": "flotilla", "name": "flotilla",
"version": "1.6.4", "version": "1.6.5",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "vite dev", "dev": "vite dev",
@@ -11,7 +11,7 @@
"tauri:info": "tauri info", "tauri:info": "tauri info",
"tauri:icons": "tauri icon assets/logo.png --output src-tauri/icons", "tauri:icons": "tauri icon assets/logo.png --output src-tauri/icons",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "./check.sh", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --check src && eslint src", "lint": "prettier --check src && eslint src",
"format": "git diff head --name-only --diff-filter d | grep -E '(js|ts|svelte|css)$' | xargs -r prettier --write", "format": "git diff head --name-only --diff-filter d | grep -E '(js|ts|svelte|css)$' | xargs -r prettier --write",
"format:all": "prettier --write src", "format:all": "prettier --write src",
@@ -57,7 +57,7 @@
"@getalby/lightning-tools": "^6.1.0", "@getalby/lightning-tools": "^6.1.0",
"@getalby/sdk": "^5.1.2", "@getalby/sdk": "^5.1.2",
"@noble/curves": "^1.9.7", "@noble/curves": "^1.9.7",
"@pomade/core": "^0.1.1", "@pomade/core": "^0.2.1",
"@poppanator/sveltekit-svg": "^4.2.1", "@poppanator/sveltekit-svg": "^4.2.1",
"@sveltejs/adapter-static": "^3.0.10", "@sveltejs/adapter-static": "^3.0.10",
"@tiptap/core": "^2.27.2", "@tiptap/core": "^2.27.2",
@@ -65,16 +65,16 @@
"@types/throttle-debounce": "^5.0.2", "@types/throttle-debounce": "^5.0.2",
"@vite-pwa/assets-generator": "^0.2.6", "@vite-pwa/assets-generator": "^0.2.6",
"@vite-pwa/sveltekit": "^0.6.8", "@vite-pwa/sveltekit": "^0.6.8",
"@welshman/app": "^0.8.7", "@welshman/app": "^0.8.8",
"@welshman/content": "^0.8.7", "@welshman/content": "^0.8.8",
"@welshman/editor": "^0.8.7", "@welshman/editor": "^0.8.8",
"@welshman/feeds": "^0.8.7", "@welshman/feeds": "^0.8.8",
"@welshman/lib": "^0.8.7", "@welshman/lib": "^0.8.8",
"@welshman/net": "^0.8.7", "@welshman/net": "^0.8.8",
"@welshman/router": "^0.8.7", "@welshman/router": "^0.8.8",
"@welshman/signer": "^0.8.7", "@welshman/signer": "^0.8.8",
"@welshman/store": "^0.8.7", "@welshman/store": "^0.8.8",
"@welshman/util": "^0.8.7", "@welshman/util": "^0.8.8",
"compressorjs-next": "^1.1.2", "compressorjs-next": "^1.1.2",
"daisyui": "^4.12.24", "daisyui": "^4.12.24",
"date-picker-svelte": "^2.17.0", "date-picker-svelte": "^2.17.0",
+364 -138
View File
@@ -57,8 +57,8 @@ importers:
specifier: ^1.9.7 specifier: ^1.9.7
version: 1.9.7 version: 1.9.7
'@pomade/core': '@pomade/core':
specifier: ^0.1.1 specifier: ^0.2.1
version: 0.1.1(@frostr/bifrost@1.0.7(typescript@5.9.3))(@noble/hashes@2.0.1)(@welshman/lib@0.8.7)(@welshman/net@0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/signer@0.8.7(@noble/curves@1.9.7)(@noble/hashes@2.0.1)(@welshman/lib@0.8.7)(@welshman/net@0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/be4bb90a1a15c8eec0934f2f66ce9e82ecc72d51(@capacitor/core@8.0.1))(nostr-tools@2.20.0(typescript@5.9.3)))(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-tools@2.20.0(typescript@5.9.3)) version: 0.2.1(@frostr/bifrost@1.0.7(typescript@5.9.3))(@noble/hashes@2.0.1)(@welshman/lib@0.8.8)(@welshman/net@0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/signer@0.8.8(@noble/curves@1.9.7)(@noble/hashes@2.0.1)(@welshman/lib@0.8.8)(@welshman/net@0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/be4bb90a1a15c8eec0934f2f66ce9e82ecc72d51(@capacitor/core@8.0.1))(nostr-tools@2.20.0(typescript@5.9.3)))(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-tools@2.20.0(typescript@5.9.3))
'@poppanator/sveltekit-svg': '@poppanator/sveltekit-svg':
specifier: ^4.2.1 specifier: ^4.2.1
version: 4.2.1(rollup@2.80.0)(svelte@5.48.0)(svgo@3.3.2)(vite@5.4.21(@types/node@25.0.10)(terser@5.46.0)) version: 4.2.1(rollup@2.80.0)(svelte@5.48.0)(svgo@3.3.2)(vite@5.4.21(@types/node@25.0.10)(terser@5.46.0))
@@ -81,35 +81,35 @@ importers:
specifier: ^0.6.8 specifier: ^0.6.8
version: 0.6.8(@sveltejs/kit@2.50.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.48.0)(vite@5.4.21(@types/node@25.0.10)(terser@5.46.0)))(svelte@5.48.0)(typescript@5.9.3)(vite@5.4.21(@types/node@25.0.10)(terser@5.46.0)))(@vite-pwa/assets-generator@0.2.6)(vite-plugin-pwa@0.21.2(@vite-pwa/assets-generator@0.2.6)(vite@5.4.21(@types/node@25.0.10)(terser@5.46.0))(workbox-build@7.3.0)(workbox-window@7.3.0)) version: 0.6.8(@sveltejs/kit@2.50.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.48.0)(vite@5.4.21(@types/node@25.0.10)(terser@5.46.0)))(svelte@5.48.0)(typescript@5.9.3)(vite@5.4.21(@types/node@25.0.10)(terser@5.46.0)))(@vite-pwa/assets-generator@0.2.6)(vite-plugin-pwa@0.21.2(@vite-pwa/assets-generator@0.2.6)(vite@5.4.21(@types/node@25.0.10)(terser@5.46.0))(workbox-build@7.3.0)(workbox-window@7.3.0))
'@welshman/app': '@welshman/app':
specifier: ^0.8.7 specifier: ^0.8.8
version: 0.8.7(42dd4e512c88dafddb6d336c46cac054) version: 0.8.8(b90dd618d8ad3ba87405490e903259ce)
'@welshman/content': '@welshman/content':
specifier: ^0.8.7 specifier: ^0.8.8
version: 0.8.7(nostr-tools@2.20.0(typescript@5.9.3)) version: 0.8.8(nostr-tools@2.20.0(typescript@5.9.3))
'@welshman/editor': '@welshman/editor':
specifier: ^0.8.7 specifier: ^0.8.8
version: 0.8.7(@tiptap/extension-image@2.27.1(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)))(@tiptap/extension-link@2.27.1(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2))(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(linkifyjs@4.3.2)(nostr-tools@2.20.0(typescript@5.9.3))(prosemirror-markdown@1.13.3)(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.5)(tiptap-markdown@0.8.10(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))) version: 0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-editor@1.1.1(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/extension-image@2.27.1(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)))(@tiptap/extension-link@2.27.1(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)(linkifyjs@4.3.2)(nostr-tools@2.20.0(typescript@5.9.3))(prosemirror-markdown@1.13.3)(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.5)(tiptap-markdown@0.8.10(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))))(nostr-tools@2.20.0(typescript@5.9.3))
'@welshman/feeds': '@welshman/feeds':
specifier: ^0.8.7 specifier: ^0.8.8
version: 0.8.7(168ce8cc007592daec2fe2c423b6ba13) version: 0.8.8(827c582d718d0d373e9315813bab1085)
'@welshman/lib': '@welshman/lib':
specifier: ^0.8.7 specifier: ^0.8.8
version: 0.8.7 version: 0.8.8
'@welshman/net': '@welshman/net':
specifier: ^0.8.7 specifier: ^0.8.8
version: 0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3) version: 0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3)
'@welshman/router': '@welshman/router':
specifier: ^0.8.7 specifier: ^0.8.8
version: 0.8.7(@welshman/lib@0.8.7)(@welshman/net@0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3))) version: 0.8.8(@welshman/lib@0.8.8)(@welshman/net@0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))
'@welshman/signer': '@welshman/signer':
specifier: ^0.8.7 specifier: ^0.8.8
version: 0.8.7(@noble/curves@1.9.7)(@noble/hashes@2.0.1)(@welshman/lib@0.8.7)(@welshman/net@0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/be4bb90a1a15c8eec0934f2f66ce9e82ecc72d51(@capacitor/core@8.0.1))(nostr-tools@2.20.0(typescript@5.9.3)) version: 0.8.8(@noble/curves@1.9.7)(@noble/hashes@2.0.1)(@welshman/lib@0.8.8)(@welshman/net@0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/be4bb90a1a15c8eec0934f2f66ce9e82ecc72d51(@capacitor/core@8.0.1))(nostr-tools@2.20.0(typescript@5.9.3))
'@welshman/store': '@welshman/store':
specifier: ^0.8.7 specifier: ^0.8.8
version: 0.8.7(@welshman/lib@0.8.7)(@welshman/net@0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(svelte@5.48.0) version: 0.8.8(@welshman/lib@0.8.8)(@welshman/net@0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(svelte@5.48.0)
'@welshman/util': '@welshman/util':
specifier: ^0.8.7 specifier: ^0.8.8
version: 0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)) version: 0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3))
compressorjs-next: compressorjs-next:
specifier: ^1.1.2 specifier: ^1.1.2
version: 1.1.2 version: 1.1.2
@@ -811,6 +811,36 @@ packages:
peerDependencies: peerDependencies:
'@capacitor/core': '>=8.0.0' '@capacitor/core': '>=8.0.0'
'@cbor-extract/cbor-extract-darwin-arm64@2.2.0':
resolution: {integrity: sha512-P7swiOAdF7aSi0H+tHtHtr6zrpF3aAq/W9FXx5HektRvLTM2O89xCyXF3pk7pLc7QpaY7AoaE8UowVf9QBdh3w==}
cpu: [arm64]
os: [darwin]
'@cbor-extract/cbor-extract-darwin-x64@2.2.0':
resolution: {integrity: sha512-1liF6fgowph0JxBbYnAS7ZlqNYLf000Qnj4KjqPNW4GViKrEql2MgZnAsExhY9LSy8dnvA4C0qHEBgPrll0z0w==}
cpu: [x64]
os: [darwin]
'@cbor-extract/cbor-extract-linux-arm64@2.2.0':
resolution: {integrity: sha512-rQvhNmDuhjTVXSPFLolmQ47/ydGOFXtbR7+wgkSY0bdOxCFept1hvg59uiLPT2fVDuJFuEy16EImo5tE2x3RsQ==}
cpu: [arm64]
os: [linux]
'@cbor-extract/cbor-extract-linux-arm@2.2.0':
resolution: {integrity: sha512-QeBcBXk964zOytiedMPQNZr7sg0TNavZeuUCD6ON4vEOU/25+pLhNN6EDIKJ9VLTKaZ7K7EaAriyYQ1NQ05s/Q==}
cpu: [arm]
os: [linux]
'@cbor-extract/cbor-extract-linux-x64@2.2.0':
resolution: {integrity: sha512-cWLAWtT3kNLHSvP4RKDzSTX9o0wvQEEAj4SKvhWuOVZxiDAeQazr9A+PSiRILK1VYMLeDml89ohxCnUNQNQNCw==}
cpu: [x64]
os: [linux]
'@cbor-extract/cbor-extract-win32-x64@2.2.0':
resolution: {integrity: sha512-l2M+Z8DO2vbvADOBNLbbh9y5ST1RY5sqkWOg/58GkUPBYou/cuNZ68SGQ644f1CvZ8kcOxyZtw06+dxWHIoN/w==}
cpu: [x64]
os: [win32]
'@cmdcode/buff@2.2.5': '@cmdcode/buff@2.2.5':
resolution: {integrity: sha512-+nc3QDoJ+MU/fp+YkX6WuEjJrXLF6ME+eVX1sj5a+MfBKO9LWb4R9Y2zH6APBrySd7nFr48ozscAui7SKvLmXg==} resolution: {integrity: sha512-+nc3QDoJ+MU/fp+YkX6WuEjJrXLF6ME+eVX1sj5a+MfBKO9LWb4R9Y2zH6APBrySd7nFr48ozscAui7SKvLmXg==}
@@ -1309,12 +1339,46 @@ packages:
'@paralleldrive/cuid2@2.3.1': '@paralleldrive/cuid2@2.3.1':
resolution: {integrity: sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==} resolution: {integrity: sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==}
'@peculiar/asn1-cms@2.6.1':
resolution: {integrity: sha512-vdG4fBF6Lkirkcl53q6eOdn3XYKt+kJTG59edgRZORlg/3atWWEReRCx5rYE1ZzTTX6vLK5zDMjHh7vbrcXGtw==}
'@peculiar/asn1-csr@2.6.1':
resolution: {integrity: sha512-WRWnKfIocHyzFYQTka8O/tXCiBquAPSrRjXbOkHbO4qdmS6loffCEGs+rby6WxxGdJCuunnhS2duHURhjyio6w==}
'@peculiar/asn1-ecc@2.6.1':
resolution: {integrity: sha512-+Vqw8WFxrtDIN5ehUdvlN2m73exS2JVG0UAyfVB31gIfor3zWEAQPD+K9ydCxaj3MLen9k0JhKpu9LqviuCE1g==}
'@peculiar/asn1-pfx@2.6.1':
resolution: {integrity: sha512-nB5jVQy3MAAWvq0KY0R2JUZG8bO/bTLpnwyOzXyEh/e54ynGTatAR+csOnXkkVD9AFZ2uL8Z7EV918+qB1qDvw==}
'@peculiar/asn1-pkcs8@2.6.1':
resolution: {integrity: sha512-JB5iQ9Izn5yGMw3ZG4Nw3Xn/hb/G38GYF3lf7WmJb8JZUydhVGEjK/ZlFSWhnlB7K/4oqEs8HnfFIKklhR58Tw==}
'@peculiar/asn1-pkcs9@2.6.1':
resolution: {integrity: sha512-5EV8nZoMSxeWmcxWmmcolg22ojZRgJg+Y9MX2fnE2bGRo5KQLqV5IL9kdSQDZxlHz95tHvIq9F//bvL1OeNILw==}
'@peculiar/asn1-rsa@2.6.1':
resolution: {integrity: sha512-1nVMEh46SElUt5CB3RUTV4EG/z7iYc7EoaDY5ECwganibQPkZ/Y2eMsTKB/LeyrUJ+W/tKoD9WUqIy8vB+CEdA==}
'@peculiar/asn1-schema@2.6.0':
resolution: {integrity: sha512-xNLYLBFTBKkCzEZIw842BxytQQATQv+lDTCEMZ8C196iJcJJMBUZxrhSTxLaohMyKK8QlzRNTRkUmanucnDSqg==}
'@peculiar/asn1-x509-attr@2.6.1':
resolution: {integrity: sha512-tlW6cxoHwgcQghnJwv3YS+9OO1737zgPogZ+CgWRUK4roEwIPzRH4JEiG770xe5HX2ATfCpmX60gurfWIF9dcQ==}
'@peculiar/asn1-x509@2.6.1':
resolution: {integrity: sha512-O9jT5F1A2+t3r7C4VT7LYGXqkGLK7Kj1xFpz7U0isPrubwU5PbDoyYtx6MiGst29yq7pXN5vZbQFKRCP+lLZlA==}
'@peculiar/x509@1.14.3':
resolution: {integrity: sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA==}
engines: {node: '>=20.0.0'}
'@polka/url@1.0.0-next.29': '@polka/url@1.0.0-next.29':
resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
'@pomade/core@0.1.1': '@pomade/core@0.2.1':
resolution: {integrity: sha512-v/lg9nQvL1ReOx1xLmjS70mAO5hW2ZcR9OXl9GdB0rxyg0gBIh45seqzJTDI8ye+MAk7AZRvhn8H6lPE6oohNQ==} resolution: {integrity: sha512-zXpPQPkhVe7OchmRDe2MbHdUxiCSeUuMwrHOyeOBs/xD1EfY093Mwj6Cu/OLfz0wxivBDSp1GMMmxqKbLWam3Q==}
version: 0.1.1 version: 0.2.1
engines: {node: '>=12.0.0'} engines: {node: '>=12.0.0'}
peerDependencies: peerDependencies:
'@frostr/bifrost': ^1.0.7 '@frostr/bifrost': ^1.0.7
@@ -1903,82 +1967,83 @@ packages:
'@vite-pwa/assets-generator': '@vite-pwa/assets-generator':
optional: true optional: true
'@welshman/app@0.8.7': '@welshman/app@0.8.8':
resolution: {integrity: sha512-P+cCy2o1r/ke5SngNmoK8WoeLmEZ6l2I83mz0QaRHremkb+Q/RN72UBQy+x2lUrUtRzWJ8tNAwXwsqBw0JGxaQ==} resolution: {integrity: sha512-pyySouAJwGZ2RSC29egiFft38Ctuioodon6xWFxB7HvJ9Llsh5b53qjkrQcAYM7lUAzXwtalf2v4Z3EwYdUObg==}
peerDependencies: peerDependencies:
'@pomade/core': ^0.1.1 '@pomade/core': ^0.1.3
'@welshman/feeds': 0.8.7 '@welshman/feeds': 0.8.8
'@welshman/lib': 0.8.7 '@welshman/lib': 0.8.8
'@welshman/net': 0.8.7 '@welshman/net': 0.8.8
'@welshman/router': 0.8.7 '@welshman/router': 0.8.8
'@welshman/signer': 0.8.7 '@welshman/signer': 0.8.8
'@welshman/store': 0.8.7 '@welshman/store': 0.8.8
'@welshman/util': 0.8.7 '@welshman/util': 0.8.8
svelte: ^4.0.0 || ^5.0.0 svelte: ^4.0.0 || ^5.0.0
'@welshman/content@0.8.7': '@welshman/content@0.8.8':
resolution: {integrity: sha512-EPeiB+hocVuMjlbWrIBdw7wmcs3jsBjI9o7jld2gsADVLmouYctahFNTSxjkeARnyK+j09ece95hC2MlJNPrbA==} resolution: {integrity: sha512-5jh2YMoqINzkOEVSDZec6JbAqiC0WThwRuPwJOwiJlAFYQ4LC0MAT1HQ8z9pht/0TXdjYQUu2X+jngqqICNOiw==}
peerDependencies: peerDependencies:
nostr-tools: ^2.19.4 nostr-tools: ^2.19.4
'@welshman/editor@0.8.7': '@welshman/editor@0.8.8':
resolution: {integrity: sha512-UZmHmP5zG9Ad1sp6h4uAQYwJ/o1mkfyCbt7tYV5+z7+7YZ2x2gsS59yqDrgr0NV1z9GFZ/axgFatl0L/c5ihKA==} resolution: {integrity: sha512-54WD2d6HEEiuoPgl/LeE4eaLtF2/SrYObk+IE9UUrJjoXcK/BK3vt8ltzazvBLR8ntfKOQINc4DhkeuBxiiCpA==}
peerDependencies: peerDependencies:
'@welshman/lib': 0.8.7 '@welshman/lib': 0.8.8
'@welshman/util': 0.8.7 '@welshman/util': 0.8.8
nostr-editor: ^1.1.1
nostr-tools: ^2.19.4 nostr-tools: ^2.19.4
'@welshman/feeds@0.8.7': '@welshman/feeds@0.8.8':
resolution: {integrity: sha512-mM9mGRje2lXQ2KGTz31gSR0MBWJVIgD8efaf2HCb/dopLzlJ0brSpGUAuGAb+yAfWwZ/wXTzwmYOLdSZT5AyvQ==} resolution: {integrity: sha512-o5JuptpWSNr6wtbM0RfSxTJgZStaNxPz160tE9u0SZzs1/a9sq/Yzesw7s+g0nKukRjBbl70DOqpTqOqfXAEIw==}
peerDependencies: peerDependencies:
'@welshman/lib': 0.8.7 '@welshman/lib': 0.8.8
'@welshman/net': 0.8.7 '@welshman/net': 0.8.8
'@welshman/router': 0.8.7 '@welshman/router': 0.8.8
'@welshman/signer': 0.8.7 '@welshman/signer': 0.8.8
'@welshman/util': 0.8.7 '@welshman/util': 0.8.8
'@welshman/lib@0.8.7': '@welshman/lib@0.8.8':
resolution: {integrity: sha512-/82PNmg7mhf6r1gtY0YaB8xFRCioRRZkZUDPb0UuAZuhBCom6tKhlffzz+ty2n2tHYFTyScMp90WMVtkU/HaDQ==} resolution: {integrity: sha512-77ZfVtodV05276ceR8c+JdDFqhOpmy2W6PkgDYbnKstQzKb5TN6wBvcLKxJppTzWMeWbyi2JADsuOYvW1jpOSQ==}
engines: {node: '>=12.0.0'} engines: {node: '>=12.0.0'}
'@welshman/net@0.8.7': '@welshman/net@0.8.8':
resolution: {integrity: sha512-FcVYX1imsYWca32zyU/HhXKly+A4IJzoElmMqe4x501bvpb0QQm8S2nfdCPxtb1lsi2rR1Y5if9jGHwgQGnEtQ==} resolution: {integrity: sha512-Rug3GzVzyABG21g++cCLOVXdjAieV6rJUZqstE8i/olZvOEWZpZ9R901DoUSDR07U2HTrAwHQrjgb1HmH4jiDQ==}
peerDependencies: peerDependencies:
'@welshman/lib': 0.8.7 '@welshman/lib': 0.8.8
'@welshman/util': 0.8.7 '@welshman/util': 0.8.8
'@welshman/router@0.8.7': '@welshman/router@0.8.8':
resolution: {integrity: sha512-p0jfyqBHnNK9j2ZI3PYHfirdUe5/ll1/jttcj0p4xi822aYoGYv5giriDVt+wnzchki1XRXBGN5lRXfpBi8bbA==} resolution: {integrity: sha512-j5O7F7KGQtOIvBJctEiUNcLfHBUnhHlYHxUx7ImPPurc1zLzt3JovvJJFubXMQoQ26D01DsK/AA1L5WZNebUhA==}
peerDependencies: peerDependencies:
'@welshman/lib': 0.8.7 '@welshman/lib': 0.8.8
'@welshman/net': 0.8.7 '@welshman/net': 0.8.8
'@welshman/util': 0.8.7 '@welshman/util': 0.8.8
'@welshman/signer@0.8.7': '@welshman/signer@0.8.8':
resolution: {integrity: sha512-RbFuRyJ0KL3Yg3EU8M9v5OADJO+XY/+sNd0CSmbWSwSry1NLlqa8lq/T+2b40x8KtnYMmQyB7Dp9yDQndO0ugA==} resolution: {integrity: sha512-rswHrTdc1+yvAno2h3JELzjp+LCfiYfUr8ACvwSSHAqDwrtezppfh0WDEPaYBp2EVSJ6tKMM1sVey0quO63aMw==}
version: 0.8.7 version: 0.8.8
peerDependencies: peerDependencies:
'@noble/curves': ^1.9.7 '@noble/curves': ^1.9.7
'@noble/hashes': ^2.0.1 '@noble/hashes': ^2.0.1
'@welshman/lib': 0.8.7 '@welshman/lib': 0.8.8
'@welshman/net': 0.8.7 '@welshman/net': 0.8.8
'@welshman/util': 0.8.7 '@welshman/util': 0.8.8
nostr-signer-capacitor-plugin: '*' nostr-signer-capacitor-plugin: '*'
nostr-tools: ^2.19.4 nostr-tools: ^2.19.4
'@welshman/store@0.8.7': '@welshman/store@0.8.8':
resolution: {integrity: sha512-ppvq7msnvzgnSlU4FsZmJgA3eSyFy9H6gYSQ91ukspbmkxCdMG2paBPCKU4tKv4fYrv/1ULgaN8gkP1BCG6riQ==} resolution: {integrity: sha512-mTFueKZi9CtrtvCZT5eT5QaLMs94LxQg4y7oO5PZp9wv8EGSnB9p7XIflM0OfpKwF7c0pu1RdXcjVlvMDsC6QQ==}
peerDependencies: peerDependencies:
'@welshman/lib': 0.8.7 '@welshman/lib': 0.8.8
'@welshman/net': 0.8.7 '@welshman/net': 0.8.8
'@welshman/util': 0.8.7 '@welshman/util': 0.8.8
svelte: ^4.0.0 || ^5.0.0 svelte: ^4.0.0 || ^5.0.0
'@welshman/util@0.8.7': '@welshman/util@0.8.8':
resolution: {integrity: sha512-UjdQookLypfOxWplxcG0lBzREGgck4n4a+digoRjAe5jRlP6S6xH7uNI8Pl1Qk01D5KB8Ntz/yBdwe6JtkvqYg==} resolution: {integrity: sha512-SNT1VXab6ce36EVfjs1A2uwWs5elYTI4eXi8SUuj42k8CqNIAtG+bOf/JFIxXNTfl3NSxxZdWzpLLZWBqgpAxQ==}
peerDependencies: peerDependencies:
'@noble/curves': ^1.9.7 '@noble/curves': ^1.9.7
'@welshman/lib': 0.8.7 '@welshman/lib': 0.8.8
nostr-tools: ^2.19.4 nostr-tools: ^2.19.4
'@xml-tools/parser@1.0.11': '@xml-tools/parser@1.0.11':
@@ -2083,6 +2148,10 @@ packages:
asap@2.0.6: asap@2.0.6:
resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==}
asn1js@3.0.7:
resolution: {integrity: sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ==}
engines: {node: '>=12.0.0'}
astral-regex@2.0.0: astral-regex@2.0.0:
resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -2216,6 +2285,13 @@ packages:
caniuse-lite@1.0.30001766: caniuse-lite@1.0.30001766:
resolution: {integrity: sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==} resolution: {integrity: sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==}
cbor-extract@2.2.0:
resolution: {integrity: sha512-Ig1zM66BjLfTXpNgKpvBePq271BPOvu8MR0Jl080yG7Jsl+wAZunfrwiwA+9ruzm/WEdIV5QF/bjDZTqyAIVHA==}
hasBin: true
cbor-x@1.6.0:
resolution: {integrity: sha512-0kareyRwHSkL6ws5VXHEf8uY1liitysCVJjlmhaLG+IXLqhSaOO+t63coaso7yjwEzWZzLy8fJo06gZDVQM9Qg==}
chalk@2.4.2: chalk@2.4.2:
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
engines: {node: '>=4'} engines: {node: '>=4'}
@@ -3430,10 +3506,6 @@ packages:
markdown-it-task-lists@2.1.1: markdown-it-task-lists@2.1.1:
resolution: {integrity: sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA==} resolution: {integrity: sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA==}
markdown-it@14.1.0:
resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==}
hasBin: true
markdown-it@14.1.1: markdown-it@14.1.1:
resolution: {integrity: sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==} resolution: {integrity: sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==}
hasBin: true hasBin: true
@@ -3570,6 +3642,10 @@ packages:
encoding: encoding:
optional: true optional: true
node-gyp-build-optional-packages@5.1.1:
resolution: {integrity: sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==}
hasBin: true
node-html-parser@5.4.2: node-html-parser@5.4.2:
resolution: {integrity: sha512-RaBPP3+51hPne/OolXxcz89iYvQvKOydaqoePpOgXcrOKZhjVIzmpKZz+Hd/RBO2/zN2q6CNJhQzucVz+u3Jyw==} resolution: {integrity: sha512-RaBPP3+51hPne/OolXxcz89iYvQvKOydaqoePpOgXcrOKZhjVIzmpKZz+Hd/RBO2/zN2q6CNJhQzucVz+u3Jyw==}
@@ -4034,6 +4110,13 @@ packages:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'} engines: {node: '>=6'}
pvtsutils@1.3.6:
resolution: {integrity: sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==}
pvutils@1.1.5:
resolution: {integrity: sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==}
engines: {node: '>=16.0.0'}
q@1.5.1: q@1.5.1:
resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==} resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==}
engines: {node: '>=0.6.0', teleport: '>=0.2.0'} engines: {node: '>=0.6.0', teleport: '>=0.2.0'}
@@ -4098,6 +4181,9 @@ packages:
resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
engines: {node: '>=8'} engines: {node: '>=8'}
reflect-metadata@0.2.2:
resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==}
reflect.getprototypeof@1.0.10: reflect.getprototypeof@1.0.10:
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@@ -4568,12 +4654,19 @@ packages:
'@swc/wasm': '@swc/wasm':
optional: true optional: true
tslib@1.14.1:
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
tslib@2.6.2: tslib@2.6.2:
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
tslib@2.8.1: tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
tsyringe@4.10.0:
resolution: {integrity: sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==}
engines: {node: '>= 6.0.0'}
type-check@0.4.0: type-check@0.4.0:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
@@ -5755,6 +5848,24 @@ snapshots:
dependencies: dependencies:
'@capacitor/core': 8.0.1 '@capacitor/core': 8.0.1
'@cbor-extract/cbor-extract-darwin-arm64@2.2.0':
optional: true
'@cbor-extract/cbor-extract-darwin-x64@2.2.0':
optional: true
'@cbor-extract/cbor-extract-linux-arm64@2.2.0':
optional: true
'@cbor-extract/cbor-extract-linux-arm@2.2.0':
optional: true
'@cbor-extract/cbor-extract-linux-x64@2.2.0':
optional: true
'@cbor-extract/cbor-extract-win32-x64@2.2.0':
optional: true
'@cmdcode/buff@2.2.5': '@cmdcode/buff@2.2.5':
dependencies: dependencies:
'@noble/hashes': 1.8.0 '@noble/hashes': 1.8.0
@@ -6233,16 +6344,108 @@ snapshots:
dependencies: dependencies:
'@noble/hashes': 1.8.0 '@noble/hashes': 1.8.0
'@peculiar/asn1-cms@2.6.1':
dependencies:
'@peculiar/asn1-schema': 2.6.0
'@peculiar/asn1-x509': 2.6.1
'@peculiar/asn1-x509-attr': 2.6.1
asn1js: 3.0.7
tslib: 2.8.1
'@peculiar/asn1-csr@2.6.1':
dependencies:
'@peculiar/asn1-schema': 2.6.0
'@peculiar/asn1-x509': 2.6.1
asn1js: 3.0.7
tslib: 2.8.1
'@peculiar/asn1-ecc@2.6.1':
dependencies:
'@peculiar/asn1-schema': 2.6.0
'@peculiar/asn1-x509': 2.6.1
asn1js: 3.0.7
tslib: 2.8.1
'@peculiar/asn1-pfx@2.6.1':
dependencies:
'@peculiar/asn1-cms': 2.6.1
'@peculiar/asn1-pkcs8': 2.6.1
'@peculiar/asn1-rsa': 2.6.1
'@peculiar/asn1-schema': 2.6.0
asn1js: 3.0.7
tslib: 2.8.1
'@peculiar/asn1-pkcs8@2.6.1':
dependencies:
'@peculiar/asn1-schema': 2.6.0
'@peculiar/asn1-x509': 2.6.1
asn1js: 3.0.7
tslib: 2.8.1
'@peculiar/asn1-pkcs9@2.6.1':
dependencies:
'@peculiar/asn1-cms': 2.6.1
'@peculiar/asn1-pfx': 2.6.1
'@peculiar/asn1-pkcs8': 2.6.1
'@peculiar/asn1-schema': 2.6.0
'@peculiar/asn1-x509': 2.6.1
'@peculiar/asn1-x509-attr': 2.6.1
asn1js: 3.0.7
tslib: 2.8.1
'@peculiar/asn1-rsa@2.6.1':
dependencies:
'@peculiar/asn1-schema': 2.6.0
'@peculiar/asn1-x509': 2.6.1
asn1js: 3.0.7
tslib: 2.8.1
'@peculiar/asn1-schema@2.6.0':
dependencies:
asn1js: 3.0.7
pvtsutils: 1.3.6
tslib: 2.8.1
'@peculiar/asn1-x509-attr@2.6.1':
dependencies:
'@peculiar/asn1-schema': 2.6.0
'@peculiar/asn1-x509': 2.6.1
asn1js: 3.0.7
tslib: 2.8.1
'@peculiar/asn1-x509@2.6.1':
dependencies:
'@peculiar/asn1-schema': 2.6.0
asn1js: 3.0.7
pvtsutils: 1.3.6
tslib: 2.8.1
'@peculiar/x509@1.14.3':
dependencies:
'@peculiar/asn1-cms': 2.6.1
'@peculiar/asn1-csr': 2.6.1
'@peculiar/asn1-ecc': 2.6.1
'@peculiar/asn1-pkcs9': 2.6.1
'@peculiar/asn1-rsa': 2.6.1
'@peculiar/asn1-schema': 2.6.0
'@peculiar/asn1-x509': 2.6.1
pvtsutils: 1.3.6
reflect-metadata: 0.2.2
tslib: 2.8.1
tsyringe: 4.10.0
'@polka/url@1.0.0-next.29': {} '@polka/url@1.0.0-next.29': {}
'@pomade/core@0.1.1(@frostr/bifrost@1.0.7(typescript@5.9.3))(@noble/hashes@2.0.1)(@welshman/lib@0.8.7)(@welshman/net@0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/signer@0.8.7(@noble/curves@1.9.7)(@noble/hashes@2.0.1)(@welshman/lib@0.8.7)(@welshman/net@0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/be4bb90a1a15c8eec0934f2f66ce9e82ecc72d51(@capacitor/core@8.0.1))(nostr-tools@2.20.0(typescript@5.9.3)))(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-tools@2.20.0(typescript@5.9.3))': '@pomade/core@0.2.1(@frostr/bifrost@1.0.7(typescript@5.9.3))(@noble/hashes@2.0.1)(@welshman/lib@0.8.8)(@welshman/net@0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/signer@0.8.8(@noble/curves@1.9.7)(@noble/hashes@2.0.1)(@welshman/lib@0.8.8)(@welshman/net@0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/be4bb90a1a15c8eec0934f2f66ce9e82ecc72d51(@capacitor/core@8.0.1))(nostr-tools@2.20.0(typescript@5.9.3)))(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-tools@2.20.0(typescript@5.9.3))':
dependencies: dependencies:
'@frostr/bifrost': 1.0.7(typescript@5.9.3) '@frostr/bifrost': 1.0.7(typescript@5.9.3)
'@noble/hashes': 2.0.1 '@noble/hashes': 2.0.1
'@welshman/lib': 0.8.7 '@peculiar/x509': 1.14.3
'@welshman/net': 0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3) '@welshman/lib': 0.8.8
'@welshman/signer': 0.8.7(@noble/curves@1.9.7)(@noble/hashes@2.0.1)(@welshman/lib@0.8.7)(@welshman/net@0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/be4bb90a1a15c8eec0934f2f66ce9e82ecc72d51(@capacitor/core@8.0.1))(nostr-tools@2.20.0(typescript@5.9.3)) '@welshman/net': 0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3)
'@welshman/util': 0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)) '@welshman/signer': 0.8.8(@noble/curves@1.9.7)(@noble/hashes@2.0.1)(@welshman/lib@0.8.8)(@welshman/net@0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/be4bb90a1a15c8eec0934f2f66ce9e82ecc72d51(@capacitor/core@8.0.1))(nostr-tools@2.20.0(typescript@5.9.3))
'@welshman/util': 0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3))
cbor-x: 1.6.0
hash-wasm: 4.12.0 hash-wasm: 4.12.0
nostr-tools: 2.20.0(typescript@5.9.3) nostr-tools: 2.20.0(typescript@5.9.3)
zod: 4.3.6 zod: 4.3.6
@@ -6828,26 +7031,26 @@ snapshots:
optionalDependencies: optionalDependencies:
'@vite-pwa/assets-generator': 0.2.6 '@vite-pwa/assets-generator': 0.2.6
'@welshman/app@0.8.7(42dd4e512c88dafddb6d336c46cac054)': '@welshman/app@0.8.8(b90dd618d8ad3ba87405490e903259ce)':
dependencies: dependencies:
'@pomade/core': 0.1.1(@frostr/bifrost@1.0.7(typescript@5.9.3))(@noble/hashes@2.0.1)(@welshman/lib@0.8.7)(@welshman/net@0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/signer@0.8.7(@noble/curves@1.9.7)(@noble/hashes@2.0.1)(@welshman/lib@0.8.7)(@welshman/net@0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/be4bb90a1a15c8eec0934f2f66ce9e82ecc72d51(@capacitor/core@8.0.1))(nostr-tools@2.20.0(typescript@5.9.3)))(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-tools@2.20.0(typescript@5.9.3)) '@pomade/core': 0.2.1(@frostr/bifrost@1.0.7(typescript@5.9.3))(@noble/hashes@2.0.1)(@welshman/lib@0.8.8)(@welshman/net@0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/signer@0.8.8(@noble/curves@1.9.7)(@noble/hashes@2.0.1)(@welshman/lib@0.8.8)(@welshman/net@0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/be4bb90a1a15c8eec0934f2f66ce9e82ecc72d51(@capacitor/core@8.0.1))(nostr-tools@2.20.0(typescript@5.9.3)))(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-tools@2.20.0(typescript@5.9.3))
'@welshman/feeds': 0.8.7(168ce8cc007592daec2fe2c423b6ba13) '@welshman/feeds': 0.8.8(827c582d718d0d373e9315813bab1085)
'@welshman/lib': 0.8.7 '@welshman/lib': 0.8.8
'@welshman/net': 0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3) '@welshman/net': 0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3)
'@welshman/router': 0.8.7(@welshman/lib@0.8.7)(@welshman/net@0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3))) '@welshman/router': 0.8.8(@welshman/lib@0.8.8)(@welshman/net@0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))
'@welshman/signer': 0.8.7(@noble/curves@1.9.7)(@noble/hashes@2.0.1)(@welshman/lib@0.8.7)(@welshman/net@0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/be4bb90a1a15c8eec0934f2f66ce9e82ecc72d51(@capacitor/core@8.0.1))(nostr-tools@2.20.0(typescript@5.9.3)) '@welshman/signer': 0.8.8(@noble/curves@1.9.7)(@noble/hashes@2.0.1)(@welshman/lib@0.8.8)(@welshman/net@0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/be4bb90a1a15c8eec0934f2f66ce9e82ecc72d51(@capacitor/core@8.0.1))(nostr-tools@2.20.0(typescript@5.9.3))
'@welshman/store': 0.8.7(@welshman/lib@0.8.7)(@welshman/net@0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(svelte@5.48.0) '@welshman/store': 0.8.8(@welshman/lib@0.8.8)(@welshman/net@0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(svelte@5.48.0)
'@welshman/util': 0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)) '@welshman/util': 0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3))
fuse.js: 7.1.0 fuse.js: 7.1.0
svelte: 5.48.0 svelte: 5.48.0
throttle-debounce: 5.0.2 throttle-debounce: 5.0.2
'@welshman/content@0.8.7(nostr-tools@2.20.0(typescript@5.9.3))': '@welshman/content@0.8.8(nostr-tools@2.20.0(typescript@5.9.3))':
dependencies: dependencies:
'@braintree/sanitize-url': 7.1.1 '@braintree/sanitize-url': 7.1.1
nostr-tools: 2.20.0(typescript@5.9.3) nostr-tools: 2.20.0(typescript@5.9.3)
'@welshman/editor@0.8.7(@tiptap/extension-image@2.27.1(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)))(@tiptap/extension-link@2.27.1(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2))(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(linkifyjs@4.3.2)(nostr-tools@2.20.0(typescript@5.9.3))(prosemirror-markdown@1.13.3)(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.5)(tiptap-markdown@0.8.10(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)))': '@welshman/editor@0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-editor@1.1.1(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/extension-image@2.27.1(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)))(@tiptap/extension-link@2.27.1(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)(linkifyjs@4.3.2)(nostr-tools@2.20.0(typescript@5.9.3))(prosemirror-markdown@1.13.3)(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.5)(tiptap-markdown@0.8.10(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))))(nostr-tools@2.20.0(typescript@5.9.3))':
dependencies: dependencies:
'@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2)
'@tiptap/extension-code': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) '@tiptap/extension-code': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))
@@ -6862,73 +7065,64 @@ snapshots:
'@tiptap/extension-text': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) '@tiptap/extension-text': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))
'@tiptap/pm': 2.27.2 '@tiptap/pm': 2.27.2
'@tiptap/suggestion': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2) '@tiptap/suggestion': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)
'@welshman/lib': 0.8.7 '@welshman/lib': 0.8.8
'@welshman/util': 0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)) '@welshman/util': 0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3))
nostr-editor: 1.1.1(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/extension-image@2.27.1(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)))(@tiptap/extension-link@2.27.1(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)(linkifyjs@4.3.2)(nostr-tools@2.20.0(typescript@5.9.3))(prosemirror-markdown@1.13.3)(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.5)(tiptap-markdown@0.8.10(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))) nostr-editor: 1.1.1(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/extension-image@2.27.1(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)))(@tiptap/extension-link@2.27.1(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)(linkifyjs@4.3.2)(nostr-tools@2.20.0(typescript@5.9.3))(prosemirror-markdown@1.13.3)(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.5)(tiptap-markdown@0.8.10(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)))
nostr-tools: 2.20.0(typescript@5.9.3) nostr-tools: 2.20.0(typescript@5.9.3)
tippy.js: 6.3.7 tippy.js: 6.3.7
transitivePeerDependencies:
- '@tiptap/extension-image'
- '@tiptap/extension-link'
- linkifyjs
- prosemirror-markdown
- prosemirror-model
- prosemirror-state
- prosemirror-view
- tiptap-markdown
'@welshman/feeds@0.8.7(168ce8cc007592daec2fe2c423b6ba13)': '@welshman/feeds@0.8.8(827c582d718d0d373e9315813bab1085)':
dependencies: dependencies:
'@welshman/lib': 0.8.7 '@welshman/lib': 0.8.8
'@welshman/net': 0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3) '@welshman/net': 0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3)
'@welshman/router': 0.8.7(@welshman/lib@0.8.7)(@welshman/net@0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3))) '@welshman/router': 0.8.8(@welshman/lib@0.8.8)(@welshman/net@0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))
'@welshman/signer': 0.8.7(@noble/curves@1.9.7)(@noble/hashes@2.0.1)(@welshman/lib@0.8.7)(@welshman/net@0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/be4bb90a1a15c8eec0934f2f66ce9e82ecc72d51(@capacitor/core@8.0.1))(nostr-tools@2.20.0(typescript@5.9.3)) '@welshman/signer': 0.8.8(@noble/curves@1.9.7)(@noble/hashes@2.0.1)(@welshman/lib@0.8.8)(@welshman/net@0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/be4bb90a1a15c8eec0934f2f66ce9e82ecc72d51(@capacitor/core@8.0.1))(nostr-tools@2.20.0(typescript@5.9.3))
'@welshman/util': 0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)) '@welshman/util': 0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3))
trava: 1.2.1 trava: 1.2.1
'@welshman/lib@0.8.7': '@welshman/lib@0.8.8':
dependencies: dependencies:
'@scure/base': 1.2.6 '@scure/base': 1.2.6
'@types/events': 3.0.3 '@types/events': 3.0.3
events: 3.3.0 events: 3.3.0
'@welshman/net@0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3)': '@welshman/net@0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3)':
dependencies: dependencies:
'@welshman/lib': 0.8.7 '@welshman/lib': 0.8.8
'@welshman/util': 0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)) '@welshman/util': 0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3))
events: 3.3.0 events: 3.3.0
isomorphic-ws: 5.0.0(ws@8.18.3) isomorphic-ws: 5.0.0(ws@8.18.3)
transitivePeerDependencies: transitivePeerDependencies:
- ws - ws
'@welshman/router@0.8.7(@welshman/lib@0.8.7)(@welshman/net@0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))': '@welshman/router@0.8.8(@welshman/lib@0.8.8)(@welshman/net@0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))':
dependencies: dependencies:
'@welshman/lib': 0.8.7 '@welshman/lib': 0.8.8
'@welshman/net': 0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3) '@welshman/net': 0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3)
'@welshman/util': 0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)) '@welshman/util': 0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3))
'@welshman/signer@0.8.7(@noble/curves@1.9.7)(@noble/hashes@2.0.1)(@welshman/lib@0.8.7)(@welshman/net@0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/be4bb90a1a15c8eec0934f2f66ce9e82ecc72d51(@capacitor/core@8.0.1))(nostr-tools@2.20.0(typescript@5.9.3))': '@welshman/signer@0.8.8(@noble/curves@1.9.7)(@noble/hashes@2.0.1)(@welshman/lib@0.8.8)(@welshman/net@0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/be4bb90a1a15c8eec0934f2f66ce9e82ecc72d51(@capacitor/core@8.0.1))(nostr-tools@2.20.0(typescript@5.9.3))':
dependencies: dependencies:
'@noble/curves': 1.9.7 '@noble/curves': 1.9.7
'@noble/hashes': 2.0.1 '@noble/hashes': 2.0.1
'@welshman/lib': 0.8.7 '@welshman/lib': 0.8.8
'@welshman/net': 0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3) '@welshman/net': 0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3)
'@welshman/util': 0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)) '@welshman/util': 0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3))
nostr-signer-capacitor-plugin: https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/be4bb90a1a15c8eec0934f2f66ce9e82ecc72d51(@capacitor/core@8.0.1) nostr-signer-capacitor-plugin: https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/be4bb90a1a15c8eec0934f2f66ce9e82ecc72d51(@capacitor/core@8.0.1)
nostr-tools: 2.20.0(typescript@5.9.3) nostr-tools: 2.20.0(typescript@5.9.3)
'@welshman/store@0.8.7(@welshman/lib@0.8.7)(@welshman/net@0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(svelte@5.48.0)': '@welshman/store@0.8.8(@welshman/lib@0.8.8)(@welshman/net@0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3))(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(svelte@5.48.0)':
dependencies: dependencies:
'@welshman/lib': 0.8.7 '@welshman/lib': 0.8.8
'@welshman/net': 0.8.7(@welshman/lib@0.8.7)(@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3) '@welshman/net': 0.8.8(@welshman/lib@0.8.8)(@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)))(ws@8.18.3)
'@welshman/util': 0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3)) '@welshman/util': 0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3))
svelte: 5.48.0 svelte: 5.48.0
'@welshman/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(nostr-tools@2.20.0(typescript@5.9.3))': '@welshman/util@0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3))':
dependencies: dependencies:
'@noble/curves': 1.9.7 '@noble/curves': 1.9.7
'@types/ws': 8.18.1 '@types/ws': 8.18.1
'@welshman/lib': 0.8.7 '@welshman/lib': 0.8.8
js-base64: 3.7.8 js-base64: 3.7.8
nostr-tools: 2.20.0(typescript@5.9.3) nostr-tools: 2.20.0(typescript@5.9.3)
nostr-wasm: 0.1.0 nostr-wasm: 0.1.0
@@ -7027,6 +7221,12 @@ snapshots:
asap@2.0.6: {} asap@2.0.6: {}
asn1js@3.0.7:
dependencies:
pvtsutils: 1.3.6
pvutils: 1.1.5
tslib: 2.8.1
astral-regex@2.0.0: {} astral-regex@2.0.0: {}
async-function@1.0.0: {} async-function@1.0.0: {}
@@ -7156,6 +7356,22 @@ snapshots:
caniuse-lite@1.0.30001766: {} caniuse-lite@1.0.30001766: {}
cbor-extract@2.2.0:
dependencies:
node-gyp-build-optional-packages: 5.1.1
optionalDependencies:
'@cbor-extract/cbor-extract-darwin-arm64': 2.2.0
'@cbor-extract/cbor-extract-darwin-x64': 2.2.0
'@cbor-extract/cbor-extract-linux-arm': 2.2.0
'@cbor-extract/cbor-extract-linux-arm64': 2.2.0
'@cbor-extract/cbor-extract-linux-x64': 2.2.0
'@cbor-extract/cbor-extract-win32-x64': 2.2.0
optional: true
cbor-x@1.6.0:
optionalDependencies:
cbor-extract: 2.2.0
chalk@2.4.2: chalk@2.4.2:
dependencies: dependencies:
ansi-styles: 3.2.1 ansi-styles: 3.2.1
@@ -8449,15 +8665,6 @@ snapshots:
markdown-it-task-lists@2.1.1: {} markdown-it-task-lists@2.1.1: {}
markdown-it@14.1.0:
dependencies:
argparse: 2.0.1
entities: 4.5.0
linkify-it: 5.0.0
mdurl: 2.0.0
punycode.js: 2.3.1
uc.micro: 2.1.0
markdown-it@14.1.1: markdown-it@14.1.1:
dependencies: dependencies:
argparse: 2.0.1 argparse: 2.0.1
@@ -8595,6 +8802,11 @@ snapshots:
dependencies: dependencies:
whatwg-url: 5.0.0 whatwg-url: 5.0.0
node-gyp-build-optional-packages@5.1.1:
dependencies:
detect-libc: 2.1.2
optional: true
node-html-parser@5.4.2: node-html-parser@5.4.2:
dependencies: dependencies:
css-select: 4.3.0 css-select: 4.3.0
@@ -8953,7 +9165,7 @@ snapshots:
prosemirror-markdown@1.13.3: prosemirror-markdown@1.13.3:
dependencies: dependencies:
'@types/markdown-it': 14.1.2 '@types/markdown-it': 14.1.2
markdown-it: 14.1.0 markdown-it: 14.1.1
prosemirror-model: 1.25.4 prosemirror-model: 1.25.4
prosemirror-menu@1.2.5: prosemirror-menu@1.2.5:
@@ -9013,6 +9225,12 @@ snapshots:
punycode@2.3.1: {} punycode@2.3.1: {}
pvtsutils@1.3.6:
dependencies:
tslib: 2.8.1
pvutils@1.1.5: {}
q@1.5.1: {} q@1.5.1: {}
qr-scanner@1.4.2: qr-scanner@1.4.2:
@@ -9088,6 +9306,8 @@ snapshots:
indent-string: 4.0.0 indent-string: 4.0.0
strip-indent: 3.0.0 strip-indent: 3.0.0
reflect-metadata@0.2.2: {}
reflect.getprototypeof@1.0.10: reflect.getprototypeof@1.0.10:
dependencies: dependencies:
call-bind: 1.0.8 call-bind: 1.0.8
@@ -9707,10 +9927,16 @@ snapshots:
v8-compile-cache-lib: 3.0.1 v8-compile-cache-lib: 3.0.1
yn: 3.1.1 yn: 3.1.1
tslib@1.14.1: {}
tslib@2.6.2: {} tslib@2.6.2: {}
tslib@2.8.1: {} tslib@2.8.1: {}
tsyringe@4.10.0:
dependencies:
tslib: 1.14.1
type-check@0.4.0: type-check@0.4.0:
dependencies: dependencies:
prelude-ls: 1.2.1 prelude-ls: 1.2.1
+1 -1
View File
@@ -1,7 +1,7 @@
import dotenv from "dotenv" import dotenv from "dotenv"
import {defineConfig, minimalPreset as preset} from "@vite-pwa/assets-generator/config" import {defineConfig, minimalPreset as preset} from "@vite-pwa/assets-generator/config"
dotenv.config({path: ".env"}) dotenv.config({path: ".env.local"})
dotenv.config({path: ".env.template"}) dotenv.config({path: ".env.template"})
export default defineConfig({ export default defineConfig({
+4 -19
View File
@@ -15,10 +15,10 @@
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import StringMultiInput from "@lib/components/StringMultiInput.svelte"
import KeyDownload from "@app/components/KeyDownload.svelte" import KeyDownload from "@app/components/KeyDownload.svelte"
import {pushToast} from "@app/util/toast" import {pushToast} from "@app/util/toast"
import {pushModal, clearModals} from "@app/util/modal" import {pushModal, clearModals} from "@app/util/modal"
import {POMADE_SIGNERS} from "@app/core/state"
type Props = { type Props = {
peersByPrefix: Map<string, string> peersByPrefix: Map<string, string>
@@ -32,18 +32,6 @@
} = $session as SessionPomade } = $session as SessionPomade
const confirmRecovery = async () => { const confirmRecovery = async () => {
const otps = input
.split(/\n/)
.map(x => x.trim())
.filter(x => x.match(/^[0-9]{8}$/))
if (otps.length < 2) {
return pushToast({
theme: "error",
message: "Failed to recover, not enough valid recovery codes were provided.",
})
}
const request = await Client.recoverWithChallenge(email, peersByPrefix, otps) const request = await Client.recoverWithChallenge(email, peersByPrefix, otps)
if (!request.ok) { if (!request.ok) {
@@ -82,7 +70,7 @@
const back = () => history.back() const back = () => history.back()
let loading = $state(false) let loading = $state(false)
let input = $state("") let otps = $state<string[]>([])
</script> </script>
<Modal tag="form" onsubmit={preventDefault(submit)}> <Modal tag="form" onsubmit={preventDefault(submit)}>
@@ -96,17 +84,14 @@
For security reasons, you may receive three or more emails with recovery codes in them. Please For security reasons, you may receive three or more emails with recovery codes in them. Please
paste <strong>all</strong> recovery codes into the text box below, on separate lines. paste <strong>all</strong> recovery codes into the text box below, on separate lines.
</p> </p>
<textarea <StringMultiInput bind:value={otps} placeholder="Enter your recovery codes..." />
rows={POMADE_SIGNERS.length + 1}
class="textarea textarea-bordered leading-4"
bind:value={input}></textarea>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button type="submit" class="btn btn-primary" disabled={loading}> <Button type="submit" class="btn btn-primary" disabled={loading || otps.length < 2}>
<Spinner {loading}>Confirm recovery</Spinner> <Spinner {loading}>Confirm recovery</Spinner>
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
-1
View File
@@ -34,7 +34,6 @@
const onSuccess = async (session: Session) => { const onSuccess = async (session: Session) => {
addSession(session) addSession(session)
pushToast({message: "Successfully logged in!"})
setChecked("*") setChecked("*")
clearModals() clearModals()
} }
+21 -15
View File
@@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import {uniq} from "@welshman/lib"
import {Client} from "@pomade/core" import {Client} from "@pomade/core"
import {loginWithPomade} from "@welshman/app"
import {preventDefault} from "@lib/html" import {preventDefault} from "@lib/html"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
@@ -17,6 +17,8 @@
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import LogInOTP from "@app/components/LogInOTP.svelte" import LogInOTP from "@app/components/LogInOTP.svelte"
import LogInSelect from "@app/components/LogInSelect.svelte"
import {deleteDeactivatedPomadeSessions, loginWithPomade} from "@app/util/pomade"
import {pushModal, clearModals} from "@app/util/modal" import {pushModal, clearModals} from "@app/util/modal"
import {setChecked} from "@app/util/notifications" import {setChecked} from "@app/util/notifications"
import {pushToast} from "@app/util/toast" import {pushToast} from "@app/util/toast"
@@ -37,7 +39,7 @@
try { try {
const {ok, options, messages, clientSecret} = await Client.loginWithPassword(email, password) const {ok, options, messages, clientSecret} = await Client.loginWithPassword(email, password)
if (!ok) { if (!ok || options.length === 0) {
console.error(messages) console.error(messages)
return pushToast({ return pushToast({
@@ -46,21 +48,25 @@
}) })
} }
const [client, peers] = options[0]! if (uniq(options.map(o => o.pubkey)).length > 1) {
const {clientOptions, ...res} = await Client.selectLogin(clientSecret, client, peers) pushModal(LogInSelect, {email, options, clientSecret})
if (res.ok && clientOptions) {
loginWithPomade(clientOptions.group.group_pk.slice(2), email, clientOptions)
pushToast({message: "Successfully logged in!"})
setChecked("*")
clearModals()
} else { } else {
console.error(res.messages) const {client, peers} = options[0]
const {clientOptions, ...res} = await Client.selectLogin(clientSecret, client, peers)
pushToast({ if (res.ok && clientOptions) {
theme: "error", loginWithPomade(clientOptions, email)
message: "Sorry, we were unable to log you in.", deleteDeactivatedPomadeSessions()
}) setChecked("*")
clearModals()
} else {
console.error(res.messages)
pushToast({
theme: "error",
message: "Sorry, we were unable to log you in.",
})
}
} }
} finally { } finally {
loading = false loading = false
-1
View File
@@ -57,7 +57,6 @@
} }
loginWithNip01(secret) loginWithNip01(secret)
pushToast({message: "Successfully logged in!"})
setChecked("*") setChecked("*")
clearModals() clearModals()
} catch (e) { } catch (e) {
+27 -36
View File
@@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import {uniq} from "@welshman/lib"
import {Client} from "@pomade/core" import {Client} from "@pomade/core"
import {loginWithPomade} from "@welshman/app"
import {preventDefault} from "@lib/html" import {preventDefault} from "@lib/html"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
@@ -13,10 +13,12 @@
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import {clearModals} from "@app/util/modal" import StringMultiInput from "@lib/components/StringMultiInput.svelte"
import {setChecked} from "@app/util/notifications" import LogInSelect from "@app/components/LogInSelect.svelte"
import {pushToast} from "@app/util/toast" import {pushToast} from "@app/util/toast"
import {POMADE_SIGNERS} from "@app/core/state" import {setChecked} from "@app/util/notifications"
import {pushModal, clearModals} from "@app/util/modal"
import {deleteDeactivatedPomadeSessions, loginWithPomade} from "@app/util/pomade"
type Props = { type Props = {
email: string email: string
@@ -28,18 +30,6 @@
const back = () => history.back() const back = () => history.back()
const onSubmit = async () => { const onSubmit = async () => {
const otps = input
.split(/\n/)
.map(x => x.trim())
.filter(x => x.match(/^[0-9]{8}$/))
if (otps.length < 2) {
return pushToast({
theme: "error",
message: "Failed to recover, not enough valid recovery codes were provided.",
})
}
loading = true loading = true
try { try {
@@ -49,7 +39,7 @@
otps, otps,
) )
if (!ok) { if (!ok || options.length === 0) {
console.error(messages) console.error(messages)
return pushToast({ return pushToast({
@@ -58,28 +48,32 @@
}) })
} }
const [client, peers] = options[0]! if (uniq(options.map(o => o.pubkey)).length > 1) {
const {clientOptions, ...res} = await Client.selectLogin(clientSecret, client, peers) pushModal(LogInSelect, {email, options, clientSecret})
if (res.ok && clientOptions) {
loginWithPomade(clientOptions.group.group_pk.slice(2), email, clientOptions)
pushToast({message: "Successfully logged in!"})
setChecked("*")
clearModals()
} else { } else {
console.error(res.messages) const {client, peers} = options[0]
const {clientOptions, ...res} = await Client.selectLogin(clientSecret, client, peers)
pushToast({ if (res.ok && clientOptions) {
theme: "error", loginWithPomade(clientOptions, email)
message: "Sorry, we were unable to log you in.", deleteDeactivatedPomadeSessions()
}) setChecked("*")
clearModals()
} else {
console.error(res.messages)
pushToast({
theme: "error",
message: "Sorry, we were unable to log you in.",
})
}
} }
} finally { } finally {
loading = false loading = false
} }
} }
let input = $state("") let otps = $state<string[]>([])
let loading = $state(false) let loading = $state(false)
</script> </script>
@@ -94,17 +88,14 @@
For security reasons, you may receive three or more emails with login codes in them. Please For security reasons, you may receive three or more emails with login codes in them. Please
paste <strong>all</strong> login codes into the text box below, on separate lines. paste <strong>all</strong> login codes into the text box below, on separate lines.
</p> </p>
<textarea <StringMultiInput bind:value={otps} placeholder="Enter your login codes..." />
rows={POMADE_SIGNERS.length + 1}
class="textarea textarea-bordered leading-4"
bind:value={input}></textarea>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back} disabled={loading}> <Button class="btn btn-link" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button type="submit" class="btn btn-primary" disabled={loading}> <Button type="submit" class="btn btn-primary" disabled={loading || otps.length < 3}>
<Spinner {loading}>Log In</Spinner> <Spinner {loading}>Log In</Spinner>
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
+83
View File
@@ -0,0 +1,83 @@
<script lang="ts">
import type {AccountOption} from "@pomade/core"
import {Client} from "@pomade/core"
import {uniqBy} from "@welshman/lib"
import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import Icon from "@lib/components/Icon.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte"
import Profile from "@app/components/Profile.svelte"
import {deleteDeactivatedPomadeSessions, loginWithPomade} from "@app/util/pomade"
import {setChecked} from "@app/util/notifications"
import {clearModals} from "@app/util/modal"
import {pushToast} from "@app/util/toast"
interface Props {
email: string
options: AccountOption[]
clientSecret: string
}
const {email, options, clientSecret}: Props = $props()
let loading = $state(false)
const back = () => history.back()
const selectAccount = async ({client, peers}: AccountOption) => {
loading = true
try {
const {clientOptions, ...res} = await Client.selectLogin(clientSecret, client, peers)
if (res.ok && clientOptions) {
loginWithPomade(clientOptions, email)
deleteDeactivatedPomadeSessions()
setChecked("*")
clearModals()
} else {
console.error(res.messages)
pushToast({
theme: "error",
message: "Sorry, we were unable to log you in.",
})
}
} finally {
loading = false
}
}
</script>
<Modal>
<ModalBody>
<ModalHeader>
<ModalTitle>Select Account</ModalTitle>
<ModalSubtitle
>Multiple accounts are associated with {email}. Please select one to continue.</ModalSubtitle>
</ModalHeader>
<div class="flex flex-col gap-2">
{#each uniqBy(o => o.pubkey, options) as option (option.pubkey)}
<Button
onclick={() => selectAccount(option)}
disabled={loading}
class="card2 bg-alt flex w-full items-center p-3 text-left">
<Profile pubkey={option.pubkey} />
</Button>
{/each}
</div>
</ModalBody>
<ModalFooter>
<Button class="btn btn-link" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
<Spinner {loading} />
</ModalFooter>
</Modal>
+2 -9
View File
@@ -9,8 +9,7 @@
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components/ModalTitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import {Push} from "@app/util/notifications" import {logout} from "@app/util/logout"
import {kv, db} from "@app/core/storage"
const back = () => history.back() const back = () => history.back()
@@ -18,13 +17,7 @@
loading = true loading = true
try { try {
await Push.disable() await logout()
await kv.clear()
await db.clear()
localStorage.clear()
window.location.href = "/"
} catch (e) { } catch (e) {
console.error(e) console.error(e)
loading = false loading = false
@@ -22,8 +22,8 @@
{#if props.event.content} {#if props.event.content}
<Content {...props} /> <Content {...props} />
{/if} {/if}
<div class="grid grid-cols-3 sm:grid-cols-5 lg:grid-cols-9"> <div class="grid grid-cols-3 sm:grid-cols-5 lg:grid-cols-9 gap-2">
{#each images as image (image)} {#each images as image, i (i + image)}
<ContentLinkBlock event={props.event} value={{url: image}} /> <ContentLinkBlock event={props.event} value={{url: image}} />
{/each} {/each}
</div> </div>
+106
View File
@@ -0,0 +1,106 @@
<script lang="ts">
import {Client} from "@pomade/core"
import type {SessionPomade} from "@welshman/app"
import {session} from "@welshman/app"
import {preventDefault} from "@lib/html"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte"
import StringMultiInput from "@lib/components/StringMultiInput.svelte"
import PasswordResetConfirm from "@app/components/PasswordResetConfirm.svelte"
import {pushToast} from "@app/util/toast"
import {pushModal} from "@app/util/modal"
import {getPomadeClient} from "@app/util/pomade"
type Props = {
peersByPrefix: Map<string, string>
}
const {peersByPrefix}: Props = $props()
const {email} = $session as SessionPomade
const confirmRecovery = async () => {
const request = await Client.recoverWithChallenge(email, peersByPrefix, otps)
if (!request.ok) {
console.log(request.messages)
return pushToast({
theme: "error",
message: `Failed to validate email ownership: ${request.messages[0]?.res?.message.toLowerCase()}`,
})
}
const client = await getPomadeClient()
if (!client) {
throw new Error("Unable to get client during password reset flow")
}
const result = await Client.selectRecovery(
request.clientSecret,
await client.getPubkey(),
client.peers,
)
if (!result.ok) {
console.log(result.messages)
return pushToast({
theme: "error",
message: `Failed to validate email ownership: ${result.messages[0]?.res?.message.toLowerCase()}`,
})
}
pushModal(PasswordResetConfirm, {userSecret: result.userSecret})
}
const submit = async () => {
loading = true
try {
await confirmRecovery()
} finally {
loading = false
}
}
const back = () => history.back()
let loading = $state(false)
let otps = $state<string[]>([])
</script>
<Modal tag="form" onsubmit={preventDefault(submit)}>
<ModalBody>
<ModalHeader>
<ModalTitle>Update your Password</ModalTitle>
<ModalSubtitle>Confirm your Email</ModalSubtitle>
</ModalHeader>
<p>Let's start by confirming your email.</p>
<p>
For security reasons, you may receive three or more emails with confirmation codes in them.
Please paste <strong>all</strong> confirmation codes into the text box below, on separate lines.
</p>
<StringMultiInput bind:value={otps} placeholder="Enter your confirmation codes..." />
</ModalBody>
<ModalFooter>
<Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
<Button type="submit" class="btn btn-primary" disabled={loading || otps.length < 2}>
<Spinner {loading}>Continue</Spinner>
<Icon icon={AltArrowRight} />
</Button>
</ModalFooter>
</Modal>
@@ -0,0 +1,118 @@
<script lang="ts">
import {Client} from "@pomade/core"
import {session} from "@welshman/app"
import type {SessionPomade} from "@welshman/app"
import {preventDefault} from "@lib/html"
import Key from "@assets/icons/key.svg?dataurl"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte"
import FieldInline from "@lib/components/FieldInline.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import Button from "@lib/components/Button.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte"
import {loginWithPomade, deleteCurrentPomadeSession} from "@app/util/pomade"
import {clearModals} from "@app/util/modal"
import {pushToast} from "@app/util/toast"
type Props = {
userSecret: string
}
const {userSecret}: Props = $props()
const {email} = $session as SessionPomade
const back = () => history.back()
const onSubmit = async () => {
if (password.trim().length < 12) {
return pushToast({
theme: "error",
message: "Password must be at least 12 characters long.",
})
}
loading = true
try {
pushToast({
timeout: 60_000,
message: "Registering your new password, please wait...",
})
const {clientOptions, ...registerRes} = await Client.register(2, 3, userSecret)
if (!registerRes.ok) {
return pushToast({
theme: "error",
message: "Failed to register your new password! Please try again.",
})
}
const setupRes = await new Client(clientOptions).setupRecovery(email, password)
if (!setupRes.ok) {
const message = setupRes.messages[0]?.res?.message || "Please try again."
return pushToast({
theme: "error",
message: `Failed to register your new password! ${message}.`,
})
}
await deleteCurrentPomadeSession()
pushToast({message: "Your password has been updated!"})
loginWithPomade(clientOptions, email)
clearModals()
} catch (e) {
console.error(e)
pushToast({
theme: "error",
message: "Failed to register your new password! Please try again.",
})
} finally {
loading = false
}
}
let password = $state("")
let loading = $state(false)
</script>
<Modal tag="form" onsubmit={preventDefault(onSubmit)}>
<ModalBody>
<ModalHeader>
<ModalTitle>Update your Password</ModalTitle>
<ModalSubtitle>Please provide your new password.</ModalSubtitle>
</ModalHeader>
<FieldInline>
{#snippet label()}
<p>New Password*</p>
{/snippet}
{#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2">
<Icon icon={Key} />
<input type="password" bind:value={password} />
</label>
{/snippet}
</FieldInline>
</ModalBody>
<ModalFooter>
<Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
<Button class="btn btn-primary" type="submit" disabled={loading || !password}>
<Spinner {loading}>Continue</Spinner>
<Icon icon={AltArrowRight} />
</Button>
</ModalFooter>
</Modal>
+57 -60
View File
@@ -1,51 +1,30 @@
<script lang="ts"> <script lang="ts">
import {onMount} from "svelte"
import {Client} from "@pomade/core" import {Client} from "@pomade/core"
import type {SessionItem} from "@pomade/core"
import {session, isPomadeSession} from "@welshman/app" import {session, isPomadeSession} from "@welshman/app"
import MenuDots from "@assets/icons/menu-dots.svg?dataurl"
import {fly} from "@lib/transition"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Popover from "@lib/components/Popover.svelte"
import TrashBin2 from "@assets/icons/trash-bin-2.svg?dataurl" import TrashBin2 from "@assets/icons/trash-bin-2.svg?dataurl"
import {pushToast} from "@app/util/toast" import {pushToast} from "@app/util/toast"
import {onMount} from "svelte" import {loadOtherPomadeSessions} from "@app/util/pomade"
import type {PomadeSessionWithPeers} from "@app/util/pomade"
type SessionWithPeers = SessionItem & {peers: string[]} const toggleMenu = (client: string) => {
menuClient = menuClient === client ? "" : client
let sessions = $state<SessionWithPeers[]>([])
let deletingSession = $state<string | null>(null)
const loadSessions = async () => {
if (!isPomadeSession($session)) return
const client = new Client($session.clientOptions)
const result = await client.listSessions()
const pubkey = await client.getPubkey()
if (result.ok) {
// Group sessions by client pubkey and collect peers
const sessionMap = new Map<string, SessionWithPeers>()
for (const message of result.messages) {
if (!message.res?.items) continue
for (const item of message.res.items) {
const existing = sessionMap.get(item.client)
if (existing) {
existing.peers.push(message.url)
} else if (item.client !== pubkey) {
sessionMap.set(item.client, {...item, peers: [message.url]})
}
}
}
sessions = Array.from(sessionMap.values())
}
} }
const deleteSession = async (sessionItem: SessionWithPeers) => { const closeMenu = () => {
if (!isPomadeSession($session)) return menuClient = ""
}
deletingSession = sessionItem.client let menuClient = $state("")
let sessions = $state<PomadeSessionWithPeers[]>([])
const deleteSession = async (sessionItem: PomadeSessionWithPeers) => {
if (!isPomadeSession($session)) return
try { try {
const client = new Client($session.clientOptions) const client = new Client($session.clientOptions)
@@ -70,8 +49,6 @@
theme: "error", theme: "error",
message: "Failed to delete session", message: "Failed to delete session",
}) })
} finally {
deletingSession = null
} }
} }
@@ -85,7 +62,9 @@
} }
onMount(() => { onMount(() => {
loadSessions() loadOtherPomadeSessions().then(_sessions => {
sessions = _sessions || []
})
}) })
</script> </script>
@@ -93,28 +72,46 @@
<div class="flex flex-col gap-4 border-t border-solid border-base-100 pt-4"> <div class="flex flex-col gap-4 border-t border-solid border-base-100 pt-4">
<strong>Other Sessions</strong> <strong>Other Sessions</strong>
{#each sessions as sessionItem (sessionItem.client)} {#each sessions as sessionItem (sessionItem.client)}
<div class="flex justify-between text-sm"> <div class="flex flex-col gap-2">
<div class="flex flex-col gap-1"> <div class="flex justify-between items-center">
<span>{sessionItem.client.slice(0, 8)}</span> <div class="flex gap-3 items-center text-sm">
<div class="flex gap-1"> <span>Session {sessionItem.client.slice(0, 8)}</span>
<div class="badge badge-neutral"> <span class="opacity-75">
Created {formatDate(sessionItem.created_at)} {#if sessionItem.deactivated_at}
</div> Deactivated
<div class="badge badge-neutral"> {/if}
Last active: {formatDate(sessionItem.last_activity)} </span>
</div> </div>
<div class="relative">
<Button
class="btn btn-circle btn-ghost btn-sm"
onclick={() => toggleMenu(sessionItem.client)}>
<Icon icon={MenuDots} />
</Button>
{#if menuClient === sessionItem.client}
<Popover hideOnClick onClose={closeMenu}>
<ul
transition:fly
class="menu absolute right-0 z-popover mt-2 w-48 gap-1 rounded-box bg-base-100 p-2 shadow-md">
<li>
<Button onclick={() => deleteSession(sessionItem)}>
<Icon icon={TrashBin2} />
Delete Session
</Button>
</li>
</ul>
</Popover>
{/if}
</div>
</div>
<div class="flex gap-1">
<div class="badge badge-neutral">
Created {formatDate(sessionItem.created_at)}
</div>
<div class="badge badge-neutral">
Active {formatDate(sessionItem.last_activity)}
</div> </div>
</div> </div>
<Button
class="btn btn-error btn-sm"
disabled={deletingSession !== null}
onclick={() => deleteSession(sessionItem)}>
{#if deletingSession === sessionItem.client}
<span class="loading loading-spinner"></span>
{:else}
<Icon icon={TrashBin2} />
{/if}
</Button>
</div> </div>
{/each} {/each}
</div> </div>
+2 -9
View File
@@ -23,9 +23,8 @@
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components/ModalBody.svelte"
import {INDEXER_RELAYS, PLATFORM_NAME, userSpaceUrls} from "@app/core/state" import {INDEXER_RELAYS, PLATFORM_NAME, userSpaceUrls} from "@app/core/state"
import {kv, db} from "@app/core/storage"
import {pushToast} from "@app/util/toast" import {pushToast} from "@app/util/toast"
import {Push} from "@app/util/notifications" import {logout} from "@app/util/logout"
let progress: number | undefined = $state(undefined) let progress: number | undefined = $state(undefined)
let confirmText = $state("") let confirmText = $state("")
@@ -88,13 +87,7 @@
await sleep(2000) await sleep(2000)
// Goodbye forever! // Goodbye forever!
await Push.disable() await logout()
await kv.clear()
await db.clear()
localStorage.clear()
window.location.href = "/"
} }
const confirm = async () => { const confirm = async () => {
+33 -6
View File
@@ -1,10 +1,12 @@
<script lang="ts"> <script lang="ts">
import type {Profile} from "@welshman/util" import type {Profile} from "@welshman/util"
import {getTag, makeProfile} from "@welshman/util" import {getTag, makeProfile} from "@welshman/util"
import {pubkey, profilesByPubkey} from "@welshman/app" import {pubkey, profilesByPubkey, waitForThunkError} from "@welshman/app"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import {errorMessage} from "@lib/util"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import ProfileEditForm from "@app/components/ProfileEditForm.svelte" import ProfileEditForm from "@app/components/ProfileEditForm.svelte"
import {clearModals} from "@app/util/modal" import {clearModals} from "@app/util/modal"
import {pushToast} from "@app/util/toast" import {pushToast} from "@app/util/toast"
@@ -17,11 +19,33 @@
const back = () => history.back() const back = () => history.back()
const onsubmit = ({profile, shouldBroadcast}: {profile: Profile; shouldBroadcast: boolean}) => { const onsubmit = async ({
updateProfile({profile, shouldBroadcast}) profile,
pushToast({message: "Your profile has been updated!"}) shouldBroadcast,
clearModals() }: {
profile: Profile
shouldBroadcast: boolean
}) => {
loading = true
try {
const error = await waitForThunkError(updateProfile({profile, shouldBroadcast}))
if (error) {
pushToast({
theme: "error",
message: `Failed to update your profile: ${errorMessage(error)}`,
})
} else {
pushToast({message: "Your profile has been updated!"})
clearModals()
}
} finally {
loading = false
}
} }
let loading = $state(false)
</script> </script>
<ProfileEditForm {initialValues} {onsubmit}> <ProfileEditForm {initialValues} {onsubmit}>
@@ -30,6 +54,9 @@
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go Back Go Back
</Button> </Button>
<Button type="submit" class="btn btn-primary">Save Changes</Button> <Button type="submit" class="btn btn-primary" disabled={loading}>
<Spinner {loading} />
Save Changes
</Button>
{/snippet} {/snippet}
</ProfileEditForm> </ProfileEditForm>
+6 -13
View File
@@ -1,15 +1,8 @@
<script lang="ts"> <script lang="ts">
import type {ClientOptions} from "@pomade/core" import type {ClientOptions} from "@pomade/core"
import type {Profile} from "@welshman/util" import type {Profile} from "@welshman/util"
import { import {makeProfile, makeSecret, RELAYS, MESSAGING_RELAYS, makeEvent} from "@welshman/util"
makeProfile, import {loginWithNip01, publishThunk} from "@welshman/app"
makeSecret,
getPubkey,
RELAYS,
MESSAGING_RELAYS,
makeEvent,
} from "@welshman/util"
import {loginWithNip01, loginWithPomade, publishThunk} from "@welshman/app"
import Key from "@assets/icons/key-minimalistic.svg?dataurl" import Key from "@assets/icons/key-minimalistic.svg?dataurl"
import Letter from "@assets/icons/letter.svg?dataurl" import Letter from "@assets/icons/letter.svg?dataurl"
import {getKey, setKey} from "@lib/implicit" import {getKey, setKey} from "@lib/implicit"
@@ -23,8 +16,6 @@
import SignUpEmail from "@app/components/SignUpEmail.svelte" import SignUpEmail from "@app/components/SignUpEmail.svelte"
import SignUpProfile from "@app/components/SignUpProfile.svelte" import SignUpProfile from "@app/components/SignUpProfile.svelte"
import SignUpComplete from "@app/components/SignUpComplete.svelte" import SignUpComplete from "@app/components/SignUpComplete.svelte"
import {setChecked} from "@app/util/notifications"
import {pushModal, clearModals} from "@app/util/modal"
import {initProfile} from "@app/core/commands" import {initProfile} from "@app/core/commands"
import { import {
POMADE_SIGNERS, POMADE_SIGNERS,
@@ -33,6 +24,9 @@
DEFAULT_RELAYS, DEFAULT_RELAYS,
DEFAULT_MESSAGING_RELAYS, DEFAULT_MESSAGING_RELAYS,
} from "@app/core/state" } from "@app/core/state"
import {setChecked} from "@app/util/notifications"
import {loginWithPomade} from "@app/util/pomade"
import {pushModal, clearModals} from "@app/util/modal"
setKey("signup.email", "") setKey("signup.email", "")
setKey("signup.secret", makeSecret()) setKey("signup.secret", makeSecret())
@@ -73,10 +67,9 @@
complete: () => pushModal(SignUpComplete, {next: flows.email.finalize}), complete: () => pushModal(SignUpComplete, {next: flows.email.finalize}),
finalize: () => { finalize: () => {
const email = getKey<string>("signup.email")! const email = getKey<string>("signup.email")!
const secret = getKey<string>("signup.secret")!
const clientOptions = getKey<ClientOptions>("signup.clientOptions")! const clientOptions = getKey<ClientOptions>("signup.clientOptions")!
loginWithPomade(getPubkey(secret), email, clientOptions) loginWithPomade(clientOptions, email)
completeSignup() completeSignup()
}, },
}, },
+9 -2
View File
@@ -18,7 +18,7 @@
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import SignUpEmailConfirm from "@app/components/SignUpEmailConfirm.svelte" import SignUpEmailConfirm from "@app/components/SignUpEmailConfirm.svelte"
import {pushToast} from "@app/util/toast" import {pushToast, popToast} from "@app/util/toast"
import {pushModal} from "@app/util/modal" import {pushModal} from "@app/util/modal"
type Props = { type Props = {
@@ -40,6 +40,11 @@
loading = true loading = true
try { try {
const toastId = pushToast({
timeout: 60_000,
message: "Creating your account, please wait...",
})
const secret = getKey<string>("signup.secret")! const secret = getKey<string>("signup.secret")!
const {clientOptions, ...registerRes} = await Client.register(2, 3, secret) const {clientOptions, ...registerRes} = await Client.register(2, 3, secret)
@@ -54,7 +59,8 @@
const setupRes = await client.setupRecovery(email, password) const setupRes = await client.setupRecovery(email, password)
if (!setupRes.ok) { if (!setupRes.ok) {
const message = setupRes.messages[0]?.res?.message || "Please try again." const message =
setupRes.messages.find(m => m.res && !m.res?.ok)?.res?.message || "Please try again."
return pushToast({ return pushToast({
theme: "error", theme: "error",
@@ -74,6 +80,7 @@
setKey("signup.email", email) setKey("signup.email", email)
setKey("signup.clientOptions", clientOptions) setKey("signup.clientOptions", clientOptions)
popToast(toastId)
pushModal(SignUpEmailConfirm, {next}) pushModal(SignUpEmailConfirm, {next})
} catch (e) { } catch (e) {
console.error(e) console.error(e)
@@ -1,5 +1,8 @@
<script lang="ts"> <script lang="ts">
import {makeProfile} from "@welshman/util"
import {getWalletAddress} from "@welshman/util" import {getWalletAddress} from "@welshman/util"
import {userProfile, waitForThunkError, session} from "@welshman/app"
import {errorMessage} from "@lib/util"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components/Modal.svelte"
@@ -9,8 +12,7 @@
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import {updateProfile} from "@app/core/commands" import {updateProfile} from "@app/core/commands"
import {clearModals} from "@app/util/modal" import {clearModals} from "@app/util/modal"
import {userProfile, session} from "@welshman/app" import {pushToast} from "@app/util/toast"
import {makeProfile} from "@welshman/util"
const lud16 = getWalletAddress($session!.wallet!) const lud16 = getWalletAddress($session!.wallet!)
@@ -20,9 +22,13 @@
loading = true loading = true
try { try {
await updateProfile({profile: {...profile, lud16}}) const error = await waitForThunkError(updateProfile({profile: {...profile, lud16}}))
clearModals() if (error) {
pushToast({theme: "error", message: `Failed to update profile: ${errorMessage(error)}`})
} else {
clearModals()
}
} finally { } finally {
loading = false loading = false
} }
@@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import {getWalletAddress} from "@welshman/util" import {getWalletAddress} from "@welshman/util"
import {session, userProfile} from "@welshman/app" import {session, waitForThunkError, userProfile} from "@welshman/app"
import {errorMessage} from "@lib/util"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
@@ -17,7 +18,7 @@
const back = () => history.back() const back = () => history.back()
let address = $state($userProfile?.lud16 || "") let address = $state($userProfile?.lud16 || "")
let isLoading = $state(false) let loading = $state(false)
const walletLud16 = $derived($session?.wallet ? getWalletAddress($session.wallet) : undefined) const walletLud16 = $derived($session?.wallet ? getWalletAddress($session.wallet) : undefined)
@@ -28,20 +29,28 @@
} }
const save = async () => { const save = async () => {
isLoading = true loading = true
try { try {
await updateProfile({ const error = await waitForThunkError(
profile: { updateProfile({
...$userProfile, profile: {
lud06: undefined, ...$userProfile,
lud16: address.trim() || undefined, lud06: undefined,
}, lud16: address.trim() || undefined,
}) },
back() }),
)
if (error) {
pushToast({theme: "error", message: `Failed to update profile: ${errorMessage(error)}`})
} else {
back()
}
} catch (error) { } catch (error) {
pushToast({theme: "error", message: "Failed to update profile"}) pushToast({theme: "error", message: "Failed to update profile"})
} finally { } finally {
isLoading = false loading = false
} }
} }
</script> </script>
@@ -61,7 +70,7 @@
placeholder="user@domain.com" placeholder="user@domain.com"
bind:value={address} bind:value={address}
class="input input-bordered flex w-full" class="input input-bordered flex w-full"
disabled={isLoading} /> disabled={loading} />
<p class="text-xs opacity-75"> <p class="text-xs opacity-75">
You can enter one manually or use your connected wallet's address (if available). Leave You can enter one manually or use your connected wallet's address (if available). Leave
empty to remove your lightning address empty to remove your lightning address
@@ -78,7 +87,7 @@
</div> </div>
<p class="text-xs opacity-75">{walletLud16}</p> <p class="text-xs opacity-75">{walletLud16}</p>
</div> </div>
<Button class="btn btn-outline btn-sm" onclick={useWalletAddress} disabled={isLoading}> <Button class="btn btn-outline btn-sm" onclick={useWalletAddress} disabled={loading}>
Use This Use This
</Button> </Button>
</div> </div>
@@ -87,9 +96,9 @@
</div> </div>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-neutral" onclick={back} disabled={isLoading}>Cancel</Button> <Button class="btn btn-neutral" onclick={back} disabled={loading}>Cancel</Button>
<Button class="btn btn-primary" onclick={save} disabled={isLoading}> <Button class="btn btn-primary" onclick={save} disabled={loading}>
{#if isLoading} {#if loading}
<span class="loading loading-spinner loading-sm"></span> <span class="loading loading-spinner loading-sm"></span>
{:else} {:else}
<Icon icon={CheckCircle} /> <Icon icon={CheckCircle} />
+2 -2
View File
@@ -676,7 +676,7 @@ export const initProfile = (profile: Profile) => {
return publishThunk({event, relays: []}) return publishThunk({event, relays: []})
} }
export const updateProfile = async ({ export const updateProfile = ({
profile, profile,
shouldBroadcast = !getTag(PROTECTED, profile.event?.tags || []), shouldBroadcast = !getTag(PROTECTED, profile.event?.tags || []),
}: { }: {
@@ -697,5 +697,5 @@ export const updateProfile = async ({
const event = makeEvent(template.kind, template) const event = makeEvent(template.kind, template)
const relays = router.merge(scenarios).getUrls() const relays = router.merge(scenarios).getUrls()
await publishThunk({event, relays}).complete return publishThunk({event, relays})
} }
+14
View File
@@ -0,0 +1,14 @@
import {kv, db} from "@app/core/storage"
import {Push} from "@app/util/notifications"
import {deactivateCurrentPomadeSession} from "@app/util/pomade"
export const logout = async () => {
await deactivateCurrentPomadeSession()
await Push.disable()
await kv.clear()
await db.clear()
localStorage.clear()
window.location.href = "/"
}
+1 -1
View File
@@ -302,7 +302,7 @@ class CapacitorNotifications implements IPushAdapter {
async request(prompt = true) { async request(prompt = true) {
let status = await PushNotifications.checkPermissions() let status = await PushNotifications.checkPermissions()
if (prompt && status.receive === "prompt") { if (prompt && ["prompt", "prompt-with-rationale"].includes(status.receive)) {
status = await PushNotifications.requestPermissions() status = await PushNotifications.requestPermissions()
} }
+78
View File
@@ -0,0 +1,78 @@
import {get} from "svelte/store"
import {Client, type SessionItem, type ClientOptions} from "@pomade/core"
import {ifLet, reject, spec} from "@welshman/lib"
import {session, isPomadeSession, loginWithPomade as _loginWithPomade} from "@welshman/app"
export const getPomadeClient = async () => {
const $session = get(session)
if (isPomadeSession($session)) {
return new Client($session.clientOptions)
}
}
export type PomadeSessionWithPeers = SessionItem & {peers: string[]}
export const loadPomadeSessions = async () => {
const sessionMap = new Map<string, PomadeSessionWithPeers>()
const client = await getPomadeClient()
if (client) {
const result = await client.listSessions()
for (const message of result.messages) {
if (!message.res?.items) continue
for (const item of message.res.items) {
const existing = sessionMap.get(item.client)
if (existing) {
existing.peers.push(message.url)
} else {
sessionMap.set(item.client, {...item, peers: [message.url]})
}
}
}
}
return Array.from(sessionMap.values())
}
export const loadOtherPomadeSessions = async () => {
const client = await getPomadeClient()
if (!client) {
return []
}
return reject(spec({client: await client.getPubkey()}), await loadPomadeSessions())
}
export const deletePomadeSession = async (clientPubkey: string, peers: string[]) =>
ifLet(await getPomadeClient(), client => client.deleteSession(clientPubkey, peers))
export const deactivatePomadeSession = async (clientPubkey: string, peers: string[]) =>
ifLet(await getPomadeClient(), client => client.deactivateSession(clientPubkey, peers))
export const deleteCurrentPomadeSession = async () =>
ifLet(await getPomadeClient(), async client =>
client.deleteSession(await client.getPubkey(), client.peers),
)
export const deactivateCurrentPomadeSession = async () =>
ifLet(await getPomadeClient(), async client =>
client.deactivateSession(await client.getPubkey(), client.peers),
)
export const deleteDeactivatedPomadeSessions = async () => {
const sessions = await loadOtherPomadeSessions()
for (const item of sessions || []) {
if (item.deactivated_at) {
await deletePomadeSession(item.client, item.peers)
}
}
}
export const loginWithPomade = (clientOptions: ClientOptions, email: string) =>
_loginWithPomade(clientOptions.group.group_pk.slice(2), email, clientOptions)
@@ -0,0 +1,77 @@
<script lang="ts">
import {writable} from "svelte/store"
import type {Writable} from "svelte/store"
import {remove, uniq} from "@welshman/lib"
import CloseCircle from "@assets/icons/close-circle.svg?dataurl"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
interface Props {
value: string[]
term?: Writable<string>
placeholder?: string
}
let {value = $bindable(), term = writable(""), placeholder = ""}: Props = $props()
const normalizeItem = (text: string) => text.trim()
const addItems = (text: string) => {
const items = text.split(/[\n,]/).map(normalizeItem).filter(Boolean)
if (items.length > 0) {
value = uniq([...value, ...items])
}
term.set("")
}
const removeItem = (item: string) => {
value = remove(item, value)
}
const onKeyDown = (e: KeyboardEvent) => {
if (e.key === "Enter" && $term) {
e.preventDefault()
addItems($term)
}
}
const onPaste = (e: ClipboardEvent) => {
const text = e.clipboardData?.getData("text")
if (text) {
e.preventDefault()
addItems(text)
}
}
const onBlur = () => {
if ($term.trim()) {
addItems($term)
}
}
</script>
<div class="flex flex-col gap-2">
<div>
{#each value as item (item)}
<div class="flex-inline badge badge-neutral mr-1 gap-1">
<Button class="flex items-center" onclick={() => removeItem(item)}>
<Icon icon={CloseCircle} size={4} class="-ml-1 mt-px" />
</Button>
<span>{item}</span>
</div>
{/each}
</div>
<label class="input input-bordered flex w-full items-center gap-2">
<input
bind:value={$term}
class="grow"
type="text"
{placeholder}
onkeydown={onKeyDown}
onpaste={onPaste}
onblur={onBlur} />
</label>
</div>
+39 -15
View File
@@ -1,12 +1,14 @@
<script lang="ts"> <script lang="ts">
import * as nip19 from "nostr-tools/nip19" import * as nip19 from "nostr-tools/nip19"
import {Client} from "@pomade/core"
import {hexToBytes} from "@welshman/lib" import {hexToBytes} from "@welshman/lib"
import {displayPubkey, displayProfile} from "@welshman/util" import {displayPubkey, displayProfile} from "@welshman/util"
import {pubkey, session, displayNip05, deriveProfile} from "@welshman/app" import {pubkey, session, SessionMethod, displayNip05, deriveProfile} from "@welshman/app"
import {slideAndFade} from "@lib/transition" import {slideAndFade} from "@lib/transition"
import PenNewSquare from "@assets/icons/pen-new-square.svg?dataurl" import PenNewSquare from "@assets/icons/pen-new-square.svg?dataurl"
import UserRounded from "@assets/icons/user-rounded.svg?dataurl" import UserRounded from "@assets/icons/user-rounded.svg?dataurl"
import Key from "@assets/icons/key-minimalistic.svg?dataurl" import Key from "@assets/icons/key-minimalistic.svg?dataurl"
import Letter from "@assets/icons/letter.svg?dataurl"
import LinkRound from "@assets/icons/link-round.svg?dataurl" import LinkRound from "@assets/icons/link-round.svg?dataurl"
import Copy from "@assets/icons/copy.svg?dataurl" import Copy from "@assets/icons/copy.svg?dataurl"
import Settings from "@assets/icons/settings.svg?dataurl" import Settings from "@assets/icons/settings.svg?dataurl"
@@ -16,15 +18,16 @@
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import FieldInline from "@lib/components/FieldInline.svelte" import FieldInline from "@lib/components/FieldInline.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import ProfileCircle from "@app/components/ProfileCircle.svelte" import ProfileCircle from "@app/components/ProfileCircle.svelte"
import ContentMinimal from "@app/components/ContentMinimal.svelte" import ContentMinimal from "@app/components/ContentMinimal.svelte"
import ProfileEdit from "@app/components/ProfileEdit.svelte" import ProfileEdit from "@app/components/ProfileEdit.svelte"
import ProfileDelete from "@app/components/ProfileDelete.svelte" import ProfileDelete from "@app/components/ProfileDelete.svelte"
import SignerStatus from "@app/components/SignerStatus.svelte" import SignerStatus from "@app/components/SignerStatus.svelte"
import PasswordReset from "@app/components/PasswordReset.svelte"
import InfoKeys from "@app/components/InfoKeys.svelte" import InfoKeys from "@app/components/InfoKeys.svelte"
import {PLATFORM_NAME} from "@app/core/state"
import {pushModal} from "@app/util/modal" import {pushModal} from "@app/util/modal"
import {clip} from "@app/util/toast" import {clip, pushToast} from "@app/util/toast"
const npub = nip19.npubEncode($pubkey!) const npub = nip19.npubEncode($pubkey!)
const profile = deriveProfile($pubkey!) const profile = deriveProfile($pubkey!)
@@ -38,9 +41,29 @@
const startDelete = () => pushModal(ProfileDelete) const startDelete = () => pushModal(ProfileDelete)
const startPasswordReset = async () => {
loading = true
try {
const {ok, peersByPrefix} = await Client.requestChallenge($session!.email)
if (!ok) {
pushToast({
theme: "error",
message: "Failed to initiate password reset!",
})
}
pushModal(PasswordReset, {peersByPrefix})
} finally {
loading = false
}
}
const startRecovery = () => pushModal(InfoKeys) const startRecovery = () => pushModal(InfoKeys)
let showAdvanced = false let loading = $state(false)
let showAdvanced = $state(false)
</script> </script>
<div class="content column gap-4"> <div class="content column gap-4">
@@ -69,10 +92,11 @@
<ContentMinimal event={{content: $profile?.about || "", tags: []}} /> <ContentMinimal event={{content: $profile?.about || "", tags: []}} />
{/key} {/key}
</div> </div>
{#if $session?.email} <div class="card2 bg-alt col-4 shadow-md">
<div class="card2 bg-alt col-4 shadow-md"> {#if $session?.method === SessionMethod.Pomade}
<FieldInline> <FieldInline>
{#snippet label()} {#snippet label()}
<Icon icon={Letter} />
<p>Email Address</p> <p>Email Address</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
@@ -81,16 +105,8 @@
<input readonly value={$session.email} class="grow" /> <input readonly value={$session.email} class="grow" />
</label> </label>
{/snippet} {/snippet}
{#snippet info()}
<p>
Your email and password can only be used to log into {PLATFORM_NAME}.
<Button class="link" onclick={startRecovery}>Start holding your own keys</Button>
</p>
{/snippet}
</FieldInline> </FieldInline>
</div> {/if}
{/if}
<div class="card2 bg-alt col-4 shadow-md">
<FieldInline> <FieldInline>
{#snippet label()} {#snippet label()}
<p class="flex items-center gap-3"> <p class="flex items-center gap-3">
@@ -139,6 +155,14 @@
</FieldInline> </FieldInline>
{/if} {/if}
<SignerStatus /> <SignerStatus />
{#if $session?.method === SessionMethod.Pomade}
<div class="flex gap-2 justify-end">
<Button class="btn" onclick={startPasswordReset}>
<Spinner {loading}>Update your password</Spinner>
</Button>
<Button class="btn btn-primary" onclick={startRecovery}>Start holding your own keys</Button>
</div>
{/if}
</div> </div>
<div class="card2 bg-alt shadow-md"> <div class="card2 bg-alt shadow-md">
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
+1 -1
View File
@@ -337,7 +337,7 @@
} }
const onEditPrevious = () => { const onEditPrevious = () => {
const prev = $events.find(e => e.pubkey === $pubkey) const prev = $events.toReversed().find(e => e.pubkey === $pubkey)
if (prev && canEditEvent(prev)) { if (prev && canEditEvent(prev)) {
onEditEvent(prev) onEditEvent(prev)
+1 -1
View File
@@ -273,7 +273,7 @@
} }
const onEditPrevious = () => { const onEditPrevious = () => {
const prev = $events.find(e => e.pubkey === $pubkey) const prev = $events.toReversed().find(e => e.pubkey === $pubkey)
if (prev && canEditEvent(prev)) { if (prev && canEditEvent(prev)) {
onEditEvent(prev) onEditEvent(prev)
+1 -1
View File
@@ -2,7 +2,7 @@ import {config} from "dotenv"
import daisyui from "daisyui" import daisyui from "daisyui"
import themes from "daisyui/src/theming/themes" import themes from "daisyui/src/theming/themes"
config({path: ".env"}) config({path: ".env.local"})
config({path: ".env.template"}) config({path: ".env.template"})
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
+1 -1
View File
@@ -4,7 +4,7 @@ import {SvelteKitPWA} from "@vite-pwa/sveltekit"
import {sveltekit} from "@sveltejs/kit/vite" import {sveltekit} from "@sveltejs/kit/vite"
import svg from "@poppanator/sveltekit-svg" import svg from "@poppanator/sveltekit-svg"
config({path: ".env"}) config({path: ".env.local"})
config({path: ".env.template"}) config({path: ".env.template"})
export default defineConfig({ export default defineConfig({