new onboarding process

This commit is contained in:
Ren Amamiya 2023-06-21 20:55:22 +07:00
parent b1cecbbc07
commit eaaf0e0e8a
25 changed files with 764 additions and 532 deletions

View File

@ -15,7 +15,7 @@
"dependencies": {
"@floating-ui/react": "^0.23.1",
"@headlessui/react": "^1.7.15",
"@nostr-dev-kit/ndk": "^0.5.4",
"@nostr-dev-kit/ndk": "^0.5.13",
"@tanstack/react-virtual": "3.0.0-beta.54",
"@tauri-apps/api": "^1.4.0",
"@vidstack/react": "^0.4.5",
@ -28,6 +28,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.45.0",
"react-hotkeys-hook": "^4.4.0",
"react-resizable-panels": "^0.0.48",
"react-string-replace": "^1.1.1",
"react-virtuoso": "^4.3.10",
@ -44,8 +45,8 @@
"@tailwindcss/typography": "^0.5.9",
"@tauri-apps/cli": "^1.4.0",
"@types/node": "^18.16.18",
"@types/react": "^18.2.12",
"@types/react-dom": "^18.2.5",
"@types/react": "^18.2.13",
"@types/react-dom": "^18.2.6",
"@types/youtube-player": "^5.5.7",
"@vitejs/plugin-react-swc": "^3.3.2",
"autoprefixer": "^10.4.14",

View File

@ -8,8 +8,8 @@ dependencies:
specifier: ^1.7.15
version: 1.7.15(react-dom@18.2.0)(react@18.2.0)
'@nostr-dev-kit/ndk':
specifier: ^0.5.4
version: 0.5.4(typescript@4.9.5)
specifier: ^0.5.13
version: 0.5.13(typescript@4.9.5)
'@tanstack/react-virtual':
specifier: 3.0.0-beta.54
version: 3.0.0-beta.54(react@18.2.0)
@ -18,7 +18,7 @@ dependencies:
version: 1.4.0
'@vidstack/react':
specifier: ^0.4.5
version: 0.4.5(@types/react@18.2.12)(maverick.js@0.33.1)(media-icons@0.4.2)(react@18.2.0)(vidstack@0.4.5)
version: 0.4.5(@types/react@18.2.13)(maverick.js@0.33.1)(media-icons@0.4.2)(react@18.2.0)(vidstack@0.4.5)
dayjs:
specifier: ^1.11.8
version: 1.11.8
@ -46,6 +46,9 @@ dependencies:
react-hook-form:
specifier: ^7.45.0
version: 7.45.0(react@18.2.0)
react-hotkeys-hook:
specifier: ^4.4.0
version: 4.4.0(react-dom@18.2.0)(react@18.2.0)
react-resizable-panels:
specifier: ^0.0.48
version: 0.0.48(react-dom@18.2.0)(react@18.2.0)
@ -91,11 +94,11 @@ devDependencies:
specifier: ^18.16.18
version: 18.16.18
'@types/react':
specifier: ^18.2.12
version: 18.2.12
specifier: ^18.2.13
version: 18.2.13
'@types/react-dom':
specifier: ^18.2.5
version: 18.2.5
specifier: ^18.2.6
version: 18.2.6
'@types/youtube-player':
specifier: ^5.5.7
version: 5.5.7
@ -411,8 +414,8 @@ packages:
resolution: {integrity: sha512-Bu+AMaXNjrpjh41znzHqaz3r2Nr8hHuHZT6V2LBKMhyMl0FgKA62PNYbqnfgmzOhoWZj70Zecisbo4H1rotP5g==}
dev: false
/@floating-ui/dom@1.4.1:
resolution: {integrity: sha512-loCXUOLzIC3jp50RFOKXZ/kQjjz26ryr/23M+FWG9jrmAv8lRf3DUfC2AiVZ3+K316GOhB08CR+Povwz8e9mDw==}
/@floating-ui/dom@1.4.2:
resolution: {integrity: sha512-VKmvHVatWnewmGGy+7Mdy4cTJX71Pli6v/Wjb5RQBuq5wjUYx+Ef+kRThi8qggZqDgD8CogCpqhRoVp3+yQk+g==}
dependencies:
'@floating-ui/core': 1.3.1
dev: false
@ -423,7 +426,7 @@ packages:
react: '>=16.8.0'
react-dom: '>=16.8.0'
dependencies:
'@floating-ui/dom': 1.4.1
'@floating-ui/dom': 1.4.2
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
@ -530,8 +533,8 @@ packages:
resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==}
dev: false
/@maverick-js/signals@5.11.0:
resolution: {integrity: sha512-SpV3TAt8/ugELL2cI4mF70paHL3dnJbM69xSq7+z2BlsKeDwMK+oVXSq+WLgYANlfwkiOhZvvfQHo6Zo0muQVw==}
/@maverick-js/signals@5.11.1:
resolution: {integrity: sha512-yr6ZIpQxupgbDl6364t1L7bOSJqK2xiwjf8hoxJ632SL+0nBL0bLNCQaiK4GFRQEhYhBwX2yYyA+eKgZLEJ6mg==}
dev: false
/@noble/curves@1.0.0:
@ -571,20 +574,20 @@ packages:
'@nodelib/fs.scandir': 2.1.5
fastq: 1.15.0
/@nostr-dev-kit/ndk@0.5.4(typescript@4.9.5):
resolution: {integrity: sha512-A1JXJVJjyO8q53KXHnmFG6lf/b+7LSveLpHOJvUtcnbM/mkMtYlPJknMQ3i08oDdBO1j+nG3/8xYC3Y/8+arVw==}
/@nostr-dev-kit/ndk@0.5.13(typescript@4.9.5):
resolution: {integrity: sha512-Lu5vHzKmV3NrQyIxbneft7QlY2KpxOhsNOo1sN71z1b4plBSDrUT8xBgPTzm1itfL1Xw0kxy6pa/LSdVlsA3oQ==}
dependencies:
'@noble/hashes': 1.3.1
'@noble/secp256k1': 2.0.0
'@scure/base': 1.1.1
'@typescript-eslint/eslint-plugin': 5.59.11(@typescript-eslint/parser@5.59.11)(eslint@8.43.0)(typescript@4.9.5)
'@typescript-eslint/parser': 5.59.11(eslint@8.43.0)(typescript@4.9.5)
'@typescript-eslint/eslint-plugin': 5.60.0(@typescript-eslint/parser@5.60.0)(eslint@8.43.0)(typescript@4.9.5)
'@typescript-eslint/parser': 5.60.0(eslint@8.43.0)(typescript@4.9.5)
debug: 4.3.4
esbuild: 0.17.19
esbuild-plugin-alias: 0.2.1
eslint: 8.43.0
eslint-config-prettier: 8.8.0(eslint@8.43.0)
eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.59.11)(eslint@8.43.0)
eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.60.0)(eslint@8.43.0)
esm-loader-typescript: 1.0.4
eventemitter3: 5.0.1
light-bolt11-decoder: 3.0.0
@ -699,8 +702,8 @@ packages:
resolution: {integrity: sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==}
dev: false
/@swc/core-darwin-arm64@1.3.65:
resolution: {integrity: sha512-fQIXZgr7CD/+1ADqrVbz/gHvSoIMmggHvPzguQjV8FggBuS9Efm1D1ZrdUSqptggKvuLLHMZf+49tENq8NWWcg==}
/@swc/core-darwin-arm64@1.3.66:
resolution: {integrity: sha512-UijJsvuLy73vxeVYEy7urIHksXS+3BdvJ9s9AY+bRMSQW483NO7RLp8g4FdTyJbRaN0BH15SQnY0dcjQBkVuHw==}
engines: {node: '>=10'}
cpu: [arm64]
os: [darwin]
@ -708,8 +711,8 @@ packages:
dev: true
optional: true
/@swc/core-darwin-x64@1.3.65:
resolution: {integrity: sha512-kGuWP7OP9mwOiIcJpEVa+ydC3Wxf0fPQ1MK0hUIPFcR6tAUEdOvdAuCzP6U20RX/JbbgwfI/Qq6ugT7VL6omgg==}
/@swc/core-darwin-x64@1.3.66:
resolution: {integrity: sha512-xGsHKvViQnwTNLF30Y/5OqWdnN6RsiyUI8awZXfz1sHcXCEaLe+v+WLQ+/E8sgw0YUkYVHzzfV/sAN2CezJK5Q==}
engines: {node: '>=10'}
cpu: [x64]
os: [darwin]
@ -717,8 +720,8 @@ packages:
dev: true
optional: true
/@swc/core-linux-arm-gnueabihf@1.3.65:
resolution: {integrity: sha512-Bjbzldp8n4mWSdAvBt4VuLiHlfFM5pyftjJvJnmSY4H1IzbxkByyT60OHOedcIPRiZveD8NJzUJqutqrgTmtLg==}
/@swc/core-linux-arm-gnueabihf@1.3.66:
resolution: {integrity: sha512-gNbLcSIV2pq90BkMSpzvK4xPXOl8GEF3YR4NaqF0CYSzQsVXXTTqMuX/r26xNYudBKzH0345S1MpoRk2qricnA==}
engines: {node: '>=10'}
cpu: [arm]
os: [linux]
@ -726,8 +729,8 @@ packages:
dev: true
optional: true
/@swc/core-linux-arm64-gnu@1.3.65:
resolution: {integrity: sha512-GmxtcCymeQqEqT9n5mo857koRsUbEwmuijrBA4OeD5KOPW9gqAmUxr+ZgwgYHwyJ3CiN+UbK8uEqPsL6UVQmLg==}
/@swc/core-linux-arm64-gnu@1.3.66:
resolution: {integrity: sha512-cJSQ0oplyWbJqy4rzVcnBYLAi6z1QT3QCcR7iAey0aAmCvfRBZJfXlyjggMjn4iosuadkauwCZR1xYNhBDRn7w==}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
@ -735,8 +738,8 @@ packages:
dev: true
optional: true
/@swc/core-linux-arm64-musl@1.3.65:
resolution: {integrity: sha512-yv9jP3gbfMsYrqswT2MwK5Q1+avSwRXAKo+LYUknTeoLQNNlukDfqSLHajNq23XrVDRP4B3Pjn7kaqjxRcihbg==}
/@swc/core-linux-arm64-musl@1.3.66:
resolution: {integrity: sha512-GDQZpcB9aGxG9PTA2shdIkoMZlGK5omJ8NR49uoBTtLBVYiGeXAwV0U1Uaw8kXEZj9i7wZDkvjzjSaNH3evRsg==}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
@ -744,8 +747,8 @@ packages:
dev: true
optional: true
/@swc/core-linux-x64-gnu@1.3.65:
resolution: {integrity: sha512-GQkwysEPTlAOQ3jiTiedObzh6pBaf9RLaQqpGdCp+iKze9+BR+STBP0IIKhZDMPG/nWWNhrYFD/VMQxRoYPjfw==}
/@swc/core-linux-x64-gnu@1.3.66:
resolution: {integrity: sha512-lg8E4O/Pd9KfK0lajdinVMuGME8dSv7V9arhEpmlfGE2eXSDCWqDn5Htk5QVBstt9lt1lsRhWHJ/YYc2eQY30Q==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
@ -753,8 +756,8 @@ packages:
dev: true
optional: true
/@swc/core-linux-x64-musl@1.3.65:
resolution: {integrity: sha512-ETzhOhtDluYFK4x73OTM9gVTMyzGd2WeWGlCu3WoT1EPPUwCqQpcAqI3TfEcP1ljFDG0pPkpYzVpwNf8yjQElg==}
/@swc/core-linux-x64-musl@1.3.66:
resolution: {integrity: sha512-lo8ZcAO/zL2pZWH+LZIyge8u2MklaeuT6+FpVVpBFktMVdYXbaVtzpvWbgRFBZHvL3SRDF+u8jxjtkXhvGUpTw==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
@ -762,8 +765,8 @@ packages:
dev: true
optional: true
/@swc/core-win32-arm64-msvc@1.3.65:
resolution: {integrity: sha512-3weD0I6F8bggN0KOnbZkvYC1PBrT5wrvohpvtgijRsODxjoWwztozjawJxF3rqgVqlSI/+nA+JkrN48e2cxJjQ==}
/@swc/core-win32-arm64-msvc@1.3.66:
resolution: {integrity: sha512-cQoVwBuJY5WkHbfpCOlndNwYr1ZThatRjQQvKy540NUIeAEk9Fa6ozlDBtU75UdaWKtUG6YQ/bWz+KTemheVxw==}
engines: {node: '>=10'}
cpu: [arm64]
os: [win32]
@ -771,8 +774,8 @@ packages:
dev: true
optional: true
/@swc/core-win32-ia32-msvc@1.3.65:
resolution: {integrity: sha512-i6c3D7E9Ca41HteW3+hn1OKQfjIabc2P0p1mJRXBkn+igwb+Ba6gXJc7NqhrlF8uZsDhhcGZTsAqBBtfcfTuHQ==}
/@swc/core-win32-ia32-msvc@1.3.66:
resolution: {integrity: sha512-y/FrAIINK4UBeUQQknGlWXEyjo+MBvjF7WkUf2KP7sNr9EHHy8+dXohAGd5Anz0eJrqOM1ZXR/GEjxRp7bGQ1Q==}
engines: {node: '>=10'}
cpu: [ia32]
os: [win32]
@ -780,8 +783,8 @@ packages:
dev: true
optional: true
/@swc/core-win32-x64-msvc@1.3.65:
resolution: {integrity: sha512-tQ9hEDtwPZxQ2sYb2n8ypfmdMjobKAf6VSnChteLMktofU7o562op5pLS6D6QCP2AtL3lcwe1piTCgIhk4vmjA==}
/@swc/core-win32-x64-msvc@1.3.66:
resolution: {integrity: sha512-yI64ACzS14qFLrfyO12qW+f/UROTotzDeEbuyJAaPD2IZexoT1cICznI3sBmIfrSt33mVuW8eF5m3AG/NUImzw==}
engines: {node: '>=10'}
cpu: [x64]
os: [win32]
@ -789,8 +792,8 @@ packages:
dev: true
optional: true
/@swc/core@1.3.65:
resolution: {integrity: sha512-d5iDiKWf12FBo6h9Fro2pcnLK6HSPbyZ7A1U5iFNpRRx8XEd4uGdKtf5NoXJ3GDLQDLXnNSLA82Cl6SfrJ1lyw==}
/@swc/core@1.3.66:
resolution: {integrity: sha512-Hpf91kH5ly7fHkWnApwryTQryT+TO4kMMPH3WyciUSQOWLE3UuQz1PtETHQQk7PZ/b1QF0qQurJrgfBr5bSKUA==}
engines: {node: '>=10'}
requiresBuild: true
peerDependencies:
@ -799,16 +802,16 @@ packages:
'@swc/helpers':
optional: true
optionalDependencies:
'@swc/core-darwin-arm64': 1.3.65
'@swc/core-darwin-x64': 1.3.65
'@swc/core-linux-arm-gnueabihf': 1.3.65
'@swc/core-linux-arm64-gnu': 1.3.65
'@swc/core-linux-arm64-musl': 1.3.65
'@swc/core-linux-x64-gnu': 1.3.65
'@swc/core-linux-x64-musl': 1.3.65
'@swc/core-win32-arm64-msvc': 1.3.65
'@swc/core-win32-ia32-msvc': 1.3.65
'@swc/core-win32-x64-msvc': 1.3.65
'@swc/core-darwin-arm64': 1.3.66
'@swc/core-darwin-x64': 1.3.66
'@swc/core-linux-arm-gnueabihf': 1.3.66
'@swc/core-linux-arm64-gnu': 1.3.66
'@swc/core-linux-arm64-musl': 1.3.66
'@swc/core-linux-x64-gnu': 1.3.66
'@swc/core-linux-x64-musl': 1.3.66
'@swc/core-win32-arm64-msvc': 1.3.66
'@swc/core-win32-ia32-msvc': 1.3.66
'@swc/core-win32-x64-msvc': 1.3.66
dev: true
/@tailwindcss/typography@0.5.9(tailwindcss@3.3.2):
@ -999,14 +1002,14 @@ packages:
/@types/prop-types@15.7.5:
resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==}
/@types/react-dom@18.2.5:
resolution: {integrity: sha512-sRQsOS/sCLnpQhR4DSKGTtWFE3FZjpQa86KPVbhUqdYMRZ9FEFcfAytKhR/vUG2rH1oFbOOej6cuD7MFSobDRQ==}
/@types/react-dom@18.2.6:
resolution: {integrity: sha512-2et4PDvg6PVCyS7fuTc4gPoksV58bW0RwSxWKcPRcHZf0PRUGq03TKcD/rUHe3azfV6/5/biUBJw+HhCQjaP0A==}
dependencies:
'@types/react': 18.2.12
'@types/react': 18.2.13
dev: true
/@types/react@18.2.12:
resolution: {integrity: sha512-ndmBMLCgn38v3SntMeoJaIrO6tGHYKMEBohCUmw8HoLLQdRMOIGXfeYaBTLe2lsFaSB3MOK1VXscYFnmLtTSmw==}
/@types/react@18.2.13:
resolution: {integrity: sha512-vJ+zElvi/Zn9cVXB5slX2xL8PZodPCwPRDpittQdw43JR2AJ5k3vKdgJJyneV/cYgIbLQUwXa9JVDvUZXGba+Q==}
dependencies:
'@types/prop-types': 15.7.5
'@types/scheduler': 0.16.3
@ -1023,8 +1026,8 @@ packages:
resolution: {integrity: sha512-W8F4eoTIvzXeNrT3JroQPimZLXnlJA8smYygHZUKFPVoYwgs/OhJkA1VBhL3iSs57OQkuINqHlY4SmMT5wtnJg==}
dev: true
/@typescript-eslint/eslint-plugin@5.59.11(@typescript-eslint/parser@5.59.11)(eslint@8.43.0)(typescript@4.9.5):
resolution: {integrity: sha512-XxuOfTkCUiOSyBWIvHlUraLw/JT/6Io1365RO6ZuI88STKMavJZPNMU0lFcUTeQXEhHiv64CbxYxBNoDVSmghg==}
/@typescript-eslint/eslint-plugin@5.60.0(@typescript-eslint/parser@5.60.0)(eslint@8.43.0)(typescript@4.9.5):
resolution: {integrity: sha512-78B+anHLF1TI8Jn/cD0Q00TBYdMgjdOn980JfAVa9yw5sop8nyTfVOQAv6LWywkOGLclDBtv5z3oxN4w7jxyNg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
'@typescript-eslint/parser': ^5.0.0
@ -1035,10 +1038,10 @@ packages:
optional: true
dependencies:
'@eslint-community/regexpp': 4.5.1
'@typescript-eslint/parser': 5.59.11(eslint@8.43.0)(typescript@4.9.5)
'@typescript-eslint/scope-manager': 5.59.11
'@typescript-eslint/type-utils': 5.59.11(eslint@8.43.0)(typescript@4.9.5)
'@typescript-eslint/utils': 5.59.11(eslint@8.43.0)(typescript@4.9.5)
'@typescript-eslint/parser': 5.60.0(eslint@8.43.0)(typescript@4.9.5)
'@typescript-eslint/scope-manager': 5.60.0
'@typescript-eslint/type-utils': 5.60.0(eslint@8.43.0)(typescript@4.9.5)
'@typescript-eslint/utils': 5.60.0(eslint@8.43.0)(typescript@4.9.5)
debug: 4.3.4
eslint: 8.43.0
grapheme-splitter: 1.0.4
@ -1051,8 +1054,8 @@ packages:
- supports-color
dev: false
/@typescript-eslint/parser@5.59.11(eslint@8.43.0)(typescript@4.9.5):
resolution: {integrity: sha512-s9ZF3M+Nym6CAZEkJJeO2TFHHDsKAM3ecNkLuH4i4s8/RCPnF5JRip2GyviYkeEAcwGMJxkqG9h2dAsnA1nZpA==}
/@typescript-eslint/parser@5.60.0(eslint@8.43.0)(typescript@4.9.5):
resolution: {integrity: sha512-jBONcBsDJ9UoTWrARkRRCgDz6wUggmH5RpQVlt7BimSwaTkTjwypGzKORXbR4/2Hqjk9hgwlon2rVQAjWNpkyQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
@ -1061,9 +1064,9 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/scope-manager': 5.59.11
'@typescript-eslint/types': 5.59.11
'@typescript-eslint/typescript-estree': 5.59.11(typescript@4.9.5)
'@typescript-eslint/scope-manager': 5.60.0
'@typescript-eslint/types': 5.60.0
'@typescript-eslint/typescript-estree': 5.60.0(typescript@4.9.5)
debug: 4.3.4
eslint: 8.43.0
typescript: 4.9.5
@ -1071,16 +1074,16 @@ packages:
- supports-color
dev: false
/@typescript-eslint/scope-manager@5.59.11:
resolution: {integrity: sha512-dHFOsxoLFtrIcSj5h0QoBT/89hxQONwmn3FOQ0GOQcLOOXm+MIrS8zEAhs4tWl5MraxCY3ZJpaXQQdFMc2Tu+Q==}
/@typescript-eslint/scope-manager@5.60.0:
resolution: {integrity: sha512-hakuzcxPwXi2ihf9WQu1BbRj1e/Pd8ZZwVTG9kfbxAMZstKz8/9OoexIwnmLzShtsdap5U/CoQGRCWlSuPbYxQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
'@typescript-eslint/types': 5.59.11
'@typescript-eslint/visitor-keys': 5.59.11
'@typescript-eslint/types': 5.60.0
'@typescript-eslint/visitor-keys': 5.60.0
dev: false
/@typescript-eslint/type-utils@5.59.11(eslint@8.43.0)(typescript@4.9.5):
resolution: {integrity: sha512-LZqVY8hMiVRF2a7/swmkStMYSoXMFlzL6sXV6U/2gL5cwnLWQgLEG8tjWPpaE4rMIdZ6VKWwcffPlo1jPfk43g==}
/@typescript-eslint/type-utils@5.60.0(eslint@8.43.0)(typescript@4.9.5):
resolution: {integrity: sha512-X7NsRQddORMYRFH7FWo6sA9Y/zbJ8s1x1RIAtnlj6YprbToTiQnM6vxcMu7iYhdunmoC0rUWlca13D5DVHkK2g==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: '*'
@ -1089,8 +1092,8 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/typescript-estree': 5.59.11(typescript@4.9.5)
'@typescript-eslint/utils': 5.59.11(eslint@8.43.0)(typescript@4.9.5)
'@typescript-eslint/typescript-estree': 5.60.0(typescript@4.9.5)
'@typescript-eslint/utils': 5.60.0(eslint@8.43.0)(typescript@4.9.5)
debug: 4.3.4
eslint: 8.43.0
tsutils: 3.21.0(typescript@4.9.5)
@ -1099,13 +1102,13 @@ packages:
- supports-color
dev: false
/@typescript-eslint/types@5.59.11:
resolution: {integrity: sha512-epoN6R6tkvBYSc+cllrz+c2sOFWkbisJZWkOE+y3xHtvYaOE6Wk6B8e114McRJwFRjGvYdJwLXQH5c9osME/AA==}
/@typescript-eslint/types@5.60.0:
resolution: {integrity: sha512-ascOuoCpNZBccFVNJRSC6rPq4EmJ2NkuoKnd6LDNyAQmdDnziAtxbCGWCbefG1CNzmDvd05zO36AmB7H8RzKPA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: false
/@typescript-eslint/typescript-estree@5.59.11(typescript@4.9.5):
resolution: {integrity: sha512-YupOpot5hJO0maupJXixi6l5ETdrITxeo5eBOeuV7RSKgYdU3G5cxO49/9WRnJq9EMrB7AuTSLH/bqOsXi7wPA==}
/@typescript-eslint/typescript-estree@5.60.0(typescript@4.9.5):
resolution: {integrity: sha512-R43thAuwarC99SnvrBmh26tc7F6sPa2B3evkXp/8q954kYL6Ro56AwASYWtEEi+4j09GbiNAHqYwNNZuNlARGQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
typescript: '*'
@ -1113,8 +1116,8 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/types': 5.59.11
'@typescript-eslint/visitor-keys': 5.59.11
'@typescript-eslint/types': 5.60.0
'@typescript-eslint/visitor-keys': 5.60.0
debug: 4.3.4
globby: 11.1.0
is-glob: 4.0.3
@ -1125,8 +1128,8 @@ packages:
- supports-color
dev: false
/@typescript-eslint/utils@5.59.11(eslint@8.43.0)(typescript@4.9.5):
resolution: {integrity: sha512-didu2rHSOMUdJThLk4aZ1Or8IcO3HzCw/ZvEjTTIfjIrcdd5cvSIwwDy2AOlE7htSNp7QIZ10fLMyRCveesMLg==}
/@typescript-eslint/utils@5.60.0(eslint@8.43.0)(typescript@4.9.5):
resolution: {integrity: sha512-ba51uMqDtfLQ5+xHtwlO84vkdjrqNzOnqrnwbMHMRY8Tqeme8C2Q8Fc7LajfGR+e3/4LoYiWXUM6BpIIbHJ4hQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
@ -1134,9 +1137,9 @@ packages:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.43.0)
'@types/json-schema': 7.0.12
'@types/semver': 7.5.0
'@typescript-eslint/scope-manager': 5.59.11
'@typescript-eslint/types': 5.59.11
'@typescript-eslint/typescript-estree': 5.59.11(typescript@4.9.5)
'@typescript-eslint/scope-manager': 5.60.0
'@typescript-eslint/types': 5.60.0
'@typescript-eslint/typescript-estree': 5.60.0(typescript@4.9.5)
eslint: 8.43.0
eslint-scope: 5.1.1
semver: 7.5.2
@ -1145,15 +1148,15 @@ packages:
- typescript
dev: false
/@typescript-eslint/visitor-keys@5.59.11:
resolution: {integrity: sha512-KGYniTGG3AMTuKF9QBD7EIrvufkB6O6uX3knP73xbKLMpH+QRPcgnCxjWXSHjMRuOxFLovljqQgQpR0c7GvjoA==}
/@typescript-eslint/visitor-keys@5.60.0:
resolution: {integrity: sha512-wm9Uz71SbCyhUKgcaPRauBdTegUyY/ZWl8gLwD/i/ybJqscrrdVSFImpvUz16BLPChIeKBK5Fa9s6KDQjsjyWw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
'@typescript-eslint/types': 5.59.11
'@typescript-eslint/types': 5.60.0
eslint-visitor-keys: 3.4.1
dev: false
/@vidstack/react@0.4.5(@types/react@18.2.12)(maverick.js@0.33.1)(media-icons@0.4.2)(react@18.2.0)(vidstack@0.4.5):
/@vidstack/react@0.4.5(@types/react@18.2.13)(maverick.js@0.33.1)(media-icons@0.4.2)(react@18.2.0)(vidstack@0.4.5):
resolution: {integrity: sha512-spcim3+p1fMzkhHRKn5PS54YQjfThW5M3F2+R8tCT+wpsxbbCDa/TGdLBoIy2oC0LNziPkn0vlBWIZko9F5iig==}
engines: {node: '>=16'}
peerDependencies:
@ -1163,7 +1166,7 @@ packages:
react: ^18.0.0
vidstack: 0.4.5
dependencies:
'@types/react': 18.2.12
'@types/react': 18.2.13
maverick.js: 0.33.1
media-icons: 0.4.2
react: 18.2.0
@ -1175,7 +1178,7 @@ packages:
peerDependencies:
vite: ^4
dependencies:
'@swc/core': 1.3.65
'@swc/core': 1.3.66
vite: 4.3.9(@types/node@18.16.18)
transitivePeerDependencies:
- '@swc/helpers'
@ -1370,7 +1373,7 @@ packages:
postcss: ^8.1.0
dependencies:
browserslist: 4.21.9
caniuse-lite: 1.0.30001504
caniuse-lite: 1.0.30001506
fraction.js: 4.2.0
normalize-range: 0.1.2
picocolors: 1.0.0
@ -1414,8 +1417,8 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
dependencies:
caniuse-lite: 1.0.30001504
electron-to-chromium: 1.4.433
caniuse-lite: 1.0.30001506
electron-to-chromium: 1.4.435
node-releases: 2.0.12
update-browserslist-db: 1.0.11(browserslist@4.21.9)
dev: true
@ -1482,8 +1485,8 @@ packages:
engines: {node: '>=6'}
dev: false
/caniuse-lite@1.0.30001504:
resolution: {integrity: sha512-5uo7eoOp2mKbWyfMXnGO9rJWOGU8duvzEiYITW+wivukL7yHH4gX9yuRaobu6El4jPxo6jKZfG+N6fB621GD/Q==}
/caniuse-lite@1.0.30001506:
resolution: {integrity: sha512-6XNEcpygZMCKaufIcgpQNZNf00GEqc7VQON+9Rd0K1bMYo8xhMZRAo5zpbnbMNizi4YNgIDAFrdykWsvY3H4Hw==}
dev: true
/chalk@2.4.2:
@ -1780,8 +1783,8 @@ packages:
/eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
/electron-to-chromium@1.4.433:
resolution: {integrity: sha512-MGO1k0w1RgrfdbLVwmXcDhHHuxCn2qRgR7dYsJvWFKDttvYPx6FNzCGG0c/fBBvzK2LDh3UV7Tt9awnHnvAAUQ==}
/electron-to-chromium@1.4.435:
resolution: {integrity: sha512-B0CBWVFhvoQCW/XtjRzgrmqcgVWg6RXOEM/dK59+wFV93BFGR6AeNKc4OyhM+T3IhJaOOG8o/V+33Y2mwJWtzw==}
dev: true
/emoji-regex@8.0.0:
@ -1984,7 +1987,7 @@ packages:
- supports-color
dev: false
/eslint-module-utils@2.8.0(@typescript-eslint/parser@5.59.11)(eslint-import-resolver-node@0.3.7)(eslint@8.43.0):
/eslint-module-utils@2.8.0(@typescript-eslint/parser@5.60.0)(eslint-import-resolver-node@0.3.7)(eslint@8.43.0):
resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==}
engines: {node: '>=4'}
peerDependencies:
@ -2005,7 +2008,7 @@ packages:
eslint-import-resolver-webpack:
optional: true
dependencies:
'@typescript-eslint/parser': 5.59.11(eslint@8.43.0)(typescript@4.9.5)
'@typescript-eslint/parser': 5.60.0(eslint@8.43.0)(typescript@4.9.5)
debug: 3.2.7
eslint: 8.43.0
eslint-import-resolver-node: 0.3.7
@ -2013,7 +2016,7 @@ packages:
- supports-color
dev: false
/eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.59.11)(eslint@8.43.0):
/eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.60.0)(eslint@8.43.0):
resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==}
engines: {node: '>=4'}
peerDependencies:
@ -2023,7 +2026,7 @@ packages:
'@typescript-eslint/parser':
optional: true
dependencies:
'@typescript-eslint/parser': 5.59.11(eslint@8.43.0)(typescript@4.9.5)
'@typescript-eslint/parser': 5.60.0(eslint@8.43.0)(typescript@4.9.5)
array-includes: 3.1.6
array.prototype.flat: 1.3.1
array.prototype.flatmap: 1.3.1
@ -2031,7 +2034,7 @@ packages:
doctrine: 2.1.0
eslint: 8.43.0
eslint-import-resolver-node: 0.3.7
eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.59.11)(eslint-import-resolver-node@0.3.7)(eslint@8.43.0)
eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.60.0)(eslint-import-resolver-node@0.3.7)(eslint@8.43.0)
has: 1.0.3
is-core-module: 2.12.1
is-glob: 4.0.3
@ -3075,7 +3078,7 @@ packages:
resolution: {integrity: sha512-p8L5V62CV6TmHAngmRAopp231oJKeH77mJja5SsKOfvzrPRoThT/Jo9U0jMRB5iMykqkvyg2J5V5Agn6FPXDWQ==}
engines: {node: '>=16'}
dependencies:
'@maverick-js/signals': 5.11.0
'@maverick-js/signals': 5.11.1
type-fest: 3.12.0
dev: false
@ -3623,8 +3626,8 @@ packages:
engines: {node: '>=4'}
dev: false
/pirates@4.0.5:
resolution: {integrity: sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==}
/pirates@4.0.6:
resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
engines: {node: '>= 6'}
dev: true
@ -3786,6 +3789,16 @@ packages:
react: 18.2.0
dev: false
/react-hotkeys-hook@4.4.0(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-wOaCWLwgT/f895CMJrR9hmzVf+gfL8IpjWDXWXKngBp9i6Xqzf0tvLv4VI8l3Vlsg/cc4C/Iik3Ck76L/Hj0tw==}
peerDependencies:
react: '>=16.8.1'
react-dom: '>=16.8.1'
dependencies:
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
/react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
dev: true
@ -4300,7 +4313,7 @@ packages:
glob: 7.1.6
lines-and-columns: 1.2.4
mz: 2.7.0
pirates: 4.0.5
pirates: 4.0.6
ts-interface-checker: 0.1.13
dev: true
@ -4701,7 +4714,7 @@ packages:
vite: '>=2.8'
dependencies:
'@rollup/plugin-virtual': 3.0.1
'@swc/core': 1.3.65
'@swc/core': 1.3.66
uuid: 9.0.0
vite: 4.3.9(@types/node@18.16.18)
transitivePeerDependencies:

View File

@ -16,7 +16,7 @@ tauri-build = { version = "1.2", features = [] }
[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
tauri = { version = "1.2", features = [ "global-shortcut-all", "clipboard-read-text", "clipboard-write-text", "dialog-open", "fs-read-dir", "fs-read-file", "http-all", "http-multipart", "notification-all", "os-all", "process-relaunch", "shell-open", "system-tray", "updater", "window-close", "window-start-dragging"] }
tauri = { version = "1.2", features = [ "clipboard-read-text", "clipboard-write-text", "dialog-open", "fs-read-dir", "fs-read-file", "http-all", "http-multipart", "notification-all", "os-all", "process-relaunch", "shell-open", "system-tray", "updater", "window-close", "window-start-dragging"] }
tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
tauri-plugin-store = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
sqlx-cli = {version = "0.6.3", default-features = false, features = ["sqlite"] }

View File

@ -22,7 +22,11 @@
"http": {
"all": true,
"request": true,
"scope": ["https://void.cat/*", "https://skrape.dev/*"]
"scope": [
"https://void.cat/*",
"https://skrape.dev/*",
"https://lume.nu/*"
]
},
"fs": {
"all": false,
@ -66,9 +70,6 @@
"exit": false,
"relaunch": true,
"relaunchDangerousAllowSymlinkMacos": false
},
"globalShortcut": {
"all": true
}
},
"bundle": {

View File

@ -6,11 +6,23 @@ import { shortenKey } from "@utils/shortenKey";
export function User({ pubkey }: { pubkey: string }) {
const { user } = useProfile(pubkey);
if (!user) {
return (
<div className="flex items-center gap-2">
<div className="relative h-11 w-11 shrink-0 rounded-md bg-zinc-800 animate-pulse" />
<div className="flex w-full flex-1 flex-col items-start text-start">
<span className="w-full h-3 rounded bg-zinc-800 animate-pulse" />
<span className="w-1/2 h-3 rounded bg-zinc-800 animate-pulse" />
</div>
</div>
);
}
return (
<div className="flex items-center gap-2">
<div className="relative h-11 w-11 shrink rounded-md">
<Image
src={user?.image || DEFAULT_AVATAR}
src={user.image || DEFAULT_AVATAR}
alt={pubkey}
className="h-11 w-11 rounded-md object-cover"
decoding="async"
@ -18,10 +30,10 @@ export function User({ pubkey }: { pubkey: string }) {
</div>
<div className="flex w-full flex-1 flex-col items-start text-start">
<span className="truncate font-medium leading-tight text-zinc-100">
{user?.displayName || user?.name}
{user.displayName || user.name}
</span>
<span className="text-base leading-tight text-zinc-400">
{user?.nip05?.toLowerCase() || shortenKey(pubkey)}
{user.nip05?.toLowerCase() || shortenKey(pubkey)}
</span>
</div>
</div>

View File

@ -1,3 +1,4 @@
import { Button } from "@shared/button";
import { EyeOffIcon, EyeOnIcon } from "@shared/icons";
import { useActiveAccount } from "@stores/accounts";
import { generatePrivateKey, getPublicKey, nip19 } from "nostr-tools";
@ -41,24 +42,22 @@ export function Page() {
<label className="text-base font-semibold text-zinc-400">
Public Key
</label>
<div className="relative shrink-0 before:pointer-events-none before:absolute before:-inset-1 before:rounded-[11px] before:border before:border-blue-500 before:opacity-0 before:ring-2 before:ring-blue-500/20 before:transition after:pointer-events-none after:absolute after:inset-px after:rounded-[7px] after:shadow-highlight after:shadow-white/5 after:transition focus-within:before:opacity-100 focus-within:after:shadow-blue-500/100 dark:focus-within:after:shadow-blue-500/20">
<input
readOnly
value={npub}
className="relative w-full rounded-lg border border-black/5 px-3.5 py-2.5 shadow-input shadow-black/5 !outline-none placeholder:text-zinc-400 dark:bg-zinc-800 dark:text-zinc-100 dark:shadow-black/10 dark:placeholder:text-zinc-600"
/>
</div>
<input
readOnly
value={npub}
className="relative w-full rounded-lg py-3 pl-3.5 pr-11 !outline-none placeholder:text-zinc-400 bg-zinc-800 text-zinc-100"
/>
</div>
<div className="flex flex-col gap-1">
<label className="text-base font-semibold text-zinc-400">
Private Key
</label>
<div className="relative shrink-0 before:pointer-events-none before:absolute before:-inset-1 before:rounded-[11px] before:border before:border-blue-500 before:opacity-0 before:ring-2 before:ring-blue-500/20 before:transition after:pointer-events-none after:absolute after:inset-px after:rounded-[7px] after:shadow-highlight after:shadow-white/5 after:transition focus-within:before:opacity-100 focus-within:after:shadow-blue-500/100 dark:focus-within:after:shadow-blue-500/20">
<div className="relative">
<input
readOnly
type={type}
value={nsec}
className="relative w-full rounded-lg border border-black/5 py-2.5 pl-3.5 pr-11 shadow-input shadow-black/5 !outline-none placeholder:text-zinc-400 dark:bg-zinc-800 dark:text-zinc-100 dark:shadow-black/10 dark:placeholder:text-zinc-600"
className="relative w-full rounded-lg py-3 pl-3.5 pr-11 !outline-none placeholder:text-zinc-400 bg-zinc-800 text-zinc-100"
/>
<button
type="button"
@ -81,13 +80,9 @@ export function Page() {
</button>
</div>
</div>
<button
type="button"
onClick={() => submit()}
className="w-full transform rounded-lg bg-fuchsia-500 px-3.5 py-2.5 font-medium text-zinc-100 shadow-button hover:bg-fuchsia-600 active:translate-y-1 disabled:cursor-not-allowed disabled:opacity-70"
>
<span>Continue </span>
</button>
<Button preset="large" onClick={() => submit()}>
Continue
</Button>
</div>
</div>
</div>

View File

@ -1,16 +1,16 @@
import { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
import { AvatarUploader } from "@shared/avatarUploader";
import { LoaderIcon } from "@shared/icons";
import { Image } from "@shared/image";
import { RelayContext } from "@shared/relayProvider";
import { useActiveAccount } from "@stores/accounts";
import { DEFAULT_AVATAR } from "@stores/constants";
import { useContext, useEffect, useState } from "react";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { navigate } from "vite-plugin-ssr/client/router";
export function Page() {
const ndk = useContext(RelayContext);
const account = useActiveAccount((state: any) => state.account);
const createTempProfile = useActiveAccount(
(state: any) => state.createTempProfile,
);
const [image, setImage] = useState(DEFAULT_AVATAR);
const [loading, setLoading] = useState(false);
@ -24,28 +24,13 @@ export function Page() {
const onSubmit = (data: any) => {
setLoading(true);
try {
const signer = new NDKPrivateKeySigner(account.privkey);
ndk.signer = signer;
const event = new NDKEvent(ndk);
// build event
event.content = JSON.stringify(data);
event.kind = 0;
event.pubkey = account.pubkey;
event.tags = [];
// publish event
event.publish();
const profile = { ...data, name: data.displayName };
createTempProfile(profile);
// redirect to step 3
setTimeout(
() =>
navigate("/app/auth/create/step-3", {
overwriteLastHistoryEntry: true,
}),
2000,
);
navigate("/app/auth/create/step-3", {
overwriteLastHistoryEntry: true,
});
} catch {
console.log("error");
}
@ -63,7 +48,7 @@ export function Page() {
Create your profile
</h1>
</div>
<div className="w-full rounded-lg border border-zinc-800 bg-zinc-900 p-4">
<div className="w-full rounded-xl border-t border-zinc-800/50 bg-zinc-900 p-5">
<form
onSubmit={handleSubmit(onSubmit)}
className="flex flex-col gap-4"
@ -75,7 +60,7 @@ export function Page() {
className="relative h-10 w-full rounded-lg border border-black/5 px-3 py-2 shadow-input shadow-black/5 !outline-none placeholder:text-zinc-400 dark:bg-zinc-800 dark:text-zinc-100 dark:shadow-black/10 dark:placeholder:text-zinc-500"
/>
<div className="flex flex-col gap-1">
<label className="text-base font-semibold uppercase tracking-wider text-zinc-400">
<label className="text-sm font-semibold uppercase tracking-wider text-zinc-400">
Avatar
</label>
<div className="relative inline-flex h-36 w-full items-center justify-center overflow-hidden rounded-lg border border-zinc-900 bg-zinc-950">
@ -90,63 +75,39 @@ export function Page() {
</div>
</div>
<div className="flex flex-col gap-1">
<label className="text-base font-semibold uppercase tracking-wider text-zinc-400">
<label className="text-sm font-semibold uppercase tracking-wider text-zinc-400">
Display Name *
</label>
<div className="relative w-full shrink-0 overflow-hidden before:pointer-events-none before:absolute before:-inset-1 before:rounded-[11px] before:border before:border-fuchsia-500 before:opacity-0 before:ring-2 before:ring-fuchsia-500/20 before:transition after:pointer-events-none after:absolute after:inset-px after:rounded-[7px] after:shadow-highlight after:shadow-white/5 after:transition focus-within:before:opacity-100 focus-within:after:shadow-fuchsia-500/100 dark:focus-within:after:shadow-fuchsia-500/20">
<input
type={"text"}
{...register("displayName", {
required: true,
minLength: 4,
})}
spellCheck={false}
className="relative h-10 w-full rounded-lg border border-black/5 px-3 py-2 shadow-input shadow-black/5 !outline-none placeholder:text-zinc-400 dark:bg-zinc-800 dark:text-zinc-100 dark:shadow-black/10 dark:placeholder:text-zinc-500"
/>
</div>
<input
type={"text"}
{...register("displayName", {
required: true,
minLength: 4,
})}
spellCheck={false}
className="relative h-10 w-full rounded-lg px-3 py-2 !outline-none bg-zinc-800 text-zinc-100 placeholder:text-zinc-500"
/>
</div>
<div className="flex flex-col gap-1">
<label className="text-base font-semibold uppercase tracking-wider text-zinc-400">
<label className="text-sm font-semibold uppercase tracking-wider text-zinc-400">
Bio
</label>
<div className="relative h-20 w-full shrink-0 overflow-hidden before:pointer-events-none before:absolute before:-inset-1 before:rounded-[11px] before:border before:border-fuchsia-500 before:opacity-0 before:ring-2 before:ring-fuchsia-500/20 before:transition after:pointer-events-none after:absolute after:inset-px after:rounded-[7px] after:shadow-highlight after:shadow-white/5 after:transition focus-within:before:opacity-100 focus-within:after:shadow-fuchsia-500/100 dark:focus-within:after:shadow-fuchsia-500/20">
<textarea
{...register("bio")}
spellCheck={false}
className="relative h-20 w-full resize-none rounded-lg border border-black/5 px-3 py-2 shadow-input shadow-black/5 !outline-none placeholder:text-zinc-400 dark:bg-zinc-800 dark:text-zinc-100 dark:shadow-black/10 dark:placeholder:text-zinc-500"
/>
</div>
<textarea
{...register("about")}
spellCheck={false}
className="resize-none relative h-20 w-full rounded-lg px-3 py-2 !outline-none bg-zinc-800 text-zinc-100 placeholder:text-zinc-500"
/>
</div>
<div>
<button
type="submit"
disabled={!isDirty || !isValid}
className="inline-flex h-10 w-full transform items-center justify-center rounded-lg bg-fuchsia-500 px-3.5 font-medium text-zinc-100 shadow-button hover:bg-fuchsia-600 active:translate-y-1 disabled:cursor-not-allowed disabled:opacity-70"
className="inline-flex items-center justify-center h-11 w-full bg-fuchsia-500 rounded-md font-medium text-zinc-100 hover:bg-fuchsia-600"
>
{loading ? (
<svg
className="h-4 w-4 animate-spin text-black dark:text-zinc-100"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<title id="loading">Loading</title>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
/>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
/>
</svg>
<LoaderIcon className="h-4 w-4 animate-spin text-black dark:text-zinc-100" />
) : (
<span>Continue </span>
"Continue →"
)}
</button>
</div>

View File

@ -1,160 +1,62 @@
import { User } from "@app/auth/components/user";
import { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
import { CheckCircleIcon } from "@shared/icons";
import { Button } from "@shared/button";
import { LoaderIcon } from "@shared/icons";
import { RelayContext } from "@shared/relayProvider";
import { useActiveAccount } from "@stores/accounts";
import { arrayToNIP02 } from "@utils/transform";
import { Body, fetch } from "@tauri-apps/api/http";
import { useContext, useState } from "react";
import { navigate } from "vite-plugin-ssr/client/router";
const initialList = [
{
pubkey: "82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2",
},
{
pubkey: "a341f45ff9758f570a21b000c17d4e53a3a497c8397f26c0e6d61e5acffc7a98",
},
{
pubkey: "04c915daefee38317fa734444acee390a8269fe5810b2241e5e6dd343dfbecc9",
},
{
pubkey: "c4eabae1be3cf657bc1855ee05e69de9f059cb7a059227168b80b89761cbc4e0",
},
{
pubkey: "6e468422dfb74a5738702a8823b9b28168abab8655faacb6853cd0ee15deee93",
},
{
pubkey: "e88a691e98d9987c964521dff60025f60700378a4879180dcbbb4a5027850411",
},
{
pubkey: "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d",
},
{
pubkey: "c49d52a573366792b9a6e4851587c28042fb24fa5625c6d67b8c95c8751aca15",
},
{
pubkey: "e33fe65f1fde44c6dc17eeb38fdad0fceaf1cae8722084332ed1e32496291d42",
},
{
pubkey: "84dee6e676e5bb67b4ad4e042cf70cbd8681155db535942fcc6a0533858a7240",
},
{
pubkey: "703e26b4f8bc0fa57f99d815dbb75b086012acc24fc557befa310f5aa08d1898",
},
{
pubkey: "bf2376e17ba4ec269d10fcc996a4746b451152be9031fa48e74553dde5526bce",
},
{
pubkey: "4523be58d395b1b196a9b8c82b038b6895cb02b683d0c253a955068dba1facd0",
},
{
pubkey: "c9b19ffcd43e6a5f23b3d27106ce19e4ad2df89ba1031dd4617f1b591e108965",
},
{
pubkey: "c7dccba4fe4426a7b1ea239a5637ba40fab9862c8c86b3330fe65e9f667435f6",
},
{
pubkey: "6e1534f56fc9e937e06237c8ba4b5662bcacc4e1a3cfab9c16d89390bec4fca3",
},
{
pubkey: "50d94fc2d8580c682b071a542f8b1e31a200b0508bab95a33bef0855df281d63",
},
{
pubkey: "3d2e51508699f98f0f2bdbe7a45b673c687fe6420f466dc296d90b908d51d594",
},
{
pubkey: "6e3f51664e19e082df5217fd4492bb96907405a0b27028671dd7f297b688608c",
},
{
pubkey: "2edbcea694d164629854a52583458fd6d965b161e3c48b57d3aff01940558884",
},
{
pubkey: "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24",
},
{
pubkey: "eab0e756d32b80bcd464f3d844b8040303075a13eabc3599a762c9ac7ab91f4f",
},
{
pubkey: "be1d89794bf92de5dd64c1e60f6a2c70c140abac9932418fee30c5c637fe9479",
},
{
pubkey: "a5e93aef8e820cbc7ab7b6205f854b87aed4b48c5f6b30fbbeba5c99e40dcf3f",
},
{
pubkey: "1989034e56b8f606c724f45a12ce84a11841621aaf7182a1f6564380b9c4276b",
},
{
pubkey: "c48b5cced5ada74db078df6b00fa53fc1139d73bf0ed16de325d52220211dbd5",
},
{
pubkey: "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c",
},
{
pubkey: "7f3b464b9ff3623630485060cbda3a7790131c5339a7803bde8feb79a5e1b06a",
},
{
pubkey: "b99dbca0184a32ce55904cb267b22e434823c97f418f36daf5d2dff0dd7b5c27",
},
{
pubkey: "e9e4276490374a0daf7759fd5f475deff6ffb9b0fc5fa98c902b5f4b2fe3bba2",
},
{
pubkey: "ea2e3c814d08a378f8a5b8faecb2884d05855975c5ca4b5c25e2d6f936286f14",
},
{
pubkey: "ff04a0e6cd80c141b0b55825fed127d4532a6eecdb7e743a38a3c28bf9f44609",
},
];
export function Page() {
const ndk = useContext(RelayContext);
const [account, updateFollows] = useActiveAccount((state: any) => [
const [account, tempProfile] = useActiveAccount((state: any) => [
state.account,
state.updateFollows,
state.tempProfile,
]);
const [username, setUsername] = useState("");
const [loading, setLoading] = useState(false);
const [follows, setFollows] = useState([]);
// toggle follow state
const toggleFollow = (pubkey: string) => {
const arr = follows.includes(pubkey)
? follows.filter((i) => i !== pubkey)
: [...follows, pubkey];
setFollows(arr);
};
// save follows to database then broadcast
const submit = async () => {
setLoading(true);
const createNIP05 = async () => {
try {
const tags = arrayToNIP02(follows);
const signer = new NDKPrivateKeySigner(account.privkey);
ndk.signer = signer;
setLoading(true);
const event = new NDKEvent(ndk);
// build event
event.content = "";
event.kind = 3;
event.pubkey = account.pubkey;
event.tags = tags;
// publish event
event.publish();
const response = await fetch("https://lume.nu/api/user-create", {
method: "POST",
timeout: 30,
headers: {
"Content-Type": "application/json; charset=utf-8",
},
body: Body.json({
username: username,
pubkey: account.pubkey,
lightningAddress: "",
}),
});
// update account follows
updateFollows(follows);
if (response.ok) {
const profile = { ...tempProfile, nip05: `${username}@lume.nu` };
// redirect to step 3
setTimeout(
() =>
navigate("/", {
overwriteLastHistoryEntry: true,
}),
2000,
);
} catch {
console.log("error");
const signer = new NDKPrivateKeySigner(account.privkey);
ndk.signer = signer;
const event = new NDKEvent(ndk);
// build event
event.content = JSON.stringify(profile);
event.kind = 0;
event.pubkey = account.pubkey;
event.tags = [];
// publish event
event.publish();
// redirect to step 4
navigate("/app/auth/create/step-4", {
overwriteLastHistoryEntry: true,
});
}
} catch (error) {
setLoading(false);
console.error("Error:", error);
}
};
@ -163,73 +65,36 @@ export function Page() {
<div className="mx-auto w-full max-w-md">
<div className="mb-8 text-center">
<h1 className="text-xl font-semibold text-zinc-100">
Personalized your newsfeed
Create your Lume ID
</h1>
</div>
<div className="flex flex-col gap-4">
<div className="w-full rounded-lg border border-zinc-800 bg-zinc-900">
<div className="inline-flex h-10 w-full items-center gap-1 border-b border-zinc-800 px-4 text-base font-medium text-zinc-400">
Follow at least
<span className="bg-gradient-to-r from-fuchsia-300 via-orange-100 to-amber-300 bg-clip-text font-bold text-transparent">
{follows.length}/10
</span>{" "}
plebs
</div>
<div className="scrollbar-hide flex h-96 flex-col overflow-y-auto py-2">
{initialList.map((item: { pubkey: string }, index: number) => (
<button
key={`item-${index}`}
type="button"
onClick={() => toggleFollow(item.pubkey)}
className="inline-flex transform items-center justify-between bg-zinc-900 px-4 py-2 hover:bg-zinc-800 active:translate-y-1"
>
<User pubkey={item.pubkey} />
{follows.includes(item.pubkey) && (
<div>
<CheckCircleIcon
width={16}
height={16}
className="text-green-400"
/>
</div>
)}
</button>
))}
</div>
<div className="w-full flex flex-col justify-center items-center gap-4">
<div className="w-full inline-flex items-center justify-center gap-2 rounded-lg bg-zinc-800">
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
autoCapitalize="false"
autoCorrect="none"
spellCheck="false"
placeholder="satoshi"
className="relative w-full py-3 pl-3.5 !outline-none placeholder:text-zinc-500 bg-transparent text-zinc-100"
/>
<span className="text-fuchsia-500 font-semibold pr-3.5">
@lume.nu
</span>
</div>
{follows.length >= 10 && (
<button
type="button"
onClick={() => submit()}
className="inline-flex h-10 w-full transform items-center justify-center rounded-lg bg-fuchsia-500 px-3.5 font-medium text-zinc-100 shadow-button hover:bg-fuchsia-600 active:translate-y-1 disabled:cursor-not-allowed disabled:opacity-70"
>
{loading === true ? (
<svg
className="h-5 w-5 animate-spin text-zinc-100"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<title id="loading">Loading</title>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
/>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
/>
</svg>
) : (
<span>Continue </span>
)}
</button>
)}
<Button
preset="large"
onClick={() => createNIP05()}
disabled={username.length === 0}
>
{loading ? (
<LoaderIcon className="h-4 w-4 animate-spin text-black dark:text-zinc-100" />
) : (
"Continue →"
)}
</Button>
</div>
</div>
</div>

View File

@ -0,0 +1,217 @@
import { User } from "@app/auth/components/user";
import { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
import { CheckCircleIcon, LoaderIcon } from "@shared/icons";
import { RelayContext } from "@shared/relayProvider";
import { useActiveAccount } from "@stores/accounts";
import { arrayToNIP02 } from "@utils/transform";
import { useContext, useState } from "react";
import { navigate } from "vite-plugin-ssr/client/router";
const initialList = [
{
pubkey: "82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2",
},
{
pubkey: "a341f45ff9758f570a21b000c17d4e53a3a497c8397f26c0e6d61e5acffc7a98",
},
{
pubkey: "04c915daefee38317fa734444acee390a8269fe5810b2241e5e6dd343dfbecc9",
},
{
pubkey: "c4eabae1be3cf657bc1855ee05e69de9f059cb7a059227168b80b89761cbc4e0",
},
{
pubkey: "6e468422dfb74a5738702a8823b9b28168abab8655faacb6853cd0ee15deee93",
},
{
pubkey: "e88a691e98d9987c964521dff60025f60700378a4879180dcbbb4a5027850411",
},
{
pubkey: "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d",
},
{
pubkey: "c49d52a573366792b9a6e4851587c28042fb24fa5625c6d67b8c95c8751aca15",
},
{
pubkey: "e33fe65f1fde44c6dc17eeb38fdad0fceaf1cae8722084332ed1e32496291d42",
},
{
pubkey: "84dee6e676e5bb67b4ad4e042cf70cbd8681155db535942fcc6a0533858a7240",
},
{
pubkey: "703e26b4f8bc0fa57f99d815dbb75b086012acc24fc557befa310f5aa08d1898",
},
{
pubkey: "bf2376e17ba4ec269d10fcc996a4746b451152be9031fa48e74553dde5526bce",
},
{
pubkey: "4523be58d395b1b196a9b8c82b038b6895cb02b683d0c253a955068dba1facd0",
},
{
pubkey: "c9b19ffcd43e6a5f23b3d27106ce19e4ad2df89ba1031dd4617f1b591e108965",
},
{
pubkey: "c7dccba4fe4426a7b1ea239a5637ba40fab9862c8c86b3330fe65e9f667435f6",
},
{
pubkey: "6e1534f56fc9e937e06237c8ba4b5662bcacc4e1a3cfab9c16d89390bec4fca3",
},
{
pubkey: "50d94fc2d8580c682b071a542f8b1e31a200b0508bab95a33bef0855df281d63",
},
{
pubkey: "3d2e51508699f98f0f2bdbe7a45b673c687fe6420f466dc296d90b908d51d594",
},
{
pubkey: "6e3f51664e19e082df5217fd4492bb96907405a0b27028671dd7f297b688608c",
},
{
pubkey: "2edbcea694d164629854a52583458fd6d965b161e3c48b57d3aff01940558884",
},
{
pubkey: "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24",
},
{
pubkey: "eab0e756d32b80bcd464f3d844b8040303075a13eabc3599a762c9ac7ab91f4f",
},
{
pubkey: "be1d89794bf92de5dd64c1e60f6a2c70c140abac9932418fee30c5c637fe9479",
},
{
pubkey: "a5e93aef8e820cbc7ab7b6205f854b87aed4b48c5f6b30fbbeba5c99e40dcf3f",
},
{
pubkey: "1989034e56b8f606c724f45a12ce84a11841621aaf7182a1f6564380b9c4276b",
},
{
pubkey: "c48b5cced5ada74db078df6b00fa53fc1139d73bf0ed16de325d52220211dbd5",
},
{
pubkey: "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c",
},
{
pubkey: "7f3b464b9ff3623630485060cbda3a7790131c5339a7803bde8feb79a5e1b06a",
},
{
pubkey: "b99dbca0184a32ce55904cb267b22e434823c97f418f36daf5d2dff0dd7b5c27",
},
{
pubkey: "e9e4276490374a0daf7759fd5f475deff6ffb9b0fc5fa98c902b5f4b2fe3bba2",
},
{
pubkey: "ea2e3c814d08a378f8a5b8faecb2884d05855975c5ca4b5c25e2d6f936286f14",
},
{
pubkey: "ff04a0e6cd80c141b0b55825fed127d4532a6eecdb7e743a38a3c28bf9f44609",
},
];
export function Page() {
const ndk = useContext(RelayContext);
const [loading, setLoading] = useState(false);
const [follows, setFollows] = useState([]);
const [account, updateFollows] = useActiveAccount((state: any) => [
state.account,
state.updateFollows,
]);
// toggle follow state
const toggleFollow = (pubkey: string) => {
const arr = follows.includes(pubkey)
? follows.filter((i) => i !== pubkey)
: [...follows, pubkey];
setFollows(arr);
};
// save follows to database then broadcast
const submit = async () => {
try {
setLoading(true);
const tags = arrayToNIP02(follows);
const signer = new NDKPrivateKeySigner(account.privkey);
ndk.signer = signer;
const event = new NDKEvent(ndk);
// build event
event.content = "";
event.kind = 3;
event.pubkey = account.pubkey;
event.tags = tags;
// publish event
event.publish();
// update account follows
updateFollows(follows);
// redirect to onboarding
setTimeout(
() =>
navigate("/app/onboarding", {
overwriteLastHistoryEntry: true,
}),
2000,
);
} catch {
console.log("error");
}
};
return (
<div className="flex h-full w-full items-center justify-center">
<div className="mx-auto w-full max-w-md">
<div className="mb-8 text-center">
<h1 className="text-xl font-semibold text-zinc-100">
Personalized your newsfeed
</h1>
</div>
<div className="flex flex-col gap-4">
<div className="w-full rounded-xl border-t border-zinc-800/50 bg-zinc-900 overflow-hidden">
<div className="inline-flex h-10 w-full items-center gap-1 border-b border-zinc-800 px-4 text-base font-medium text-zinc-400">
Follow at least
<span className="text-fuchsia-500 font-semibold">
{follows.length}/10
</span>{" "}
plebs
</div>
<div className="scrollbar-hide flex h-96 flex-col overflow-y-auto py-2">
{initialList.map((item: { pubkey: string }, index: number) => (
<button
key={`item-${index}`}
type="button"
onClick={() => toggleFollow(item.pubkey)}
className="inline-flex transform items-center justify-between bg-zinc-900 px-4 py-2 hover:bg-zinc-800 active:translate-y-1"
>
<User pubkey={item.pubkey} />
{follows.includes(item.pubkey) && (
<div>
<CheckCircleIcon
width={16}
height={16}
className="text-green-400"
/>
</div>
)}
</button>
))}
</div>
</div>
{follows.length >= 10 && (
<button
type="button"
onClick={() => submit()}
className="inline-flex items-center justify-center h-11 w-full bg-fuchsia-500 rounded-md font-medium text-zinc-100 hover:bg-fuchsia-600"
>
{loading ? (
<LoaderIcon className="h-4 w-4 animate-spin text-black dark:text-zinc-100" />
) : (
"Finish →"
)}
</button>
)}
</div>
</div>
</div>
);
}

View File

@ -1,3 +1,4 @@
import { LoaderIcon } from "@shared/icons";
import { useActiveAccount } from "@stores/accounts";
import { getPublicKey, nip19 } from "nostr-tools";
import { Resolver, useForm } from "react-hook-form";
@ -67,50 +68,28 @@ export function Page() {
className="flex flex-col gap-3"
>
<div className="flex flex-col gap-0.5">
<div className="relative shrink-0 before:pointer-events-none before:absolute before:-inset-1 before:rounded-[11px] before:transition after:pointer-events-none after:absolute after:inset-px after:rounded-[7px] after:shadow-highlight after:shadow-white/5 after:transition focus-within:before:opacity-100 focus-within:after:shadow-fuchsia-500/100 dark:focus-within:after:shadow-fuchsia-500/20">
<input
{...register("key", { required: true, minLength: 32 })}
type={"password"}
placeholder="Paste private key here..."
className="relative w-full rounded-lg border border-black/5 px-3.5 py-2.5 text-center shadow-input shadow-black/5 !outline-none placeholder:text-zinc-400 dark:bg-zinc-800 dark:text-zinc-100 dark:shadow-black/10 dark:placeholder:text-zinc-500"
/>
</div>
<input
{...register("key", { required: true, minLength: 32 })}
type={"password"}
placeholder="Paste private key here..."
className="relative w-full rounded-lg px-3 py-3 !outline-none bg-zinc-800 text-zinc-100 placeholder:text-zinc-500"
/>
<span className="text-base text-red-400">
{errors.key && <p>{errors.key.message}</p>}
</span>
</div>
<div className="flex h-9 items-center justify-center">
{isSubmitting ? (
<svg
className="h-5 w-5 animate-spin text-zinc-100"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<title id="loading">Loading</title>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
/>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
/>
</svg>
) : (
<button
type="submit"
disabled={!isDirty || !isValid}
className="w-full transform rounded-lg bg-fuchsia-500 px-3.5 py-2.5 font-medium text-zinc-100 shadow-button hover:bg-fuchsia-600 active:translate-y-1 disabled:cursor-not-allowed disabled:opacity-70"
>
<span className="drop-shadow-lg">Continue </span>
</button>
)}
<div className="flex items-center justify-center">
<button
type="submit"
disabled={!isDirty || !isValid}
className="inline-flex items-center justify-center h-11 w-full bg-fuchsia-500 rounded-md font-medium text-zinc-100 hover:bg-fuchsia-600"
>
{isSubmitting ? (
<LoaderIcon className="h-4 w-4 animate-spin text-black dark:text-zinc-100" />
) : (
"Continue →"
)}
</button>
</div>
</form>
</div>

View File

@ -1,4 +1,5 @@
import { User } from "@app/auth/components/user";
import { LoaderIcon } from "@shared/icons";
import { RelayContext } from "@shared/relayProvider";
import { useActiveAccount } from "@stores/accounts";
import { setToArray } from "@utils/transform";
@ -28,9 +29,9 @@ export function Page() {
// update account follows in store
updateFollows(followsList);
// redirect to home
// redirect to onboarding
setTimeout(
() => navigate("/", { overwriteLastHistoryEntry: true }),
() => navigate("/app/onboarding", { overwriteLastHistoryEntry: true }),
2000,
);
} catch {
@ -63,31 +64,12 @@ export function Page() {
<button
type="button"
onClick={() => submit()}
className="inline-flex h-10 w-full transform items-center justify-center rounded-lg bg-fuchsia-500 px-3.5 font-medium text-zinc-100 shadow-button hover:bg-fuchsia-600 active:translate-y-1 disabled:cursor-not-allowed disabled:opacity-70"
className="inline-flex items-center justify-center h-11 w-full bg-fuchsia-500 rounded-md font-medium text-zinc-100 hover:bg-fuchsia-600"
>
{loading ? (
<svg
className="h-5 w-5 animate-spin text-black dark:text-zinc-100"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
/>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
/>
</svg>
<LoaderIcon className="h-4 w-4 animate-spin text-black dark:text-zinc-100" />
) : (
<span>Continue </span>
"Continue →"
)}
</button>
</div>

View File

@ -1,26 +1,52 @@
import { ArrowRightCircleIcon } from "@shared/icons/arrowRightCircle";
export function Page() {
return (
<div className="flex flex-col justify-between h-full w-full">
<div className="w-full h-full flex flex-col justify-center items-center gap-4 overflow-hidden">
<h1 className="text-white text-5xl font-bold leading-none text-transparent">
Preserve your freedom
</h1>
<div className="mt-4 flex flex-col gap-1.5">
<div className="w-full h-full grid grid-cols-12 gap-4 px-4 py-4">
<div className="col-span-5 border-t border-zinc-800/50 bg-zinc-900 rounded-xl flex flex-col">
<div className="w-full h-full flex flex-col justify-center px-4 py-4 gap-2">
<h1 className="text-zinc-700 text-4xl font-bold leading-none text-transparent">
Preserve your <span className="text-fuchsia-300">freedom</span>
</h1>
<h2 className="text-zinc-700 text-4xl font-bold leading-none text-transparent">
Protect your <span className="text-red-300">future</span>
</h2>
<h3 className="text-zinc-700 text-4xl font-bold leading-none text-transparent">
Stack <span className="text-orange-300">bitcoin</span>
</h3>
<h3 className="text-zinc-700 text-4xl font-bold leading-none text-transparent">
Use <span className="text-purple-300">nostr</span>
</h3>
</div>
<div className="mt-auto w-full flex flex-col gap-2 px-4 py-4">
<a
href="/app/auth/import"
className="inline-flex h-14 w-64 items-center justify-center gap-2 rounded-lg px-6 font-medium text-zinc-200 hover:bg-zinc-900"
className="inline-flex h-12 w-full items-center justify-between gap-2 rounded-lg px-6 font-medium text-zinc-100 bg-fuchsia-500 hover:bg-fuchsia-600"
>
Login with private key
<span className="w-5" />
<span>Login with private key</span>
<ArrowRightCircleIcon className="w-5 h-5" />
</a>
<a
href="/app/auth/create"
className="inline-flex h-14 w-64 items-center justify-center gap-2 rounded-lg px-6 font-medium text-zinc-200 hover:bg-zinc-900"
className="inline-flex h-12 w-full items-center justify-center gap-2 rounded-lg px-6 font-medium text-zinc-200 bg-zinc-800 hover:bg-zinc-700"
>
Create new key
</a>
</div>
</div>
<div className="overflow-hidden" />
<div
className="col-span-5 bg-zinc-900 rounded-xl bg-cover bg-center"
style={{
backgroundImage: `url("https://void.cat/d/Ps1b36vu5pdkEA2w75usuB")`,
}}
/>
<div
className="col-span-2 bg-zinc-900 rounded-xl bg-cover bg-center"
style={{
backgroundImage: `url("https://void.cat/d/5FdJcBP5ZXKAjYqV8hpcp3")`,
}}
/>
</div>
);
}

View File

@ -9,19 +9,18 @@ export function Page() {
const lastLogin = useActiveAccount((state: any) => state.lastLogin);
useEffect(() => {
if (!account) {
navigate("/app/auth", { overwriteLastHistoryEntry: true });
}
if (account) {
navigate("/app/prefetch", { overwriteLastHistoryEntry: true });
}
if (account === null) {
fetchAccount();
}
if (lastLogin === null) {
fetchLastLogin();
}
if (!account) {
navigate("/app/auth", { overwriteLastHistoryEntry: true });
}
if (account) {
navigate("/app/prefetch", { overwriteLastHistoryEntry: true });
}
}, [fetchAccount, fetchLastLogin, account, lastLogin]);
return (

View File

@ -0,0 +1 @@
export { LayoutOnboarding as Layout } from "./layout";

View File

@ -0,0 +1,65 @@
import { ArrowLeftIcon, ArrowRightIcon } from "@shared/icons";
import useSWR from "swr";
const fetcher = async () => {
const { platform } = await import("@tauri-apps/api/os");
return await platform();
};
export function LayoutOnboarding({ children }: { children: React.ReactNode }) {
const { data: platform } = useSWR("platform", fetcher);
const goBack = () => {
window.history.back();
};
const goForward = () => {
window.history.forward();
};
return (
<div className="h-screen w-screen bg-zinc-50 text-zinc-900 dark:bg-zinc-950 dark:text-zinc-100">
<div className="flex h-screen w-full flex-col">
<div
data-tauri-drag-region
className="relative h-9 shrink-0 border border-zinc-100 bg-white dark:border-zinc-900 dark:bg-black"
>
<div
data-tauri-drag-region
className="flex h-full w-full flex-1 items-center px-2"
>
<div
className={`flex h-full items-center gap-2 ${
platform === "darwin" ? "pl-[68px]" : ""
}`}
>
<button
type="button"
onClick={() => goBack()}
className="group inline-flex h-6 w-6 items-center justify-center rounded-md hover:bg-zinc-900"
>
<ArrowLeftIcon
width={16}
height={16}
className="text-zinc-500 group-hover:text-zinc-300"
/>
</button>
<button
type="button"
onClick={() => goForward()}
className="group inline-flex h-6 w-6 items-center justify-center rounded-md hover:bg-zinc-900"
>
<ArrowRightIcon
width={16}
height={16}
className="text-zinc-500 group-hover:text-zinc-300"
/>
</button>
</div>
</div>
</div>
<div className="relative flex min-h-0 w-full flex-1">{children}</div>
</div>
</div>
);
}

View File

@ -0,0 +1,106 @@
import { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
import { ArrowRightCircleIcon } from "@shared/icons/arrowRightCircle";
import { RelayContext } from "@shared/relayProvider";
import { User } from "@shared/user";
import { useActiveAccount } from "@stores/accounts";
import { dateToUnix } from "@utils/date";
import { useContext, useEffect } from "react";
import { navigate } from "vite-plugin-ssr/client/router";
export function Page() {
const ndk = useContext(RelayContext);
const [account, fetchAccount] = useActiveAccount((state: any) => [
state.account,
state.fetch,
]);
useEffect(() => {
if (account === null) {
fetchAccount();
}
}, [fetchAccount]);
const publish = async () => {
try {
const event = new NDKEvent(ndk);
const signer = new NDKPrivateKeySigner(account.privkey);
ndk.signer = signer;
event.content =
"Running Lume, fighting for better future, join us here: https://lume.nu";
event.created_at = dateToUnix();
event.pubkey = account.pubkey;
event.kind = 1;
event.tags = [];
// publish event
event.publish();
// redirect to home
setTimeout(
() => navigate("/", { overwriteLastHistoryEntry: true }),
2000,
);
} catch (error) {
console.log(error);
}
};
return (
<div className="flex h-full w-full items-center justify-center">
<div className="mx-auto w-full max-w-md">
<div className="mb-8 text-center">
<h1 className="mb-2 text-xl font-semibold text-zinc-100">
👋 Hello, welcome you to Lume
</h1>
<p className="text-sm text-zinc-300">
You're a part of better future that we're fighting
</p>
<p className="text-sm text-zinc-300">
If Lume gets your attention, please help us spread via button below
</p>
</div>
<div className="w-full border-t border-zinc-800/50 bg-zinc-900 rounded-xl">
<div className="h-min w-full px-5 py-3">
<User
pubkey={account.pubkey}
time={Math.floor(Date.now() / 1000)}
/>
<div className="-mt-6 pl-[49px] select-text whitespace-pre-line break-words text-base text-zinc-100">
<p>Running Lume, fighting for better future</p>
<p>
join us here:{" "}
<a
href="https://lume.nu"
className="text-fuchsia-500 hover:text-fuchsia-600 no-underline font-normal"
target="_blank"
rel="noreferrer"
>
https://lume.nu
</a>
</p>
</div>
</div>
</div>
<div className="mt-4 w-full flex flex-col gap-2">
<button
type="button"
onClick={() => publish()}
className="inline-flex h-12 w-full items-center justify-between gap-2 rounded-lg px-6 font-medium text-zinc-100 bg-fuchsia-500 hover:bg-fuchsia-600"
>
<span className="w-5" />
<span>Publish</span>
<ArrowRightCircleIcon className="w-5 h-5" />
</button>
<a
href="/"
className="inline-flex h-10 w-full items-center justify-center gap-2 rounded-lg px-6 text-sm font-medium text-zinc-200"
>
Skip for now
</a>
</div>
</div>
</div>
);
}

View File

@ -0,0 +1,11 @@
export function Page() {
return (
<div className="flex h-full w-full items-center justify-center">
<div className="mx-auto w-full max-w-md">
<div className="mb-8 text-center">
<h1 className="text-xl font-semibold text-zinc-100"># TODO</h1>
</div>
</div>
</div>
);
}

View File

@ -17,7 +17,7 @@ export function Page() {
const ndk = useContext(RelayContext);
const pageContext = usePageContext();
const searchParams: any = pageContext.urlParsed.search;
const pubkey = searchParams.pubkey;
const pubkey = searchParams.pubkey || "";
const { user } = useProfile(pubkey);
const { data: userStats, error } = useSWR(

View File

@ -1,5 +1,6 @@
import { createBlobFromFile } from "@utils/createBlobFromFile";
import { LoaderIcon } from "./icons";
import { open } from "@tauri-apps/api/dialog";
import { Body, fetch } from "@tauri-apps/api/http";
import { useState } from "react";
@ -54,30 +55,10 @@ export function AvatarUploader({ valueState }: { valueState: any }) {
<button
onClick={() => openFileDialog()}
type="button"
className="inline-flex h-6 items-center justify-center rounded bg-zinc-900 px-3 text-base font-medium text-zinc-100 ring-1 ring-zinc-800 hover:bg-zinc-700"
className="inline-flex h-7 items-center justify-center rounded bg-zinc-900 px-3 text-sm font-medium text-zinc-200 hover:bg-zinc-800"
>
{loading ? (
<svg
className="h-4 w-4 animate-spin text-black dark:text-zinc-100"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<title id="loading">Loading</title>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
/>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
/>
</svg>
<LoaderIcon className="h-4 w-4 animate-spin text-black dark:text-zinc-100" />
) : (
<span className="leading-none">Upload</span>
)}

View File

@ -24,7 +24,7 @@ export function Button({
break;
case "large":
preClass =
"h-11 w-full bg-fuchsia-500 rounded-md text-sm font-medium text-zinc-100 hover:bg-fuchsia-600";
"h-11 w-full bg-fuchsia-500 rounded-md font-medium text-zinc-100 hover:bg-fuchsia-600";
break;
default:
break;

View File

@ -11,8 +11,8 @@ import {
import { useActiveAccount } from "@stores/accounts";
import { useComposer } from "@stores/composer";
import { COMPOSE_SHORTCUT } from "@stores/shortcuts";
import { isRegistered, register } from "@tauri-apps/api/globalShortcut";
import { Fragment, useEffect } from "react";
import { Fragment } from "react";
import { useHotkeys } from "react-hotkeys-hook";
export function Composer() {
const account = useActiveAccount((state: any) => state.account);
@ -25,18 +25,7 @@ export function Composer() {
toggle(false);
};
const registerShortcut = async () => {
const isShortcutRegistered = await isRegistered(COMPOSE_SHORTCUT);
if (!isShortcutRegistered) {
await register(COMPOSE_SHORTCUT, () => {
toggle(true);
});
}
};
useEffect(() => {
registerShortcut();
}, []);
useHotkeys(COMPOSE_SHORTCUT, () => toggle(true));
return (
<>

View File

@ -0,0 +1,24 @@
import { SVGProps } from "react";
export function ArrowRightCircleIcon(
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="M7.75 12h8M13 8.75l2.896 2.896a.5.5 0 010 .708L13 15.25M21.25 12a9.25 9.25 0 11-18.5 0 9.25 9.25 0 0118.5 0z"
/>
</svg>
);
}

View File

@ -10,7 +10,7 @@ export function Kind1({
return (
<>
<div
className={`select-text break-words text-base text-zinc-100 ${
className={`select-text whitespace-pre-line break-words text-base text-zinc-100 ${
truncate ? "line-clamp-3" : ""
}`}
>

View File

@ -15,9 +15,13 @@ export const useActiveAccount = create(
immer(
persist(
(set: any, get: any) => ({
tempProfile: {},
account: null,
blocks: null,
lastLogin: null,
createTempProfile: (data: any) => {
set({ tempProfile: data });
},
create: async (npub: string, pubkey: string, privkey: string) => {
const response = await createAccount(npub, pubkey, privkey, null, 1);
if (response) {
@ -25,8 +29,8 @@ export const useActiveAccount = create(
await addBlockToDB(
activeAccount.id,
0,
"Freedom Awaits",
"https://void.cat/d/88M2kWHtjZLRtdyfAajHbu.webp",
"Lume ❤️ You",
"https://void.cat/d/5FdJcBP5ZXKAjYqV8hpcp3",
);
set({
account: activeAccount,

View File

@ -1 +1 @@
export const COMPOSE_SHORTCUT = "CommandOrControl+N";
export const COMPOSE_SHORTCUT = "meta+n";