From c50e507c140d4a4ba4c79ceca674686553c1c831 Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Sat, 22 Apr 2023 08:53:18 +0700 Subject: [PATCH 1/4] install vite --- next-env.d.ts | 5 - next.config.js | 28 - package.json | 11 +- pnpm-lock.yaml | 818 +++++++++++++++++---------- src/{assets/global.css => index.css} | 0 vite.config.ts | 8 + 6 files changed, 534 insertions(+), 336 deletions(-) delete mode 100644 next-env.d.ts delete mode 100644 next.config.js rename src/{assets/global.css => index.css} (100%) create mode 100644 vite.config.ts diff --git a/next-env.d.ts b/next-env.d.ts deleted file mode 100644 index 4f11a03d..00000000 --- a/next-env.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -/// -/// - -// NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/next.config.js b/next.config.js deleted file mode 100644 index 192e9f31..00000000 --- a/next.config.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @type {import('next').NextConfig} - */ - -const withBundleAnalyzer = require('@next/bundle-analyzer')({ - enabled: process.env.ANALYZE === 'true', -}); - -const nextConfig = withBundleAnalyzer({ - output: 'export', - swcMinify: false, - images: { - unoptimized: true, - }, - typescript: { - ignoreBuildErrors: true, - }, - experimental: { - appDir: true, - scrollRestoration: true, - }, - webpack: (config) => { - config.experiments = { ...config.experiments, topLevelAwait: true }; - return config; - }, -}); - -module.exports = nextConfig; diff --git a/package.json b/package.json index 0f365eb0..be1e1cc2 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,8 @@ "private": true, "version": "0.2.5", "scripts": { - "dev": "next dev -p 1420", - "build": "next build", + "dev": "vite", + "build": "vite build", "tauri": "tauri", "add-migrate": "cd src-tauri/ && sqlx migrate add", "prepare": "husky install" @@ -26,10 +26,8 @@ "@tauri-apps/api": "^1.2.0", "dayjs": "^1.11.7", "destr": "^1.2.2", - "framer-motion": "^9.1.7", "iconoir-react": "^6.6.0", "jotai": "^2.0.4", - "next": "13.3.1", "nostr-relaypool": "^0.5.18", "nostr-tools": "^1.10.0", "react": "^18.2.0", @@ -44,7 +42,6 @@ "unique-names-generator": "^4.7.1" }, "devDependencies": { - "@next/bundle-analyzer": "^13.3.0", "@tailwindcss/typography": "^0.5.9", "@tauri-apps/cli": "^1.2.3", "@trivago/prettier-plugin-sort-imports": "^4.1.1", @@ -53,6 +50,7 @@ "@types/react-dom": "^18.0.11", "@typescript-eslint/eslint-plugin": "^5.59.0", "@typescript-eslint/parser": "^5.59.0", + "@vitejs/plugin-react-swc": "^3.3.0", "autoprefixer": "^10.4.14", "cross-env": "^7.0.3", "csstype": "^3.1.2", @@ -70,6 +68,9 @@ "prop-types": "^15.8.1", "tailwindcss": "^3.3.1", "typescript": "^4.9.5", + "vite": "^4.3.1", + "vite-plugin-ssr": "^0.4.115", + "vite-tsconfig-paths": "^4.2.0", "ws": "^8.13.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 10b8155f..ee6fef5f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,7 +1,6 @@ lockfileVersion: 5.4 specifiers: - '@next/bundle-analyzer': ^13.3.0 '@radix-ui/react-alert-dialog': ^1.0.3 '@radix-ui/react-collapsible': ^1.0.2 '@radix-ui/react-dialog': ^1.0.3 @@ -20,6 +19,7 @@ specifiers: '@types/react-dom': ^18.0.11 '@typescript-eslint/eslint-plugin': ^5.59.0 '@typescript-eslint/parser': ^5.59.0 + '@vitejs/plugin-react-swc': ^3.3.0 autoprefixer: ^10.4.14 cross-env: ^7.0.3 csstype: ^3.1.2 @@ -31,12 +31,10 @@ specifiers: eslint-config-prettier: ^8.8.0 eslint-plugin-react: ^7.32.2 eslint-plugin-react-hooks: ^4.6.0 - framer-motion: ^9.1.7 husky: ^8.0.3 iconoir-react: ^6.6.0 jotai: ^2.0.4 lint-staged: ^13.2.1 - next: 13.3.1 nostr-relaypool: ^0.5.18 nostr-tools: ^1.10.0 postcss: ^8.4.23 @@ -55,6 +53,9 @@ specifiers: tauri-plugin-sql-api: github:tauri-apps/tauri-plugin-sql typescript: ^4.9.5 unique-names-generator: ^4.7.1 + vite: ^4.3.1 + vite-plugin-ssr: ^0.4.115 + vite-tsconfig-paths: ^4.2.0 ws: ^8.13.0 dependencies: @@ -70,10 +71,8 @@ dependencies: '@tauri-apps/api': 1.2.0 dayjs: 1.11.7 destr: 1.2.2 - framer-motion: 9.1.7_biqbaboplfbrettd7655fr4n2y iconoir-react: 6.6.0_react@18.2.0 jotai: 2.0.4_react@18.2.0 - next: 13.3.1_biqbaboplfbrettd7655fr4n2y nostr-relaypool: 0.5.18_ws@8.13.0 nostr-tools: 1.10.0 react: 18.2.0 @@ -88,7 +87,6 @@ dependencies: unique-names-generator: 4.7.1 devDependencies: - '@next/bundle-analyzer': 13.3.0 '@tailwindcss/typography': 0.5.9_tailwindcss@3.3.1 '@tauri-apps/cli': 1.2.3 '@trivago/prettier-plugin-sort-imports': 4.1.1_prettier@2.8.7 @@ -97,6 +95,7 @@ devDependencies: '@types/react-dom': 18.0.11 '@typescript-eslint/eslint-plugin': 5.59.0_fdxyi3g57a6lyb5rx36h2olw2q '@typescript-eslint/parser': 5.59.0_ze6bmax3gcsfve3yrzu6npguhe + '@vitejs/plugin-react-swc': 3.3.0_vite@4.3.1 autoprefixer: 10.4.14_postcss@8.4.23 cross-env: 7.0.3 csstype: 3.1.2 @@ -114,6 +113,9 @@ devDependencies: prop-types: 15.8.1 tailwindcss: 3.3.1_postcss@8.4.23 typescript: 4.9.5 + vite: 4.3.1_@types+node@18.15.13 + vite-plugin-ssr: 0.4.115_vite@4.3.1 + vite-tsconfig-paths: 4.2.0_mzhihm7zd2gyalpll4qoudvuha ws: 8.13.0 packages: @@ -252,19 +254,241 @@ packages: to-fast-properties: 2.0.0 dev: true - /@emotion/is-prop-valid/0.8.8: + /@brillout/import/0.2.3: resolution: - { integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA== } - requiresBuild: true + { integrity: sha512-1T8WlD75eeFSMrptGy8jiLHmfHgMmSjWvLOIUvHmSVZt+6k0eQqYUoK4KbmE4T9pVLIfxvZSOm2D68VEqKRHRw== } + dev: true + + /@brillout/json-serializer/0.5.3: + resolution: + { integrity: sha512-IxlOMD5gOM0WfFGdeR98jHKiC82Ad1tUnSjvLS5jnRkfMEKBI+YzHA32Umw8W3Ccp5N4fNEX229BW6RaRpxRWQ== } + dev: true + + /@brillout/vite-plugin-import-build/0.2.16: + resolution: + { integrity: sha512-3rbNIgOUIPf8JrV3lozG3lpIe+xnujUANpMaf9aPVGnZV5SVKOSrvLk83+2Y8/nhHgLYTBplNZTW3DTD6J29ag== } dependencies: - '@emotion/memoize': 0.7.4 - dev: false + '@brillout/import': 0.2.3 + dev: true + + /@esbuild/android-arm/0.17.17: + resolution: + { integrity: sha512-E6VAZwN7diCa3labs0GYvhEPL2M94WLF8A+czO8hfjREXxba8Ng7nM5VxV+9ihNXIY1iQO1XxUU4P7hbqbICxg== } + engines: { node: '>=12' } + cpu: [arm] + os: [android] + requiresBuild: true + dev: true optional: true - /@emotion/memoize/0.7.4: + /@esbuild/android-arm64/0.17.17: resolution: - { integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== } - dev: false + { integrity: sha512-jaJ5IlmaDLFPNttv0ofcwy/cfeY4bh/n705Tgh+eLObbGtQBK3EPAu+CzL95JVE4nFAliyrnEu0d32Q5foavqg== } + engines: { node: '>=12' } + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64/0.17.17: + resolution: + { integrity: sha512-446zpfJ3nioMC7ASvJB1pszHVskkw4u/9Eu8s5yvvsSDTzYh4p4ZIRj0DznSl3FBF0Z/mZfrKXTtt0QCoFmoHA== } + engines: { node: '>=12' } + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64/0.17.17: + resolution: + { integrity: sha512-m/gwyiBwH3jqfUabtq3GH31otL/0sE0l34XKpSIqR7NjQ/XHQ3lpmQHLHbG8AHTGCw8Ao059GvV08MS0bhFIJQ== } + engines: { node: '>=12' } + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64/0.17.17: + resolution: + { integrity: sha512-4utIrsX9IykrqYaXR8ob9Ha2hAY2qLc6ohJ8c0CN1DR8yWeMrTgYFjgdeQ9LIoTOfLetXjuCu5TRPHT9yKYJVg== } + engines: { node: '>=12' } + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64/0.17.17: + resolution: + { integrity: sha512-4PxjQII/9ppOrpEwzQ1b0pXCsFLqy77i0GaHodrmzH9zq2/NEhHMAMJkJ635Ns4fyJPFOlHMz4AsklIyRqFZWA== } + engines: { node: '>=12' } + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64/0.17.17: + resolution: + { integrity: sha512-lQRS+4sW5S3P1sv0z2Ym807qMDfkmdhUYX30GRBURtLTrJOPDpoU0kI6pVz1hz3U0+YQ0tXGS9YWveQjUewAJw== } + engines: { node: '>=12' } + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm/0.17.17: + resolution: + { integrity: sha512-biDs7bjGdOdcmIk6xU426VgdRUpGg39Yz6sT9Xp23aq+IEHDb/u5cbmu/pAANpDB4rZpY/2USPhCA+w9t3roQg== } + engines: { node: '>=12' } + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64/0.17.17: + resolution: + { integrity: sha512-2+pwLx0whKY1/Vqt8lyzStyda1v0qjJ5INWIe+d8+1onqQxHLLi3yr5bAa4gvbzhZqBztifYEu8hh1La5+7sUw== } + engines: { node: '>=12' } + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32/0.17.17: + resolution: + { integrity: sha512-IBTTv8X60dYo6P2t23sSUYym8fGfMAiuv7PzJ+0LcdAndZRzvke+wTVxJeCq4WgjppkOpndL04gMZIFvwoU34Q== } + engines: { node: '>=12' } + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64/0.17.17: + resolution: + { integrity: sha512-WVMBtcDpATjaGfWfp6u9dANIqmU9r37SY8wgAivuKmgKHE+bWSuv0qXEFt/p3qXQYxJIGXQQv6hHcm7iWhWjiw== } + engines: { node: '>=12' } + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el/0.17.17: + resolution: + { integrity: sha512-2kYCGh8589ZYnY031FgMLy0kmE4VoGdvfJkxLdxP4HJvWNXpyLhjOvxVsYjYZ6awqY4bgLR9tpdYyStgZZhi2A== } + engines: { node: '>=12' } + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64/0.17.17: + resolution: + { integrity: sha512-KIdG5jdAEeAKogfyMTcszRxy3OPbZhq0PPsW4iKKcdlbk3YE4miKznxV2YOSmiK/hfOZ+lqHri3v8eecT2ATwQ== } + engines: { node: '>=12' } + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64/0.17.17: + resolution: + { integrity: sha512-Cj6uWLBR5LWhcD/2Lkfg2NrkVsNb2sFM5aVEfumKB2vYetkA/9Uyc1jVoxLZ0a38sUhFk4JOVKH0aVdPbjZQeA== } + engines: { node: '>=12' } + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x/0.17.17: + resolution: + { integrity: sha512-lK+SffWIr0XsFf7E0srBjhpkdFVJf3HEgXCwzkm69kNbRar8MhezFpkIwpk0qo2IOQL4JE4mJPJI8AbRPLbuOQ== } + engines: { node: '>=12' } + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64/0.17.17: + resolution: + { integrity: sha512-XcSGTQcWFQS2jx3lZtQi7cQmDYLrpLRyz1Ns1DzZCtn898cWfm5Icx/DEWNcTU+T+tyPV89RQtDnI7qL2PObPg== } + engines: { node: '>=12' } + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64/0.17.17: + resolution: + { integrity: sha512-RNLCDmLP5kCWAJR+ItLM3cHxzXRTe4N00TQyQiimq+lyqVqZWGPAvcyfUBM0isE79eEZhIuGN09rAz8EL5KdLA== } + engines: { node: '>=12' } + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64/0.17.17: + resolution: + { integrity: sha512-PAXswI5+cQq3Pann7FNdcpSUrhrql3wKjj3gVkmuz6OHhqqYxKvi6GgRBoaHjaG22HV/ZZEgF9TlS+9ftHVigA== } + engines: { node: '>=12' } + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64/0.17.17: + resolution: + { integrity: sha512-V63egsWKnx/4V0FMYkr9NXWrKTB5qFftKGKuZKFIrAkO/7EWLFnbBZNM1CvJ6Sis+XBdPws2YQSHF1Gqf1oj/Q== } + engines: { node: '>=12' } + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64/0.17.17: + resolution: + { integrity: sha512-YtUXLdVnd6YBSYlZODjWzH+KzbaubV0YVd6UxSfoFfa5PtNJNaW+1i+Hcmjpg2nEe0YXUCNF5bkKy1NnBv1y7Q== } + engines: { node: '>=12' } + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32/0.17.17: + resolution: + { integrity: sha512-yczSLRbDdReCO74Yfc5tKG0izzm+lPMYyO1fFTcn0QNwnKmc3K+HdxZWLGKg4pZVte7XVgcFku7TIZNbWEJdeQ== } + engines: { node: '>=12' } + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64/0.17.17: + resolution: + { integrity: sha512-FNZw7H3aqhF9OyRQbDDnzUApDXfC1N6fgBhkqEO2jvYCJ+DxMTfZVqg3AX0R1khg1wHTBRD5SdcibSJ+XF6bFg== } + engines: { node: '>=12' } + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true optional: true /@eslint-community/eslint-utils/4.4.0_eslint@8.38.0: @@ -405,21 +629,6 @@ packages: '@jridgewell/resolve-uri': 3.1.0 '@jridgewell/sourcemap-codec': 1.4.14 - /@next/bundle-analyzer/13.3.0: - resolution: - { integrity: sha512-MNtsx3MFh/kqq2DDa4ladjzfUV8McncEowNvt/s7Z9UjvX6DkuJGFRdjq/RYtxWvjQAsDgiOsgyIOLzDbvQo3g== } - dependencies: - webpack-bundle-analyzer: 4.7.0 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - dev: true - - /@next/env/13.3.1: - resolution: - { integrity: sha512-EDtCoedIZC7JlUQ3uaQpSc4aVmyhbLHmQVALg7pFfQgOTjgSnn7mKtA0DiCMkYvvsx6aFb5octGMtWrOtGXW9A== } - dev: false - /@next/eslint-plugin-next/13.3.0: resolution: { integrity: sha512-wuGN5qSEjSgcq9fVkH0Y/qIPFjnZtW3ZPwfjJOn7l/rrf6y8J24h/lo61kwqunTyzZJm/ETGfGVU9PUs8cnzEA== } @@ -427,96 +636,6 @@ packages: glob: 7.1.7 dev: true - /@next/swc-darwin-arm64/13.3.1: - resolution: - { integrity: sha512-UXPtriEc/pBP8luSLSCZBcbzPeVv+SSjs9cH/KygTbhmACye8/OOXRZO13Z2Wq1G0gLmEAIHQAOuF+vafPd2lw== } - engines: { node: '>= 10' } - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@next/swc-darwin-x64/13.3.1: - resolution: - { integrity: sha512-lT36yYxosCfLtplFzJWgo0hrPu6/do8+msgM7oQkPeohDNdhjtjFUgOOwdSnPublLR6Mo2Ym4P/wl5OANuD2bw== } - engines: { node: '>= 10' } - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-arm64-gnu/13.3.1: - resolution: - { integrity: sha512-wRb76nLWJhonH8s3kxC/1tFguEkeOPayIwe9mkaz1G/yeS3OrjeyKMJsb4+Kdg0zbTo53bNCOl59NNtDM7yyyw== } - engines: { node: '>= 10' } - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-arm64-musl/13.3.1: - resolution: - { integrity: sha512-qz3BzjJRZ16Iq/jrp+pjiYOc0jTjHlfmxQmZk9x/+5uhRP6/eWQSTAPVJ33BMo6oK5O5N4644OgTAbzXzorecg== } - engines: { node: '>= 10' } - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-x64-gnu/13.3.1: - resolution: - { integrity: sha512-6mgkLmwlyWlomQmpl21I3hxgqE5INoW4owTlcLpNsd1V4wP+J46BlI/5zV5KWWbzjfncIqzXoeGs5Eg+1GHODA== } - engines: { node: '>= 10' } - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-x64-musl/13.3.1: - resolution: - { integrity: sha512-uqm5sielhQmKJM+qayIhgZv1KlS5pqTdQ99b+Z7hMWryXS96qE0DftTmMZowBcUL6x7s2vSXyH5wPtO1ON7LBg== } - engines: { node: '>= 10' } - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-arm64-msvc/13.3.1: - resolution: - { integrity: sha512-WomIiTj/v3LevltlibNQKmvrOymNRYL+a0dp5R73IwPWN5FvXWwSELN/kiNALig/+T3luc4qHNTyvMCp9L6U5Q== } - engines: { node: '>= 10' } - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-ia32-msvc/13.3.1: - resolution: - { integrity: sha512-M+PoH+0+q658wRUbs285RIaSTYnGBSTdweH/0CdzDgA6Q4rBM0sQs4DHmO3BPP0ltCO/vViIoyG7ks66XmCA5g== } - engines: { node: '>= 10' } - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-x64-msvc/13.3.1: - resolution: - { integrity: sha512-Sl1F4Vp5Z1rNXWZYqJwMuWRRol4bqOB6+/d7KqkgQ4AcafKPN1PZmpkCoxv4UFHtFNIB7EotnuIhtXu3zScicQ== } - engines: { node: '>= 10' } - cpu: [x64] - os: [win32] - requiresBuild: true - dev: false - optional: true - /@noble/hashes/1.2.0: resolution: { integrity: sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== } @@ -1162,12 +1281,128 @@ packages: - supports-color dev: false - /@swc/helpers/0.5.0: + /@swc/core-darwin-arm64/1.3.53: resolution: - { integrity: sha512-SjY/p4MmECVVEWspzSRpQEM3sjR17sP8PbGxELWrT+YZMBfiUyt1MRUNjMV23zohwlG2HYtCQOsCwsTHguXkyg== } - dependencies: - tslib: 2.5.0 - dev: false + { integrity: sha512-JvWwV/duzdQ60iwWYceDhDk75LmdrLoPC7myX3Src3gl/bJtETMq7uHS9uY8m0GQOqbct7XGR3q5Ff21YxkSzg== } + engines: { node: '>=10' } + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@swc/core-darwin-x64/1.3.53: + resolution: + { integrity: sha512-UuIGZtCfUPJM2Q01bRIFzmucOMg8UZ+mY3kh5xB8kl/VrLltBlraSWGjjJzYmUeUxiF8+CtMfeSYav5QfU2v3g== } + engines: { node: '>=10' } + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@swc/core-linux-arm-gnueabihf/1.3.53: + resolution: + { integrity: sha512-LupAjTErteyLmowYIfiQeTz3uVh7/SPYv/EuG1PYrajNoUYomt7WA0rQUoyglF9VtwVyNqxptWEO5So32ApTHA== } + engines: { node: '>=10' } + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@swc/core-linux-arm64-gnu/1.3.53: + resolution: + { integrity: sha512-kREfZdiJH/O8GtJJ22wVN9DVzz/+CPAkw5Mn5te2KQg0xJHMWaESU5XeYMWvtwyOQVmb31b6zCGFy3pnBWWfGw== } + engines: { node: '>=10' } + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@swc/core-linux-arm64-musl/1.3.53: + resolution: + { integrity: sha512-VeAgomBr6BVuBRjZjRHmvp5gKp1nZgbbd441ca1AvsPd2c+ZyhyHLxTWeHOzBDa/vYnmi9BCwx3QJzFqbAFPVw== } + engines: { node: '>=10' } + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@swc/core-linux-x64-gnu/1.3.53: + resolution: + { integrity: sha512-LFX5+QpQkESPkmx860C40pIiYf1utEqoA+WDtmKnUz3DucYvw3eGlXCBdyklP7UBWwJktKIcPlIqr7yROY5VlQ== } + engines: { node: '>=10' } + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@swc/core-linux-x64-musl/1.3.53: + resolution: + { integrity: sha512-O0lbJgeaM0VEsG8wFYvpF+Iuf0IENv+LnXHoygkAsv67sVW54+gFxav2sEdkftD5qYe9ku4tmtTVYRZlFgC84Q== } + engines: { node: '>=10' } + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@swc/core-win32-arm64-msvc/1.3.53: + resolution: + { integrity: sha512-7PgvPl0aNLaFZSK+rIi4DB1g0aW2qOsTIJQSJGRszsCP8pze/traXymyuSG2I3y9Hx7Z+bP5ycJydyAgCw88WA== } + engines: { node: '>=10' } + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@swc/core-win32-ia32-msvc/1.3.53: + resolution: + { integrity: sha512-T+OacGm69t8+1mt1sHlwhREiFiFgSeIGL3h11FIs8o2zKnOr5z2H9myzR432X8WuHGVQAOCMvDu53LCMBD0ZzQ== } + engines: { node: '>=10' } + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@swc/core-win32-x64-msvc/1.3.53: + resolution: + { integrity: sha512-uV1/GhROJ/SXzj+f+kKcVtR2GuAiggvbqepzZS46+G47okf6229hr2T1fjmiwYyA75w9R3Bj/wil4UhodohOLg== } + engines: { node: '>=10' } + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@swc/core/1.3.53: + resolution: + { integrity: sha512-OM5nCfKDZXr1HjxD072Jlx5463tPX7xeY7NDSRE3X4KFlkRDFdyMWAyV3pet1oouOfUNrzzoVTAR4XSU8ytO6Q== } + engines: { node: '>=10' } + requiresBuild: true + peerDependencies: + '@swc/helpers': ^0.5.0 + peerDependenciesMeta: + '@swc/helpers': + optional: true + optionalDependencies: + '@swc/core-darwin-arm64': 1.3.53 + '@swc/core-darwin-x64': 1.3.53 + '@swc/core-linux-arm-gnueabihf': 1.3.53 + '@swc/core-linux-arm64-gnu': 1.3.53 + '@swc/core-linux-arm64-musl': 1.3.53 + '@swc/core-linux-x64-gnu': 1.3.53 + '@swc/core-linux-x64-musl': 1.3.53 + '@swc/core-win32-arm64-msvc': 1.3.53 + '@swc/core-win32-ia32-msvc': 1.3.53 + '@swc/core-win32-x64-msvc': 1.3.53 + dev: true /@tailwindcss/typography/0.5.9_tailwindcss@3.3.1: resolution: @@ -1508,6 +1743,18 @@ packages: eslint-visitor-keys: 3.4.0 dev: true + /@vitejs/plugin-react-swc/3.3.0_vite@4.3.1: + resolution: + { integrity: sha512-Ycg+n2eyCOTpn/wRy+evVo859+hw7qCj9iaX5CMny6x1fx1Uoq0xBG+a98lFtwLNGfGEnpI0F26YigRuxCRkwg== } + peerDependencies: + vite: ^4 + dependencies: + '@swc/core': 1.3.53 + vite: 4.3.1_@types+node@18.15.13 + transitivePeerDependencies: + - '@swc/helpers' + dev: true + /acorn-jsx/5.3.2_acorn@8.8.2: resolution: { integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== } @@ -1517,12 +1764,6 @@ packages: acorn: 8.8.2 dev: true - /acorn-walk/8.2.0: - resolution: - { integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== } - engines: { node: '>=0.4.0' } - dev: true - /acorn/8.8.2: resolution: { integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== } @@ -1784,13 +2025,11 @@ packages: node-gyp-build: 4.6.0 dev: false - /busboy/1.6.0: + /cac/6.7.14: resolution: - { integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== } - engines: { node: '>=10.16.0' } - dependencies: - streamsearch: 1.1.0 - dev: false + { integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== } + engines: { node: '>=8' } + dev: true /call-bind/1.0.2: resolution: @@ -1814,6 +2053,7 @@ packages: /caniuse-lite/1.0.30001481: resolution: { integrity: sha512-KCqHwRnaa1InZBtqXzP98LPg0ajCVujMKjqKDhZEthIpAsJl/YEIa3YvXjGXPVqzZVguccuu7ga9KOE1J9rKPQ== } + dev: true /chalk/2.4.2: resolution: @@ -1888,11 +2128,6 @@ packages: string-width: 5.1.2 dev: true - /client-only/0.0.1: - resolution: - { integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== } - dev: false - /color-convert/1.9.3: resolution: { integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== } @@ -1935,12 +2170,6 @@ packages: engines: { node: '>= 6' } dev: true - /commander/7.2.0: - resolution: - { integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== } - engines: { node: '>= 10' } - dev: true - /concat-map/0.0.1: resolution: { integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== } @@ -2133,11 +2362,6 @@ packages: esutils: 2.0.3 dev: true - /duplexer/0.1.2: - resolution: - { integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== } - dev: true - /eastasianwidth/0.2.0: resolution: { integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== } @@ -2229,6 +2453,11 @@ packages: stop-iteration-iterator: 1.0.0 dev: true + /es-module-lexer/0.10.5: + resolution: + { integrity: sha512-+7IwY/kiGAacQfY+YBhKMvEmyAJnw5grTUgjG85Pe7vcUI/6b7pZjZG8nQ7+48YhzEAEqrEgD2dCz/JIK+AYvw== } + dev: true + /es-set-tostringtag/2.0.1: resolution: { integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== } @@ -2284,6 +2513,37 @@ packages: ext: 1.7.0 dev: false + /esbuild/0.17.17: + resolution: + { integrity: sha512-/jUywtAymR8jR4qsa2RujlAF7Krpt5VWi72Q2yuLD4e/hvtNcFQ0I1j8m/bxq238pf3/0KO5yuXNpuLx8BE1KA== } + engines: { node: '>=12' } + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.17.17 + '@esbuild/android-arm64': 0.17.17 + '@esbuild/android-x64': 0.17.17 + '@esbuild/darwin-arm64': 0.17.17 + '@esbuild/darwin-x64': 0.17.17 + '@esbuild/freebsd-arm64': 0.17.17 + '@esbuild/freebsd-x64': 0.17.17 + '@esbuild/linux-arm': 0.17.17 + '@esbuild/linux-arm64': 0.17.17 + '@esbuild/linux-ia32': 0.17.17 + '@esbuild/linux-loong64': 0.17.17 + '@esbuild/linux-mips64el': 0.17.17 + '@esbuild/linux-ppc64': 0.17.17 + '@esbuild/linux-riscv64': 0.17.17 + '@esbuild/linux-s390x': 0.17.17 + '@esbuild/linux-x64': 0.17.17 + '@esbuild/netbsd-x64': 0.17.17 + '@esbuild/openbsd-x64': 0.17.17 + '@esbuild/sunos-x64': 0.17.17 + '@esbuild/win32-arm64': 0.17.17 + '@esbuild/win32-ia32': 0.17.17 + '@esbuild/win32-x64': 0.17.17 + dev: true + /escalade/3.1.1: resolution: { integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== } @@ -2726,20 +2986,6 @@ packages: { integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA== } dev: true - /framer-motion/9.1.7_biqbaboplfbrettd7655fr4n2y: - resolution: - { integrity: sha512-nKxBkIO4IPkMEqcBbbATxsVjwPYShKl051yhBv9628iAH6JLeHD0siBHxkL62oQzMC1+GNX73XtPjgP753ufuw== } - peerDependencies: - react: ^18.0.0 - react-dom: ^18.0.0 - dependencies: - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 - tslib: 2.5.0 - optionalDependencies: - '@emotion/is-prop-valid': 0.8.8 - dev: false - /fs.realpath/1.0.0: resolution: { integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== } @@ -2935,14 +3181,6 @@ packages: { integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== } dev: true - /gzip-size/6.0.0: - resolution: - { integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== } - engines: { node: '>=10' } - dependencies: - duplexer: 0.1.2 - dev: true - /has-bigints/1.0.2: resolution: { integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== } @@ -3609,6 +3847,7 @@ packages: { integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== } engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 } hasBin: true + dev: true /natural-compare-lite/1.4.0: resolution: @@ -3625,51 +3864,6 @@ packages: { integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== } dev: false - /next/13.3.1_biqbaboplfbrettd7655fr4n2y: - resolution: - { integrity: sha512-eByWRxPzKHs2oQz1yE41LX35umhz86ZSZ+mYyXBqn2IBi2hyUqxBA88avywdr4uyH+hCJczegGsDGWbzQA5Rqw== } - engines: { node: '>=14.18.0' } - hasBin: true - peerDependencies: - '@opentelemetry/api': ^1.1.0 - fibers: '>= 3.1.0' - node-sass: ^6.0.0 || ^7.0.0 - react: ^18.2.0 - react-dom: ^18.2.0 - sass: ^1.3.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - fibers: - optional: true - node-sass: - optional: true - sass: - optional: true - dependencies: - '@next/env': 13.3.1 - '@swc/helpers': 0.5.0 - busboy: 1.6.0 - caniuse-lite: 1.0.30001481 - postcss: 8.4.14 - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 - styled-jsx: 5.1.1_react@18.2.0 - optionalDependencies: - '@next/swc-darwin-arm64': 13.3.1 - '@next/swc-darwin-x64': 13.3.1 - '@next/swc-linux-arm64-gnu': 13.3.1 - '@next/swc-linux-arm64-musl': 13.3.1 - '@next/swc-linux-x64-gnu': 13.3.1 - '@next/swc-linux-x64-musl': 13.3.1 - '@next/swc-win32-arm64-msvc': 13.3.1 - '@next/swc-win32-ia32-msvc': 13.3.1 - '@next/swc-win32-x64-msvc': 13.3.1 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - dev: false - /node-fetch/2.6.7_encoding@0.1.13: resolution: { integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== } @@ -3851,12 +4045,6 @@ packages: is-wsl: 2.2.0 dev: true - /opener/1.5.2: - resolution: - { integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== } - hasBin: true - dev: true - /optionator/0.9.1: resolution: { integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== } @@ -3940,6 +4128,7 @@ packages: /picocolors/1.0.0: resolution: { integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== } + dev: true /picomatch/2.3.1: resolution: @@ -4042,16 +4231,6 @@ packages: { integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== } dev: true - /postcss/8.4.14: - resolution: - { integrity: sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig== } - engines: { node: ^10 || ^12 || >=14 } - dependencies: - nanoid: 3.3.6 - picocolors: 1.0.0 - source-map-js: 1.0.2 - dev: false - /postcss/8.4.23: resolution: { integrity: sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA== } @@ -4374,6 +4553,15 @@ packages: glob: 7.2.3 dev: true + /rollup/3.20.7: + resolution: + { integrity: sha512-P7E2zezKSLhWnTz46XxjSmInrbOCiul1yf+kJccMxT56vxjHwCbDfoLbiqFgu+WQoo9ij2PkraYaBstgB2prBA== } + engines: { node: '>=14.18.0', npm: '>=8.0.0' } + hasBin: true + optionalDependencies: + fsevents: 2.3.2 + dev: true + /run-parallel/1.2.0: resolution: { integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== } @@ -4457,14 +4645,14 @@ packages: { integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== } dev: true - /sirv/1.0.19: + /sirv/2.0.2: resolution: - { integrity: sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ== } + { integrity: sha512-4Qog6aE29nIjAOKe/wowFTxOdmbEZKb+3tsLljaBRzJwtqto0BChD2zzH0LhgCSXiI+V7X+Y45v14wBZQ1TK3w== } engines: { node: '>= 10' } dependencies: '@polka/url': 1.0.0-next.21 mrmime: 1.0.1 - totalist: 1.1.0 + totalist: 3.0.1 dev: true /slash/3.0.0: @@ -4512,6 +4700,7 @@ packages: resolution: { integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== } engines: { node: '>=0.10.0' } + dev: true /source-map/0.5.7: resolution: @@ -4527,12 +4716,6 @@ packages: internal-slot: 1.0.5 dev: true - /streamsearch/1.1.0: - resolution: - { integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== } - engines: { node: '>=10.0.0' } - dev: false - /string-argv/0.3.1: resolution: { integrity: sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== } @@ -4635,24 +4818,6 @@ packages: engines: { node: '>=8' } dev: true - /styled-jsx/5.1.1_react@18.2.0: - resolution: - { integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw== } - engines: { node: '>= 12.0.0' } - peerDependencies: - '@babel/core': '*' - babel-plugin-macros: '*' - react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' - peerDependenciesMeta: - '@babel/core': - optional: true - babel-plugin-macros: - optional: true - dependencies: - client-only: 0.0.1 - react: 18.2.0 - dev: false - /sucrase/3.32.0: resolution: { integrity: sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ== } @@ -4798,9 +4963,9 @@ packages: is-number: 7.0.0 dev: true - /totalist/1.1.0: + /totalist/3.0.1: resolution: - { integrity: sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== } + { integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ== } engines: { node: '>=6' } dev: true @@ -4814,6 +4979,20 @@ packages: { integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== } dev: true + /tsconfck/2.1.1_typescript@4.9.5: + resolution: + { integrity: sha512-ZPCkJBKASZBmBUNqGHmRhdhM8pJYDdOXp4nRgj/O0JwUwsMq50lCDRQP/M5GBNAA0elPrq4gAeu4dkaVCuKWww== } + engines: { node: ^14.13.1 || ^16 || >=18 } + hasBin: true + peerDependencies: + typescript: ^4.3.5 || ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + dependencies: + typescript: 4.9.5 + dev: true + /tsconfig-paths/3.14.2: resolution: { integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g== } @@ -5002,31 +5181,88 @@ packages: { integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== } dev: true + /vite-plugin-ssr/0.4.115_vite@4.3.1: + resolution: + { integrity: sha512-SXoru+rFEwSBgYXvQXzG73nfN8x+MGhlW4pcJI2BX0p6Tei8ys0tyg1yNu1VI95Uux2rBZip6ra/43rvKSNsag== } + engines: { node: '>=12.19.0' } + hasBin: true + peerDependencies: + react-streaming: '>=0.3.5' + vite: '>=3.0.0' + peerDependenciesMeta: + react-streaming: + optional: true + dependencies: + '@brillout/import': 0.2.3 + '@brillout/json-serializer': 0.5.3 + '@brillout/vite-plugin-import-build': 0.2.16 + acorn: 8.8.2 + cac: 6.7.14 + es-module-lexer: 0.10.5 + esbuild: 0.17.17 + fast-glob: 3.2.12 + picocolors: 1.0.0 + sirv: 2.0.2 + vite: 4.3.1_@types+node@18.15.13 + dev: true + + /vite-tsconfig-paths/4.2.0_mzhihm7zd2gyalpll4qoudvuha: + resolution: + { integrity: sha512-jGpus0eUy5qbbMVGiTxCL1iB9ZGN6Bd37VGLJU39kTDD6ZfULTTb1bcc5IeTWqWJKiWV5YihCaibeASPiGi8kw== } + peerDependencies: + vite: '*' + peerDependenciesMeta: + vite: + optional: true + dependencies: + debug: 4.3.4 + globrex: 0.1.2 + tsconfck: 2.1.1_typescript@4.9.5 + vite: 4.3.1_@types+node@18.15.13 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /vite/4.3.1_@types+node@18.15.13: + resolution: + { integrity: sha512-EPmfPLAI79Z/RofuMvkIS0Yr091T2ReUoXQqc5ppBX/sjFRhHKiPPF/R46cTdoci/XgeQpB23diiJxq5w30vdg== } + engines: { node: ^14.18.0 || >=16.0.0 } + hasBin: true + peerDependencies: + '@types/node': '>= 14' + less: '*' + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 18.15.13 + esbuild: 0.17.17 + postcss: 8.4.23 + rollup: 3.20.7 + optionalDependencies: + fsevents: 2.3.2 + dev: true + /webidl-conversions/3.0.1: resolution: { integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== } dev: false - /webpack-bundle-analyzer/4.7.0: - resolution: - { integrity: sha512-j9b8ynpJS4K+zfO5GGwsAcQX4ZHpWV+yRiHDiL+bE0XHJ8NiPYLTNVQdlFYWxtpg9lfAQNlwJg16J9AJtFSXRg== } - engines: { node: '>= 10.13.0' } - hasBin: true - dependencies: - acorn: 8.8.2 - acorn-walk: 8.2.0 - chalk: 4.1.2 - commander: 7.2.0 - gzip-size: 6.0.0 - lodash: 4.17.21 - opener: 1.5.2 - sirv: 1.0.19 - ws: 7.5.9 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - dev: true - /websocket/1.0.34: resolution: { integrity: sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== } @@ -5124,20 +5360,6 @@ packages: { integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== } dev: true - /ws/7.5.9: - resolution: - { integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== } - engines: { node: '>=8.3.0' } - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true - /ws/8.13.0: resolution: { integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== } diff --git a/src/assets/global.css b/src/index.css similarity index 100% rename from src/assets/global.css rename to src/index.css diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 00000000..27c24e7e --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,8 @@ +import react from '@vitejs/plugin-react-swc'; +import { defineConfig } from 'vite'; +import ssr from 'vite-plugin-ssr/plugin'; +import viteTsconfigPaths from 'vite-tsconfig-paths'; + +export default defineConfig({ + plugins: [react(), ssr(), viteTsconfigPaths()], +}); From b9bafc851e69f04af708cadcf46c702c383d338a Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Sat, 22 Apr 2023 17:56:09 +0700 Subject: [PATCH 2/4] migrated to vite and vite-plugin-ssr --- .prettierrc | 1 + src-tauri/tauri.conf.json | 4 +- src/app/layout.tsx | 13 -- src/app/nostr/newsfeed/circle/page.tsx | 7 - src/app/nostr/newsfeed/note/page.tsx | 10 - src/app/nostr/user/page.tsx | 51 ------ src/app/onboarding/create/page.tsx | 169 ----------------- src/app/onboarding/login/page.tsx | 120 ------------ src/app/onboarding/login/step-2/page.tsx | 145 --------------- src/app/providers.tsx | 9 - src/components/activeLink.tsx | 25 --- src/components/appHeader/actions.tsx | 10 +- src/components/appHeader/index.tsx | 11 +- src/components/channels/channelList.tsx | 13 -- src/components/channels/channelListItem.tsx | 20 +- src/components/chats/chatList.tsx | 16 +- src/components/chats/chatListItem.tsx | 20 +- src/components/chats/chatModalUser.tsx | 14 +- src/components/chats/messageUser.tsx | 11 +- src/components/eventCollector.tsx | 2 - src/components/form/emojiPicker.tsx | 36 ---- src/components/imageWithFallback.tsx | 26 --- .../layouts/newsfeed.tsx} | 2 +- .../layouts/onboarding.tsx} | 0 src/components/link.tsx | 12 ++ .../multiAccounts/activeAccount.tsx | 14 +- .../multiAccounts/inactiveAccount.tsx | 9 +- src/components/multiAccounts/index.tsx | 13 +- src/components/navigation/channels.tsx | 2 - src/components/navigation/chats.tsx | 2 - src/components/navigation/newsfeed.tsx | 20 +- src/components/note/base.tsx | 7 +- src/components/note/meta/comment.tsx | 13 +- src/components/note/preview/image.tsx | 11 +- src/components/note/preview/link.tsx | 23 --- src/components/note/rootNote.tsx | 7 +- src/components/profile/followers.tsx | 2 - src/components/profile/follows.tsx | 2 - src/components/profile/metadata.tsx | 18 +- src/components/profile/notes.tsx | 2 - src/components/relaysProvider.tsx | 2 - src/components/user/base.tsx | 9 +- src/components/user/extend.tsx | 9 +- src/components/user/follow.tsx | 9 +- src/components/user/large.tsx | 7 +- src/components/user/mini.tsx | 9 +- src/components/user/quoteRepost.tsx | 9 +- .../page.tsx => pages/channel/index.page.tsx} | 25 +-- .../page.tsx => pages/chat/index.page.tsx} | 26 +-- src/{app/page.tsx => pages/index.page.tsx} | 55 +++--- src/pages/newsfeed/circle/index.page.tsx | 3 + .../newsfeed/following/index.page.tsx} | 53 +++--- src/pages/onboarding/create/index.page.tsx | 172 ++++++++++++++++++ .../onboarding/create/step-2/index.page.tsx} | 130 ++++++------- .../onboarding/index.page.tsx} | 93 +++++----- src/pages/onboarding/login/index.page.tsx | 121 ++++++++++++ .../onboarding/login/step-2/index.page.tsx | 144 +++++++++++++++ src/pages/user/index.page.tsx | 57 ++++++ src/renderer/_default.page.client.tsx | 20 ++ src/renderer/_default.page.server.tsx | 30 +++ src/renderer/_error.page.tsx | 17 ++ src/{ => renderer}/index.css | 0 src/renderer/shell.tsx | 17 ++ src/renderer/types.ts | 35 ++++ src/utils/hooks/usePageContext.tsx | 22 +++ tsconfig.json | 3 +- vite.config.ts | 2 +- 67 files changed, 911 insertions(+), 1060 deletions(-) delete mode 100644 src/app/layout.tsx delete mode 100644 src/app/nostr/newsfeed/circle/page.tsx delete mode 100644 src/app/nostr/newsfeed/note/page.tsx delete mode 100644 src/app/nostr/user/page.tsx delete mode 100644 src/app/onboarding/create/page.tsx delete mode 100644 src/app/onboarding/login/page.tsx delete mode 100644 src/app/onboarding/login/step-2/page.tsx delete mode 100644 src/app/providers.tsx delete mode 100644 src/components/activeLink.tsx delete mode 100644 src/components/form/emojiPicker.tsx delete mode 100644 src/components/imageWithFallback.tsx rename src/{app/nostr/layout.tsx => components/layouts/newsfeed.tsx} (95%) rename src/{app/onboarding/layout.tsx => components/layouts/onboarding.tsx} (100%) create mode 100644 src/components/link.tsx delete mode 100644 src/components/note/preview/link.tsx rename src/{app/nostr/channel/page.tsx => pages/channel/index.page.tsx} (82%) rename src/{app/nostr/chat/page.tsx => pages/chat/index.page.tsx} (73%) rename src/{app/page.tsx => pages/index.page.tsx} (86%) create mode 100644 src/pages/newsfeed/circle/index.page.tsx rename src/{app/nostr/newsfeed/following/page.tsx => pages/newsfeed/following/index.page.tsx} (71%) create mode 100644 src/pages/onboarding/create/index.page.tsx rename src/{app/onboarding/create/step-2/page.tsx => pages/onboarding/create/step-2/index.page.tsx} (61%) rename src/{app/onboarding/page.tsx => pages/onboarding/index.page.tsx} (61%) create mode 100644 src/pages/onboarding/login/index.page.tsx create mode 100644 src/pages/onboarding/login/step-2/index.page.tsx create mode 100644 src/pages/user/index.page.tsx create mode 100644 src/renderer/_default.page.client.tsx create mode 100644 src/renderer/_default.page.server.tsx create mode 100644 src/renderer/_error.page.tsx rename src/{ => renderer}/index.css (100%) create mode 100644 src/renderer/shell.tsx create mode 100644 src/renderer/types.ts create mode 100644 src/utils/hooks/usePageContext.tsx diff --git a/.prettierrc b/.prettierrc index 4ed3e6bf..b63ef5a4 100644 --- a/.prettierrc +++ b/.prettierrc @@ -15,6 +15,7 @@ "^@stores/(.*)$", "^@utils/(.*)$", "^@assets/(.*)$", + "^@renderer/(.*)$", "", "^[./]" ], diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 430b269c..44eda095 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -2,8 +2,8 @@ "build": { "beforeDevCommand": "pnpm dev", "beforeBuildCommand": "pnpm build", - "devPath": "http://localhost:1420", - "distDir": "../out", + "devPath": "http://localhost:3000", + "distDir": "../dist", "withGlobalTauri": true }, "package": { diff --git a/src/app/layout.tsx b/src/app/layout.tsx deleted file mode 100644 index 7a87fa9c..00000000 --- a/src/app/layout.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import '@assets/global.css'; - -import { Providers } from './providers'; - -export default function RootLayout({ children }: { children: React.ReactNode }) { - return ( - - - {children} - - - ); -} diff --git a/src/app/nostr/newsfeed/circle/page.tsx b/src/app/nostr/newsfeed/circle/page.tsx deleted file mode 100644 index a51233ce..00000000 --- a/src/app/nostr/newsfeed/circle/page.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function Page() { - return ( -
-

