From 50f90ddcc26bd1ab76fae8c2c3adb451b3ac7367 Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Sun, 24 Sep 2023 07:55:27 +0700 Subject: [PATCH] wip --- package.json | 1 + pnpm-lock.yaml | 183 ++++++-- src/app.tsx | 539 ++++++++++++----------- src/app/browse/components/userDrawer.tsx | 27 +- src/app/browse/index.tsx | 13 +- src/app/browse/users.tsx | 19 +- src/libs/storage/instance.ts | 12 +- src/libs/storage/provider.tsx | 12 +- src/shared/icons/dots.tsx | 20 + src/shared/icons/index.ts | 1 + src/utils/checkActiveAccount.ts | 28 -- src/utils/transform.ts | 6 + 12 files changed, 510 insertions(+), 351 deletions(-) create mode 100644 src/shared/icons/dots.tsx delete mode 100644 src/utils/checkActiveAccount.ts diff --git a/package.json b/package.json index 5c05915b..5ffc56ba 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "react-dom": "^18.2.0", "react-hook-form": "^7.46.1", "react-markdown": "^8.0.7", + "react-organizational-chart": "^2.2.1", "react-player": "^2.13.0", "react-router-dom": "^6.16.0", "react-textarea-autosize": "^8.5.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7affeff8..18dafd98 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -107,6 +107,9 @@ dependencies: react-markdown: specifier: ^8.0.7 version: 8.0.7(@types/react@18.2.22)(react@18.2.0) + react-organizational-chart: + specifier: ^2.2.1 + version: 2.2.1(react-dom@18.2.0)(react@18.2.0) react-player: specifier: ^2.13.0 version: 2.13.0(react@18.2.0) @@ -254,7 +257,6 @@ packages: dependencies: '@babel/highlight': 7.22.20 chalk: 2.4.2 - dev: true /@babel/generator@7.17.7: resolution: {integrity: sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==} @@ -285,6 +287,13 @@ packages: '@babel/types': 7.22.19 dev: true + /@babel/helper-module-imports@7.22.15: + resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.22.19 + dev: false + /@babel/helper-split-export-declaration@7.22.6: resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} engines: {node: '>=6.9.0'} @@ -295,12 +304,10 @@ packages: /@babel/helper-string-parser@7.22.5: resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} engines: {node: '>=6.9.0'} - dev: true /@babel/helper-validator-identifier@7.22.20: resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} engines: {node: '>=6.9.0'} - dev: true /@babel/highlight@7.22.20: resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==} @@ -309,7 +316,6 @@ packages: '@babel/helper-validator-identifier': 7.22.20 chalk: 2.4.2 js-tokens: 4.0.0 - dev: true /@babel/parser@7.22.16: resolution: {integrity: sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==} @@ -367,7 +373,76 @@ packages: '@babel/helper-string-parser': 7.22.5 '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 - dev: true + + /@emotion/babel-plugin@11.11.0: + resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==} + dependencies: + '@babel/helper-module-imports': 7.22.15 + '@babel/runtime': 7.22.15 + '@emotion/hash': 0.9.1 + '@emotion/memoize': 0.8.1 + '@emotion/serialize': 1.1.2 + babel-plugin-macros: 3.1.0 + convert-source-map: 1.9.0 + escape-string-regexp: 4.0.0 + find-root: 1.1.0 + source-map: 0.5.7 + stylis: 4.2.0 + dev: false + + /@emotion/cache@11.11.0: + resolution: {integrity: sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==} + dependencies: + '@emotion/memoize': 0.8.1 + '@emotion/sheet': 1.2.2 + '@emotion/utils': 1.2.1 + '@emotion/weak-memoize': 0.3.1 + stylis: 4.2.0 + dev: false + + /@emotion/css@11.11.2: + resolution: {integrity: sha512-VJxe1ucoMYMS7DkiMdC2T7PWNbrEI0a39YRiyDvK2qq4lXwjRbVP/z4lpG+odCsRzadlR+1ywwrTzhdm5HNdew==} + dependencies: + '@emotion/babel-plugin': 11.11.0 + '@emotion/cache': 11.11.0 + '@emotion/serialize': 1.1.2 + '@emotion/sheet': 1.2.2 + '@emotion/utils': 1.2.1 + dev: false + + /@emotion/hash@0.9.1: + resolution: {integrity: sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==} + dev: false + + /@emotion/memoize@0.8.1: + resolution: {integrity: sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==} + dev: false + + /@emotion/serialize@1.1.2: + resolution: {integrity: sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==} + dependencies: + '@emotion/hash': 0.9.1 + '@emotion/memoize': 0.8.1 + '@emotion/unitless': 0.8.1 + '@emotion/utils': 1.2.1 + csstype: 3.1.2 + dev: false + + /@emotion/sheet@1.2.2: + resolution: {integrity: sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==} + dev: false + + /@emotion/unitless@0.8.1: + resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==} + dev: false + + /@emotion/utils@1.2.1: + resolution: {integrity: sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==} + dev: false + + /@emotion/weak-memoize@0.3.1: + resolution: {integrity: sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==} + dev: false /@esbuild/android-arm64@0.18.20: resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} @@ -2124,6 +2199,10 @@ packages: resolution: {integrity: sha512-sn7L+qQ6RLPdXRoiaE7bZ/Ek+o4uICma/lBFPyJEKDTPTBP1W8u0c4baj3EiS4DiqLs+Hk+KUGvMVJtAw3ePJg==} dev: false + /@types/parse-json@4.0.0: + resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} + dev: false + /@types/prop-types@15.7.6: resolution: {integrity: sha512-RK/kBbYOQQHLYj9Z95eh7S6t7gq4Ojt/NT8HTk8bWVhA5DaF+5SMnxHKkP4gPNN3wAZkKP+VjAf0ebtYzf+fxg==} @@ -2345,7 +2424,6 @@ packages: engines: {node: '>=4'} dependencies: color-convert: 1.9.3 - dev: true /ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} @@ -2499,6 +2577,15 @@ packages: dequal: 2.0.3 dev: true + /babel-plugin-macros@3.1.0: + resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} + engines: {node: '>=10', npm: '>=6'} + dependencies: + '@babel/runtime': 7.22.15 + cosmiconfig: 7.1.0 + resolve: 1.22.6 + dev: false + /bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} dev: false @@ -2555,7 +2642,6 @@ packages: /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - dev: true /camelcase-css@2.0.1: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} @@ -2582,7 +2668,6 @@ packages: ansi-styles: 3.2.1 escape-string-regexp: 1.0.5 supports-color: 5.5.0 - dev: true /chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} @@ -2640,7 +2725,6 @@ packages: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: color-name: 1.1.3 - dev: true /color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} @@ -2651,7 +2735,6 @@ packages: /color-name@1.1.3: resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: true /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} @@ -2679,6 +2762,21 @@ packages: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} dev: true + /convert-source-map@1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + dev: false + + /cosmiconfig@7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} + engines: {node: '>=10'} + dependencies: + '@types/parse-json': 4.0.0 + import-fresh: 3.3.0 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + dev: false + /crelt@1.0.6: resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} dev: false @@ -2893,6 +2991,12 @@ packages: engines: {node: '>=0.12'} dev: false + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: false + /es-abstract@1.22.2: resolution: {integrity: sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==} engines: {node: '>= 0.4'} @@ -3044,7 +3148,6 @@ packages: /escape-string-regexp@1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} - dev: true /escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} @@ -3297,6 +3400,10 @@ packages: to-regex-range: 5.0.1 dev: true + /find-root@1.1.0: + resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} + dev: false + /find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -3349,7 +3456,6 @@ packages: /function-bind@1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - dev: true /function.prototype.name@1.1.6: resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} @@ -3480,7 +3586,6 @@ packages: /has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} - dev: true /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} @@ -3515,7 +3620,6 @@ packages: engines: {node: '>= 0.4.0'} dependencies: function-bind: 1.1.1 - dev: true /hast-util-whitespace@2.0.1: resolution: {integrity: sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==} @@ -3570,7 +3674,6 @@ packages: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 - dev: true /imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} @@ -3615,6 +3718,10 @@ packages: is-typed-array: 1.1.12 dev: true + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: false + /is-async-function@2.0.0: resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} engines: {node: '>= 0.4'} @@ -3657,7 +3764,6 @@ packages: resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} dependencies: has: 1.0.3 - dev: true /is-date-object@1.0.5: resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} @@ -3858,6 +3964,10 @@ packages: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} dev: true + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: false + /json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} dev: true @@ -3922,7 +4032,6 @@ packages: /lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true /linkify-it@4.0.1: resolution: {integrity: sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==} @@ -4708,7 +4817,16 @@ packages: engines: {node: '>=6'} dependencies: callsites: 3.1.0 - dev: true + + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.22.13 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: false /parseley@0.12.1: resolution: {integrity: sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==} @@ -4739,12 +4857,10 @@ packages: /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - dev: true /peberminta@0.9.0: resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==} @@ -5166,6 +5282,18 @@ packages: - supports-color dev: false + /react-organizational-chart@2.2.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-JORmpLeYzCVtztdqCHsnKL8H3WiLRPHjohgh/PxQoszLuaQ+l3F8YefKSfpcBPZJhHwy3SlqjFjPC28a3Hh3QQ==} + engines: {node: '>=16', npm: '>=8'} + peerDependencies: + react: '>= 16.12.0' + react-dom: '>= 16.12.0' + dependencies: + '@emotion/css': 11.11.2 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /react-player@2.13.0(react@18.2.0): resolution: {integrity: sha512-gkY7ZdbVFztlKFFhCPcnDrFQm+L399b8fhWsKatZ+b2wpKJwfUHBXQFMRxqYQGT0ic1/wQ7D7EZEWy7ZBqk2pw==} peerDependencies: @@ -5356,7 +5484,6 @@ packages: /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - dev: true /resolve@1.22.6: resolution: {integrity: sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==} @@ -5365,7 +5492,6 @@ packages: is-core-module: 2.13.0 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - dev: true /resolve@2.0.0-next.4: resolution: {integrity: sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==} @@ -5526,7 +5652,6 @@ packages: /source-map@0.5.7: resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} engines: {node: '>=0.10.0'} - dev: true /space-separated-tokens@2.0.2: resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} @@ -5615,6 +5740,10 @@ packages: inline-style-parser: 0.1.1 dev: false + /stylis@4.2.0: + resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} + dev: false + /sucrase@3.34.0: resolution: {integrity: sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==} engines: {node: '>=8'} @@ -5634,7 +5763,6 @@ packages: engines: {node: '>=4'} dependencies: has-flag: 3.0.0 - dev: true /supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} @@ -5646,7 +5774,6 @@ packages: /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - dev: true /tailwind-merge@1.14.0: resolution: {integrity: sha512-3mFKyCo/MBcgyOTlrY8T7odzZFx+w+qKSMAmdFzRvqBfLlSigU6TZnlFHK0lkMwj9Bj8OYU+9yW9lmGuS0QEnQ==} @@ -5714,7 +5841,6 @@ packages: /to-fast-properties@2.0.0: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} - dev: true /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} @@ -6208,6 +6334,11 @@ packages: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: true + /yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + dev: false + /yaml@2.3.1: resolution: {integrity: sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==} engines: {node: '>= 14'} diff --git a/src/app.tsx b/src/app.tsx index 4eb26828..916f432c 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -7,6 +7,8 @@ import { OnboardingScreen } from '@app/auth/onboarding'; import { BrowseScreen } from '@app/browse'; import { ErrorScreen } from '@app/error'; +import { useStorage } from '@libs/storage/provider'; + import { Frame } from '@shared/frame'; import { LoaderIcon } from '@shared/icons'; import { AppLayout } from '@shared/layouts/app'; @@ -14,275 +16,279 @@ import { AuthLayout } from '@shared/layouts/auth'; import { NoteLayout } from '@shared/layouts/note'; import { SettingsLayout } from '@shared/layouts/settings'; -import { checkActiveAccount } from '@utils/checkActiveAccount'; - import './index.css'; -async function Loader() { - try { - const account = await checkActiveAccount(); - - const stronghold = sessionStorage.getItem('stronghold'); - const privkey = JSON.parse(stronghold).state.privkey || null; - - const onboarding = localStorage.getItem('onboarding'); - const step = JSON.parse(onboarding).state.step || null; - - if (!account) { - return redirect('/auth/welcome'); - } else { - if (step) { - return redirect(step); - } - - if (!privkey) { - return redirect('/auth/unlock'); - } - } - - return null; - } catch (e) { - await message(e, { title: 'An unexpected error has occurred', type: 'error' }); - } -} - -const router = createBrowserRouter([ - { - path: '/', - element: , - errorElement: , - loader: Loader, - children: [ - { - path: '', - async lazy() { - const { SpaceScreen } = await import('@app/space'); - return { Component: SpaceScreen }; - }, - }, - { - path: 'browse', - element: , - errorElement: , - children: [ - { - path: '', - async lazy() { - const { BrowseUsersScreen } = await import('@app/browse/users'); - return { Component: BrowseUsersScreen }; - }, - }, - { - path: 'relays', - async lazy() { - const { BrowseRelaysScreen } = await import('@app/browse/relays'); - return { Component: BrowseRelaysScreen }; - }, - }, - ], - }, - { - path: 'users/:pubkey', - async lazy() { - const { UserScreen } = await import('@app/users'); - return { Component: UserScreen }; - }, - }, - { - path: 'chats/:pubkey', - async lazy() { - const { ChatScreen } = await import('@app/chats'); - return { Component: ChatScreen }; - }, - }, - { - path: 'notifications', - async lazy() { - const { NotificationScreen } = await import('@app/notifications'); - return { Component: NotificationScreen }; - }, - }, - { - path: 'nwc', - async lazy() { - const { NWCScreen } = await import('@app/nwc'); - return { Component: NWCScreen }; - }, - }, - ], - }, - { - path: '/notes', - element: , - errorElement: , - children: [ - { - path: 'text/:id', - async lazy() { - const { TextNoteScreen } = await import('@app/notes/text'); - return { Component: TextNoteScreen }; - }, - }, - { - path: 'article/:id', - async lazy() { - const { ArticleNoteScreen } = await import('@app/notes/article'); - return { Component: ArticleNoteScreen }; - }, - }, - ], - }, - { - path: '/splashscreen', - errorElement: , - async lazy() { - const { SplashScreen } = await import('@app/splash'); - return { Component: SplashScreen }; - }, - }, - { - path: '/auth', - element: , - errorElement: , - children: [ - { - path: 'welcome', - async lazy() { - const { WelcomeScreen } = await import('@app/auth/welcome'); - return { Component: WelcomeScreen }; - }, - }, - { - path: 'import', - element: , - errorElement: , - children: [ - { - path: '', - async lazy() { - const { ImportStep1Screen } = await import('@app/auth/import/step-1'); - return { Component: ImportStep1Screen }; - }, - }, - { - path: 'step-2', - async lazy() { - const { ImportStep2Screen } = await import('@app/auth/import/step-2'); - return { Component: ImportStep2Screen }; - }, - }, - { - path: 'step-3', - async lazy() { - const { ImportStep3Screen } = await import('@app/auth/import/step-3'); - return { Component: ImportStep3Screen }; - }, - }, - ], - }, - { - path: 'create', - element: , - errorElement: , - children: [ - { - path: '', - async lazy() { - const { CreateStep1Screen } = await import('@app/auth/create/step-1'); - return { Component: CreateStep1Screen }; - }, - }, - { - path: 'step-2', - async lazy() { - const { CreateStep2Screen } = await import('@app/auth/create/step-2'); - return { Component: CreateStep2Screen }; - }, - }, - { - path: 'step-3', - async lazy() { - const { CreateStep3Screen } = await import('@app/auth/create/step-3'); - return { Component: CreateStep3Screen }; - }, - }, - ], - }, - { - path: 'onboarding', - element: , - errorElement: , - children: [ - { - path: '', - async lazy() { - const { OnboardStep1Screen } = await import('@app/auth/onboarding/step-1'); - return { Component: OnboardStep1Screen }; - }, - }, - { - path: 'step-2', - async lazy() { - const { OnboardStep2Screen } = await import('@app/auth/onboarding/step-2'); - return { Component: OnboardStep2Screen }; - }, - }, - ], - }, - { - path: 'complete', - async lazy() { - const { CompleteScreen } = await import('@app/auth/complete'); - return { Component: CompleteScreen }; - }, - }, - { - path: 'unlock', - async lazy() { - const { UnlockScreen } = await import('@app/auth/unlock'); - return { Component: UnlockScreen }; - }, - }, - { - path: 'migrate', - async lazy() { - const { MigrateScreen } = await import('@app/auth/migrate'); - return { Component: MigrateScreen }; - }, - }, - { - path: 'reset', - async lazy() { - const { ResetScreen } = await import('@app/auth/reset'); - return { Component: ResetScreen }; - }, - }, - ], - }, - { - path: '/settings', - element: , - errorElement: , - children: [ - { - path: '', - async lazy() { - const { GeneralSettingsScreen } = await import('@app/settings/general'); - return { Component: GeneralSettingsScreen }; - }, - }, - { - path: 'backup', - async lazy() { - const { AccountSettingsScreen } = await import('@app/settings/account'); - return { Component: AccountSettingsScreen }; - }, - }, - ], - }, -]); - export default function App() { + const { db } = useStorage(); + + const accountLoader = async () => { + try { + const account = await db.checkAccount(); + + const stronghold = sessionStorage.getItem('stronghold'); + const privkey = JSON.parse(stronghold).state.privkey || null; + + const onboarding = localStorage.getItem('onboarding'); + const step = JSON.parse(onboarding).state.step || null; + + if (!account) { + return redirect('/auth/welcome'); + } else { + if (step) { + return redirect(step); + } + + if (!privkey) { + return redirect('/auth/unlock'); + } + } + + return null; + } catch (e) { + await message(e, { title: 'An unexpected error has occurred', type: 'error' }); + } + }; + + const router = createBrowserRouter([ + { + path: '/', + element: , + errorElement: , + loader: accountLoader, + children: [ + { + path: '', + async lazy() { + const { SpaceScreen } = await import('@app/space'); + return { Component: SpaceScreen }; + }, + }, + { + path: 'browse', + element: , + errorElement: , + children: [ + { + path: '', + async lazy() { + const { BrowseUsersScreen } = await import('@app/browse/users'); + return { Component: BrowseUsersScreen }; + }, + }, + { + path: 'relays', + async lazy() { + const { BrowseRelaysScreen } = await import('@app/browse/relays'); + return { Component: BrowseRelaysScreen }; + }, + }, + ], + }, + { + path: 'users/:pubkey', + async lazy() { + const { UserScreen } = await import('@app/users'); + return { Component: UserScreen }; + }, + }, + { + path: 'chats/:pubkey', + async lazy() { + const { ChatScreen } = await import('@app/chats'); + return { Component: ChatScreen }; + }, + }, + { + path: 'notifications', + async lazy() { + const { NotificationScreen } = await import('@app/notifications'); + return { Component: NotificationScreen }; + }, + }, + { + path: 'nwc', + async lazy() { + const { NWCScreen } = await import('@app/nwc'); + return { Component: NWCScreen }; + }, + }, + ], + }, + { + path: '/notes', + element: , + errorElement: , + children: [ + { + path: 'text/:id', + async lazy() { + const { TextNoteScreen } = await import('@app/notes/text'); + return { Component: TextNoteScreen }; + }, + }, + { + path: 'article/:id', + async lazy() { + const { ArticleNoteScreen } = await import('@app/notes/article'); + return { Component: ArticleNoteScreen }; + }, + }, + ], + }, + { + path: '/splashscreen', + errorElement: , + async lazy() { + const { SplashScreen } = await import('@app/splash'); + return { Component: SplashScreen }; + }, + }, + { + path: '/auth', + element: , + errorElement: , + children: [ + { + path: 'welcome', + async lazy() { + const { WelcomeScreen } = await import('@app/auth/welcome'); + return { Component: WelcomeScreen }; + }, + }, + { + path: 'import', + element: , + errorElement: , + children: [ + { + path: '', + async lazy() { + const { ImportStep1Screen } = await import('@app/auth/import/step-1'); + return { Component: ImportStep1Screen }; + }, + }, + { + path: 'step-2', + async lazy() { + const { ImportStep2Screen } = await import('@app/auth/import/step-2'); + return { Component: ImportStep2Screen }; + }, + }, + { + path: 'step-3', + async lazy() { + const { ImportStep3Screen } = await import('@app/auth/import/step-3'); + return { Component: ImportStep3Screen }; + }, + }, + ], + }, + { + path: 'create', + element: , + errorElement: , + children: [ + { + path: '', + async lazy() { + const { CreateStep1Screen } = await import('@app/auth/create/step-1'); + return { Component: CreateStep1Screen }; + }, + }, + { + path: 'step-2', + async lazy() { + const { CreateStep2Screen } = await import('@app/auth/create/step-2'); + return { Component: CreateStep2Screen }; + }, + }, + { + path: 'step-3', + async lazy() { + const { CreateStep3Screen } = await import('@app/auth/create/step-3'); + return { Component: CreateStep3Screen }; + }, + }, + ], + }, + { + path: 'onboarding', + element: , + errorElement: , + children: [ + { + path: '', + async lazy() { + const { OnboardStep1Screen } = await import( + '@app/auth/onboarding/step-1' + ); + return { Component: OnboardStep1Screen }; + }, + }, + { + path: 'step-2', + async lazy() { + const { OnboardStep2Screen } = await import( + '@app/auth/onboarding/step-2' + ); + return { Component: OnboardStep2Screen }; + }, + }, + ], + }, + { + path: 'complete', + async lazy() { + const { CompleteScreen } = await import('@app/auth/complete'); + return { Component: CompleteScreen }; + }, + }, + { + path: 'unlock', + async lazy() { + const { UnlockScreen } = await import('@app/auth/unlock'); + return { Component: UnlockScreen }; + }, + }, + { + path: 'migrate', + async lazy() { + const { MigrateScreen } = await import('@app/auth/migrate'); + return { Component: MigrateScreen }; + }, + }, + { + path: 'reset', + async lazy() { + const { ResetScreen } = await import('@app/auth/reset'); + return { Component: ResetScreen }; + }, + }, + ], + }, + { + path: '/settings', + element: , + errorElement: , + children: [ + { + path: '', + async lazy() { + const { GeneralSettingsScreen } = await import('@app/settings/general'); + return { Component: GeneralSettingsScreen }; + }, + }, + { + path: 'backup', + async lazy() { + const { AccountSettingsScreen } = await import('@app/settings/account'); + return { Component: AccountSettingsScreen }; + }, + }, + ], + }, + ]); + return ( } + future={{ v7_startTransition: true }} /> ); } diff --git a/src/app/browse/components/userDrawer.tsx b/src/app/browse/components/userDrawer.tsx index 63b685a0..9ad9d8ed 100644 --- a/src/app/browse/components/userDrawer.tsx +++ b/src/app/browse/components/userDrawer.tsx @@ -4,6 +4,7 @@ import { Link } from 'react-router-dom'; import { useStorage } from '@libs/storage/provider'; +import { PlusIcon } from '@shared/icons'; import { Image } from '@shared/image'; import { NIP05 } from '@shared/nip05'; import { TextNote } from '@shared/notes'; @@ -50,14 +51,26 @@ export const UserDrawer = memo(function UserDrawer({ pubkey }: { pubkey: string return ( - - - +
+ + + +
+
+ +
+
+
- -
+ +
{status === 'loading' ? (

Loading...

diff --git a/src/app/browse/index.tsx b/src/app/browse/index.tsx index ecad24dc..a98e4b50 100644 --- a/src/app/browse/index.tsx +++ b/src/app/browse/index.tsx @@ -1,12 +1,14 @@ import { NavLink, Outlet } from 'react-router-dom'; import { twMerge } from 'tailwind-merge'; +import { DotsPattern } from '@shared/icons'; + export function BrowseScreen() { return (
-
+
-
+
@@ -32,7 +34,12 @@ export function BrowseScreen() {
- +
+ +
+
+ +
); } diff --git a/src/app/browse/users.tsx b/src/app/browse/users.tsx index f8504477..d5e4d079 100644 --- a/src/app/browse/users.tsx +++ b/src/app/browse/users.tsx @@ -1,21 +1,24 @@ +import { useMemo } from 'react'; + import { UserDrawer } from '@app/browse/components/userDrawer'; import { useStorage } from '@libs/storage/provider'; import { User } from '@shared/user'; +import { getMultipleRandom } from '@utils/transform'; + export function BrowseUsersScreen() { const { db } = useStorage(); + const data = useMemo(() => getMultipleRandom(db.account.follows, 10), []); return ( -
-
- -
- {db.account.follows.map((user) => ( - - ))} -
+
+ +
+ {data.map((user) => ( + + ))}
); diff --git a/src/libs/storage/instance.ts b/src/libs/storage/instance.ts index 2b05fd9c..7fc8fbca 100644 --- a/src/libs/storage/instance.ts +++ b/src/libs/storage/instance.ts @@ -1,6 +1,5 @@ import { NDKEvent } from '@nostr-dev-kit/ndk'; import { BaseDirectory, removeFile } from '@tauri-apps/api/fs'; -import { Platform } from '@tauri-apps/api/os'; import Database from 'tauri-plugin-sql-api'; import { Stronghold } from 'tauri-plugin-stronghold-api'; @@ -11,13 +10,11 @@ import { Account, DBEvent, Relays, Widget } from '@utils/types'; export class LumeStorage { public db: Database; - public platform: Platform; public secureDB: Stronghold; public account: Account | null = null; - constructor(sqlite: Database, platform: Platform, stronghold?: Stronghold) { + constructor(sqlite: Database, stronghold?: Stronghold) { this.db = sqlite; - this.platform = platform ?? undefined; this.secureDB = stronghold ?? undefined; this.account = null; } @@ -59,6 +56,13 @@ export class LumeStorage { return await removeFile('lume.stronghold', { dir: BaseDirectory.AppConfig }); } + public async checkAccount() { + const result: Array = await this.db.select( + 'SELECT * FROM accounts WHERE is_active = 1;' + ); + return result.length > 0; + } + public async getActiveAccount() { const results: Array = await this.db.select( 'SELECT * FROM accounts WHERE is_active = "1" ORDER BY id DESC LIMIT 1;' diff --git a/src/libs/storage/provider.tsx b/src/libs/storage/provider.tsx index 73d02183..c9bb39a8 100644 --- a/src/libs/storage/provider.tsx +++ b/src/libs/storage/provider.tsx @@ -1,6 +1,4 @@ import { message } from '@tauri-apps/api/dialog'; -import { platform } from '@tauri-apps/api/os'; -import { appConfigDir } from '@tauri-apps/api/path'; import { PropsWithChildren, createContext, useContext, useEffect, useState } from 'react'; import Database from 'tauri-plugin-sql-api'; @@ -17,14 +15,10 @@ const StorageContext = createContext({ const StorageProvider = ({ children }: PropsWithChildren) => { const [db, setDB] = useState(undefined); - async function initLumeStorage() { + const initLumeStorage = async () => { try { - const dir = await appConfigDir(); const sqlite = await Database.load('sqlite:lume.db'); - const platformName = await platform(); - const lumeStorage = new LumeStorage(sqlite, platformName); - - console.log('App config dir: ', dir); + const lumeStorage = new LumeStorage(sqlite); if (!lumeStorage.account) await lumeStorage.getActiveAccount(); setDB(lumeStorage); @@ -34,7 +28,7 @@ const StorageProvider = ({ children }: PropsWithChildren) => { type: 'error', }); } - } + }; useEffect(() => { if (!db) initLumeStorage(); diff --git a/src/shared/icons/dots.tsx b/src/shared/icons/dots.tsx new file mode 100644 index 00000000..2b49a257 --- /dev/null +++ b/src/shared/icons/dots.tsx @@ -0,0 +1,20 @@ +import { SVGProps } from 'react'; + +export function DotsPattern(props: JSX.IntrinsicAttributes & SVGProps) { + return ( + + + + + + + ); +} diff --git a/src/shared/icons/index.ts b/src/shared/icons/index.ts index 144c1ab4..24e62684 100644 --- a/src/shared/icons/index.ts +++ b/src/shared/icons/index.ts @@ -65,3 +65,4 @@ export * from './alby'; export * from './stars'; export * from './nwc'; export * from './timeline'; +export * from './dots'; diff --git a/src/utils/checkActiveAccount.ts b/src/utils/checkActiveAccount.ts deleted file mode 100644 index f7ff0bbb..00000000 --- a/src/utils/checkActiveAccount.ts +++ /dev/null @@ -1,28 +0,0 @@ -import Database from 'tauri-plugin-sql-api'; - -import { Account } from '@utils/types'; - -async function connect(): Promise { - let db: null | Database = null; - - if (db) { - return db; - } - - try { - db = await Database.load('sqlite:lume.db'); - } catch (e) { - throw new Error('Failed to connect to database, error: ', e); - } - - return db; -} - -export async function checkActiveAccount() { - const db = await connect(); - const result: Array = await db.select( - 'SELECT * FROM accounts WHERE is_active = 1;' - ); - - return result.length > 0; -} diff --git a/src/utils/transform.ts b/src/utils/transform.ts index 74441dd9..704f97c9 100644 --- a/src/utils/transform.ts +++ b/src/utils/transform.ts @@ -24,3 +24,9 @@ export function getRepostID(tags: NDKTag[]) { return quoteID; } + +// get random n elements from array +export function getMultipleRandom(arr: string[], num: number) { + const shuffled = [...arr].sort(() => 0.5 - Math.random()); + return shuffled.slice(0, num); +}