From 3e0cd807c2986d076f1ffd4ce6e5cdb09750b07f Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Tue, 4 Feb 2025 11:10:07 -0600 Subject: [PATCH] remove old batch loaders --- package.json | 4 +- pnpm-lock.yaml | 366 +++++++++--------- src/classes/batch-identifier-loader.ts | 148 ------- src/classes/batch-relation-loader.ts | 148 ------- src/classes/persistent-subscription.ts | 84 ---- src/classes/relay.ts | 6 - src/components/markdown/wiki-link.tsx | 13 +- src/components/zap/event-zap-button.tsx | 7 +- src/components/zap/event-zap-icon-button.tsx | 4 +- src/helpers/notification.ts | 1 - src/hooks/use-channel-metadata.ts | 10 +- src/hooks/use-event-reactions.ts | 12 +- src/hooks/use-event-zaps.ts | 10 +- src/hooks/use-wiki-pages.ts | 21 + src/queries/wiki-pages.ts | 10 + src/queries/wiki-topics.ts | 28 ++ src/services/channel-metadata-loader.ts | 19 + src/services/channel-metadata.ts | 157 -------- src/services/debug-api.ts | 2 +- src/services/dictionary.ts | 91 ----- src/services/event-reactions-loader.ts | 38 ++ src/services/event-reactions.ts | 41 -- src/services/event-zaps-loader.ts | 34 ++ src/services/event-zaps.ts | 42 -- src/services/wiki-page-loader.ts | 15 + .../emojis/components/emoji-pack-card.tsx | 4 +- .../goals/components/goal-zap-button.tsx | 4 +- src/views/settings/mailboxes/index.tsx | 2 +- src/views/settings/relays/index.tsx | 3 +- src/views/settings/relays/relay-control.tsx | 3 +- src/views/wiki/create.tsx | 2 - src/views/wiki/edit.tsx | 2 - src/views/wiki/index.tsx | 54 ++- src/views/wiki/page.tsx | 7 +- src/views/wiki/search.tsx | 10 +- src/views/wiki/topic.tsx | 8 +- 36 files changed, 417 insertions(+), 993 deletions(-) delete mode 100644 src/classes/batch-identifier-loader.ts delete mode 100644 src/classes/batch-relation-loader.ts delete mode 100644 src/classes/persistent-subscription.ts delete mode 100644 src/classes/relay.ts create mode 100644 src/hooks/use-wiki-pages.ts create mode 100644 src/queries/wiki-pages.ts create mode 100644 src/queries/wiki-topics.ts create mode 100644 src/services/channel-metadata-loader.ts delete mode 100644 src/services/channel-metadata.ts delete mode 100644 src/services/dictionary.ts create mode 100644 src/services/event-reactions-loader.ts delete mode 100644 src/services/event-reactions.ts create mode 100644 src/services/event-zaps-loader.ts delete mode 100644 src/services/event-zaps.ts create mode 100644 src/services/wiki-page-loader.ts diff --git a/package.json b/package.json index 3eef4e185..7e45166ce 100644 --- a/package.json +++ b/package.json @@ -45,8 +45,8 @@ "@satellite-earth/core": "^0.5.0", "@scure/base": "^1.2.4", "@snort/worker-relay": "^1.3.1", - "@uiw/codemirror-theme-github": "^4.23.7", - "@uiw/react-codemirror": "^4.23.7", + "@uiw/codemirror-theme-github": "^4.23.8", + "@uiw/react-codemirror": "^4.23.8", "@webscopeio/react-textarea-autocomplete": "^4.9.2", "ansi-to-html": "^0.7.2", "applesauce-accounts": "next", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bba0c3cd3..c41fc921b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -91,11 +91,11 @@ importers: specifier: ^1.3.1 version: 1.3.1 '@uiw/codemirror-theme-github': - specifier: ^4.23.7 - version: 4.23.7(@codemirror/language@6.10.8)(@codemirror/state@6.5.2)(@codemirror/view@6.36.2) + specifier: ^4.23.8 + version: 4.23.8(@codemirror/language@6.10.8)(@codemirror/state@6.5.2)(@codemirror/view@6.36.2) '@uiw/react-codemirror': - specifier: ^4.23.7 - version: 4.23.7(@babel/runtime@7.26.7)(@codemirror/autocomplete@6.18.4)(@codemirror/language@6.10.8)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.8)(@codemirror/state@6.5.2)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.36.2)(codemirror@6.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + specifier: ^4.23.8 + version: 4.23.8(@babel/runtime@7.26.7)(@codemirror/autocomplete@6.18.4)(@codemirror/language@6.10.8)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.8)(@codemirror/state@6.5.2)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.36.2)(codemirror@6.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@webscopeio/react-textarea-autocomplete': specifier: ^4.9.2 version: 4.9.2(prop-types@15.8.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) @@ -104,28 +104,28 @@ importers: version: 0.7.2 applesauce-accounts: specifier: next - version: 0.0.0-next-20250203215539(typescript@5.7.3) + version: 0.0.0-next-20250204170704(typescript@5.7.3) applesauce-content: specifier: next - version: 0.0.0-next-20250203215539(typescript@5.7.3) + version: 0.0.0-next-20250204170704(typescript@5.7.3) applesauce-core: specifier: next - version: 0.0.0-next-20250203215539(typescript@5.7.3) + version: 0.0.0-next-20250204170704(typescript@5.7.3) applesauce-factory: specifier: next - version: 0.0.0-next-20250203215539(typescript@5.7.3) + version: 0.0.0-next-20250204170704(typescript@5.7.3) applesauce-loaders: specifier: next - version: 0.0.0-next-20250203215539(typescript@5.7.3) + version: 0.0.0-next-20250204170704(typescript@5.7.3) applesauce-net: specifier: ^0.10.0 version: 0.10.0(typescript@5.7.3) applesauce-react: specifier: next - version: 0.0.0-next-20250203215539(typescript@5.7.3) + version: 0.0.0-next-20250204170704(typescript@5.7.3) applesauce-signers: specifier: next - version: 0.0.0-next-20250203215539(typescript@5.7.3) + version: 0.0.0-next-20250204170704(typescript@5.7.3) bech32: specifier: ^2.0.0 version: 2.0.0 @@ -269,7 +269,7 @@ importers: version: 9.0.3(@types/react@18.3.18)(react@19.0.0) react-mosaic-component: specifier: ^6.1.1 - version: 6.1.1(@types/node@22.13.0)(@types/react@18.3.18)(dnd-core@16.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + version: 6.1.1(@types/node@22.13.1)(@types/react@18.3.18)(dnd-core@16.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) react-photo-album: specifier: ^2.4.1 version: 2.4.1(react@19.0.0) @@ -357,7 +357,7 @@ importers: version: 6.0.2(@capacitor/core@6.2.0) '@capacitor/assets': specifier: ^3.0.5 - version: 3.0.5(@types/node@22.13.0)(typescript@5.7.3) + version: 3.0.5(@types/node@22.13.1)(typescript@5.7.3) '@capacitor/cli': specifier: ^6.2.0 version: 6.2.0 @@ -426,7 +426,7 @@ importers: version: 4.7.5 '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.3.4(vite@5.4.14(@types/node@22.13.0)(terser@5.37.0)) + version: 4.3.4(vite@5.4.14(@types/node@22.13.1)(terser@5.37.0)) camelcase: specifier: ^8.0.0 version: 8.0.0 @@ -441,13 +441,13 @@ importers: version: 5.7.3 vite: specifier: ^5.4.14 - version: 5.4.14(@types/node@22.13.0)(terser@5.37.0) + version: 5.4.14(@types/node@22.13.1)(terser@5.37.0) vite-plugin-pwa: specifier: ^0.21.1 - version: 0.21.1(vite@5.4.14(@types/node@22.13.0)(terser@5.37.0))(workbox-build@7.3.0(@types/babel__core@7.20.5))(workbox-window@7.3.0) + version: 0.21.1(vite@5.4.14(@types/node@22.13.1)(terser@5.37.0))(workbox-build@7.3.0(@types/babel__core@7.20.5))(workbox-window@7.3.0) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.7.3)(vite@5.4.14(@types/node@22.13.0)(terser@5.37.0)) + version: 5.1.4(typescript@5.7.3)(vite@5.4.14(@types/node@22.13.1)(terser@5.37.0)) workbox-build: specifier: ^7.3.0 version: 7.3.0(@types/babel__core@7.20.5) @@ -1720,98 +1720,98 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.34.1': - resolution: {integrity: sha512-kwctwVlswSEsr4ljpmxKrRKp1eG1v2NAhlzFzDf1x1OdYaMjBYjDCbHkzWm57ZXzTwqn8stMXgROrnMw8dJK3w==} + '@rollup/rollup-android-arm-eabi@4.34.2': + resolution: {integrity: sha512-6Fyg9yQbwJR+ykVdT9sid1oc2ewejS6h4wzQltmJfSW53N60G/ah9pngXGANdy9/aaE/TcUFpWosdm7JXS1WTQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.34.1': - resolution: {integrity: sha512-4H5ZtZitBPlbPsTv6HBB8zh1g5d0T8TzCmpndQdqq20Ugle/nroOyDMf9p7f88Gsu8vBLU78/cuh8FYHZqdXxw==} + '@rollup/rollup-android-arm64@4.34.2': + resolution: {integrity: sha512-K5GfWe+vtQ3kyEbihrimM38UgX57UqHp+oME7X/EX9Im6suwZfa7Hsr8AtzbJvukTpwMGs+4s29YMSO3rwWtsw==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.34.1': - resolution: {integrity: sha512-f2AJ7Qwx9z25hikXvg+asco8Sfuc5NCLg8rmqQBIOUoWys5sb/ZX9RkMZDPdnnDevXAMJA5AWLnRBmgdXGEUiA==} + '@rollup/rollup-darwin-arm64@4.34.2': + resolution: {integrity: sha512-PSN58XG/V/tzqDb9kDGutUruycgylMlUE59f40ny6QIRNsTEIZsrNQTJKUN2keMMSmlzgunMFqyaGLmly39sug==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.34.1': - resolution: {integrity: sha512-+/2JBrRfISCsWE4aEFXxd+7k9nWGXA8+wh7ZUHn/u8UDXOU9LN+QYKKhd57sIn6WRcorOnlqPMYFIwie/OHXWw==} + '@rollup/rollup-darwin-x64@4.34.2': + resolution: {integrity: sha512-gQhK788rQJm9pzmXyfBB84VHViDERhAhzGafw+E5mUpnGKuxZGkMVDa3wgDFKT6ukLC5V7QTifzsUKdNVxp5qQ==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.34.1': - resolution: {integrity: sha512-SUeB0pYjIXwT2vfAMQ7E4ERPq9VGRrPR7Z+S4AMssah5EHIilYqjWQoTn5dkDtuIJUSTs8H+C9dwoEcg3b0sCA==} + '@rollup/rollup-freebsd-arm64@4.34.2': + resolution: {integrity: sha512-eiaHgQwGPpxLC3+zTAcdKl4VsBl3r0AiJOd1Um/ArEzAjN/dbPK1nROHrVkdnoE6p7Svvn04w3f/jEZSTVHunA==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.34.1': - resolution: {integrity: sha512-L3T66wAZiB/ooiPbxz0s6JEX6Sr2+HfgPSK+LMuZkaGZFAFCQAHiP3dbyqovYdNaiUXcl9TlgnIbcsIicAnOZg==} + '@rollup/rollup-freebsd-x64@4.34.2': + resolution: {integrity: sha512-lhdiwQ+jf8pewYOTG4bag0Qd68Jn1v2gO1i0mTuiD+Qkt5vNfHVK/jrT7uVvycV8ZchlzXp5HDVmhpzjC6mh0g==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.34.1': - resolution: {integrity: sha512-UBXdQ4+ATARuFgsFrQ+tAsKvBi/Hly99aSVdeCUiHV9dRTTpMU7OrM3WXGys1l40wKVNiOl0QYY6cZQJ2xhKlQ==} + '@rollup/rollup-linux-arm-gnueabihf@4.34.2': + resolution: {integrity: sha512-lfqTpWjSvbgQP1vqGTXdv+/kxIznKXZlI109WkIFPbud41bjigjNmOAAKoazmRGx+k9e3rtIdbq2pQZPV1pMig==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.34.1': - resolution: {integrity: sha512-m/yfZ25HGdcCSwmopEJm00GP7xAUyVcBPjttGLRAqZ60X/bB4Qn6gP7XTwCIU6bITeKmIhhwZ4AMh2XLro+4+w==} + '@rollup/rollup-linux-arm-musleabihf@4.34.2': + resolution: {integrity: sha512-RGjqULqIurqqv+NJTyuPgdZhka8ImMLB32YwUle2BPTDqDoXNgwFjdjQC59FbSk08z0IqlRJjrJ0AvDQ5W5lpw==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.34.1': - resolution: {integrity: sha512-Wy+cUmFuvziNL9qWRRzboNprqSQ/n38orbjRvd6byYWridp5TJ3CD+0+HUsbcWVSNz9bxkDUkyASGP0zS7GAvg==} + '@rollup/rollup-linux-arm64-gnu@4.34.2': + resolution: {integrity: sha512-ZvkPiheyXtXlFqHpsdgscx+tZ7hoR59vOettvArinEspq5fxSDSgfF+L5wqqJ9R4t+n53nyn0sKxeXlik7AY9Q==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.34.1': - resolution: {integrity: sha512-CQ3MAGgiFmQW5XJX5W3wnxOBxKwFlUAgSXFA2SwgVRjrIiVt5LHfcQLeNSHKq5OEZwv+VCBwlD1+YKCjDG8cpg==} + '@rollup/rollup-linux-arm64-musl@4.34.2': + resolution: {integrity: sha512-UlFk+E46TZEoxD9ufLKDBzfSG7Ki03fo6hsNRRRHF+KuvNZ5vd1RRVQm8YZlGsjcJG8R252XFK0xNPay+4WV7w==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loongarch64-gnu@4.34.1': - resolution: {integrity: sha512-rSzb1TsY4lSwH811cYC3OC2O2mzNMhM13vcnA7/0T6Mtreqr3/qs6WMDriMRs8yvHDI54qxHgOk8EV5YRAHFbw==} + '@rollup/rollup-linux-loongarch64-gnu@4.34.2': + resolution: {integrity: sha512-hJhfsD9ykx59jZuuoQgYT1GEcNNi3RCoEmbo5OGfG8RlHOiVS7iVNev9rhLKh7UBYq409f4uEw0cclTXx8nh8Q==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.34.1': - resolution: {integrity: sha512-fwr0n6NS0pG3QxxlqVYpfiY64Fd1Dqd8Cecje4ILAV01ROMp4aEdCj5ssHjRY3UwU7RJmeWd5fi89DBqMaTawg==} + '@rollup/rollup-linux-powerpc64le-gnu@4.34.2': + resolution: {integrity: sha512-g/O5IpgtrQqPegvqopvmdCF9vneLE7eqYfdPWW8yjPS8f63DNam3U4ARL1PNNB64XHZDHKpvO2Giftf43puB8Q==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.34.1': - resolution: {integrity: sha512-4uJb9qz7+Z/yUp5RPxDGGGUcoh0PnKF33QyWgEZ3X/GocpWb6Mb+skDh59FEt5d8+Skxqs9mng6Swa6B2AmQZg==} + '@rollup/rollup-linux-riscv64-gnu@4.34.2': + resolution: {integrity: sha512-bSQijDC96M6PuooOuXHpvXUYiIwsnDmqGU8+br2U7iPoykNi9JtMUpN7K6xml29e0evK0/g0D1qbAUzWZFHY5Q==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.34.1': - resolution: {integrity: sha512-QlIo8ndocWBEnfmkYqj8vVtIUpIqJjfqKggjy7IdUncnt8BGixte1wDON7NJEvLg3Kzvqxtbo8tk+U1acYEBlw==} + '@rollup/rollup-linux-s390x-gnu@4.34.2': + resolution: {integrity: sha512-49TtdeVAsdRuiUHXPrFVucaP4SivazetGUVH8CIxVsNsaPHV4PFkpLmH9LeqU/R4Nbgky9lzX5Xe1NrzLyraVA==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.34.1': - resolution: {integrity: sha512-hzpleiKtq14GWjz3ahWvJXgU1DQC9DteiwcsY4HgqUJUGxZThlL66MotdUEK9zEo0PK/2ADeZGM9LIondE302A==} + '@rollup/rollup-linux-x64-gnu@4.34.2': + resolution: {integrity: sha512-j+jFdfOycLIQ7FWKka9Zd3qvsIyugg5LeZuHF6kFlXo6MSOc6R1w37YUVy8VpAKd81LMWGi5g9J25P09M0SSIw==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.34.1': - resolution: {integrity: sha512-jqtKrO715hDlvUcEsPn55tZt2TEiBvBtCMkUuU0R6fO/WPT7lO9AONjPbd8II7/asSiNVQHCMn4OLGigSuxVQA==} + '@rollup/rollup-linux-x64-musl@4.34.2': + resolution: {integrity: sha512-aDPHyM/D2SpXfSNCVWCxyHmOqN9qb7SWkY1+vaXqMNMXslZYnwh9V/UCudl6psyG0v6Ukj7pXanIpfZwCOEMUg==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.34.1': - resolution: {integrity: sha512-RnHy7yFf2Wz8Jj1+h8klB93N0NHNHXFhNwAmiy9zJdpY7DE01VbEVtPdrK1kkILeIbHGRJjvfBDBhnxBr8kD4g==} + '@rollup/rollup-win32-arm64-msvc@4.34.2': + resolution: {integrity: sha512-LQRkCyUBnAo7r8dbEdtNU08EKLCJMgAk2oP5H3R7BnUlKLqgR3dUjrLBVirmc1RK6U6qhtDw29Dimeer8d5hzQ==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.34.1': - resolution: {integrity: sha512-i7aT5HdiZIcd7quhzvwQ2oAuX7zPYrYfkrd1QFfs28Po/i0q6kas/oRrzGlDhAEyug+1UfUtkWdmoVlLJj5x9Q==} + '@rollup/rollup-win32-ia32-msvc@4.34.2': + resolution: {integrity: sha512-wt8OhpQUi6JuPFkm1wbVi1BByeag87LDFzeKSXzIdGcX4bMLqORTtKxLoCbV57BHYNSUSOKlSL4BYYUghainYA==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.34.1': - resolution: {integrity: sha512-k3MVFD9Oq+laHkw2N2v7ILgoa9017ZMF/inTtHzyTVZjYs9cSH18sdyAf6spBAJIGwJ5UaC7et2ZH1WCdlhkMw==} + '@rollup/rollup-win32-x64-msvc@4.34.2': + resolution: {integrity: sha512-rUrqINax0TvrPBXrFKg0YbQx18NpPN3NNrgmaao9xRNbTwek7lOXObhx8tQy8gelmQ/gLaGy1WptpU2eKJZImg==} cpu: [x64] os: [win32] @@ -2005,8 +2005,8 @@ packages: '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - '@types/node@22.13.0': - resolution: {integrity: sha512-ClIbNe36lawluuvq3+YYhnIN2CELi+6q8NpnM7PYp4hBn/TatfboPgVSm2rwKRfnV2M+Ty9GWDFI64KEe+kysA==} + '@types/node@22.13.1': + resolution: {integrity: sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -2061,8 +2061,8 @@ packages: '@types/webxr@0.5.21': resolution: {integrity: sha512-geZIAtLzjGmgY2JUi6VxXdCrTb99A7yP49lxLr2Nm/uIK0PkkxcEi4OGhoGDO4pxCf3JwGz2GiJL2Ej4K2bKaA==} - '@uiw/codemirror-extensions-basic-setup@4.23.7': - resolution: {integrity: sha512-9/2EUa1Lck4kFKkR2BkxlZPpgD/EWuKHnOlysf1yHKZGraaZmZEaUw+utDK4QcuJc8Iz097vsLz4f4th5EU27g==} + '@uiw/codemirror-extensions-basic-setup@4.23.8': + resolution: {integrity: sha512-XJR/8AEVcE7ufy1BhW2nCN9qSVDYEdCtYLfvhaMwl6Q3qcaYYCGE2K5QbFCy7LsdP/3uZKvc1OskuqatoOPdhQ==} peerDependencies: '@codemirror/autocomplete': '>=6.0.0' '@codemirror/commands': '>=6.0.0' @@ -2072,18 +2072,18 @@ packages: '@codemirror/state': '>=6.0.0' '@codemirror/view': '>=6.0.0' - '@uiw/codemirror-theme-github@4.23.7': - resolution: {integrity: sha512-r9SstBZD7Ow1sQ8F0EpsRGx9b11K552M2FayvyLWTkal64YJmQMKW0S2KcWykgCMKLWhmDFi7LX+h8cg6nek8g==} + '@uiw/codemirror-theme-github@4.23.8': + resolution: {integrity: sha512-+LVpFdF6RMjDsTo+HkJYBWkEGy2AgcZJVCDku+yWme/shEtV/FulpGwHeb+NrArAFNyXjUXSVMPhLq3+syOLhw==} - '@uiw/codemirror-themes@4.23.7': - resolution: {integrity: sha512-UNf1XOx1hG9OmJnrtT86PxKcdcwhaNhbrcD+nsk8WxRJ3n5c8nH6euDvgVPdVLPwbizsaQcZTILACgA/FjRpVg==} + '@uiw/codemirror-themes@4.23.8': + resolution: {integrity: sha512-PZmJBZxWMuZ48p/2D5aRPl8zTlBq1d/+NeRqyyH6P6k6yWDF6h71m0Dt+fjslgPE7KmWXux2hbejXXXoRLZO9Q==} peerDependencies: '@codemirror/language': '>=6.0.0' '@codemirror/state': '>=6.0.0' '@codemirror/view': '>=6.0.0' - '@uiw/react-codemirror@4.23.7': - resolution: {integrity: sha512-Nh/0P6W+kWta+ARp9YpnKPD9ick5teEnwmtNoPQnyd6NPv0EQP3Ui4YmRVNj1nkUEo+QjrAUaEfcejJ2up/HZA==} + '@uiw/react-codemirror@4.23.8': + resolution: {integrity: sha512-/NA5Pj4MmXkLSlmlUm4yfEmRLntrNq5TkQKBSINn7TukXQ4fc+C6Bk0U60Qa4rkvCSgwzZdQ2exyP0t0+2GtqA==} peerDependencies: '@babel/runtime': '>=7.11.0' '@codemirror/state': '>=6.0.0' @@ -2192,32 +2192,32 @@ packages: engines: {node: '>=8.0.0'} hasBin: true - applesauce-accounts@0.0.0-next-20250203215539: - resolution: {integrity: sha512-PuxwOkGC1wZrfVy585JTE6Eo7vnu9uN5Dt7rEb7PC/NFntv1RFSNfKOrXlEqzltiIo6StErN2ypFz2Tvtj20Eg==} + applesauce-accounts@0.0.0-next-20250204170704: + resolution: {integrity: sha512-y80D4PfoT9gkd+TtUExeQdiq5grlchUbsdjRfmEG3JuAopTCzdgEAa2L7wfLT4DmsUwBvO8ISAm+zKRZ+GI/NQ==} - applesauce-content@0.0.0-next-20250203215539: - resolution: {integrity: sha512-B7lNI/wtB1JZ20h6keFwMscP/ClVuyCC0e/fI4fhtv1RzPbr+GMrHD+liIJZnIqodptD/li3B8ixH41Ux20JlA==} + applesauce-content@0.0.0-next-20250204170704: + resolution: {integrity: sha512-hY6H2v6wSa/rzq6OCnjSL+y2Lv4/AR5z7irdqbSuzhSElslm78pqUPjsFlnVt7nu5K+1cAv0B/Ib/2yhaacgYw==} - applesauce-core@0.0.0-next-20250203215539: - resolution: {integrity: sha512-0Io5Vu1tXYm0ddtaK1DyboxrUblaKhEfYs/TIe9WhcGjBcHBNJgyqoAlZ9YNJ6TN6VX6CmyVAq779KH3IWtWgQ==} + applesauce-core@0.0.0-next-20250204170704: + resolution: {integrity: sha512-TcvcmFHYmduVFZsR+87/cPldZEUz/uafyHIMGPdM8Go4TWg/SMB2tRILdDuUrEjgIgtUVskAGlPF4uIoiH/bEA==} applesauce-core@0.10.0: resolution: {integrity: sha512-QMhUh4FIARcqY5soCB4Z8DIu+py0rYb28IgWT4gP9DLBGpDrY8lStXk7W1/46TLjEH97y0hbiXFK7kMCZ31oOQ==} - applesauce-factory@0.0.0-next-20250203215539: - resolution: {integrity: sha512-1jMAzucp8as7bIyOHKwCHGQnkVuOmlaxoDohMth6nVhXclLBUp7pXzHDIwfqQndWWMCMq5TcPQAfYmlVsFQgAQ==} + applesauce-factory@0.0.0-next-20250204170704: + resolution: {integrity: sha512-5lA2aWaKibpt3jNQkNSJJWjopk9CNSWJzDOiM156fBG2Qhe8GzdN7fBiCPlm+iPCRogGyDCAHabSS+JnZB6LTA==} - applesauce-loaders@0.0.0-next-20250203215539: - resolution: {integrity: sha512-ZhzJnnLLigJ/WGXtm3oeQSC3MwGpII92FmO0/Rbrd4vceOOx7b9hEbseDTtfYUtY8e/abahYuKqLH0d8QQFtiA==} + applesauce-loaders@0.0.0-next-20250204170704: + resolution: {integrity: sha512-7mYbE2qJA58A5cfdnpfQbdkohRvg6uhct+QieLlGOc/mNEmMxpA10GP9Wu7FprokWdCJEs0Pn7q7pobsJgPpKw==} applesauce-net@0.10.0: resolution: {integrity: sha512-ZsAs/MkeGHiPZ2/a8lwP8lx/Eh+5Dot0qG4BLTAqjg4emP/RsiqW+hyc6v6QcVbdvuR0+hP1gka3+wWtiy/cTA==} - applesauce-react@0.0.0-next-20250203215539: - resolution: {integrity: sha512-KVizXnEkyjHJuVyl11oUArKAIk760U9olSH0hSSkhvPmvzmfUKFvNmugaIeyarr5FJA1qoebkrpsYzbIkvXnMA==} + applesauce-react@0.0.0-next-20250204170704: + resolution: {integrity: sha512-rHA9dO4k5UUeZESMtsrD0oGk7q26AFlpjLjWHBDKiFxRPsr5MusoKyW8X2fZOrN1fyNhgHD+lhCtesTWVUOU7Q==} - applesauce-signers@0.0.0-next-20250203215539: - resolution: {integrity: sha512-o2xftPZuBDLWobAGPdCxWkAGY8F7NqmS85Dra8sVjSB8ZqFOIjII+2iBcqKAk5ytU23FAH3TzZXt1/11w0dGgQ==} + applesauce-signers@0.0.0-next-20250204170704: + resolution: {integrity: sha512-SZUA5uZQChBReIRj34t1y4ZQnV8LR96oHyMelnhAPFJXZT57wUfMJB7Z6KVkxbMHwo2SYUP6qi4MpkC6KQyGng==} arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} @@ -2454,8 +2454,8 @@ packages: resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} engines: {node: '>=16'} - caniuse-lite@1.0.30001696: - resolution: {integrity: sha512-pDCPkvzfa39ehJtJ+OwGT/2yvT2SbjfHhiIW2LWOAcMQ7BzwxT/XuyUp4OTOd0XFWA6BKw0JalnBHgSi5DGJBQ==} + caniuse-lite@1.0.30001697: + resolution: {integrity: sha512-GwNPlWJin8E+d7Gxq96jxM6w0w+VFeyyXRsjU58emtkYqnbwHqXm5uT2uCmO0RQE9htWknOP4xtBlLmM/gWxvQ==} canvas-color-tracker@1.3.1: resolution: {integrity: sha512-eNycxGS7oQ3IS/9QQY41f/aQjiO9Y/MtedhCgSdsbLSxC9EyUD8L3ehl/Q3Kfmvt8um79S45PBV+5Rxm5ztdSw==} @@ -3033,8 +3033,8 @@ packages: engines: {node: '>=0.10.0'} hasBin: true - electron-to-chromium@1.5.90: - resolution: {integrity: sha512-C3PN4aydfW91Natdyd449Kw+BzhLmof6tzy5W1pFC5SpQxVXT+oyiyOG9AgYYSN9OdA/ik3YkCrpwqI8ug5Tug==} + electron-to-chromium@1.5.91: + resolution: {integrity: sha512-sNSHHyq048PFmZY4S90ax61q+gLCs0X0YmcOII9wG9S2XwbVr+h4VW2wWhnbp/Eys3cCwTxVF292W3qPaxIapQ==} elementtree@0.1.7: resolution: {integrity: sha512-wkgGT6kugeQk/P6VZ/f4T+4HB41BVgNBq5CDIZVbQ02nvTVqAiVTbskxxu3eA/X96lMlfYOwnLQpN2v5E1zDEg==} @@ -3807,8 +3807,8 @@ packages: resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} engines: {node: '>= 0.4'} - is-weakref@1.1.0: - resolution: {integrity: sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==} + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} engines: {node: '>= 0.4'} is-weakset@2.0.4: @@ -5135,8 +5135,8 @@ packages: engines: {node: '>=10.0.0'} hasBin: true - rollup@4.34.1: - resolution: {integrity: sha512-iYZ/+PcdLYSGfH3S+dGahlW/RWmsqDhLgj1BT9DH/xXJ0ggZN7xkdP9wipPNjjNLczI+fmMLmTB9pye+d2r4GQ==} + rollup@4.34.2: + resolution: {integrity: sha512-sBDUoxZEaqLu9QeNalL8v3jw6WjPku4wfZGyTU7l7m1oC+rpRihXc/n/H+4148ZkGz5Xli8CHMns//fFGKvpIQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -6849,12 +6849,12 @@ snapshots: dependencies: '@capacitor/core': 6.2.0 - '@capacitor/assets@3.0.5(@types/node@22.13.0)(typescript@5.7.3)': + '@capacitor/assets@3.0.5(@types/node@22.13.1)(typescript@5.7.3)': dependencies: '@capacitor/cli': 5.7.8 '@ionic/utils-array': 2.1.6 '@ionic/utils-fs': 3.1.7 - '@trapezedev/project': 7.1.3(@types/node@22.13.0)(typescript@5.7.3) + '@trapezedev/project': 7.1.3(@types/node@22.13.1)(typescript@5.7.3) commander: 8.3.0 debug: 4.3.4 fs-extra: 10.1.0 @@ -7907,61 +7907,61 @@ snapshots: optionalDependencies: rollup: 2.79.2 - '@rollup/rollup-android-arm-eabi@4.34.1': + '@rollup/rollup-android-arm-eabi@4.34.2': optional: true - '@rollup/rollup-android-arm64@4.34.1': + '@rollup/rollup-android-arm64@4.34.2': optional: true - '@rollup/rollup-darwin-arm64@4.34.1': + '@rollup/rollup-darwin-arm64@4.34.2': optional: true - '@rollup/rollup-darwin-x64@4.34.1': + '@rollup/rollup-darwin-x64@4.34.2': optional: true - '@rollup/rollup-freebsd-arm64@4.34.1': + '@rollup/rollup-freebsd-arm64@4.34.2': optional: true - '@rollup/rollup-freebsd-x64@4.34.1': + '@rollup/rollup-freebsd-x64@4.34.2': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.34.1': + '@rollup/rollup-linux-arm-gnueabihf@4.34.2': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.34.1': + '@rollup/rollup-linux-arm-musleabihf@4.34.2': optional: true - '@rollup/rollup-linux-arm64-gnu@4.34.1': + '@rollup/rollup-linux-arm64-gnu@4.34.2': optional: true - '@rollup/rollup-linux-arm64-musl@4.34.1': + '@rollup/rollup-linux-arm64-musl@4.34.2': optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.34.1': + '@rollup/rollup-linux-loongarch64-gnu@4.34.2': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.34.1': + '@rollup/rollup-linux-powerpc64le-gnu@4.34.2': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.34.1': + '@rollup/rollup-linux-riscv64-gnu@4.34.2': optional: true - '@rollup/rollup-linux-s390x-gnu@4.34.1': + '@rollup/rollup-linux-s390x-gnu@4.34.2': optional: true - '@rollup/rollup-linux-x64-gnu@4.34.1': + '@rollup/rollup-linux-x64-gnu@4.34.2': optional: true - '@rollup/rollup-linux-x64-musl@4.34.1': + '@rollup/rollup-linux-x64-musl@4.34.2': optional: true - '@rollup/rollup-win32-arm64-msvc@4.34.1': + '@rollup/rollup-win32-arm64-msvc@4.34.2': optional: true - '@rollup/rollup-win32-ia32-msvc@4.34.1': + '@rollup/rollup-win32-ia32-msvc@4.34.2': optional: true - '@rollup/rollup-win32-x64-msvc@4.34.1': + '@rollup/rollup-win32-x64-msvc@4.34.2': optional: true '@sagold/json-pointer@5.1.2': {} @@ -8077,7 +8077,7 @@ snapshots: '@trapezedev/gradle-parse@7.1.3': {} - '@trapezedev/project@7.1.3(@types/node@22.13.0)(typescript@5.7.3)': + '@trapezedev/project@7.1.3(@types/node@22.13.1)(typescript@5.7.3)': dependencies: '@ionic/utils-fs': 3.1.7 '@ionic/utils-subprocess': 2.1.14 @@ -8099,7 +8099,7 @@ snapshots: replace: 1.2.2 tempy: 1.0.1 tmp: 0.2.3 - ts-node: 10.9.2(@types/node@22.13.0)(typescript@5.7.3) + ts-node: 10.9.2(@types/node@22.13.1)(typescript@5.7.3) xcode: 3.0.1 xml-js: 1.6.11 xpath: 0.0.32 @@ -8180,7 +8180,7 @@ snapshots: '@types/fs-extra@8.1.5': dependencies: - '@types/node': 22.13.0 + '@types/node': 22.13.1 '@types/geojson@7946.0.16': {} @@ -8232,7 +8232,7 @@ snapshots: '@types/node@12.20.55': {} - '@types/node@22.13.0': + '@types/node@22.13.1': dependencies: undici-types: 6.20.0 @@ -8286,7 +8286,7 @@ snapshots: '@types/webxr@0.5.21': {} - '@uiw/codemirror-extensions-basic-setup@4.23.7(@codemirror/autocomplete@6.18.4)(@codemirror/commands@6.8.0)(@codemirror/language@6.10.8)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.8)(@codemirror/state@6.5.2)(@codemirror/view@6.36.2)': + '@uiw/codemirror-extensions-basic-setup@4.23.8(@codemirror/autocomplete@6.18.4)(@codemirror/commands@6.8.0)(@codemirror/language@6.10.8)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.8)(@codemirror/state@6.5.2)(@codemirror/view@6.36.2)': dependencies: '@codemirror/autocomplete': 6.18.4 '@codemirror/commands': 6.8.0 @@ -8296,28 +8296,28 @@ snapshots: '@codemirror/state': 6.5.2 '@codemirror/view': 6.36.2 - '@uiw/codemirror-theme-github@4.23.7(@codemirror/language@6.10.8)(@codemirror/state@6.5.2)(@codemirror/view@6.36.2)': + '@uiw/codemirror-theme-github@4.23.8(@codemirror/language@6.10.8)(@codemirror/state@6.5.2)(@codemirror/view@6.36.2)': dependencies: - '@uiw/codemirror-themes': 4.23.7(@codemirror/language@6.10.8)(@codemirror/state@6.5.2)(@codemirror/view@6.36.2) + '@uiw/codemirror-themes': 4.23.8(@codemirror/language@6.10.8)(@codemirror/state@6.5.2)(@codemirror/view@6.36.2) transitivePeerDependencies: - '@codemirror/language' - '@codemirror/state' - '@codemirror/view' - '@uiw/codemirror-themes@4.23.7(@codemirror/language@6.10.8)(@codemirror/state@6.5.2)(@codemirror/view@6.36.2)': + '@uiw/codemirror-themes@4.23.8(@codemirror/language@6.10.8)(@codemirror/state@6.5.2)(@codemirror/view@6.36.2)': dependencies: '@codemirror/language': 6.10.8 '@codemirror/state': 6.5.2 '@codemirror/view': 6.36.2 - '@uiw/react-codemirror@4.23.7(@babel/runtime@7.26.7)(@codemirror/autocomplete@6.18.4)(@codemirror/language@6.10.8)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.8)(@codemirror/state@6.5.2)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.36.2)(codemirror@6.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@uiw/react-codemirror@4.23.8(@babel/runtime@7.26.7)(@codemirror/autocomplete@6.18.4)(@codemirror/language@6.10.8)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.8)(@codemirror/state@6.5.2)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.36.2)(codemirror@6.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@babel/runtime': 7.26.7 '@codemirror/commands': 6.8.0 '@codemirror/state': 6.5.2 '@codemirror/theme-one-dark': 6.1.2 '@codemirror/view': 6.36.2 - '@uiw/codemirror-extensions-basic-setup': 4.23.7(@codemirror/autocomplete@6.18.4)(@codemirror/commands@6.8.0)(@codemirror/language@6.10.8)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.8)(@codemirror/state@6.5.2)(@codemirror/view@6.36.2) + '@uiw/codemirror-extensions-basic-setup': 4.23.8(@codemirror/autocomplete@6.18.4)(@codemirror/commands@6.8.0)(@codemirror/language@6.10.8)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.8)(@codemirror/state@6.5.2)(@codemirror/view@6.36.2) codemirror: 6.0.1 react: 19.0.0 react-dom: 19.0.0(react@19.0.0) @@ -8329,14 +8329,14 @@ snapshots: '@ungap/structured-clone@1.3.0': {} - '@vitejs/plugin-react@4.3.4(vite@5.4.14(@types/node@22.13.0)(terser@5.37.0))': + '@vitejs/plugin-react@4.3.4(vite@5.4.14(@types/node@22.13.1)(terser@5.37.0))': dependencies: '@babel/core': 7.26.7 '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.7) '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.7) '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 5.4.14(@types/node@22.13.0)(terser@5.37.0) + vite: 5.4.14(@types/node@22.13.1)(terser@5.37.0) transitivePeerDependencies: - supports-color @@ -8423,10 +8423,10 @@ snapshots: dependencies: entities: 2.2.0 - applesauce-accounts@0.0.0-next-20250203215539(typescript@5.7.3): + applesauce-accounts@0.0.0-next-20250204170704(typescript@5.7.3): dependencies: '@noble/hashes': 1.7.1 - applesauce-signers: 0.0.0-next-20250203215539(typescript@5.7.3) + applesauce-signers: 0.0.0-next-20250204170704(typescript@5.7.3) nanoid: 5.0.9 nostr-tools: 2.10.4(typescript@5.7.3) rxjs: 7.8.1 @@ -8434,13 +8434,13 @@ snapshots: - supports-color - typescript - applesauce-content@0.0.0-next-20250203215539(typescript@5.7.3): + applesauce-content@0.0.0-next-20250204170704(typescript@5.7.3): dependencies: '@cashu/cashu-ts': 2.0.0-rc1 '@types/hast': 3.0.4 '@types/mdast': 4.0.4 '@types/unist': 3.0.3 - applesauce-core: 0.0.0-next-20250203215539(typescript@5.7.3) + applesauce-core: 0.0.0-next-20250204170704(typescript@5.7.3) mdast-util-find-and-replace: 3.0.2 nostr-tools: 2.10.4(typescript@5.7.3) remark: 15.0.1 @@ -8451,7 +8451,7 @@ snapshots: - supports-color - typescript - applesauce-core@0.0.0-next-20250203215539(typescript@5.7.3): + applesauce-core@0.0.0-next-20250204170704(typescript@5.7.3): dependencies: '@scure/base': 1.2.4 debug: 4.4.0 @@ -8479,19 +8479,19 @@ snapshots: - supports-color - typescript - applesauce-factory@0.0.0-next-20250203215539(typescript@5.7.3): + applesauce-factory@0.0.0-next-20250204170704(typescript@5.7.3): dependencies: - applesauce-content: 0.0.0-next-20250203215539(typescript@5.7.3) - applesauce-core: 0.0.0-next-20250203215539(typescript@5.7.3) + applesauce-content: 0.0.0-next-20250204170704(typescript@5.7.3) + applesauce-core: 0.0.0-next-20250204170704(typescript@5.7.3) nanoid: 5.0.9 nostr-tools: 2.10.4(typescript@5.7.3) transitivePeerDependencies: - supports-color - typescript - applesauce-loaders@0.0.0-next-20250203215539(typescript@5.7.3): + applesauce-loaders@0.0.0-next-20250204170704(typescript@5.7.3): dependencies: - applesauce-core: 0.0.0-next-20250203215539(typescript@5.7.3) + applesauce-core: 0.0.0-next-20250204170704(typescript@5.7.3) nanoid: 5.0.9 nostr-tools: 2.10.4(typescript@5.7.3) rx-nostr: 3.5.0 @@ -8510,12 +8510,12 @@ snapshots: - supports-color - typescript - applesauce-react@0.0.0-next-20250203215539(typescript@5.7.3): + applesauce-react@0.0.0-next-20250204170704(typescript@5.7.3): dependencies: - applesauce-accounts: 0.0.0-next-20250203215539(typescript@5.7.3) - applesauce-content: 0.0.0-next-20250203215539(typescript@5.7.3) - applesauce-core: 0.0.0-next-20250203215539(typescript@5.7.3) - applesauce-factory: 0.0.0-next-20250203215539(typescript@5.7.3) + applesauce-accounts: 0.0.0-next-20250204170704(typescript@5.7.3) + applesauce-content: 0.0.0-next-20250204170704(typescript@5.7.3) + applesauce-core: 0.0.0-next-20250204170704(typescript@5.7.3) + applesauce-factory: 0.0.0-next-20250204170704(typescript@5.7.3) nostr-tools: 2.10.4(typescript@5.7.3) react: 18.3.1 rxjs: 7.8.1 @@ -8523,12 +8523,12 @@ snapshots: - supports-color - typescript - applesauce-signers@0.0.0-next-20250203215539(typescript@5.7.3): + applesauce-signers@0.0.0-next-20250204170704(typescript@5.7.3): dependencies: '@noble/hashes': 1.7.1 '@noble/secp256k1': 1.7.1 '@scure/base': 1.2.4 - applesauce-core: 0.0.0-next-20250203215539(typescript@5.7.3) + applesauce-core: 0.0.0-next-20250204170704(typescript@5.7.3) debug: 4.4.0 nanoid: 5.0.9 nostr-tools: 2.10.4(typescript@5.7.3) @@ -8752,8 +8752,8 @@ snapshots: browserslist@4.24.4: dependencies: - caniuse-lite: 1.0.30001696 - electron-to-chromium: 1.5.90 + caniuse-lite: 1.0.30001697 + electron-to-chromium: 1.5.91 node-releases: 2.0.19 update-browserslist-db: 1.1.2(browserslist@4.24.4) @@ -8802,7 +8802,7 @@ snapshots: camelcase@8.0.0: {} - caniuse-lite@1.0.30001696: {} + caniuse-lite@1.0.30001697: {} canvas-color-tracker@1.3.1: dependencies: @@ -9450,7 +9450,7 @@ snapshots: dependencies: jake: 10.9.2 - electron-to-chromium@1.5.90: {} + electron-to-chromium@1.5.91: {} elementtree@0.1.7: dependencies: @@ -9533,7 +9533,7 @@ snapshots: is-shared-array-buffer: 1.0.4 is-string: 1.1.1 is-typed-array: 1.1.15 - is-weakref: 1.1.0 + is-weakref: 1.1.1 math-intrinsics: 1.1.0 object-inspect: 1.13.3 object-keys: 1.1.1 @@ -10310,7 +10310,7 @@ snapshots: is-weakmap@2.0.2: {} - is-weakref@1.1.0: + is-weakref@1.1.1: dependencies: call-bound: 1.0.3 @@ -11472,26 +11472,26 @@ snapshots: dependencies: dnd-core: 16.0.1 - react-dnd-multi-backend@8.1.2(dnd-core@16.0.1)(react-dnd@16.0.1(@types/node@22.13.0)(@types/react@18.3.18)(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + react-dnd-multi-backend@8.1.2(dnd-core@16.0.1)(react-dnd@16.0.1(@types/node@22.13.1)(@types/react@18.3.18)(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0): dependencies: dnd-core: 16.0.1 dnd-multi-backend: 8.1.2(dnd-core@16.0.1) react: 19.0.0 - react-dnd: 16.0.1(@types/node@22.13.0)(@types/react@18.3.18)(react@19.0.0) - react-dnd-preview: 8.1.2(react-dnd@16.0.1(@types/node@22.13.0)(@types/react@18.3.18)(react@19.0.0))(react@19.0.0) + react-dnd: 16.0.1(@types/node@22.13.1)(@types/react@18.3.18)(react@19.0.0) + react-dnd-preview: 8.1.2(react-dnd@16.0.1(@types/node@22.13.1)(@types/react@18.3.18)(react@19.0.0))(react@19.0.0) react-dom: 19.0.0(react@19.0.0) - react-dnd-preview@8.1.2(react-dnd@16.0.1(@types/node@22.13.0)(@types/react@18.3.18)(react@19.0.0))(react@19.0.0): + react-dnd-preview@8.1.2(react-dnd@16.0.1(@types/node@22.13.1)(@types/react@18.3.18)(react@19.0.0))(react@19.0.0): dependencies: react: 19.0.0 - react-dnd: 16.0.1(@types/node@22.13.0)(@types/react@18.3.18)(react@19.0.0) + react-dnd: 16.0.1(@types/node@22.13.1)(@types/react@18.3.18)(react@19.0.0) react-dnd-touch-backend@16.0.1: dependencies: '@react-dnd/invariant': 4.0.2 dnd-core: 16.0.1 - react-dnd@16.0.1(@types/node@22.13.0)(@types/react@18.3.18)(react@19.0.0): + react-dnd@16.0.1(@types/node@22.13.1)(@types/react@18.3.18)(react@19.0.0): dependencies: '@react-dnd/invariant': 4.0.2 '@react-dnd/shallowequal': 4.0.2 @@ -11500,7 +11500,7 @@ snapshots: hoist-non-react-statics: 3.3.2 react: 19.0.0 optionalDependencies: - '@types/node': 22.13.0 + '@types/node': 22.13.1 '@types/react': 18.3.18 react-dom@19.0.0(react@19.0.0): @@ -11569,7 +11569,7 @@ snapshots: transitivePeerDependencies: - supports-color - react-mosaic-component@6.1.1(@types/node@22.13.0)(@types/react@18.3.18)(dnd-core@16.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + react-mosaic-component@6.1.1(@types/node@22.13.1)(@types/react@18.3.18)(dnd-core@16.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0): dependencies: classnames: 2.5.1 immutability-helper: 3.1.1 @@ -11577,9 +11577,9 @@ snapshots: prop-types: 15.8.1 rdndmb-html5-to-touch: 8.1.2(dnd-core@16.0.1) react: 19.0.0 - react-dnd: 16.0.1(@types/node@22.13.0)(@types/react@18.3.18)(react@19.0.0) + react-dnd: 16.0.1(@types/node@22.13.1)(@types/react@18.3.18)(react@19.0.0) react-dnd-html5-backend: 16.0.1 - react-dnd-multi-backend: 8.1.2(dnd-core@16.0.1)(react-dnd@16.0.1(@types/node@22.13.0)(@types/react@18.3.18)(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react-dnd-multi-backend: 8.1.2(dnd-core@16.0.1)(react-dnd@16.0.1(@types/node@22.13.1)(@types/react@18.3.18)(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0) react-dnd-touch-backend: 16.0.1 uuid: 9.0.1 transitivePeerDependencies: @@ -11911,29 +11911,29 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - rollup@4.34.1: + rollup@4.34.2: dependencies: '@types/estree': 1.0.6 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.34.1 - '@rollup/rollup-android-arm64': 4.34.1 - '@rollup/rollup-darwin-arm64': 4.34.1 - '@rollup/rollup-darwin-x64': 4.34.1 - '@rollup/rollup-freebsd-arm64': 4.34.1 - '@rollup/rollup-freebsd-x64': 4.34.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.34.1 - '@rollup/rollup-linux-arm-musleabihf': 4.34.1 - '@rollup/rollup-linux-arm64-gnu': 4.34.1 - '@rollup/rollup-linux-arm64-musl': 4.34.1 - '@rollup/rollup-linux-loongarch64-gnu': 4.34.1 - '@rollup/rollup-linux-powerpc64le-gnu': 4.34.1 - '@rollup/rollup-linux-riscv64-gnu': 4.34.1 - '@rollup/rollup-linux-s390x-gnu': 4.34.1 - '@rollup/rollup-linux-x64-gnu': 4.34.1 - '@rollup/rollup-linux-x64-musl': 4.34.1 - '@rollup/rollup-win32-arm64-msvc': 4.34.1 - '@rollup/rollup-win32-ia32-msvc': 4.34.1 - '@rollup/rollup-win32-x64-msvc': 4.34.1 + '@rollup/rollup-android-arm-eabi': 4.34.2 + '@rollup/rollup-android-arm64': 4.34.2 + '@rollup/rollup-darwin-arm64': 4.34.2 + '@rollup/rollup-darwin-x64': 4.34.2 + '@rollup/rollup-freebsd-arm64': 4.34.2 + '@rollup/rollup-freebsd-x64': 4.34.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.34.2 + '@rollup/rollup-linux-arm-musleabihf': 4.34.2 + '@rollup/rollup-linux-arm64-gnu': 4.34.2 + '@rollup/rollup-linux-arm64-musl': 4.34.2 + '@rollup/rollup-linux-loongarch64-gnu': 4.34.2 + '@rollup/rollup-linux-powerpc64le-gnu': 4.34.2 + '@rollup/rollup-linux-riscv64-gnu': 4.34.2 + '@rollup/rollup-linux-s390x-gnu': 4.34.2 + '@rollup/rollup-linux-x64-gnu': 4.34.2 + '@rollup/rollup-linux-x64-musl': 4.34.2 + '@rollup/rollup-win32-arm64-msvc': 4.34.2 + '@rollup/rollup-win32-ia32-msvc': 4.34.2 + '@rollup/rollup-win32-x64-msvc': 4.34.2 fsevents: 2.3.3 rtl-css-js@1.16.1: @@ -12500,14 +12500,14 @@ snapshots: ts-easing@0.2.0: {} - ts-node@10.9.2(@types/node@22.13.0)(typescript@5.7.3): + ts-node@10.9.2(@types/node@22.13.1)(typescript@5.7.3): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 22.13.0 + '@types/node': 22.13.1 acorn: 8.14.0 acorn-walk: 8.3.4 arg: 4.1.3 @@ -12722,35 +12722,35 @@ snapshots: vite-plugin-funding@0.1.0: {} - vite-plugin-pwa@0.21.1(vite@5.4.14(@types/node@22.13.0)(terser@5.37.0))(workbox-build@7.3.0(@types/babel__core@7.20.5))(workbox-window@7.3.0): + vite-plugin-pwa@0.21.1(vite@5.4.14(@types/node@22.13.1)(terser@5.37.0))(workbox-build@7.3.0(@types/babel__core@7.20.5))(workbox-window@7.3.0): dependencies: debug: 4.4.0 pretty-bytes: 6.1.1 tinyglobby: 0.2.10 - vite: 5.4.14(@types/node@22.13.0)(terser@5.37.0) + vite: 5.4.14(@types/node@22.13.1)(terser@5.37.0) workbox-build: 7.3.0(@types/babel__core@7.20.5) workbox-window: 7.3.0 transitivePeerDependencies: - supports-color - vite-tsconfig-paths@5.1.4(typescript@5.7.3)(vite@5.4.14(@types/node@22.13.0)(terser@5.37.0)): + vite-tsconfig-paths@5.1.4(typescript@5.7.3)(vite@5.4.14(@types/node@22.13.1)(terser@5.37.0)): dependencies: debug: 4.4.0 globrex: 0.1.2 tsconfck: 3.1.4(typescript@5.7.3) optionalDependencies: - vite: 5.4.14(@types/node@22.13.0)(terser@5.37.0) + vite: 5.4.14(@types/node@22.13.1)(terser@5.37.0) transitivePeerDependencies: - supports-color - typescript - vite@5.4.14(@types/node@22.13.0)(terser@5.37.0): + vite@5.4.14(@types/node@22.13.1)(terser@5.37.0): dependencies: esbuild: 0.21.5 postcss: 8.5.1 - rollup: 4.34.1 + rollup: 4.34.2 optionalDependencies: - '@types/node': 22.13.0 + '@types/node': 22.13.1 fsevents: 2.3.3 terser: 5.37.0 @@ -12805,7 +12805,7 @@ snapshots: is-finalizationregistry: 1.1.1 is-generator-function: 1.1.0 is-regex: 1.2.1 - is-weakref: 1.1.0 + is-weakref: 1.1.1 isarray: 2.0.5 which-boxed-primitive: 1.1.1 which-collection: 1.0.2 diff --git a/src/classes/batch-identifier-loader.ts b/src/classes/batch-identifier-loader.ts deleted file mode 100644 index ed6fa29a3..000000000 --- a/src/classes/batch-identifier-loader.ts +++ /dev/null @@ -1,148 +0,0 @@ -import { NostrEvent } from "nostr-tools"; -import { AbstractRelay } from "nostr-tools/abstract-relay"; -import _throttle from "lodash.throttle"; -import debug, { Debugger } from "debug"; -import { EventStore } from "applesauce-core"; -import { getEventUID } from "applesauce-core/helpers"; -import { createDefer, Deferred } from "applesauce-core/promise"; -import { Subject } from "rxjs"; - -import PersistentSubscription from "./persistent-subscription"; -import SuperMap from "./super-map"; - -/** Batches requests for events with #d tags from a single relay */ -export default class BatchIdentifierLoader { - store: EventStore; - kinds: number[]; - relay: AbstractRelay; - - /** list of identifiers that have been loaded */ - requested = new Set(); - /** identifier -> event uid -> event */ - identifiers = new SuperMap>(() => new Map()); - - onIdentifierUpdate = new Subject(); - - subscription: PersistentSubscription; - - // a map of identifiers that are waiting for the current request to finish - private next = new Map>>(); - - // a map of identifiers currently being requested from the relay - private pending = new Map>>(); - - log: Debugger; - - active = false; - constructor(store: EventStore, relay: AbstractRelay, kinds: number[], log?: Debugger) { - this.store = store; - this.relay = relay; - this.kinds = kinds; - this.log = log || debug("BatchIdentifierLoader"); - - this.subscription = new PersistentSubscription(this.relay, { - onevent: (event) => this.handleEvent(event), - oneose: () => this.handleEOSE(), - }); - } - - requestEvents(identifier: string): Promise> { - // if there is a cache only return it if we have requested this id before - if (this.identifiers.has(identifier) && this.requested.has(identifier)) { - return Promise.resolve(this.identifiers.get(identifier)); - } - - if (this.pending.has(identifier)) return this.pending.get(identifier)!; - if (this.next.has(identifier)) return this.next.get(identifier)!; - - const defer = createDefer>(); - this.next.set(identifier, defer); - - // request subscription update - this.requestUpdate(); - - return defer; - } - - requestUpdate = _throttle( - () => { - // don't do anything if the subscription is already running - if (this.active) return; - - this.active = true; - this.update(); - }, - 500, - { leading: false, trailing: true }, - ); - - handleEvent(event: NostrEvent) { - event = this.store.add(event, this.relay.url); - - // add event to cache - for (const tag of event.tags) { - if (tag[0] === "d" && tag[1]) { - const identifier = tag[1]; - this.identifiers.get(identifier).set(getEventUID(event), event); - this.changedIdentifiers.add(identifier); - } - } - } - - private changedIdentifiers = new Set(); - handleEOSE() { - // resolve all pending from the last request - for (const [identifier, defer] of this.pending) { - defer.resolve(this.identifiers.get(identifier)); - this.changedIdentifiers.add(identifier); - } - - // reset - this.pending.clear(); - this.active = false; - - for (const identifier of this.changedIdentifiers) { - this.onIdentifierUpdate.next(identifier); - } - - // do next request or close the subscription - if (this.next.size > 0) this.requestUpdate(); - } - - async update() { - // copy everything from next to pending - for (const [identifier, defer] of this.next) this.pending.set(identifier, defer); - this.next.clear(); - - // update subscription - if (this.pending.size > 0) { - this.log(`Updating filters ${this.pending.size} events`); - - const dTags: string[] = []; - const identifiers = Array.from(this.pending.keys()); - for (const identifier of identifiers) { - this.requested.add(identifier); - dTags.push(identifier); - } - - try { - this.active = true; - this.subscription.filters = []; - if (dTags.length > 0) this.subscription.filters.push({ "#d": dTags, kinds: this.kinds }); - - await this.subscription.update(); - } catch (error) { - if (error instanceof Error) this.log(`Failed to update subscription`, error.message); - this.active = false; - } - } else { - this.log("Closing"); - this.subscription.close(); - this.active = false; - } - } - - destroy() { - this.subscription.destroy(); - } -} diff --git a/src/classes/batch-relation-loader.ts b/src/classes/batch-relation-loader.ts deleted file mode 100644 index 295d586b7..000000000 --- a/src/classes/batch-relation-loader.ts +++ /dev/null @@ -1,148 +0,0 @@ -import { NostrEvent } from "nostr-tools"; -import { AbstractRelay } from "nostr-tools/abstract-relay"; -import _throttle from "lodash.throttle"; -import debug, { Debugger } from "debug"; -import { createDefer, Deferred } from "applesauce-core/promise"; -import { Subject } from "rxjs"; - -import PersistentSubscription from "./persistent-subscription"; -import SuperMap from "./super-map"; -import { eventStore } from "../services/event-store"; - -/** Batches requests for events that reference another event (via #e tag) from a single relay */ -export default class BatchRelationLoader { - kinds: number[]; - relay: AbstractRelay; - - requested = new Set(); - /** event id / coordinate -> event id -> event */ - references = new SuperMap>(() => new Map()); - - onEventUpdate = new Subject(); - - subscription: PersistentSubscription; - - // a map of events that are waiting for the current request to finish - private next = new Map>>(); - - // a map of events currently being requested from the relay - private pending = new Map>>(); - - log: Debugger; - - active = false; - constructor(relay: AbstractRelay, kinds: number[], log?: Debugger) { - this.relay = relay; - this.kinds = kinds; - this.log = log || debug("BatchRelationLoader"); - - this.subscription = new PersistentSubscription(this.relay, { - onevent: (event) => this.handleEvent(event), - oneose: () => this.handleEOSE(), - }); - } - - requestEvents(uid: string): Promise> { - // if there is a cache only return it if we have requested this id before - if (this.references.has(uid) && this.requested.has(uid)) { - return Promise.resolve(this.references.get(uid)); - } - - if (this.pending.has(uid)) return this.pending.get(uid)!; - if (this.next.has(uid)) return this.next.get(uid)!; - - const defer = createDefer>(); - this.next.set(uid, defer); - - // request subscription update - this.requestUpdate(); - - return defer; - } - - requestUpdate = _throttle( - () => { - // don't do anything if the subscription is already running - if (this.active) return; - - this.active = true; - this.update(); - }, - 500, - { leading: false, trailing: true }, - ); - - handleEvent(event: NostrEvent) { - event = eventStore.add(event, this.relay.url); - - // add event to cache - const updateIds = new Set(); - for (const tag of event.tags) { - if (tag[0] === "e" && tag[1]) { - const id = tag[1]; - this.references.get(id).set(event.id, event); - updateIds.add(id); - } else if (tag[0] === "a" && tag[1]) { - const cord = tag[1]; - this.references.get(cord).set(event.id, event); - updateIds.add(cord); - } - } - - for (const id of updateIds) this.onEventUpdate.next(id); - } - handleEOSE() { - // resolve all pending from the last request - for (const [uid, defer] of this.pending) { - defer.resolve(this.references.get(uid)); - } - - // reset - this.pending.clear(); - this.active = false; - - // do next request or close the subscription - if (this.next.size > 0) this.requestUpdate(); - } - - async update() { - // copy everything from next to pending - for (const [uid, defer] of this.next) this.pending.set(uid, defer); - this.next.clear(); - - // update subscription - if (this.pending.size > 0) { - this.log(`Updating filters ${this.pending.size} events`); - - const ids: string[] = []; - const cords: string[] = []; - const uids = Array.from(this.pending.keys()); - for (const uid of uids) { - this.requested.add(uid); - - if (uid.includes(":")) cords.push(uid); - else ids.push(uid); - } - - try { - this.active = true; - this.subscription.filters = []; - if (ids.length > 0) this.subscription.filters.push({ "#e": ids, kinds: this.kinds }); - if (cords.length > 0) this.subscription.filters.push({ "#a": cords, kinds: this.kinds }); - - await this.subscription.update(); - } catch (error) { - if (error instanceof Error) this.log(`Failed to update subscription`, error.message); - this.active = false; - } - } else { - this.log("Closing"); - this.subscription.close(); - this.active = false; - } - } - - destroy() { - this.subscription.destroy(); - } -} diff --git a/src/classes/persistent-subscription.ts b/src/classes/persistent-subscription.ts deleted file mode 100644 index 0288d0071..000000000 --- a/src/classes/persistent-subscription.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { nanoid } from "nanoid"; -import { Filter, Relay } from "nostr-tools"; -import { AbstractRelay, Subscription, SubscriptionParams } from "nostr-tools/abstract-relay"; -import { isFilterEqual } from "applesauce-core/helpers"; - -import relayPoolService from "../services/relay-pool"; - -export default class PersistentSubscription { - id: string; - relay: Relay; - filters: Filter[]; - connecting = false; - params: Partial; - - subscription: Subscription | null = null; - get eosed() { - return !!this.subscription?.eosed; - } - get closed() { - return !this.subscription || this.subscription.closed; - } - - active = false; - constructor(relay: AbstractRelay, params?: Partial) { - this.id = nanoid(8); - this.filters = []; - this.params = { - //@ts-expect-error - id: this.id, - ...params, - }; - - this.relay = relay; - } - - /** attempts to update the subscription */ - async update() { - if (!this.filters || this.filters.length === 0) throw new Error("Missing filters"); - if (this.connecting) throw new Error("Cant update while connecting"); - - this.active = true; - - this.connecting = true; - if ((await relayPoolService.waitForOpen(this.relay)) === false) { - this.connecting = false; - this.active = false; - throw new Error("Failed to connect to relay"); - } - this.connecting = false; - - // recreate the subscription if its closed since nostr-tools cant reopen a sub - if (!this.subscription || this.subscription.closed) { - this.subscription = this.relay.subscribe(this.filters, { - ...this.params, - oneose: () => { - this.params.oneose?.(); - }, - onclose: (reason) => { - if (!this.closed) { - relayPoolService.handleRelayNotice(this.relay, reason); - - this.active = false; - } - this.params.onclose?.(reason); - }, - }); - } else if (isFilterEqual(this.subscription.filters, this.filters) === false) { - this.subscription.filters = this.filters; - // NOTE: reset the eosed flag since nostr-tools dose not - this.subscription.eosed = false; - this.subscription.fire(); - } else throw new Error("Subscription filters have not changed"); - } - close() { - if (this.subscription?.closed === false) this.subscription.close(); - this.active = false; - - return this; - } - - destroy() { - this.close(); - } -} diff --git a/src/classes/relay.ts b/src/classes/relay.ts deleted file mode 100644 index d904c87e1..000000000 --- a/src/classes/relay.ts +++ /dev/null @@ -1,6 +0,0 @@ -export enum RelayMode { - NONE = 0, - READ = 1, - WRITE = 2, - BOTH = 1 | 2, -} diff --git a/src/components/markdown/wiki-link.tsx b/src/components/markdown/wiki-link.tsx index 3789bf789..655ee05e7 100644 --- a/src/components/markdown/wiki-link.tsx +++ b/src/components/markdown/wiki-link.tsx @@ -23,8 +23,8 @@ import { useObservable } from "applesauce-react/hooks"; import { useReadRelays } from "../../hooks/use-client-relays"; import { getPageDefer, getPageSummary } from "../../helpers/nostr/wiki"; import UserName from "../user/user-name"; -import dictionaryService from "../../services/dictionary"; import { useWebOfTrust } from "../../providers/global/web-of-trust-provider"; +import useWikiPages from "../../hooks/use-wiki-pages"; export default function WikiLink({ children, @@ -43,11 +43,10 @@ export default function WikiLink({ topic = properties.href.replace(/^#\/page\//, ""); } - const subject = useMemo( - () => (topic ? dictionaryService.requestTopic(topic, readRelays) : undefined), - [topic, readRelays], - ); - const events = useObservable(subject); + // TODO: if topic cant be found, render something else + if (!topic) return null; + + const events = useWikiPages(topic, readRelays); const sorted = useMemo(() => { if (!events) return []; @@ -97,7 +96,7 @@ export default function WikiLink({ : {getPageSummary(page)} ))} - {events?.size === 0 && There is no entry for this topic} + {events?.length === 0 && There is no entry for this topic} diff --git a/src/components/zap/event-zap-button.tsx b/src/components/zap/event-zap-button.tsx index 8d9ec4a05..c39b198b4 100644 --- a/src/components/zap/event-zap-button.tsx +++ b/src/components/zap/event-zap-button.tsx @@ -1,16 +1,15 @@ import { Button, ButtonProps, IconButton, useDisclosure } from "@chakra-ui/react"; -import { getZapSender } from "applesauce-core/helpers"; +import { getEventUID, getZapSender } from "applesauce-core/helpers"; import { useActiveAccount } from "applesauce-react/hooks"; import { humanReadableSats } from "../../helpers/lightning"; import { totalZaps } from "../../helpers/nostr/zaps"; import useEventZaps from "../../hooks/use-event-zaps"; -import eventZapsService from "../../services/event-zaps"; +import { requestZaps } from "../../services/event-zaps-loader"; import { NostrEvent } from "../../types/nostr-event"; import { LightningIcon } from "../icons"; import ZapModal from "../event-zap-modal"; import useUserLNURLMetadata from "../../hooks/use-user-lnurl-metadata"; -import { getEventUID } from "../../helpers/nostr/event"; import { useReadRelays } from "../../hooks/use-client-relays"; export type NoteZapButtonProps = Omit & { @@ -30,7 +29,7 @@ export default function EventZapButton({ event, allowComment, showEventPreview, const readRelays = useReadRelays(); const onZapped = () => { onClose(); - eventZapsService.requestZaps(getEventUID(event), readRelays, true); + requestZaps(getEventUID(event), readRelays, true); }; const total = totalZaps(zaps); diff --git a/src/components/zap/event-zap-icon-button.tsx b/src/components/zap/event-zap-icon-button.tsx index d7ee3386d..a80eed182 100644 --- a/src/components/zap/event-zap-icon-button.tsx +++ b/src/components/zap/event-zap-icon-button.tsx @@ -2,13 +2,13 @@ import { IconButton, IconButtonProps, useDisclosure } from "@chakra-ui/react"; import { useActiveAccount } from "applesauce-react/hooks"; import useEventZaps from "../../hooks/use-event-zaps"; -import eventZapsService from "../../services/event-zaps"; import { NostrEvent } from "../../types/nostr-event"; import { LightningIcon } from "../icons"; import ZapModal from "../event-zap-modal"; import useUserLNURLMetadata from "../../hooks/use-user-lnurl-metadata"; import { getEventUID } from "../../helpers/nostr/event"; import { useReadRelays } from "../../hooks/use-client-relays"; +import { requestZaps } from "../../services/event-zaps-loader"; export default function EventZapIconButton({ event, @@ -22,7 +22,7 @@ export default function EventZapIconButton({ const readRelays = useReadRelays(); const onZapped = () => { onClose(); - eventZapsService.requestZaps(getEventUID(event), readRelays, true); + requestZaps(getEventUID(event), readRelays, true); }; const canZap = !!metadata?.allowsNostr || event.tags.some((t) => t[0] === "zap"); diff --git a/src/helpers/notification.ts b/src/helpers/notification.ts index e310fa81f..e04def7a2 100644 --- a/src/helpers/notification.ts +++ b/src/helpers/notification.ts @@ -1,6 +1,5 @@ import SuperMap from "../classes/super-map"; import { NostrEvent } from "../types/nostr-event"; -import { getThreadReferences, sortByDate } from "./nostr/event"; const DAY_IN_SECONDS = 60 * 60 * 24; diff --git a/src/hooks/use-channel-metadata.ts b/src/hooks/use-channel-metadata.ts index 24a57f30f..1cbec7e39 100644 --- a/src/hooks/use-channel-metadata.ts +++ b/src/hooks/use-channel-metadata.ts @@ -2,19 +2,21 @@ import { useMemo } from "react"; import { useStoreQuery } from "applesauce-react/hooks"; import { ChannelMetadataQuery } from "applesauce-core/queries"; -import channelMetadataService from "../services/channel-metadata"; import useSingleEvent from "./use-single-event"; +import channelMetadataLoader from "../services/channel-metadata-loader"; +import { useReadRelays } from "./use-client-relays"; export default function useChannelMetadata( channelId: string | undefined, - relays: Iterable = [], + additionalRelays?: string[], force?: boolean, ) { + const relays = useReadRelays(additionalRelays); const channel = useSingleEvent(channelId); useMemo(() => { if (!channelId) return; - return channelMetadataService.requestMetadata(relays, channelId, { alwaysRequest: force, ignoreCache: force }); - }, [channelId, Array.from(relays).join("|"), force]); + return channelMetadataLoader.next({ value: channelId, relays, force }); + }, [channelId, relays.join("|"), force]); const metadata = useStoreQuery(ChannelMetadataQuery, channel && [channel]); diff --git a/src/hooks/use-event-reactions.ts b/src/hooks/use-event-reactions.ts index eb6d7a25f..4d50f5a63 100644 --- a/src/hooks/use-event-reactions.ts +++ b/src/hooks/use-event-reactions.ts @@ -4,19 +4,15 @@ import { getEventUID } from "applesauce-core/helpers"; import { useStoreQuery } from "applesauce-react/hooks"; import { ReactionsQuery } from "applesauce-core/queries"; -import eventReactionsService from "../services/event-reactions"; import { useReadRelays } from "./use-client-relays"; +import { requestReactions } from "../services/event-reactions-loader"; -export default function useEventReactions( - event: NostrEvent, - additionalRelays?: Iterable, - alwaysRequest = true, -) { +export default function useEventReactions(event: NostrEvent, additionalRelays?: string[], force?: boolean) { const relays = useReadRelays(additionalRelays); useEffect(() => { - eventReactionsService.requestReactions(getEventUID(event), relays, alwaysRequest); - }, [event, relays, alwaysRequest]); + requestReactions(getEventUID(event), relays, force); + }, [event, relays.join(","), force]); return useStoreQuery(ReactionsQuery, [event]); } diff --git a/src/hooks/use-event-zaps.ts b/src/hooks/use-event-zaps.ts index 3c923ca82..c7de54c03 100644 --- a/src/hooks/use-event-zaps.ts +++ b/src/hooks/use-event-zaps.ts @@ -2,16 +2,16 @@ import { useEffect, useMemo } from "react"; import { useStoreQuery } from "applesauce-react/hooks"; import { parseCoordinate } from "applesauce-core/helpers"; import { EventZapsQuery } from "applesauce-core/queries"; +import { requestZaps } from "../services/event-zaps-loader"; -import eventZapsService from "../services/event-zaps"; import { useReadRelays } from "./use-client-relays"; -export default function useEventZaps(uid: string, additionalRelays?: Iterable, alwaysRequest = false) { - const readRelays = useReadRelays(additionalRelays); +export default function useEventZaps(uid: string, additionalRelays?: Iterable, force?: boolean) { + const relay = useReadRelays(additionalRelays); useEffect(() => { - eventZapsService.requestZaps(uid, readRelays, alwaysRequest); - }, [uid, readRelays.join("|"), alwaysRequest]); + requestZaps(uid, relay, force); + }, [uid, relay.join("|"), force]); const pointer = useMemo(() => { if (uid.includes(":")) return parseCoordinate(uid, true); diff --git a/src/hooks/use-wiki-pages.ts b/src/hooks/use-wiki-pages.ts new file mode 100644 index 000000000..4f0618db6 --- /dev/null +++ b/src/hooks/use-wiki-pages.ts @@ -0,0 +1,21 @@ +import { useEffect } from "react"; +import { useStoreQuery } from "applesauce-react/hooks"; +import { NostrEvent } from "nostr-tools"; + +import { useReadRelays } from "./use-client-relays"; +import wikiPageLoader from "../services/wiki-page-loader"; +import { WikiPagesQuery } from "../queries/wiki-pages"; + +export default function useWikiPages( + topic: string, + additionalRelays?: Iterable, + force?: boolean, +): NostrEvent[] { + const relays = useReadRelays(additionalRelays); + + useEffect(() => { + wikiPageLoader.next({ value: topic, relays, force }); + }, [topic, relays.join("|"), force]); + + return useStoreQuery(WikiPagesQuery, topic ? [topic] : undefined) ?? []; +} diff --git a/src/queries/wiki-pages.ts b/src/queries/wiki-pages.ts new file mode 100644 index 000000000..75964f86d --- /dev/null +++ b/src/queries/wiki-pages.ts @@ -0,0 +1,10 @@ +import { Query } from "applesauce-core"; +import { NostrEvent } from "nostr-tools"; +import { WIKI_PAGE_KIND } from "../helpers/nostr/wiki"; + +export function WikiPagesQuery(topic: string): Query { + return { + key: topic, + run: (store) => store.timeline([{ kinds: [WIKI_PAGE_KIND], "#d": [topic] }]), + }; +} diff --git a/src/queries/wiki-topics.ts b/src/queries/wiki-topics.ts new file mode 100644 index 000000000..5aef58cd2 --- /dev/null +++ b/src/queries/wiki-topics.ts @@ -0,0 +1,28 @@ +import { Query } from "applesauce-core"; +import { groupBy, map } from "rxjs"; +import { NostrEvent } from "nostr-tools"; + +import { WIKI_PAGE_KIND } from "../helpers/nostr/wiki"; +import { getReplaceableIdentifier } from "applesauce-core/helpers"; + +export function WikiTopicsQuery(): Query> { + return { + key: "topics", + run: (store) => + store.timeline([{ kinds: [WIKI_PAGE_KIND] }]).pipe( + map((events) => { + const topics: Record = {}; + + for (const event of events) { + const d = getReplaceableIdentifier(event); + if (!d) continue; + + if (!topics[d]) topics[d] = [event]; + else topics[d].push(event); + } + + return topics; + }), + ), + }; +} diff --git a/src/services/channel-metadata-loader.ts b/src/services/channel-metadata-loader.ts new file mode 100644 index 000000000..2b4cb3889 --- /dev/null +++ b/src/services/channel-metadata-loader.ts @@ -0,0 +1,19 @@ +import { kinds } from "nostr-tools"; + +import { cacheRequest } from "./cache-relay"; +import { TagValueLoader } from "applesauce-loaders"; +import rxNostr from "./rx-nostr"; +import { eventStore } from "./event-store"; + +const channelMetadataLoader = new TagValueLoader(rxNostr, "e", { + name: "channel-metadata", + kinds: [kinds.ChannelMetadata], + cacheRequest, +}); + +// start the loader and send all events to the event store +channelMetadataLoader.subscribe((packet) => { + eventStore.add(packet.event, packet.from); +}); + +export default channelMetadataLoader; diff --git a/src/services/channel-metadata.ts b/src/services/channel-metadata.ts deleted file mode 100644 index 358a19567..000000000 --- a/src/services/channel-metadata.ts +++ /dev/null @@ -1,157 +0,0 @@ -import dayjs from "dayjs"; -import { Debugger } from "debug"; -import _throttle from "lodash.throttle"; -import { Filter, kinds } from "nostr-tools"; - -import SuperMap from "../classes/super-map"; -import { NostrEvent } from "../types/nostr-event"; -import { logger } from "../helpers/debug"; -import { eventStore } from "./event-store"; -import relayPoolService from "./relay-pool"; -import PersistentSubscription from "../classes/persistent-subscription"; -import { getChannelPointer, markFromCache } from "applesauce-core/helpers"; -import { AbstractRelay } from "nostr-tools/abstract-relay"; -import { cacheRelay$, getCacheRelay } from "./cache-relay"; - -export type RequestOptions = { - /** Always request the event from the relays */ - alwaysRequest?: boolean; - /** ignore the cache on initial load */ - ignoreCache?: boolean; -}; - -const RELAY_REQUEST_BATCH_TIME = 1000; - -/** This class is ued to batch requests to a single relay */ -class ChannelMetadataRelayLoader { - private subscription: PersistentSubscription; - - private requestNext = new Set(); - private requested = new Map(); - - log: Debugger; - isCache = false; - - constructor(relay: AbstractRelay, log?: Debugger) { - this.log = log || logger.extend("ChannelMetadataRelayLoader"); - this.subscription = new PersistentSubscription(relay, { - onevent: (event) => this.handleEvent(event), - oneose: () => this.handleEOSE(), - }); - } - - private handleEvent(event: NostrEvent) { - const channelId = getChannelPointer(event)?.id; - if (!channelId) return; - - // remove the pubkey from the waiting list - this.requested.delete(channelId); - - if (this.isCache) markFromCache(event); - - eventStore.add(event); - } - private handleEOSE() { - // relays says it has nothing left - this.requested.clear(); - } - - requestMetadata(channelId: string) { - this.requestNext.add(channelId); - this.updateThrottle(); - } - - updateThrottle = _throttle(this.update, RELAY_REQUEST_BATCH_TIME); - update() { - let needsUpdate = false; - for (const channelId of this.requestNext) { - if (!this.requested.has(channelId)) { - this.requested.set(channelId, new Date()); - needsUpdate = true; - } - } - this.requestNext.clear(); - - // prune requests - const timeout = dayjs().subtract(1, "minute"); - for (const [channelId, date] of this.requested) { - if (dayjs(date).isBefore(timeout)) { - this.requested.delete(channelId); - needsUpdate = true; - } - } - - // update the subscription - if (needsUpdate) { - if (this.requested.size > 0) { - const query: Filter = { - kinds: [kinds.ChannelMetadata], - "#e": Array.from(this.requested.keys()), - }; - - if (query["#e"] && query["#e"].length > 0) this.log(`Updating query`, query["#e"].length); - this.subscription.filters = [query]; - - this.subscription.update(); - } else { - this.subscription.close(); - } - } - } -} - -/** This is a clone of ReplaceableEventLoaderService to support channel metadata */ -class ChannelMetadataService { - private loaders = new SuperMap( - (relay) => new ChannelMetadataRelayLoader(relay, this.log.extend(relay.url)), - ); - - log = logger.extend("ChannelMetadata"); - - constructor() { - cacheRelay$.subscribe((cacheRelay) => { - if (!cacheRelay) return; - - const loader = this.loaders.get(cacheRelay as AbstractRelay); - loader.isCache = true; - }); - } - - handleEvent(event: NostrEvent) { - eventStore.add(event); - - const channelId = getChannelPointer(event)?.id; - if (!channelId) return; - } - - private requestChannelMetadataFromRelays(relays: Iterable, channelId: string) { - const relayUrls = Array.from(relays); - for (const url of relayUrls) { - const relay = relayPoolService.getRelay(url); - if (relay) this.loaders.get(relay).requestMetadata(channelId); - } - } - - private loaded = new Map(); - requestMetadata(relays: Iterable, channelId: string, opts: RequestOptions = {}) { - const loaded = this.loaded.get(channelId); - - const cacheRelay = getCacheRelay(); - if (!loaded && cacheRelay) { - this.loaders.get(cacheRelay as AbstractRelay).requestMetadata(channelId); - } - - if (opts?.alwaysRequest || (!loaded && opts.ignoreCache)) { - this.requestChannelMetadataFromRelays(relays, channelId); - } - } -} - -const channelMetadataService = new ChannelMetadataService(); - -if (import.meta.env.DEV) { - //@ts-expect-error debug - window.channelMetadataService = channelMetadataService; -} - -export default channelMetadataService; diff --git a/src/services/debug-api.ts b/src/services/debug-api.ts index eae847239..e2494a9ad 100644 --- a/src/services/debug-api.ts +++ b/src/services/debug-api.ts @@ -1,6 +1,6 @@ import rxNostr from "./rx-nostr"; import accounts from "./accounts"; -import channelMetadataService from "./channel-metadata"; +import channelMetadataService from "./channel-metadata-loader"; import { eventStore, queryStore } from "./event-store"; import localSettings from "./local-settings"; import readStatusService from "./read-status"; diff --git a/src/services/dictionary.ts b/src/services/dictionary.ts deleted file mode 100644 index a0d5153b5..000000000 --- a/src/services/dictionary.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { NostrEvent } from "nostr-tools"; -import { AbstractRelay } from "nostr-tools/abstract-relay"; -import { EventStore } from "applesauce-core"; -import { BehaviorSubject } from "rxjs"; - -import { WIKI_PAGE_KIND } from "../helpers/nostr/wiki"; -import { logger } from "../helpers/debug"; -import SuperMap from "../classes/super-map"; -import BatchIdentifierLoader from "../classes/batch-identifier-loader"; -import relayPoolService from "./relay-pool"; -import { eventStore } from "./event-store"; -import { getCacheRelay } from "./cache-relay"; - -class DictionaryService { - log = logger.extend("DictionaryService"); - store: EventStore; - - topics = new SuperMap>>( - () => new BehaviorSubject>(new Map()), - ); - - loaders = new SuperMap((relay) => { - const loader = new BatchIdentifierLoader(this.store, relay, [WIKI_PAGE_KIND], this.log.extend(relay.url)); - loader.onIdentifierUpdate.subscribe((identifier) => { - this.updateSubject(identifier); - }); - return loader; - }); - - constructor(store: EventStore) { - this.store = store; - } - - // merged results from all loaders for a single event - private updateSubject(identifier: string) { - const events = new Map(); - const subject = this.topics.get(identifier); - - for (const [relay, loader] of this.loaders) { - if (loader.identifiers.has(identifier)) { - const other = loader.identifiers.get(identifier); - for (const [uid, e] of other) { - if (e.content.trim().length === 0) continue; - const existing = events.get(uid); - if (!existing || e.created_at > existing.created_at) events.set(uid, e); - } - } - } - - subject.next(events); - } - - getTopic(topic: string) { - return this.topics.get(topic); - } - - requestTopic(topic: string, urls: Iterable, alwaysRequest = true) { - const subject = this.topics.get(topic); - if (subject.value && !alwaysRequest) return subject; - - const cacheRelay = getCacheRelay(); - if (cacheRelay) { - this.loaders.get(cacheRelay as AbstractRelay).requestEvents(topic); - } - - const relays = relayPoolService.getRelays(urls); - for (const relay of relays) { - this.loaders.get(relay).requestEvents(topic); - } - - return subject; - } - - handleEvent(event: NostrEvent) { - event = this.store.add(event); - - const cacheRelay = getCacheRelay(); - // pretend it came from the local relay - // TODO: remove this once DictionaryService uses subscriptions from event store - if (cacheRelay) this.loaders.get(cacheRelay as AbstractRelay).handleEvent(event); - } -} - -const dictionaryService = new DictionaryService(eventStore); - -if (import.meta.env.DEV) { - // @ts-expect-error debug - window.dictionaryService = dictionaryService; -} - -export default dictionaryService; diff --git a/src/services/event-reactions-loader.ts b/src/services/event-reactions-loader.ts new file mode 100644 index 000000000..6d8b48825 --- /dev/null +++ b/src/services/event-reactions-loader.ts @@ -0,0 +1,38 @@ +import { kinds } from "nostr-tools"; +import { AddressPointer, EventPointer } from "nostr-tools/nip19"; +import { getCoordinateFromAddressPointer, isAddressPointer, isEventPointer } from "applesauce-core/helpers"; + +import { cacheRequest } from "./cache-relay"; +import { TagValueLoader } from "applesauce-loaders"; +import rxNostr from "./rx-nostr"; +import { eventStore } from "./event-store"; + +export function requestReactions(id: string | EventPointer | AddressPointer, relays: string[], force?: boolean) { + if (typeof id === "string") { + if (id.includes(":")) replaceableEventsZapsLoader.next({ value: id, relays, force }); + else singleEventsZapsLoader.next({ value: id, relays, force }); + } else if (isEventPointer(id)) { + singleEventsZapsLoader.next({ value: id.id, relays, force }); + } else if (isAddressPointer(id)) { + replaceableEventsZapsLoader.next({ value: getCoordinateFromAddressPointer(id), relays, force }); + } +} + +const replaceableEventsZapsLoader = new TagValueLoader(rxNostr, "a", { + name: "reactions", + kinds: [kinds.Reaction], + cacheRequest, +}); +const singleEventsZapsLoader = new TagValueLoader(rxNostr, "e", { + name: "reactions", + kinds: [kinds.Reaction], + cacheRequest, +}); + +// start the loader and send all events to the event store +replaceableEventsZapsLoader.subscribe((packet) => { + eventStore.add(packet.event, packet.from); +}); +singleEventsZapsLoader.subscribe((packet) => { + eventStore.add(packet.event, packet.from); +}); diff --git a/src/services/event-reactions.ts b/src/services/event-reactions.ts deleted file mode 100644 index a190a53e9..000000000 --- a/src/services/event-reactions.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { kinds } from "nostr-tools"; -import _throttle from "lodash.throttle"; -import { AbstractRelay } from "nostr-tools/abstract-relay"; - -import SuperMap from "../classes/super-map"; -import relayPoolService from "./relay-pool"; -import BatchRelationLoader from "../classes/batch-relation-loader"; -import { logger } from "../helpers/debug"; -import { getCacheRelay } from "./cache-relay"; - -class EventReactionsService { - log = logger.extend("EventReactionsService"); - - private loaded = new Map(); - loaders = new SuperMap((relay) => { - return new BatchRelationLoader(relay, [kinds.Reaction], this.log.extend(relay.url)); - }); - - requestReactions(uid: string, urls: Iterable, alwaysRequest = false) { - if (this.loaded.get(uid) && !alwaysRequest) return; - - const cacheRelay = getCacheRelay(); - if (cacheRelay) { - this.loaders.get(cacheRelay as AbstractRelay).requestEvents(uid); - } - - const relays = relayPoolService.getRelays(urls); - for (const relay of relays) { - this.loaders.get(relay).requestEvents(uid); - } - } -} - -const eventReactionsService = new EventReactionsService(); - -if (import.meta.env.DEV) { - // @ts-expect-error debug - window.eventReactionsService = eventReactionsService; -} - -export default eventReactionsService; diff --git a/src/services/event-zaps-loader.ts b/src/services/event-zaps-loader.ts new file mode 100644 index 000000000..dd65057a8 --- /dev/null +++ b/src/services/event-zaps-loader.ts @@ -0,0 +1,34 @@ +import { kinds } from "nostr-tools"; +import { getCoordinateFromAddressPointer, isAddressPointer, isEventPointer } from "applesauce-core/helpers"; +import { AddressPointer, EventPointer } from "nostr-tools/nip19"; +import { TagValueLoader } from "applesauce-loaders"; + +import { cacheRequest } from "./cache-relay"; +import rxNostr from "./rx-nostr"; +import { eventStore } from "./event-store"; + +export function requestZaps(id: string | EventPointer | AddressPointer, relays: string[], force?: boolean) { + if (typeof id === "string") { + if (id.includes(":")) replaceableEventsZapsLoader.next({ value: id, relays, force }); + else singleEventsZapsLoader.next({ value: id, relays, force }); + } else if (isEventPointer(id)) { + singleEventsZapsLoader.next({ value: id.id, relays, force }); + } else if (isAddressPointer(id)) { + replaceableEventsZapsLoader.next({ value: getCoordinateFromAddressPointer(id), relays, force }); + } +} + +const replaceableEventsZapsLoader = new TagValueLoader(rxNostr, "a", { + name: "zaps", + kinds: [kinds.Zap], + cacheRequest, +}); +const singleEventsZapsLoader = new TagValueLoader(rxNostr, "e", { name: "zaps", kinds: [kinds.Zap], cacheRequest }); + +// start the loader and send all events to the event store +replaceableEventsZapsLoader.subscribe((packet) => { + eventStore.add(packet.event, packet.from); +}); +singleEventsZapsLoader.subscribe((packet) => { + eventStore.add(packet.event, packet.from); +}); diff --git a/src/services/event-zaps.ts b/src/services/event-zaps.ts deleted file mode 100644 index 813320f5c..000000000 --- a/src/services/event-zaps.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { kinds } from "nostr-tools"; -import _throttle from "lodash.throttle"; -import { AbstractRelay } from "nostr-tools/abstract-relay"; - -import SuperMap from "../classes/super-map"; -import relayPoolService from "./relay-pool"; -import BatchRelationLoader from "../classes/batch-relation-loader"; -import { logger } from "../helpers/debug"; -import { getCacheRelay } from "./cache-relay"; - -class EventZapsService { - log = logger.extend("EventZapsService"); - - private loaded = new Map(); - loaders = new SuperMap((relay) => { - const loader = new BatchRelationLoader(relay, [kinds.Zap], this.log.extend(relay.url)); - return loader; - }); - - requestZaps(uid: string, urls: Iterable, alwaysRequest = true) { - if (this.loaded.get(uid) && !alwaysRequest) return; - - const cacheRelay = getCacheRelay(); - if (cacheRelay) { - this.loaders.get(cacheRelay as AbstractRelay).requestEvents(uid); - } - - const relays = relayPoolService.getRelays(urls); - for (const relay of relays) { - this.loaders.get(relay).requestEvents(uid); - } - } -} - -const eventZapsService = new EventZapsService(); - -if (import.meta.env.DEV) { - // @ts-expect-error debug - window.eventZapsService = eventZapsService; -} - -export default eventZapsService; diff --git a/src/services/wiki-page-loader.ts b/src/services/wiki-page-loader.ts new file mode 100644 index 000000000..f94886d79 --- /dev/null +++ b/src/services/wiki-page-loader.ts @@ -0,0 +1,15 @@ +import { TagValueLoader } from "applesauce-loaders"; + +import { WIKI_PAGE_KIND } from "../helpers/nostr/wiki"; +import { eventStore } from "./event-store"; +import { cacheRequest } from "./cache-relay"; +import rxNostr from "./rx-nostr"; + +const wikiPageLoader = new TagValueLoader(rxNostr, "d", { name: "wiki-pages", kinds: [WIKI_PAGE_KIND], cacheRequest }); + +// start the loader and send all events to the event store +wikiPageLoader.subscribe((packet) => { + eventStore.add(packet.event, packet.from); +}); + +export default wikiPageLoader; diff --git a/src/views/emojis/components/emoji-pack-card.tsx b/src/views/emojis/components/emoji-pack-card.tsx index a9fcadb07..b4bd16fa6 100644 --- a/src/views/emojis/components/emoji-pack-card.tsx +++ b/src/views/emojis/components/emoji-pack-card.tsx @@ -52,11 +52,11 @@ export default function EmojiPackCard({ pack, ...props }: Omit - + - + diff --git a/src/views/goals/components/goal-zap-button.tsx b/src/views/goals/components/goal-zap-button.tsx index e7f6f450c..e30a7a5fb 100644 --- a/src/views/goals/components/goal-zap-button.tsx +++ b/src/views/goals/components/goal-zap-button.tsx @@ -1,10 +1,10 @@ import { Button, ButtonProps, useDisclosure } from "@chakra-ui/react"; import { NostrEvent } from "../../../types/nostr-event"; import ZapModal from "../../../components/event-zap-modal"; -import eventZapsService from "../../../services/event-zaps"; import { getEventUID } from "../../../helpers/nostr/event"; import { getGoalRelays } from "../../../helpers/nostr/goal"; import { useReadRelays } from "../../../hooks/use-client-relays"; +import { requestZaps } from "../../../services/event-zaps-loader"; export default function GoalZapButton({ goal, @@ -16,7 +16,7 @@ export default function GoalZapButton({ const onZapped = async () => { modal.onClose(); setTimeout(() => { - eventZapsService.requestZaps(getEventUID(goal), readRelays, true); + requestZaps(getEventUID(goal), readRelays, true); }, 1000); }; diff --git a/src/views/settings/mailboxes/index.tsx b/src/views/settings/mailboxes/index.tsx index 890205504..20ea7f3a6 100644 --- a/src/views/settings/mailboxes/index.tsx +++ b/src/views/settings/mailboxes/index.tsx @@ -9,7 +9,6 @@ import useUserMailboxes from "../../../hooks/use-user-mailboxes"; import { useActiveAccount } from "applesauce-react/hooks"; import { InboxIcon, OutboxIcon } from "../../../components/icons"; import MediaServerFavicon from "../../../components/media-server/media-server-favicon"; -import { RelayMode } from "../../../classes/relay"; import { NostrEvent } from "../../../types/nostr-event"; import useAsyncErrorHandler from "../../../hooks/use-async-error-handler"; import { usePublishEvent } from "../../../providers/global/publish-provider"; @@ -19,6 +18,7 @@ import DebugEventButton from "../../../components/debug-modal/debug-event-button import useReplaceableEvent from "../../../hooks/use-replaceable-event"; import { COMMON_CONTACT_RELAYS } from "../../../const"; import SimpleView from "../../../components/layout/presets/simple-view"; +import { RelayMode } from "../../../services/app-relays"; function RelayLine({ relay, mode, list }: { relay: string; mode: RelayMode; list?: NostrEvent }) { const publish = usePublishEvent(); diff --git a/src/views/settings/relays/index.tsx b/src/views/settings/relays/index.tsx index b0cc776c2..ac3e12222 100644 --- a/src/views/settings/relays/index.tsx +++ b/src/views/settings/relays/index.tsx @@ -4,7 +4,6 @@ import { WarningIcon } from "@chakra-ui/icons"; import { RECOMMENDED_READ_RELAYS, RECOMMENDED_WRITE_RELAYS } from "../../../const"; import AddRelayForm from "./add-relay-form"; -import { RelayMode } from "../../../classes/relay"; import { useReadRelays, useWriteRelays } from "../../../hooks/use-client-relays"; import { useActiveAccount } from "applesauce-react/hooks"; import RelayControl from "./relay-control"; @@ -15,7 +14,7 @@ import { mergeRelaySets, safeRelayUrls } from "../../../helpers/relay"; import HoverLinkOverlay from "../../../components/hover-link-overlay"; import SimpleView from "../../../components/layout/presets/simple-view"; import localSettings from "../../../services/local-settings"; -import { addAppRelay } from "../../../services/app-relays"; +import { addAppRelay, RelayMode } from "../../../services/app-relays"; import useUserMailboxes from "../../../hooks/use-user-mailboxes"; const JAPANESE_RELAYS = safeRelayUrls([ diff --git a/src/views/settings/relays/relay-control.tsx b/src/views/settings/relays/relay-control.tsx index ebcb9bf89..ce69fd06e 100644 --- a/src/views/settings/relays/relay-control.tsx +++ b/src/views/settings/relays/relay-control.tsx @@ -6,8 +6,7 @@ import RelayFavicon from "../../../components/relay-favicon"; import UploadCloud01 from "../../../components/icons/upload-cloud-01"; import { useWriteRelays } from "../../../hooks/use-client-relays"; import localSettings from "../../../services/local-settings"; -import { removeAppRelay } from "../../../services/app-relays"; -import { RelayMode } from "../../../classes/relay"; +import { RelayMode, removeAppRelay } from "../../../services/app-relays"; export default function RelayControl({ url }: { url: string }) { const writeRelays = useWriteRelays(); diff --git a/src/views/wiki/create.tsx b/src/views/wiki/create.tsx index 0804c1dcb..f233f428d 100644 --- a/src/views/wiki/create.tsx +++ b/src/views/wiki/create.tsx @@ -31,7 +31,6 @@ import { useReadRelays } from "../../hooks/use-client-relays"; import UserName from "../../components/user/user-name"; import { getEventCoordinate } from "../../helpers/nostr/event"; import FormatButton from "./components/format-toolbar"; -import dictionaryService from "../../services/dictionary"; import { getSharableEventAddress } from "../../services/relay-hints"; export default function CreateWikiPageView() { @@ -109,7 +108,6 @@ export default function CreateWikiPageView() { } const pub = await publish("Publish Page", draft, WIKI_RELAYS, false); - dictionaryService.handleEvent(pub.event); clearFormCache(); navigate(`/wiki/page/${getSharableEventAddress(pub.event)}`, { replace: true }); } catch (error) { diff --git a/src/views/wiki/edit.tsx b/src/views/wiki/edit.tsx index 7625c8bd4..e8bb9e151 100644 --- a/src/views/wiki/edit.tsx +++ b/src/views/wiki/edit.tsx @@ -25,7 +25,6 @@ import MarkdownEditor from "./components/markdown-editor"; import { ErrorBoundary } from "../../components/error-boundary"; import { cloneEvent, replaceOrAddSimpleTag } from "../../helpers/nostr/event"; import FormatButton from "./components/format-toolbar"; -import dictionaryService from "../../services/dictionary"; import { getSharableEventAddress } from "../../services/relay-hints"; function EditWikiPagePage({ page }: { page: NostrEvent }) { @@ -62,7 +61,6 @@ function EditWikiPagePage({ page }: { page: NostrEvent }) { replaceOrAddSimpleTag(draft, "summary", values.summary); const pub = await publish("Publish Page", draft, WIKI_RELAYS, false); - dictionaryService.handleEvent(pub.event); clearFormCache(); navigate(`/wiki/page/${getSharableEventAddress(pub.event)}`, { replace: true }); } catch (error) { diff --git a/src/views/wiki/index.tsx b/src/views/wiki/index.tsx index c51d1f63c..a80dc3592 100644 --- a/src/views/wiki/index.tsx +++ b/src/views/wiki/index.tsx @@ -1,21 +1,20 @@ -import { AvatarGroup, Link, Button, Flex, Heading, LinkBox, SimpleGrid, useInterval } from "@chakra-ui/react"; +import { AvatarGroup, Link, Button, Flex, Heading, LinkBox, SimpleGrid } from "@chakra-ui/react"; import { Link as RouterLink } from "react-router-dom"; +import { useStoreQuery } from "applesauce-react/hooks"; import { NostrEvent } from "nostr-tools"; +import { WIKI_RELAYS } from "../../const"; import VerticalPageLayout from "../../components/vertical-page-layout"; import WikiSearchForm from "./components/wiki-search-form"; import { WIKI_PAGE_KIND, validatePage } from "../../helpers/nostr/wiki"; import useTimelineLoader from "../../hooks/use-timeline-loader"; import { useReadRelays } from "../../hooks/use-client-relays"; import TimelineActionAndStatus from "../../components/timeline/timeline-action-and-status"; -import { WIKI_RELAYS } from "../../const"; import { ExternalLinkIcon } from "../../components/icons"; import WikiLink from "../../components/markdown/wiki-link"; -import { useEffect } from "react"; -import dictionaryService from "../../services/dictionary"; import UserAvatar from "../../components/user/user-avatar"; import HoverLinkOverlay from "../../components/hover-link-overlay"; -import useForceUpdate from "../../hooks/use-force-update"; +import { WikiTopicsQuery } from "../../queries/wiki-topics"; function eventFilter(event: NostrEvent) { if (!validatePage(event)) return false; @@ -28,16 +27,7 @@ export default function WikiHomeView() { eventFilter, }); - useEffect(() => { - if (pages) { - for (const page of pages) { - dictionaryService.handleEvent(page); - } - } - }, [pages]); - - const update = useForceUpdate(); - useInterval(update, 1000); + const topics = useStoreQuery(WikiTopicsQuery, []); return ( @@ -60,23 +50,23 @@ export default function WikiHomeView() { Recent Updates: - {Array.from(dictionaryService.topics) - .filter(([_, sub]) => !!sub.value && sub.value.size > 0) - .sort((a, b) => b[1].value!.size - a[1].value!.size) - .map(([topic, sub]) => ( - - - - {topic} - - - - {Array.from(sub.value!.values()).map((page) => ( - - ))} - - - ))} + {topics && + Object.entries(topics) + .sort((a, b) => b[1].length - a[1].length) + .map(([topic, events]) => ( + + + + {topic} + + + + {events.map((page) => ( + + ))} + + + ))} diff --git a/src/views/wiki/page.tsx b/src/views/wiki/page.tsx index afa1185d3..bd91a64ed 100644 --- a/src/views/wiki/page.tsx +++ b/src/views/wiki/page.tsx @@ -1,4 +1,3 @@ -import { useMemo } from "react"; import { NostrEvent, nip19 } from "nostr-tools"; import { Alert, @@ -14,7 +13,6 @@ import { Text, } from "@chakra-ui/react"; import { Link as RouterLink } from "react-router-dom"; -import { useObservable } from "applesauce-react/hooks"; import useParamsAddressPointer from "../../hooks/use-params-address-pointer"; import useReplaceableEvent from "../../hooks/use-replaceable-event"; @@ -35,10 +33,10 @@ import EventQuoteButton from "../../components/note/event-quote-button"; import WikiPageMenu from "./components/wiki-page-menu"; import EventVoteButtons from "../../components/reactions/event-vote-buttions"; import { useActiveAccount } from "applesauce-react/hooks"; -import dictionaryService from "../../services/dictionary"; import { useReadRelays } from "../../hooks/use-client-relays"; import { useWebOfTrust } from "../../providers/global/web-of-trust-provider"; import { getSharableEventAddress } from "../../services/relay-hints"; +import useWikiPages from "../../hooks/use-wiki-pages"; function ForkAlert({ page, address }: { page: NostrEvent; address: nip19.AddressPointer }) { const topic = getPageTopic(page); @@ -141,8 +139,7 @@ function WikiPageFooter({ page }: { page: NostrEvent }) { const topic = getPageTopic(page); const readRelays = useReadRelays(); - const subject = useMemo(() => dictionaryService.requestTopic(topic, readRelays), [topic, readRelays]); - const pages = useObservable(subject); + const pages = useWikiPages(topic, readRelays, true); let forks = pages ? Array.from(pages.values()).filter((p) => getPageForks(p).address?.pubkey === page.pubkey) : []; if (webOfTrust) forks = webOfTrust.sortByDistanceAndConnections(forks, (p) => p.pubkey); diff --git a/src/views/wiki/search.tsx b/src/views/wiki/search.tsx index 2467aabca..c5698c47d 100644 --- a/src/views/wiki/search.tsx +++ b/src/views/wiki/search.tsx @@ -13,9 +13,10 @@ import { DEFAULT_SEARCH_RELAYS, WIKI_RELAYS } from "../../const"; import { WIKI_PAGE_KIND } from "../../helpers/nostr/wiki"; import { cacheRelay$ } from "../../services/cache-relay"; import WikiPageResult from "./components/wiki-page-result"; -import dictionaryService from "../../services/dictionary"; import { useWebOfTrust } from "../../providers/global/web-of-trust-provider"; import { useObservable } from "applesauce-react/hooks"; +import { eventStore } from "../../services/event-store"; +import { ErrorBoundary } from "../../components/error-boundary"; export default function WikiSearchView() { const cacheRelay = useObservable(cacheRelay$); @@ -37,7 +38,8 @@ export default function WikiSearchView() { const seen = new Set(); const handleEvent = (event: NostrEvent) => { - dictionaryService.handleEvent(event); + eventStore.add(event); + if (seen.has(getEventUID(event))) return; setResults((arr) => arr.concat(event)); seen.add(getEventUID(event)); @@ -82,7 +84,9 @@ export default function WikiSearchView() { {sorted.map((page) => ( - + + + ))} ); diff --git a/src/views/wiki/topic.tsx b/src/views/wiki/topic.tsx index f7cf5bd4a..bafe002d3 100644 --- a/src/views/wiki/topic.tsx +++ b/src/views/wiki/topic.tsx @@ -1,11 +1,8 @@ import { Button, Flex, Heading, Link } from "@chakra-ui/react"; import { Navigate, useParams, Link as RouterLink } from "react-router-dom"; -import { useObservable } from "applesauce-react/hooks"; import { NostrEvent } from "nostr-tools"; import VerticalPageLayout from "../../components/vertical-page-layout"; -import { useMemo } from "react"; -import dictionaryService from "../../services/dictionary"; import { useReadRelays } from "../../hooks/use-client-relays"; import WikiPageHeader from "./components/wiki-page-header"; import UserAvatar from "../../components/user/user-avatar"; @@ -14,6 +11,7 @@ import { WikiPagePage } from "./page"; import { useWebOfTrust } from "../../providers/global/web-of-trust-provider"; import useRouteSearchValue from "../../hooks/use-route-search-value"; import { getPageDefer } from "../../helpers/nostr/wiki"; +import useWikiPages from "../../hooks/use-wiki-pages"; export default function WikiTopicView() { const { topic } = useParams(); @@ -21,9 +19,7 @@ export default function WikiTopicView() { const webOfTrust = useWebOfTrust(); const readRelays = useReadRelays(); - const subject = useMemo(() => dictionaryService.requestTopic(topic, readRelays, true), [topic, readRelays]); - - const pages = useObservable(subject); + const pages = useWikiPages(topic, readRelays, true); let sorted = pages ? Array.from(pages.values()) : []; if (webOfTrust) sorted = webOfTrust.sortByDistanceAndConnections(sorted, (p) => p.pubkey);