Compare commits

..

3 Commits

Author SHA1 Message Date
mplorentz e885fe073f Source .env explicitly during build 2026-02-27 13:35:11 -05:00
mplorentz 3dde0253e6 Fix issue where docker build would rebuild when app did not change 2026-02-27 12:44:34 -05:00
mplorentz eca8981542 Fix pnpm-lock 2026-02-27 12:44:12 -05:00
41 changed files with 388 additions and 1192 deletions
-1
View File
@@ -1,6 +1,5 @@
# Env # Env
.env .env
.env.local
# Vite # Vite
vite.config.js.timestamp-* vite.config.js.timestamp-*
-26
View File
@@ -1,31 +1,5 @@
# 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
+1 -1
View File
@@ -2,7 +2,7 @@
# Uses .env from build context for config (logo, branding, etc.) # Uses .env from build context for config (logo, branding, etc.)
# Optional: docker build --build-arg VITE_BUILD_HASH=$(git rev-parse --short HEAD) -t flotilla . # Optional: docker build --build-arg VITE_BUILD_HASH=$(git rev-parse --short HEAD) -t flotilla .
FROM node:20-bookworm AS builder FROM node:20-slim AS builder
RUN npm install -g pnpm@latest RUN npm install -g pnpm@latest
+1 -1
View File
@@ -11,7 +11,7 @@ You can also optionally create an `.env` file and populate it with the following
- `VITE_DEFAULT_PUBKEYS` - A comma-separated list of hex pubkeys for bootstrapping web of trust - `VITE_DEFAULT_PUBKEYS` - A comma-separated list of hex pubkeys for bootstrapping web of trust
- `VITE_PLATFORM_URL` - The url where the app will be hosted - `VITE_PLATFORM_URL` - The url where the app will be hosted
- `VITE_PLATFORM_NAME` - The name of the app - `VITE_PLATFORM_NAME` - The name of the app
- `VITE_PLATFORM_LOGO` - A logo url for the app. Can be a local path or https link. Must be a PNG file. - `VITE_PLATFORM_LOGO` - A logo url for the app
- `VITE_PLATFORM_RELAYS` - A list of comma-separated relay urls that will make flotilla operate in "platform mode". Disables all space browse/add/select functionality and makes the first platform relay the home page. - `VITE_PLATFORM_RELAYS` - A list of comma-separated relay urls that will make flotilla operate in "platform mode". Disables all space browse/add/select functionality and makes the first platform relay the home page.
- `VITE_PLATFORM_ACCENT` - A hex color for the app's accent color - `VITE_PLATFORM_ACCENT` - A hex color for the app's accent color
- `VITE_PLATFORM_DESCRIPTION` - A description of the app - `VITE_PLATFORM_DESCRIPTION` - A description of the app
+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 41 versionCode 40
versionName "1.6.5" versionName "1.6.4"
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.
+5 -6
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.local ]; then if [ -f .env ]; then
source .env.local source .env
fi fi
# Avoid overwriting env vars provided directly # Avoid overwriting env vars provided directly
@@ -17,13 +17,12 @@ if [[ -z $VITE_BUILD_HASH ]]; then
export VITE_BUILD_HASH=$(git rev-parse --short HEAD) export VITE_BUILD_HASH=$(git rev-parse --short HEAD)
fi fi
if [[ $VITE_PLATFORM_LOGO =~ ^https:// ]]; then if [[ $VITE_PLATFORM_LOGO =~ ^https://* ]]; then
curl -fSL "$VITE_PLATFORM_LOGO" -o static/logo.png curl $VITE_PLATFORM_LOGO > static/logo.png
export VITE_PLATFORM_LOGO=static/logo.png export VITE_PLATFORM_LOGO=static/logo.png
fi fi
# Ensure generator uses local path (dotenv may have loaded URL from .env) npx pwa-assets-generator
VITE_PLATFORM_LOGO="${VITE_PLATFORM_LOGO}" npx pwa-assets-generator
npx vite build npx vite build
# Replace index.html variables with stuff from our env # Replace index.html variables with stuff from our env
+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 = 32; CURRENT_PROJECT_VERSION = 31;
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.5; MARKETING_VERSION = 1.6.4;
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 = 32; CURRENT_PROJECT_VERSION = 31;
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.5; MARKETING_VERSION = 1.6.4;
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.5", "version": "1.6.4",
"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": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", "check:watch": "./check.sh",
"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.2.1", "@pomade/core": "^0.1.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.8", "@welshman/app": "^0.8.7",
"@welshman/content": "^0.8.8", "@welshman/content": "^0.8.7",
"@welshman/editor": "^0.8.8", "@welshman/editor": "^0.8.7",
"@welshman/feeds": "^0.8.8", "@welshman/feeds": "^0.8.7",
"@welshman/lib": "^0.8.8", "@welshman/lib": "^0.8.7",
"@welshman/net": "^0.8.8", "@welshman/net": "^0.8.7",
"@welshman/router": "^0.8.8", "@welshman/router": "^0.8.7",
"@welshman/signer": "^0.8.8", "@welshman/signer": "^0.8.7",
"@welshman/store": "^0.8.8", "@welshman/store": "^0.8.7",
"@welshman/util": "^0.8.8", "@welshman/util": "^0.8.7",
"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",
+138 -364
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.2.1 specifier: ^0.1.1
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)) 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))
'@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.8 specifier: ^0.8.7
version: 0.8.8(b90dd618d8ad3ba87405490e903259ce) version: 0.8.7(42dd4e512c88dafddb6d336c46cac054)
'@welshman/content': '@welshman/content':
specifier: ^0.8.8 specifier: ^0.8.7
version: 0.8.8(nostr-tools@2.20.0(typescript@5.9.3)) version: 0.8.7(nostr-tools@2.20.0(typescript@5.9.3))
'@welshman/editor': '@welshman/editor':
specifier: ^0.8.8 specifier: ^0.8.7
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)) 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)))
'@welshman/feeds': '@welshman/feeds':
specifier: ^0.8.8 specifier: ^0.8.7
version: 0.8.8(827c582d718d0d373e9315813bab1085) version: 0.8.7(168ce8cc007592daec2fe2c423b6ba13)
'@welshman/lib': '@welshman/lib':
specifier: ^0.8.8 specifier: ^0.8.7
version: 0.8.8 version: 0.8.7
'@welshman/net': '@welshman/net':
specifier: ^0.8.8 specifier: ^0.8.7
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) 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)
'@welshman/router': '@welshman/router':
specifier: ^0.8.8 specifier: ^0.8.7
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))) 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)))
'@welshman/signer': '@welshman/signer':
specifier: ^0.8.8 specifier: ^0.8.7
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)) 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))
'@welshman/store': '@welshman/store':
specifier: ^0.8.8 specifier: ^0.8.7
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) 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)
'@welshman/util': '@welshman/util':
specifier: ^0.8.8 specifier: ^0.8.7
version: 0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(nostr-tools@2.20.0(typescript@5.9.3)) version: 0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(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,36 +811,6 @@ 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==}
@@ -1339,46 +1309,12 @@ 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.2.1': '@pomade/core@0.1.1':
resolution: {integrity: sha512-zXpPQPkhVe7OchmRDe2MbHdUxiCSeUuMwrHOyeOBs/xD1EfY093Mwj6Cu/OLfz0wxivBDSp1GMMmxqKbLWam3Q==} resolution: {integrity: sha512-v/lg9nQvL1ReOx1xLmjS70mAO5hW2ZcR9OXl9GdB0rxyg0gBIh45seqzJTDI8ye+MAk7AZRvhn8H6lPE6oohNQ==}
version: 0.2.1 version: 0.1.1
engines: {node: '>=12.0.0'} engines: {node: '>=12.0.0'}
peerDependencies: peerDependencies:
'@frostr/bifrost': ^1.0.7 '@frostr/bifrost': ^1.0.7
@@ -1967,83 +1903,82 @@ packages:
'@vite-pwa/assets-generator': '@vite-pwa/assets-generator':
optional: true optional: true
'@welshman/app@0.8.8': '@welshman/app@0.8.7':
resolution: {integrity: sha512-pyySouAJwGZ2RSC29egiFft38Ctuioodon6xWFxB7HvJ9Llsh5b53qjkrQcAYM7lUAzXwtalf2v4Z3EwYdUObg==} resolution: {integrity: sha512-P+cCy2o1r/ke5SngNmoK8WoeLmEZ6l2I83mz0QaRHremkb+Q/RN72UBQy+x2lUrUtRzWJ8tNAwXwsqBw0JGxaQ==}
peerDependencies: peerDependencies:
'@pomade/core': ^0.1.3 '@pomade/core': ^0.1.1
'@welshman/feeds': 0.8.8 '@welshman/feeds': 0.8.7
'@welshman/lib': 0.8.8 '@welshman/lib': 0.8.7
'@welshman/net': 0.8.8 '@welshman/net': 0.8.7
'@welshman/router': 0.8.8 '@welshman/router': 0.8.7
'@welshman/signer': 0.8.8 '@welshman/signer': 0.8.7
'@welshman/store': 0.8.8 '@welshman/store': 0.8.7
'@welshman/util': 0.8.8 '@welshman/util': 0.8.7
svelte: ^4.0.0 || ^5.0.0 svelte: ^4.0.0 || ^5.0.0
'@welshman/content@0.8.8': '@welshman/content@0.8.7':
resolution: {integrity: sha512-5jh2YMoqINzkOEVSDZec6JbAqiC0WThwRuPwJOwiJlAFYQ4LC0MAT1HQ8z9pht/0TXdjYQUu2X+jngqqICNOiw==} resolution: {integrity: sha512-EPeiB+hocVuMjlbWrIBdw7wmcs3jsBjI9o7jld2gsADVLmouYctahFNTSxjkeARnyK+j09ece95hC2MlJNPrbA==}
peerDependencies: peerDependencies:
nostr-tools: ^2.19.4 nostr-tools: ^2.19.4
'@welshman/editor@0.8.8': '@welshman/editor@0.8.7':
resolution: {integrity: sha512-54WD2d6HEEiuoPgl/LeE4eaLtF2/SrYObk+IE9UUrJjoXcK/BK3vt8ltzazvBLR8ntfKOQINc4DhkeuBxiiCpA==} resolution: {integrity: sha512-UZmHmP5zG9Ad1sp6h4uAQYwJ/o1mkfyCbt7tYV5+z7+7YZ2x2gsS59yqDrgr0NV1z9GFZ/axgFatl0L/c5ihKA==}
peerDependencies: peerDependencies:
'@welshman/lib': 0.8.8 '@welshman/lib': 0.8.7
'@welshman/util': 0.8.8 '@welshman/util': 0.8.7
nostr-editor: ^1.1.1
nostr-tools: ^2.19.4 nostr-tools: ^2.19.4
'@welshman/feeds@0.8.8': '@welshman/feeds@0.8.7':
resolution: {integrity: sha512-o5JuptpWSNr6wtbM0RfSxTJgZStaNxPz160tE9u0SZzs1/a9sq/Yzesw7s+g0nKukRjBbl70DOqpTqOqfXAEIw==} resolution: {integrity: sha512-mM9mGRje2lXQ2KGTz31gSR0MBWJVIgD8efaf2HCb/dopLzlJ0brSpGUAuGAb+yAfWwZ/wXTzwmYOLdSZT5AyvQ==}
peerDependencies: peerDependencies:
'@welshman/lib': 0.8.8 '@welshman/lib': 0.8.7
'@welshman/net': 0.8.8 '@welshman/net': 0.8.7
'@welshman/router': 0.8.8 '@welshman/router': 0.8.7
'@welshman/signer': 0.8.8 '@welshman/signer': 0.8.7
'@welshman/util': 0.8.8 '@welshman/util': 0.8.7
'@welshman/lib@0.8.8': '@welshman/lib@0.8.7':
resolution: {integrity: sha512-77ZfVtodV05276ceR8c+JdDFqhOpmy2W6PkgDYbnKstQzKb5TN6wBvcLKxJppTzWMeWbyi2JADsuOYvW1jpOSQ==} resolution: {integrity: sha512-/82PNmg7mhf6r1gtY0YaB8xFRCioRRZkZUDPb0UuAZuhBCom6tKhlffzz+ty2n2tHYFTyScMp90WMVtkU/HaDQ==}
engines: {node: '>=12.0.0'} engines: {node: '>=12.0.0'}
'@welshman/net@0.8.8': '@welshman/net@0.8.7':
resolution: {integrity: sha512-Rug3GzVzyABG21g++cCLOVXdjAieV6rJUZqstE8i/olZvOEWZpZ9R901DoUSDR07U2HTrAwHQrjgb1HmH4jiDQ==} resolution: {integrity: sha512-FcVYX1imsYWca32zyU/HhXKly+A4IJzoElmMqe4x501bvpb0QQm8S2nfdCPxtb1lsi2rR1Y5if9jGHwgQGnEtQ==}
peerDependencies: peerDependencies:
'@welshman/lib': 0.8.8 '@welshman/lib': 0.8.7
'@welshman/util': 0.8.8 '@welshman/util': 0.8.7
'@welshman/router@0.8.8': '@welshman/router@0.8.7':
resolution: {integrity: sha512-j5O7F7KGQtOIvBJctEiUNcLfHBUnhHlYHxUx7ImPPurc1zLzt3JovvJJFubXMQoQ26D01DsK/AA1L5WZNebUhA==} resolution: {integrity: sha512-p0jfyqBHnNK9j2ZI3PYHfirdUe5/ll1/jttcj0p4xi822aYoGYv5giriDVt+wnzchki1XRXBGN5lRXfpBi8bbA==}
peerDependencies: peerDependencies:
'@welshman/lib': 0.8.8 '@welshman/lib': 0.8.7
'@welshman/net': 0.8.8 '@welshman/net': 0.8.7
'@welshman/util': 0.8.8 '@welshman/util': 0.8.7
'@welshman/signer@0.8.8': '@welshman/signer@0.8.7':
resolution: {integrity: sha512-rswHrTdc1+yvAno2h3JELzjp+LCfiYfUr8ACvwSSHAqDwrtezppfh0WDEPaYBp2EVSJ6tKMM1sVey0quO63aMw==} resolution: {integrity: sha512-RbFuRyJ0KL3Yg3EU8M9v5OADJO+XY/+sNd0CSmbWSwSry1NLlqa8lq/T+2b40x8KtnYMmQyB7Dp9yDQndO0ugA==}
version: 0.8.8 version: 0.8.7
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.8 '@welshman/lib': 0.8.7
'@welshman/net': 0.8.8 '@welshman/net': 0.8.7
'@welshman/util': 0.8.8 '@welshman/util': 0.8.7
nostr-signer-capacitor-plugin: '*' nostr-signer-capacitor-plugin: '*'
nostr-tools: ^2.19.4 nostr-tools: ^2.19.4
'@welshman/store@0.8.8': '@welshman/store@0.8.7':
resolution: {integrity: sha512-mTFueKZi9CtrtvCZT5eT5QaLMs94LxQg4y7oO5PZp9wv8EGSnB9p7XIflM0OfpKwF7c0pu1RdXcjVlvMDsC6QQ==} resolution: {integrity: sha512-ppvq7msnvzgnSlU4FsZmJgA3eSyFy9H6gYSQ91ukspbmkxCdMG2paBPCKU4tKv4fYrv/1ULgaN8gkP1BCG6riQ==}
peerDependencies: peerDependencies:
'@welshman/lib': 0.8.8 '@welshman/lib': 0.8.7
'@welshman/net': 0.8.8 '@welshman/net': 0.8.7
'@welshman/util': 0.8.8 '@welshman/util': 0.8.7
svelte: ^4.0.0 || ^5.0.0 svelte: ^4.0.0 || ^5.0.0
'@welshman/util@0.8.8': '@welshman/util@0.8.7':
resolution: {integrity: sha512-SNT1VXab6ce36EVfjs1A2uwWs5elYTI4eXi8SUuj42k8CqNIAtG+bOf/JFIxXNTfl3NSxxZdWzpLLZWBqgpAxQ==} resolution: {integrity: sha512-UjdQookLypfOxWplxcG0lBzREGgck4n4a+digoRjAe5jRlP6S6xH7uNI8Pl1Qk01D5KB8Ntz/yBdwe6JtkvqYg==}
peerDependencies: peerDependencies:
'@noble/curves': ^1.9.7 '@noble/curves': ^1.9.7
'@welshman/lib': 0.8.8 '@welshman/lib': 0.8.7
nostr-tools: ^2.19.4 nostr-tools: ^2.19.4
'@xml-tools/parser@1.0.11': '@xml-tools/parser@1.0.11':
@@ -2148,10 +2083,6 @@ 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'}
@@ -2285,13 +2216,6 @@ 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'}
@@ -3506,6 +3430,10 @@ 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
@@ -3642,10 +3570,6 @@ 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==}
@@ -4110,13 +4034,6 @@ 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'}
@@ -4181,9 +4098,6 @@ 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'}
@@ -4654,19 +4568,12 @@ 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'}
@@ -5848,24 +5755,6 @@ 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
@@ -6344,108 +6233,16 @@ 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.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))': '@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))':
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
'@peculiar/x509': 1.14.3 '@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/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))
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
@@ -7031,26 +6828,26 @@ snapshots:
optionalDependencies: optionalDependencies:
'@vite-pwa/assets-generator': 0.2.6 '@vite-pwa/assets-generator': 0.2.6
'@welshman/app@0.8.8(b90dd618d8ad3ba87405490e903259ce)': '@welshman/app@0.8.7(42dd4e512c88dafddb6d336c46cac054)':
dependencies: dependencies:
'@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)) '@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))
'@welshman/feeds': 0.8.8(827c582d718d0d373e9315813bab1085) '@welshman/feeds': 0.8.7(168ce8cc007592daec2fe2c423b6ba13)
'@welshman/lib': 0.8.8 '@welshman/lib': 0.8.7
'@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/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/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/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/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/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/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/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/util': 0.8.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(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))
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.8(nostr-tools@2.20.0(typescript@5.9.3))': '@welshman/content@0.8.7(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.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/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)))':
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))
@@ -7065,64 +6862,73 @@ 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.8 '@welshman/lib': 0.8.7
'@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/util': 0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(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.8(827c582d718d0d373e9315813bab1085)': '@welshman/feeds@0.8.7(168ce8cc007592daec2fe2c423b6ba13)':
dependencies: dependencies:
'@welshman/lib': 0.8.8 '@welshman/lib': 0.8.7
'@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/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/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/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/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/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.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(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))
trava: 1.2.1 trava: 1.2.1
'@welshman/lib@0.8.8': '@welshman/lib@0.8.7':
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.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/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)':
dependencies: dependencies:
'@welshman/lib': 0.8.8 '@welshman/lib': 0.8.7
'@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/util': 0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(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.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/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)))':
dependencies: dependencies:
'@welshman/lib': 0.8.8 '@welshman/lib': 0.8.7
'@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/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.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(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/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/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))':
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.8 '@welshman/lib': 0.8.7
'@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/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.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(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-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.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/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)':
dependencies: dependencies:
'@welshman/lib': 0.8.8 '@welshman/lib': 0.8.7
'@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/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.8(@noble/curves@1.9.7)(@welshman/lib@0.8.8)(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))
svelte: 5.48.0 svelte: 5.48.0
'@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/util@0.8.7(@noble/curves@1.9.7)(@welshman/lib@0.8.7)(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.8 '@welshman/lib': 0.8.7
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
@@ -7221,12 +7027,6 @@ 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: {}
@@ -7356,22 +7156,6 @@ 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
@@ -8665,6 +8449,15 @@ 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
@@ -8802,11 +8595,6 @@ 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
@@ -9165,7 +8953,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.1 markdown-it: 14.1.0
prosemirror-model: 1.25.4 prosemirror-model: 1.25.4
prosemirror-menu@1.2.5: prosemirror-menu@1.2.5:
@@ -9225,12 +9013,6 @@ 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:
@@ -9306,8 +9088,6 @@ 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
@@ -9927,16 +9707,10 @@ 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.local"}) dotenv.config({path: ".env"})
dotenv.config({path: ".env.template"}) dotenv.config({path: ".env.template"})
export default defineConfig({ export default defineConfig({
+19 -4
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,6 +32,18 @@
} = $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) {
@@ -70,7 +82,7 @@
const back = () => history.back() const back = () => history.back()
let loading = $state(false) let loading = $state(false)
let otps = $state<string[]>([]) let input = $state("")
</script> </script>
<Modal tag="form" onsubmit={preventDefault(submit)}> <Modal tag="form" onsubmit={preventDefault(submit)}>
@@ -84,14 +96,17 @@
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>
<StringMultiInput bind:value={otps} placeholder="Enter your recovery codes..." /> <textarea
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 || otps.length < 2}> <Button type="submit" class="btn btn-primary" disabled={loading}>
<Spinner {loading}>Confirm recovery</Spinner> <Spinner {loading}>Confirm recovery</Spinner>
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
+1
View File
@@ -34,6 +34,7 @@
const onSuccess = async (session: Session) => { const onSuccess = async (session: Session) => {
addSession(session) addSession(session)
pushToast({message: "Successfully logged in!"})
setChecked("*") setChecked("*")
clearModals() clearModals()
} }
+15 -21
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,8 +17,6 @@
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"
@@ -39,7 +37,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 || options.length === 0) { if (!ok) {
console.error(messages) console.error(messages)
return pushToast({ return pushToast({
@@ -48,25 +46,21 @@
}) })
} }
if (uniq(options.map(o => o.pubkey)).length > 1) { const [client, peers] = options[0]!
pushModal(LogInSelect, {email, options, clientSecret}) const {clientOptions, ...res} = await Client.selectLogin(clientSecret, client, peers)
if (res.ok && clientOptions) {
loginWithPomade(clientOptions.group.group_pk.slice(2), email, clientOptions)
pushToast({message: "Successfully logged in!"})
setChecked("*")
clearModals()
} else { } else {
const {client, peers} = options[0] console.error(res.messages)
const {clientOptions, ...res} = await Client.selectLogin(clientSecret, client, peers)
if (res.ok && clientOptions) { pushToast({
loginWithPomade(clientOptions, email) theme: "error",
deleteDeactivatedPomadeSessions() message: "Sorry, we were unable to log you in.",
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,6 +57,7 @@
} }
loginWithNip01(secret) loginWithNip01(secret)
pushToast({message: "Successfully logged in!"})
setChecked("*") setChecked("*")
clearModals() clearModals()
} catch (e) { } catch (e) {
+36 -27
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,12 +13,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 {clearModals} from "@app/util/modal"
import LogInSelect from "@app/components/LogInSelect.svelte"
import {pushToast} from "@app/util/toast"
import {setChecked} from "@app/util/notifications" import {setChecked} from "@app/util/notifications"
import {pushModal, clearModals} from "@app/util/modal" import {pushToast} from "@app/util/toast"
import {deleteDeactivatedPomadeSessions, loginWithPomade} from "@app/util/pomade" import {POMADE_SIGNERS} from "@app/core/state"
type Props = { type Props = {
email: string email: string
@@ -30,6 +28,18 @@
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 {
@@ -39,7 +49,7 @@
otps, otps,
) )
if (!ok || options.length === 0) { if (!ok) {
console.error(messages) console.error(messages)
return pushToast({ return pushToast({
@@ -48,32 +58,28 @@
}) })
} }
if (uniq(options.map(o => o.pubkey)).length > 1) { const [client, peers] = options[0]!
pushModal(LogInSelect, {email, options, clientSecret}) const {clientOptions, ...res} = await Client.selectLogin(clientSecret, client, peers)
if (res.ok && clientOptions) {
loginWithPomade(clientOptions.group.group_pk.slice(2), email, clientOptions)
pushToast({message: "Successfully logged in!"})
setChecked("*")
clearModals()
} else { } else {
const {client, peers} = options[0] console.error(res.messages)
const {clientOptions, ...res} = await Client.selectLogin(clientSecret, client, peers)
if (res.ok && clientOptions) { pushToast({
loginWithPomade(clientOptions, email) theme: "error",
deleteDeactivatedPomadeSessions() message: "Sorry, we were unable to log you in.",
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 otps = $state<string[]>([]) let input = $state("")
let loading = $state(false) let loading = $state(false)
</script> </script>
@@ -88,14 +94,17 @@
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>
<StringMultiInput bind:value={otps} placeholder="Enter your login codes..." /> <textarea
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 || otps.length < 3}> <Button type="submit" class="btn btn-primary" disabled={loading}>
<Spinner {loading}>Log In</Spinner> <Spinner {loading}>Log In</Spinner>
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
-83
View File
@@ -1,83 +0,0 @@
<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>
+9 -2
View File
@@ -9,7 +9,8 @@
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 {logout} from "@app/util/logout" import {Push} from "@app/util/notifications"
import {kv, db} from "@app/core/storage"
const back = () => history.back() const back = () => history.back()
@@ -17,7 +18,13 @@
loading = true loading = true
try { try {
await logout() await Push.disable()
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 gap-2"> <div class="grid grid-cols-3 sm:grid-cols-5 lg:grid-cols-9">
{#each images as image, i (i + image)} {#each images as image (image)}
<ContentLinkBlock event={props.event} value={{url: image}} /> <ContentLinkBlock event={props.event} value={{url: image}} />
{/each} {/each}
</div> </div>
-106
View File
@@ -1,106 +0,0 @@
<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>
@@ -1,118 +0,0 @@
<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>
+60 -57
View File
@@ -1,31 +1,52 @@
<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 {loadOtherPomadeSessions} from "@app/util/pomade" import {onMount} from "svelte"
import type {PomadeSessionWithPeers} from "@app/util/pomade"
const toggleMenu = (client: string) => { type SessionWithPeers = SessionItem & {peers: string[]}
menuClient = menuClient === client ? "" : client
}
const closeMenu = () => { let sessions = $state<SessionWithPeers[]>([])
menuClient = "" let deletingSession = $state<string | null>(null)
}
let menuClient = $state("") const loadSessions = async () => {
let sessions = $state<PomadeSessionWithPeers[]>([])
const deleteSession = async (sessionItem: PomadeSessionWithPeers) => {
if (!isPomadeSession($session)) return 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) => {
if (!isPomadeSession($session)) return
deletingSession = sessionItem.client
try { try {
const client = new Client($session.clientOptions) const client = new Client($session.clientOptions)
const result = await client.deleteSession(sessionItem.client, sessionItem.peers) const result = await client.deleteSession(sessionItem.client, sessionItem.peers)
@@ -49,6 +70,8 @@
theme: "error", theme: "error",
message: "Failed to delete session", message: "Failed to delete session",
}) })
} finally {
deletingSession = null
} }
} }
@@ -62,9 +85,7 @@
} }
onMount(() => { onMount(() => {
loadOtherPomadeSessions().then(_sessions => { loadSessions()
sessions = _sessions || []
})
}) })
</script> </script>
@@ -72,46 +93,28 @@
<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 flex-col gap-2"> <div class="flex justify-between text-sm">
<div class="flex justify-between items-center"> <div class="flex flex-col gap-1">
<div class="flex gap-3 items-center text-sm"> <span>{sessionItem.client.slice(0, 8)}</span>
<span>Session {sessionItem.client.slice(0, 8)}</span> <div class="flex gap-1">
<span class="opacity-75"> <div class="badge badge-neutral">
{#if sessionItem.deactivated_at} Created {formatDate(sessionItem.created_at)}
Deactivated </div>
{/if} <div class="badge badge-neutral">
</span> Last active: {formatDate(sessionItem.last_activity)}
</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>
+9 -2
View File
@@ -23,8 +23,9 @@
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 {logout} from "@app/util/logout" import {Push} from "@app/util/notifications"
let progress: number | undefined = $state(undefined) let progress: number | undefined = $state(undefined)
let confirmText = $state("") let confirmText = $state("")
@@ -87,7 +88,13 @@
await sleep(2000) await sleep(2000)
// Goodbye forever! // Goodbye forever!
await logout() await Push.disable()
await kv.clear()
await db.clear()
localStorage.clear()
window.location.href = "/"
} }
const confirm = async () => { const confirm = async () => {
+6 -33
View File
@@ -1,12 +1,10 @@
<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, waitForThunkError} from "@welshman/app" import {pubkey, profilesByPubkey} 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"
@@ -19,33 +17,11 @@
const back = () => history.back() const back = () => history.back()
const onsubmit = async ({ const onsubmit = ({profile, shouldBroadcast}: {profile: Profile; shouldBroadcast: boolean}) => {
profile, updateProfile({profile, shouldBroadcast})
shouldBroadcast, pushToast({message: "Your profile has been updated!"})
}: { 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}>
@@ -54,9 +30,6 @@
<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">Save Changes</Button>
<Spinner {loading} />
Save Changes
</Button>
{/snippet} {/snippet}
</ProfileEditForm> </ProfileEditForm>
+13 -6
View File
@@ -1,8 +1,15 @@
<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 {makeProfile, makeSecret, RELAYS, MESSAGING_RELAYS, makeEvent} from "@welshman/util" import {
import {loginWithNip01, publishThunk} from "@welshman/app" makeProfile,
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"
@@ -16,6 +23,8 @@
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,
@@ -24,9 +33,6 @@
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())
@@ -67,9 +73,10 @@
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(clientOptions, email) loginWithPomade(getPubkey(secret), email, clientOptions)
completeSignup() completeSignup()
}, },
}, },
+2 -9
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, popToast} from "@app/util/toast" import {pushToast} from "@app/util/toast"
import {pushModal} from "@app/util/modal" import {pushModal} from "@app/util/modal"
type Props = { type Props = {
@@ -40,11 +40,6 @@
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)
@@ -59,8 +54,7 @@
const setupRes = await client.setupRecovery(email, password) const setupRes = await client.setupRecovery(email, password)
if (!setupRes.ok) { if (!setupRes.ok) {
const message = const message = setupRes.messages[0]?.res?.message || "Please try again."
setupRes.messages.find(m => m.res && !m.res?.ok)?.res?.message || "Please try again."
return pushToast({ return pushToast({
theme: "error", theme: "error",
@@ -80,7 +74,6 @@
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 -1
View File
@@ -256,7 +256,7 @@
<SecondaryNavHeader>Your Rooms</SecondaryNavHeader> <SecondaryNavHeader>Your Rooms</SecondaryNavHeader>
{/if} {/if}
{#each $userRooms as h, i (h)} {#each $userRooms as h, i (h)}
<SpaceMenuRoomItem notify {replaceState} {url} {h} /> <SpaceMenuRoomItem {replaceState} {url} {h} />
{/each} {/each}
{#if $otherRooms.length > 0} {#if $otherRooms.length > 0}
<div class="h-2"></div> <div class="h-2"></div>
@@ -3,15 +3,11 @@
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 SpaceMenu from "@app/components/SpaceMenu.svelte" import SpaceMenu from "@app/components/SpaceMenu.svelte"
import {notifications} from "@app/util/notifications"
import {makeSpacePath} from "@app/util/routes"
import {pushDrawer} from "@app/util/modal" import {pushDrawer} from "@app/util/modal"
import {deriveSocketStatus} from "@app/core/state" import {deriveSocketStatus} from "@app/core/state"
const {url} = $props() const {url} = $props()
const path = makeSpacePath(url) + ":mobile"
const status = deriveSocketStatus(url) const status = deriveSocketStatus(url)
const openMenu = () => pushDrawer(SpaceMenu, {url}) const openMenu = () => pushDrawer(SpaceMenu, {url})
@@ -21,7 +17,5 @@
<Icon icon={MenuDots} /> <Icon icon={MenuDots} />
{#if $status.theme !== "success"} {#if $status.theme !== "success"}
<div class="absolute right-0 top-0 -mr-1 -mt-1 h-2 w-2 rounded-full bg-{$status.theme}"></div> <div class="absolute right-0 top-0 -mr-1 -mt-1 h-2 w-2 rounded-full bg-{$status.theme}"></div>
{:else if $notifications.has(path)}
<div class="absolute right-0 top-0 -mr-1 -mt-1 h-2 w-2 rounded-full bg-primary"></div>
{/if} {/if}
</Button> </Button>
+2 -7
View File
@@ -4,18 +4,16 @@
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import SecondaryNavItem from "@lib/components/SecondaryNavItem.svelte" import SecondaryNavItem from "@lib/components/SecondaryNavItem.svelte"
import RoomNameWithImage from "@app/components/RoomNameWithImage.svelte" import RoomNameWithImage from "@app/components/RoomNameWithImage.svelte"
import {notifications} from "@app/util/notifications"
import {makeRoomPath} from "@app/util/routes" import {makeRoomPath} from "@app/util/routes"
import {deriveShouldNotify} from "@app/core/state" import {deriveShouldNotify} from "@app/core/state"
interface Props { interface Props {
url: any url: any
h: any h: any
notify?: boolean
replaceState?: boolean replaceState?: boolean
} }
const {url, h, notify = false, replaceState = false}: Props = $props() const {url, h, replaceState = false}: Props = $props()
const path = makeRoomPath(url, h) const path = makeRoomPath(url, h)
const shouldNotifyForSpace = deriveShouldNotify(url) const shouldNotifyForSpace = deriveShouldNotify(url)
@@ -23,10 +21,7 @@
const showDifferenceIcon = $derived($shouldNotifyForRoom !== $shouldNotifyForSpace) const showDifferenceIcon = $derived($shouldNotifyForRoom !== $shouldNotifyForSpace)
</script> </script>
<SecondaryNavItem <SecondaryNavItem href={path} {replaceState}>
href={path}
{replaceState}
notification={notify ? $notifications.has(path) : false}>
<RoomNameWithImage {url} {h} /> <RoomNameWithImage {url} {h} />
{#if showDifferenceIcon} {#if showDifferenceIcon}
<Icon icon={$shouldNotifyForRoom ? VolumeLoud : VolumeCross} size={4} class="opacity-50" /> <Icon icon={$shouldNotifyForRoom ? VolumeLoud : VolumeCross} size={4} class="opacity-50" />
@@ -1,8 +1,5 @@
<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"
@@ -12,7 +9,8 @@
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 {pushToast} from "@app/util/toast" import {userProfile, session} from "@welshman/app"
import {makeProfile} from "@welshman/util"
const lud16 = getWalletAddress($session!.wallet!) const lud16 = getWalletAddress($session!.wallet!)
@@ -22,13 +20,9 @@
loading = true loading = true
try { try {
const error = await waitForThunkError(updateProfile({profile: {...profile, lud16}})) await updateProfile({profile: {...profile, lud16}})
if (error) { clearModals()
pushToast({theme: "error", message: `Failed to update profile: ${errorMessage(error)}`})
} else {
clearModals()
}
} finally { } finally {
loading = false loading = false
} }
@@ -1,7 +1,6 @@
<script lang="ts"> <script lang="ts">
import {getWalletAddress} from "@welshman/util" import {getWalletAddress} from "@welshman/util"
import {session, waitForThunkError, userProfile} from "@welshman/app" import {session, 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"
@@ -18,7 +17,7 @@
const back = () => history.back() const back = () => history.back()
let address = $state($userProfile?.lud16 || "") let address = $state($userProfile?.lud16 || "")
let loading = $state(false) let isLoading = $state(false)
const walletLud16 = $derived($session?.wallet ? getWalletAddress($session.wallet) : undefined) const walletLud16 = $derived($session?.wallet ? getWalletAddress($session.wallet) : undefined)
@@ -29,28 +28,20 @@
} }
const save = async () => { const save = async () => {
loading = true isLoading = true
try { try {
const error = await waitForThunkError( await updateProfile({
updateProfile({ profile: {
profile: { ...$userProfile,
...$userProfile, lud06: undefined,
lud06: undefined, lud16: address.trim() || 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 {
loading = false isLoading = false
} }
} }
</script> </script>
@@ -70,7 +61,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={loading} /> disabled={isLoading} />
<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
@@ -87,7 +78,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={loading}> <Button class="btn btn-outline btn-sm" onclick={useWalletAddress} disabled={isLoading}>
Use This Use This
</Button> </Button>
</div> </div>
@@ -96,9 +87,9 @@
</div> </div>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-neutral" onclick={back} disabled={loading}>Cancel</Button> <Button class="btn btn-neutral" onclick={back} disabled={isLoading}>Cancel</Button>
<Button class="btn btn-primary" onclick={save} disabled={loading}> <Button class="btn btn-primary" onclick={save} disabled={isLoading}>
{#if loading} {#if isLoading}
<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 = ({ export const updateProfile = async ({
profile, profile,
shouldBroadcast = !getTag(PROTECTED, profile.event?.tags || []), shouldBroadcast = !getTag(PROTECTED, profile.event?.tags || []),
}: { }: {
@@ -697,5 +697,5 @@ export const updateProfile = ({
const event = makeEvent(template.kind, template) const event = makeEvent(template.kind, template)
const relays = router.merge(scenarios).getUrls() const relays = router.merge(scenarios).getUrls()
return publishThunk({event, relays}) await publishThunk({event, relays}).complete
} }
-14
View File
@@ -1,14 +0,0 @@
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 = "/"
}
+3 -37
View File
@@ -12,14 +12,12 @@ import {
repository, repository,
publishThunk, publishThunk,
loadRelay, loadRelay,
relaysByUrl,
waitForThunkError, waitForThunkError,
userMessagingRelayList, userMessagingRelayList,
} from "@welshman/app" } from "@welshman/app"
import { import {
on, on,
call, call,
find,
assoc, assoc,
poll, poll,
prop, prop,
@@ -46,14 +44,7 @@ import {
Address, Address,
} from "@welshman/util" } from "@welshman/util"
import {buildUrl} from "@lib/util" import {buildUrl} from "@lib/util"
import { import {makeSpacePath, makeChatPath, getEventPath, goToEvent} from "@app/util/routes"
makeSpacePath,
makeRoomPath,
makeSpaceChatPath,
makeChatPath,
getEventPath,
goToEvent,
} from "@app/util/routes"
import { import {
DM_KINDS, DM_KINDS,
CONTENT_KINDS, CONTENT_KINDS,
@@ -66,11 +57,9 @@ import {
userSettingsValues, userSettingsValues,
userGroupList, userGroupList,
getSpaceUrlsFromGroupList, getSpaceUrlsFromGroupList,
getSpaceRoomsFromGroupList,
makeCommentFilter, makeCommentFilter,
userSpaceUrls, userSpaceUrls,
shouldNotify, shouldNotify,
hasNip29,
device, device,
} from "@app/core/state" } from "@app/core/state"
import {kv} from "@app/core/storage" import {kv} from "@app/core/storage"
@@ -136,7 +125,6 @@ export const allNotifications = derived(
pubkey, pubkey,
checked, checked,
chatsById, chatsById,
relaysByUrl,
userGroupList, userGroupList,
deriveEventsByIdByUrl({ deriveEventsByIdByUrl({
tracker, tracker,
@@ -147,7 +135,7 @@ export const allNotifications = derived(
identity, identity,
), ),
), ),
([$pubkey, $checked, $chatsById, $relaysByUrl, $userGroupList, eventsByIdByUrl]) => { ([$pubkey, $checked, $chatsById, $userGroupList, eventsByIdByUrl]) => {
const hasNotification = (path: string, latestEvent?: TrustedEvent) => { const hasNotification = (path: string, latestEvent?: TrustedEvent) => {
if (!latestEvent || latestEvent.pubkey === $pubkey) { if (!latestEvent || latestEvent.pubkey === $pubkey) {
return false return false
@@ -180,34 +168,12 @@ export const allNotifications = derived(
for (const url of getSpaceUrlsFromGroupList($userGroupList)) { for (const url of getSpaceUrlsFromGroupList($userGroupList)) {
const spacePath = makeSpacePath(url) const spacePath = makeSpacePath(url)
const spacePathMobile = spacePath + ":mobile"
const eventsById = eventsByIdByUrl.get(url) || new Map() const eventsById = eventsByIdByUrl.get(url) || new Map()
const latestEvent = first(sortEventsDesc(eventsById.values())) const latestEvent = first(sortEventsDesc(eventsById.values()))
if (hasNotification(spacePath, latestEvent)) { if (hasNotification(spacePath, latestEvent)) {
paths.add(spacePath) paths.add(spacePath)
} }
if (hasNip29($relaysByUrl.get(url))) {
for (const h of getSpaceRoomsFromGroupList(url, $userGroupList)) {
const roomPath = makeRoomPath(url, h)
const latestEvent = find(e => e.tags.some(spec(["h", h])), eventsById.values())
if (hasNotification(roomPath, latestEvent)) {
paths.add(spacePathMobile)
paths.add(spacePath)
paths.add(roomPath)
}
}
} else {
const messagesPath = makeSpaceChatPath(url)
if (hasNotification(messagesPath, first(eventsById.values()))) {
paths.add(spacePathMobile)
paths.add(spacePath)
paths.add(messagesPath)
}
}
} }
return paths return paths
@@ -302,7 +268,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 && ["prompt", "prompt-with-rationale"].includes(status.receive)) { if (prompt && status.receive === "prompt") {
status = await PushNotifications.requestPermissions() status = await PushNotifications.requestPermissions()
} }
-78
View File
@@ -1,78 +0,0 @@
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)
+2 -2
View File
@@ -38,7 +38,7 @@
class:text-base-content={active} class:text-base-content={active}
class:bg-base-100={active}> class:bg-base-100={active}>
{@render children?.()} {@render children?.()}
{#if notification} {#if !active && notification}
<div class="absolute right-2 top-5 h-2 w-2 rounded-full bg-primary" transition:fade></div> <div class="absolute right-2 top-5 h-2 w-2 rounded-full bg-primary" transition:fade></div>
{/if} {/if}
</a> </a>
@@ -48,7 +48,7 @@
class="{restProps.class} relative flex w-full items-center gap-3 text-left transition-all hover:bg-base-100 hover:text-base-content" class="{restProps.class} relative flex w-full items-center gap-3 text-left transition-all hover:bg-base-100 hover:text-base-content"
class:text-base-content={active} class:text-base-content={active}
class:bg-base-100={active}> class:bg-base-100={active}>
{#if notification} {#if !active && notification}
<div class="absolute right-2 top-5 h-2 w-2 rounded-full bg-primary" transition:fade></div> <div class="absolute right-2 top-5 h-2 w-2 rounded-full bg-primary" transition:fade></div>
{/if} {/if}
{@render children?.()} {@render children?.()}
@@ -1,77 +0,0 @@
<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>
+15 -39
View File
@@ -1,14 +1,12 @@
<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, SessionMethod, displayNip05, deriveProfile} from "@welshman/app" import {pubkey, session, 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"
@@ -18,16 +16,15 @@
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, pushToast} from "@app/util/toast" import {clip} from "@app/util/toast"
const npub = nip19.npubEncode($pubkey!) const npub = nip19.npubEncode($pubkey!)
const profile = deriveProfile($pubkey!) const profile = deriveProfile($pubkey!)
@@ -41,29 +38,9 @@
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 loading = $state(false) let showAdvanced = false
let showAdvanced = $state(false)
</script> </script>
<div class="content column gap-4"> <div class="content column gap-4">
@@ -92,11 +69,10 @@
<ContentMinimal event={{content: $profile?.about || "", tags: []}} /> <ContentMinimal event={{content: $profile?.about || "", tags: []}} />
{/key} {/key}
</div> </div>
<div class="card2 bg-alt col-4 shadow-md"> {#if $session?.email}
{#if $session?.method === SessionMethod.Pomade} <div class="card2 bg-alt col-4 shadow-md">
<FieldInline> <FieldInline>
{#snippet label()} {#snippet label()}
<Icon icon={Letter} />
<p>Email Address</p> <p>Email Address</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
@@ -105,8 +81,16 @@
<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>
{/if} </div>
{/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">
@@ -155,14 +139,6 @@
</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.toReversed().find(e => e.pubkey === $pubkey) const prev = $events.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.toReversed().find(e => e.pubkey === $pubkey) const prev = $events.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.local"}) config({path: ".env"})
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.local"}) config({path: ".env"})
config({path: ".env.template"}) config({path: ".env.template"})
export default defineConfig({ export default defineConfig({