Compare commits

..

11 Commits

Author SHA1 Message Date
Jon Staab df56af9b0e Bump version 2025-12-05 09:51:15 -08:00
Jon Staab 83f7f9584f Fix duplicate rooms 2025-12-04 17:06:50 -08:00
Jon Staab a2d440e54f Fix dialog z index 2025-12-04 16:01:39 -08:00
Jon Staab 4132e8449b Fix recent missing events in feeds 2025-12-04 15:56:05 -08:00
Jon Staab ee444416e4 Fall back to file name as hash for images 2025-12-04 14:37:59 -08:00
Jon Staab 10c12c3c48 Improve time based chat partitioning 2025-12-04 14:29:12 -08:00
Jon Staab db3775ae99 Fix timezone parsing in AlertAdd 2025-12-04 11:20:54 -08:00
Jon Staab 393acce884 Fix removing non-normalized urls 2025-12-02 17:27:14 -08:00
Jon Staab 68fe663730 Fix chat content bottom offset when keyboard is open 2025-12-02 17:20:10 -08:00
Jon Staab f65a4b0db0 Handle relay urls in content and link within the app 2025-12-02 17:09:56 -08:00
Jon Staab cdfb502e6e Fix skinny profile circles 2025-12-02 13:49:04 -08:00
19 changed files with 230 additions and 132 deletions
+10
View File
@@ -1,5 +1,15 @@
# Changelog
# 1.6.1
* Fix skinny profile images
* Custom handler for relay urls
* Improve time based chat partitioning
* Improve authenticated image access interop
* Fix image detail dialog
* Fix zapper loading
* Fix recent events missing in feeds
# 1.6.0
* Switch back to indexeddb to fix memory and performance
+2 -2
View File
@@ -7,8 +7,8 @@ android {
applicationId "social.flotilla"
minSdk rootProject.ext.minSdkVersion
targetSdk rootProject.ext.targetSdkVersion
versionCode 35
versionName "1.6.0"
versionCode 37
versionName "1.6.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
+4 -4
View File
@@ -358,14 +358,14 @@
CODE_SIGN_ENTITLEMENTS = "Flotilla Chat.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 26;
CURRENT_PROJECT_VERSION = 27;
DEVELOPMENT_TEAM = S26U9DYW3A;
INFOPLIST_FILE = App/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Flotilla Chat";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.6.0;
MARKETING_VERSION = 1.6.1;
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
PRODUCT_BUNDLE_IDENTIFIER = social.flotilla;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -384,14 +384,14 @@
CODE_SIGN_ENTITLEMENTS = "Flotilla Chat.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 26;
CURRENT_PROJECT_VERSION = 27;
DEVELOPMENT_TEAM = S26U9DYW3A;
INFOPLIST_FILE = App/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Flotilla Chat";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.6.0;
MARKETING_VERSION = 1.6.1;
PRODUCT_BUNDLE_IDENTIFIER = social.flotilla;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
+11 -11
View File
@@ -1,6 +1,6 @@
{
"name": "flotilla",
"version": "1.6.0",
"version": "1.6.1",
"private": true,
"scripts": {
"dev": "vite dev",
@@ -61,16 +61,16 @@
"@types/throttle-debounce": "^5.0.2",
"@vite-pwa/assets-generator": "^0.2.6",
"@vite-pwa/sveltekit": "^0.6.8",
"@welshman/app": "^0.7.0",
"@welshman/content": "^0.7.0",
"@welshman/editor": "^0.7.0",
"@welshman/feeds": "^0.7.0",
"@welshman/lib": "^0.7.0",
"@welshman/net": "^0.7.0",
"@welshman/router": "^0.7.0",
"@welshman/signer": "^0.7.0",
"@welshman/store": "^0.7.0",
"@welshman/util": "^0.7.0",
"@welshman/app": "^0.7.1",
"@welshman/content": "^0.7.1",
"@welshman/editor": "^0.7.1",
"@welshman/feeds": "^0.7.1",
"@welshman/lib": "^0.7.1",
"@welshman/net": "^0.7.1",
"@welshman/router": "^0.7.1",
"@welshman/signer": "^0.7.1",
"@welshman/store": "^0.7.1",
"@welshman/util": "^0.7.1",
"compressorjs": "^1.2.1",
"daisyui": "^4.12.24",
"date-picker-svelte": "^2.16.0",
+132 -78
View File
@@ -75,35 +75,35 @@ importers:
specifier: ^0.6.8
version: 0.6.8(@sveltejs/kit@2.46.5(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.39.12)(vite@5.4.20(@types/node@24.7.2)(terser@5.44.0)))(svelte@5.39.12)(vite@5.4.20(@types/node@24.7.2)(terser@5.44.0)))(@vite-pwa/assets-generator@0.2.6)(vite-plugin-pwa@0.21.2(@vite-pwa/assets-generator@0.2.6)(vite@5.4.20(@types/node@24.7.2)(terser@5.44.0))(workbox-build@7.3.0)(workbox-window@7.3.0))
'@welshman/app':
specifier: ^0.7.0
version: 0.7.0(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)
specifier: ^0.7.1
version: 0.7.1(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)
'@welshman/content':
specifier: ^0.7.0
version: 0.7.0(typescript@5.9.3)
specifier: ^0.7.1
version: 0.7.1(typescript@5.9.3)
'@welshman/editor':
specifier: ^0.7.0
version: 0.7.0(@tiptap/extension-image@2.27.1(@tiptap/core@2.26.3(@tiptap/pm@2.26.3)))(@tiptap/extension-link@2.27.1(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3))(linkifyjs@4.3.2)(prosemirror-markdown@1.13.2)(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.41.3)(tiptap-markdown@0.8.10(@tiptap/core@2.26.3(@tiptap/pm@2.26.3)))(typescript@5.9.3)
specifier: ^0.7.1
version: 0.7.1(@tiptap/extension-image@2.27.1(@tiptap/core@2.26.3(@tiptap/pm@2.26.3)))(@tiptap/extension-link@2.27.1(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3))(linkifyjs@4.3.2)(prosemirror-markdown@1.13.2)(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.41.3)(tiptap-markdown@0.8.10(@tiptap/core@2.26.3(@tiptap/pm@2.26.3)))(typescript@5.9.3)
'@welshman/feeds':
specifier: ^0.7.0
version: 0.7.0(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)
specifier: ^0.7.1
version: 0.7.1(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)
'@welshman/lib':
specifier: ^0.7.0
version: 0.7.0
specifier: ^0.7.1
version: 0.7.1
'@welshman/net':
specifier: ^0.7.0
version: 0.7.0(typescript@5.9.3)(ws@8.18.3)
specifier: ^0.7.1
version: 0.7.1(typescript@5.9.3)(ws@8.18.3)
'@welshman/router':
specifier: ^0.7.0
version: 0.7.0(typescript@5.9.3)(ws@8.18.3)
specifier: ^0.7.1
version: 0.7.1(typescript@5.9.3)(ws@8.18.3)
'@welshman/signer':
specifier: ^0.7.0
version: 0.7.0(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)
specifier: ^0.7.1
version: 0.7.1(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)
'@welshman/store':
specifier: ^0.7.0
version: 0.7.0(typescript@5.9.3)(ws@8.18.3)
specifier: ^0.7.1
version: 0.7.1(typescript@5.9.3)(ws@8.18.3)
'@welshman/util':
specifier: ^0.7.0
version: 0.7.0(typescript@5.9.3)
specifier: ^0.7.1
version: 0.7.1(typescript@5.9.3)
compressorjs:
specifier: ^1.2.1
version: 1.2.1
@@ -1099,6 +1099,15 @@ packages:
'@jridgewell/trace-mapping@0.3.9':
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
'@jsr/fiatjaf__promenade-trusted-dealer@0.4.1':
resolution: {integrity: sha512-K9WjpDkQGyLl5gUZBLr3Gb+b5b1r8miZmDOo4+ZlzGQgoXD2TaqT+dkBjL/yLj/pYwBcd1Bschv0xuNpguL2ZQ==, tarball: https://npm.jsr.io/~/11/@jsr/fiatjaf__promenade-trusted-dealer/0.4.1.tgz}
'@jsr/henrygd__semaphore@0.0.2':
resolution: {integrity: sha512-nrwZ8HaqU1Agb2ij8omIxaOCAsKkDHWcwS9hTRumPhZuptwh6/0BJExBd8+eClTYM7jBnZxK+cP4WJRTcHBvCA==, tarball: https://npm.jsr.io/~/11/@jsr/henrygd__semaphore/0.0.2.tgz}
'@jsr/nostr__tools@2.16.2':
resolution: {integrity: sha512-QK1XwHvAnqEwbimD+ywbLQ3T2iI+/qE/zrRgOhmtjoEGlCWgtbPTNJ6Y/MEunXr6H/MnuHV+s400i/Yk4suvGQ==, tarball: https://npm.jsr.io/~/11/@jsr/nostr__tools/2.16.2.tgz}
'@noble/ciphers@0.5.3':
resolution: {integrity: sha512-B0+6IIHiqEs3BPMT0hcRmHvEj2QHOLu+uwt+tqDDeVd0oyVzh7BPrDcPjRnV1PV/5LaknXJJQvOuRGR0zQJz+w==}
@@ -1124,6 +1133,10 @@ packages:
resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==}
engines: {node: ^14.21.3 || >=16}
'@noble/hashes@2.0.1':
resolution: {integrity: sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==}
engines: {node: '>= 20.19.0'}
'@nodelib/fs.scandir@2.1.5':
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
@@ -1699,38 +1712,38 @@ packages:
'@vite-pwa/assets-generator':
optional: true
'@welshman/app@0.7.0':
resolution: {integrity: sha512-g+LSfB+KOmz683DEBjXohLATi1FO+U24LMUCMgcElFPyxCdVShL8uBz+DZWMmMsfy0A+WlzwBNd9/L+8amdcTA==}
'@welshman/app@0.7.1':
resolution: {integrity: sha512-gHXuUVplKEtV2J7BDXxz9r6Gv9PwIfhXFEhjOraPW9/BEYS1zK0KneCe87jwZe5B/zmMk3dwMhkaUx4H3WphIA==}
'@welshman/content@0.7.0':
resolution: {integrity: sha512-eJSdsTOQ0VpjvTEG1/mK06Tl2Bdd8iOkPup92/IhHwodXdNHjmauPSt/L7PbV8SQsIASQWTyS48UNQ+eG2KJKA==}
'@welshman/content@0.7.1':
resolution: {integrity: sha512-AHSwpodzQ9zjgbKy7CRIoQg7Irni8PUNyqlvcj4RYbY19bgaGcSoozwjbDat0wY4ULBnVsX1y2DE3+rm5R0T2A==}
'@welshman/editor@0.7.0':
resolution: {integrity: sha512-iQbrFP/Q+d2E8eBcLKPgzK8sxHQzY8wa41UHjWLrZdjwj4yUFttoiKXeRcNJHJj9Wv2vBktHTF2LUCdP80dRgg==}
'@welshman/editor@0.7.1':
resolution: {integrity: sha512-fsCm+W8AQbygoN2+fm1LS6xkxdanB7v5FfhQKFsa8L1B9eYEYCAhwvrxy+nZsBEK/dt8zelk7qKQwq/CJ9sppQ==}
'@welshman/feeds@0.7.0':
resolution: {integrity: sha512-A0FjnpfONXz15QXtsDCKwUUgGK3lKlGH6Jj2uJ/X0tf5KygDr3PFS3ZYtPn0LXFAYGPjV6YI6e7hYilmoTt8QQ==}
'@welshman/feeds@0.7.1':
resolution: {integrity: sha512-i9SCE1jlVIBjM1pfPVW+5axQ0BSNBmOYeo9lKdFOjeTx1sHityb/Q3kK9lgie6IDgXhK/SshEH6bKdYSnOkVSg==}
'@welshman/lib@0.7.0':
resolution: {integrity: sha512-bjkt69D5rQPk/q6Ny7R34wksoMY8jhyAQMsm2mLgv7v68unWDjhYaUy4Q5MQcLKit0pgySSx4tUh3xFlh5TCug==}
'@welshman/lib@0.7.1':
resolution: {integrity: sha512-NQkxPwnAoUY4uSroQcfvR4YPG63j7Ke0R9YrLNXF9SQn2t2p6iAQ6A3GEOVu/koUQiVBseYn514lS7X1XkCP3A==}
engines: {node: '>=12.0.0'}
'@welshman/net@0.7.0':
resolution: {integrity: sha512-9PNiMzNPtKIh5LTlyfYQOn6N3OkNSES0OdBedbGDYGX883C35gSwpPga8MXU2gg/EJDnbF77ozAhI1V0s6pGRw==}
'@welshman/net@0.7.1':
resolution: {integrity: sha512-S3dFH73Cy4phLy5I2KKEeefkRmNBYWB2qONK8txUVDhx1u7ezpALzZEMSPVqVIZk/vCQU3KJ0CyagvbuGF+F9Q==}
'@welshman/router@0.7.0':
resolution: {integrity: sha512-UOsSw4aIMAD6Mkd4jecSD7/18zwFzAES/piegwYv/pWQvX0OAFXoaoPOAbBk19II1mzTX6FzGsoIMf35LO7ZXA==}
'@welshman/router@0.7.1':
resolution: {integrity: sha512-PZnbGHtbnVbsY+b+FqQHNlyY2+MrEAJ3arFiO3fouayb/sWHdBfSd9EL5UM1FQd1q0fjoZIncTmffRcvQfeBqQ==}
'@welshman/signer@0.7.0':
resolution: {integrity: sha512-Jom7yQhG60X/L29XjaJgAAzhvQlIDy05OEluEl6flgpNJdmbvbPfEc0mMvH8g8pK0qDvJtTIQ7957c8zbYdXCg==}
'@welshman/signer@0.7.1':
resolution: {integrity: sha512-/WNEgXZemQ36A07lmrEy78Yn7kEngBjySmXW+xYmHc3OLhQ9XEq3FBCTR+vxsmp1w/t+7IEScPTKn/wvAQ/cSw==}
peerDependencies:
nostr-signer-capacitor-plugin: ~0.0.4
'@welshman/store@0.7.0':
resolution: {integrity: sha512-oKWD5azFtJZECtwqv/DKiZfRTiZ5/hrmuRoxFtKjKDNQYCgMOThHd+ZqsgphA3Q3+bhLpzq74A/uUAontzxUCw==}
'@welshman/store@0.7.1':
resolution: {integrity: sha512-EE+vlMdUeVgQhzJqzhAkbLnnOL22gXW8afJzR377n+CvHABLV7/zY9aW0Hmgm1RnyI7fSfWF2YEa6l6VP8x4pw==}
'@welshman/util@0.7.0':
resolution: {integrity: sha512-ZLtEP107/BncZePUINHHOqzfcjkXS1ljF3UyaJeE8+kdb2X08ncTA2PAzgrs/r+NSSRWObOM4Wxf6qJSSLzkPw==}
'@welshman/util@0.7.1':
resolution: {integrity: sha512-UGryq1jfwRHFS7mjGa4fmuqN851iwKeR+616LmUpTJQHAfhGU7ifer2+JLdDLYBU/neI5iKHdRDO5hg92U6k8Q==}
'@xml-tools/parser@1.0.11':
resolution: {integrity: sha512-aKqQ077XnR+oQtHJlrAflaZaL7qZsulWc/i/ZEooar5JiWj1eLt0+Wg28cpa+XLney107wXqneC+oG1IZvxkTA==}
@@ -3533,6 +3546,14 @@ packages:
typescript:
optional: true
nostr-tools@2.19.1:
resolution: {integrity: sha512-iEHSzRxD1gCMohtna5Jx6Cm90gGK4mrJD2+2VYMu346/EucSlz9gsUFubQ3B7f3SMsnQnh1Srm5nCcPfy2NsNw==}
peerDependencies:
typescript: '>=5.0.0'
peerDependenciesMeta:
typescript:
optional: true
nostr-wasm@0.1.0:
resolution: {integrity: sha512-78BTryCLcLYv96ONU8Ws3Q1JzjlAt+43pWQhIl86xZmWeegYCNLPml7yQ+gG3vR6V5h4XGj+TxO+SS5dsThQIA==}
@@ -6033,6 +6054,24 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
'@jsr/fiatjaf__promenade-trusted-dealer@0.4.1':
dependencies:
'@jsr/henrygd__semaphore': 0.0.2
'@jsr/nostr__tools': 2.16.2
'@noble/curves': 1.9.7
'@jsr/henrygd__semaphore@0.0.2': {}
'@jsr/nostr__tools@2.16.2':
dependencies:
'@noble/ciphers': 0.5.3
'@noble/curves': 1.2.0
'@noble/hashes': 1.3.1
'@scure/base': 1.1.1
'@scure/bip32': 1.3.1
'@scure/bip39': 1.2.1
nostr-wasm: 0.1.0
'@noble/ciphers@0.5.3': {}
'@noble/curves@1.1.0':
@@ -6053,6 +6092,8 @@ snapshots:
'@noble/hashes@1.8.0': {}
'@noble/hashes@2.0.1': {}
'@nodelib/fs.scandir@2.1.5':
dependencies:
'@nodelib/fs.stat': 2.0.5
@@ -6660,16 +6701,16 @@ snapshots:
optionalDependencies:
'@vite-pwa/assets-generator': 0.2.6
'@welshman/app@0.7.0(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)':
'@welshman/app@0.7.1(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)':
dependencies:
'@types/throttle-debounce': 5.0.2
'@welshman/feeds': 0.7.0(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)
'@welshman/lib': 0.7.0
'@welshman/net': 0.7.0(typescript@5.9.3)(ws@8.18.3)
'@welshman/router': 0.7.0(typescript@5.9.3)(ws@8.18.3)
'@welshman/signer': 0.7.0(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)
'@welshman/store': 0.7.0(typescript@5.9.3)(ws@8.18.3)
'@welshman/util': 0.7.0(typescript@5.9.3)
'@welshman/feeds': 0.7.1(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)
'@welshman/lib': 0.7.1
'@welshman/net': 0.7.1(typescript@5.9.3)(ws@8.18.3)
'@welshman/router': 0.7.1(typescript@5.9.3)(ws@8.18.3)
'@welshman/signer': 0.7.1(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)
'@welshman/store': 0.7.1(typescript@5.9.3)(ws@8.18.3)
'@welshman/util': 0.7.1(typescript@5.9.3)
fuse.js: 7.1.0
svelte: 4.2.20
throttle-debounce: 5.0.2
@@ -6678,14 +6719,14 @@ snapshots:
- typescript
- ws
'@welshman/content@0.7.0(typescript@5.9.3)':
'@welshman/content@0.7.1(typescript@5.9.3)':
dependencies:
'@braintree/sanitize-url': 7.1.1
nostr-tools: 2.17.0(typescript@5.9.3)
transitivePeerDependencies:
- typescript
'@welshman/editor@0.7.0(@tiptap/extension-image@2.27.1(@tiptap/core@2.26.3(@tiptap/pm@2.26.3)))(@tiptap/extension-link@2.27.1(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3))(linkifyjs@4.3.2)(prosemirror-markdown@1.13.2)(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.41.3)(tiptap-markdown@0.8.10(@tiptap/core@2.26.3(@tiptap/pm@2.26.3)))(typescript@5.9.3)':
'@welshman/editor@0.7.1(@tiptap/extension-image@2.27.1(@tiptap/core@2.26.3(@tiptap/pm@2.26.3)))(@tiptap/extension-link@2.27.1(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3))(linkifyjs@4.3.2)(prosemirror-markdown@1.13.2)(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.41.3)(tiptap-markdown@0.8.10(@tiptap/core@2.26.3(@tiptap/pm@2.26.3)))(typescript@5.9.3)':
dependencies:
'@tiptap/core': 2.26.3(@tiptap/pm@2.26.3)
'@tiptap/extension-code': 2.27.1(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))
@@ -6700,8 +6741,8 @@ snapshots:
'@tiptap/extension-text': 2.27.1(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))
'@tiptap/pm': 2.26.3
'@tiptap/suggestion': 2.27.1(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)
'@welshman/lib': 0.7.0
'@welshman/util': 0.7.0(typescript@5.9.3)
'@welshman/lib': 0.7.1
'@welshman/util': 0.7.1(typescript@5.9.3)
nostr-editor: 1.0.2(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))(@tiptap/extension-image@2.27.1(@tiptap/core@2.26.3(@tiptap/pm@2.26.3)))(@tiptap/extension-link@2.27.1(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)(linkifyjs@4.3.2)(nostr-tools@2.17.0(typescript@5.9.3))(prosemirror-markdown@1.13.2)(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.41.3)(tiptap-markdown@0.8.10(@tiptap/core@2.26.3(@tiptap/pm@2.26.3)))
nostr-tools: 2.17.0(typescript@5.9.3)
tippy.js: 6.3.7
@@ -6716,72 +6757,73 @@ snapshots:
- tiptap-markdown
- typescript
'@welshman/feeds@0.7.0(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)':
'@welshman/feeds@0.7.1(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)':
dependencies:
'@welshman/lib': 0.7.0
'@welshman/net': 0.7.0(typescript@5.9.3)(ws@8.18.3)
'@welshman/router': 0.7.0(typescript@5.9.3)(ws@8.18.3)
'@welshman/signer': 0.7.0(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)
'@welshman/util': 0.7.0(typescript@5.9.3)
'@welshman/lib': 0.7.1
'@welshman/net': 0.7.1(typescript@5.9.3)(ws@8.18.3)
'@welshman/router': 0.7.1(typescript@5.9.3)(ws@8.18.3)
'@welshman/signer': 0.7.1(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)
'@welshman/util': 0.7.1(typescript@5.9.3)
trava: 1.2.1
transitivePeerDependencies:
- nostr-signer-capacitor-plugin
- typescript
- ws
'@welshman/lib@0.7.0':
'@welshman/lib@0.7.1':
dependencies:
'@scure/base': 1.2.6
'@types/events': 3.0.3
events: 3.3.0
'@welshman/net@0.7.0(typescript@5.9.3)(ws@8.18.3)':
'@welshman/net@0.7.1(typescript@5.9.3)(ws@8.18.3)':
dependencies:
'@welshman/lib': 0.7.0
'@welshman/util': 0.7.0(typescript@5.9.3)
'@welshman/lib': 0.7.1
'@welshman/util': 0.7.1(typescript@5.9.3)
events: 3.3.0
isomorphic-ws: 5.0.0(ws@8.18.3)
transitivePeerDependencies:
- typescript
- ws
'@welshman/router@0.7.0(typescript@5.9.3)(ws@8.18.3)':
'@welshman/router@0.7.1(typescript@5.9.3)(ws@8.18.3)':
dependencies:
'@welshman/lib': 0.7.0
'@welshman/net': 0.7.0(typescript@5.9.3)(ws@8.18.3)
'@welshman/util': 0.7.0(typescript@5.9.3)
'@welshman/lib': 0.7.1
'@welshman/net': 0.7.1(typescript@5.9.3)(ws@8.18.3)
'@welshman/util': 0.7.1(typescript@5.9.3)
transitivePeerDependencies:
- typescript
- ws
'@welshman/signer@0.7.0(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)':
'@welshman/signer@0.7.1(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)':
dependencies:
'@jsr/fiatjaf__promenade-trusted-dealer': 0.4.1
'@noble/curves': 1.9.7
'@noble/hashes': 1.8.0
'@welshman/lib': 0.7.0
'@welshman/net': 0.7.0(typescript@5.9.3)(ws@8.18.3)
'@welshman/util': 0.7.0(typescript@5.9.3)
'@noble/hashes': 2.0.1
'@welshman/lib': 0.7.1
'@welshman/net': 0.7.1(typescript@5.9.3)(ws@8.18.3)
'@welshman/util': 0.7.1(typescript@5.9.3)
nostr-signer-capacitor-plugin: 0.0.4(@capacitor/core@7.4.3)
nostr-tools: 2.17.0(typescript@5.9.3)
nostr-tools: 2.19.1(typescript@5.9.3)
transitivePeerDependencies:
- typescript
- ws
'@welshman/store@0.7.0(typescript@5.9.3)(ws@8.18.3)':
'@welshman/store@0.7.1(typescript@5.9.3)(ws@8.18.3)':
dependencies:
'@welshman/lib': 0.7.0
'@welshman/net': 0.7.0(typescript@5.9.3)(ws@8.18.3)
'@welshman/util': 0.7.0(typescript@5.9.3)
'@welshman/lib': 0.7.1
'@welshman/net': 0.7.1(typescript@5.9.3)(ws@8.18.3)
'@welshman/util': 0.7.1(typescript@5.9.3)
svelte: 4.2.20
transitivePeerDependencies:
- typescript
- ws
'@welshman/util@0.7.0(typescript@5.9.3)':
'@welshman/util@0.7.1(typescript@5.9.3)':
dependencies:
'@noble/curves': 1.9.7
'@types/ws': 8.18.1
'@welshman/lib': 0.7.0
'@welshman/lib': 0.7.1
js-base64: 3.7.8
nostr-tools: 2.17.0(typescript@5.9.3)
nostr-wasm: 0.1.0
@@ -8679,6 +8721,18 @@ snapshots:
optionalDependencies:
typescript: 5.9.3
nostr-tools@2.19.1(typescript@5.9.3):
dependencies:
'@noble/ciphers': 0.5.3
'@noble/curves': 1.2.0
'@noble/hashes': 1.3.1
'@scure/base': 1.1.1
'@scure/bip32': 1.3.1
'@scure/bip39': 1.2.1
nostr-wasm: 0.1.0
optionalDependencies:
typescript: 5.9.3
nostr-wasm@0.1.0: {}
nth-check@2.1.1:
+1 -1
View File
@@ -398,7 +398,7 @@ body.keyboard-open .cb {
@apply bottom-sai;
}
body.keyboard-open .bottom-nav {
body.keyboard-open .hide-on-keyboard {
display: none;
}
+2 -2
View File
@@ -1,7 +1,7 @@
<script lang="ts">
import {onMount} from "svelte"
import {preventDefault} from "@lib/html"
import {randomInt, map, displayList, TIMEZONE, identity} from "@welshman/lib"
import {randomInt, map, displayList, identity, TIMEZONE} from "@welshman/lib"
import {displayRelayUrl, getTagValue, THREAD, MESSAGE, EVENT_TIME, COMMENT} from "@welshman/util"
import type {Filter} from "@welshman/util"
import {makeIntersectionFeed, makeRelayFeed, feedFromFilters} from "@welshman/feeds"
@@ -37,7 +37,7 @@
hideSpaceField = false,
}: Props = $props()
const timezoneOffset = parseInt(TIMEZONE.slice(3)) / 100
const timezoneOffset = parseInt(TIMEZONE.split(":")?.[0] || "00")
const minute = randomInt(0, 59)
const hour = (17 - timezoneOffset) % 24
const WEEKLY = `0 ${minute} ${hour} * * 1`
+10 -5
View File
@@ -1,20 +1,25 @@
<script lang="ts">
import {ellipsize, displayUrl, postJson} from "@welshman/lib"
import {dufflepud} from "@app/core/state"
import {call, ellipsize, displayUrl, postJson} from "@welshman/lib"
import {isRelayUrl} from "@welshman/util"
import {preventDefault, stopPropagation} from "@lib/html"
import Link from "@lib/components/Link.svelte"
import ContentLinkDetail from "@app/components/ContentLinkDetail.svelte"
import ContentLinkBlockImage from "@app/components/ContentLinkBlockImage.svelte"
import {pushModal} from "@app/util/modal"
import {PLATFORM_URL} from "@app/core/state"
import {dufflepud, PLATFORM_URL} from "@app/core/state"
import {makeSpacePath} from "@app/util/routes"
const {value, event} = $props()
let hideImage = $state(false)
const url = value.url.toString()
const external = !url.startsWith(PLATFORM_URL)
const href = external ? url : url.replace(PLATFORM_URL, "")
const [href, external] = call(() => {
if (isRelayUrl(url)) return [makeSpacePath(url), false]
if (url.startsWith(PLATFORM_URL)) return [url.replace(PLATFORM_URL, ""), false]
return [url, true]
})
const loadPreview = async () => {
const json = await postJson(dufflepud("link/preview"), {url})
@@ -21,7 +21,8 @@
.map(tagsFromIMeta)
.find(meta => getTagValue("url", meta) === url) || event.tags
const hash = getTagValue("x", meta)
// Fallback to filename if hash was omitted from the message for interoperability
const hash = getTagValue("x", meta) || url.split(/[\/\.]/).slice(-2)[0]
const key = getTagValue("decryption-key", meta)
const nonce = getTagValue("decryption-nonce", meta)
const algorithm = getTagValue("encryption-algorithm", meta)
+9 -3
View File
@@ -1,5 +1,6 @@
<script lang="ts">
import {displayUrl} from "@welshman/lib"
import {call, displayUrl} from "@welshman/lib"
import {isRelayUrl} from "@welshman/util"
import {preventDefault} from "@lib/html"
import LinkRound from "@assets/icons/link-round.svg?dataurl"
import Icon from "@lib/components/Icon.svelte"
@@ -7,12 +8,17 @@
import ContentLinkDetail from "@app/components/ContentLinkDetail.svelte"
import {pushModal} from "@app/util/modal"
import {PLATFORM_URL} from "@app/core/state"
import {makeSpacePath} from "@app/util/routes"
const {value} = $props()
const url = value.url.toString()
const external = !url.startsWith(PLATFORM_URL)
const href = external ? url : url.replace(PLATFORM_URL, "")
const [href, external] = call(() => {
if (isRelayUrl(url)) return [makeSpacePath(url), false]
if (url.startsWith(PLATFORM_URL)) return [url.replace(PLATFORM_URL, ""), false]
return [url, true]
})
const expand = () => pushModal(ContentLinkDetail, {url}, {fullscreen: true})
</script>
+3 -2
View File
@@ -110,10 +110,11 @@
{@render children?.()}
<!-- a little extra something for ios -->
<div class="bottom-nav fixed bottom-0 left-0 right-0 z-nav h-[var(--saib)] bg-base-100 md:hidden">
<div
class="bottom-nav hide-on-keyboard fixed bottom-0 left-0 right-0 z-nav h-[var(--saib)] bg-base-100 md:hidden">
</div>
<div
class="bottom-nav border-top bottom-sai fixed left-0 right-0 z-nav h-14 border border-base-200 bg-base-100 md:hidden">
class="bottom-nav hide-on-keyboard border-top bottom-sai fixed left-0 right-0 z-nav h-14 border border-base-200 bg-base-100 md:hidden">
<div class="content-padding-x content-sizing flex justify-between px-2">
<div class="flex gap-2 sm:gap-6">
<PrimaryNavItem title="Home" href="/home">
+1 -1
View File
@@ -176,7 +176,7 @@ export const addSpaceMembership = async (url: string) => {
export const removeSpaceMembership = async (url: string) => {
const list = get(userGroupList) || makeList({kind: ROOMS})
const pred = (t: string[]) => t[t[0] === "r" ? 1 : 2] === url
const pred = (t: string[]) => normalizeRelayUrl(t[t[0] === "r" ? 1 : 2]) === url
const event = await removeFromListByPredicate(list, pred).reconcile(nip44EncryptToSelf)
const relays = uniq([url, ...Router.get().FromUser().getUrls(), ...getRelayTagValues(event.tags)])
+8 -11
View File
@@ -4,7 +4,6 @@ import {
int,
YEAR,
DAY,
assoc,
insertAt,
sortBy,
now,
@@ -33,7 +32,7 @@ import {load, request} from "@welshman/net"
import {repository, makeFeedController, loadRelay, tracker} from "@welshman/app"
import {createScroller} from "@lib/html"
import {daysBetween} from "@lib/util"
import {NOTIFIER_RELAY} from "@app/core/state"
import {NOTIFIER_RELAY, getEventsForUrl} from "@app/core/state"
// Utils
@@ -48,12 +47,9 @@ export const makeFeed = ({
element: HTMLElement
onExhausted?: () => void
}) => {
const initialIds = Array.from(tracker.getIds(url))
const initialFilters = filters.map(assoc("ids", initialIds))
const initialEvents = repository.query(initialFilters)
const seen = new Set(initialEvents.map(e => e.id))
const seen = new Set<string>()
const controller = new AbortController()
const buffer = writable(initialEvents)
const buffer = writable<TrustedEvent[]>([])
const events = writable<TrustedEvent[]>([])
const insertEvent = (event: TrustedEvent) => {
@@ -124,6 +120,10 @@ export const makeFeed = ({
},
})
for (const event of getEventsForUrl(url, filters)) {
insertEvent(event)
}
return {
events,
cleanup: () => {
@@ -147,9 +147,6 @@ export const makeCalendarFeed = ({
}) => {
const interval = int(5, DAY)
const controller = new AbortController()
const initialIds = Array.from(tracker.getIds(url))
const initialFilters = filters.map(assoc("ids", initialIds))
const initialEvents = repository.query(initialFilters)
let exhaustedScrollers = 0
let backwardWindow = [now() - interval, now()]
@@ -159,7 +156,7 @@ export const makeCalendarFeed = ({
const getEnd = (event: TrustedEvent) => parseInt(getTagValue("end", event.tags) || "")
const events = writable(sortBy(getStart, initialEvents))
const events = writable(sortBy(getStart, getEventsForUrl(url, filters)))
const insertEvent = (event: TrustedEvent) => {
const start = getStart(event)
+21 -4
View File
@@ -17,7 +17,6 @@ import {
uniq,
indexBy,
partition,
pushToMapKey,
shuffle,
parseJson,
memoize,
@@ -48,6 +47,7 @@ import {
deriveItemsByKey,
deriveEventsByIdByUrl,
deriveEventsByIdForUrl,
getEventsByIdForUrl,
} from "@welshman/store"
import {isKindFeed, findFeed} from "@welshman/feeds"
import {
@@ -216,6 +216,9 @@ export const deriveEvent = makeDeriveEvent({
onDerive: (filters: Filter[], relays: string[]) => load({filters, relays}),
})
export const getEventsForUrl = (url: string, filters: Filter[]) =>
getEventsByIdForUrl({url, tracker, repository, filters}).values()
export const deriveEventsForUrl = (url: string, filters: Filter[]) =>
deriveArray(deriveEventsByIdForUrl({url, tracker, repository, filters}))
@@ -282,7 +285,7 @@ export const defaultSettings = {
report_usage: true,
report_errors: true,
send_delay: 0,
font_size: 1,
font_size: 1.1,
play_notification_sound: true,
show_notifications_badge: true,
}
@@ -488,7 +491,7 @@ export const roomMetaEventsByIdByUrl = deriveEventsByIdByUrl({
})
export const roomsByUrl = derived(roomMetaEventsByIdByUrl, roomMetaEventsByIdByUrl => {
const result = new Map<string, Room[]>()
const metaByIdByUrl = new Map<string, Map<string, Room>>()
for (const [url, events] of roomMetaEventsByIdByUrl.entries()) {
const [metaEvents, deleteEvents] = partition(spec({kind: ROOM_META}), events.values())
@@ -507,10 +510,24 @@ export const roomsByUrl = derived(roomMetaEventsByIdByUrl, roomMetaEventsByIdByU
continue
}
pushToMapKey(result, url, {...meta, url, id: makeRoomId(url, meta.h)})
let metaById = metaByIdByUrl.get(url)
if (!metaById) {
metaById = new Map()
metaByIdByUrl.set(url, metaById)
}
const id = makeRoomId(url, meta.h)
metaById.set(id, {...meta, url, id})
}
}
const result = new Map<string, Room[]>()
for (const [url, metaById] of metaByIdByUrl.entries()) {
result.set(url, Array.from(metaById.values()))
}
return result
})
+1 -1
View File
@@ -28,7 +28,7 @@
transition:fade={{duration: 300}}
onclick={onClose}>
</button>
<div class="scroll-container {extraClass}" transition:fly={{duration: 300}}>
<div class="scroll-container relative {extraClass}" transition:fly={{duration: 300}}>
{@render children?.()}
</div>
</div>
+4 -1
View File
@@ -14,5 +14,8 @@
{#if src.includes("image/svg") || src.endsWith(".svg")}
<Icon icon={src} {size} class={props.class} />
{:else}
<img {src} {alt} class="h-{size} w-{size} aspect-square object-cover {props.class}" />
<img
{src}
{alt}
class="h-{size} w-{size} min-w-{size} min-h-{size} aspect-square object-cover {props.class}" />
{/if}
+1 -1
View File
@@ -14,6 +14,6 @@
{...props}
bind:this={element}
data-component="PageContent"
class="scroll-container cw md:bottom-sai fixed bottom-[calc(var(--saib)+3.5rem)] top-[calc(var(--sait)+3rem)] z-feature overflow-y-auto overflow-x-hidden {props.class}">
class="scroll-container cw cb fixed top-[calc(var(--sait)+3rem)] z-feature overflow-y-auto overflow-x-hidden {props.class}">
{@render children?.()}
</div>
+4 -2
View File
@@ -5,7 +5,7 @@
import {page} from "$app/stores"
import type {Readable} from "svelte/store"
import type {MakeNonOptional} from "@welshman/lib"
import {now, formatTimestampAsDate, ago, MINUTE} from "@welshman/lib"
import {now, int, formatTimestampAsDate, ago, MINUTE} from "@welshman/lib"
import type {TrustedEvent, EventContent} from "@welshman/util"
import {
makeEvent,
@@ -213,6 +213,7 @@
let previousDate
let previousKind
let previousPubkey
let previousCreatedAt = 0
let newMessagesSeen = false
if (events) {
@@ -249,14 +250,15 @@
type: "note",
value: event,
showPubkey:
date !== previousDate ||
previousPubkey !== event.pubkey ||
event.created_at - previousCreatedAt > int(3, MINUTE) ||
[ROOM_ADD_MEMBER, ROOM_REMOVE_MEMBER].includes(previousKind!),
})
previousDate = date
previousKind = event.kind
previousPubkey = event.pubkey
previousCreatedAt = event.created_at
seen.add(event.id)
}
}
+4 -2
View File
@@ -3,7 +3,7 @@
import {page} from "$app/stores"
import type {Readable} from "svelte/store"
import {readable} from "svelte/store"
import {now, formatTimestampAsDate, MINUTE, ago} from "@welshman/lib"
import {now, int, formatTimestampAsDate, MINUTE, ago} from "@welshman/lib"
import type {TrustedEvent, EventContent} from "@welshman/util"
import {makeEvent, MESSAGE, RELAY_ADD_MEMBER, RELAY_REMOVE_MEMBER} from "@welshman/util"
import {pubkey, publishThunk} from "@welshman/app"
@@ -138,6 +138,7 @@
let previousDate
let previousKind
let previousPubkey
let previousCreatedAt = 0
let newMessagesSeen = false
if (events) {
@@ -174,14 +175,15 @@
type: "note",
value: event,
showPubkey:
date !== previousDate ||
previousPubkey !== event.pubkey ||
event.created_at - previousCreatedAt > int(3, MINUTE) ||
[RELAY_ADD_MEMBER, RELAY_REMOVE_MEMBER].includes(previousKind!),
})
previousDate = date
previousKind = event.kind
previousPubkey = event.pubkey
previousCreatedAt = event.created_at
seen.add(event.id)
}
}