diff --git a/package.json b/package.json index d9ce2241..de73aafe 100644 --- a/package.json +++ b/package.json @@ -59,17 +59,16 @@ "@types/throttle-debounce": "^5.0.2", "@vite-pwa/assets-generator": "^0.2.6", "@vite-pwa/sveltekit": "^0.6.8", - "@welshman/app": "^0.5.3", - "@welshman/content": "^0.5.3", - "@welshman/editor": "^0.5.3", - "@welshman/feeds": "^0.5.3", - "@welshman/lib": "^0.5.3", - "@welshman/net": "^0.5.3", - "@welshman/relay": "^0.5.3", - "@welshman/router": "^0.5.3", - "@welshman/signer": "^0.5.3", - "@welshman/store": "^0.5.3", - "@welshman/util": "^0.5.3", + "@welshman/app": "^0.6.0", + "@welshman/content": "^0.6.0", + "@welshman/editor": "^0.6.0", + "@welshman/feeds": "^0.6.0", + "@welshman/lib": "^0.6.0", + "@welshman/net": "^0.6.0", + "@welshman/router": "^0.6.0", + "@welshman/signer": "^0.6.0", + "@welshman/store": "^0.6.0", + "@welshman/util": "^0.6.0", "compressorjs": "^1.2.1", "daisyui": "^4.12.24", "date-picker-svelte": "^2.16.0", @@ -79,7 +78,7 @@ "husky": "^9.1.7", "idb": "^8.0.3", "nostr-signer-capacitor-plugin": "^0.0.4", - "nostr-tools": "^2.17.0", + "nostr-tools": "^2.14.2", "prettier-plugin-tailwindcss": "^0.6.14", "qr-scanner": "^1.4.2", "qrcode": "^1.5.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 75b15d3b..1a9e2965 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -72,38 +72,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.5.3 - version: 0.5.3(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3) + specifier: ^0.6.0 + version: 0.6.0(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3) '@welshman/content': - specifier: ^0.5.3 - version: 0.5.3(typescript@5.9.3) + specifier: ^0.6.0 + version: 0.6.0(typescript@5.9.3) '@welshman/editor': - specifier: ^0.5.3 - version: 0.5.3(@tiptap/extension-image@2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3)))(@tiptap/extension-link@2.26.3(@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.6.0 + version: 0.6.0(@tiptap/extension-image@2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3)))(@tiptap/extension-link@2.26.3(@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.5.3 - version: 0.5.3(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3) + specifier: ^0.6.0 + version: 0.6.0(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3) '@welshman/lib': - specifier: ^0.5.3 - version: 0.5.3 + specifier: ^0.6.0 + version: 0.6.0 '@welshman/net': - specifier: ^0.5.3 - version: 0.5.3(typescript@5.9.3)(ws@8.18.3) - '@welshman/relay': - specifier: ^0.5.3 - version: 0.5.3(typescript@5.9.3) + specifier: ^0.6.0 + version: 0.6.0(typescript@5.9.3)(ws@8.18.3) '@welshman/router': - specifier: ^0.5.3 - version: 0.5.3(typescript@5.9.3) + specifier: ^0.6.0 + version: 0.6.0(typescript@5.9.3)(ws@8.18.3) '@welshman/signer': - specifier: ^0.5.3 - version: 0.5.3(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3) + specifier: ^0.6.0 + version: 0.6.0(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3) '@welshman/store': - specifier: ^0.5.3 - version: 0.5.3(typescript@5.9.3) + specifier: ^0.6.0 + version: 0.6.0(typescript@5.9.3)(ws@8.18.3) '@welshman/util': - specifier: ^0.5.3 - version: 0.5.3(typescript@5.9.3) + specifier: ^0.6.0 + version: 0.6.0(typescript@5.9.3) compressorjs: specifier: ^1.2.1 version: 1.2.1 @@ -132,7 +129,7 @@ importers: specifier: ^0.0.4 version: 0.0.4(@capacitor/core@7.4.3) nostr-tools: - specifier: ^2.17.0 + specifier: ^2.14.2 version: 2.17.0(typescript@5.9.3) prettier-plugin-tailwindcss: specifier: ^0.6.14 @@ -1695,41 +1692,38 @@ packages: '@vite-pwa/assets-generator': optional: true - '@welshman/app@0.5.3': - resolution: {integrity: sha512-uygqUotknMYPEE7jkpBEWJXEfwHrowbMYuR1TygdqqKIWv/BzlZ7HO/infIHZHWy1xuR/9gEFhEY1sukxkNEow==} + '@welshman/app@0.6.0': + resolution: {integrity: sha512-izbI6581NvadR8ACLGnqzyS0iTl7qLwv+hHodsoNSqEQ3/Wo0fEyOyxPhgQkJv1BgVRLPgJ1x31dNsSGl6sCsw==} - '@welshman/content@0.5.3': - resolution: {integrity: sha512-o4zQReYP0dcE6ofom0nEbYqSBe+dlNdQAQ3LcaRY2Bgm+IG8mPtT8FZ6SFnAHJOG215MW5uQ8eUuqOtSKzlYcg==} + '@welshman/content@0.6.0': + resolution: {integrity: sha512-Db3NdHk8oyITtH1YjTHIlcMfnfCqEuwmMTTDqwMwJ+Lj1yrLHzd+D36+MS36gVfUgxYu/CvV2LP8Hui25J/RDA==} - '@welshman/editor@0.5.3': - resolution: {integrity: sha512-rIm3WquSVcBDwaa0tI9ppBHnEEHifPWAy6kTks1M2ZLUNrhyBMMCqsjEIJiWEmP7uVuzvsSH3LDk/Bs+tYUPcg==} + '@welshman/editor@0.6.0': + resolution: {integrity: sha512-JQURL22IE4sbjD7PnLVscY9WIXFQMoXL9JblNsVh+NHR/YtCSH8n++NxW2k4wqWeCbp/gEZYrBIVEIwBuvONbw==} - '@welshman/feeds@0.5.3': - resolution: {integrity: sha512-ilE6Ui+nKlV+fyk8MDd+3fx5xU/K5hOLM5p0idE+cLeA0th2IanKm4JRS5vz9p/Niox4XhyvuaCxVNRLxXZ4zg==} + '@welshman/feeds@0.6.0': + resolution: {integrity: sha512-NmNQDKQrKrEsa5q3TqPgHUkdvIbtq9jo1kN6HCZr8A+sK7vteuOZuwm7YGdNRlfJOwoDG1Edc0HKzNmtQA/wHA==} - '@welshman/lib@0.5.3': - resolution: {integrity: sha512-XElYDyJhuHLHwJdaoTKdq9a+evUoFxqguTh18cIOpsp55f8FOVcmF67PN3YZ7p/PTt6d3kWh7jQ2AIo3yJIPQg==} + '@welshman/lib@0.6.0': + resolution: {integrity: sha512-clW0W7hqo0/HyoCd8xYAWmAMuWEZQERVmnyYA/6os5ZJDZYq9oSDL/AanYQnB8rme2XoZjxUgDZEhRz8cPFvRQ==} engines: {node: '>=12.0.0'} - '@welshman/net@0.5.3': - resolution: {integrity: sha512-XhGwkG35LuLo38pFJmkEa1/D0DaMP83KziZ9F0VMVDNOSgSCkLBuANbcCeZWcNuKNb/EwlvzJZLWA0ywqyq+1g==} + '@welshman/net@0.6.0': + resolution: {integrity: sha512-ZNyIKaDfZd2gpoVLVPnvuFsqM+bhgSA7XTlT0KHytTeRHQ8aYAkTMKGUgxASAISAqwX84HcNhoKQODP+4YgFow==} - '@welshman/relay@0.5.3': - resolution: {integrity: sha512-AWWDQ01TPMsakuET+hkarBQeeqk20mcKk4fmeR/bEUZWSGCDbCK6pD1L1ozilJ5dQKTmWrSzHGe+jJU4sFvZNw==} + '@welshman/router@0.6.0': + resolution: {integrity: sha512-6g/pPQrSwDW0LXvGlrg+TvLkpJ7zNkW/qrnPKQYH591dOqB+z6LQ6hstI4m+FJBBB9a9qjx2gnzptUMKkesHow==} - '@welshman/router@0.5.3': - resolution: {integrity: sha512-abowfhW14vDBZFcDZuTAj4ktIJyfmOkAWlkXAD3g1mu2amoJ0LZ2jDro8GEFa+qUv2dnxLh0yILdv/89SzUguA==} - - '@welshman/signer@0.5.3': - resolution: {integrity: sha512-XlXtVpF5Mj4bmYtf32p1eRCsBK3o8e+lfBFJ7kXIU0FWmZHVtOnl7+ZjU5SCRqREG4zmzn6Ad0G/JA4kYJMIWw==} + '@welshman/signer@0.6.0': + resolution: {integrity: sha512-uQqapz9kMm0CaUrvXxDHo5Hao/jmUQLnd9dEoBJ1a6WbNolzCu9eaa3fue78MIxujEHBq3KKGPsp1KFH6MXBhg==} peerDependencies: nostr-signer-capacitor-plugin: ~0.0.4 - '@welshman/store@0.5.3': - resolution: {integrity: sha512-VB2r0NASwnFxzm/Io1qZ73yD3lHA8wEEjmlHOnH0FXNp/UNlJKGREWsgsjbLH/A+04lCjsMv2QmlkW2NqCBS/A==} + '@welshman/store@0.6.0': + resolution: {integrity: sha512-sCxIrBPw9lOtvM0C3cm+a62LmgAJZkLtoZOzHgU7WQU5z4xIskYUwCzFIT6YuZdewRXNV86JF6uOfWC6Ff+J4w==} - '@welshman/util@0.5.3': - resolution: {integrity: sha512-avMOK1AcO3V9qTQP+oAl4pgTdquD86Fkey74f1WOOu3BZRVgWN7LjBQCecszW9BQMg/TH4mUk2PuSqSoPy8zSw==} + '@welshman/util@0.6.0': + resolution: {integrity: sha512-ll4mOff5ujIN55FhvvrFnHNrVmEepswmuDaEW9HC/UlIgmEc3By6wq83OX8/fdJxUhU98wXV6XXHsM14UCpMZg==} '@xml-tools/parser@1.0.11': resolution: {integrity: sha512-aKqQ077XnR+oQtHJlrAflaZaL7qZsulWc/i/ZEooar5JiWj1eLt0+Wg28cpa+XLney107wXqneC+oG1IZvxkTA==} @@ -6210,12 +6204,12 @@ snapshots: '@scure/bip32@1.3.1': dependencies: '@noble/curves': 1.1.0 - '@noble/hashes': 1.3.1 + '@noble/hashes': 1.3.2 '@scure/base': 1.1.1 '@scure/bip39@1.2.1': dependencies: - '@noble/hashes': 1.3.1 + '@noble/hashes': 1.3.2 '@scure/base': 1.1.1 '@sentry-internal/browser-utils@8.55.0': @@ -6657,17 +6651,16 @@ snapshots: optionalDependencies: '@vite-pwa/assets-generator': 0.2.6 - '@welshman/app@0.5.3(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)': + '@welshman/app@0.6.0(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.5.3(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3) - '@welshman/lib': 0.5.3 - '@welshman/net': 0.5.3(typescript@5.9.3)(ws@8.18.3) - '@welshman/relay': 0.5.3(typescript@5.9.3) - '@welshman/router': 0.5.3(typescript@5.9.3) - '@welshman/signer': 0.5.3(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3) - '@welshman/store': 0.5.3(typescript@5.9.3) - '@welshman/util': 0.5.3(typescript@5.9.3) + '@welshman/feeds': 0.6.0(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3) + '@welshman/lib': 0.6.0 + '@welshman/net': 0.6.0(typescript@5.9.3)(ws@8.18.3) + '@welshman/router': 0.6.0(typescript@5.9.3)(ws@8.18.3) + '@welshman/signer': 0.6.0(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3) + '@welshman/store': 0.6.0(typescript@5.9.3)(ws@8.18.3) + '@welshman/util': 0.6.0(typescript@5.9.3) fuse.js: 7.1.0 svelte: 4.2.20 throttle-debounce: 5.0.2 @@ -6676,14 +6669,14 @@ snapshots: - typescript - ws - '@welshman/content@0.5.3(typescript@5.9.3)': + '@welshman/content@0.6.0(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.5.3(@tiptap/extension-image@2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3)))(@tiptap/extension-link@2.26.3(@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.6.0(@tiptap/extension-image@2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3)))(@tiptap/extension-link@2.26.3(@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.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3)) @@ -6698,8 +6691,8 @@ snapshots: '@tiptap/extension-text': 2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3)) '@tiptap/pm': 2.26.3 '@tiptap/suggestion': 2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3) - '@welshman/lib': 0.5.3 - '@welshman/util': 0.5.3(typescript@5.9.3) + '@welshman/lib': 0.6.0 + '@welshman/util': 0.6.0(typescript@5.9.3) nostr-editor: 1.0.1(@tiptap/core@2.26.3(@tiptap/pm@2.26.3))(@tiptap/extension-image@2.26.3(@tiptap/core@2.26.3(@tiptap/pm@2.26.3)))(@tiptap/extension-link@2.26.3(@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 @@ -6714,78 +6707,71 @@ snapshots: - tiptap-markdown - typescript - '@welshman/feeds@0.5.3(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)': + '@welshman/feeds@0.6.0(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)': dependencies: - '@welshman/lib': 0.5.3 - '@welshman/net': 0.5.3(typescript@5.9.3)(ws@8.18.3) - '@welshman/relay': 0.5.3(typescript@5.9.3) - '@welshman/router': 0.5.3(typescript@5.9.3) - '@welshman/signer': 0.5.3(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3) - '@welshman/util': 0.5.3(typescript@5.9.3) + '@welshman/lib': 0.6.0 + '@welshman/net': 0.6.0(typescript@5.9.3)(ws@8.18.3) + '@welshman/router': 0.6.0(typescript@5.9.3)(ws@8.18.3) + '@welshman/signer': 0.6.0(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3) + '@welshman/util': 0.6.0(typescript@5.9.3) trava: 1.2.1 transitivePeerDependencies: - nostr-signer-capacitor-plugin - typescript - ws - '@welshman/lib@0.5.3': + '@welshman/lib@0.6.0': dependencies: '@scure/base': 1.2.6 '@types/events': 3.0.3 events: 3.3.0 - '@welshman/net@0.5.3(typescript@5.9.3)(ws@8.18.3)': + '@welshman/net@0.6.0(typescript@5.9.3)(ws@8.18.3)': dependencies: - '@welshman/lib': 0.5.3 - '@welshman/relay': 0.5.3(typescript@5.9.3) - '@welshman/util': 0.5.3(typescript@5.9.3) + '@welshman/lib': 0.6.0 + '@welshman/util': 0.6.0(typescript@5.9.3) events: 3.3.0 isomorphic-ws: 5.0.0(ws@8.18.3) transitivePeerDependencies: - typescript - ws - '@welshman/relay@0.5.3(typescript@5.9.3)': + '@welshman/router@0.6.0(typescript@5.9.3)(ws@8.18.3)': dependencies: - '@welshman/lib': 0.5.3 - '@welshman/util': 0.5.3(typescript@5.9.3) + '@welshman/lib': 0.6.0 + '@welshman/net': 0.6.0(typescript@5.9.3)(ws@8.18.3) + '@welshman/util': 0.6.0(typescript@5.9.3) transitivePeerDependencies: - typescript + - ws - '@welshman/router@0.5.3(typescript@5.9.3)': - dependencies: - '@welshman/lib': 0.5.3 - '@welshman/relay': 0.5.3(typescript@5.9.3) - '@welshman/util': 0.5.3(typescript@5.9.3) - transitivePeerDependencies: - - typescript - - '@welshman/signer@0.5.3(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)': + '@welshman/signer@0.6.0(nostr-signer-capacitor-plugin@0.0.4(@capacitor/core@7.4.3))(typescript@5.9.3)(ws@8.18.3)': dependencies: '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 - '@welshman/lib': 0.5.3 - '@welshman/net': 0.5.3(typescript@5.9.3)(ws@8.18.3) - '@welshman/util': 0.5.3(typescript@5.9.3) + '@welshman/lib': 0.6.0 + '@welshman/net': 0.6.0(typescript@5.9.3)(ws@8.18.3) + '@welshman/util': 0.6.0(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) transitivePeerDependencies: - typescript - ws - '@welshman/store@0.5.3(typescript@5.9.3)': + '@welshman/store@0.6.0(typescript@5.9.3)(ws@8.18.3)': dependencies: - '@welshman/lib': 0.5.3 - '@welshman/relay': 0.5.3(typescript@5.9.3) - '@welshman/util': 0.5.3(typescript@5.9.3) + '@welshman/lib': 0.6.0 + '@welshman/net': 0.6.0(typescript@5.9.3)(ws@8.18.3) + '@welshman/util': 0.6.0(typescript@5.9.3) svelte: 4.2.20 transitivePeerDependencies: - typescript + - ws - '@welshman/util@0.5.3(typescript@5.9.3)': + '@welshman/util@0.6.0(typescript@5.9.3)': dependencies: '@types/ws': 8.18.1 - '@welshman/lib': 0.5.3 + '@welshman/lib': 0.6.0 js-base64: 3.7.8 nostr-tools: 2.17.0(typescript@5.9.3) nostr-wasm: 0.1.0 diff --git a/src/app/components/ChannelItem.svelte b/src/app/components/ChannelItem.svelte index ef611dc7..191ee178 100644 --- a/src/app/components/ChannelItem.svelte +++ b/src/app/components/ChannelItem.svelte @@ -6,6 +6,7 @@ import { thunks, pubkey, + mergeThunks, deriveProfile, deriveProfileDisplay, displayProfileByPubkey, @@ -52,12 +53,12 @@ onEdit, }: Props = $props() - const thunk = $thunks[event.id] const path = getChannelItemPath(url, event) const shouldProtect = canEnforceNip70(url) const today = formatTimestampAsDate(now()) const profile = deriveProfile(event.pubkey, [url]) const profileDisplay = deriveProfileDisplay(event.pubkey, [url]) + const thunk = mergeThunks($thunks.filter(t => t.event.id === event.id)) const [_, colorValue] = colors[parseInt(hash(event.pubkey)) % colors.length] const comments = deriveEventsForUrl(url, [{kinds: [COMMENT], "#e": [event.id]}]) diff --git a/src/app/components/Chat.svelte b/src/app/components/Chat.svelte index 06ebf481..99ef8500 100644 --- a/src/app/components/Chat.svelte +++ b/src/app/components/Chat.svelte @@ -11,6 +11,7 @@ MINUTE, sortBy, remove, + enumerate, formatTimestampAsDate, } from "@welshman/lib" import type {TrustedEvent, EventTemplate, EventContent} from "@welshman/util" @@ -30,7 +31,6 @@ loadInboxRelaySelections, inboxRelaySelectionsByPubkey, } from "@welshman/app" - import type {AbstractThunk} from "@welshman/app" import Danger from "@assets/icons/danger-triangle.svg?dataurl" import Icon from "@lib/components/Icon.svelte" import Link from "@lib/components/Link.svelte" @@ -126,14 +126,13 @@ // Split the message into multiple pieces so that we can use kind 15 to send images per nip 17 // Sleep 1 second between each one to make sure timestamps are distinct - const thunks: AbstractThunk[] = [] - for (let i = 0; i < templates.length; i++) { - const template = templates[i] - - thunks.push( - await sendWrapped({pubkeys, template, delay: $userSettingsValues.send_delay + ms(i)}), - ) - } + const thunks = Array.from(enumerate(templates)).map(([i, event]) => + sendWrapped({ + event, + recipients: pubkeys, + delay: $userSettingsValues.send_delay + ms(i), + }), + ) pushToast({ timeout: 30_000, diff --git a/src/app/components/ChatEnable.svelte b/src/app/components/ChatEnable.svelte index 7abc8198..ff5eaa8a 100644 --- a/src/app/components/ChatEnable.svelte +++ b/src/app/components/ChatEnable.svelte @@ -1,6 +1,7 @@ diff --git a/src/app/components/ChatMessageMenuMobile.svelte b/src/app/components/ChatMessageMenuMobile.svelte index b7466980..446387e6 100644 --- a/src/app/components/ChatMessageMenuMobile.svelte +++ b/src/app/components/ChatMessageMenuMobile.svelte @@ -24,7 +24,10 @@ const onEmoji = ((event: TrustedEvent, pubkeys: string[], emoji: NativeEmoji) => { history.back() - sendWrapped({template: makeReaction({event, content: emoji.unicode, protect: false}), pubkeys}) + sendWrapped({ + event: makeReaction({event, content: emoji.unicode, protect: false}), + recipients: pubkeys, + }) }).bind(undefined, event, pubkeys) const showEmojiPicker = () => pushModal(EmojiPicker, {onClick: onEmoji}, {replaceState: true}) diff --git a/src/app/components/PrimaryNav.svelte b/src/app/components/PrimaryNav.svelte index 6a018bea..a95f370f 100644 --- a/src/app/components/PrimaryNav.svelte +++ b/src/app/components/PrimaryNav.svelte @@ -3,7 +3,7 @@ import {page} from "$app/stores" import {goto} from "$app/navigation" import {splitAt} from "@welshman/lib" - import {userProfile} from "@welshman/app" + import {userProfile, shouldUnwrap} from "@welshman/app" import Avatar from "@lib/components/Avatar.svelte" import Divider from "@lib/components/Divider.svelte" import PrimaryNavItem from "@lib/components/PrimaryNavItem.svelte" @@ -13,7 +13,7 @@ import MenuOtherSpaces from "@app/components/MenuOtherSpaces.svelte" import MenuSettings from "@app/components/MenuSettings.svelte" import PrimaryNavItemSpace from "@app/components/PrimaryNavItemSpace.svelte" - import {userRoomsByUrl, canDecrypt, PLATFORM_RELAYS, PLATFORM_LOGO} from "@app/core/state" + import {userRoomsByUrl, PLATFORM_RELAYS, PLATFORM_LOGO} from "@app/core/state" import {pushModal} from "@app/util/modal" import {makeSpacePath} from "@app/util/routes" import {notifications} from "@app/util/notifications" @@ -37,7 +37,7 @@ const showSettingsMenu = () => pushModal(MenuSettings) - const openChat = () => ($canDecrypt ? goto("/chat") : pushModal(ChatEnable, {next: "/chat"})) + const openChat = () => ($shouldUnwrap ? goto("/chat") : pushModal(ChatEnable, {next: "/chat"})) const hasNotification = (url: string) => { const path = makeSpacePath(url) diff --git a/src/app/components/ProfileDetail.svelte b/src/app/components/ProfileDetail.svelte index 27c45b40..13720155 100644 --- a/src/app/components/ProfileDetail.svelte +++ b/src/app/components/ProfileDetail.svelte @@ -1,5 +1,6 @@
diff --git a/src/app/components/ThunkFailure.svelte b/src/app/components/ThunkFailure.svelte index 70febc88..c09186e3 100644 --- a/src/app/components/ThunkFailure.svelte +++ b/src/app/components/ThunkFailure.svelte @@ -1,14 +1,8 @@ {#if $deleted} diff --git a/src/app/core/commands.ts b/src/app/core/commands.ts index fa57d16a..12ec2c69 100644 --- a/src/app/core/commands.ts +++ b/src/app/core/commands.ts @@ -90,6 +90,7 @@ import { waitForThunkError, getPubkeyRelays, userBlossomServers, + shouldUnwrap, } from "@welshman/app" import {compressFile} from "@src/lib/html" import type {SettingsValues, Alert} from "@app/core/state" @@ -103,8 +104,6 @@ import { DEFAULT_BLOSSOM_SERVERS, userRoomsByUrl, userSettingsValues, - canDecrypt, - ensureUnwrapped, userInboxRelays, getMembershipUrls, } from "@app/core/state" @@ -593,8 +592,8 @@ export const createAlert = async (params: CreateAlertParams): Promise { - if (!get(canDecrypt)) { - enableGiftWraps() + if (!shouldUnwrap.get()) { + shouldUnwrap.set(true) } return createAlert({ @@ -658,16 +657,6 @@ export const payInvoice = async (invoice: string) => { } } -// Gift Wraps - -export const enableGiftWraps = () => { - canDecrypt.set(true) - - for (const event of repository.query([{kinds: [WRAP]}])) { - ensureUnwrapped(event) - } -} - // File upload export const normalizeBlossomUrl = (url: string) => normalizeUrl(url.replace(/^ws/, "http")) diff --git a/src/app/core/state.ts b/src/app/core/state.ts index 0dc553a3..ba8fe21e 100644 --- a/src/app/core/state.ts +++ b/src/app/core/state.ts @@ -27,14 +27,7 @@ import { } from "@welshman/lib" import type {Socket} from "@welshman/net" import {Pool, load, AuthStateEvent, AuthStatus, SocketEvent, netContext} from "@welshman/net" -import { - collection, - custom, - deriveEvents, - deriveEventsMapped, - withGetter, - synced, -} from "@welshman/store" +import {collection, custom, deriveEvents, deriveEventsMapped, withGetter} from "@welshman/store" import {isKindFeed, findFeed} from "@welshman/feeds" import { getIdFilters, @@ -68,7 +61,6 @@ import { getGroupTags, getRelayTagValues, getPubkeyTagValues, - isHashedEvent, displayProfile, readList, getListTags, @@ -82,8 +74,8 @@ import { RelayMode, getRelaysFromList, } from "@welshman/util" -import type {TrustedEvent, SignedEvent, PublishedList, List, Filter} from "@welshman/util" -import {Nip59, decrypt} from "@welshman/signer" +import type {TrustedEvent, PublishedList, List, Filter} from "@welshman/util" +import {decrypt} from "@welshman/signer" import {routerContext, Router} from "@welshman/router" import { pubkey, @@ -92,14 +84,10 @@ import { tracker, makeTrackerStore, makeRepositoryStore, - relay, - getSession, - getSigner, createSearch, userFollows, ensurePlaintext, thunks, - flattenThunks, signer, makeOutboxLoader, appContext, @@ -109,7 +97,6 @@ import { userInboxRelaySelections, } from "@welshman/app" import type {Thunk, Relay} from "@welshman/app" -import {preferencesStorageProvider} from "@src/lib/storage" export const fromCsv = (s: string) => (s || "").split(",").filter(identity) @@ -195,46 +182,6 @@ export const defaultPubkeys = derived(userFollows, $userFollows => { return userPubkeys.length > 5 ? userPubkeys : [...userPubkeys, ...appPubkeys] }) -const failedUnwraps = new Set() - -export const ensureUnwrapped = async (event: TrustedEvent) => { - if (event.kind !== WRAP) { - return event - } - - let rumor = repository.eventsByWrap.get(event.id) - - if (rumor || failedUnwraps.has(event.id)) { - return rumor - } - - for (const recipient of getPubkeyTagValues(event.tags)) { - const session = getSession(recipient) - const signer = getSigner(session) - - if (signer) { - try { - rumor = await Nip59.fromSigner(signer).unwrap(event as SignedEvent) - break - } catch (e) { - // pass - } - } - } - - if (rumor && isHashedEvent(rumor)) { - // Copy urls over to the rumor - tracker.copy(event.id, rumor.id) - - // Send the rumor via our relay so listeners get updated - relay.send("EVENT", rumor) - } else { - failedUnwraps.add(event.id) - } - - return rumor -} - export const trackerStore = makeTrackerStore() export const repositoryStore = makeRepositoryStore() @@ -262,7 +209,7 @@ export const getUrlsForEvent = derived([trackerStore, thunks], ([$tracker, $thun const getThunksByEventId = memoize(() => { const thunksByEventId = new Map() - for (const thunk of flattenThunks(Object.values($thunks))) { + for (const thunk of $thunks) { pushToMapKey(thunksByEventId, thunk.event.id, thunk) } @@ -285,7 +232,7 @@ export const getUrlsForEvent = derived([trackerStore, thunks], ([$tracker, $thun export const getEventsForUrl = (url: string, filters: Filter[]) => { const ids = uniq([ ...tracker.getIds(url), - ...Array.from(flattenThunks(Object.values(get(thunks)))) + ...get(thunks) .filter(t => t.options.relays.includes(url)) .map(t => t.event.id), ]) @@ -297,9 +244,7 @@ export const deriveEventsForUrl = (url: string, filters: Filter[]) => derived([trackerStore, thunks], ([$tracker, $thunks]) => { const ids = uniq([ ...$tracker.getIds(url), - ...Array.from(flattenThunks(Object.values($thunks))) - .filter(t => t.options.relays.includes(url)) - .map(t => t.event.id), + ...$thunks.filter(t => t.options.relays.includes(url)).map(t => t.event.id), ]) return repository.query(filters.map(assoc("ids", ids))) @@ -336,12 +281,6 @@ export const COMMENT_FILTER = makeCommentFilter(MESSAGE_KINDS) // Settings -export const canDecrypt = synced({ - key: "canDecrypt", - defaultValue: false, - storage: preferencesStorageProvider, -}) - export const SETTINGS = "flotilla/settings" export type SettingsValues = { @@ -555,11 +494,6 @@ export const chats = derived( const messagesByChatId = new Map() for (const message of $messages) { - // Filter out messages we sent but aren't addressed to the user - if (!getPubkeyTagValues(message.wrap?.tags || []).includes($pubkey!)) { - continue - } - const chatId = makeChatId(getPubkeyTagValues(message.tags).concat(message.pubkey)) pushToMapKey(messagesByChatId, chatId, message) diff --git a/src/app/core/sync.ts b/src/app/core/sync.ts index 687b61be..a6f71d59 100644 --- a/src/app/core/sync.ts +++ b/src/app/core/sync.ts @@ -39,6 +39,7 @@ import { loadMutes, loadProfile, repository, + shouldUnwrap, hasNegentropy, } from "@welshman/app" import { @@ -46,7 +47,6 @@ import { COMMENT_FILTER, INDEXER_RELAYS, REACTION_KINDS, - canDecrypt, loadSettings, userMembership, defaultPubkeys, @@ -334,14 +334,14 @@ const syncDMs = () => { } // When pubkey changes, re-sync - const unsubscribePubkey = derived([pubkey, canDecrypt], identity).subscribe( - ([$pubkey, $canDecrypt]) => { + const unsubscribePubkey = derived([pubkey, shouldUnwrap], identity).subscribe( + ([$pubkey, $shouldUnwrap]) => { if ($pubkey !== currentPubkey) { unsubscribeAll() } // If we have a pubkey, refresh our user's relay selections then sync our subscriptions - if ($pubkey && $canDecrypt) { + if ($pubkey && $shouldUnwrap) { loadRelaySelections($pubkey) .then(() => loadInboxRelaySelections($pubkey)) .then($l => subscribeAll($pubkey, getRelayTagValues(getListTags($l)))) @@ -352,11 +352,12 @@ const syncDMs = () => { ) // When user inbox relays change, update synchronization - const unsubscribeSelections = userInboxRelaySelections.subscribe($l => { + const unsubscribeSelections = userInboxRelaySelections.subscribe($userInboxRelaySelections => { const $pubkey = pubkey.get() + const $shouldUnwrap = shouldUnwrap.get() - if ($pubkey && $l) { - subscribeAll($pubkey, getRelayTagValues(getListTags($l))) + if ($pubkey && $shouldUnwrap) { + subscribeAll($pubkey, getRelayTagValues(getListTags($userInboxRelaySelections))) } }) diff --git a/src/app/util/routes.ts b/src/app/util/routes.ts index 5ad0ac8a..18a201d6 100644 --- a/src/app/util/routes.ts +++ b/src/app/util/routes.ts @@ -17,7 +17,6 @@ import { getPubkeyTagValues, } from "@welshman/util" import { - ensureUnwrapped, makeChatId, entityLink, decodeRelay, @@ -85,20 +84,16 @@ export const getPrimaryNavItemIndex = ($page: Page) => { } export const goToEvent = async (event: TrustedEvent, options: Record = {}) => { - const unwrapped = await ensureUnwrapped(event) + const urls = Array.from(tracker.getRelays(event.id)) + const path = await getEventPath(event, urls) - if (unwrapped) { - const urls = Array.from(tracker.getRelays(unwrapped.id)) - const path = await getEventPath(unwrapped, urls) + if (path.includes("://")) { + window.open(path) + } else { + goto(path, options) - if (path.includes("://")) { - window.open(path) - } else { - goto(path, options) - - await sleep(300) - await scrollToEvent(unwrapped.id) - } + await sleep(300) + await scrollToEvent(event.id) } } diff --git a/src/app/util/storage.ts b/src/app/util/storage.ts index 49cc8c01..9499db3e 100644 --- a/src/app/util/storage.ts +++ b/src/app/util/storage.ts @@ -33,7 +33,7 @@ import { verifiedSymbol, } from "@welshman/util" import type {Zapper, TrustedEvent} from "@welshman/util" -import type {RepositoryUpdate} from "@welshman/relay" +import type {RepositoryUpdate, WrapItem} from "@welshman/net" import type {Handle, Relay} from "@welshman/app" import { plaintext, @@ -44,6 +44,7 @@ import { zappers, onZapper, onHandle, + wrapManager, } from "@welshman/app" import {Collection} from "@lib/storage" @@ -258,6 +259,28 @@ const syncPlaintext = async () => { }) } +const syncWrapManager = async () => { + const collection = new Collection({ + table: "wraps", + shards: Array.from("0123456789abcdef"), + getShard: (item: WrapItem) => last(hash(item.id)), + }) + + wrapManager.load(await collection.get()) + + const addOne = batch(3000, (wrapItems: WrapItem[]) => collection.add(wrapItems)) + + const updateAll = throttle(3000, () => collection.set(wrapManager.dump())) + + wrapManager.on("add", addOne) + wrapManager.on("remove", updateAll) + + return () => { + wrapManager.off("add", addOne) + wrapManager.off("remove", updateAll) + } +} + export const syncDataStores = () => Promise.all([ syncEvents(), @@ -267,4 +290,5 @@ export const syncDataStores = () => syncZappers(), syncFreshness(), syncPlaintext(), + syncWrapManager(), ]) diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 38530683..059df604 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -8,10 +8,9 @@ import {App, type URLOpenListenerEvent} from "@capacitor/app" import {dev} from "$app/environment" import {goto} from "$app/navigation" - import {sync, localStorageProvider} from "@welshman/store" - import {assoc, call, defer, dissoc, on, sleep, spec, TaskQueue} from "@welshman/lib" - import type {TrustedEvent, StampedEvent} from "@welshman/util" - import {WRAP} from "@welshman/util" + import {sync} from "@welshman/store" + import {assoc, call, defer, dissoc, on, sleep, spec} from "@welshman/lib" + import type {StampedEvent} from "@welshman/util" import {Nip46Broker, makeSecret} from "@welshman/signer" import type {Socket, RelayMessage, ClientMessage} from "@welshman/net" import { @@ -33,6 +32,7 @@ signer, signerLog, dropSession, + shouldUnwrap, loginWithNip01, loginWithNip46, loadRelaySelections, @@ -55,8 +55,6 @@ import { userSettingsValues, relaysPendingTrust, - ensureUnwrapped, - canDecrypt, getSetting, relaysMostlyRestricted, } from "@app/core/state" @@ -106,44 +104,6 @@ ...notifications, }) - // migrate from localStorage to capacitor Preferences storage if needed - const runMigration = async () => { - const isSome = (item: any) => { - return item !== undefined && item !== null && item !== "" - } - - const localStoragePubKey = await localStorageProvider.get("pubkey") - if (isSome(localStoragePubKey)) { - await preferencesStorageProvider.set("pubkey", localStoragePubKey) - localStorage.removeItem("pubkey") - } - - const localStorageSessions = await localStorageProvider.get("sessions") - if (isSome(localStorageSessions)) { - await preferencesStorageProvider.set("sessions", localStorageSessions) - localStorage.removeItem("sessions") - } - - const localStorageCanDecrypt = await localStorageProvider.get("canDecrypt") - if (isSome(localStorageCanDecrypt)) { - await preferencesStorageProvider.set("canDecrypt", localStorageCanDecrypt) - localStorage.removeItem("canDecrypt") - } - - const localStorageChecked = await localStorageProvider.get("checked") - if (isSome(localStorageChecked)) { - await preferencesStorageProvider.set("checked", localStorageChecked) - localStorage.removeItem("checked") - } - - const localStorageTheme = await localStorageProvider.get("theme") - if (isSome(localStorageTheme)) { - await preferencesStorageProvider.set("theme", localStorageTheme) - localStorage.removeItem("theme") - } - } - await runMigration() - // Listen for navigation messages from service worker navigator.serviceWorker?.addEventListener("message", event => { if (event.data && event.data.type === "NAVIGATE") { @@ -217,16 +177,9 @@ } }) - // Unwrap gift wraps as they come in, but throttled - const unwrapper = new TaskQueue({batchSize: 10, processItem: ensureUnwrapped}) - repository.on("update", ({added}) => { for (const event of added) { loadRelaySelections(event.pubkey) - - if ($canDecrypt && event.kind === WRAP) { - unwrapper.push(event) - } } }) @@ -244,6 +197,13 @@ storage: preferencesStorageProvider, }) + // Sync shouldUnwrap + await sync({ + key: "shouldUnwrap", + store: shouldUnwrap, + storage: preferencesStorageProvider, + }) + // Sync application data (relay, events, etc) await storage.syncDataStores() diff --git a/src/routes/[bech32]/+page.svelte b/src/routes/[bech32]/+page.svelte index d7597dc6..af15a035 100644 --- a/src/routes/[bech32]/+page.svelte +++ b/src/routes/[bech32]/+page.svelte @@ -4,8 +4,7 @@ import type {MakeNonOptional} from "@welshman/lib" import type {TrustedEvent} from "@welshman/util" import {Address, getIdFilters} from "@welshman/util" - import {LOCAL_RELAY_URL} from "@welshman/relay" - import {load} from "@welshman/net" + import {load, LOCAL_RELAY_URL} from "@welshman/net" import {page} from "$app/stores" import {goto} from "$app/navigation" import Spinner from "@lib/components/Spinner.svelte" diff --git a/src/routes/home/+page.svelte b/src/routes/home/+page.svelte index 3bcd3f94..55271657 100644 --- a/src/routes/home/+page.svelte +++ b/src/routes/home/+page.svelte @@ -1,6 +1,7 @@