feat(depot): update onboarding screen

This commit is contained in:
reya 2023-12-19 15:43:32 +07:00
parent d9e8d05db7
commit a6ca2589ab
13 changed files with 397 additions and 579 deletions

View File

@ -80,6 +80,7 @@
"react-hotkeys-hook": "^4.4.1",
"react-router-dom": "^6.21.0",
"react-string-replace": "^1.1.1",
"smol-toml": "^1.1.3",
"sonner": "^1.2.4",
"tippy.js": "^6.3.7",
"tiptap-markdown": "^0.8.8",
@ -116,7 +117,7 @@
"tailwind-scrollbar": "^3.0.5",
"tailwindcss": "^3.3.7",
"typescript": "^5.3.3",
"vite": "^5.0.10",
"vite": "4",
"vite-tsconfig-paths": "^4.2.2"
}
}

View File

@ -191,6 +191,9 @@ dependencies:
react-string-replace:
specifier: ^1.1.1
version: 1.1.1
smol-toml:
specifier: ^1.1.3
version: 1.1.3
sonner:
specifier: ^1.2.4
version: 1.2.4(react-dom@18.2.0)(react@18.2.0)
@ -237,7 +240,7 @@ devDependencies:
version: 6.15.0(eslint@8.56.0)(typescript@5.3.3)
'@vitejs/plugin-react-swc':
specifier: ^3.5.0
version: 3.5.0(vite@5.0.10)
version: 3.5.0(vite@4.5.1)
autoprefixer:
specifier: ^10.4.16
version: 10.4.16(postcss@8.4.32)
@ -296,11 +299,11 @@ devDependencies:
specifier: ^5.3.3
version: 5.3.3
vite:
specifier: ^5.0.10
version: 5.0.10(@types/node@20.10.5)
specifier: '4'
version: 4.5.1(@types/node@20.10.5)
vite-tsconfig-paths:
specifier: ^4.2.2
version: 4.2.2(typescript@5.3.3)(vite@5.0.10)
version: 4.2.2(typescript@5.3.3)(vite@4.5.1)
packages:
@ -459,17 +462,8 @@ packages:
dev: false
optional: true
/@esbuild/aix-ppc64@0.19.10:
resolution: {integrity: sha512-Q+mk96KJ+FZ30h9fsJl+67IjNJm3x2eX+GBWGmocAKgzp27cowCOOqSdscX80s0SpdFXZnIv/+1xD1EctFx96Q==}
engines: {node: '>=12'}
cpu: [ppc64]
os: [aix]
requiresBuild: true
dev: true
optional: true
/@esbuild/android-arm64@0.19.10:
resolution: {integrity: sha512-1X4CClKhDgC3by7k8aOWZeBXQX8dHT5QAMCAQDArCLaYfkppoARvh0fit3X2Qs+MXDngKcHv6XXyQCpY0hkK1Q==}
/@esbuild/android-arm64@0.18.20:
resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==}
engines: {node: '>=12'}
cpu: [arm64]
os: [android]
@ -477,8 +471,8 @@ packages:
dev: true
optional: true
/@esbuild/android-arm@0.19.10:
resolution: {integrity: sha512-7W0bK7qfkw1fc2viBfrtAEkDKHatYfHzr/jKAHNr9BvkYDXPcC6bodtm8AyLJNNuqClLNaeTLuwURt4PRT9d7w==}
/@esbuild/android-arm@0.18.20:
resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==}
engines: {node: '>=12'}
cpu: [arm]
os: [android]
@ -486,8 +480,8 @@ packages:
dev: true
optional: true
/@esbuild/android-x64@0.19.10:
resolution: {integrity: sha512-O/nO/g+/7NlitUxETkUv/IvADKuZXyH4BHf/g/7laqKC4i/7whLpB0gvpPc2zpF0q9Q6FXS3TS75QHac9MvVWw==}
/@esbuild/android-x64@0.18.20:
resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==}
engines: {node: '>=12'}
cpu: [x64]
os: [android]
@ -495,8 +489,8 @@ packages:
dev: true
optional: true
/@esbuild/darwin-arm64@0.19.10:
resolution: {integrity: sha512-YSRRs2zOpwypck+6GL3wGXx2gNP7DXzetmo5pHXLrY/VIMsS59yKfjPizQ4lLt5vEI80M41gjm2BxrGZ5U+VMA==}
/@esbuild/darwin-arm64@0.18.20:
resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==}
engines: {node: '>=12'}
cpu: [arm64]
os: [darwin]
@ -504,8 +498,8 @@ packages:
dev: true
optional: true
/@esbuild/darwin-x64@0.19.10:
resolution: {integrity: sha512-alfGtT+IEICKtNE54hbvPg13xGBe4GkVxyGWtzr+yHO7HIiRJppPDhOKq3zstTcVf8msXb/t4eavW3jCDpMSmA==}
/@esbuild/darwin-x64@0.18.20:
resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [darwin]
@ -513,8 +507,8 @@ packages:
dev: true
optional: true
/@esbuild/freebsd-arm64@0.19.10:
resolution: {integrity: sha512-dMtk1wc7FSH8CCkE854GyGuNKCewlh+7heYP/sclpOG6Cectzk14qdUIY5CrKDbkA/OczXq9WesqnPl09mj5dg==}
/@esbuild/freebsd-arm64@0.18.20:
resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==}
engines: {node: '>=12'}
cpu: [arm64]
os: [freebsd]
@ -522,8 +516,8 @@ packages:
dev: true
optional: true
/@esbuild/freebsd-x64@0.19.10:
resolution: {integrity: sha512-G5UPPspryHu1T3uX8WiOEUa6q6OlQh6gNl4CO4Iw5PS+Kg5bVggVFehzXBJY6X6RSOMS8iXDv2330VzaObm4Ag==}
/@esbuild/freebsd-x64@0.18.20:
resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [freebsd]
@ -531,8 +525,8 @@ packages:
dev: true
optional: true
/@esbuild/linux-arm64@0.19.10:
resolution: {integrity: sha512-QxaouHWZ+2KWEj7cGJmvTIHVALfhpGxo3WLmlYfJ+dA5fJB6lDEIg+oe/0//FuyVHuS3l79/wyBxbHr0NgtxJQ==}
/@esbuild/linux-arm64@0.18.20:
resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==}
engines: {node: '>=12'}
cpu: [arm64]
os: [linux]
@ -540,8 +534,8 @@ packages:
dev: true
optional: true
/@esbuild/linux-arm@0.19.10:
resolution: {integrity: sha512-j6gUW5aAaPgD416Hk9FHxn27On28H4eVI9rJ4az7oCGTFW48+LcgNDBN+9f8rKZz7EEowo889CPKyeaD0iw9Kg==}
/@esbuild/linux-arm@0.18.20:
resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==}
engines: {node: '>=12'}
cpu: [arm]
os: [linux]
@ -549,8 +543,8 @@ packages:
dev: true
optional: true
/@esbuild/linux-ia32@0.19.10:
resolution: {integrity: sha512-4ub1YwXxYjj9h1UIZs2hYbnTZBtenPw5NfXCRgEkGb0b6OJ2gpkMvDqRDYIDRjRdWSe/TBiZltm3Y3Q8SN1xNg==}
/@esbuild/linux-ia32@0.18.20:
resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==}
engines: {node: '>=12'}
cpu: [ia32]
os: [linux]
@ -558,8 +552,8 @@ packages:
dev: true
optional: true
/@esbuild/linux-loong64@0.19.10:
resolution: {integrity: sha512-lo3I9k+mbEKoxtoIbM0yC/MZ1i2wM0cIeOejlVdZ3D86LAcFXFRdeuZmh91QJvUTW51bOK5W2BznGNIl4+mDaA==}
/@esbuild/linux-loong64@0.18.20:
resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==}
engines: {node: '>=12'}
cpu: [loong64]
os: [linux]
@ -567,8 +561,8 @@ packages:
dev: true
optional: true
/@esbuild/linux-mips64el@0.19.10:
resolution: {integrity: sha512-J4gH3zhHNbdZN0Bcr1QUGVNkHTdpijgx5VMxeetSk6ntdt+vR1DqGmHxQYHRmNb77tP6GVvD+K0NyO4xjd7y4A==}
/@esbuild/linux-mips64el@0.18.20:
resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==}
engines: {node: '>=12'}
cpu: [mips64el]
os: [linux]
@ -576,8 +570,8 @@ packages:
dev: true
optional: true
/@esbuild/linux-ppc64@0.19.10:
resolution: {integrity: sha512-tgT/7u+QhV6ge8wFMzaklOY7KqiyitgT1AUHMApau32ZlvTB/+efeCtMk4eXS+uEymYK249JsoiklZN64xt6oQ==}
/@esbuild/linux-ppc64@0.18.20:
resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==}
engines: {node: '>=12'}
cpu: [ppc64]
os: [linux]
@ -585,8 +579,8 @@ packages:
dev: true
optional: true
/@esbuild/linux-riscv64@0.19.10:
resolution: {integrity: sha512-0f/spw0PfBMZBNqtKe5FLzBDGo0SKZKvMl5PHYQr3+eiSscfJ96XEknCe+JoOayybWUFQbcJTrk946i3j9uYZA==}
/@esbuild/linux-riscv64@0.18.20:
resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==}
engines: {node: '>=12'}
cpu: [riscv64]
os: [linux]
@ -594,8 +588,8 @@ packages:
dev: true
optional: true
/@esbuild/linux-s390x@0.19.10:
resolution: {integrity: sha512-pZFe0OeskMHzHa9U38g+z8Yx5FNCLFtUnJtQMpwhS+r4S566aK2ci3t4NCP4tjt6d5j5uo4h7tExZMjeKoehAA==}
/@esbuild/linux-s390x@0.18.20:
resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==}
engines: {node: '>=12'}
cpu: [s390x]
os: [linux]
@ -603,8 +597,8 @@ packages:
dev: true
optional: true
/@esbuild/linux-x64@0.19.10:
resolution: {integrity: sha512-SpYNEqg/6pZYoc+1zLCjVOYvxfZVZj6w0KROZ3Fje/QrM3nfvT2llI+wmKSrWuX6wmZeTapbarvuNNK/qepSgA==}
/@esbuild/linux-x64@0.18.20:
resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==}
engines: {node: '>=12'}
cpu: [x64]
os: [linux]
@ -612,8 +606,8 @@ packages:
dev: true
optional: true
/@esbuild/netbsd-x64@0.19.10:
resolution: {integrity: sha512-ACbZ0vXy9zksNArWlk2c38NdKg25+L9pr/mVaj9SUq6lHZu/35nx2xnQVRGLrC1KKQqJKRIB0q8GspiHI3J80Q==}
/@esbuild/netbsd-x64@0.18.20:
resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==}
engines: {node: '>=12'}
cpu: [x64]
os: [netbsd]
@ -621,8 +615,8 @@ packages:
dev: true
optional: true
/@esbuild/openbsd-x64@0.19.10:
resolution: {integrity: sha512-PxcgvjdSjtgPMiPQrM3pwSaG4kGphP+bLSb+cihuP0LYdZv1epbAIecHVl5sD3npkfYBZ0ZnOjR878I7MdJDFg==}
/@esbuild/openbsd-x64@0.18.20:
resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==}
engines: {node: '>=12'}
cpu: [x64]
os: [openbsd]
@ -630,8 +624,8 @@ packages:
dev: true
optional: true
/@esbuild/sunos-x64@0.19.10:
resolution: {integrity: sha512-ZkIOtrRL8SEJjr+VHjmW0znkPs+oJXhlJbNwfI37rvgeMtk3sxOQevXPXjmAPZPigVTncvFqLMd+uV0IBSEzqA==}
/@esbuild/sunos-x64@0.18.20:
resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [sunos]
@ -639,8 +633,8 @@ packages:
dev: true
optional: true
/@esbuild/win32-arm64@0.19.10:
resolution: {integrity: sha512-+Sa4oTDbpBfGpl3Hn3XiUe4f8TU2JF7aX8cOfqFYMMjXp6ma6NJDztl5FDG8Ezx0OjwGikIHw+iA54YLDNNVfw==}
/@esbuild/win32-arm64@0.18.20:
resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==}
engines: {node: '>=12'}
cpu: [arm64]
os: [win32]
@ -648,8 +642,8 @@ packages:
dev: true
optional: true
/@esbuild/win32-ia32@0.19.10:
resolution: {integrity: sha512-EOGVLK1oWMBXgfttJdPHDTiivYSjX6jDNaATeNOaCOFEVcfMjtbx7WVQwPSE1eIfCp/CaSF2nSrDtzc4I9f8TQ==}
/@esbuild/win32-ia32@0.18.20:
resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==}
engines: {node: '>=12'}
cpu: [ia32]
os: [win32]
@ -657,8 +651,8 @@ packages:
dev: true
optional: true
/@esbuild/win32-x64@0.19.10:
resolution: {integrity: sha512-whqLG6Sc70AbU73fFYvuYzaE4MNMBIlR1Y/IrUeOXFrWHxBEjjbZaQ3IXIQS8wJdAzue2GwYZCjOrgrU1oUHoA==}
/@esbuild/win32-x64@0.18.20:
resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [win32]
@ -1799,110 +1793,6 @@ packages:
engines: {node: '>=14.0.0'}
dev: false
/@rollup/rollup-android-arm-eabi@4.9.1:
resolution: {integrity: sha512-6vMdBZqtq1dVQ4CWdhFwhKZL6E4L1dV6jUjuBvsavvNJSppzi6dLBbuV+3+IyUREaj9ZFvQefnQm28v4OCXlig==}
cpu: [arm]
os: [android]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-android-arm64@4.9.1:
resolution: {integrity: sha512-Jto9Fl3YQ9OLsTDWtLFPtaIMSL2kwGyGoVCmPC8Gxvym9TCZm4Sie+cVeblPO66YZsYH8MhBKDMGZ2NDxuk/XQ==}
cpu: [arm64]
os: [android]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-darwin-arm64@4.9.1:
resolution: {integrity: sha512-LtYcLNM+bhsaKAIGwVkh5IOWhaZhjTfNOkGzGqdHvhiCUVuJDalvDxEdSnhFzAn+g23wgsycmZk1vbnaibZwwA==}
cpu: [arm64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-darwin-x64@4.9.1:
resolution: {integrity: sha512-KyP/byeXu9V+etKO6Lw3E4tW4QdcnzDG/ake031mg42lob5tN+5qfr+lkcT/SGZaH2PdW4Z1NX9GHEkZ8xV7og==}
cpu: [x64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-linux-arm-gnueabihf@4.9.1:
resolution: {integrity: sha512-Yqz/Doumf3QTKplwGNrCHe/B2p9xqDghBZSlAY0/hU6ikuDVQuOUIpDP/YcmoT+447tsZTmirmjgG3znvSCR0Q==}
cpu: [arm]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-linux-arm64-gnu@4.9.1:
resolution: {integrity: sha512-u3XkZVvxcvlAOlQJ3UsD1rFvLWqu4Ef/Ggl40WAVCuogf4S1nJPHh5RTgqYFpCOvuGJ7H5yGHabjFKEZGExk5Q==}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-linux-arm64-musl@4.9.1:
resolution: {integrity: sha512-0XSYN/rfWShW+i+qjZ0phc6vZ7UWI8XWNz4E/l+6edFt+FxoEghrJHjX1EY/kcUGCnZzYYRCl31SNdfOi450Aw==}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-linux-riscv64-gnu@4.9.1:
resolution: {integrity: sha512-LmYIO65oZVfFt9t6cpYkbC4d5lKHLYv5B4CSHRpnANq0VZUQXGcCPXHzbCXCz4RQnx7jvlYB1ISVNCE/omz5cw==}
cpu: [riscv64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-linux-x64-gnu@4.9.1:
resolution: {integrity: sha512-kr8rEPQ6ns/Lmr/hiw8sEVj9aa07gh1/tQF2Y5HrNCCEPiCBGnBUt9tVusrcBBiJfIt1yNaXN6r1CCmpbFEDpg==}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-linux-x64-musl@4.9.1:
resolution: {integrity: sha512-t4QSR7gN+OEZLG0MiCgPqMWZGwmeHhsM4AkegJ0Kiy6TnJ9vZ8dEIwHw1LcZKhbHxTY32hp9eVCMdR3/I8MGRw==}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-win32-arm64-msvc@4.9.1:
resolution: {integrity: sha512-7XI4ZCBN34cb+BH557FJPmh0kmNz2c25SCQeT9OiFWEgf8+dL6ZwJ8f9RnUIit+j01u07Yvrsuu1rZGxJCc51g==}
cpu: [arm64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-win32-ia32-msvc@4.9.1:
resolution: {integrity: sha512-yE5c2j1lSWOH5jp+Q0qNL3Mdhr8WuqCNVjc6BxbVfS5cAS6zRmdiw7ktb8GNpDCEUJphILY6KACoFoRtKoqNQg==}
cpu: [ia32]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-win32-x64-msvc@4.9.1:
resolution: {integrity: sha512-PyJsSsafjmIhVgaI1Zdj7m8BB8mMckFah/xbpplObyHfiXzKcI5UOUXRyOdHW7nz4DpMCuzLnF7v5IWHenCwYA==}
cpu: [x64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@scure/base@1.1.1:
resolution: {integrity: sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==}
dev: false
@ -2803,13 +2693,13 @@ packages:
react: 18.2.0
dev: false
/@vitejs/plugin-react-swc@3.5.0(vite@5.0.10):
/@vitejs/plugin-react-swc@3.5.0(vite@4.5.1):
resolution: {integrity: sha512-1PrOvAaDpqlCV+Up8RkAh9qaiUjoDUcjtttyhXDKw53XA6Ve16SOp6cCOpRs8Dj8DqUQs6eTW5YkLcLJjrXAig==}
peerDependencies:
vite: ^4 || ^5
dependencies:
'@swc/core': 1.3.101
vite: 5.0.10(@types/node@20.10.5)
vite: 4.5.1(@types/node@20.10.5)
transitivePeerDependencies:
- '@swc/helpers'
dev: true
@ -3496,35 +3386,34 @@ packages:
ext: 1.7.0
dev: false
/esbuild@0.19.10:
resolution: {integrity: sha512-S1Y27QGt/snkNYrRcswgRFqZjaTG5a5xM3EQo97uNBnH505pdzSNe/HLBq1v0RO7iK/ngdbhJB6mDAp0OK+iUA==}
/esbuild@0.18.20:
resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==}
engines: {node: '>=12'}
hasBin: true
requiresBuild: true
optionalDependencies:
'@esbuild/aix-ppc64': 0.19.10
'@esbuild/android-arm': 0.19.10
'@esbuild/android-arm64': 0.19.10
'@esbuild/android-x64': 0.19.10
'@esbuild/darwin-arm64': 0.19.10
'@esbuild/darwin-x64': 0.19.10
'@esbuild/freebsd-arm64': 0.19.10
'@esbuild/freebsd-x64': 0.19.10
'@esbuild/linux-arm': 0.19.10
'@esbuild/linux-arm64': 0.19.10
'@esbuild/linux-ia32': 0.19.10
'@esbuild/linux-loong64': 0.19.10
'@esbuild/linux-mips64el': 0.19.10
'@esbuild/linux-ppc64': 0.19.10
'@esbuild/linux-riscv64': 0.19.10
'@esbuild/linux-s390x': 0.19.10
'@esbuild/linux-x64': 0.19.10
'@esbuild/netbsd-x64': 0.19.10
'@esbuild/openbsd-x64': 0.19.10
'@esbuild/sunos-x64': 0.19.10
'@esbuild/win32-arm64': 0.19.10
'@esbuild/win32-ia32': 0.19.10
'@esbuild/win32-x64': 0.19.10
'@esbuild/android-arm': 0.18.20
'@esbuild/android-arm64': 0.18.20
'@esbuild/android-x64': 0.18.20
'@esbuild/darwin-arm64': 0.18.20
'@esbuild/darwin-x64': 0.18.20
'@esbuild/freebsd-arm64': 0.18.20
'@esbuild/freebsd-x64': 0.18.20
'@esbuild/linux-arm': 0.18.20
'@esbuild/linux-arm64': 0.18.20
'@esbuild/linux-ia32': 0.18.20
'@esbuild/linux-loong64': 0.18.20
'@esbuild/linux-mips64el': 0.18.20
'@esbuild/linux-ppc64': 0.18.20
'@esbuild/linux-riscv64': 0.18.20
'@esbuild/linux-s390x': 0.18.20
'@esbuild/linux-x64': 0.18.20
'@esbuild/netbsd-x64': 0.18.20
'@esbuild/openbsd-x64': 0.18.20
'@esbuild/sunos-x64': 0.18.20
'@esbuild/win32-arm64': 0.18.20
'@esbuild/win32-ia32': 0.18.20
'@esbuild/win32-x64': 0.18.20
dev: true
/escalade@3.1.1:
@ -5446,24 +5335,11 @@ packages:
glob: 7.2.3
dev: true
/rollup@4.9.1:
resolution: {integrity: sha512-pgPO9DWzLoW/vIhlSoDByCzcpX92bKEorbgXuZrqxByte3JFk2xSW2JEeAcyLc9Ru9pqcNNW+Ob7ntsk2oT/Xw==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
/rollup@3.29.4:
resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==}
engines: {node: '>=14.18.0', npm: '>=8.0.0'}
hasBin: true
optionalDependencies:
'@rollup/rollup-android-arm-eabi': 4.9.1
'@rollup/rollup-android-arm64': 4.9.1
'@rollup/rollup-darwin-arm64': 4.9.1
'@rollup/rollup-darwin-x64': 4.9.1
'@rollup/rollup-linux-arm-gnueabihf': 4.9.1
'@rollup/rollup-linux-arm64-gnu': 4.9.1
'@rollup/rollup-linux-arm64-musl': 4.9.1
'@rollup/rollup-linux-riscv64-gnu': 4.9.1
'@rollup/rollup-linux-x64-gnu': 4.9.1
'@rollup/rollup-linux-x64-musl': 4.9.1
'@rollup/rollup-win32-arm64-msvc': 4.9.1
'@rollup/rollup-win32-ia32-msvc': 4.9.1
'@rollup/rollup-win32-x64-msvc': 4.9.1
fsevents: 2.3.3
dev: true
@ -5593,6 +5469,11 @@ packages:
is-fullwidth-code-point: 5.0.0
dev: true
/smol-toml@1.1.3:
resolution: {integrity: sha512-qTyy6Owjho1ISBmxj4HdrFWB2kMQ5RczU6J04OqslSfdSH656OIHuomHS4ZDvhwm37nig/uXyiTMJxlC9zIVfw==}
engines: {node: '>= 18', pnpm: '>= 8'}
dev: false
/sonner@1.2.4(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-WGLP2QQnomgewaCTsK7YWiLcy5n1Yj83vsL5cP4zHMmpSkmFsCYTpQKhlXJrPE5kzjwbqCkCFXcOpbKc4vaUaA==}
peerDependencies:
@ -6053,7 +5934,7 @@ packages:
react-dom: 18.2.0(react@18.2.0)
dev: false
/vite-tsconfig-paths@4.2.2(typescript@5.3.3)(vite@5.0.10):
/vite-tsconfig-paths@4.2.2(typescript@5.3.3)(vite@4.5.1):
resolution: {integrity: sha512-dq0FjyxHHDnp0uS3P12WEOX2W7NeuLzX9AWP38D7Zw2CTbFErapwQVlCiT5DMJcVWKQ1MMdTe92PZl/rBQ7qcw==}
peerDependencies:
vite: '*'
@ -6064,18 +5945,18 @@ packages:
debug: 4.3.4
globrex: 0.1.2
tsconfck: 2.1.2(typescript@5.3.3)
vite: 5.0.10(@types/node@20.10.5)
vite: 4.5.1(@types/node@20.10.5)
transitivePeerDependencies:
- supports-color
- typescript
dev: true
/vite@5.0.10(@types/node@20.10.5):
resolution: {integrity: sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw==}
engines: {node: ^18.0.0 || >=20.0.0}
/vite@4.5.1(@types/node@20.10.5):
resolution: {integrity: sha512-AXXFaAJ8yebyqzoNB9fu2pHoo/nWX+xZlaRwoeYUxEqBO+Zj4msE5G+BhGBll9lYEKv9Hfks52PAF2X7qDYXQA==}
engines: {node: ^14.18.0 || >=16.0.0}
hasBin: true
peerDependencies:
'@types/node': ^18.0.0 || >=20.0.0
'@types/node': '>= 14'
less: '*'
lightningcss: ^1.21.0
sass: '*'
@ -6099,9 +5980,9 @@ packages:
optional: true
dependencies:
'@types/node': 20.10.5
esbuild: 0.19.10
esbuild: 0.18.20
postcss: 8.4.32
rollup: 4.9.1
rollup: 3.29.4
optionalDependencies:
fsevents: 2.3.3
dev: true

View File

@ -1,70 +1,53 @@
# Nostr-rs-relay configuration
[info]
# The advertised URL for the Nostr websocket.
relay_url = "<url>"
# Relay information for clients. Put your unique server name here.
name = "depot"
# Description
description = "Nostr Relay inside Lume. Powered by nostr-rs-relay"
# Administrative contact pubkey (32-byte hex, not npub)
pubkey = "<pubkey>"
# Administrative contact URI
pubkey = ""
favicon = "favicon.ico"
relay_icon = "https://example.test/img.png"
#contact = "mailto:contact@example.com"
# Favicon location. Relative to the current directory. Assumes an
# ICO format.
#favicon = "favicon.ico"
# URL of Relay's icon.
#relay_icon = "https://example.test/img.png"
[diagnostics]
# Enable tokio tracing (for use with tokio-console)
#tracing = false
[database]
# Database engine (sqlite/postgres). Defaults to sqlite.
# Support for postgres is currently experimental.
engine = "sqlite"
# Directory for SQLite files. Defaults to the current directory. Can
# also be specified (and overriden) with the "--db dirname" command
# line option.
data_directory = "."
# Use an in-memory database instead of 'nostr.db'.
# Requires sqlite engine.
# Caution; this will not survive a process restart!
#in_memory = false
# Database connection pool settings for subscribers:
# Minimum number of SQLite reader connections
#min_conn = 0
# Maximum number of SQLite reader connections. Recommend setting this
# to approx the number of cores.
max_conn = 8
# Database connection string. Required for postgres; not used for
# sqlite.
#connection = "postgresql://postgres:nostr@localhost:7500/nostr"
# Optional database connection string for writing. Use this for
# postgres clusters where you want to separate reads and writes to
# different nodes. Ignore for single-database instances.
#connection_write = "postgresql://postgres:nostr@localhost:7500/nostr"
min_conn = 0
[logging]
# Directory to store log files. Log files roll over daily.
#folder_path = "./log"
#file_prefix = "nostr-relay"
[network]
address = "0.0.0.0"
port = 6090
#remote_ip_header = "x-forwarded-for"
#remote_ip_header = "cf-connecting-ip"
#ping_interval = 300
[options]
reject_future_seconds = 1800
[limits]
messages_per_sec = 10
subscriptions_per_min = 10
limit_scrapers = false
[authorization]
pubkey_whitelist = []
nip42_auth = true
nip42_dms = true
[verified_users]
mode = "passive"
#domain_blacklist = ["wellorder.net"]
#domain_whitelist = ["example.com"]
verify_expiration = "1 week"
#verify_update_frequency = "24 hours"
max_consecutive_failures = 3
[grpc]
# gRPC interfaces for externalized decisions and other extensions to
# functionality.
@ -80,122 +63,6 @@ max_conn = 8
# This is reflected in the relay information document.
# restricts_write = true
[network]
# Bind to this network address
address = "0.0.0.0"
# Listen on this port
port = 6090
# If present, read this HTTP header for logging client IP addresses.
# Examples for common proxies, cloudflare:
#remote_ip_header = "x-forwarded-for"
#remote_ip_header = "cf-connecting-ip"
# Websocket ping interval in seconds, defaults to 5 minutes
#ping_interval = 300
[options]
# Reject events that have timestamps greater than this many seconds in
# the future. Recommended to reject anything greater than 30 minutes
# from the current time, but the default is to allow any date.
reject_future_seconds = 1800
[limits]
# Limit events created per second, averaged over one minute. Must be
# an integer. If not set (or set to 0), there is no limit. Note:
# this is for the server as a whole, not per-connection.
#
# Limiting event creation is highly recommended if your relay is
# public!
#
messages_per_sec = 10
# Limit client subscriptions created, averaged over one minute. Must
# be an integer. If not set (or set to 0), defaults to unlimited.
# Strongly recommended to set this to a low value such as 10 to ensure
# fair service.
subscriptions_per_min = 10
# UNIMPLEMENTED...
# Limit how many concurrent database connections a client can have.
# This prevents a single client from starting too many expensive
# database queries. Must be an integer. If not set (or set to 0),
# defaults to unlimited (subject to subscription limits).
#db_conns_per_client = 0
# Limit blocking threads used for database connections. Defaults to 16.
#max_blocking_threads = 16
# Limit the maximum size of an EVENT message. Defaults to 128 KB.
# Set to 0 for unlimited.
#max_event_bytes = 131072
# Maximum WebSocket message in bytes. Defaults to 128 KB.
#max_ws_message_bytes = 131072
# Maximum WebSocket frame size in bytes. Defaults to 128 KB.
#max_ws_frame_bytes = 131072
# Broadcast buffer size, in number of events. This prevents slow
# readers from consuming memory.
#broadcast_buffer = 16384
# Event persistence buffer size, in number of events. This provides
# backpressure to senders if writes are slow.
#event_persist_buffer = 4096
# Event kind blacklist. Events with these kinds will be discarded.
#event_kind_blacklist = [
# 70202,
#]
# Event kind allowlist. Events other than these kinds will be discarded.
#event_kind_allowlist = [
# 0, 1, 2, 3, 7, 40, 41, 42, 43, 44, 30023,
#]
# Rejects imprecise requests (kind only and author only etc)
# This is a temperary measure to improve the adoption of outbox model
# Its recommended to have this enabled
limit_scrapers = false
[authorization]
# Pubkey addresses in this array are whitelisted for event publishing.
# Only valid events by these authors will be accepted, if the variable
# is set.
pubkey_whitelist = []
# Enable NIP-42 authentication
nip42_auth = true
# Send DMs (kind 4 and 44) and gift wraps (kind 1059) only to their authenticated recipients
nip42_dms = true
[verified_users]
# NIP-05 verification of users. Can be "enabled" to require NIP-05
# metadata for event authors, "passive" to perform validation but
# never block publishing, or "disabled" to do nothing.
mode = "passive"
# Domain names that will be prevented from publishing events.
#domain_blacklist = ["wellorder.net"]
# Domain names that are allowed to publish events. If defined, only
# events NIP-05 verified authors at these domains are persisted.
#domain_whitelist = ["example.com"]
# Consider an pubkey "verified" if we have a successful validation
# from the NIP-05 domain within this amount of time. Note, if the
# domain provides a successful response that omits the account,
# verification is immediately revoked.
verify_expiration = "1 week"
# How long to wait between verification attempts for a specific author.
#verify_update_frequency = "24 hours"
# How many consecutive failed checks before we give up on verifying
# this author.
max_consecutive_failures = 3
[pay_to_relay]
# Enable pay to relay
#enabled = false

View File

@ -24,7 +24,9 @@
"$PICTURE/*",
"$PUBLIC/*",
"$VIDEO/*",
"$RESOURCE/*"
"$RESOURCE",
"$RESOURCE/*",
"$RESOURCE/**"
]
},
"http": {
@ -54,7 +56,7 @@
"depends": []
},
"externalBin": ["bin/depot"],
"resources": ["resources/config.toml"],
"resources": ["resources/*"],
"icon": [
"icons/32x32.png",
"icons/128x128.png",

View File

@ -1,5 +1,4 @@
import { fetch } from '@tauri-apps/plugin-http';
import { nip19 } from 'nostr-tools';
import { RouterProvider, createBrowserRouter, defer, redirect } from 'react-router-dom';
import { ErrorScreen } from '@app/error';
import { useArk } from '@libs/ark';
@ -13,17 +12,6 @@ import { SettingsLayout } from '@shared/layouts/settings';
export default function App() {
const ark = useArk();
const relayLoader = async ({ params }) => {
return defer({
relay: fetch(`https://${params.url}`, {
method: 'GET',
headers: {
Accept: 'application/nostr+json',
},
}).then((res) => res.json()),
});
};
const router = createBrowserRouter([
{
element: <AppLayout platform={ark.platform} />,
@ -44,21 +32,6 @@ export default function App() {
return { Component: HomeScreen };
},
},
{
path: ':address',
loader: ({ params }) => {
const address = params.address;
const decode = nip19.decode(address);
if (decode.type === 'npub') return redirect(`/users/${decode.data}`);
if (decode.type === 'nprofile')
return redirect(`/users/${decode.data.pubkey}`);
if (decode.type === 'note') return redirect(`/events/${decode.data}`);
if (decode.type === 'nrelay') return redirect(`/relays/${decode.data}`);
if (decode.type === 'nevent')
return redirect(`/relays/${decode.data.id}`);
return null;
},
},
{
path: 'nwc',
async lazy() {
@ -75,7 +48,16 @@ export default function App() {
},
{
path: 'relays/:url',
loader: relayLoader,
loader: async ({ params }) => {
return defer({
relay: fetch(`https://${params.url}`, {
method: 'GET',
headers: {
Accept: 'application/nostr+json',
},
}).then((res) => res.json()),
});
},
async lazy() {
const { RelayScreen } = await import('@app/relays/relay');
return { Component: RelayScreen };
@ -83,10 +65,29 @@ export default function App() {
},
{
path: 'depot',
async lazy() {
const { DepotScreen } = await import('@app/depot');
return { Component: DepotScreen };
},
children: [
{
index: true,
loader: () => {
const depot = ark.checkDepot();
if (!depot) return redirect('/depot/onboarding/');
return null;
},
async lazy() {
const { DepotScreen } = await import('@app/depot');
return { Component: DepotScreen };
},
},
{
path: 'onboarding',
async lazy() {
const { DepotOnboardingScreen } = await import(
'@app/depot/onboarding'
);
return { Component: DepotOnboardingScreen };
},
},
],
},
{
path: 'new',

View File

@ -73,7 +73,7 @@ export function CreateAccountScreen() {
await ark.createEvent({
kind: NDKKind.RelayList,
tags: [ark.relays],
tags: ark.relays.map((item) => ['r', item, '']),
});
setKeys({ npub: userNpub, nsec: userNsec });

View File

@ -1,149 +1,96 @@
import { useEffect, useState } from 'react';
import { toast } from 'sonner';
import { useArk } from '@libs/ark';
import { LoaderIcon } from '@shared/icons';
import { delay } from '@utils/delay';
export function DepotScreen() {
const ark = useArk();
const [status, setStatus] = useState(false);
const [loading, setLoading] = useState(false);
const launch = async () => {
try {
setLoading(true);
await ark.launchDepot();
await ark.createSetting('depot', '1');
await delay(2000); // delay 2s to make sure depot is running
// default depot url: ws://localhost:6090
// #TODO: user can custom depot url
const connect = await ark.connectDepot();
if (connect) {
setStatus(true);
setLoading(false);
}
} catch (e) {
toast.error(e);
}
};
useEffect(() => {
const depotStatus = ark.checkDepot();
setStatus(depotStatus);
}, []);
return (
<div className="flex h-full w-full flex-col items-center justify-center">
{!status ? (
<div className="flex flex-col items-center gap-4">
<h1 className="mb-1 text-2xl font-semibold text-neutral-400 dark:text-neutral-600">
<span>Deploy Nostr Relay inside Lume</span>{' '}
<span className="text-neutral-900 dark:text-neutral-100">with Depot.</span>
</h1>
<button
type="button"
onClick={() => launch()}
className="inline-flex h-11 w-24 items-center justify-center rounded-lg bg-blue-500 font-medium text-white hover:bg-blue-600"
>
{loading ? <LoaderIcon className="h-4 w-4 animate-spin" /> : 'Launch'}
</button>
</div>
) : (
<div className="mx-auto w-full max-w-md">
<div className="flex flex-col gap-10">
<div className="text-center">
<h1 className="mb-1 text-2xl font-semibold text-neutral-400 dark:text-neutral-600">
Your Depot is running
</h1>
<div className="flex items-center justify-center gap-2.5">
<span className="relative flex h-3 w-3">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-teal-400 opacity-75"></span>
<span className="relative inline-flex h-3 w-3 rounded-full bg-teal-500"></span>
</span>
<p className="font-medium">ws://localhost:6090</p>
</div>
<div className="px-16 py-14">
<div className="mx-auto w-full max-w-md">
<div className="flex flex-col gap-10">
<div className="text-center">
<h1 className="mb-1 text-2xl font-semibold text-neutral-400 dark:text-neutral-600">
Your Depot is running
</h1>
<div className="flex items-center justify-center gap-2.5">
<span className="relative flex h-3 w-3">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-teal-400 opacity-75"></span>
<span className="relative inline-flex h-3 w-3 rounded-full bg-teal-500"></span>
</span>
<p className="font-medium">ws://localhost:6090</p>
</div>
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between gap-6">
<div>
<h3 className="text-lg font-semibold">Backup</h3>
<p className="text-sm text-neutral-600 dark:text-neutral-400">
Sync all your data to Depot.
</p>
</div>
<button
type="button"
className="inline-flex h-9 w-20 shrink-0 items-center justify-center rounded-lg bg-neutral-200 font-medium hover:bg-blue-500 hover:text-white dark:bg-neutral-800"
>
Sync
</button>
</div>
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between gap-6">
<div>
<h3 className="text-lg font-semibold">Backup</h3>
<p className="text-sm text-neutral-600 dark:text-neutral-400">
Sync all your data to Depot.
</p>
</div>
<div className="flex items-center justify-between gap-6">
<div>
<h3 className="text-lg font-semibold">Expose</h3>
<p className="text-sm text-neutral-600 dark:text-neutral-400">
Help other users can see your depot on Internet. You also can do it by
yourself by using other service like ngrok or localtunnel.
</p>
</div>
<button
type="button"
className="inline-flex h-9 w-20 shrink-0 items-center justify-center rounded-lg bg-neutral-200 font-medium hover:bg-blue-500 hover:text-white dark:bg-neutral-800"
>
Start
</button>
<button
type="button"
className="inline-flex h-9 w-20 shrink-0 items-center justify-center rounded-lg bg-neutral-200 font-medium hover:bg-blue-500 hover:text-white dark:bg-neutral-800"
>
Sync
</button>
</div>
<div className="flex items-center justify-between gap-6">
<div>
<h3 className="text-lg font-semibold">Expose</h3>
<p className="text-sm text-neutral-600 dark:text-neutral-400">
Help other users can see your depot on Internet. You also can do it by
yourself by using other service like ngrok or localtunnel.
</p>
</div>
<div className="flex items-center justify-between gap-6">
<div>
<h3 className="text-lg font-semibold">Relay Hint</h3>
<p className="text-sm text-neutral-600 dark:text-neutral-400">
Instruct other Nostr client find your events in this depot.
</p>
</div>
<button
type="button"
className="inline-flex h-9 w-20 shrink-0 items-center justify-center rounded-lg bg-neutral-200 font-medium hover:bg-blue-500 hover:text-white dark:bg-neutral-800"
>
Add
</button>
<button
type="button"
className="inline-flex h-9 w-20 shrink-0 items-center justify-center rounded-lg bg-neutral-200 font-medium hover:bg-blue-500 hover:text-white dark:bg-neutral-800"
>
Start
</button>
</div>
<div className="flex items-center justify-between gap-6">
<div>
<h3 className="text-lg font-semibold">Relay Hint</h3>
<p className="text-sm text-neutral-600 dark:text-neutral-400">
Instruct other Nostr client find your events in this depot.
</p>
</div>
<div className="flex items-center justify-between gap-6">
<div>
<h3 className="text-lg font-semibold">Invite</h3>
<p className="text-sm text-neutral-600 dark:text-neutral-400">
By default, only you can write event to Depot, but you can invite
other user to your Depot.
</p>
</div>
<button
type="button"
className="inline-flex h-9 w-20 shrink-0 items-center justify-center rounded-lg bg-neutral-200 font-medium hover:bg-blue-500 hover:text-white dark:bg-neutral-800"
>
Invite
</button>
<button
type="button"
className="inline-flex h-9 w-20 shrink-0 items-center justify-center rounded-lg bg-neutral-200 font-medium hover:bg-blue-500 hover:text-white dark:bg-neutral-800"
>
Add
</button>
</div>
<div className="flex items-center justify-between gap-6">
<div>
<h3 className="text-lg font-semibold">Invite</h3>
<p className="text-sm text-neutral-600 dark:text-neutral-400">
By default, only you can write event to Depot, but you can invite other
user to your Depot.
</p>
</div>
<div className="flex items-center justify-between gap-6">
<div>
<h3 className="text-lg font-semibold">Customize</h3>
<p className="text-sm text-neutral-600 dark:text-neutral-400">
Depot also provide plenty config to customize your experiences.
</p>
</div>
<button
type="button"
className="inline-flex h-9 w-20 shrink-0 items-center justify-center rounded-lg bg-neutral-200 font-medium hover:bg-blue-500 hover:text-white dark:bg-neutral-800"
>
Config
</button>
<button
type="button"
className="inline-flex h-9 w-20 shrink-0 items-center justify-center rounded-lg bg-neutral-200 font-medium hover:bg-blue-500 hover:text-white dark:bg-neutral-800"
>
Invite
</button>
</div>
<div className="flex items-center justify-between gap-6">
<div>
<h3 className="text-lg font-semibold">Customize</h3>
<p className="text-sm text-neutral-600 dark:text-neutral-400">
Depot also provide plenty config to customize your experiences.
</p>
</div>
<button
type="button"
className="inline-flex h-9 w-20 shrink-0 items-center justify-center rounded-lg bg-neutral-200 font-medium hover:bg-blue-500 hover:text-white dark:bg-neutral-800"
>
Config
</button>
</div>
</div>
</div>
)}
</div>
</div>
);
}

View File

@ -0,0 +1,95 @@
import { resolveResource } from '@tauri-apps/api/path';
import { readTextFile, writeTextFile } from '@tauri-apps/plugin-fs';
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { parse, stringify } from 'smol-toml';
import { toast } from 'sonner';
import { useArk } from '@libs/ark';
import { LoaderIcon } from '@shared/icons';
import { delay } from '@utils/delay';
export function DepotOnboardingScreen() {
const ark = useArk();
const navigate = useNavigate();
const [loading, setLoading] = useState(false);
const launchDepot = async () => {
try {
setLoading(true);
// get default config
const defaultConfig = await resolveResource('resources/config.toml');
const config = await readTextFile(defaultConfig);
const parsedConfig = parse(config);
// add current user to whitelist
parsedConfig.authorization['pubkey_whitelist'].push(ark.account.pubkey);
// update new config
const newConfig = stringify(parsedConfig);
await writeTextFile(defaultConfig, newConfig);
// launch depot
await ark.launchDepot();
await ark.createSetting('depot', '1');
await delay(2000); // delay 2s to make sure depot is running
// default depot url: ws://localhost:6090
// #TODO: user can custom depot url
const connect = await ark.connectDepot();
if (connect) {
toast.success('Your Depot is successfully launch.');
setLoading(false);
navigate('/depot/');
}
} catch (e) {
toast.error(e);
}
};
return (
<div className="flex h-full w-full flex-col items-center justify-center gap-10">
<div className="flex flex-col items-center gap-8">
<div className="text-center">
<h1 className="mb-1 text-3xl font-semibold text-neutral-400 dark:text-neutral-600">
Run your Personal Nostr Relay inside Lume
</h1>
<h2 className="text-4xl font-semibold">Your Relay, Your Control.</h2>
</div>
<div className="rounded-xl bg-blue-100 p-1.5 dark:bg-blue-900">
<button
type="button"
onClick={launchDepot}
className="inline-flex h-11 w-36 transform items-center justify-center gap-2 rounded-lg bg-blue-500 font-medium text-white active:translate-y-1"
>
{loading ? (
<>
<LoaderIcon className="h-5 w-5 animate-spin" />
Launching...
</>
) : (
<>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className="h-5 w-5"
>
<path
fillRule="evenodd"
d="M12 2.25a.75.75 0 0 1 .75.75v9a.75.75 0 0 1-1.5 0V3a.75.75 0 0 1 .75-.75ZM6.166 5.106a.75.75 0 0 1 0 1.06 8.25 8.25 0 1 0 11.668 0 .75.75 0 1 1 1.06-1.06c3.808 3.807 3.808 9.98 0 13.788-3.807 3.808-9.98 3.808-13.788 0-3.808-3.807-3.808-9.98 0-13.788a.75.75 0 0 1 1.06 0Z"
clipRule="evenodd"
/>
</svg>
Launch
</>
)}
</button>
</div>
</div>
</div>
);
}

View File

@ -121,7 +121,7 @@ export function NewPostScreen() {
}, []);
return (
<div className="flex flex-1 flex-col gap-4">
<div className="flex h-[500px] flex-1 flex-col gap-4">
<div className="flex-1 overflow-y-auto">
<div ref={containerRef} style={{ height: `${height}px` }}>
<EditorContent

View File

@ -11,7 +11,7 @@ import NDK, {
NostrEvent,
} from '@nostr-dev-kit/ndk';
import { ndkAdapter } from '@nostr-fetch/adapter-ndk';
import { configDir, resolveResource } from '@tauri-apps/api/path';
import { appConfigDir, resolveResource } from '@tauri-apps/api/path';
import { invoke } from '@tauri-apps/api/primitives';
import { open } from '@tauri-apps/plugin-dialog';
import { readBinaryFile } from '@tauri-apps/plugin-fs';
@ -28,12 +28,12 @@ import {
import { nip19 } from 'nostr-tools';
import { NDKCacheAdapterTauri } from '@libs/cache';
import {
Account,
NDKCacheUser,
NDKCacheUserProfile,
NDKEventWithReplies,
NIP05,
Widget,
type Account,
type NDKCacheUser,
type NDKCacheUserProfile,
type NDKEventWithReplies,
type NIP05,
type WidgetProps,
} from '@utils/types';
export class Ark {
@ -69,7 +69,7 @@ export class Ark {
public async launchDepot() {
const configPath = await resolveResource('resources/config.toml');
const dataPath = await configDir();
const dataPath = await appConfigDir();
const command = Command.sidecar('bin/depot', ['-c', configPath, '-d', dataPath]);
this.#depot = await command.spawn();
@ -77,11 +77,29 @@ export class Ark {
public async connectDepot() {
if (!this.#depot) return;
return this.ndk.addExplicitRelay(
new NDKRelay('ws://localhost:6090'),
undefined,
true
);
// connect
this.ndk.addExplicitRelay(new NDKRelay('ws://localhost:6090'), undefined, true);
const relayEvent = await this.ndk.fetchEvent({
kinds: [NDKKind.RelayList],
authors: [this.account.pubkey],
});
if (!relayEvent) {
// create new relay list
return await this.createEvent({
kind: NDKKind.RelayList,
tags: [['r', 'ws://localhost:6090', '']],
});
}
// update old relay list
relayEvent.tags.push(['r', 'ws://localhost:6090', '']);
return await this.createEvent({
kind: NDKKind.RelayList,
tags: relayEvent.tags,
});
}
public checkDepot() {
@ -325,7 +343,7 @@ export class Ark {
}
public async getWidgets() {
const widgets: Array<Widget> = await this.#storage.select(
const widgets: Array<WidgetProps> = await this.#storage.select(
'SELECT * FROM widgets WHERE account_id = $1 ORDER BY created_at DESC;',
[this.account.id]
);
@ -339,7 +357,7 @@ export class Ark {
);
if (insert) {
const widgets: Array<Widget> = await this.#storage.select(
const widgets: Array<WidgetProps> = await this.#storage.select(
'SELECT * FROM widgets ORDER BY id DESC LIMIT 1;'
);
if (widgets.length < 1) console.error('get created widget failed');

View File

@ -18,7 +18,7 @@ export function ActiveAccount() {
encodeURIComponent(minidenticon(ark.account.pubkey, 90, 50));
return (
<div className="flex flex-col gap-1 rounded-lg bg-black/10 p-1 ring-1 ring-transparent hover:bg-black/20 hover:ring-blue-500 dark:bg-white/10 dark:hover:bg-white/20">
<div className="flex flex-col gap-1 rounded-xl bg-black/10 p-1 ring-1 ring-transparent hover:bg-black/20 hover:ring-blue-500 dark:bg-white/10 dark:hover:bg-white/20">
<Link to="/settings/" className="relative inline-block">
<Avatar.Root>
<Avatar.Image
@ -27,13 +27,13 @@ export function ActiveAccount() {
loading="lazy"
decoding="async"
style={{ contentVisibility: 'auto' }}
className="aspect-square h-auto w-full rounded-md object-cover"
className="aspect-square h-auto w-full rounded-lg object-cover"
/>
<Avatar.Fallback delayMs={150}>
<img
src={svgURI}
alt={ark.account.pubkey}
className="aspect-square h-auto w-full rounded-md bg-black dark:bg-white"
className="aspect-square h-auto w-full rounded-lg bg-black dark:bg-white"
/>
</Avatar.Fallback>
</Avatar.Root>

View File

@ -4,9 +4,7 @@ import { Navigation } from '@shared/navigation';
export function HomeLayout() {
return (
<div className="flex h-full w-full">
<div className="w-[68px] shrink-0">
<Navigation />
</div>
<Navigation />
<div className="min-h-0 flex-1 rounded-tl-lg bg-white shadow-[rgba(50,_50,_105,_0.15)_0px_2px_5px_0px,_rgba(0,_0,_0,_0.05)_0px_1px_1px_0px] dark:bg-black dark:shadow-[inset_0_0_0.5px_1px_hsla(0,0%,100%,0.075),0_0_0_1px_hsla(0,0%,0%,0.05),0_0.3px_0.4px_hsla(0,0%,0%,0.02),0_0.9px_1.5px_hsla(0,0%,0%,0.045),0_3.5px_6px_hsla(0,0%,0%,0.09)]">
<Outlet />
</div>

View File

@ -12,7 +12,7 @@ import {
export function Navigation() {
return (
<div className="flex h-full w-full flex-col justify-between p-3">
<div className="flex h-full w-20 shrink-0 flex-col justify-between px-4 py-3">
<div className="flex flex-1 flex-col gap-5">
<NavLink
to="/"
@ -33,8 +33,10 @@ export function Navigation() {
</div>
<div
className={twMerge(
'text-sm text-black dark:text-white',
isActive ? 'font-semibold' : 'font-medium'
'text-sm',
isActive
? 'font-semibold text-black dark:text-white'
: 'font-medium text-black/50 dark:text-white/50'
)}
>
Home
@ -61,8 +63,10 @@ export function Navigation() {
</div>
<div
className={twMerge(
'text-sm text-black dark:text-white',
isActive ? 'font-semibold' : 'font-medium'
'text-sm',
isActive
? 'font-semibold text-black dark:text-white'
: 'font-medium text-black/50 dark:text-white/50'
)}
>
Relays
@ -89,8 +93,10 @@ export function Navigation() {
</div>
<div
className={twMerge(
'text-sm text-black dark:text-white',
isActive ? 'font-semibold' : 'font-medium'
'text-sm',
isActive
? 'font-semibold text-black dark:text-white'
: 'font-medium text-black/50 dark:text-white/50'
)}
>
Depot
@ -117,8 +123,10 @@ export function Navigation() {
</div>
<div
className={twMerge(
'text-sm text-black dark:text-white',
isActive ? 'font-semibold' : 'font-medium'
'text-sm',
isActive
? 'font-semibold text-black dark:text-white'
: 'font-medium text-black/50 dark:text-white/50'
)}
>
Wallet