Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1553f5ced2 | ||
|
|
41901b2174 | ||
|
|
177e4c1ff7 | ||
|
|
10036500cb | ||
|
|
a1fa777f8c | ||
|
|
472925bb05 | ||
|
|
8eb11efb34 | ||
|
|
48066a4018 | ||
|
|
5c8850ea8f | ||
|
|
09aea3cff5 | ||
|
|
45c5a890b9 |
12
package.json
12
package.json
@@ -2,7 +2,7 @@
|
||||
"name": "lume",
|
||||
"description": "the communication app",
|
||||
"private": true,
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.4",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
@@ -20,7 +20,7 @@
|
||||
"dependencies": {
|
||||
"@ctrl/magnet-link": "^3.1.2",
|
||||
"@getalby/sdk": "^2.4.0",
|
||||
"@nostr-dev-kit/ndk": "^0.8.23",
|
||||
"@nostr-dev-kit/ndk": "^1.0.0",
|
||||
"@nostr-fetch/adapter-ndk": "^0.12.2",
|
||||
"@radix-ui/react-alert-dialog": "^1.0.4",
|
||||
"@radix-ui/react-collapsible": "^1.0.3",
|
||||
@@ -28,7 +28,7 @@
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.5",
|
||||
"@radix-ui/react-popover": "^1.0.6",
|
||||
"@radix-ui/react-tooltip": "^1.0.6",
|
||||
"@tanstack/react-query": "^4.33.0",
|
||||
"@tanstack/react-query": "^4.35.0",
|
||||
"@tanstack/react-virtual": "3.0.0-beta.54",
|
||||
"@tauri-apps/api": "^1.4.0",
|
||||
"@tiptap/extension-image": "^2.1.8",
|
||||
@@ -54,10 +54,10 @@
|
||||
"react-hook-form": "^7.46.1",
|
||||
"react-hotkeys-hook": "^4.4.1",
|
||||
"react-markdown": "^8.0.7",
|
||||
"react-player": "^2.12.0",
|
||||
"react-player": "^2.13.0",
|
||||
"react-router-dom": "^6.15.0",
|
||||
"react-textarea-autosize": "^8.5.3",
|
||||
"react-virtuoso": "^4.5.0",
|
||||
"react-virtuoso": "^4.5.1",
|
||||
"remark-gfm": "^3.0.1",
|
||||
"tauri-plugin-sql-api": "github:tauri-apps/tauri-plugin-sql#v1",
|
||||
"tauri-plugin-store-api": "github:tauri-apps/tauri-plugin-store#v1",
|
||||
@@ -67,7 +67,7 @@
|
||||
"zustand": "^4.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "^0.5.9",
|
||||
"@tailwindcss/typography": "^0.5.10",
|
||||
"@tauri-apps/cli": "^1.4.0",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.2.0",
|
||||
"@types/html-to-text": "^9.0.1",
|
||||
|
||||
246
pnpm-lock.yaml
generated
246
pnpm-lock.yaml
generated
@@ -8,11 +8,11 @@ dependencies:
|
||||
specifier: ^2.4.0
|
||||
version: 2.4.0
|
||||
'@nostr-dev-kit/ndk':
|
||||
specifier: ^0.8.23
|
||||
version: 0.8.23(typescript@5.2.2)
|
||||
specifier: ^1.0.0
|
||||
version: 1.0.0(typescript@5.2.2)
|
||||
'@nostr-fetch/adapter-ndk':
|
||||
specifier: ^0.12.2
|
||||
version: 0.12.2(@nostr-dev-kit/ndk@0.8.23)(nostr-fetch@0.13.0)
|
||||
version: 0.12.2(@nostr-dev-kit/ndk@1.0.0)(nostr-fetch@0.13.0)
|
||||
'@radix-ui/react-alert-dialog':
|
||||
specifier: ^1.0.4
|
||||
version: 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.21)(react-dom@18.2.0)(react@18.2.0)
|
||||
@@ -32,8 +32,8 @@ dependencies:
|
||||
specifier: ^1.0.6
|
||||
version: 1.0.6(@types/react-dom@18.2.7)(@types/react@18.2.21)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@tanstack/react-query':
|
||||
specifier: ^4.33.0
|
||||
version: 4.33.0(react-dom@18.2.0)(react@18.2.0)
|
||||
specifier: ^4.35.0
|
||||
version: 4.35.0(react-dom@18.2.0)(react@18.2.0)
|
||||
'@tanstack/react-virtual':
|
||||
specifier: 3.0.0-beta.54
|
||||
version: 3.0.0-beta.54(react@18.2.0)
|
||||
@@ -110,8 +110,8 @@ dependencies:
|
||||
specifier: ^8.0.7
|
||||
version: 8.0.7(@types/react@18.2.21)(react@18.2.0)
|
||||
react-player:
|
||||
specifier: ^2.12.0
|
||||
version: 2.12.0(react@18.2.0)
|
||||
specifier: ^2.13.0
|
||||
version: 2.13.0(react@18.2.0)
|
||||
react-router-dom:
|
||||
specifier: ^6.15.0
|
||||
version: 6.15.0(react-dom@18.2.0)(react@18.2.0)
|
||||
@@ -119,8 +119,8 @@ dependencies:
|
||||
specifier: ^8.5.3
|
||||
version: 8.5.3(@types/react@18.2.21)(react@18.2.0)
|
||||
react-virtuoso:
|
||||
specifier: ^4.5.0
|
||||
version: 4.5.0(react-dom@18.2.0)(react@18.2.0)
|
||||
specifier: ^4.5.1
|
||||
version: 4.5.1(react-dom@18.2.0)(react@18.2.0)
|
||||
remark-gfm:
|
||||
specifier: ^3.0.1
|
||||
version: 3.0.1
|
||||
@@ -145,8 +145,8 @@ dependencies:
|
||||
|
||||
devDependencies:
|
||||
'@tailwindcss/typography':
|
||||
specifier: ^0.5.9
|
||||
version: 0.5.9(tailwindcss@3.3.3)
|
||||
specifier: ^0.5.10
|
||||
version: 0.5.10(tailwindcss@3.3.3)
|
||||
'@tauri-apps/cli':
|
||||
specifier: ^1.4.0
|
||||
version: 1.4.0
|
||||
@@ -312,8 +312,8 @@ packages:
|
||||
chalk: 2.4.2
|
||||
js-tokens: 4.0.0
|
||||
|
||||
/@babel/parser@7.22.15:
|
||||
resolution: {integrity: sha512-RWmQ/sklUN9BvGGpCDgSubhHWfAx24XDTDObup4ffvxaYsptOg2P3KG0j+1eWKLxpkX0j0uHxmpq2Z1SP/VhxA==}
|
||||
/@babel/parser@7.22.16:
|
||||
resolution: {integrity: sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
@@ -331,7 +331,7 @@ packages:
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.22.13
|
||||
'@babel/parser': 7.22.15
|
||||
'@babel/parser': 7.22.16
|
||||
'@babel/types': 7.22.15
|
||||
dev: true
|
||||
|
||||
@@ -345,7 +345,7 @@ packages:
|
||||
'@babel/helper-function-name': 7.22.5
|
||||
'@babel/helper-hoist-variables': 7.22.5
|
||||
'@babel/helper-split-export-declaration': 7.22.6
|
||||
'@babel/parser': 7.22.15
|
||||
'@babel/parser': 7.22.16
|
||||
'@babel/types': 7.17.0
|
||||
debug: 4.3.4
|
||||
globals: 11.12.0
|
||||
@@ -950,8 +950,8 @@ packages:
|
||||
'@nodelib/fs.scandir': 2.1.5
|
||||
fastq: 1.15.0
|
||||
|
||||
/@nostr-dev-kit/ndk@0.8.23(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-wX/9Cl02gCR0Kz25C/1xxGO47K13Ve1x8IISbkF/M3RTTXftYBvzB7bL8qwLaFaeqb02cMU0YVL+oKDrYzH/Ng==}
|
||||
/@nostr-dev-kit/ndk@1.0.0(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-EY2MVHZgHp6RSudnLVoWYYP1BQvtb4nX3Vafoa4LzmME5dD8i0XLURdW29h7+87mluPdLTJLMI6wTZWEy2NFUQ==}
|
||||
dependencies:
|
||||
'@noble/hashes': 1.3.2
|
||||
'@noble/secp256k1': 2.0.0
|
||||
@@ -970,6 +970,7 @@ packages:
|
||||
node-fetch: 3.3.2
|
||||
nostr-tools: 1.14.2
|
||||
tsd: 0.28.1
|
||||
typescript-lru-cache: 2.0.0
|
||||
utf8-buffer: 1.0.0
|
||||
transitivePeerDependencies:
|
||||
- eslint-import-resolver-typescript
|
||||
@@ -978,13 +979,13 @@ packages:
|
||||
- typescript
|
||||
dev: false
|
||||
|
||||
/@nostr-fetch/adapter-ndk@0.12.2(@nostr-dev-kit/ndk@0.8.23)(nostr-fetch@0.13.0):
|
||||
/@nostr-fetch/adapter-ndk@0.12.2(@nostr-dev-kit/ndk@1.0.0)(nostr-fetch@0.13.0):
|
||||
resolution: {integrity: sha512-+7EVuxS5DDZvNo6qbfFp7xRHwIyjyi36hYkiQFDjbQ4gX5LKo9RIPB1P+1XGkOSDFshypTbovZCaFunscJ/zhQ==}
|
||||
peerDependencies:
|
||||
'@nostr-dev-kit/ndk': ^0.7.5
|
||||
nostr-fetch: ^0.12.2
|
||||
dependencies:
|
||||
'@nostr-dev-kit/ndk': 0.8.23(typescript@5.2.2)
|
||||
'@nostr-dev-kit/ndk': 1.0.0(typescript@5.2.2)
|
||||
'@nostr-fetch/kernel': 0.12.2
|
||||
nostr-fetch: 0.13.0
|
||||
dev: false
|
||||
@@ -1695,15 +1696,15 @@ packages:
|
||||
resolution: {integrity: sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==}
|
||||
dependencies:
|
||||
'@noble/curves': 1.1.0
|
||||
'@noble/hashes': 1.3.2
|
||||
'@scure/base': 1.1.3
|
||||
'@noble/hashes': 1.3.1
|
||||
'@scure/base': 1.1.1
|
||||
dev: false
|
||||
|
||||
/@scure/bip39@1.2.1:
|
||||
resolution: {integrity: sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==}
|
||||
dependencies:
|
||||
'@noble/hashes': 1.3.2
|
||||
'@scure/base': 1.1.3
|
||||
'@noble/hashes': 1.3.1
|
||||
'@scure/base': 1.1.1
|
||||
dev: false
|
||||
|
||||
/@selderee/plugin-htmlparser2@0.11.0:
|
||||
@@ -1717,8 +1718,8 @@ packages:
|
||||
resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
|
||||
dev: false
|
||||
|
||||
/@swc/core-darwin-arm64@1.3.82:
|
||||
resolution: {integrity: sha512-JfsyDW34gVKD3uE0OUpUqYvAD3yseEaicnFP6pB292THtLJb0IKBBnK50vV/RzEJtc1bR3g1kNfxo2PeurZTrA==}
|
||||
/@swc/core-darwin-arm64@1.3.83:
|
||||
resolution: {integrity: sha512-Plz2IKeveVLivbXTSCC3OZjD2MojyKYllhPrn9RotkDIZEFRYJZtW5/Ik1tJW/2rzu5HVKuGYrDKdScVVTbOxQ==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
@@ -1726,8 +1727,8 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-darwin-x64@1.3.82:
|
||||
resolution: {integrity: sha512-ogQWgNMq7qTpITjcP3dnzkFNj7bh6SwMr859GvtOTrE75H7L7jDWxESfH4f8foB/LGxBKiDNmxKhitCuAsZK4A==}
|
||||
/@swc/core-darwin-x64@1.3.83:
|
||||
resolution: {integrity: sha512-FBGVg5IPF/8jQ6FbK60iDUHjv0H5+LwfpJHKH6wZnRaYWFtm7+pzYgreLu3NTsm3m7/1a7t0+7KURwBGUaJCCw==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
@@ -1735,8 +1736,8 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-arm-gnueabihf@1.3.82:
|
||||
resolution: {integrity: sha512-7TMXG1lXlNhD0kUiEqs+YlGV4irAdBa2quuy+XI3oJf2fBK6dQfEq4xBy65B3khrorzQS3O0oDGQ+cmdpHExHA==}
|
||||
/@swc/core-linux-arm-gnueabihf@1.3.83:
|
||||
resolution: {integrity: sha512-EZcsuRYhGkzofXtzwDjuuBC/suiX9s7zeg2YYXOVjWwyebb6BUhB1yad3mcykFQ20rTLO9JUyIaiaMYDHGobqw==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
@@ -1744,8 +1745,8 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-arm64-gnu@1.3.82:
|
||||
resolution: {integrity: sha512-26JkOujbzcItPAmIbD5vHJxQVy5ihcSu3YHTKwope1h28sApZdtE7S3e2G3gsZRTIdsCQkXUtAQeqHxGWWR3pw==}
|
||||
/@swc/core-linux-arm64-gnu@1.3.83:
|
||||
resolution: {integrity: sha512-khI41szLHrCD/cFOcN4p2SYvZgHjhhHlcMHz5BksRrDyteSJKu0qtWRZITVom0N/9jWoAleoFhMnFTUs0H8IWA==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
@@ -1753,8 +1754,8 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-arm64-musl@1.3.82:
|
||||
resolution: {integrity: sha512-8Izj9tuuMpoc3cqiPBRtwqpO1BZ/+sfZVsEhLxrbOFlcSb8LnKyMle1g3JMMUwI4EU75RGVIzZMn8A6GOKdJbA==}
|
||||
/@swc/core-linux-arm64-musl@1.3.83:
|
||||
resolution: {integrity: sha512-zgT7yNOdbjHcGAwvys79mbfNLK65KBlPJWzeig+Yk7I8TVzmaQge7B6ZS/gwF9/p+8TiLYo/tZ5aF2lqlgdSVw==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
@@ -1762,8 +1763,8 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-x64-gnu@1.3.82:
|
||||
resolution: {integrity: sha512-0GSrIBScQwTaPv46T2qB7XnDYxndRCpwH4HMjh6FN+I+lfPUhTSJKW8AonqrqT1TbpFIgvzQs7EnTsD7AnSCow==}
|
||||
/@swc/core-linux-x64-gnu@1.3.83:
|
||||
resolution: {integrity: sha512-x+mH0Y3NC/G0YNlFmGi3vGD4VOm7IPDhh+tGrx6WtJp0BsShAbOpxtfU885rp1QweZe4qYoEmGqiEjE2WrPIdA==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
@@ -1771,8 +1772,8 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-x64-musl@1.3.82:
|
||||
resolution: {integrity: sha512-KJUnaaepDKNzrEbwz4jv0iC3/t9x0NSoe06fnkAlhh2+NFKWKKJhVCOBTrpds8n7eylBDIXUlK34XQafjVMUdg==}
|
||||
/@swc/core-linux-x64-musl@1.3.83:
|
||||
resolution: {integrity: sha512-s5AYhAOmetUwUZwS5g9qb92IYgNHHBGiY2mTLImtEgpAeBwe0LPDj6WrujxCBuZnaS55mKRLLOuiMZE5TpjBNA==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
@@ -1780,8 +1781,8 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-win32-arm64-msvc@1.3.82:
|
||||
resolution: {integrity: sha512-TR3MHKhDYIyGyFcyl2d/p1ftceXcubAhX5wRSOdtOyr5+K/v3jbyCCqN7bbqO5o43wQVCwwR/drHleYyDZvg8Q==}
|
||||
/@swc/core-win32-arm64-msvc@1.3.83:
|
||||
resolution: {integrity: sha512-yw2rd/KVOGs95lRRB+killLWNaO1dy4uVa8Q3/4wb5txlLru07W1m041fZLzwOg/1Sh0TMjJgGxj0XHGR3ZXhQ==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
@@ -1789,8 +1790,8 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-win32-ia32-msvc@1.3.82:
|
||||
resolution: {integrity: sha512-ZX4HzVVt6hs84YUg70UvyBJnBOIspmQQM0iXSzBvOikk3zRoN7BnDwQH4GScvevCEBuou60+i4I6d5kHLOfh8Q==}
|
||||
/@swc/core-win32-ia32-msvc@1.3.83:
|
||||
resolution: {integrity: sha512-POW+rgZ6KWqBpwPGIRd2/3pcf46P+UrKBm4HLt5IwbHvekJ4avIM8ixJa9kK0muJNVJcDpaZgxaU1ELxtJ1j8w==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
@@ -1798,8 +1799,8 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-win32-x64-msvc@1.3.82:
|
||||
resolution: {integrity: sha512-4mJMnex21kbQoaHeAmHnVwQN9/XAfPszJ6n9HI7SVH+aAHnbBIR0M59/b50/CJMjTj5niUGk7EwQ3nhVNOG32g==}
|
||||
/@swc/core-win32-x64-msvc@1.3.83:
|
||||
resolution: {integrity: sha512-CiWQtkFnZElXQUalaHp+Wacw0Jd+24ncRYhqaJ9YKnEQP1H82CxIIuQqLM8IFaLpn5dpY6SgzaeubWF46hjcLA==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
@@ -1807,8 +1808,8 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core@1.3.82:
|
||||
resolution: {integrity: sha512-jpC1a18HMH67018Ij2jh+hT7JBFu7ZKcQVfrZ8K6JuEY+kjXmbea07P9MbQUZbAe0FB+xi3CqEVCP73MebodJQ==}
|
||||
/@swc/core@1.3.83:
|
||||
resolution: {integrity: sha512-PccHDgGQlFjpExgJxH91qA3a4aifR+axCFJ4RieCoiI0m5gURE4nBhxzTBY5YU/YKTBmPO8Gc5Q6inE3+NquWg==}
|
||||
engines: {node: '>=10'}
|
||||
requiresBuild: true
|
||||
peerDependencies:
|
||||
@@ -1819,24 +1820,24 @@ packages:
|
||||
dependencies:
|
||||
'@swc/types': 0.1.4
|
||||
optionalDependencies:
|
||||
'@swc/core-darwin-arm64': 1.3.82
|
||||
'@swc/core-darwin-x64': 1.3.82
|
||||
'@swc/core-linux-arm-gnueabihf': 1.3.82
|
||||
'@swc/core-linux-arm64-gnu': 1.3.82
|
||||
'@swc/core-linux-arm64-musl': 1.3.82
|
||||
'@swc/core-linux-x64-gnu': 1.3.82
|
||||
'@swc/core-linux-x64-musl': 1.3.82
|
||||
'@swc/core-win32-arm64-msvc': 1.3.82
|
||||
'@swc/core-win32-ia32-msvc': 1.3.82
|
||||
'@swc/core-win32-x64-msvc': 1.3.82
|
||||
'@swc/core-darwin-arm64': 1.3.83
|
||||
'@swc/core-darwin-x64': 1.3.83
|
||||
'@swc/core-linux-arm-gnueabihf': 1.3.83
|
||||
'@swc/core-linux-arm64-gnu': 1.3.83
|
||||
'@swc/core-linux-arm64-musl': 1.3.83
|
||||
'@swc/core-linux-x64-gnu': 1.3.83
|
||||
'@swc/core-linux-x64-musl': 1.3.83
|
||||
'@swc/core-win32-arm64-msvc': 1.3.83
|
||||
'@swc/core-win32-ia32-msvc': 1.3.83
|
||||
'@swc/core-win32-x64-msvc': 1.3.83
|
||||
dev: true
|
||||
|
||||
/@swc/types@0.1.4:
|
||||
resolution: {integrity: sha512-z/G02d+59gyyUb7KYhKi9jOhicek6QD2oMaotUyG+lUkybpXoV49dY9bj7Ah5Q+y7knK2jU67UTX9FyfGzaxQg==}
|
||||
dev: true
|
||||
|
||||
/@tailwindcss/typography@0.5.9(tailwindcss@3.3.3):
|
||||
resolution: {integrity: sha512-t8Sg3DyynFysV9f4JDOVISGsjazNb48AeIYQwcL+Bsq5uf4RYL75C1giZ43KISjeDGBaTN3Kxh7Xj/vRSMJUUg==}
|
||||
/@tailwindcss/typography@0.5.10(tailwindcss@3.3.3):
|
||||
resolution: {integrity: sha512-Pe8BuPJQJd3FfRnm6H0ulKIGoMEQS+Vq01R6M5aCrFB/ccR/shT+0kXLjouGC1gFLm9hopTFN+DMP0pfwRWzPw==}
|
||||
peerDependencies:
|
||||
tailwindcss: '>=3.0.0 || insiders'
|
||||
dependencies:
|
||||
@@ -1847,12 +1848,12 @@ packages:
|
||||
tailwindcss: 3.3.3
|
||||
dev: true
|
||||
|
||||
/@tanstack/query-core@4.33.0:
|
||||
resolution: {integrity: sha512-qYu73ptvnzRh6se2nyBIDHGBQvPY1XXl3yR769B7B6mIDD7s+EZhdlWHQ67JI6UOTFRaI7wupnTnwJ3gE0Mr/g==}
|
||||
/@tanstack/query-core@4.35.0:
|
||||
resolution: {integrity: sha512-4GMcKQuLZQi6RFBiBZNsLhl+hQGYScRZ5ZoVq8QAzfqz9M7vcGin/2YdSESwl7WaV+Qzsb5CZOAbMBes4lNTnA==}
|
||||
dev: false
|
||||
|
||||
/@tanstack/react-query@4.33.0(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-97nGbmDK0/m0B86BdiXzx3EW9RcDYKpnyL2+WwyuLHEgpfThYAnXFaMMmnTDuAO4bQJXEhflumIEUfKmP7ESGA==}
|
||||
/@tanstack/react-query@4.35.0(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-LLYDNnM9ewYHgjm2rzhk4KG/puN2rdoqCUD+N9+V7SwlsYwJk5ypX58rpkoZAhFyZ+KmFUJ7Iv2lIEOoUqydIg==}
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
@@ -1863,7 +1864,7 @@ packages:
|
||||
react-native:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@tanstack/query-core': 4.33.0
|
||||
'@tanstack/query-core': 4.35.0
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
use-sync-external-store: 1.2.0(react@18.2.0)
|
||||
@@ -2293,7 +2294,7 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/generator': 7.17.7
|
||||
'@babel/parser': 7.22.15
|
||||
'@babel/parser': 7.22.16
|
||||
'@babel/traverse': 7.17.3
|
||||
'@babel/types': 7.17.0
|
||||
javascript-natural-sort: 0.7.1
|
||||
@@ -2455,7 +2456,7 @@ packages:
|
||||
ignore: 5.2.4
|
||||
natural-compare: 1.4.0
|
||||
semver: 7.5.4
|
||||
ts-api-utils: 1.0.2(typescript@5.2.2)
|
||||
ts-api-utils: 1.0.3(typescript@5.2.2)
|
||||
typescript: 5.2.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -2552,7 +2553,7 @@ packages:
|
||||
'@typescript-eslint/utils': 6.6.0(eslint@8.48.0)(typescript@5.2.2)
|
||||
debug: 4.3.4
|
||||
eslint: 8.48.0
|
||||
ts-api-utils: 1.0.2(typescript@5.2.2)
|
||||
ts-api-utils: 1.0.3(typescript@5.2.2)
|
||||
typescript: 5.2.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -2604,7 +2605,7 @@ packages:
|
||||
globby: 11.1.0
|
||||
is-glob: 4.0.3
|
||||
semver: 7.5.4
|
||||
ts-api-utils: 1.0.2(typescript@5.2.2)
|
||||
ts-api-utils: 1.0.3(typescript@5.2.2)
|
||||
typescript: 5.2.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -2670,7 +2671,7 @@ packages:
|
||||
peerDependencies:
|
||||
vite: ^4
|
||||
dependencies:
|
||||
'@swc/core': 1.3.82
|
||||
'@swc/core': 1.3.83
|
||||
vite: 4.4.9(@types/node@20.5.9)
|
||||
transitivePeerDependencies:
|
||||
- '@swc/helpers'
|
||||
@@ -2810,8 +2811,8 @@ packages:
|
||||
get-intrinsic: 1.2.1
|
||||
dev: false
|
||||
|
||||
/array.prototype.flat@1.3.1:
|
||||
resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==}
|
||||
/array.prototype.flat@1.3.2:
|
||||
resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
dependencies:
|
||||
call-bind: 1.0.2
|
||||
@@ -2819,8 +2820,8 @@ packages:
|
||||
es-abstract: 1.22.1
|
||||
es-shim-unscopables: 1.0.0
|
||||
|
||||
/array.prototype.flatmap@1.3.1:
|
||||
resolution: {integrity: sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==}
|
||||
/array.prototype.flatmap@1.3.2:
|
||||
resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
dependencies:
|
||||
call-bind: 1.0.2
|
||||
@@ -2828,8 +2829,8 @@ packages:
|
||||
es-abstract: 1.22.1
|
||||
es-shim-unscopables: 1.0.0
|
||||
|
||||
/array.prototype.tosorted@1.1.1:
|
||||
resolution: {integrity: sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==}
|
||||
/array.prototype.tosorted@1.1.2:
|
||||
resolution: {integrity: sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==}
|
||||
dependencies:
|
||||
call-bind: 1.0.2
|
||||
define-properties: 1.2.0
|
||||
@@ -2838,13 +2839,14 @@ packages:
|
||||
get-intrinsic: 1.2.1
|
||||
dev: true
|
||||
|
||||
/arraybuffer.prototype.slice@1.0.1:
|
||||
resolution: {integrity: sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==}
|
||||
/arraybuffer.prototype.slice@1.0.2:
|
||||
resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
dependencies:
|
||||
array-buffer-byte-length: 1.0.0
|
||||
call-bind: 1.0.2
|
||||
define-properties: 1.2.0
|
||||
es-abstract: 1.22.1
|
||||
get-intrinsic: 1.2.1
|
||||
is-array-buffer: 3.0.2
|
||||
is-shared-array-buffer: 1.0.2
|
||||
@@ -2872,7 +2874,7 @@ packages:
|
||||
postcss: ^8.1.0
|
||||
dependencies:
|
||||
browserslist: 4.21.10
|
||||
caniuse-lite: 1.0.30001525
|
||||
caniuse-lite: 1.0.30001528
|
||||
fraction.js: 4.3.6
|
||||
normalize-range: 0.1.2
|
||||
picocolors: 1.0.0
|
||||
@@ -2884,8 +2886,8 @@ packages:
|
||||
resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
/axe-core@4.7.2:
|
||||
resolution: {integrity: sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==}
|
||||
/axe-core@4.8.0:
|
||||
resolution: {integrity: sha512-ZtlVZobOeDQhb/y2lMK6mznDw7TJHDNcKx5/bbBkFvArIQ5CVFhSI6hWWQnMx9I8cNmNmZ30wpDyOC2E2nvgbQ==}
|
||||
engines: {node: '>=4'}
|
||||
dev: true
|
||||
|
||||
@@ -2924,8 +2926,8 @@ packages:
|
||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
caniuse-lite: 1.0.30001525
|
||||
electron-to-chromium: 1.4.508
|
||||
caniuse-lite: 1.0.30001528
|
||||
electron-to-chromium: 1.4.511
|
||||
node-releases: 2.0.13
|
||||
update-browserslist-db: 1.0.11(browserslist@4.21.10)
|
||||
dev: true
|
||||
@@ -2959,8 +2961,8 @@ packages:
|
||||
engines: {node: '>=6'}
|
||||
dev: false
|
||||
|
||||
/caniuse-lite@1.0.30001525:
|
||||
resolution: {integrity: sha512-/3z+wB4icFt3r0USMwxujAqRvaD/B7rvGTsKhbhSQErVrJvkZCLhgNLJxU8MevahQVH6hCU9FsHdNUFbiwmE7Q==}
|
||||
/caniuse-lite@1.0.30001528:
|
||||
resolution: {integrity: sha512-0Db4yyjR9QMNlsxh+kKWzQtkyflkG/snYheSzkjmvdEtEXB1+jt7A2HmSEiO6XIJPIbo92lHNGNySvE5pZcs5Q==}
|
||||
dev: true
|
||||
|
||||
/case-anything@2.1.13:
|
||||
@@ -3284,8 +3286,8 @@ packages:
|
||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
||||
dev: true
|
||||
|
||||
/electron-to-chromium@1.4.508:
|
||||
resolution: {integrity: sha512-FFa8QKjQK/A5QuFr2167myhMesGrhlOBD+3cYNxO9/S4XzHEXesyTD/1/xF644gC8buFPz3ca6G1LOQD0tZrrg==}
|
||||
/electron-to-chromium@1.4.511:
|
||||
resolution: {integrity: sha512-udHyLfdy390CObLy3uFQitCBvK+WxWu6WZWQMBzO/npNiRy6tanDKR1c/F6OImfAiSt1ylgNszPJBxix2c0w3w==}
|
||||
dev: true
|
||||
|
||||
/emoji-regex@8.0.0:
|
||||
@@ -3323,7 +3325,7 @@ packages:
|
||||
engines: {node: '>= 0.4'}
|
||||
dependencies:
|
||||
array-buffer-byte-length: 1.0.0
|
||||
arraybuffer.prototype.slice: 1.0.1
|
||||
arraybuffer.prototype.slice: 1.0.2
|
||||
available-typed-arrays: 1.0.5
|
||||
call-bind: 1.0.2
|
||||
es-set-tostringtag: 2.0.1
|
||||
@@ -3350,11 +3352,11 @@ packages:
|
||||
object-keys: 1.1.1
|
||||
object.assign: 4.1.4
|
||||
regexp.prototype.flags: 1.5.0
|
||||
safe-array-concat: 1.0.0
|
||||
safe-array-concat: 1.0.1
|
||||
safe-regex-test: 1.0.0
|
||||
string.prototype.trim: 1.2.7
|
||||
string.prototype.trimend: 1.0.6
|
||||
string.prototype.trimstart: 1.0.6
|
||||
string.prototype.trim: 1.2.8
|
||||
string.prototype.trimend: 1.0.7
|
||||
string.prototype.trimstart: 1.0.7
|
||||
typed-array-buffer: 1.0.0
|
||||
typed-array-byte-length: 1.0.0
|
||||
typed-array-byte-offset: 1.0.0
|
||||
@@ -3378,7 +3380,7 @@ packages:
|
||||
has-symbols: 1.0.3
|
||||
internal-slot: 1.0.5
|
||||
iterator.prototype: 1.1.1
|
||||
safe-array-concat: 1.0.0
|
||||
safe-array-concat: 1.0.1
|
||||
dev: true
|
||||
|
||||
/es-set-tostringtag@2.0.1:
|
||||
@@ -3568,8 +3570,8 @@ packages:
|
||||
'@typescript-eslint/parser': 5.62.0(eslint@8.48.0)(typescript@5.2.2)
|
||||
array-includes: 3.1.7
|
||||
array.prototype.findlastindex: 1.2.3
|
||||
array.prototype.flat: 1.3.1
|
||||
array.prototype.flatmap: 1.3.1
|
||||
array.prototype.flat: 1.3.2
|
||||
array.prototype.flatmap: 1.3.2
|
||||
debug: 3.2.7
|
||||
doctrine: 2.1.0
|
||||
eslint: 8.48.0
|
||||
@@ -3599,9 +3601,9 @@ packages:
|
||||
'@babel/runtime': 7.22.15
|
||||
aria-query: 5.3.0
|
||||
array-includes: 3.1.7
|
||||
array.prototype.flatmap: 1.3.1
|
||||
array.prototype.flatmap: 1.3.2
|
||||
ast-types-flow: 0.0.7
|
||||
axe-core: 4.7.2
|
||||
axe-core: 4.8.0
|
||||
axobject-query: 3.2.1
|
||||
damerau-levenshtein: 1.0.8
|
||||
emoji-regex: 9.2.2
|
||||
@@ -3622,8 +3624,8 @@ packages:
|
||||
eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8
|
||||
dependencies:
|
||||
array-includes: 3.1.7
|
||||
array.prototype.flatmap: 1.3.1
|
||||
array.prototype.tosorted: 1.1.1
|
||||
array.prototype.flatmap: 1.3.2
|
||||
array.prototype.tosorted: 1.1.2
|
||||
doctrine: 2.1.0
|
||||
es-iterator-helpers: 1.0.14
|
||||
eslint: 8.48.0
|
||||
@@ -4406,8 +4408,8 @@ packages:
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
dev: false
|
||||
|
||||
/jiti@1.19.3:
|
||||
resolution: {integrity: sha512-5eEbBDQT/jF1xg6l36P+mWGGoH9Spuy0PCdSr2dtWRDGC6ph/w9ZCL4lmESW8f8F7MwT3XKescfP0wnZWAKL9w==}
|
||||
/jiti@1.20.0:
|
||||
resolution: {integrity: sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA==}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
@@ -4455,7 +4457,7 @@ packages:
|
||||
engines: {node: '>=4.0'}
|
||||
dependencies:
|
||||
array-includes: 3.1.7
|
||||
array.prototype.flat: 1.3.1
|
||||
array.prototype.flat: 1.3.2
|
||||
object.assign: 4.1.4
|
||||
object.values: 1.1.7
|
||||
dev: true
|
||||
@@ -5255,7 +5257,7 @@ packages:
|
||||
pidtree: 0.3.1
|
||||
read-pkg: 3.0.0
|
||||
shell-quote: 1.8.1
|
||||
string.prototype.padend: 3.1.4
|
||||
string.prototype.padend: 3.1.5
|
||||
dev: false
|
||||
|
||||
/npm-run-path@5.1.0:
|
||||
@@ -5917,8 +5919,8 @@ packages:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/react-player@2.12.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-rymLRz/2GJJD+Wc01S7S+i9pGMFYnNmQibR2gVE3KmHJCBNN8BhPAlOPTGZtn1uKpJ6p4RPLlzPQ1OLreXd8gw==}
|
||||
/react-player@2.13.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-gkY7ZdbVFztlKFFhCPcnDrFQm+L399b8fhWsKatZ+b2wpKJwfUHBXQFMRxqYQGT0ic1/wQ7D7EZEWy7ZBqk2pw==}
|
||||
peerDependencies:
|
||||
react: '>=16.6.0'
|
||||
dependencies:
|
||||
@@ -6019,8 +6021,8 @@ packages:
|
||||
- '@types/react'
|
||||
dev: false
|
||||
|
||||
/react-virtuoso@4.5.0(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-OMP6XrzJMMos1vbJZC16RxGW7utAxUMP7i5PNPi6epBNVH7nz+CF/DlmecNBep5wyjLud51dQ5epjb2A0w9W/Q==}
|
||||
/react-virtuoso@4.5.1(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-Jdo9M/T5PcDAczvmXAKwvb/BW0MCMr/cb+3j2m9192zlQgQ+syMdJR42i+Sk80ln5aSNaL1fnxleJzdKsCc4lw==}
|
||||
engines: {node: '>=10'}
|
||||
peerDependencies:
|
||||
react: '>=16 || >=17 || >= 18'
|
||||
@@ -6182,8 +6184,8 @@ packages:
|
||||
dependencies:
|
||||
glob: 7.2.3
|
||||
|
||||
/rollup@3.28.1:
|
||||
resolution: {integrity: sha512-R9OMQmIHJm9znrU3m3cpE8uhN0fGdXiawME7aZIpQqvpS/85+Vt1Hq1/yVIcYfOmaQiHjvXkQAoJukvLpau6Yw==}
|
||||
/rollup@3.29.0:
|
||||
resolution: {integrity: sha512-nszM8DINnx1vSS+TpbWKMkxem0CDWk3cSit/WWCBVs9/JZ1I/XLwOsiUglYuYReaeWWSsW9kge5zE5NZtf/a4w==}
|
||||
engines: {node: '>=14.18.0', npm: '>=8.0.0'}
|
||||
hasBin: true
|
||||
optionalDependencies:
|
||||
@@ -6206,8 +6208,8 @@ packages:
|
||||
mri: 1.2.0
|
||||
dev: false
|
||||
|
||||
/safe-array-concat@1.0.0:
|
||||
resolution: {integrity: sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==}
|
||||
/safe-array-concat@1.0.1:
|
||||
resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==}
|
||||
engines: {node: '>=0.4'}
|
||||
dependencies:
|
||||
call-bind: 1.0.2
|
||||
@@ -6379,8 +6381,8 @@ packages:
|
||||
side-channel: 1.0.4
|
||||
dev: true
|
||||
|
||||
/string.prototype.padend@3.1.4:
|
||||
resolution: {integrity: sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw==}
|
||||
/string.prototype.padend@3.1.5:
|
||||
resolution: {integrity: sha512-DOB27b/2UTTD+4myKUFh+/fXWcu/UDyASIXfg+7VzoCNNGOfWvoyU/x5pvVHr++ztyt/oSYI1BcWBBG/hmlNjA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
dependencies:
|
||||
call-bind: 1.0.2
|
||||
@@ -6388,23 +6390,23 @@ packages:
|
||||
es-abstract: 1.22.1
|
||||
dev: false
|
||||
|
||||
/string.prototype.trim@1.2.7:
|
||||
resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==}
|
||||
/string.prototype.trim@1.2.8:
|
||||
resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
dependencies:
|
||||
call-bind: 1.0.2
|
||||
define-properties: 1.2.0
|
||||
es-abstract: 1.22.1
|
||||
|
||||
/string.prototype.trimend@1.0.6:
|
||||
resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==}
|
||||
/string.prototype.trimend@1.0.7:
|
||||
resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==}
|
||||
dependencies:
|
||||
call-bind: 1.0.2
|
||||
define-properties: 1.2.0
|
||||
es-abstract: 1.22.1
|
||||
|
||||
/string.prototype.trimstart@1.0.6:
|
||||
resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==}
|
||||
/string.prototype.trimstart@1.0.7:
|
||||
resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==}
|
||||
dependencies:
|
||||
call-bind: 1.0.2
|
||||
define-properties: 1.2.0
|
||||
@@ -6514,7 +6516,7 @@ packages:
|
||||
fast-glob: 3.3.1
|
||||
glob-parent: 6.0.2
|
||||
is-glob: 4.0.3
|
||||
jiti: 1.19.3
|
||||
jiti: 1.20.0
|
||||
lilconfig: 2.1.0
|
||||
micromatch: 4.0.5
|
||||
normalize-path: 3.0.0
|
||||
@@ -6595,8 +6597,8 @@ packages:
|
||||
resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==}
|
||||
dev: false
|
||||
|
||||
/ts-api-utils@1.0.2(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-Cbu4nIqnEdd+THNEsBdkolnOXhg0I8XteoHaEKgvsxpsbWda4IsUut2c187HxywQCvveojow0Dgw/amxtSKVkQ==}
|
||||
/ts-api-utils@1.0.3(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==}
|
||||
engines: {node: '>=16.13.0'}
|
||||
peerDependencies:
|
||||
typescript: '>=4.2.0'
|
||||
@@ -6736,6 +6738,10 @@ packages:
|
||||
for-each: 0.3.3
|
||||
is-typed-array: 1.1.12
|
||||
|
||||
/typescript-lru-cache@2.0.0:
|
||||
resolution: {integrity: sha512-Jp57Qyy8wXeMkdNuZiglE6v2Cypg13eDA1chHwDG6kq51X7gk4K7P7HaDdzZKCxkegXkVHNcPD0n5aW6OZH3aA==}
|
||||
dev: false
|
||||
|
||||
/typescript@5.2.2:
|
||||
resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==}
|
||||
engines: {node: '>=14.17'}
|
||||
@@ -6996,7 +7002,7 @@ packages:
|
||||
'@types/node': 20.5.9
|
||||
esbuild: 0.18.20
|
||||
postcss: 8.4.29
|
||||
rollup: 3.28.1
|
||||
rollup: 3.29.0
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
dev: true
|
||||
|
||||
30
src-tauri/Cargo.lock
generated
30
src-tauri/Cargo.lock
generated
@@ -533,9 +533,9 @@ checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.13.1"
|
||||
version = "1.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
|
||||
checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
@@ -545,9 +545,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.4.0"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
|
||||
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -695,9 +695,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.28"
|
||||
version = "0.4.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95ed24df0632f708f5f6d8082675bef2596f7084dee3dd55f632290bf35bfe0f"
|
||||
checksum = "defd4e7873dbddba6c7c91e199c7fcb946abc4a6a4ac3195400bcfb01b5de877"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
@@ -2627,7 +2627,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lume"
|
||||
version = "1.2.2"
|
||||
version = "1.2.4"
|
||||
dependencies = [
|
||||
"rust-argon2 1.0.0",
|
||||
"serde",
|
||||
@@ -2642,7 +2642,6 @@ dependencies = [
|
||||
"tauri-plugin-stronghold",
|
||||
"tauri-plugin-upload",
|
||||
"webpage",
|
||||
"window-shadows",
|
||||
"window-vibrancy",
|
||||
]
|
||||
|
||||
@@ -5709,9 +5708,9 @@ checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.3.3"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
|
||||
checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
@@ -5971,17 +5970,6 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "window-shadows"
|
||||
version = "0.2.1"
|
||||
source = "git+https://github.com/tauri-apps/window-shadows?branch=dev#a9f5f1f7725609c71404539befca1f1a98095cd2"
|
||||
dependencies = [
|
||||
"cocoa 0.25.0",
|
||||
"objc",
|
||||
"raw-window-handle",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "window-vibrancy"
|
||||
version = "0.4.0"
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
[package]
|
||||
name = "lume"
|
||||
version = "1.2.2"
|
||||
version = "1.2.4"
|
||||
description = "the communication app"
|
||||
authors = ["Ren Amamiya"]
|
||||
license = "GPL-3.0"
|
||||
repository = "https://github.com/luminous-devs/lume"
|
||||
edition = "2021"
|
||||
rust-version = "1.71"
|
||||
rust-version = "1.66"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "1.4.0", features = [] }
|
||||
tauri-build = { version = "1.4", features = [] }
|
||||
|
||||
[dependencies]
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tauri = { version = "1.4.0", features = [
|
||||
tauri = { version = "1.4", features = [
|
||||
"fs-read-dir",
|
||||
"fs-read-file",
|
||||
"window-start-dragging",
|
||||
@@ -34,7 +34,6 @@ tauri = { version = "1.4.0", features = [
|
||||
"fs-remove-file",
|
||||
"window-center",
|
||||
"dialog-all",
|
||||
"macos-private-api",
|
||||
"http-multipart",
|
||||
] }
|
||||
tauri-plugin-sql = { git = "hhttps://github.com/tauri-apps/plugins-workspace", branch = "v1", features = [
|
||||
@@ -46,7 +45,6 @@ tauri-plugin-stronghold = { git = "https://github.com/tauri-apps/plugins-workspa
|
||||
tauri-plugin-store = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
|
||||
tauri-plugin-upload = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
|
||||
window-vibrancy = { git = "https://github.com/tauri-apps/window-vibrancy", branch = "dev" }
|
||||
window-shadows = { git = "https://github.com/tauri-apps/window-shadows", branch = "dev" }
|
||||
sqlx-cli = { version = "0.7.0", default-features = false, features = [
|
||||
"sqlite",
|
||||
] }
|
||||
@@ -54,8 +52,11 @@ rust-argon2 = "1.0"
|
||||
webpage = { version = "1.6.0", features = ["serde"] }
|
||||
|
||||
[features]
|
||||
# this feature is used for production builds or when `devPath` points to the filesystem
|
||||
# DO NOT REMOVE!!
|
||||
# by default Tauri runs in production mode
|
||||
# when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL
|
||||
default = ["custom-protocol"]
|
||||
# this feature is used used for production builds where `devPath` points to the filesystem
|
||||
# DO NOT remove this
|
||||
custom-protocol = ["tauri/custom-protocol"]
|
||||
|
||||
# Optimized for bundle size. If you want faster builds comment out/delete this section.
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
use tauri::Manager;
|
||||
use tauri_plugin_autostart::MacosLauncher;
|
||||
use tauri_plugin_sql::{Migration, MigrationKind};
|
||||
use window_shadows::set_shadow;
|
||||
use webpage::{Webpage, WebpageOptions};
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -103,9 +102,6 @@ fn main() {
|
||||
apply_vibrancy(&window, NSVisualEffectMaterial::HudWindow, None, None)
|
||||
.expect("Unsupported platform! 'apply_vibrancy' is only supported on macOS");
|
||||
|
||||
// set native shadow
|
||||
set_shadow(&window, true).expect("Unsupported platform!");
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.plugin(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
||||
"build": {
|
||||
"beforeBuildCommand": "pnpm build",
|
||||
"beforeDevCommand": "pnpm dev",
|
||||
@@ -8,7 +9,7 @@
|
||||
},
|
||||
"package": {
|
||||
"productName": "Lume",
|
||||
"version": "1.2.2"
|
||||
"version": "1.2.4"
|
||||
},
|
||||
"tauri": {
|
||||
"allowlist": {
|
||||
@@ -124,6 +125,7 @@
|
||||
"csp": {
|
||||
"content-security-policy": "upgrade-insecure-requests"
|
||||
}
|
||||
}
|
||||
},
|
||||
"macOSPrivateApi": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
||||
"tauri": {
|
||||
"windows": [
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
||||
"tauri": {
|
||||
"macOSPrivateApi": true,
|
||||
"windows": [
|
||||
{
|
||||
"width": 400,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
||||
"tauri": {
|
||||
"windows": [
|
||||
{
|
||||
|
||||
13
src/app.tsx
13
src/app.tsx
@@ -1,3 +1,4 @@
|
||||
import { message } from '@tauri-apps/api/dialog';
|
||||
import { RouterProvider, createBrowserRouter, redirect } from 'react-router-dom';
|
||||
|
||||
import { AuthCreateScreen } from '@app/auth/create';
|
||||
@@ -19,18 +20,20 @@ import './index.css';
|
||||
async function Loader() {
|
||||
try {
|
||||
const account = await checkActiveAccount();
|
||||
|
||||
const stronghold = sessionStorage.getItem('stronghold');
|
||||
const privkey = JSON.parse(stronghold).state.privkey || null;
|
||||
|
||||
const onboarding = localStorage.getItem('onboarding');
|
||||
const step = JSON.parse(onboarding).state.step || null;
|
||||
|
||||
if (step) {
|
||||
return redirect(step);
|
||||
}
|
||||
|
||||
if (!account) {
|
||||
return redirect('/auth/welcome');
|
||||
} else {
|
||||
if (step) {
|
||||
return redirect(step);
|
||||
}
|
||||
|
||||
if (!privkey) {
|
||||
return redirect('/auth/unlock');
|
||||
}
|
||||
@@ -38,7 +41,7 @@ async function Loader() {
|
||||
|
||||
return null;
|
||||
} catch (e) {
|
||||
throw new Error('App failed to load');
|
||||
await message(e, { title: 'An unexpected error has occurred', type: 'error' });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ export function CreateStep1Screen() {
|
||||
|
||||
useEffect(() => {
|
||||
// save current step, if user close app and reopen it
|
||||
setStep('/auth/create/step-1');
|
||||
setStep('/auth/create');
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
||||
@@ -63,7 +63,7 @@ export function CreateStep2Screen() {
|
||||
const dir = await appConfigDir();
|
||||
const stronghold = await Stronghold.load(`${dir}/lume.stronghold`, data.password);
|
||||
|
||||
db.secureDB = stronghold;
|
||||
if (!db.secureDB) db.secureDB = stronghold;
|
||||
|
||||
// save privkey to secure storage
|
||||
await db.secureSave(pubkey, privkey);
|
||||
|
||||
@@ -79,7 +79,7 @@ export function ImportStep1Screen() {
|
||||
|
||||
useEffect(() => {
|
||||
// save current step, if user close app and reopen it
|
||||
setStep('/auth/import/step-1');
|
||||
setStep('/auth/import');
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
||||
@@ -63,7 +63,7 @@ export function ImportStep2Screen() {
|
||||
const dir = await appConfigDir();
|
||||
const stronghold = await Stronghold.load(`${dir}/lume.stronghold`, data.password);
|
||||
|
||||
db.secureDB = stronghold;
|
||||
if (!db.secureDB) db.secureDB = stronghold;
|
||||
|
||||
// save privkey to secure storage
|
||||
await db.secureSave(pubkey, privkey);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { message } from '@tauri-apps/api/dialog';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
|
||||
@@ -52,12 +53,12 @@ export function OnboardStep2Screen() {
|
||||
setLoading(true);
|
||||
|
||||
for (const tag of tags) {
|
||||
await db.createWidget(WidgetKinds.hashtag, tag, tag.replace('#', ''));
|
||||
await db.createWidget(WidgetKinds.global.hashtag, tag, tag.replace('#', ''));
|
||||
}
|
||||
|
||||
navigate('/auth/onboarding/step-3', { replace: true });
|
||||
} catch {
|
||||
console.log('error');
|
||||
} catch (e) {
|
||||
await message(e, { title: 'Error', type: 'error' });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -49,6 +49,8 @@ export function OnboardStep3Screen() {
|
||||
}
|
||||
);
|
||||
|
||||
const relaysAsArray = Array.from(data?.keys() || []);
|
||||
|
||||
const toggleRelay = (relay: string) => {
|
||||
if (relays.has(relay)) {
|
||||
setRelays((prev) => {
|
||||
@@ -61,8 +63,9 @@ export function OnboardStep3Screen() {
|
||||
};
|
||||
|
||||
const submit = async (skip?: boolean) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
setLoading(true);
|
||||
|
||||
if (!skip) {
|
||||
for (const relay of relays) {
|
||||
await db.createRelay(relay);
|
||||
@@ -87,8 +90,6 @@ export function OnboardStep3Screen() {
|
||||
}
|
||||
};
|
||||
|
||||
const relaysAsArray = Array.from(data?.keys() || []);
|
||||
|
||||
useEffect(() => {
|
||||
// save current step, if user close app and reopen it
|
||||
setStep('/auth/onboarding/step-3');
|
||||
@@ -118,10 +119,11 @@ export function OnboardStep3Screen() {
|
||||
<LoaderIcon className="h-4 w-4 animate-spin text-white" />
|
||||
</div>
|
||||
) : relaysAsArray.length === 0 ? (
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
<div className="flex h-full w-full items-center justify-center px-6">
|
||||
<p className="text-center text-white/50">
|
||||
Can't found any relays, you can skip this step and use default relays
|
||||
instead
|
||||
Lume couldn't find any relays from your follows.
|
||||
<br />
|
||||
You can skip this step and use default relays instead.
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
@@ -145,7 +147,7 @@ export function OnboardStep3Screen() {
|
||||
))
|
||||
)}
|
||||
{relays.size > 5 && (
|
||||
<div className="sticky bottom-0 left-0 inline-flex w-full items-center justify-center bg-white/10 px-4 py-2 backdrop-blur-2xl backdrop-blur-xl">
|
||||
<div className="sticky bottom-0 left-0 inline-flex w-full items-center justify-center bg-white/10 px-4 py-2 backdrop-blur-2xl">
|
||||
<p className="text-sm text-orange-400">
|
||||
Using too much relay can cause high resource usage
|
||||
</p>
|
||||
@@ -178,7 +180,7 @@ export function OnboardStep3Screen() {
|
||||
onClick={() => submit(true)}
|
||||
className="inline-flex h-11 w-full items-center justify-center rounded-lg px-6 font-medium leading-none text-white backdrop-blur-xl hover:bg-white/10 focus:outline-none"
|
||||
>
|
||||
Skip, use default relays
|
||||
Skip, use Lume default relays
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,32 +1,25 @@
|
||||
import { NDKEvent } from '@nostr-dev-kit/ndk';
|
||||
import { useMemo } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { NotiContent } from '@app/notifications/components/content';
|
||||
import { NotiUser } from '@app/notifications/components/user';
|
||||
|
||||
import { formatCreatedAt } from '@utils/createdAt';
|
||||
import { parser } from '@utils/parser';
|
||||
|
||||
export function NotiMention({ event }: { event: NDKEvent }) {
|
||||
const createdAt = formatCreatedAt(event.created_at);
|
||||
const content = useMemo(() => parser(event), [event]);
|
||||
const rootId = event.tags.find((el) => el[0])?.[1];
|
||||
|
||||
return (
|
||||
<div className="h-min w-full px-3 py-1.5">
|
||||
<div className="relative overflow-hidden rounded-xl bg-white/10 px-3 pt-3 backdrop-blur-xl">
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex items-start gap-1">
|
||||
<NotiUser pubkey={event.pubkey} />
|
||||
<p className="leading-none text-white/50">has reply you post · {createdAt}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="f- relative z-10 -mt-6 flex gap-3">
|
||||
<div className="h-11 w-11 shrink-0" />
|
||||
<div className="mb-2 mt-3 w-full cursor-default rounded-lg bg-white/10 px-3 py-3 backdrop-blur-xl">
|
||||
<NotiContent content={content} />
|
||||
</div>
|
||||
<Link to={`/notes/text/${rootId}`} className="h-min w-full px-3">
|
||||
<div className="group flex items-center justify-between rounded-xl px-3 py-3 hover:bg-white/10">
|
||||
<div className="flex items-center gap-2">
|
||||
<NotiUser pubkey={event.pubkey} />
|
||||
<p className="leading-none text-white/50">has mention you · {createdAt}</p>
|
||||
</div>
|
||||
<span className="hidden text-sm font-semibold text-fuchsia-500 group-hover:block">
|
||||
View
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,30 +1,27 @@
|
||||
import { NDKEvent } from '@nostr-dev-kit/ndk';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { SimpleNote } from '@app/notifications/components/simpleNote';
|
||||
import { NotiUser } from '@app/notifications/components/user';
|
||||
|
||||
import { formatCreatedAt } from '@utils/createdAt';
|
||||
|
||||
export function NotiReaction({ event }: { event: NDKEvent }) {
|
||||
const root = event.tags.find((e) => e[0] === 'e')?.[1];
|
||||
const createdAt = formatCreatedAt(event.created_at);
|
||||
const rootId = event.tags.find((el) => el[0])?.[1];
|
||||
|
||||
return (
|
||||
<div className="h-min w-full px-3 py-1.5">
|
||||
<div className="relative overflow-hidden rounded-xl bg-white/10 px-3 pt-3 backdrop-blur-xl">
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex items-start gap-1">
|
||||
<NotiUser pubkey={event.pubkey} />
|
||||
<p className="leading-none text-white/50">
|
||||
reacted {event.content} · {createdAt}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative z-10 -mt-6 flex gap-3">
|
||||
<div className="h-11 w-11 shrink-0" />
|
||||
<div className="flex-1">{root && <SimpleNote id={root} />}</div>
|
||||
<Link to={`/notes/text/${rootId}`} className="h-min w-full px-3">
|
||||
<div className="group flex items-center justify-between rounded-xl px-3 py-3 hover:bg-white/10">
|
||||
<div className="flex items-center gap-2">
|
||||
<NotiUser pubkey={event.pubkey} />
|
||||
<p className="leading-none text-white/50">
|
||||
reacted {event.content} · {createdAt}
|
||||
</p>
|
||||
</div>
|
||||
<span className="hidden text-sm font-semibold text-fuchsia-500 group-hover:block">
|
||||
View
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { NDKEvent } from '@nostr-dev-kit/ndk';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { SimpleNote } from '@app/notifications/components/simpleNote';
|
||||
import { NotiUser } from '@app/notifications/components/user';
|
||||
|
||||
import { useStorage } from '@libs/storage/provider';
|
||||
@@ -10,29 +10,24 @@ import { formatCreatedAt } from '@utils/createdAt';
|
||||
export function NotiRepost({ event }: { event: NDKEvent }) {
|
||||
const { db } = useStorage();
|
||||
|
||||
const root = event.tags.find((e) => e[0] === 'e')?.[1];
|
||||
const createdAt = formatCreatedAt(event.created_at);
|
||||
const rootId = event.tags.find((el) => el[0])?.[1];
|
||||
|
||||
return (
|
||||
<div className="h-min w-full px-3 py-1.5">
|
||||
<div className="relative overflow-hidden rounded-xl bg-white/10 px-3 pt-3 backdrop-blur-xl">
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex items-start gap-1">
|
||||
<NotiUser pubkey={event.pubkey} />
|
||||
<p className="leading-none text-white/50">
|
||||
repost{' '}
|
||||
{event.pubkey !== db.account.pubkey
|
||||
? 'a post that mention you'
|
||||
: 'your post'}{' '}
|
||||
· {createdAt}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative z-10 -mt-6 flex gap-3">
|
||||
<div className="h-11 w-11 shrink-0" />
|
||||
<div className="flex-1">{root && <SimpleNote id={root} />}</div>
|
||||
<Link to={`/notes/text/${rootId}`} className="h-min w-full px-3">
|
||||
<div className="group flex items-center justify-between rounded-xl px-3 py-3 hover:bg-white/10">
|
||||
<div className="flex items-center gap-2">
|
||||
<NotiUser pubkey={event.pubkey} />
|
||||
<p className="leading-none text-white/50">
|
||||
repost{' '}
|
||||
{event.pubkey !== db.account.pubkey ? 'a post that mention you' : 'your post'}{' '}
|
||||
· {createdAt}
|
||||
</p>
|
||||
</div>
|
||||
<span className="hidden text-sm font-semibold text-fuchsia-500 group-hover:block">
|
||||
View
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,13 +18,13 @@ export function NotiUser({ pubkey }: { pubkey: string }) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex shrink-0 items-start justify-start gap-3">
|
||||
<div className="flex shrink-0 items-center justify-start gap-2">
|
||||
<Image
|
||||
src={user?.picture || user?.image}
|
||||
alt={pubkey}
|
||||
className="h-11 w-11 shrink-0 rounded-lg object-cover"
|
||||
className="h-8 w-8 shrink-0 rounded-md object-cover"
|
||||
/>
|
||||
<span className="max-w-[10rem] flex-1 truncate font-medium leading-none text-white">
|
||||
<span className="max-w-[10rem] truncate font-medium leading-none text-white">
|
||||
{user?.name || user?.display_name || displayNpub(pubkey, 16)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -1,28 +1,24 @@
|
||||
import { NDKEvent } from '@nostr-dev-kit/ndk';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useCallback } from 'react';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
|
||||
import { NotiMention } from '@app/notifications/components/mention';
|
||||
import { NotiReaction } from '@app/notifications/components/reaction';
|
||||
import { NotiRepost } from '@app/notifications/components/repost';
|
||||
|
||||
import { useStorage } from '@libs/storage/provider';
|
||||
|
||||
import { LoaderIcon } from '@shared/icons';
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
|
||||
import { useActivities } from '@stores/activities';
|
||||
|
||||
import { useNostr } from '@utils/hooks/useNostr';
|
||||
|
||||
export function NotificationScreen() {
|
||||
const { db } = useStorage();
|
||||
const { fetchActivities } = useNostr();
|
||||
const { status, data } = useQuery(
|
||||
['notifications', db.account.pubkey],
|
||||
async () => {
|
||||
return await fetchActivities();
|
||||
},
|
||||
{ refetchOnWindowFocus: false }
|
||||
);
|
||||
const [activities, setActivities, clearTotalNewActivities] = useActivities((state) => [
|
||||
state.activities,
|
||||
state.setActivities,
|
||||
state.clearTotalNewActivities,
|
||||
]);
|
||||
|
||||
const renderItem = useCallback(
|
||||
(event: NDKEvent) => {
|
||||
@@ -37,34 +33,43 @@ export function NotificationScreen() {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
[data]
|
||||
[activities]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
async function getActivities() {
|
||||
const events = await fetchActivities();
|
||||
setActivities(events);
|
||||
// clear total new activities
|
||||
clearTotalNewActivities();
|
||||
}
|
||||
|
||||
getActivities();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="scrollbar-hide h-full w-full overflow-y-auto bg-white/10 backdrop-blur-xl">
|
||||
<div className="grid h-full grid-cols-3">
|
||||
<div className="col-span-2 flex flex-col border-r border-white/5">
|
||||
<TitleBar title="Activities in the last 24 hours" />
|
||||
<div className="flex h-full flex-col gap-1.5">
|
||||
<div className="flex h-full flex-col">
|
||||
{status === 'loading' ? (
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
<div className="flex flex-col items-center gap-1.5">
|
||||
<LoaderIcon className="h-5 w-5 animate-spin text-white" />
|
||||
<p className="text-sm font-medium text-white/50">Loading</p>
|
||||
</div>
|
||||
<div className="flex h-full flex-col">
|
||||
{!activities ? (
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
<div className="flex flex-col items-center gap-1.5">
|
||||
<LoaderIcon className="h-5 w-5 animate-spin text-white" />
|
||||
<p className="text-sm font-medium text-white/50">Loading</p>
|
||||
</div>
|
||||
) : data?.length < 1 ? (
|
||||
<div className="flex h-full w-full flex-col items-center justify-center">
|
||||
<p className="mb-1 text-4xl">🎉</p>
|
||||
<p className="font-medium text-white/50">
|
||||
Yo!, no new activities around you in the last 24 hours
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
data.map((event) => renderItem(event))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : activities.length < 1 ? (
|
||||
<div className="flex h-full w-full flex-col items-center justify-center">
|
||||
<p className="mb-1 text-4xl">🎉</p>
|
||||
<p className="font-medium text-white/50">
|
||||
Yo!, no new activities around you in the last 24 hours
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
activities.map((event) => renderItem(event))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,9 +2,17 @@ import { useCallback } from 'react';
|
||||
|
||||
import { useStorage } from '@libs/storage/provider';
|
||||
|
||||
import {
|
||||
ArticleIcon,
|
||||
FileIcon,
|
||||
FollowsIcon,
|
||||
GroupFeedsIcon,
|
||||
HashtagIcon,
|
||||
TrendingIcon,
|
||||
} from '@shared/icons';
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
|
||||
import { DefaultWidgets, useWidgets } from '@stores/widgets';
|
||||
import { DefaultWidgets, WidgetKinds, useWidgets } from '@stores/widgets';
|
||||
|
||||
import { Widget, WidgetGroup, WidgetGroupItem } from '@utils/types';
|
||||
|
||||
@@ -20,16 +28,61 @@ export function WidgetList({ params }: { params: Widget }) {
|
||||
removeWidget(db, params.id);
|
||||
};
|
||||
|
||||
const renderIcon = useCallback(
|
||||
(kind: number) => {
|
||||
switch (kind) {
|
||||
case WidgetKinds.tmp.xfeed:
|
||||
return <GroupFeedsIcon className="h-5 w-5 text-white" />;
|
||||
case WidgetKinds.local.follows:
|
||||
return <FollowsIcon className="h-5 w-5 text-white" />;
|
||||
case WidgetKinds.local.files:
|
||||
case WidgetKinds.global.files:
|
||||
return <FileIcon className="h-5 w-5 text-white" />;
|
||||
case WidgetKinds.local.articles:
|
||||
case WidgetKinds.global.articles:
|
||||
return <ArticleIcon className="h-5 w-5 text-white" />;
|
||||
case WidgetKinds.tmp.xhashtag:
|
||||
return <HashtagIcon className="h-5 w-4 text-white" />;
|
||||
case WidgetKinds.nostrBand.trendingAccounts:
|
||||
case WidgetKinds.nostrBand.trendingNotes:
|
||||
return <TrendingIcon className="h-5 w-4 text-white" />;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
},
|
||||
[DefaultWidgets]
|
||||
);
|
||||
|
||||
const renderItem = useCallback(
|
||||
(row: WidgetGroup) => {
|
||||
return (
|
||||
<div className="flex flex-col gap-3">
|
||||
<h3 className="font-medium text-white/50">{row.title}</h3>
|
||||
<div className="grid grid-cols-3 gap-6">
|
||||
<div className="flex flex-col divide-y divide-white/5 overflow-hidden rounded-xl bg-white/10">
|
||||
{row.data.map((item, index) => (
|
||||
<button onClick={() => openWidget(item)} key={index}>
|
||||
<div className="inline-flex aspect-square h-full w-full transform-gpu flex-col items-center justify-center gap-2.5 rounded-2xl bg-white/5 hover:bg-white/10">
|
||||
<h5 className="text-sm font-medium">{item.title}</h5>
|
||||
<button
|
||||
onClick={() => openWidget(item)}
|
||||
key={index}
|
||||
className="flex items-center gap-2.5 px-4 hover:bg-white/10"
|
||||
>
|
||||
{item.icon ? (
|
||||
<div className="h-10 w-10 shrink-0 rounded-md">
|
||||
<img
|
||||
src={item.icon}
|
||||
alt={item.title}
|
||||
className="h-10 w-10 object-cover"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-md bg-white/10">
|
||||
{renderIcon(item.kind)}
|
||||
</div>
|
||||
)}
|
||||
<div className="inline-flex h-16 w-full flex-col items-start justify-center gap-1">
|
||||
<h5 className="line-clamp-1 font-medium leading-none">{item.title}</h5>
|
||||
<p className="line-clamp-1 text-xs leading-none text-white/50">
|
||||
{item.description}
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
@@ -41,11 +94,27 @@ export function WidgetList({ params }: { params: Widget }) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="relative h-full shrink-0 grow-0 basis-[400px] overflow-hidden">
|
||||
<div className="relative h-full shrink-0 grow-0 basis-[400px] overflow-hidden bg-white/10">
|
||||
<TitleBar id={params.id} title="Add widget" />
|
||||
<div className="flex flex-col gap-8 px-3">
|
||||
<div className="flex flex-col gap-6 px-3">
|
||||
{DefaultWidgets.map((row: WidgetGroup) => renderItem(row))}
|
||||
</div>
|
||||
<div className="mt-6 px-3">
|
||||
<div className="border-t border-white/5 pt-6">
|
||||
<button
|
||||
type="button"
|
||||
disabled
|
||||
className="inline-flex h-14 w-full items-center justify-center gap-2.5 rounded-xl bg-white/5 text-sm font-medium text-white/50"
|
||||
>
|
||||
Build your own widget{' '}
|
||||
<div className="-rotate-3 transform rounded-md border border-white/20 bg-white/10 px-1.5 py-1">
|
||||
<span className="bg-gradient-to-t from-fuchsia-200 via-red-200 to-orange-300 bg-clip-text text-xs text-transparent">
|
||||
Coming soon
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
XfeedsWidget,
|
||||
XhashtagWidget,
|
||||
} from '@shared/widgets';
|
||||
import { LocalFollowsWidget } from '@shared/widgets/local/follows';
|
||||
|
||||
import { WidgetKinds, useWidgets } from '@stores/widgets';
|
||||
|
||||
@@ -40,6 +41,8 @@ export function SpaceScreen() {
|
||||
switch (widget.kind) {
|
||||
case WidgetKinds.local.network:
|
||||
return <LocalNetworkWidget key={widget.id} />;
|
||||
case WidgetKinds.local.follows:
|
||||
return <LocalFollowsWidget key={widget.id} params={widget} />;
|
||||
case WidgetKinds.local.feeds:
|
||||
return <LocalFeedsWidget key={widget.id} params={widget} />;
|
||||
case WidgetKinds.local.files:
|
||||
|
||||
@@ -15,45 +15,50 @@ export function SplashScreen() {
|
||||
const { fetchUserData, prefetchEvents } = useNostr();
|
||||
|
||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||
const [errorMessage, setErrorMessage] = useState<null | string>(null);
|
||||
|
||||
const skip = async () => {
|
||||
await invoke('close_splashscreen');
|
||||
};
|
||||
|
||||
const prefetch = async () => {
|
||||
const onboarding = localStorage.getItem('onboarding');
|
||||
const step = JSON.parse(onboarding).state.step || null;
|
||||
if (step) await invoke('close_splashscreen');
|
||||
|
||||
try {
|
||||
const user = await fetchUserData();
|
||||
const data = await prefetchEvents();
|
||||
|
||||
if (user.status === 'ok' && data.status === 'ok') {
|
||||
// update last login = current time
|
||||
await db.updateLastLogin();
|
||||
// close splash screen and open main app screen
|
||||
await invoke('close_splashscreen');
|
||||
} else {
|
||||
setIsLoading(false);
|
||||
setErrorMessage(user.message);
|
||||
console.log('fetch failed, error: ', user.message);
|
||||
}
|
||||
} catch (e) {
|
||||
setIsLoading(false);
|
||||
setErrorMessage(e);
|
||||
await message(`Something wrong: ${e}`, {
|
||||
title: 'Lume',
|
||||
await message(e, {
|
||||
title: 'An unexpected error has occurred',
|
||||
type: 'error',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (ndk) {
|
||||
if (!db.account) invoke('close_splashscreen');
|
||||
async function initial() {
|
||||
if (!db.account) {
|
||||
await invoke('close_splashscreen');
|
||||
} else {
|
||||
const onboarding = localStorage.getItem('onboarding');
|
||||
const step = JSON.parse(onboarding).state.step || null;
|
||||
|
||||
console.log('prefetching...');
|
||||
prefetch();
|
||||
if (step) {
|
||||
await invoke('close_splashscreen');
|
||||
} else {
|
||||
console.log('prefetching...');
|
||||
prefetch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ndk) {
|
||||
initial();
|
||||
}
|
||||
}, [ndk, db.account]);
|
||||
|
||||
@@ -75,15 +80,14 @@ export function SplashScreen() {
|
||||
) : (
|
||||
<div className="mt-2 flex flex-col gap-1 text-center">
|
||||
<h3 className="text-lg font-semibold leading-none text-white">
|
||||
Something wrong!
|
||||
An unexpected error has occurred
|
||||
</h3>
|
||||
<p className="text-sm text-white/50">{errorMessage}</p>
|
||||
<button
|
||||
type="button"
|
||||
onClick={skip}
|
||||
className="mx-auto mt-4 inline-flex h-10 w-max items-center justify-center rounded-md bg-white/10 px-8 text-sm font-medium leading-none text-white backdrop-blur-xl hover:bg-white/20"
|
||||
>
|
||||
Skip
|
||||
Skip this step
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -17,40 +17,32 @@ export const NDKInstance = () => {
|
||||
const cacheAdapter = useMemo(() => new TauriAdapter(), [ndk]);
|
||||
|
||||
// TODO: fully support NIP-11
|
||||
async function verifyRelays(relays: string[]) {
|
||||
async function getExplicitRelays() {
|
||||
try {
|
||||
const urls: string[] = relays.map((relay) => {
|
||||
if (relay.startsWith('ws')) {
|
||||
return relay.replace('ws', 'http');
|
||||
}
|
||||
if (relay.startsWith('wss')) {
|
||||
return relay.replace('wss', 'https');
|
||||
}
|
||||
});
|
||||
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort('timeout'), 10000);
|
||||
|
||||
const requests = urls.map((url) =>
|
||||
fetch(url, {
|
||||
// get relays
|
||||
const relays = (await db.getExplicitRelayUrls()) ?? FULL_RELAYS;
|
||||
|
||||
const requests = relays.map((relay) => {
|
||||
const url = new URL(relay);
|
||||
|
||||
return fetch(`https://${url.hostname + url.pathname}`, {
|
||||
headers: { Accept: 'application/nostr+json' },
|
||||
signal: controller.signal,
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
const responses = await Promise.all(requests);
|
||||
const errors = responses.filter((response) => !response.ok);
|
||||
|
||||
if (errors.length > 0) {
|
||||
throw errors.map((response) => Error(response.statusText));
|
||||
}
|
||||
if (errors.length > 0) throw errors.map((response) => Error(response.statusText));
|
||||
|
||||
const verifiedRelays: string[] = responses.map((res) => {
|
||||
if (res.url.startsWith('http')) {
|
||||
return res.url.replace('htto', 'ws');
|
||||
}
|
||||
if (res.url.startsWith('https')) {
|
||||
return res.url.replace('https', 'wss');
|
||||
}
|
||||
const url = new URL(res.url);
|
||||
if (url.protocol === 'http:') return `ws://${url.hostname + url.pathname}`;
|
||||
if (url.protocol === 'https:') return `wss://${url.hostname + url.pathname}`;
|
||||
});
|
||||
|
||||
// clear timeout
|
||||
@@ -59,31 +51,19 @@ export const NDKInstance = () => {
|
||||
// return all validate relays
|
||||
return verifiedRelays;
|
||||
} catch (e) {
|
||||
console.error('verify relay failed with error: ', e);
|
||||
await message(e, { title: 'Cannot connect to relays', type: 'error' });
|
||||
}
|
||||
}
|
||||
|
||||
async function initNDK() {
|
||||
let explicitRelayUrls: string[];
|
||||
const explicitRelayUrlsFromDB = await db.getExplicitRelayUrls();
|
||||
const explicitRelayUrls = await getExplicitRelays();
|
||||
const instance = new NDK({
|
||||
explicitRelayUrls,
|
||||
cacheAdapter,
|
||||
// outboxRelayUrls: ['wss://purplepag.es'],
|
||||
// enableOutboxModel: true,
|
||||
});
|
||||
|
||||
console.log('relays in db: ', explicitRelayUrlsFromDB);
|
||||
console.log('ndk cache adapter: ', cacheAdapter);
|
||||
|
||||
if (explicitRelayUrlsFromDB) {
|
||||
explicitRelayUrls = await verifyRelays(explicitRelayUrlsFromDB);
|
||||
} else {
|
||||
explicitRelayUrls = await verifyRelays(FULL_RELAYS);
|
||||
}
|
||||
|
||||
if (explicitRelayUrls.length < 1) {
|
||||
await message('Something is wrong. No relays have been found.', {
|
||||
title: 'Lume',
|
||||
type: 'error',
|
||||
});
|
||||
}
|
||||
|
||||
const instance = new NDK({ explicitRelayUrls, cacheAdapter });
|
||||
try {
|
||||
await instance.connect(10000);
|
||||
} catch (error) {
|
||||
|
||||
@@ -291,6 +291,15 @@ export class LumeStorage {
|
||||
);
|
||||
}
|
||||
|
||||
public async accountLogout() {
|
||||
await this.db.execute("UPDATE accounts SET is_active = '0' WHERE id = $1;", [
|
||||
this.account.id,
|
||||
]);
|
||||
|
||||
this.account = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
public async close() {
|
||||
return this.db.close();
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import { useStorage } from '@libs/storage/provider';
|
||||
import { AccountMoreActions } from '@shared/accounts/more';
|
||||
import { Image } from '@shared/image';
|
||||
|
||||
import { useActivities } from '@stores/activities';
|
||||
|
||||
import { useNostr } from '@utils/hooks/useNostr';
|
||||
import { useProfile } from '@utils/hooks/useProfile';
|
||||
import { sendNativeNotification } from '@utils/notification';
|
||||
@@ -16,6 +18,8 @@ export function ActiveAccount() {
|
||||
const { status, user } = useProfile(db.account.pubkey);
|
||||
const { sub } = useNostr();
|
||||
|
||||
const addActivity = useActivities((state) => state.addActivity);
|
||||
|
||||
useEffect(() => {
|
||||
const filter: NDKFilter = {
|
||||
'#p': [db.account.pubkey],
|
||||
@@ -30,6 +34,8 @@ export function ActiveAccount() {
|
||||
};
|
||||
|
||||
sub(filter, async (event) => {
|
||||
addActivity(event);
|
||||
|
||||
switch (event.kind) {
|
||||
case NDKKind.Text:
|
||||
return await sendNativeNotification('Mention');
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { HorizontalDotsIcon } from '@shared/icons';
|
||||
import { Logout } from '@shared/logout';
|
||||
|
||||
export function AccountMoreActions({ pubkey }: { pubkey: string }) {
|
||||
const [open, setOpen] = useState(false);
|
||||
@@ -44,9 +45,7 @@ export function AccountMoreActions({ pubkey }: { pubkey: string }) {
|
||||
</Link>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item asChild>
|
||||
<button className="inline-flex h-10 items-center rounded-lg px-2 text-sm font-medium text-white hover:bg-white/10">
|
||||
Logout
|
||||
</button>
|
||||
<Logout />
|
||||
</DropdownMenu.Item>
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Portal>
|
||||
|
||||
@@ -125,7 +125,7 @@ export function Composer() {
|
||||
autoCapitalize="off"
|
||||
className={twMerge(
|
||||
'scrollbar-hide markdown max-h-[500px] overflow-y-auto break-all pr-2 outline-none',
|
||||
expand ? 'min-h-[500px]' : 'min-h-[120px]'
|
||||
expand ? 'min-h-[500px]' : reply.id ? 'min-h-min' : 'min-h-[120px]'
|
||||
)}
|
||||
/>
|
||||
{reply.id && (
|
||||
|
||||
22
src/shared/icons/article.tsx
Normal file
22
src/shared/icons/article.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { SVGProps } from 'react';
|
||||
|
||||
export function ArticleIcon(props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="1.5"
|
||||
d="M16.25 12V4.75a1 1 0 00-1-1H3.75a1 1 0 00-1 1v13a2.5 2.5 0 002.5 2.5H18.5M16.25 12v5.75a2.5 2.5 0 005 0V13a1 1 0 00-1-1h-4zm-9.5 3.75h5.5m-5.5-8h5.5v4.5h-5.5v-4.5z"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -13,10 +13,9 @@ export function FileIcon(props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="1.5"
|
||||
d="M8.75 6.75h6.5m-6.5 4h6.5m-6.5 4h2.5m-5.5 6.5h12.5a1 1 0 001-1V3.75a1 1 0 00-1-1H5.75a1 1 0 00-1 1v16.5a1 1 0 001 1z"
|
||||
/>
|
||||
d="M12.75 3.25v5a1 1 0 001 1h5m-10 4h3.5m-3.5 4h6.5m-9.5-14.5h6.586a1 1 0 01.707.293l5.914 5.914a1 1 0 01.293.707V20.25a1 1 0 01-1 1H5.75a1 1 0 01-1-1V3.75a1 1 0 011-1z"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
22
src/shared/icons/follows.tsx
Normal file
22
src/shared/icons/follows.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { SVGProps } from 'react';
|
||||
|
||||
export function FollowsIcon(props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="1.5"
|
||||
d="M17.75 19.25h3.673c.581 0 1.045-.496.947-1.07-.531-3.118-2.351-5.43-5.37-5.43-.446 0-.866.05-1.26.147M11.25 7a3.25 3.25 0 11-6.5 0 3.25 3.25 0 016.5 0zm8.5.5a2.75 2.75 0 11-5.5 0 2.75 2.75 0 015.5 0zM1.87 19.18c.568-3.68 2.647-6.43 6.13-6.43 3.482 0 5.561 2.75 6.13 6.43.088.575-.375 1.07-.956 1.07H2.825c-.58 0-1.043-.495-.955-1.07z"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
22
src/shared/icons/groupFeeds.tsx
Normal file
22
src/shared/icons/groupFeeds.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { SVGProps } from 'react';
|
||||
|
||||
export function GroupFeedsIcon(props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="1.5"
|
||||
d="M14.425 13.18c3.361-1.396 7.598.605 8.454 6.003.09.573-.372 1.067-.952 1.067H16.75M10.75 7a3.25 3.25 0 11-6.5 0 3.25 3.25 0 016.5 0zm9 0a3.25 3.25 0 11-6.5 0 3.25 3.25 0 016.5 0zm-6.966 13.25H2.072c-.58 0-1.042-.497-.951-1.07 1.362-8.573 11.252-8.573 12.614 0 .091.573-.371 1.07-.951 1.07z"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -16,7 +16,7 @@ export function HashtagIcon(props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElem
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="1.5"
|
||||
d="M8.75 3.75l-2 16.5m10.5-16.5l-2 16.5M3.75 7.75h16.5m0 8.5H3.75"
|
||||
/>
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -58,3 +58,6 @@ export * from './chevronUp';
|
||||
export * from './secure';
|
||||
export * from './verified';
|
||||
export * from './mention';
|
||||
export * from './groupFeeds';
|
||||
export * from './article';
|
||||
export * from './follows';
|
||||
|
||||
@@ -1,75 +1,65 @@
|
||||
import * as Dialog from '@radix-ui/react-dialog';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import * as AlertDialog from '@radix-ui/react-alert-dialog';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { CancelIcon, LogoutIcon } from '@shared/icons';
|
||||
import { useStorage } from '@libs/storage/provider';
|
||||
|
||||
import { useStronghold } from '@stores/stronghold';
|
||||
|
||||
export function Logout() {
|
||||
const queryClient = useQueryClient();
|
||||
const { db } = useStorage();
|
||||
|
||||
const navigate = useNavigate();
|
||||
const clearPrivkey = useStronghold((state) => state.clearPrivkey);
|
||||
|
||||
const logout = async () => {
|
||||
// reset database
|
||||
// await removeAll();
|
||||
// reset react query
|
||||
queryClient.clear();
|
||||
// remove account
|
||||
db.accountLogout();
|
||||
// clear privkey in session storage
|
||||
clearPrivkey();
|
||||
// redirect to welcome screen
|
||||
navigate('/auth/welcome');
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog.Root>
|
||||
<Dialog.Trigger asChild>
|
||||
<AlertDialog.Root>
|
||||
<AlertDialog.Trigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Logout"
|
||||
className="inline-flex h-9 w-9 transform items-center justify-center rounded-md bg-white/20 active:translate-y-1"
|
||||
className="inline-flex h-10 items-center rounded-lg px-2 text-sm font-medium text-white hover:bg-white/10"
|
||||
>
|
||||
<LogoutIcon className="h-4 w-4 text-white" />
|
||||
Logout
|
||||
</button>
|
||||
</Dialog.Trigger>
|
||||
<Dialog.Portal className="relative z-10">
|
||||
<Dialog.Overlay className="fixed inset-0 z-50 bg-black/80 backdrop-blur-xl" />
|
||||
<Dialog.Content className="fixed inset-0 z-50 flex min-h-full items-center justify-center">
|
||||
<div className="relative h-min w-full max-w-xl rounded-xl bg-white/10 backdrop-blur-xl">
|
||||
<div className="h-min w-full shrink-0 border-b border-white/10 bg-white/5 px-5 py-6">
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<Dialog.Title className="text-lg font-semibold leading-none text-white">
|
||||
Are you sure!
|
||||
</Dialog.Title>
|
||||
<Dialog.Close className="inline-flex h-6 w-6 items-center justify-center rounded-md backdrop-blur-xl hover:bg-white/10">
|
||||
<CancelIcon className="h-4 w-4 text-white/50" />
|
||||
</Dialog.Close>
|
||||
</div>
|
||||
<Dialog.Description className="text-sm leading-tight text-white/50">
|
||||
<p className="mb-2">
|
||||
When logout, all local data will be wiped, and restart app then you
|
||||
need to start onboarding process again when you log in.
|
||||
</p>
|
||||
<p>
|
||||
In the next version, Lume will support multi account, then you can
|
||||
switch between all account s instead of logout
|
||||
</p>
|
||||
</Dialog.Description>
|
||||
</div>
|
||||
</AlertDialog.Trigger>
|
||||
<AlertDialog.Portal className="relative z-10">
|
||||
<AlertDialog.Overlay className="fixed inset-0 z-50 bg-black/80 backdrop-blur-2xl" />
|
||||
<AlertDialog.Content className="fixed inset-0 z-50 flex min-h-full items-center justify-center">
|
||||
<div className="relative h-min w-full max-w-md rounded-xl bg-white/10 backdrop-blur-xl">
|
||||
<div className="flex flex-col gap-2 border-b border-white/5 px-5 py-4">
|
||||
<AlertDialog.Title className="text-lg font-semibold leading-none text-white">
|
||||
Are you sure!
|
||||
</AlertDialog.Title>
|
||||
<AlertDialog.Description className="text-sm leading-tight text-white/50">
|
||||
You can always log back in at any time. If you just want to switch
|
||||
accounts, you can do that by adding an existing account.
|
||||
</AlertDialog.Description>
|
||||
</div>
|
||||
<div className="flex h-full w-full flex-col items-end justify-center overflow-y-auto px-5 py-2.5">
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex h-9 items-center justify-center rounded-md px-3 text-sm font-medium text-white/50 backdrop-blur-xl hover:bg-white/10"
|
||||
>
|
||||
<div className="flex justify-end gap-2 px-5 py-3">
|
||||
<AlertDialog.Cancel asChild>
|
||||
<button className="inline-flex h-9 items-center justify-center rounded-md px-4 text-sm font-medium leading-none text-white outline-none hover:bg-white/10 hover:backdrop-blur-xl">
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => logout()}
|
||||
className="inline-flex h-9 items-center justify-center rounded-md bg-red-500 px-3 text-sm font-medium text-white hover:bg-red-600"
|
||||
>
|
||||
Confirm
|
||||
</button>
|
||||
</div>
|
||||
</AlertDialog.Cancel>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => logout()}
|
||||
className="inline-flex h-9 items-center justify-center rounded-md bg-white/10 px-4 text-sm font-medium leading-none text-white outline-none hover:bg-fuchsia-500"
|
||||
>
|
||||
Logout
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog.Content>
|
||||
</Dialog.Portal>
|
||||
</Dialog.Root>
|
||||
</AlertDialog.Content>
|
||||
</AlertDialog.Portal>
|
||||
</AlertDialog.Root>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,19 +4,29 @@ import { twMerge } from 'tailwind-merge';
|
||||
|
||||
import { ChatsList } from '@app/chats/components/list';
|
||||
|
||||
import { useStorage } from '@libs/storage/provider';
|
||||
|
||||
import { ActiveAccount } from '@shared/accounts/active';
|
||||
import { ComposerModal } from '@shared/composer';
|
||||
import { Frame } from '@shared/frame';
|
||||
import { BellIcon, NavArrowDownIcon, SpaceIcon } from '@shared/icons';
|
||||
|
||||
import { useActivities } from '@stores/activities';
|
||||
import { useSidebar } from '@stores/sidebar';
|
||||
|
||||
import { compactNumber } from '@utils/number';
|
||||
|
||||
export function Navigation() {
|
||||
const { db } = useStorage();
|
||||
|
||||
const [totalNewActivities] = useActivities((state) => [state.totalNewActivities]);
|
||||
const [chats, toggleChats] = useSidebar((state) => [state.chats, state.toggleChats]);
|
||||
|
||||
return (
|
||||
<Frame className="relative flex h-full w-[232px] flex-col" lighter>
|
||||
<div data-tauri-drag-region className="h-11 w-full shrink-0" />
|
||||
{db.platform === 'darwin' ? (
|
||||
<div data-tauri-drag-region className="h-11 w-full shrink-0" />
|
||||
) : null}
|
||||
<div className="scrollbar-hide flex h-full flex-1 flex-col gap-6 overflow-y-auto pb-32">
|
||||
<div className="flex flex-col pr-2">
|
||||
<ComposerModal />
|
||||
@@ -42,17 +52,26 @@ export function Navigation() {
|
||||
preventScrollReset={true}
|
||||
className={({ isActive }) =>
|
||||
twMerge(
|
||||
'flex h-10 items-center gap-2.5 rounded-r-lg border-l-2 pl-4 pr-2',
|
||||
'flex h-10 items-center justify-between rounded-r-lg border-l-2 pl-4 pr-2',
|
||||
isActive
|
||||
? 'border-fuchsia-500 bg-white/5 text-white'
|
||||
: 'border-transparent text-white/80'
|
||||
)
|
||||
}
|
||||
>
|
||||
<span className="inline-flex h-7 w-7 shrink-0 items-center justify-center rounded bg-white/10 backdrop-blur-xl">
|
||||
<BellIcon className="h-4 w-4 text-white" />
|
||||
</span>
|
||||
Notifications
|
||||
<div className="flex items-center gap-2.5">
|
||||
<span className="inline-flex h-7 w-7 shrink-0 items-center justify-center rounded bg-white/10 backdrop-blur-xl">
|
||||
<BellIcon className="h-4 w-4 text-white" />
|
||||
</span>
|
||||
Notifications
|
||||
</div>
|
||||
{totalNewActivities > 0 ? (
|
||||
<div className="inline-flex h-5 w-8 items-center justify-center rounded bg-fuchsia-500">
|
||||
<span className="text-xs font-medium text-white">
|
||||
{compactNumber.format(totalNewActivities)}
|
||||
</span>
|
||||
</div>
|
||||
) : null}
|
||||
</NavLink>
|
||||
</div>
|
||||
<Collapsible.Root open={chats} onOpenChange={toggleChats}>
|
||||
|
||||
@@ -46,26 +46,26 @@ export function NoteRepost({ id, pubkey }: { id: string; pubkey: string }) {
|
||||
<AlertDialog.Portal className="relative z-10">
|
||||
<AlertDialog.Overlay className="fixed inset-0 z-50 bg-black/80 backdrop-blur-2xl" />
|
||||
<AlertDialog.Content className="fixed inset-0 z-50 flex min-h-full items-center justify-center">
|
||||
<div className="relative h-min w-full max-w-xl rounded-xl bg-white/10 backdrop-blur-xl">
|
||||
<div className="relative h-min w-full max-w-md rounded-xl bg-white/10 backdrop-blur-xl">
|
||||
<div className="flex flex-col gap-2 border-b border-white/5 px-5 py-4">
|
||||
<AlertDialog.Title className="text-lg font-semibold leading-none text-white">
|
||||
Confirm repost this post?
|
||||
</AlertDialog.Title>
|
||||
<AlertDialog.Description className="text-sm leading-none text-white/50">
|
||||
<AlertDialog.Description className="text-sm leading-tight text-white/50">
|
||||
Reposted post will be visible to your followers, and you cannot undo this
|
||||
action.
|
||||
</AlertDialog.Description>
|
||||
</div>
|
||||
<div className="flex justify-end gap-6 px-5 py-3">
|
||||
<div className="flex justify-end gap-2 px-5 py-3">
|
||||
<AlertDialog.Cancel asChild>
|
||||
<button className="inline-flex h-11 items-center justify-center rounded-lg bg-white/10 px-4 font-medium leading-none text-white outline-none backdrop-blur-xl">
|
||||
<button className="inline-flex h-9 items-center justify-center rounded-md px-4 text-sm font-medium leading-none text-white outline-none hover:bg-white/10 hover:backdrop-blur-xl">
|
||||
Cancel
|
||||
</button>
|
||||
</AlertDialog.Cancel>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => submit()}
|
||||
className="inline-flex h-11 items-center justify-center rounded-lg bg-fuchsia-500 px-4 font-medium leading-none text-white outline-none"
|
||||
className="inline-flex h-9 items-center justify-center rounded-md bg-white/10 px-4 text-sm font-medium leading-none text-white outline-none hover:bg-fuchsia-500"
|
||||
>
|
||||
Yes, repost
|
||||
</button>
|
||||
|
||||
@@ -19,7 +19,7 @@ import { useEvent } from '@utils/hooks/useEvent';
|
||||
|
||||
export function Repost({ event }: { event: NDKEvent }) {
|
||||
// @ts-expect-error, root_id isn't exist on NDKEvent
|
||||
const { status, data } = useEvent(event.root_id, event.content);
|
||||
const { status, data } = useEvent(event.root_id ?? event.id, event.content);
|
||||
|
||||
const renderKind = useCallback(
|
||||
(repostEvent: NDKEvent) => {
|
||||
|
||||
@@ -42,7 +42,7 @@ export function TextNote({ content }: { content: string }) {
|
||||
const cleanURL = new URL(href);
|
||||
cleanURL.search = '';
|
||||
return (
|
||||
<Link to={href} target="_blank">
|
||||
<Link to={href} target="_blank" className="line-clamp-1">
|
||||
{cleanURL.hostname + cleanURL.pathname}
|
||||
</Link>
|
||||
);
|
||||
|
||||
@@ -58,29 +58,24 @@ export const MentionNote = memo(function MentionNote({ id }: { id: string }) {
|
||||
if (status === 'error') {
|
||||
const noteLink = `https://nostr.com/${nip19.noteEncode(id)}`;
|
||||
return (
|
||||
<div className="relative mb-5 flex flex-col">
|
||||
<div className="relative z-10 flex items-start gap-3">
|
||||
<div className="inline-flex h-11 w-11 items-end justify-center rounded-lg bg-black pb-1">
|
||||
<div className="relative mt-3 flex flex-col">
|
||||
<div className="relative z-10 flex items-center gap-3">
|
||||
<div className="inline-flex h-6 w-6 items-end justify-center rounded bg-black pb-1">
|
||||
<img src="/lume.png" alt="lume" className="h-auto w-1/3" />
|
||||
</div>
|
||||
<h5 className="truncate font-semibold leading-none text-white">
|
||||
Lume <span className="text-green-500">(System)</span>
|
||||
</h5>
|
||||
</div>
|
||||
<div className="-mt-6 flex items-start gap-3">
|
||||
<div className="w-11 shrink-0" />
|
||||
<div>
|
||||
<div className="relative z-20 mt-1 flex-1 select-text">
|
||||
<div className="mb-1 select-text rounded-lg bg-white/5 p-1.5 text-sm">
|
||||
Lume cannot find this post with your current relays, but you can view it
|
||||
via nostr.com.{' '}
|
||||
<Link to={noteLink} className="text-fuchsia-500">
|
||||
Learn more
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<LinkPreview urls={[noteLink]} />
|
||||
<div className="mt-1">
|
||||
<div className="mb-1 select-text rounded-lg bg-white/5 p-1.5 text-sm">
|
||||
Lume cannot find this post with your current relays, but you can view it via
|
||||
nostr.com.{' '}
|
||||
<Link to={noteLink} className="text-fuchsia-500">
|
||||
Learn more
|
||||
</Link>
|
||||
</div>
|
||||
<LinkPreview urls={[noteLink]} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -17,9 +17,9 @@ import {
|
||||
import { NoteSkeleton } from '@shared/notes/skeleton';
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
|
||||
import { DBEvent } from '@utils/types';
|
||||
import { DBEvent, Widget } from '@utils/types';
|
||||
|
||||
export function LocalFollowsWidget() {
|
||||
export function LocalFollowsWidget({ params }: { params: Widget }) {
|
||||
const { db } = useStorage();
|
||||
const { status, data, hasNextPage, isFetchingNextPage, fetchNextPage } =
|
||||
useInfiniteQuery({
|
||||
@@ -116,7 +116,7 @@ export function LocalFollowsWidget() {
|
||||
|
||||
return (
|
||||
<div className="relative shrink-0 grow-0 basis-[400px] bg-white/10 backdrop-blur-xl">
|
||||
<TitleBar title="👋 Network" />
|
||||
<TitleBar id={params.id} title="Follows" />
|
||||
<div ref={parentRef} className="scrollbar-hide h-full overflow-y-auto pb-20">
|
||||
{status === 'loading' ? (
|
||||
<div className="px-3 py-1.5">
|
||||
|
||||
27
src/stores/activities.ts
Normal file
27
src/stores/activities.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { NDKEvent } from '@nostr-dev-kit/ndk';
|
||||
import { create } from 'zustand';
|
||||
|
||||
interface ActivitiesState {
|
||||
activities: Array<NDKEvent>;
|
||||
totalNewActivities: number;
|
||||
setActivities: (events: NDKEvent[]) => void;
|
||||
addActivity: (event: NDKEvent) => void;
|
||||
clearTotalNewActivities: () => void;
|
||||
}
|
||||
|
||||
export const useActivities = create<ActivitiesState>((set) => ({
|
||||
activities: null,
|
||||
totalNewActivities: 0,
|
||||
setActivities: (events: NDKEvent[]) => {
|
||||
set(() => ({ activities: events }));
|
||||
},
|
||||
addActivity: (event: NDKEvent) => {
|
||||
set((state) => ({
|
||||
activities: state.activities ? [event, ...state.activities] : [event],
|
||||
totalNewActivities: state.totalNewActivities++,
|
||||
}));
|
||||
},
|
||||
clearTotalNewActivities: () => {
|
||||
set(() => ({ totalNewActivities: 0 }));
|
||||
},
|
||||
}));
|
||||
@@ -4,6 +4,7 @@ import { createJSONStorage, persist } from 'zustand/middleware';
|
||||
interface StrongholdState {
|
||||
privkey: null | string;
|
||||
setPrivkey: (privkey: string) => void;
|
||||
clearPrivkey: () => void;
|
||||
}
|
||||
|
||||
export const useStronghold = create<StrongholdState>()(
|
||||
@@ -13,6 +14,9 @@ export const useStronghold = create<StrongholdState>()(
|
||||
setPrivkey: (privkey: string) => {
|
||||
set({ privkey: privkey });
|
||||
},
|
||||
clearPrivkey: () => {
|
||||
set({ privkey: null });
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: 'stronghold',
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createJSONStorage, persist } from 'zustand/middleware';
|
||||
|
||||
import { LumeStorage } from '@libs/storage/instance';
|
||||
|
||||
import { Widget } from '@utils/types';
|
||||
import { Widget, WidgetGroup } from '@utils/types';
|
||||
|
||||
interface WidgetState {
|
||||
widgets: null | Array<Widget>;
|
||||
@@ -39,25 +39,29 @@ export const WidgetKinds = {
|
||||
},
|
||||
};
|
||||
|
||||
export const DefaultWidgets = [
|
||||
export const DefaultWidgets: Array<WidgetGroup> = [
|
||||
{
|
||||
title: 'Network / Follows',
|
||||
data: [
|
||||
{
|
||||
kind: WidgetKinds.tmp.xfeed,
|
||||
title: 'Group feeds',
|
||||
description: 'All posts from specific people you want to keep up with',
|
||||
},
|
||||
{
|
||||
kind: WidgetKinds.local.files,
|
||||
title: 'Files',
|
||||
description: 'All files shared by people in your network',
|
||||
},
|
||||
{
|
||||
kind: WidgetKinds.local.articles,
|
||||
title: 'Articles',
|
||||
description: 'All articles shared by people in your network',
|
||||
},
|
||||
{
|
||||
kind: WidgetKinds.local.follows,
|
||||
title: 'Follows',
|
||||
description: 'All posts from people you are following',
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -67,27 +71,32 @@ export const DefaultWidgets = [
|
||||
{
|
||||
kind: WidgetKinds.tmp.xhashtag,
|
||||
title: 'Hashtag',
|
||||
description: 'All posts have a specific hashtag',
|
||||
},
|
||||
{
|
||||
kind: WidgetKinds.global.files,
|
||||
title: 'Files',
|
||||
description: 'All files shared by people in your current relay set',
|
||||
},
|
||||
{
|
||||
kind: WidgetKinds.global.articles,
|
||||
title: 'Articles',
|
||||
description: 'All articles shared by people in your current relay set',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Trending (nostr.band)',
|
||||
title: 'nostr.band',
|
||||
data: [
|
||||
{
|
||||
kind: WidgetKinds.nostrBand.trendingAccounts,
|
||||
title: 'Accounts',
|
||||
description: 'Trending accounts from the last 24 hours',
|
||||
},
|
||||
{
|
||||
kind: WidgetKinds.nostrBand.trendingNotes,
|
||||
title: 'Notes',
|
||||
description: 'Trending notes from the last 24 hours',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -12,7 +12,7 @@ export function useEvent(id: string, embed?: string) {
|
||||
const { status, data } = useQuery(
|
||||
['event', id],
|
||||
async () => {
|
||||
// return embed event (nostr.band api)
|
||||
// return embed event (nostr.band api) or repost
|
||||
if (embed) {
|
||||
const event: NDKEvent = JSON.parse(embed);
|
||||
return event;
|
||||
|
||||
@@ -3,17 +3,20 @@ import { EventPointer } from 'nostr-tools/lib/nip19';
|
||||
|
||||
import { RichContent } from '@utils/types';
|
||||
|
||||
function isURL(str: string) {
|
||||
const pattern = new RegExp(
|
||||
'^(https?:\\/\\/)?' + // protocol
|
||||
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
|
||||
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
|
||||
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
|
||||
'(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
|
||||
'(\\#[-a-z\\d_]*)?$', // fragment locator
|
||||
'i'
|
||||
);
|
||||
return !!pattern.test(str);
|
||||
function isURL(string: string) {
|
||||
try {
|
||||
const url = new URL(string);
|
||||
if (url.protocol.length > 0) {
|
||||
if (url.protocol === 'https:' || url.protocol === 'http:') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function parser(eventContent: string) {
|
||||
@@ -32,18 +35,18 @@ export function parser(eventContent: string) {
|
||||
const url = new URL(word);
|
||||
url.search = '';
|
||||
|
||||
if (url.toString().match(/\.(jpg|jpeg|gif|png|webp|avif)$/)) {
|
||||
if (url.pathname.match(/\.(jpg|jpeg|gif|png|webp|avif)$/)) {
|
||||
// image url
|
||||
content.images.push(word);
|
||||
// remove url from original content
|
||||
return word.replace(word, '');
|
||||
}
|
||||
|
||||
if (url.toString().match(/\.(mp4|mov|webm|wmv|flv|mts|avi|ogv|mkv|mp3|m3u8)$/)) {
|
||||
if (url.pathname.match(/\.(mp4|mov|webm|wmv|flv|mts|avi|ogv|mkv|mp3|m3u8)$/)) {
|
||||
// video
|
||||
content.videos.push(word);
|
||||
// remove url from original content
|
||||
word = word.replace(word, '');
|
||||
return word.replace(word, '');
|
||||
}
|
||||
|
||||
content.links.push(url.toString());
|
||||
|
||||
2
src/utils/types.d.ts
vendored
2
src/utils/types.d.ts
vendored
@@ -44,7 +44,9 @@ export interface WidgetGroup {
|
||||
|
||||
export interface WidgetGroupItem {
|
||||
title: string;
|
||||
description: string;
|
||||
kind: number;
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
export interface Widget {
|
||||
|
||||
Reference in New Issue
Block a user