Sorry, this feature under development, it will come in the next version

-
- ); -} diff --git a/src/app/nostr/newsfeed/note/page.tsx b/src/app/nostr/newsfeed/note/page.tsx deleted file mode 100644 index 276b0122..00000000 --- a/src/app/nostr/newsfeed/note/page.tsx +++ /dev/null @@ -1,10 +0,0 @@ -'use client'; - -import { useSearchParams } from 'next/navigation'; - -export default function Page() { - const searchParams = useSearchParams(); - const id = searchParams.get('event-id'); - - return
{id}
; -} diff --git a/src/app/nostr/user/page.tsx b/src/app/nostr/user/page.tsx deleted file mode 100644 index 31252c80..00000000 --- a/src/app/nostr/user/page.tsx +++ /dev/null @@ -1,51 +0,0 @@ -'use client'; - -import ProfileFollowers from '@components/profile/followers'; -import ProfileFollows from '@components/profile/follows'; -import ProfileMetadata from '@components/profile/metadata'; -import ProfileNotes from '@components/profile/notes'; - -import * as Tabs from '@radix-ui/react-tabs'; -import { useSearchParams } from 'next/navigation'; - -export default function Page() { - const searchParams = useSearchParams(); - const pubkey = searchParams.get('pubkey'); - - return ( -
- - - - - Notes - - - Followers - - - Following - - - - - - - - - - - - -
- ); -} diff --git a/src/app/onboarding/create/page.tsx b/src/app/onboarding/create/page.tsx deleted file mode 100644 index ee91734a..00000000 --- a/src/app/onboarding/create/page.tsx +++ /dev/null @@ -1,169 +0,0 @@ -'use client'; - -import { RelayContext } from '@components/relaysProvider'; - -import { createAccount } from '@utils/storage'; - -import { EyeClose, EyeEmpty } from 'iconoir-react'; -import Image from 'next/image'; -import { useRouter } from 'next/navigation'; -import { generatePrivateKey, getEventHash, getPublicKey, nip19, signEvent } from 'nostr-tools'; -import { useCallback, useContext, useMemo, useState } from 'react'; -import { Config, names, uniqueNamesGenerator } from 'unique-names-generator'; - -const config: Config = { - dictionaries: [names], -}; - -export default function Page() { - const router = useRouter(); - const [pool, relays]: any = useContext(RelayContext); - - const [type, setType] = useState('password'); - const [loading, setLoading] = useState(false); - - const privkey = useMemo(() => generatePrivateKey(), []); - const name = useMemo(() => uniqueNamesGenerator(config).toString(), []); - - const pubkey = getPublicKey(privkey); - const npub = nip19.npubEncode(pubkey); - const nsec = nip19.nsecEncode(privkey); - - // auto-generated profile metadata - const metadata: any = useMemo( - () => ({ - display_name: name, - name: name, - username: name.toLowerCase(), - picture: 'https://void.cat/d/KmypFh2fBdYCEvyJrPiN89.webp', - }), - [name] - ); - - // toggle privatek key - const showPrivateKey = () => { - if (type === 'password') { - setType('text'); - } else { - setType('password'); - } - }; - - // create account and broadcast to all relays - const submit = useCallback(async () => { - setLoading(true); - - // build event - const event: any = { - content: JSON.stringify(metadata), - created_at: Math.floor(Date.now() / 1000), - kind: 0, - pubkey: pubkey, - tags: [], - }; - event.id = getEventHash(event); - event.sig = signEvent(event, privkey); - // insert to database - createAccount(pubkey, privkey, metadata); - // broadcast - pool.publish(event, relays); - // redirect to next step - router.push(`/onboarding/create/step-2?pubkey=${pubkey}&privkey=${privkey}`, { forceOptimisticNavigation: true }); - }, [pool, pubkey, privkey, metadata, relays, router]); - - return ( -
-
-

- Create new account -

-
-
-
-
-
- -
- -
-
-
- -
- - -
-
-
- -
-
-
-
- -
-
-
-

{metadata.display_name}

-

@{metadata.username}

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {loading === true ? ( - - - - - ) : ( - - )} -
-
-
-
- ); -} diff --git a/src/app/onboarding/login/page.tsx b/src/app/onboarding/login/page.tsx deleted file mode 100644 index a0eeccfa..00000000 --- a/src/app/onboarding/login/page.tsx +++ /dev/null @@ -1,120 +0,0 @@ -'use client'; - -import { CableTag } from 'iconoir-react'; -import { useRouter } from 'next/navigation'; -import { getPublicKey, nip19 } from 'nostr-tools'; -import { Resolver, useForm } from 'react-hook-form'; - -type FormValues = { - key: string; -}; - -const resolver: Resolver = async (values) => { - return { - values: values.key ? values : {}, - errors: !values.key - ? { - key: { - type: 'required', - message: 'This is required.', - }, - } - : {}, - }; -}; - -export default function Page() { - const router = useRouter(); - const { - register, - setError, - handleSubmit, - formState: { errors, isDirty, isValid, isSubmitting }, - } = useForm({ resolver }); - - const onSubmit = async (data: any) => { - try { - let privkey = data['key']; - - if (privkey.substring(0, 4) === 'nsec') { - privkey = nip19.decode(privkey).data; - } - if (typeof getPublicKey(privkey) === 'string') { - router.push(`/onboarding/login/step-2?privkey=${privkey}`, { forceOptimisticNavigation: true }); - } - } catch (error) { - setError('key', { - type: 'custom', - message: 'Private Key is invalid, please check again', - }); - } - }; - - return ( -
-
-

- Login with Private Key -

-
-
-
-
-
- {/* #TODO: add function */} - -
-
-
-
-
-
- or -
-
-
-
- -
- {errors.key &&

{errors.key.message}

}
-
-
-
- {isSubmitting ? ( - - - - - ) : ( - - )} -
-
-
-
- ); -} diff --git a/src/app/onboarding/login/step-2/page.tsx b/src/app/onboarding/login/step-2/page.tsx deleted file mode 100644 index b9f23ee4..00000000 --- a/src/app/onboarding/login/step-2/page.tsx +++ /dev/null @@ -1,145 +0,0 @@ -'use client'; - -import { RelayContext } from '@components/relaysProvider'; - -import { DEFAULT_AVATAR } from '@stores/constants'; - -import { fetchProfileMetadata } from '@utils/hooks/useProfileMetadata'; -import { shortenKey } from '@utils/shortenKey'; -import { createAccount, createPleb, updateAccount } from '@utils/storage'; -import { nip02ToArray } from '@utils/transform'; - -import Image from 'next/image'; -import Link from 'next/link'; -import { useSearchParams } from 'next/navigation'; -import { getPublicKey } from 'nostr-tools'; -import { useCallback, useContext, useEffect, useRef, useState } from 'react'; - -export default function Page() { - const searchParams = useSearchParams(); - const privkey = searchParams.get('privkey'); - - const [pool, relays]: any = useContext(RelayContext); - const [profile, setProfile] = useState({ metadata: null }); - const [done, setDone] = useState(false); - const timeout = useRef(null); - - const pubkey = getPublicKey(privkey); - - const createPlebs = useCallback(async (tags: string[]) => { - for (const tag of tags) { - fetchProfileMetadata(tag[1]) - .then((res: any) => createPleb(tag[1], res.content)) - .catch(console.error); - } - }, []); - - useEffect(() => { - const unsubscribe = pool.subscribe( - [ - { - kinds: [0, 3], - authors: [pubkey], - }, - ], - relays, - (event: any) => { - if (event.kind === 0) { - // create account - createAccount(pubkey, privkey, event.content); - // update state - setProfile({ - metadata: JSON.parse(event.content), - }); - } else { - if (event.tags.length > 0) { - createPlebs(event.tags); - const arr = nip02ToArray(event.tags); - // update account's folllows with NIP-02 tag list - updateAccount('follows', arr, pubkey); - } - } - }, - undefined, - () => { - timeout.current = setTimeout(() => setDone(true), 5000); - }, - { - unsubscribeOnEose: true, - logAllEvents: false, - } - ); - - return () => { - unsubscribe(); - clearTimeout(timeout.current); - }; - }, [pool, relays, pubkey, privkey, createPlebs]); - - return ( -
-
-

- Bringing back your profile... -

-
-
-
-
-
-
-
- -
-
-
-

{profile.metadata?.display_name || profile.metadata?.name}

- · -

@{profile.metadata?.username || (pubkey && shortenKey(pubkey))}

-
-
-
-
-
-
-
-
-
-
-
-
-
- {done === false ? ( - - - - - ) : ( - - Done! Go to newsfeed - - )} -
-
-
-
- ); -} diff --git a/src/app/providers.tsx b/src/app/providers.tsx deleted file mode 100644 index 5d563bcb..00000000 --- a/src/app/providers.tsx +++ /dev/null @@ -1,9 +0,0 @@ -'use client'; - -import dynamic from 'next/dynamic'; - -const RelayProvider = dynamic(() => import('@components/relaysProvider'), { ssr: false }); - -export function Providers({ children }: { children: React.ReactNode }) { - return {children}; -} diff --git a/src/components/activeLink.tsx b/src/components/activeLink.tsx deleted file mode 100644 index 510b8dcb..00000000 --- a/src/components/activeLink.tsx +++ /dev/null @@ -1,25 +0,0 @@ -'use client'; - -import Link from 'next/link'; -import { useSelectedLayoutSegments } from 'next/navigation'; - -export const ActiveLink = ({ - href, - className, - activeClassName, - children, -}: { - href: string; - className: string; - activeClassName: string; - children: React.ReactNode; -}) => { - const segments = useSelectedLayoutSegments(); - const isActive = href.includes(segments[1]); - - return ( - - {children} - - ); -}; diff --git a/src/components/appHeader/actions.tsx b/src/components/appHeader/actions.tsx index b8c13ada..f5c4cf0d 100644 --- a/src/components/appHeader/actions.tsx +++ b/src/components/appHeader/actions.tsx @@ -1,24 +1,20 @@ -'use client'; - import { platform } from '@tauri-apps/api/os'; import { ArrowLeft, ArrowRight, Refresh } from 'iconoir-react'; -import { useRouter } from 'next/navigation'; import { useLayoutEffect, useState } from 'react'; export default function AppActions() { - const router = useRouter(); const [os, setOS] = useState(''); const goBack = () => { - router.back(); + window.history.back(); }; const goForward = () => { - router.forward(); + window.history.forward(); }; const reload = () => { - router.refresh(); + window.location.reload(); }; useLayoutEffect(() => { diff --git a/src/components/appHeader/index.tsx b/src/components/appHeader/index.tsx index 4c72fca8..7f10a490 100644 --- a/src/components/appHeader/index.tsx +++ b/src/components/appHeader/index.tsx @@ -1,12 +1,5 @@ -import dynamic from 'next/dynamic'; - -const AppActions = dynamic(() => import('@components/appHeader/actions'), { - ssr: false, -}); - -const EventCollector = dynamic(() => import('@components/eventCollector'), { - ssr: false, -}); +import AppActions from '@components/appHeader/actions'; +import EventCollector from '@components/eventCollector'; export default function AppHeader({ collector }: { collector: boolean }) { return ( diff --git a/src/components/channels/channelList.tsx b/src/components/channels/channelList.tsx index e6ecb109..cab853a6 100644 --- a/src/components/channels/channelList.tsx +++ b/src/components/channels/channelList.tsx @@ -10,19 +10,6 @@ export default function ChannelList() { return (
- {/* - -
- -
-
-
Browse channels
-
- - */} {list.map((item) => ( ))} diff --git a/src/components/channels/channelListItem.tsx b/src/components/channels/channelListItem.tsx index dbdae2cb..4b8368e9 100644 --- a/src/components/channels/channelListItem.tsx +++ b/src/components/channels/channelListItem.tsx @@ -1,31 +1,21 @@ -import { ImageWithFallback } from '@components/imageWithFallback'; - import { DEFAULT_AVATAR } from '@stores/constants'; import { useChannelMetadata } from '@utils/hooks/useChannelMetadata'; -import Link from 'next/link'; - export const ChannelListItem = ({ data }: { data: any }) => { const channel = useChannelMetadata(data.event_id, data.metadata); return ( - -
- +
+ {data.event_id}
{channel?.name.toLowerCase()}
- + ); }; diff --git a/src/components/chats/chatList.tsx b/src/components/chats/chatList.tsx index 726bdf47..65bbacf1 100644 --- a/src/components/chats/chatList.tsx +++ b/src/components/chats/chatList.tsx @@ -1,13 +1,11 @@ import { ChatListItem } from '@components/chats/chatListItem'; import { ChatModal } from '@components/chats/chatModal'; -import { ImageWithFallback } from '@components/imageWithFallback'; import { DEFAULT_AVATAR } from '@stores/constants'; import { getChats } from '@utils/storage'; import useLocalStorage from '@rehooks/local-storage'; -import Link from 'next/link'; import { useEffect, useState } from 'react'; export default function ChatList() { @@ -33,17 +31,15 @@ export default function ChatList() { return (
- -
- + {activeAccount.pubkey}
@@ -51,7 +47,7 @@ export default function ChatList() { {profile?.display_name || profile?.name} (you)
- + {list.map((item) => ( ))} diff --git a/src/components/chats/chatListItem.tsx b/src/components/chats/chatListItem.tsx index 1e58c7ce..32cdc1ab 100644 --- a/src/components/chats/chatListItem.tsx +++ b/src/components/chats/chatListItem.tsx @@ -1,34 +1,24 @@ -import { ImageWithFallback } from '@components/imageWithFallback'; - import { DEFAULT_AVATAR } from '@stores/constants'; import { useProfileMetadata } from '@utils/hooks/useProfileMetadata'; import { shortenKey } from '@utils/shortenKey'; -import Link from 'next/link'; - export const ChatListItem = ({ pubkey }: { pubkey: string }) => { const profile = useProfileMetadata(pubkey); return ( - -
- +
+ {pubkey}
{profile?.display_name || profile?.name || shortenKey(pubkey)}
- + ); }; diff --git a/src/components/chats/chatModalUser.tsx b/src/components/chats/chatModalUser.tsx index bf2cbbf9..c211c65e 100644 --- a/src/components/chats/chatModalUser.tsx +++ b/src/components/chats/chatModalUser.tsx @@ -1,28 +1,24 @@ -import { ImageWithFallback } from '@components/imageWithFallback'; - import { DEFAULT_AVATAR } from '@stores/constants'; import { shortenKey } from '@utils/shortenKey'; -import { useRouter } from 'next/navigation'; +import { navigate } from 'vite-plugin-ssr/client/router'; export const ChatModalUser = ({ data }: { data: any }) => { - const router = useRouter(); const profile = JSON.parse(data.metadata); const openNewChat = () => { - router.push(`/nostr/chat?pubkey=${data.pubkey}`, { forceOptimisticNavigation: true }); + navigate(`/chat?pubkey=${data.pubkey}`); }; return (
-
- + {data.pubkey}
diff --git a/src/components/chats/messageUser.tsx b/src/components/chats/messageUser.tsx index 4c632014..5b3a903a 100644 --- a/src/components/chats/messageUser.tsx +++ b/src/components/chats/messageUser.tsx @@ -1,5 +1,3 @@ -import { ImageWithFallback } from '@components/imageWithFallback'; - import { DEFAULT_AVATAR } from '@stores/constants'; import { useProfileMetadata } from '@utils/hooks/useProfileMetadata'; @@ -15,13 +13,8 @@ export const MessageUser = ({ pubkey, time }: { pubkey: string; time: number }) return (
-
- +
+ {pubkey}
diff --git a/src/components/eventCollector.tsx b/src/components/eventCollector.tsx index 54a833fa..e402d962 100644 --- a/src/components/eventCollector.tsx +++ b/src/components/eventCollector.tsx @@ -1,5 +1,3 @@ -'use client'; - import { NetworkStatusIndicator } from '@components/networkStatusIndicator'; import { RelayContext } from '@components/relaysProvider'; diff --git a/src/components/form/emojiPicker.tsx b/src/components/form/emojiPicker.tsx deleted file mode 100644 index e48802cc..00000000 --- a/src/components/form/emojiPicker.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { noteContentAtom } from '@stores/note'; - -import data from '@emoji-mart/data'; -import Picker from '@emoji-mart/react'; -import * as Popover from '@radix-ui/react-popover'; -import { Emoji } from 'iconoir-react'; -import { useAtom } from 'jotai'; - -export default function EmojiPicker() { - const [value, setValue] = useAtom(noteContentAtom); - - return ( - - - - - - - setValue(value + ' ' + res.native)} - /> - - - - - ); -} diff --git a/src/components/imageWithFallback.tsx b/src/components/imageWithFallback.tsx deleted file mode 100644 index dcf3ed97..00000000 --- a/src/components/imageWithFallback.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { DEFAULT_AVATAR } from '@stores/constants'; - -import Image from 'next/image'; -import { memo, useEffect, useState } from 'react'; - -export const ImageWithFallback = memo(function ImageWithFallback({ - src, - alt, - fill, - className, -}: { - src: string; - alt: string; - fill: boolean; - className: string; -}) { - const [error, setError] = useState(null); - - useEffect(() => { - setError(null); - }, [src]); - - return ( - {alt} - ); -}); diff --git a/src/app/nostr/layout.tsx b/src/components/layouts/newsfeed.tsx similarity index 95% rename from src/app/nostr/layout.tsx rename to src/components/layouts/newsfeed.tsx index 0da145e3..563fc421 100644 --- a/src/app/nostr/layout.tsx +++ b/src/components/layouts/newsfeed.tsx @@ -2,7 +2,7 @@ import AppHeader from '@components/appHeader'; import MultiAccounts from '@components/multiAccounts'; import Navigation from '@components/navigation'; -export default function NostrLayout({ children }: { children: React.ReactNode }) { +export default function NewsfeedLayout({ children }: { children: React.ReactNode }) { return (
diff --git a/src/app/onboarding/layout.tsx b/src/components/layouts/onboarding.tsx similarity index 100% rename from src/app/onboarding/layout.tsx rename to src/components/layouts/onboarding.tsx diff --git a/src/components/link.tsx b/src/components/link.tsx new file mode 100644 index 00000000..93b3181c --- /dev/null +++ b/src/components/link.tsx @@ -0,0 +1,12 @@ +import { usePageContext } from '@utils/hooks/usePageContext'; + +import { AnchorHTMLAttributes, ClassAttributes } from 'react'; + +export function Link( + props: JSX.IntrinsicAttributes & ClassAttributes & AnchorHTMLAttributes, + activeClass: string +) { + const pageContext = usePageContext(); + const className = [props.className, pageContext.urlPathname === props.href && activeClass].filter(Boolean).join(' '); + return ; +} diff --git a/src/components/multiAccounts/activeAccount.tsx b/src/components/multiAccounts/activeAccount.tsx index 90cdc165..a1aca932 100644 --- a/src/components/multiAccounts/activeAccount.tsx +++ b/src/components/multiAccounts/activeAccount.tsx @@ -1,20 +1,16 @@ -'use client'; - import { DEFAULT_AVATAR } from '@stores/constants'; import * as DropdownMenu from '@radix-ui/react-dropdown-menu'; import { writeText } from '@tauri-apps/api/clipboard'; import { LogOut, ProfileCircle, Settings } from 'iconoir-react'; -import Image from 'next/image'; -import { useRouter } from 'next/navigation'; import { nip19 } from 'nostr-tools'; +import { navigate } from 'vite-plugin-ssr/client/router'; export const ActiveAccount = ({ user }: { user: any }) => { - const router = useRouter(); const userData = JSON.parse(user.metadata); const openProfilePage = () => { - router.push(`/nostr/user?pubkey=${user.pubkey}`, { forceOptimisticNavigation: true }); + navigate(`/user?pubkey=${user.pubkey}`); }; const copyPublicKey = async () => { @@ -25,12 +21,10 @@ export const ActiveAccount = ({ user }: { user: any }) => { diff --git a/src/components/multiAccounts/inactiveAccount.tsx b/src/components/multiAccounts/inactiveAccount.tsx index b2d42c6e..ede7d61d 100644 --- a/src/components/multiAccounts/inactiveAccount.tsx +++ b/src/components/multiAccounts/inactiveAccount.tsx @@ -1,6 +1,5 @@ import { DEFAULT_AVATAR } from '@stores/constants'; -import Image from 'next/image'; import { memo } from 'react'; export const InactiveAccount = memo(function InactiveAccount({ user }: { user: any }) { @@ -12,13 +11,7 @@ export const InactiveAccount = memo(function InactiveAccount({ user }: { user: a return ( ); }); diff --git a/src/components/multiAccounts/index.tsx b/src/components/multiAccounts/index.tsx index 853b1623..734d258b 100644 --- a/src/components/multiAccounts/index.tsx +++ b/src/components/multiAccounts/index.tsx @@ -1,5 +1,3 @@ -'use client'; - import { ActiveAccount } from '@components/multiAccounts/activeAccount'; import { InactiveAccount } from '@components/multiAccounts/inactiveAccount'; @@ -11,7 +9,6 @@ import LumeSymbol from '@assets/icons/Lume'; import useLocalStorage from '@rehooks/local-storage'; import { Plus } from 'iconoir-react'; -import Link from 'next/link'; import { useCallback, useEffect, useState } from 'react'; export default function MultiAccounts() { @@ -38,21 +35,19 @@ export default function MultiAccounts() { return (
- - +
{users.map((user) => renderAccount(user))}
- - +
diff --git a/src/components/navigation/channels.tsx b/src/components/navigation/channels.tsx index e005c856..952c0cb5 100644 --- a/src/components/navigation/channels.tsx +++ b/src/components/navigation/channels.tsx @@ -1,5 +1,3 @@ -'use client'; - import ChannelList from '@components/channels/channelList'; import * as Collapsible from '@radix-ui/react-collapsible'; diff --git a/src/components/navigation/chats.tsx b/src/components/navigation/chats.tsx index db5f8c56..ae882c87 100644 --- a/src/components/navigation/chats.tsx +++ b/src/components/navigation/chats.tsx @@ -1,5 +1,3 @@ -'use client'; - import ChatList from '@components/chats/chatList'; import * as Collapsible from '@radix-ui/react-collapsible'; diff --git a/src/components/navigation/newsfeed.tsx b/src/components/navigation/newsfeed.tsx index 1327e511..1efb5d3b 100644 --- a/src/components/navigation/newsfeed.tsx +++ b/src/components/navigation/newsfeed.tsx @@ -1,7 +1,3 @@ -'use client'; - -import { ActiveLink } from '@components/activeLink'; - import * as Collapsible from '@radix-ui/react-collapsible'; import { Bonfire, NavArrowUp, PeopleTag } from 'iconoir-react'; import { useState } from 'react'; @@ -23,22 +19,22 @@ export default function Newsfeed() {

Newsfeed

- Following - - + Circle - +
diff --git a/src/components/note/base.tsx b/src/components/note/base.tsx index 42856031..3b33eae4 100644 --- a/src/components/note/base.tsx +++ b/src/components/note/base.tsx @@ -4,11 +4,10 @@ import { UserExtend } from '@components/user/extend'; import { contentParser } from '@utils/parser'; -import { useRouter } from 'next/navigation'; import { memo } from 'react'; +import { navigate } from 'vite-plugin-ssr/client/router'; export const NoteBase = memo(function NoteBase({ event }: { event: any }) { - const router = useRouter(); const content = contentParser(event.content, event.tags); const parentNote = () => { @@ -22,13 +21,13 @@ export const NoteBase = memo(function NoteBase({ event }: { event: any }) { const openUserPage = (e) => { e.stopPropagation(); - router.push(`/nostr/user?pubkey=${event.pubkey}`, { forceOptimisticNavigation: true }); + navigate(`/user?pubkey=${event.pubkey}`); }; const openThread = (e) => { const selection = window.getSelection(); if (selection.toString().length === 0) { - router.push(`/nostr/newsfeed/note?id=${event.parent_id}`, { forceOptimisticNavigation: true }); + navigate(`/newsfeed/note?id=${event.parent_id}`); } else { e.stopPropagation(); } diff --git a/src/components/note/meta/comment.tsx b/src/components/note/meta/comment.tsx index 8e5717c4..4e2a40d1 100644 --- a/src/components/note/meta/comment.tsx +++ b/src/components/note/meta/comment.tsx @@ -1,4 +1,3 @@ -import { ImageWithFallback } from '@components/imageWithFallback'; import { RelayContext } from '@components/relaysProvider'; import { UserExtend } from '@components/user/extend'; @@ -7,9 +6,9 @@ import { dateToUnix } from '@utils/getDate'; import * as Dialog from '@radix-ui/react-dialog'; import useLocalStorage from '@rehooks/local-storage'; import { ChatLines, OpenNewWindow } from 'iconoir-react'; -import { useRouter } from 'next/navigation'; import { getEventHash, signEvent } from 'nostr-tools'; import { useContext, useState } from 'react'; +import { navigate } from 'vite-plugin-ssr/client/router'; export const NoteComment = ({ count, @@ -24,7 +23,6 @@ export const NoteComment = ({ eventTime: number; eventContent: any; }) => { - const router = useRouter(); const [pool, relays]: any = useContext(RelayContext); const [open, setOpen] = useState(false); @@ -34,7 +32,7 @@ export const NoteComment = ({ const profile = activeAccount.metadata ? JSON.parse(activeAccount.metadata) : null; const openThread = () => { - router.push(`/nostr/newsfeed/note?id=${eventID}`, { forceOptimisticNavigation: true }); + navigate(`/newsfeed/note?id=${eventID}`); }; const submitEvent = () => { @@ -84,12 +82,7 @@ export const NoteComment = ({
- + user's avatar
diff --git a/src/components/note/preview/image.tsx b/src/components/note/preview/image.tsx index 0ec989d4..60327fd1 100644 --- a/src/components/note/preview/image.tsx +++ b/src/components/note/preview/image.tsx @@ -1,18 +1,9 @@ -import Image from 'next/image'; import { memo } from 'react'; export const ImagePreview = memo(function ImagePreview({ url, size }: { url: string; size: string }) { return (
- {url} + {url}
); }); diff --git a/src/components/note/preview/link.tsx b/src/components/note/preview/link.tsx deleted file mode 100644 index d1064231..00000000 --- a/src/components/note/preview/link.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import Image from 'next/image'; -import Link from 'next/link'; - -export default function LinkCard({ data }: { data: any }) { - return ( - -
- image preview -
-
-
-
{data['title']}
-

{data['description']}

-
- {data['url']} -
- - ); -} diff --git a/src/components/note/rootNote.tsx b/src/components/note/rootNote.tsx index a3678207..f09e5b18 100644 --- a/src/components/note/rootNote.tsx +++ b/src/components/note/rootNote.tsx @@ -4,11 +4,10 @@ import { UserExtend } from '@components/user/extend'; import { contentParser } from '@utils/parser'; -import { useRouter } from 'next/navigation'; import { memo, useCallback, useContext, useEffect, useState } from 'react'; +import { navigate } from 'vite-plugin-ssr/client/router'; export const RootNote = memo(function RootNote({ event }: { event: any }) { - const router = useRouter(); const [pool, relays]: any = useContext(RelayContext); const [data, setData] = useState(null); @@ -16,13 +15,13 @@ export const RootNote = memo(function RootNote({ event }: { event: any }) { const openUserPage = (e) => { e.stopPropagation(); - router.push(`/nostr/user?pubkey=${event.pubkey}`, { forceOptimisticNavigation: true }); + navigate(`/user?pubkey=${event.pubkey}`); }; const openThread = (e) => { const selection = window.getSelection(); if (selection.toString().length === 0) { - router.push(`/nostr/newsfeed/note?id=${event.parent_id}`, { forceOptimisticNavigation: true }); + navigate(`/newsfeed/note?id=${event.parent_id}`); } else { e.stopPropagation(); } diff --git a/src/components/profile/followers.tsx b/src/components/profile/followers.tsx index ef03f58f..5645b764 100644 --- a/src/components/profile/followers.tsx +++ b/src/components/profile/followers.tsx @@ -1,5 +1,3 @@ -'use client'; - import { RelayContext } from '@components/relaysProvider'; import { UserFollow } from '@components/user/follow'; diff --git a/src/components/profile/follows.tsx b/src/components/profile/follows.tsx index 7b807a03..14cda816 100644 --- a/src/components/profile/follows.tsx +++ b/src/components/profile/follows.tsx @@ -1,5 +1,3 @@ -'use client'; - import { RelayContext } from '@components/relaysProvider'; import { UserFollow } from '@components/user/follow'; diff --git a/src/components/profile/metadata.tsx b/src/components/profile/metadata.tsx index 3d5a1ea6..bc0e24e5 100644 --- a/src/components/profile/metadata.tsx +++ b/src/components/profile/metadata.tsx @@ -1,6 +1,3 @@ -'use client'; - -import { ImageWithFallback } from '@components/imageWithFallback'; import { RelayContext } from '@components/relaysProvider'; import { DEFAULT_AVATAR } from '@stores/constants'; @@ -8,7 +5,6 @@ import { DEFAULT_AVATAR } from '@stores/constants'; import { shortenKey } from '@utils/shortenKey'; import destr from 'destr'; -import Image from 'next/image'; import { Author } from 'nostr-relaypool'; import { useContext, useEffect, useState } from 'react'; @@ -27,21 +23,11 @@ export default function ProfileMetadata({ id }: { id: string }) { <>
- user's banner + user's banner
- + {id}
diff --git a/src/components/profile/notes.tsx b/src/components/profile/notes.tsx index 11ab6d06..d1a315c2 100644 --- a/src/components/profile/notes.tsx +++ b/src/components/profile/notes.tsx @@ -1,5 +1,3 @@ -'use client'; - import { NoteBase } from '@components/note/base'; import { RelayContext } from '@components/relaysProvider'; diff --git a/src/components/relaysProvider.tsx b/src/components/relaysProvider.tsx index 72c5d0cc..2ae54ff7 100644 --- a/src/components/relaysProvider.tsx +++ b/src/components/relaysProvider.tsx @@ -1,5 +1,3 @@ -'use client'; - import { DEFAULT_RELAYS } from '@stores/constants'; import { RelayPool } from 'nostr-relaypool'; diff --git a/src/components/user/base.tsx b/src/components/user/base.tsx index 0d363ee2..9464bec2 100644 --- a/src/components/user/base.tsx +++ b/src/components/user/base.tsx @@ -1,5 +1,3 @@ -import { ImageWithFallback } from '@components/imageWithFallback'; - import { DEFAULT_AVATAR } from '@stores/constants'; import { useProfileMetadata } from '@utils/hooks/useProfileMetadata'; @@ -13,12 +11,7 @@ export const UserBase = memo(function UserBase({ pubkey }: { pubkey: string }) { return (
- + {pubkey}
diff --git a/src/components/user/extend.tsx b/src/components/user/extend.tsx index 1beb204a..0311adcc 100644 --- a/src/components/user/extend.tsx +++ b/src/components/user/extend.tsx @@ -1,5 +1,3 @@ -import { ImageWithFallback } from '@components/imageWithFallback'; - import { DEFAULT_AVATAR } from '@stores/constants'; import { useProfileMetadata } from '@utils/hooks/useProfileMetadata'; @@ -16,12 +14,7 @@ export const UserExtend = ({ pubkey, time }: { pubkey: string; time: number }) = return (
- + {pubkey}
diff --git a/src/components/user/follow.tsx b/src/components/user/follow.tsx index 3942f561..0b4337be 100644 --- a/src/components/user/follow.tsx +++ b/src/components/user/follow.tsx @@ -1,5 +1,3 @@ -import { ImageWithFallback } from '@components/imageWithFallback'; - import { DEFAULT_AVATAR } from '@stores/constants'; import { useProfileMetadata } from '@utils/hooks/useProfileMetadata'; @@ -11,12 +9,7 @@ export const UserFollow = ({ pubkey }: { pubkey: string }) => { return (
- + {pubkey}
diff --git a/src/components/user/large.tsx b/src/components/user/large.tsx index c060578f..3fd0ac80 100644 --- a/src/components/user/large.tsx +++ b/src/components/user/large.tsx @@ -1,5 +1,3 @@ -import { ImageWithFallback } from '@components/imageWithFallback'; - import { DEFAULT_AVATAR } from '@stores/constants'; import { useProfileMetadata } from '@utils/hooks/useProfileMetadata'; @@ -17,11 +15,10 @@ export const UserLarge = ({ pubkey, time }: { pubkey: string; time: number }) => return (
-
diff --git a/src/components/user/mini.tsx b/src/components/user/mini.tsx index e4191755..5423f6a0 100644 --- a/src/components/user/mini.tsx +++ b/src/components/user/mini.tsx @@ -1,5 +1,3 @@ -import { ImageWithFallback } from '@components/imageWithFallback'; - import { DEFAULT_AVATAR } from '@stores/constants'; import { useProfileMetadata } from '@utils/hooks/useProfileMetadata'; @@ -11,12 +9,7 @@ export const UserMini = ({ pubkey }: { pubkey: string }) => { return (
- + {pubkey}
Replying to {profile?.name || shortenKey(pubkey)} diff --git a/src/components/user/quoteRepost.tsx b/src/components/user/quoteRepost.tsx index f240c7e4..956c7742 100644 --- a/src/components/user/quoteRepost.tsx +++ b/src/components/user/quoteRepost.tsx @@ -1,5 +1,3 @@ -import { ImageWithFallback } from '@components/imageWithFallback'; - import { DEFAULT_AVATAR } from '@stores/constants'; import { useProfileMetadata } from '@utils/hooks/useProfileMetadata'; @@ -16,12 +14,7 @@ export const UserQuoteRepost = ({ pubkey, time }: { pubkey: string; time: number return (
- + {pubkey}
diff --git a/src/app/nostr/channel/page.tsx b/src/pages/channel/index.page.tsx similarity index 82% rename from src/app/nostr/channel/page.tsx rename to src/pages/channel/index.page.tsx index ba83d9d8..f25ff292 100644 --- a/src/app/nostr/channel/page.tsx +++ b/src/pages/channel/index.page.tsx @@ -1,24 +1,25 @@ -'use client'; - import { ChannelMessages } from '@components/channels/messages'; import { FormChannel } from '@components/form/channel'; +import NewsfeedLayout from '@components/layouts/newsfeed'; import { RelayContext } from '@components/relaysProvider'; import { channelMessagesAtom, channelReplyAtom } from '@stores/channel'; import { FULL_RELAYS } from '@stores/constants'; import { dateToUnix, hoursAgo } from '@utils/getDate'; +import { usePageContext } from '@utils/hooks/usePageContext'; import useLocalStorage from '@rehooks/local-storage'; import { useSetAtom } from 'jotai'; import { useResetAtom } from 'jotai/utils'; -import { useSearchParams } from 'next/navigation'; import { useContext, useEffect, useRef } from 'react'; import useSWRSubscription from 'swr/subscription'; -export default function Page() { - const searchParams = useSearchParams(); - const id = searchParams.get('channel-id'); +export function Page() { + const pageContext = usePageContext(); + const searchParams: any = pageContext.urlParsed.search; + + const id = searchParams.id; const [pool]: any = useContext(RelayContext); const [activeAccount]: any = useLocalStorage('account', {}); @@ -84,11 +85,13 @@ export default function Page() { }, [resetChannelReply, resetChannelMessages]); return ( -
- -
- + +
+ +
+ +
-
+ ); } diff --git a/src/app/nostr/chat/page.tsx b/src/pages/chat/index.page.tsx similarity index 73% rename from src/app/nostr/chat/page.tsx rename to src/pages/chat/index.page.tsx index 57865643..30915591 100644 --- a/src/app/nostr/chat/page.tsx +++ b/src/pages/chat/index.page.tsx @@ -1,22 +1,24 @@ -'use client'; - import { MessageList } from '@components/chats/messageList'; import FormChat from '@components/form/chat'; +import NewsfeedLayout from '@components/layouts/newsfeed'; import { RelayContext } from '@components/relaysProvider'; import { chatMessagesAtom } from '@stores/chat'; import { FULL_RELAYS } from '@stores/constants'; +import { usePageContext } from '@utils/hooks/usePageContext'; + import useLocalStorage from '@rehooks/local-storage'; import { useSetAtom } from 'jotai'; import { useResetAtom } from 'jotai/utils'; -import { useSearchParams } from 'next/navigation'; import { useContext, useEffect } from 'react'; import useSWRSubscription from 'swr/subscription'; -export default function Page() { - const searchParams = useSearchParams(); - const pubkey = searchParams.get('pubkey'); +export function Page() { + const pageContext = usePageContext(); + const searchParams: any = pageContext.urlParsed.search; + + const pubkey = searchParams.pubkey; const [pool]: any = useContext(RelayContext); const [activeAccount]: any = useLocalStorage('account', {}); @@ -62,11 +64,13 @@ export default function Page() { }, [resetChatMessages]); return ( -
- -
- + +
+ +
+ +
-
+ ); } diff --git a/src/app/page.tsx b/src/pages/index.page.tsx similarity index 86% rename from src/app/page.tsx rename to src/pages/index.page.tsx index 7647f8b8..299aea41 100644 --- a/src/app/page.tsx +++ b/src/pages/index.page.tsx @@ -1,5 +1,3 @@ -'use client'; - import { RelayContext } from '@components/relaysProvider'; import { dateToUnix, hoursAgo } from '@utils/getDate'; @@ -19,11 +17,10 @@ import { getParentID } from '@utils/transform'; import LumeSymbol from '@assets/icons/Lume'; import { writeStorage } from '@rehooks/local-storage'; -import { useRouter } from 'next/navigation'; import { useCallback, useContext, useEffect, useRef } from 'react'; +import { navigate } from 'vite-plugin-ssr/client/router'; -export default function Page() { - const router = useRouter(); +export function Page() { const [pool, relays]: any = useContext(RelayContext); const now = useRef(new Date()); @@ -126,7 +123,7 @@ export default function Page() { () => { updateLastLogin(dateToUnix(now.current)); timeout.current = setTimeout(() => { - router.replace('/nostr/newsfeed/following', { forceOptimisticNavigation: true }); + navigate('/newsfeed/following', { overwriteLastHistoryEntry: true }); }, 5000); }, { @@ -139,39 +136,41 @@ export default function Page() { unsubscribe(); }; }, - [router, pool, relays] + [pool, relays] ); useEffect(() => { let ignore = false; - getPlebs() - .then((res) => { - if (res && !ignore) { - writeStorage('plebs', res); - } - }) - .catch(console.error); + if (!ignore) { + getActiveAccount() + .then((res: any) => { + if (res) { + const account = res; + // update local storage + writeStorage('account', account); + // fetch data + fetchData(account, account.follows); + } else { + navigate('/onboarding', { overwriteLastHistoryEntry: true }); + } + }) + .catch(console.error); - getActiveAccount() - .then((res: any) => { - if (res && !ignore) { - const account = res; - // update local storage - writeStorage('account', account); - // fetch data - fetchData(account, account.follows); - } else { - router.replace('/onboarding', { forceOptimisticNavigation: true }); - } - }) - .catch(console.error); + getPlebs() + .then((res) => { + if (res && !ignore) { + writeStorage('plebs', res); + } + }) + .catch(console.error); + } return () => { ignore = true; clearTimeout(timeout.current); }; - }, [fetchData, router]); + }, [fetchData]); return (
diff --git a/src/pages/newsfeed/circle/index.page.tsx b/src/pages/newsfeed/circle/index.page.tsx new file mode 100644 index 00000000..e7c8b9ac --- /dev/null +++ b/src/pages/newsfeed/circle/index.page.tsx @@ -0,0 +1,3 @@ +export function Page() { + return <>; +} diff --git a/src/app/nostr/newsfeed/following/page.tsx b/src/pages/newsfeed/following/index.page.tsx similarity index 71% rename from src/app/nostr/newsfeed/following/page.tsx rename to src/pages/newsfeed/following/index.page.tsx index 8f5ce5f9..ef48d400 100644 --- a/src/app/nostr/newsfeed/following/page.tsx +++ b/src/pages/newsfeed/following/index.page.tsx @@ -1,6 +1,5 @@ -'use client'; - import FormBase from '@components/form/base'; +import NewsfeedLayout from '@components/layouts/newsfeed'; import { NoteBase } from '@components/note/base'; import { Placeholder } from '@components/note/placeholder'; import { NoteQuoteRepost } from '@components/note/quoteRepost'; @@ -15,7 +14,7 @@ import { useAtom, useAtomValue, useSetAtom } from 'jotai'; import { useCallback, useEffect, useRef } from 'react'; import { Virtuoso } from 'react-virtuoso'; -export default function Page() { +export function Page() { const [hasNewerNote, setHasNewerNote] = useAtom(hasNewerNoteAtom); const setData = useSetAtom(notesAtom); const data = useAtomValue(filteredNotesAtom); @@ -82,29 +81,31 @@ export default function Page() { }, [initialData]); return ( -
- {hasNewerNote && ( -
- -
- )} - -
+ +
+ {hasNewerNote && ( +
+ +
+ )} + +
+
); } diff --git a/src/pages/onboarding/create/index.page.tsx b/src/pages/onboarding/create/index.page.tsx new file mode 100644 index 00000000..bf8f452b --- /dev/null +++ b/src/pages/onboarding/create/index.page.tsx @@ -0,0 +1,172 @@ +import OnboardingLayout from '@components/layouts/onboarding'; +import { RelayContext } from '@components/relaysProvider'; + +import { createAccount } from '@utils/storage'; + +import { EyeClose, EyeEmpty } from 'iconoir-react'; +import { generatePrivateKey, getEventHash, getPublicKey, nip19, signEvent } from 'nostr-tools'; +import { useCallback, useContext, useMemo, useState } from 'react'; +import { Config, names, uniqueNamesGenerator } from 'unique-names-generator'; +import { navigate } from 'vite-plugin-ssr/client/router'; + +const config: Config = { + dictionaries: [names], +}; + +export function Page() { + const [pool, relays]: any = useContext(RelayContext); + + const [type, setType] = useState('password'); + const [loading, setLoading] = useState(false); + + const privkey = useMemo(() => generatePrivateKey(), []); + const name = useMemo(() => uniqueNamesGenerator(config).toString(), []); + + const pubkey = getPublicKey(privkey); + const npub = nip19.npubEncode(pubkey); + const nsec = nip19.nsecEncode(privkey); + + // auto-generated profile metadata + const metadata: any = useMemo( + () => ({ + display_name: name, + name: name, + username: name.toLowerCase(), + picture: 'https://void.cat/d/KmypFh2fBdYCEvyJrPiN89.webp', + }), + [name] + ); + + // toggle privatek key + const showPrivateKey = () => { + if (type === 'password') { + setType('text'); + } else { + setType('password'); + } + }; + + // create account and broadcast to all relays + const submit = useCallback(async () => { + setLoading(true); + + // build event + const event: any = { + content: JSON.stringify(metadata), + created_at: Math.floor(Date.now() / 1000), + kind: 0, + pubkey: pubkey, + tags: [], + }; + event.id = getEventHash(event); + event.sig = signEvent(event, privkey); + // insert to database + createAccount(pubkey, privkey, metadata); + // broadcast + pool.publish(event, relays); + // redirect to next step + navigate(`/onboarding/create/step-2?pubkey=${pubkey}&privkey=${privkey}`); + }, [pool, pubkey, privkey, metadata, relays]); + + return ( + +
+
+

+ Create new account +

+
+
+
+
+
+ +
+ +
+
+
+ +
+ + +
+
+
+ +
+
+
+
+ default avatar +
+
+
+

{metadata.display_name}

+

@{metadata.username}

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {loading === true ? ( + + + + + ) : ( + + )} +
+
+
+
+
+ ); +} diff --git a/src/app/onboarding/create/step-2/page.tsx b/src/pages/onboarding/create/step-2/index.page.tsx similarity index 61% rename from src/app/onboarding/create/step-2/page.tsx rename to src/pages/onboarding/create/step-2/index.page.tsx index fd8b992d..d152353b 100644 --- a/src/app/onboarding/create/step-2/page.tsx +++ b/src/pages/onboarding/create/step-2/index.page.tsx @@ -1,17 +1,17 @@ -'use client'; - +import OnboardingLayout from '@components/layouts/onboarding'; import { RelayContext } from '@components/relaysProvider'; import { UserBase } from '@components/user/base'; +import { usePageContext } from '@utils/hooks/usePageContext'; import { fetchProfileMetadata } from '@utils/hooks/useProfileMetadata'; import { createPleb, updateAccount } from '@utils/storage'; import { arrayToNIP02 } from '@utils/transform'; import { createClient } from '@supabase/supabase-js'; import { CheckCircle } from 'iconoir-react'; -import { useRouter, useSearchParams } from 'next/navigation'; import { getEventHash, signEvent } from 'nostr-tools'; import { Key, useCallback, useContext, useEffect, useState } from 'react'; +import { navigate } from 'vite-plugin-ssr/client/router'; const supabase = createClient( 'https://niwaazauwnrwiwmnocnn.supabase.co', @@ -53,12 +53,12 @@ const initialList = [ { pubkey: 'ff04a0e6cd80c141b0b55825fed127d4532a6eecdb7e743a38a3c28bf9f44609' }, ]; -export default function Page() { - const router = useRouter(); - const searchParams = useSearchParams(); +export function Page() { + const pageContext = usePageContext(); + const searchParams: any = pageContext.urlParsed.search; - const pubkey = searchParams.get('pubkey'); - const privkey = searchParams.get('privkey'); + const pubkey = searchParams.pubkey; + const privkey = searchParams.privkey; const [pool, relays]: any = useContext(RelayContext); const [loading, setLoading] = useState(false); @@ -100,8 +100,8 @@ export default function Page() { // broadcast pool.publish(event, relays); // redirect to splashscreen - router.replace('/'); - }, [pubkey, privkey, follows, pool, relays, router]); + navigate('/'); + }, [pubkey, privkey, follows, pool, relays]); useEffect(() => { let ignore = false; @@ -122,65 +122,67 @@ export default function Page() { }, []); return ( -
-
-
-

- Personalized your newsfeed -

-

- Follow at least{' '} - - {follows.length}/10 - {' '} - plebs -

+ +
+
+
+

+ Personalized your newsfeed +

+

+ Follow at least{' '} + + {follows.length}/10 + {' '} + plebs +

+
-
-
-
- {list.map((item: { pubkey: string }, index: Key) => ( +
+
+ {list.map((item: { pubkey: string }, index: Key) => ( + + ))} +
+
+ {follows.length >= 10 && ( +
- ))} -
+
+ )}
- {follows.length >= 10 && ( -
- -
- )} -
+ ); } diff --git a/src/app/onboarding/page.tsx b/src/pages/onboarding/index.page.tsx similarity index 61% rename from src/app/onboarding/page.tsx rename to src/pages/onboarding/index.page.tsx index 7a84b156..22bc717d 100644 --- a/src/app/onboarding/page.tsx +++ b/src/pages/onboarding/index.page.tsx @@ -1,6 +1,6 @@ +import OnboardingLayout from '@components/layouts/onboarding'; + import { ArrowRight } from 'iconoir-react'; -import Image from 'next/image'; -import Link from 'next/link'; const PLEBS = [ 'https://133332.xyz/p.jpg', @@ -72,58 +72,47 @@ const InfiniteLoopSlider = ({ children, duration, reverse }: { children: any; du ); }; -export default function Page() { +export function Page() { return ( -
-
-
- {[...new Array(ROWS)].map((_, i) => ( - - {shuffle(PLEBS) - .slice(0, PLEBS_PER_ROW) - .map((tag) => ( -
- {tag} -
- ))} -
- ))} -
+ +
+
+
+ {[...new Array(ROWS)].map((_, i) => ( + + {shuffle(PLEBS) + .slice(0, PLEBS_PER_ROW) + .map((tag) => ( +
+ {tag} +
+ ))} +
+ ))} +
+
+
+
-
-

- Let's start! -

-
- - Create new key - - - - Login with private key - -
-
-
+
); } diff --git a/src/pages/onboarding/login/index.page.tsx b/src/pages/onboarding/login/index.page.tsx new file mode 100644 index 00000000..fdb975dd --- /dev/null +++ b/src/pages/onboarding/login/index.page.tsx @@ -0,0 +1,121 @@ +import OnboardingLayout from '@components/layouts/onboarding'; + +import { CableTag } from 'iconoir-react'; +import { getPublicKey, nip19 } from 'nostr-tools'; +import { Resolver, useForm } from 'react-hook-form'; +import { navigate } from 'vite-plugin-ssr/client/router'; + +type FormValues = { + key: string; +}; + +const resolver: Resolver = async (values) => { + return { + values: values.key ? values : {}, + errors: !values.key + ? { + key: { + type: 'required', + message: 'This is required.', + }, + } + : {}, + }; +}; + +export function Page() { + const { + register, + setError, + handleSubmit, + formState: { errors, isDirty, isValid, isSubmitting }, + } = useForm({ resolver }); + + const onSubmit = async (data: any) => { + try { + let privkey = data['key']; + + if (privkey.substring(0, 4) === 'nsec') { + privkey = nip19.decode(privkey).data; + } + if (typeof getPublicKey(privkey) === 'string') { + navigate(`/onboarding/login/step-2?privkey=${privkey}`); + } + } catch (error) { + setError('key', { + type: 'custom', + message: 'Private Key is invalid, please check again', + }); + } + }; + + return ( + +
+
+

+ Login with Private Key +

+
+
+
+
+
+ {/* #TODO: add function */} + +
+
+
+
+
+
+ or +
+
+
+
+ +
+ {errors.key &&

{errors.key.message}

}
+
+
+
+ {isSubmitting ? ( + + + + + ) : ( + + )} +
+
+
+
+
+ ); +} diff --git a/src/pages/onboarding/login/step-2/index.page.tsx b/src/pages/onboarding/login/step-2/index.page.tsx new file mode 100644 index 00000000..5e52b89d --- /dev/null +++ b/src/pages/onboarding/login/step-2/index.page.tsx @@ -0,0 +1,144 @@ +import OnboardingLayout from '@components/layouts/onboarding'; +import { RelayContext } from '@components/relaysProvider'; + +import { DEFAULT_AVATAR } from '@stores/constants'; + +import { usePageContext } from '@utils/hooks/usePageContext'; +import { fetchProfileMetadata } from '@utils/hooks/useProfileMetadata'; +import { shortenKey } from '@utils/shortenKey'; +import { createAccount, createPleb, updateAccount } from '@utils/storage'; +import { nip02ToArray } from '@utils/transform'; + +import { getPublicKey } from 'nostr-tools'; +import { useCallback, useContext, useEffect, useRef, useState } from 'react'; + +export function Page() { + const pageContext = usePageContext(); + const searchParams = pageContext.urlParsed.search; + + const privkey = searchParams.privkey; + const pubkey = getPublicKey(privkey); + + const [pool, relays]: any = useContext(RelayContext); + const [profile, setProfile] = useState({ metadata: null }); + const [done, setDone] = useState(false); + + const timeout = useRef(null); + + const createPlebs = useCallback(async (tags: string[]) => { + for (const tag of tags) { + fetchProfileMetadata(tag[1]) + .then((res: any) => createPleb(tag[1], res.content)) + .catch(console.error); + } + }, []); + + useEffect(() => { + const unsubscribe = pool.subscribe( + [ + { + kinds: [0, 3], + authors: [pubkey], + }, + ], + relays, + (event: any) => { + if (event.kind === 0) { + // create account + createAccount(pubkey, privkey, event.content); + // update state + setProfile({ + metadata: JSON.parse(event.content), + }); + } else { + if (event.tags.length > 0) { + createPlebs(event.tags); + const arr = nip02ToArray(event.tags); + // update account's folllows with NIP-02 tag list + updateAccount('follows', arr, pubkey); + } + } + }, + undefined, + () => { + timeout.current = setTimeout(() => setDone(true), 5000); + }, + { + unsubscribeOnEose: true, + logAllEvents: false, + } + ); + + return () => { + unsubscribe(); + clearTimeout(timeout.current); + }; + }, [pool, relays, pubkey, privkey, createPlebs]); + + return ( + +
+
+

+ Bringing back your profile... +

+
+
+
+
+
+
+
+ avatar +
+
+
+

{profile.metadata?.display_name || profile.metadata?.name}

+ · +

@{profile.metadata?.username || (pubkey && shortenKey(pubkey))}

+
+
+
+
+
+
+
+
+
+
+
+
+
+ {done === false ? ( + + + + + ) : ( + + Done! Go to newsfeed + + )} +
+
+
+
+
+ ); +} diff --git a/src/pages/user/index.page.tsx b/src/pages/user/index.page.tsx new file mode 100644 index 00000000..c35af46f --- /dev/null +++ b/src/pages/user/index.page.tsx @@ -0,0 +1,57 @@ +'use client'; + +import NewsfeedLayout from '@components/layouts/newsfeed'; +import ProfileFollowers from '@components/profile/followers'; +import ProfileFollows from '@components/profile/follows'; +import ProfileMetadata from '@components/profile/metadata'; +import ProfileNotes from '@components/profile/notes'; + +import { usePageContext } from '@utils/hooks/usePageContext'; + +import * as Tabs from '@radix-ui/react-tabs'; + +export function Page() { + const pageContext = usePageContext(); + const searchParams: any = pageContext.urlParsed.search; + + const pubkey = searchParams.pubkey; + + return ( + +
+ + + + + Notes + + + Followers + + + Following + + + + + + + + + + + + +
+
+ ); +} diff --git a/src/renderer/_default.page.client.tsx b/src/renderer/_default.page.client.tsx new file mode 100644 index 00000000..a82fd1b7 --- /dev/null +++ b/src/renderer/_default.page.client.tsx @@ -0,0 +1,20 @@ +import '@renderer/index.css'; +import { Shell } from '@renderer/shell'; +import { PageContextClient } from '@renderer/types'; + +import { hydrateRoot } from 'react-dom/client'; + +export const clientRouting = true; + +export async function render(pageContext: PageContextClient) { + const { Page, pageProps } = pageContext; + + if (!Page) throw new Error('Client-side render() hook expects pageContext.Page to be defined'); + + hydrateRoot( + document.getElementById('app')!, + + + + ); +} diff --git a/src/renderer/_default.page.server.tsx b/src/renderer/_default.page.server.tsx new file mode 100644 index 00000000..79018e03 --- /dev/null +++ b/src/renderer/_default.page.server.tsx @@ -0,0 +1,30 @@ +import { Shell } from '@renderer/shell'; +import { PageContextServer } from '@renderer/types'; + +import ReactDOMServer from 'react-dom/server'; +import { dangerouslySkipEscape, escapeInject } from 'vite-plugin-ssr/server'; + +export const passToClient = ['pageProps']; + +export function render(pageContext: PageContextServer) { + const { Page, pageProps } = pageContext; + + if (!Page) throw new Error('My render() hook expects pageContext.Page to be defined'); + + const pageHtml = ReactDOMServer.renderToString( + + + + ); + + return escapeInject` + + + + + + +
${dangerouslySkipEscape(pageHtml)}
+ + `; +} diff --git a/src/renderer/_error.page.tsx b/src/renderer/_error.page.tsx new file mode 100644 index 00000000..73711c64 --- /dev/null +++ b/src/renderer/_error.page.tsx @@ -0,0 +1,17 @@ +export function Page({ is404 }: { is404: boolean }) { + if (is404) { + return ( + <> +

404 Page Not Found

+

This page could not be found.

+ + ); + } else { + return ( + <> +

500 Internal Server Error

+

Something went wrong.

+ + ); + } +} diff --git a/src/index.css b/src/renderer/index.css similarity index 100% rename from src/index.css rename to src/renderer/index.css diff --git a/src/renderer/shell.tsx b/src/renderer/shell.tsx new file mode 100644 index 00000000..d16efe11 --- /dev/null +++ b/src/renderer/shell.tsx @@ -0,0 +1,17 @@ +import RelayProvider from '@components/relaysProvider'; + +import { PageContextProvider } from '@utils/hooks/usePageContext'; + +import { PageContext } from '@renderer/types'; + +import { StrictMode } from 'react'; + +export function Shell({ children, pageContext }: { children: React.ReactNode; pageContext: PageContext }) { + return ( + + + {children} + + + ); +} diff --git a/src/renderer/types.ts b/src/renderer/types.ts new file mode 100644 index 00000000..105b060b --- /dev/null +++ b/src/renderer/types.ts @@ -0,0 +1,35 @@ +import type { + PageContextBuiltIn, + /* +// When using Client Routing https://vite-plugin-ssr.com/clientRouting +PageContextBuiltInClientWithClientRouting as PageContextBuiltInClient +/*/ + // When using Server Routing + PageContextBuiltInClientWithServerRouting as PageContextBuiltInClient, //*/ +} from 'vite-plugin-ssr/types'; + +export type { PageContextServer }; +export type { PageContextClient }; +export type { PageContext }; +export type { PageProps }; + +type Page = (pageProps: PageProps) => React.ReactElement; +type PageProps = Record; + +export type PageContextCustom = { + Page: Page; + pageProps?: PageProps; + redirectTo?: string; + urlPathname: string; + exports: { + documentProps?: { + title?: string; + description?: string; + }; + }; +}; + +type PageContextServer = PageContextBuiltIn & PageContextCustom; +type PageContextClient = PageContextBuiltInClient & PageContextCustom; + +type PageContext = PageContextClient | PageContextServer; diff --git a/src/utils/hooks/usePageContext.tsx b/src/utils/hooks/usePageContext.tsx new file mode 100644 index 00000000..a1303f6b --- /dev/null +++ b/src/utils/hooks/usePageContext.tsx @@ -0,0 +1,22 @@ +// `usePageContext` allows us to access `pageContext` in any React component. +// See https://vite-plugin-ssr.com/pageContext-anywhere +import type { PageContext } from '@renderer/types'; + +import { createContext, useContext } from 'react'; + +const Context = createContext(undefined as any); + +export function PageContextProvider({ + pageContext, + children, +}: { + pageContext: PageContext; + children: React.ReactNode; +}) { + return {children}; +} + +export function usePageContext() { + const pageContext = useContext(Context); + return pageContext; +} diff --git a/tsconfig.json b/tsconfig.json index fc672f7d..95493d99 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,8 @@ "@components/*": ["src/components/*"], "@stores/*": ["src/stores/*"], "@utils/*": ["src/utils/*"], - "@assets/*": ["src/assets/*"] + "@assets/*": ["src/assets/*"], + "@renderer/*": ["src/renderer/*"] }, "target": "es2017", "lib": ["dom", "dom.iterable", "esnext"], diff --git a/vite.config.ts b/vite.config.ts index 27c24e7e..b78d40d1 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -4,5 +4,5 @@ import ssr from 'vite-plugin-ssr/plugin'; import viteTsconfigPaths from 'vite-tsconfig-paths'; export default defineConfig({ - plugins: [react(), ssr(), viteTsconfigPaths()], + plugins: [react(), ssr({ prerender: true }), viteTsconfigPaths()], }); From 8b6bffcff2ab612cf7900552043a85deb148b435 Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Sun, 23 Apr 2023 08:25:27 +0700 Subject: [PATCH 3/4] fixed ssr errors --- src/components/appHeader/actions.tsx | 25 ++++++--- src/components/channels/channelListItem.tsx | 2 +- src/components/chats/chatList.tsx | 2 +- src/components/eventCollector.tsx | 12 ++++- src/components/note/preview/video.tsx | 2 +- .../{index.page.tsx => index.page.client.tsx} | 0 .../{index.page.tsx => index.page.client.tsx} | 0 src/pages/index.page.tsx | 6 ++- .../{index.page.tsx => index.page.client.tsx} | 0 .../onboarding/login/step-2/index.page.tsx | 52 ++++++++++++------- src/renderer/_default.page.client.tsx | 18 +++++-- src/renderer/_default.page.server.tsx | 21 +++++--- src/utils/transform.tsx | 1 + vite.config.ts | 5 ++ 14 files changed, 101 insertions(+), 45 deletions(-) rename src/pages/channel/{index.page.tsx => index.page.client.tsx} (100%) rename src/pages/chat/{index.page.tsx => index.page.client.tsx} (100%) rename src/pages/newsfeed/following/{index.page.tsx => index.page.client.tsx} (100%) diff --git a/src/components/appHeader/actions.tsx b/src/components/appHeader/actions.tsx index f5c4cf0d..df14a387 100644 --- a/src/components/appHeader/actions.tsx +++ b/src/components/appHeader/actions.tsx @@ -1,6 +1,5 @@ -import { platform } from '@tauri-apps/api/os'; import { ArrowLeft, ArrowRight, Refresh } from 'iconoir-react'; -import { useLayoutEffect, useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; export default function AppActions() { const [os, setOS] = useState(''); @@ -17,13 +16,23 @@ export default function AppActions() { window.location.reload(); }; - useLayoutEffect(() => { - const getPlatform = async () => { - const result = await platform(); - setOS(result); - }; + const getPlatform = useCallback(async () => { + const { platform } = await import('@tauri-apps/api/os'); + const result = await platform(); - getPlatform().catch(console.error); + setOS(result); + }, []); + + useEffect(() => { + let ignore = false; + + if (!ignore) { + getPlatform().catch(console.error); + } + + return () => { + ignore = true; + }; }, []); return ( diff --git a/src/components/channels/channelListItem.tsx b/src/components/channels/channelListItem.tsx index 4b8368e9..3818f87d 100644 --- a/src/components/channels/channelListItem.tsx +++ b/src/components/channels/channelListItem.tsx @@ -7,7 +7,7 @@ export const ChannelListItem = ({ data }: { data: any }) => { return (
diff --git a/src/components/chats/chatList.tsx b/src/components/chats/chatList.tsx index 65bbacf1..b4b46dd4 100644 --- a/src/components/chats/chatList.tsx +++ b/src/components/chats/chatList.tsx @@ -11,7 +11,7 @@ import { useEffect, useState } from 'react'; export default function ChatList() { const [list, setList] = useState([]); const [activeAccount]: any = useLocalStorage('account', {}); - const profile = JSON.parse(activeAccount.metadata); + const profile = activeAccount.metadata ? JSON.parse(activeAccount.metadata) : null; useEffect(() => { let ignore = false; diff --git a/src/components/eventCollector.tsx b/src/components/eventCollector.tsx index e402d962..f640e047 100644 --- a/src/components/eventCollector.tsx +++ b/src/components/eventCollector.tsx @@ -13,7 +13,7 @@ import { useCallback, useContext, useEffect, useRef } from 'react'; export default function EventCollector() { const [pool, relays]: any = useContext(RelayContext); - const [activeAccount]: any = useLocalStorage('account', {}); + const [activeAccount]: any = useLocalStorage('account', null); const setHasNewerNote = useSetAtom(hasNewerNoteAtom); const follows = JSON.parse(activeAccount.follows); @@ -106,7 +106,15 @@ export default function EventCollector() { }, [activeAccount.pubkey, activeAccount.id, follows, pool, relays, setHasNewerNote]); useEffect(() => { - subscribe(); + let ignore = false; + + if (!ignore) { + subscribe(); + } + + return () => { + ignore = true; + }; }, [setHasNewerNote, subscribe]); return ; diff --git a/src/components/note/preview/video.tsx b/src/components/note/preview/video.tsx index 138e14ed..89dec265 100644 --- a/src/components/note/preview/video.tsx +++ b/src/components/note/preview/video.tsx @@ -1,5 +1,5 @@ import { memo } from 'react'; -import ReactPlayer from 'react-player/lazy'; +import ReactPlayer from 'react-player'; export const VideoPreview = memo(function VideoPreview({ url }: { url: string }) { return ( diff --git a/src/pages/channel/index.page.tsx b/src/pages/channel/index.page.client.tsx similarity index 100% rename from src/pages/channel/index.page.tsx rename to src/pages/channel/index.page.client.tsx diff --git a/src/pages/chat/index.page.tsx b/src/pages/chat/index.page.client.tsx similarity index 100% rename from src/pages/chat/index.page.tsx rename to src/pages/chat/index.page.client.tsx diff --git a/src/pages/index.page.tsx b/src/pages/index.page.tsx index 299aea41..3f618f28 100644 --- a/src/pages/index.page.tsx +++ b/src/pages/index.page.tsx @@ -18,7 +18,7 @@ import LumeSymbol from '@assets/icons/Lume'; import { writeStorage } from '@rehooks/local-storage'; import { useCallback, useContext, useEffect, useRef } from 'react'; -import { navigate } from 'vite-plugin-ssr/client/router'; +import { navigate, prefetch } from 'vite-plugin-ssr/client/router'; export function Page() { const [pool, relays]: any = useContext(RelayContext); @@ -123,7 +123,8 @@ export function Page() { () => { updateLastLogin(dateToUnix(now.current)); timeout.current = setTimeout(() => { - navigate('/newsfeed/following', { overwriteLastHistoryEntry: true }); + prefetch('/newsfeed/following'); + navigate('/newsfeed/following'); }, 5000); }, { @@ -152,6 +153,7 @@ export function Page() { // fetch data fetchData(account, account.follows); } else { + prefetch('/onboarding'); navigate('/onboarding', { overwriteLastHistoryEntry: true }); } }) diff --git a/src/pages/newsfeed/following/index.page.tsx b/src/pages/newsfeed/following/index.page.client.tsx similarity index 100% rename from src/pages/newsfeed/following/index.page.tsx rename to src/pages/newsfeed/following/index.page.client.tsx diff --git a/src/pages/onboarding/login/step-2/index.page.tsx b/src/pages/onboarding/login/step-2/index.page.tsx index 5e52b89d..ce3a3b6e 100644 --- a/src/pages/onboarding/login/step-2/index.page.tsx +++ b/src/pages/onboarding/login/step-2/index.page.tsx @@ -10,20 +10,22 @@ import { createAccount, createPleb, updateAccount } from '@utils/storage'; import { nip02ToArray } from '@utils/transform'; import { getPublicKey } from 'nostr-tools'; -import { useCallback, useContext, useEffect, useRef, useState } from 'react'; +import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; +import { navigate } from 'vite-plugin-ssr/client/router'; export function Page() { const pageContext = usePageContext(); const searchParams = pageContext.urlParsed.search; const privkey = searchParams.privkey; - const pubkey = getPublicKey(privkey); + const pubkey = useMemo(() => getPublicKey(privkey), [privkey]); const [pool, relays]: any = useContext(RelayContext); const [profile, setProfile] = useState({ metadata: null }); const [done, setDone] = useState(false); const timeout = useRef(null); + const nip02 = useRef(null); const createPlebs = useCallback(async (tags: string[]) => { for (const tag of tags) { @@ -33,6 +35,16 @@ export function Page() { } }, []); + const submit = () => { + // update account's folllows with NIP-02 tag list + const arr = nip02ToArray(nip02.current); + updateAccount('follows', arr, pubkey); + // create plebs (saved nostr profile) + createPlebs(nip02.current); + // redirect to splashscreen + navigate('/', { overwriteLastHistoryEntry: true }); + }; + useEffect(() => { const unsubscribe = pool.subscribe( [ @@ -43,20 +55,20 @@ export function Page() { ], relays, (event: any) => { - if (event.kind === 0) { - // create account - createAccount(pubkey, privkey, event.content); - // update state - setProfile({ - metadata: JSON.parse(event.content), - }); - } else { - if (event.tags.length > 0) { - createPlebs(event.tags); - const arr = nip02ToArray(event.tags); - // update account's folllows with NIP-02 tag list - updateAccount('follows', arr, pubkey); - } + switch (event.kind) { + case 0: + // create account + createAccount(pubkey, privkey, event.content); + // update state + setProfile({ + metadata: JSON.parse(event.content), + }); + break; + case 3: + nip02.current = event.tags; + break; + default: + break; } }, undefined, @@ -73,7 +85,7 @@ export function Page() { unsubscribe(); clearTimeout(timeout.current); }; - }, [pool, relays, pubkey, privkey, createPlebs]); + }, [pool, relays, pubkey, privkey]); return ( @@ -128,12 +140,12 @@ export function Page() { > ) : ( - submit()} className="inline-flex w-full transform items-center justify-center rounded-lg bg-gradient-to-r from-fuchsia-300 via-orange-100 to-amber-300 px-3.5 py-2.5 font-medium text-zinc-800 active:translate-y-1 disabled:cursor-not-allowed disabled:opacity-30" > Done! Go to newsfeed - + )}
diff --git a/src/renderer/_default.page.client.tsx b/src/renderer/_default.page.client.tsx index a82fd1b7..daaefcef 100644 --- a/src/renderer/_default.page.client.tsx +++ b/src/renderer/_default.page.client.tsx @@ -2,19 +2,31 @@ import '@renderer/index.css'; import { Shell } from '@renderer/shell'; import { PageContextClient } from '@renderer/types'; -import { hydrateRoot } from 'react-dom/client'; +import { Root, createRoot, hydrateRoot } from 'react-dom/client'; export const clientRouting = true; +let root: Root; export async function render(pageContext: PageContextClient) { const { Page, pageProps } = pageContext; if (!Page) throw new Error('Client-side render() hook expects pageContext.Page to be defined'); - hydrateRoot( - document.getElementById('app')!, + const page = ( ); + + const container = document.getElementById('app'); + // SPA + if (container.innerHTML === '' || !pageContext.isHydration) { + if (!root) { + root = createRoot(container); + } + root.render(page); + // SSR + } else { + root = hydrateRoot(container, page); + } } diff --git a/src/renderer/_default.page.server.tsx b/src/renderer/_default.page.server.tsx index 79018e03..a5e69201 100644 --- a/src/renderer/_default.page.server.tsx +++ b/src/renderer/_default.page.server.tsx @@ -7,15 +7,22 @@ import { dangerouslySkipEscape, escapeInject } from 'vite-plugin-ssr/server'; export const passToClient = ['pageProps']; export function render(pageContext: PageContextServer) { - const { Page, pageProps } = pageContext; + let pageHtml: string; - if (!Page) throw new Error('My render() hook expects pageContext.Page to be defined'); + if (!pageContext.Page) { + // SPA + pageHtml = ''; + } else { + // SSR / HTML-only + const { Page, pageProps } = pageContext; + if (!Page) throw new Error('My render() hook expects pageContext.Page to be defined'); - const pageHtml = ReactDOMServer.renderToString( - - - - ); + pageHtml = ReactDOMServer.renderToString( + + + + ); + } return escapeInject` diff --git a/src/utils/transform.tsx b/src/utils/transform.tsx index b1f853d9..a2cf3921 100644 --- a/src/utils/transform.tsx +++ b/src/utils/transform.tsx @@ -6,6 +6,7 @@ export const nip02ToArray = (tags: string[]) => { tags.forEach((item) => { arr.push(item[1]); }); + return arr; }; diff --git a/vite.config.ts b/vite.config.ts index b78d40d1..5fa66fa7 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -5,4 +5,9 @@ import viteTsconfigPaths from 'vite-tsconfig-paths'; export default defineConfig({ plugins: [react(), ssr({ prerender: true }), viteTsconfigPaths()], + define: { + global: { + window: {}, + }, + }, }); From accd690880b3aea7d04b64c33f631270dd16bd2e Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Sun, 23 Apr 2023 08:43:08 +0700 Subject: [PATCH 4/4] clean up --- .../onboarding/create/{index.page.tsx => index.page.client.tsx} | 0 .../create/step-2/{index.page.tsx => index.page.client.tsx} | 0 .../onboarding/login/{index.page.tsx => index.page.client.tsx} | 0 .../login/step-2/{index.page.tsx => index.page.client.tsx} | 0 src/pages/user/{index.page.tsx => index.page.client.tsx} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename src/pages/onboarding/create/{index.page.tsx => index.page.client.tsx} (100%) rename src/pages/onboarding/create/step-2/{index.page.tsx => index.page.client.tsx} (100%) rename src/pages/onboarding/login/{index.page.tsx => index.page.client.tsx} (100%) rename src/pages/onboarding/login/step-2/{index.page.tsx => index.page.client.tsx} (100%) rename src/pages/user/{index.page.tsx => index.page.client.tsx} (100%) diff --git a/src/pages/onboarding/create/index.page.tsx b/src/pages/onboarding/create/index.page.client.tsx similarity index 100% rename from src/pages/onboarding/create/index.page.tsx rename to src/pages/onboarding/create/index.page.client.tsx diff --git a/src/pages/onboarding/create/step-2/index.page.tsx b/src/pages/onboarding/create/step-2/index.page.client.tsx similarity index 100% rename from src/pages/onboarding/create/step-2/index.page.tsx rename to src/pages/onboarding/create/step-2/index.page.client.tsx diff --git a/src/pages/onboarding/login/index.page.tsx b/src/pages/onboarding/login/index.page.client.tsx similarity index 100% rename from src/pages/onboarding/login/index.page.tsx rename to src/pages/onboarding/login/index.page.client.tsx diff --git a/src/pages/onboarding/login/step-2/index.page.tsx b/src/pages/onboarding/login/step-2/index.page.client.tsx similarity index 100% rename from src/pages/onboarding/login/step-2/index.page.tsx rename to src/pages/onboarding/login/step-2/index.page.client.tsx diff --git a/src/pages/user/index.page.tsx b/src/pages/user/index.page.client.tsx similarity index 100% rename from src/pages/user/index.page.tsx rename to src/pages/user/index.page.client.tsx