From 1e4138e40efe1c858b73c3068b7053dbc49caba8 Mon Sep 17 00:00:00 2001 From: Untone Date: Fri, 26 Jul 2024 18:49:15 +0300 Subject: [PATCH] reset1 --- .gitignore | 1 + .vscode/launch.json | 14 - app.config.ts | 9 +- codegen.yml | 4 +- package-lock.json | 380 ++++++++--------- package.json | 64 +-- src/components/Article/Comment/Comment.tsx | 3 +- .../Article/CommentRatingControl.tsx | 122 ++++++ src/components/Article/CommentsTree.tsx | 78 ++-- src/components/Article/FullArticle.tsx | 53 ++- src/components/Article/RatingControl.tsx | 254 ------------ src/components/Article/ShoutRatingControl.tsx | 107 +++++ .../Author/AuthorBadge/AuthorBadge.tsx | 3 +- .../Author/AuthorCard/AuthorCard.tsx | 2 +- src/components/Editor/SimplifiedEditor.tsx | 387 +++++++++--------- .../Feed/ArticleCard/ArticleCard.tsx | 2 +- src/components/HeaderNav/Header.module.scss | 14 +- .../Views/AllAuthors/AllAuthors.tsx | 53 ++- src/components/Views/Author/Author.tsx | 64 ++- src/components/_shared/Icon/Icon.module.scss | 21 - src/components/_shared/Image/Image.tsx | 4 +- src/components/_shared/LoadMoreWrapper.tsx | 13 +- src/context/authors.tsx | 2 +- src/context/reactions.tsx | 52 +-- src/graphql/api/public.ts | 38 +- src/graphql/mutation/core/reaction-create.ts | 1 - src/graphql/mutation/core/reaction-destroy.ts | 4 +- .../query/core/article-comments-load.ts | 29 -- .../query/core/article-ratings-load.ts | 29 -- .../query/core/comment-ratings-load.ts | 29 -- src/graphql/query/core/reactions-load-by.ts | 1 - src/intl/locales/ru/translation.json | 2 +- src/lib/sort.ts | 2 +- src/routes/author/(all-authors).tsx | 45 +- src/routes/author/[slug]/[...tab].tsx | 45 +- src/routes/feed/[...order].tsx | 2 +- 36 files changed, 875 insertions(+), 1058 deletions(-) delete mode 100644 .vscode/launch.json create mode 100644 src/components/Article/CommentRatingControl.tsx delete mode 100644 src/components/Article/RatingControl.tsx create mode 100644 src/components/Article/ShoutRatingControl.tsx delete mode 100644 src/graphql/query/core/article-comments-load.ts delete mode 100644 src/graphql/query/core/article-ratings-load.ts delete mode 100644 src/graphql/query/core/comment-ratings-load.ts diff --git a/.gitignore b/.gitignore index a8ed6c74..66ac320e 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ target .output .vinxi *.pem +edge.* diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 6a7811d5..00000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Launch browser against localhost", - "type": "chrome", - "request": "launch", - "url": "https://localhost:3000", - "webRoot": "${workspaceFolder}/src", - "sourceMaps": true, - "trace": true - } - ] -} diff --git a/app.config.ts b/app.config.ts index 3cd5e7c6..860366d2 100644 --- a/app.config.ts +++ b/app.config.ts @@ -30,12 +30,11 @@ export default defineConfig({ https: true }, devOverlay: true, + build: { + chunkSizeWarningLimit: 1024, + target: 'esnext' + }, vite: { - build: { - sourcemap: true, - chunkSizeWarningLimit: 1024, - target: 'esnext' - }, envPrefix: 'PUBLIC_', plugins: [!isVercel && mkcert(), nodePolyfills(polyfillOptions), sassDts()], css: { diff --git a/codegen.yml b/codegen.yml index b09f0596..eb4811ba 100644 --- a/codegen.yml +++ b/codegen.yml @@ -11,7 +11,7 @@ generates: skipTypename: true useTypeImports: true outputPath: './src/graphql/types/chat.gen.ts' - # namingConvention: lodash#pascalCase + # namingConvention: change-case#CamelCase # for generated types # Generate types for core src/graphql/schema/core.gen.ts: @@ -24,7 +24,7 @@ generates: skipTypename: true useTypeImports: true outputPath: './src/graphql/types/core.gen.ts' - # namingConvention: lodash#pascalCase + # namingConvention: change-case#CamelCase # for generated types hooks: afterAllFileWrite: - prettier --ignore-path .gitignore --write --plugin-search-dir=. src/graphql/schema/*.gen.ts diff --git a/package-lock.json b/package-lock.json index 850685af..9d52d2a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "@graphql-codegen/typescript-operations": "^4.2.3", "@graphql-codegen/typescript-urql": "^4.0.0", "@hocuspocus/provider": "^2.13.5", - "@playwright/test": "^1.45.2", + "@playwright/test": "^1.45.3", "@popperjs/core": "^2.11.8", "@solid-primitives/media": "^2.2.9", "@solid-primitives/memo": "^1.3.9", @@ -33,35 +33,35 @@ "@solidjs/meta": "^0.29.4", "@solidjs/router": "^0.14.1", "@solidjs/start": "^1.0.6", - "@tiptap/core": "^2.5.4", - "@tiptap/extension-blockquote": "^2.5.4", - "@tiptap/extension-bold": "^2.5.4", - "@tiptap/extension-bubble-menu": "^2.5.4", - "@tiptap/extension-bullet-list": "^2.5.4", - "@tiptap/extension-character-count": "^2.5.4", - "@tiptap/extension-collaboration": "^2.5.4", - "@tiptap/extension-collaboration-cursor": "^2.5.4", - "@tiptap/extension-document": "^2.5.4", - "@tiptap/extension-dropcursor": "^2.5.4", - "@tiptap/extension-floating-menu": "^2.5.4", - "@tiptap/extension-focus": "^2.5.4", - "@tiptap/extension-gapcursor": "^2.5.4", - "@tiptap/extension-hard-break": "^2.5.4", - "@tiptap/extension-heading": "^2.5.4", - "@tiptap/extension-highlight": "^2.5.4", - "@tiptap/extension-history": "^2.5.4", - "@tiptap/extension-horizontal-rule": "^2.5.4", - "@tiptap/extension-image": "^2.5.4", - "@tiptap/extension-italic": "^2.5.4", - "@tiptap/extension-link": "^2.5.4", - "@tiptap/extension-list-item": "^2.5.4", - "@tiptap/extension-ordered-list": "^2.5.4", - "@tiptap/extension-paragraph": "^2.5.4", - "@tiptap/extension-placeholder": "^2.5.4", - "@tiptap/extension-strike": "^2.5.4", - "@tiptap/extension-text": "^2.5.4", - "@tiptap/extension-underline": "^2.5.4", - "@tiptap/extension-youtube": "^2.5.4", + "@tiptap/core": "^2.5.5", + "@tiptap/extension-blockquote": "^2.5.5", + "@tiptap/extension-bold": "^2.5.5", + "@tiptap/extension-bubble-menu": "^2.5.5", + "@tiptap/extension-bullet-list": "^2.5.5", + "@tiptap/extension-character-count": "^2.5.5", + "@tiptap/extension-collaboration": "^2.5.5", + "@tiptap/extension-collaboration-cursor": "^2.5.5", + "@tiptap/extension-document": "^2.5.5", + "@tiptap/extension-dropcursor": "^2.5.5", + "@tiptap/extension-floating-menu": "^2.5.5", + "@tiptap/extension-focus": "^2.5.5", + "@tiptap/extension-gapcursor": "^2.5.5", + "@tiptap/extension-hard-break": "^2.5.5", + "@tiptap/extension-heading": "^2.5.5", + "@tiptap/extension-highlight": "^2.5.5", + "@tiptap/extension-history": "^2.5.5", + "@tiptap/extension-horizontal-rule": "^2.5.5", + "@tiptap/extension-image": "^2.5.5", + "@tiptap/extension-italic": "^2.5.5", + "@tiptap/extension-link": "^2.5.5", + "@tiptap/extension-list-item": "^2.5.5", + "@tiptap/extension-ordered-list": "^2.5.5", + "@tiptap/extension-paragraph": "^2.5.5", + "@tiptap/extension-placeholder": "^2.5.5", + "@tiptap/extension-strike": "^2.5.5", + "@tiptap/extension-text": "^2.5.5", + "@tiptap/extension-underline": "^2.5.5", + "@tiptap/extension-youtube": "^2.5.5", "@types/cookie": "^0.6.0", "@types/cookie-signature": "^1.1.2", "@types/node": "^20.14.11", @@ -98,7 +98,7 @@ "swiper": "^11.1.5", "throttle-debounce": "^5.0.2", "tslib": "^2.6.3", - "typescript": "^5.5.3", + "typescript": "^5.5.4", "typograf": "^7.4.1", "uniqolor": "^1.1.1", "vinxi": "^0.4.1", @@ -2604,9 +2604,9 @@ } }, "node_modules/@graphql-tools/delegate": { - "version": "10.0.14", - "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-10.0.14.tgz", - "integrity": "sha512-mYrLtwVKTHg5F4OFrJbiL5F7dzopzGiac5ezkVrnlGNPBQ8GNCr1zo32c1rYyIbsa8fJSUvAJfJfFj6ipnutnw==", + "version": "10.0.15", + "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-10.0.15.tgz", + "integrity": "sha512-18R4vcJWz/6pk6K9SslijR0jCSe0mAnSs0sd1eioTvSSCWiagPdCOOhaM9dPNfEnxp3TRHg3cnYqywRtJgKHvw==", "dev": true, "license": "MIT", "dependencies": { @@ -4148,13 +4148,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.45.2", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.45.2.tgz", - "integrity": "sha512-JxG9eq92ET75EbVi3s+4sYbcG7q72ECeZNbdBlaMkGcNbiDQ4cAi8U2QP5oKkOx+1gpaiL1LDStmzCaEM1Z6fQ==", + "version": "1.45.3", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.45.3.tgz", + "integrity": "sha512-UKF4XsBfy+u3MFWEH44hva1Q8Da28G6RFtR2+5saw+jgAFQV5yYnB1fu68Mz7fO+5GJF3wgwAIs0UelU8TxFrA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.45.2" + "playwright": "1.45.3" }, "bin": { "playwright": "cli.js" @@ -4956,9 +4956,9 @@ } }, "node_modules/@tiptap/core": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.5.4.tgz", - "integrity": "sha512-Zs/hShr4+W02+0nOlpmr5cS2YjDRLqd+XMt+jsiQH0QNr3s1Lc82pfF6C3CjgLEZtdUzImZrW2ABtLlpvbogaA==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.5.5.tgz", + "integrity": "sha512-VnAnyWnsqN65QijtUFHbe7EPSJCkhNEAwlatsG/HvrZvUv9KmoWWbMsHAU73wozKzPXR3nHRbCxN+LuxP5bADg==", "dev": true, "license": "MIT", "funding": { @@ -4966,13 +4966,13 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/pm": "^2.5.4" + "@tiptap/pm": "^2.5.5" } }, "node_modules/@tiptap/extension-blockquote": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-2.5.4.tgz", - "integrity": "sha512-UqeJunZM3IiCQGZE0X5YNUOWYkuIieqrwPgOEghAIjnhDcQizQcouRQ5R7cwwv/scNr2JvZHncOTLrALV3Janw==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-2.5.5.tgz", + "integrity": "sha512-K+fc++ASlgDRHN6i3j3JBGzWiDhhoZv0jCUB/l7Jzut4UfjIoWqKhmJajnp95Qu9tmwQUy9LMzHqG4G5wUsIsQ==", "dev": true, "license": "MIT", "funding": { @@ -4980,13 +4980,13 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4" + "@tiptap/core": "^2.5.5" } }, "node_modules/@tiptap/extension-bold": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-2.5.4.tgz", - "integrity": "sha512-H5sjqloFMjq7VOSfE+U4T7dqGoflOiF6RW6/gZm/U6KYeHG2/bG0ktq7mWAnnhbiKiy7gUcxyJCV+ILdGX9C5g==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-2.5.5.tgz", + "integrity": "sha512-vXqaeTKy4nf4X+s7NkFt0OsuS1eKMQhrdt7SzACf0gWi3M761WGkaKHy8XUlo7zhWhqHtkgey53Gaw0nbEY54Q==", "dev": true, "license": "MIT", "funding": { @@ -4994,13 +4994,13 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4" + "@tiptap/core": "^2.5.5" } }, "node_modules/@tiptap/extension-bubble-menu": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.5.4.tgz", - "integrity": "sha512-GHwef912K1yd75pp9JGDnKSp1DvdOHH8BcHQv0no+a3q2ePFPYcgaSwVRR59jHRX9WzdVfoLcqDSAeoNGOrISw==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.5.5.tgz", + "integrity": "sha512-7k0HqrnhQGVZk86MEc5vt8stNRxIY65AMjZfszY/mQw0Dza7EQig/9b/AEmi9n+TNW5/8Qu+OMJD9ln92d/Eog==", "dev": true, "license": "MIT", "dependencies": { @@ -5011,14 +5011,14 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4", - "@tiptap/pm": "^2.5.4" + "@tiptap/core": "^2.5.5", + "@tiptap/pm": "^2.5.5" } }, "node_modules/@tiptap/extension-bullet-list": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-2.5.4.tgz", - "integrity": "sha512-aAfpALeD6OxymkbtrzDqbgkAkzVVHudxOb8GsK1N6m42nFL7Q9JzHJ5/8KzB+xi25CcIbS+HmXJkRIQJXgNbSA==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-2.5.5.tgz", + "integrity": "sha512-p89cTmGUoq3OEFzcS49iQ/tyQjDoKW1J0c7EghS7eU3wHVxeo/Ke110cY2W5o1e4KMFowo3a4jVsxKuCQJkWrA==", "dev": true, "license": "MIT", "funding": { @@ -5026,13 +5026,13 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4" + "@tiptap/core": "^2.5.5" } }, "node_modules/@tiptap/extension-character-count": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-character-count/-/extension-character-count-2.5.4.tgz", - "integrity": "sha512-6qwt+81I+y+t3eoFPmCG2ouQce2RccwyiUC0ZOPTG1eUB+5yXmyIwBYI4aOM4TEfxNizyaZtQw32CDdAhMr3YA==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-character-count/-/extension-character-count-2.5.5.tgz", + "integrity": "sha512-rh6q3YeuLV8PnaKUqQbnOQ16obXPcqsqnQ+y1XLWH74lHwdvbOvE1BCvSZD0ULPI9EcOtvhdZEZkDxlqQ9H3jg==", "dev": true, "license": "MIT", "funding": { @@ -5040,14 +5040,14 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4", - "@tiptap/pm": "^2.5.4" + "@tiptap/core": "^2.5.5", + "@tiptap/pm": "^2.5.5" } }, "node_modules/@tiptap/extension-collaboration": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-collaboration/-/extension-collaboration-2.5.4.tgz", - "integrity": "sha512-CpQdbr7XpQaVqRFo/A1DchrQZMDb8vrkP+FcUIgvHN0b8hwKDmXRAHDtuk8yTTEatW1EqpX8lx8UxaUTcDNbIg==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-collaboration/-/extension-collaboration-2.5.5.tgz", + "integrity": "sha512-HpDW+1VTKdtK7BglQNLFv2UzJIxtzZ9zvT+wdYDWPB3ZstoL8drpp4wGP2xt3tbki6wzGpUFkDCpVNl0oOunXQ==", "dev": true, "license": "MIT", "funding": { @@ -5055,15 +5055,15 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4", - "@tiptap/pm": "^2.5.4", + "@tiptap/core": "^2.5.5", + "@tiptap/pm": "^2.5.5", "y-prosemirror": "^1.2.6" } }, "node_modules/@tiptap/extension-collaboration-cursor": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-collaboration-cursor/-/extension-collaboration-cursor-2.5.4.tgz", - "integrity": "sha512-M32JChnP5RVdr1n+Tf0gF9bxx0gHvc0uV4SDxCMN3uaNH5YpcofmvKElS60rDGVfCdRTId/aj7P3AtwrvRlYdQ==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-collaboration-cursor/-/extension-collaboration-cursor-2.5.5.tgz", + "integrity": "sha512-DWX3eOplWyLegOWeZa0CAVbb9/UYbngiZyKjVMpDlx5qzhUuLL+Df54/UGKqB1ZrBZrxKCVQE3APMyXkxI/2VQ==", "dev": true, "license": "MIT", "funding": { @@ -5071,14 +5071,14 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4", + "@tiptap/core": "^2.5.5", "y-prosemirror": "^1.2.6" } }, "node_modules/@tiptap/extension-document": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.5.4.tgz", - "integrity": "sha512-4RDrhASxCTOZETYhIhEW1TfZqx3Tm+LQxouvBMFyODmT1PSgsg5Xz1FYpDPr+J49bGAK0Pr9ae0XcGW011L3sA==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.5.5.tgz", + "integrity": "sha512-MIjYO63JepcJW37PQuKVmYuZFqkQOZ/12tV0YLU4o6gmGVdqJS0+3md9CdnyUFUDIo7x6TBh8r5i5L2xQpm3Sg==", "dev": true, "license": "MIT", "funding": { @@ -5086,13 +5086,13 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4" + "@tiptap/core": "^2.5.5" } }, "node_modules/@tiptap/extension-dropcursor": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-2.5.4.tgz", - "integrity": "sha512-jzSnuuYhlc0SsHvAteWkE9TJy3eRwkxQs4MO2JxALOzJECN4G82nlX8vciihBD6xf7lVgVSBACejK9+rsTHqCg==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-2.5.5.tgz", + "integrity": "sha512-+K/qd115c3zFgHdvxtOkZhSTKNyPpjM0Np2v4cehqn0j+/3stOMGlAH2Jm/b2L8RylFKGtQP1b/1wsKY5feuAg==", "dev": true, "license": "MIT", "funding": { @@ -5100,14 +5100,14 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4", - "@tiptap/pm": "^2.5.4" + "@tiptap/core": "^2.5.5", + "@tiptap/pm": "^2.5.5" } }, "node_modules/@tiptap/extension-floating-menu": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-2.5.4.tgz", - "integrity": "sha512-EqD4rgi3UhnDcV3H1+ndAS4Ue2zpsU7hFKoevOIV6GS7xVnWN70AGt6swH24QzuHKKISFtWoLpKjrwRORNIxuA==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-2.5.5.tgz", + "integrity": "sha512-1mgpxZGfy1ziNSvWz6m1nGb9ZF9fVVz4X4XwrIqwGw1Vqt9oXflm6puglnzwVLDeaMDT014VUfczJ4My3wDZzA==", "dev": true, "license": "MIT", "dependencies": { @@ -5118,14 +5118,14 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4", - "@tiptap/pm": "^2.5.4" + "@tiptap/core": "^2.5.5", + "@tiptap/pm": "^2.5.5" } }, "node_modules/@tiptap/extension-focus": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-focus/-/extension-focus-2.5.4.tgz", - "integrity": "sha512-/Iq++93f9S+bNJzj3OmgOydCO58VfAhmnsImbGK/GmxV39hHbgJdazxMugwdQlvrY/oe3+Y+WY8ZI1WlWwTJ4g==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-focus/-/extension-focus-2.5.5.tgz", + "integrity": "sha512-c5ul5PNl/2HcYwEPu1kjjs/u8N5BtLnreeUyb223y8i4BEcjydVlnCfVVUdonQIWnj0mKQ8KZbyLTSYdijDsVA==", "dev": true, "license": "MIT", "funding": { @@ -5133,14 +5133,14 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4", - "@tiptap/pm": "^2.5.4" + "@tiptap/core": "^2.5.5", + "@tiptap/pm": "^2.5.5" } }, "node_modules/@tiptap/extension-gapcursor": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-2.5.4.tgz", - "integrity": "sha512-wzTh1piODZBS0wmuDgPjjg8PQwclYa5LssnxDIo9pDSnt4l3AfHSAJIJSGIfgt96KnzF1wqRTRpe08qNa1n7/g==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-2.5.5.tgz", + "integrity": "sha512-An/HwTheUP+D4UU1GVy2e4ypqA1TanZ7haNcm5WB+wSZQo6UNPIszIa49TTGenkk86hP2DH9cQSlTREsyAW6wg==", "dev": true, "license": "MIT", "funding": { @@ -5148,14 +5148,14 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4", - "@tiptap/pm": "^2.5.4" + "@tiptap/core": "^2.5.5", + "@tiptap/pm": "^2.5.5" } }, "node_modules/@tiptap/extension-hard-break": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-2.5.4.tgz", - "integrity": "sha512-nLn6HP9tqgdGGwbMORXVtcY30DTGctYFaWADRthvBjVgacYSeKlhUcsSu3YgaxtbxZp6BhfRvD2kKrxyQsSjnQ==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-2.5.5.tgz", + "integrity": "sha512-VtrwKU0LYS/0rfH5rGz8ztKwA0bsHRyBF53G7aP2FS4BiN8aOEu8t7VkvBZAewXDITDah9K6rqfXk+MNwoul2Q==", "dev": true, "license": "MIT", "funding": { @@ -5163,13 +5163,13 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4" + "@tiptap/core": "^2.5.5" } }, "node_modules/@tiptap/extension-heading": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.5.4.tgz", - "integrity": "sha512-DuAB58/e7eho1rkyad0Z/SjW+EB+H2hRqHlswEeZZYhBTjzey5UmBwkMWTGC/SQiRisx1xYQYTd8T0fiABi5hw==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.5.5.tgz", + "integrity": "sha512-NDnXOR6HmnkBA68oZTVf0BT5t8ikVFv9X6Ft/O5oU6IuzCswS8BUb5MJIhKBWQXJTsCNbC6EYl5jhJ3hukLcHw==", "dev": true, "license": "MIT", "funding": { @@ -5177,13 +5177,13 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4" + "@tiptap/core": "^2.5.5" } }, "node_modules/@tiptap/extension-highlight": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-highlight/-/extension-highlight-2.5.4.tgz", - "integrity": "sha512-TSYnFBluZu1YQdTCyXl2wuxFuhFUYFzbaV0f1wq2P2Nc8U2OiiuaNz+QggHw5Hf3ILzkRxQCUQnq97Q/5smMwQ==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-highlight/-/extension-highlight-2.5.5.tgz", + "integrity": "sha512-NqMmL9/82288DI1trnuxB3hcf61x+iDKFvNAE+thW6MmY6ZWi47bEnfUQGwDeInxH81NfMhTTSxuXmnuO10noQ==", "dev": true, "license": "MIT", "funding": { @@ -5191,13 +5191,13 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4" + "@tiptap/core": "^2.5.5" } }, "node_modules/@tiptap/extension-history": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.5.4.tgz", - "integrity": "sha512-WB1fZYGIlpahAD6Ba+mj9vIb1tk8S3TsADXDFKxLVpZWZPQ+B7duGJP7g/vRH2XAXEs836JzC2oxjKeaop3k7A==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.5.5.tgz", + "integrity": "sha512-CYxFpE9wayc+iZQIlXd3cbq47WP+KqjDhprbKF5Tb7+WoWLS2FB5WK3n+r/SrcoIaslIt5SYDRQPzx4fS3N7LA==", "dev": true, "license": "MIT", "funding": { @@ -5205,14 +5205,14 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4", - "@tiptap/pm": "^2.5.4" + "@tiptap/core": "^2.5.5", + "@tiptap/pm": "^2.5.5" } }, "node_modules/@tiptap/extension-horizontal-rule": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.5.4.tgz", - "integrity": "sha512-uXLDe/iyzQbyfDkJ8kE5XaAkY3EOcbTFLjbueqGlkbWtjJgy+3LysGvh8fQj8PAOaIBMaFRFhTq7GMbW2ebRog==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.5.5.tgz", + "integrity": "sha512-8oV0oLgGwJqr44wk7+bHxTAenR0bvk9aVdmE/owg1oy2tkSX0bwtvQEOnwwxtfPJGTwq8JGhefUGYcpHfG2YYg==", "dev": true, "license": "MIT", "funding": { @@ -5220,14 +5220,14 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4", - "@tiptap/pm": "^2.5.4" + "@tiptap/core": "^2.5.5", + "@tiptap/pm": "^2.5.5" } }, "node_modules/@tiptap/extension-image": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-image/-/extension-image-2.5.4.tgz", - "integrity": "sha512-4ySSP7iPsbbo1SlPJYj546TKettuO6FGY5MQKxH8AGnZWyQGZYl89GpU1iGFAaeHq4dKUemM5D3ikgSynEQLow==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-image/-/extension-image-2.5.5.tgz", + "integrity": "sha512-DvnKf3XCGf/2GQrqtwgKwgaeqIn2dXgHTire0E2aPj8T939jA4ApX5qLPumndHX0rAckX5VAbnJjQeoxtEmMFw==", "dev": true, "license": "MIT", "funding": { @@ -5235,13 +5235,13 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4" + "@tiptap/core": "^2.5.5" } }, "node_modules/@tiptap/extension-italic": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-2.5.4.tgz", - "integrity": "sha512-TAhtl/fNBgv1elzF3HWES8uwVdpKBSYrq1e6yeYfj74mQn//3ksvdhWQrLzc1e+zcoHbk1PeOp/5ODdPuZ6tkg==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-2.5.5.tgz", + "integrity": "sha512-PEeI68/u7Bm4n4xIcxVAV12jPhEa72fpHRnYfJe4CGp4x8mJfz/dowKN/P0/6CfjROB7Q8rY26u5E9fS+Cg73w==", "dev": true, "license": "MIT", "funding": { @@ -5249,13 +5249,13 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4" + "@tiptap/core": "^2.5.5" } }, "node_modules/@tiptap/extension-link": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-2.5.4.tgz", - "integrity": "sha512-xTB/+T6SHHCXInJni8WdqOfF40a/MiFUf5OoWW9cPrApx3I7TzJ9j8/WDshM0BOnDDw80w1bl9F2zkUQjC0Y2A==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-2.5.5.tgz", + "integrity": "sha512-zVpNvMD8R9uW1SX1PJoj3fLyOHwuFWqiqEHN2KWfLbEnbL/KXNnpIyKdpHnI9lqFrsMf2dmyZCS3R6xIrynviQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5266,14 +5266,14 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4", - "@tiptap/pm": "^2.5.4" + "@tiptap/core": "^2.5.5", + "@tiptap/pm": "^2.5.5" } }, "node_modules/@tiptap/extension-list-item": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.5.4.tgz", - "integrity": "sha512-bPxUCFt9HnAfoaZQgwqCfRAZ6L3QlYhIRDDbOvZag7IxCdQuZmeY4k5OZfQIGijNDTag7CN9cdL4fl9rnm6/sQ==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.5.5.tgz", + "integrity": "sha512-CfNVCP8Pqqgr7fAQAuRvZikzXT9vCEogcW7/C16cyGykbUJBqBmpsyHcAlj7XwsBFUuJ5MCeULtk/0frUI5fMQ==", "dev": true, "license": "MIT", "funding": { @@ -5281,13 +5281,13 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4" + "@tiptap/core": "^2.5.5" } }, "node_modules/@tiptap/extension-ordered-list": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-2.5.4.tgz", - "integrity": "sha512-cl3cTJitY6yDUmxqgjDUtDWCyX1VVsZNJ6i9yiPeARcxvzFc81KmUJxTGl8WPT5TjqmM+TleRkZjsxgvXX57+Q==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-2.5.5.tgz", + "integrity": "sha512-wElnGQJhKznayP7tVGl/r42mj1dLEeU+Ln1Y3wF/m+nFwKl2Gpsy01PjBy5sXPUgskGSWgMlOgJrQyMvH9AuAw==", "dev": true, "license": "MIT", "funding": { @@ -5295,13 +5295,13 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4" + "@tiptap/core": "^2.5.5" } }, "node_modules/@tiptap/extension-paragraph": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-2.5.4.tgz", - "integrity": "sha512-pC1YIkkRPXoU0eDrhfAf8ZrFJQzvw2ftP6KRhLnnSw/Ot1DOjT1r95l7zsFefS9oCDMT/L4HghTAiPZ4rcpPbg==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-2.5.5.tgz", + "integrity": "sha512-XZO1rqsU1vlt9qeG2pVVAt2gXjD0twl2D+uxy4Nw6gxqbhSgfbNq3RP72mmtcS4KyFJi7ETANpcRpb8ZNvXfmg==", "dev": true, "license": "MIT", "funding": { @@ -5309,13 +5309,13 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4" + "@tiptap/core": "^2.5.5" } }, "node_modules/@tiptap/extension-placeholder": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-placeholder/-/extension-placeholder-2.5.4.tgz", - "integrity": "sha512-mcj4j2Z/L1H5dzWHbbWChuAdJK9F2p06fcjqL4iyJtVx38QQFzCdVmGaTAim8CLp/EynbAOYJ5gk9w2PTdv7+w==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-placeholder/-/extension-placeholder-2.5.5.tgz", + "integrity": "sha512-SwWLYdyrMeoVUQdivkIJ4kkAcb38pykxSetlrXitfUmnkwv0/fi+p76Rickf+roudWPsfzqvgvJ4gT6OAOJrGA==", "dev": true, "license": "MIT", "funding": { @@ -5323,14 +5323,14 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4", - "@tiptap/pm": "^2.5.4" + "@tiptap/core": "^2.5.5", + "@tiptap/pm": "^2.5.5" } }, "node_modules/@tiptap/extension-strike": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-2.5.4.tgz", - "integrity": "sha512-OSN6ePbCwEhi3hYZZOPow/P9Ym2Kv3NhVbUvasjZCiqQuk8TGc33xirPWl9DTjb/BLfL66TtJ2tKUEVOKl5dKg==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-2.5.5.tgz", + "integrity": "sha512-xnVdSsP7+4yQ1E+rI77ZHvzDH1Gwe2Ty1tgXeOaLjt3RfeVx4xy75o09yHzab6J4hgPebonoXKbZV0JVTGnjtQ==", "dev": true, "license": "MIT", "funding": { @@ -5338,13 +5338,13 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4" + "@tiptap/core": "^2.5.5" } }, "node_modules/@tiptap/extension-text": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.5.4.tgz", - "integrity": "sha512-+3x/hYqhmCYbvedCcQzQHFtZ5MAcMOlKuczomZtygf8AfDfuQVrG1m4GoJyNzJdqxjN80/xq4e2vDVvqQxYTCw==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.5.5.tgz", + "integrity": "sha512-8c/hxcw7t/S3iKGSFwGNxC2I6AkKpRiySQJ95ML2miwSOAxWhnltoYYV7gobWCRgm25lnvzX/Z6BdpFzXBrBKA==", "dev": true, "license": "MIT", "funding": { @@ -5352,13 +5352,13 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4" + "@tiptap/core": "^2.5.5" } }, "node_modules/@tiptap/extension-underline": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-2.5.4.tgz", - "integrity": "sha512-o8T3oWbniA3rLo6LkslPRF8pwdjsaHXJCeK4KmKeCyYhTpMfjypT3uptd+VSSJ4iQkaiFInKeIUOBqqEQ9cADw==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-2.5.5.tgz", + "integrity": "sha512-3uog8d4G/AdqaJC8qutIIgkYnU2TfXW3QbtEy0Yg2WdjCz97bWXkFkNhhVZM/hvXjFCbYboRN5HLcIHl8+Zgmg==", "dev": true, "license": "MIT", "funding": { @@ -5366,13 +5366,13 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4" + "@tiptap/core": "^2.5.5" } }, "node_modules/@tiptap/extension-youtube": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/extension-youtube/-/extension-youtube-2.5.4.tgz", - "integrity": "sha512-iHcvXOA32MZsVJTT7mvZ1CWKUo2quQMQXfBniizLm0lUG1ftSioqnDuXy4kEjeCBR2cnZr3yph6tbG/pF0RcHg==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-youtube/-/extension-youtube-2.5.5.tgz", + "integrity": "sha512-dPLSLsEiMdXB5q0YDRJKWiiTqdFiSeyaC5qWLio4SHYfyTYT1+M2Wwox+5Dm/OSgCHpxpT2W8JRt+H4+P38t9A==", "dev": true, "license": "MIT", "funding": { @@ -5380,13 +5380,13 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.5.4" + "@tiptap/core": "^2.5.5" } }, "node_modules/@tiptap/pm": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.5.4.tgz", - "integrity": "sha512-oFIsuniptdUXn93x4aM2sVN3hYKo9Fj55zAkYrWhwxFYUYcPxd5ibra2we+wRK5TaiPu098wpC+yMSTZ/KKMpA==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.5.5.tgz", + "integrity": "sha512-ppePiLaeG6IKkm8Yq+mRENT4LIAS4qQyLT8EnKadznaTL6SNj/72mm0MjD44URkM38ySzIyvt/vqHDapNK0Hww==", "dev": true, "license": "MIT", "peer": true, @@ -7057,9 +7057,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001642", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz", - "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==", + "version": "1.0.30001643", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz", + "integrity": "sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==", "dev": true, "funding": [ { @@ -8441,9 +8441,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.4.832", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.832.tgz", - "integrity": "sha512-cTen3SB0H2SGU7x467NRe1eVcQgcuS6jckKfWJHia2eo0cHIGOqHoAxevIYZD4eRHcWjkvFzo93bi3vJ9W+1lA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.0.tgz", + "integrity": "sha512-Vb3xHHYnLseK8vlMJQKJYXJ++t4u1/qJ3vykuVrVjvdiOEhYyT1AuP4x03G8EnPmYvYOhe9T+dADTmthjRQMkA==", "dev": true, "license": "ISC" }, @@ -11898,9 +11898,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.17.tgz", - "integrity": "sha512-Ww6ZlOiEQfPfXM45v17oabk77Z7mg5bOt7AjDyzy7RjK9OrLrLC8dyZQoAPEOtFX9SaNf1Tdvr5gRJWdTJj7GA==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", "dev": true, "license": "MIT" }, @@ -12682,13 +12682,13 @@ } }, "node_modules/playwright": { - "version": "1.45.2", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.2.tgz", - "integrity": "sha512-ReywF2t/0teRvNBpfIgh5e4wnrI/8Su8ssdo5XsQKpjxJj+jspm00jSoz9BTg91TT0c9HRjXO7LBNVrgYj9X0g==", + "version": "1.45.3", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.3.tgz", + "integrity": "sha512-QhVaS+lpluxCaioejDZ95l4Y4jSFCsBvl2UZkpeXlzxmqS+aABr5c82YmfMHrL6x27nvrvykJAFpkzT2eWdJww==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.45.2" + "playwright-core": "1.45.3" }, "bin": { "playwright": "cli.js" @@ -12701,9 +12701,9 @@ } }, "node_modules/playwright-core": { - "version": "1.45.2", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.2.tgz", - "integrity": "sha512-ha175tAWb0dTK0X4orvBIqi3jGEt701SMxMhyujxNrgd8K0Uy5wMSwwcQHtyB4om7INUkfndx02XnQ2p6dvLDw==", + "version": "1.45.3", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.3.tgz", + "integrity": "sha512-+ym0jNbcjikaOwwSZycFbwkWgfruWvYlJfThKYAlImbxUgdWFO2oW70ojPm4OpE4t6TAo2FY/smM+hpVTtkhDA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -13891,9 +13891,9 @@ } }, "node_modules/sass/node_modules/immutable": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz", - "integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", + "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", "dev": true, "license": "MIT" }, @@ -15196,9 +15196,9 @@ } }, "node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 32002eec..53ad2946 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "discoursio-webapp", "private": true, - "version": "0.9.6", + "version": "0.9.5", "type": "module", "scripts": { "dev": "vinxi dev", @@ -25,7 +25,7 @@ "@graphql-codegen/typescript-operations": "^4.2.3", "@graphql-codegen/typescript-urql": "^4.0.0", "@hocuspocus/provider": "^2.13.5", - "@playwright/test": "^1.45.2", + "@playwright/test": "^1.45.3", "@popperjs/core": "^2.11.8", "@solid-primitives/media": "^2.2.9", "@solid-primitives/memo": "^1.3.9", @@ -37,35 +37,35 @@ "@solidjs/meta": "^0.29.4", "@solidjs/router": "^0.14.1", "@solidjs/start": "^1.0.6", - "@tiptap/core": "^2.5.4", - "@tiptap/extension-blockquote": "^2.5.4", - "@tiptap/extension-bold": "^2.5.4", - "@tiptap/extension-bubble-menu": "^2.5.4", - "@tiptap/extension-bullet-list": "^2.5.4", - "@tiptap/extension-character-count": "^2.5.4", - "@tiptap/extension-collaboration": "^2.5.4", - "@tiptap/extension-collaboration-cursor": "^2.5.4", - "@tiptap/extension-document": "^2.5.4", - "@tiptap/extension-dropcursor": "^2.5.4", - "@tiptap/extension-floating-menu": "^2.5.4", - "@tiptap/extension-focus": "^2.5.4", - "@tiptap/extension-gapcursor": "^2.5.4", - "@tiptap/extension-hard-break": "^2.5.4", - "@tiptap/extension-heading": "^2.5.4", - "@tiptap/extension-highlight": "^2.5.4", - "@tiptap/extension-history": "^2.5.4", - "@tiptap/extension-horizontal-rule": "^2.5.4", - "@tiptap/extension-image": "^2.5.4", - "@tiptap/extension-italic": "^2.5.4", - "@tiptap/extension-link": "^2.5.4", - "@tiptap/extension-list-item": "^2.5.4", - "@tiptap/extension-ordered-list": "^2.5.4", - "@tiptap/extension-paragraph": "^2.5.4", - "@tiptap/extension-placeholder": "^2.5.4", - "@tiptap/extension-strike": "^2.5.4", - "@tiptap/extension-text": "^2.5.4", - "@tiptap/extension-underline": "^2.5.4", - "@tiptap/extension-youtube": "^2.5.4", + "@tiptap/core": "^2.5.5", + "@tiptap/extension-blockquote": "^2.5.5", + "@tiptap/extension-bold": "^2.5.5", + "@tiptap/extension-bubble-menu": "^2.5.5", + "@tiptap/extension-bullet-list": "^2.5.5", + "@tiptap/extension-character-count": "^2.5.5", + "@tiptap/extension-collaboration": "^2.5.5", + "@tiptap/extension-collaboration-cursor": "^2.5.5", + "@tiptap/extension-document": "^2.5.5", + "@tiptap/extension-dropcursor": "^2.5.5", + "@tiptap/extension-floating-menu": "^2.5.5", + "@tiptap/extension-focus": "^2.5.5", + "@tiptap/extension-gapcursor": "^2.5.5", + "@tiptap/extension-hard-break": "^2.5.5", + "@tiptap/extension-heading": "^2.5.5", + "@tiptap/extension-highlight": "^2.5.5", + "@tiptap/extension-history": "^2.5.5", + "@tiptap/extension-horizontal-rule": "^2.5.5", + "@tiptap/extension-image": "^2.5.5", + "@tiptap/extension-italic": "^2.5.5", + "@tiptap/extension-link": "^2.5.5", + "@tiptap/extension-list-item": "^2.5.5", + "@tiptap/extension-ordered-list": "^2.5.5", + "@tiptap/extension-paragraph": "^2.5.5", + "@tiptap/extension-placeholder": "^2.5.5", + "@tiptap/extension-strike": "^2.5.5", + "@tiptap/extension-text": "^2.5.5", + "@tiptap/extension-underline": "^2.5.5", + "@tiptap/extension-youtube": "^2.5.5", "@types/cookie": "^0.6.0", "@types/cookie-signature": "^1.1.2", "@types/node": "^20.14.11", @@ -102,7 +102,7 @@ "swiper": "^11.1.5", "throttle-debounce": "^5.0.2", "tslib": "^2.6.3", - "typescript": "^5.5.3", + "typescript": "^5.5.4", "typograf": "^7.4.1", "uniqolor": "^1.1.1", "vinxi": "^0.4.1", diff --git a/src/components/Article/Comment/Comment.tsx b/src/components/Article/Comment/Comment.tsx index 0a24765c..18693fa2 100644 --- a/src/components/Article/Comment/Comment.tsx +++ b/src/components/Article/Comment/Comment.tsx @@ -19,8 +19,7 @@ import { import { AuthorLink } from '../../Author/AuthorLink' import { Userpic } from '../../Author/Userpic' import { CommentDate } from '../CommentDate' -import { RatingControl as CommentRatingControl } from '../RatingControl' - +import { CommentRatingControl } from '../CommentRatingControl' import styles from './Comment.module.scss' const SimplifiedEditor = lazy(() => import('../../Editor/SimplifiedEditor')) diff --git a/src/components/Article/CommentRatingControl.tsx b/src/components/Article/CommentRatingControl.tsx new file mode 100644 index 00000000..08c8d555 --- /dev/null +++ b/src/components/Article/CommentRatingControl.tsx @@ -0,0 +1,122 @@ +import { clsx } from 'clsx' +import { createMemo } from 'solid-js' + +import { useFeed } from '~/context/feed' +import { useLocalize } from '~/context/localize' +import { useReactions } from '~/context/reactions' +import { useSession } from '~/context/session' +import { useSnackbar } from '~/context/ui' +import { Reaction, ReactionKind } from '~/graphql/schema/core.gen' +import { Popup } from '../_shared/Popup' +import { VotersList } from '../_shared/VotersList' + +import styles from './CommentRatingControl.module.scss' + +type Props = { + comment: Reaction +} + +export const CommentRatingControl = (props: Props) => { + const { t } = useLocalize() + const { loadShout } = useFeed() + const { session } = useSession() + const uid = createMemo(() => session()?.user?.app_data?.profile?.id || 0) + const { showSnackbar } = useSnackbar() + const { reactionEntities, createReaction, deleteReaction, loadReactionsBy } = useReactions() + + const checkReaction = (reactionKind: ReactionKind) => + Object.values(reactionEntities).some( + (r) => + r.kind === reactionKind && + r.created_by.id === uid() && + r.shout.id === props.comment.shout.id && + r.reply_to === props.comment.id + ) + const isUpvoted = createMemo(() => checkReaction(ReactionKind.Like)) + const isDownvoted = createMemo(() => checkReaction(ReactionKind.Dislike)) + const canVote = createMemo(() => uid() !== props.comment.created_by.id) + + const commentRatingReactions = createMemo(() => + Object.values(reactionEntities).filter( + (r) => + [ReactionKind.Like, ReactionKind.Dislike].includes(r.kind) && + r.shout.id === props.comment.shout.id && + r.reply_to === props.comment.id + ) + ) + + const deleteCommentReaction = async (reactionKind: ReactionKind) => { + const reactionToDelete = Object.values(reactionEntities).find( + (r) => + r.kind === reactionKind && + r.created_by.id === uid() && + r.shout.id === props.comment.shout.id && + r.reply_to === props.comment.id + ) + if (reactionToDelete) return deleteReaction(reactionToDelete.id) + } + + const handleRatingChange = async (isUpvote: boolean) => { + try { + if (isUpvoted()) { + await deleteCommentReaction(ReactionKind.Like) + } else if (isDownvoted()) { + await deleteCommentReaction(ReactionKind.Dislike) + } else { + await createReaction({ + reaction: { + kind: isUpvote ? ReactionKind.Like : ReactionKind.Dislike, + shout: props.comment.shout.id, + reply_to: props.comment.id + } + }) + } + } catch { + showSnackbar({ type: 'error', body: t('Error') }) + } + + await loadShout(props.comment.shout.slug) + await loadReactionsBy({ + by: { shout: props.comment.shout.slug } + }) + } + + return ( +
+
+ } + variant="tiny" + > + + + - - - changeSearchParams({ mode: 'login', m: 'auth' })}> - {t('Enter')} - - {lang() === 'ru' ? ', ' : ' '} - {t('to see the voters')} - - } - > - - - - - - ) -} diff --git a/src/components/Article/ShoutRatingControl.tsx b/src/components/Article/ShoutRatingControl.tsx new file mode 100644 index 00000000..b1302ed1 --- /dev/null +++ b/src/components/Article/ShoutRatingControl.tsx @@ -0,0 +1,107 @@ +import { clsx } from 'clsx' +import { Show, createMemo, createSignal } from 'solid-js' +import { useFeed } from '~/context/feed' +import { useLocalize } from '~/context/localize' +import { useReactions } from '~/context/reactions' +import { useSession } from '~/context/session' +import type { Author } from '~/graphql/schema/core.gen' +import { ReactionKind, Shout } from '~/graphql/schema/core.gen' +import { Icon } from '../_shared/Icon' +import { Popup } from '../_shared/Popup' +import { VotersList } from '../_shared/VotersList' + +import styles from './ShoutRatingControl.module.scss' + +interface ShoutRatingControlProps { + shout: Shout + class?: string +} + +export const ShoutRatingControl = (props: ShoutRatingControlProps) => { + const { t } = useLocalize() + const { loadShout } = useFeed() + const { requireAuthentication, session } = useSession() + const author = createMemo(() => session()?.user?.app_data?.profile as Author) + const { reactionEntities, createReaction, deleteReaction, loadReactionsBy } = useReactions() + const [isLoading, setIsLoading] = createSignal(false) + + const checkReaction = (reactionKind: ReactionKind) => + Object.values(reactionEntities).some( + (r) => + r.kind === reactionKind && + r.created_by.id === author()?.id && + r.shout.id === props.shout.id && + !r.reply_to + ) + + const isUpvoted = createMemo(() => checkReaction(ReactionKind.Like)) + const isDownvoted = createMemo(() => checkReaction(ReactionKind.Dislike)) + + const shoutRatingReactions = createMemo(() => + Object.values(reactionEntities).filter( + (r) => ['LIKE', 'DISLIKE'].includes(r.kind) && r.shout.id === props.shout.id && !r.reply_to + ) + ) + + const deleteShoutReaction = async (reactionKind: ReactionKind) => { + const reactionToDelete = Object.values(reactionEntities).find( + (r) => + r.kind === reactionKind && + r.created_by.id === author()?.id && + r.shout.id === props.shout.id && + !r.reply_to + ) + if (reactionToDelete) return deleteReaction(reactionToDelete.id) + } + + const handleRatingChange = (isUpvote: boolean) => { + requireAuthentication(async () => { + setIsLoading(true) + if (isUpvoted()) { + await deleteShoutReaction(ReactionKind.Like) + } else if (isDownvoted()) { + await deleteShoutReaction(ReactionKind.Dislike) + } else { + await createReaction({ + reaction: { + kind: isUpvote ? ReactionKind.Like : ReactionKind.Dislike, + shout: props.shout.id + } + }) + } + + loadShout(props.shout.slug) + loadReactionsBy({ + by: { shout: props.shout.slug } + }) + + setIsLoading(false) + }, 'vote') + } + + return ( +
+ + + {props.shout.stat?.rating || 0}} + variant="tiny" + > + + + + +
+ ) +} diff --git a/src/components/Author/AuthorBadge/AuthorBadge.tsx b/src/components/Author/AuthorBadge/AuthorBadge.tsx index ea9149b3..8531f3f5 100644 --- a/src/components/Author/AuthorBadge/AuthorBadge.tsx +++ b/src/components/Author/AuthorBadge/AuthorBadge.tsx @@ -26,6 +26,7 @@ type Props = { inviteView?: boolean onInvite?: (id: number) => void selected?: boolean + subscriptionsMode?: boolean } export const AuthorBadge = (props: Props) => { const { session, requireAuthentication } = useSession() @@ -116,7 +117,7 @@ export const AuthorBadge = (props: Props) => {
- +
0}>
{t('some posts', { count: props.author.stat?.shouts ?? 0 })}
diff --git a/src/components/Author/AuthorCard/AuthorCard.tsx b/src/components/Author/AuthorCard/AuthorCard.tsx index 4f87ec2c..405749a9 100644 --- a/src/components/Author/AuthorCard/AuthorCard.tsx +++ b/src/components/Author/AuthorCard/AuthorCard.tsx @@ -162,7 +162,7 @@ export const AuthorCard = (props: Props) => { {(subscription) => 'name' in subscription ? ( - + ) : ( ) diff --git a/src/components/Editor/SimplifiedEditor.tsx b/src/components/Editor/SimplifiedEditor.tsx index 1a1dc712..79db649f 100644 --- a/src/components/Editor/SimplifiedEditor.tsx +++ b/src/components/Editor/SimplifiedEditor.tsx @@ -1,4 +1,3 @@ -import { Editor } from '@tiptap/core' import { Blockquote } from '@tiptap/extension-blockquote' import { Bold } from '@tiptap/extension-bold' import { BubbleMenu } from '@tiptap/extension-bubble-menu' @@ -11,7 +10,7 @@ import { Paragraph } from '@tiptap/extension-paragraph' import { Placeholder } from '@tiptap/extension-placeholder' import { Text } from '@tiptap/extension-text' import { clsx } from 'clsx' -import { Show, Suspense, createEffect, createMemo, createSignal, onCleanup, onMount } from 'solid-js' +import { Show, createEffect, createMemo, createSignal, on, onCleanup, onMount } from 'solid-js' import { Portal } from 'solid-js/web' import { createEditorTransaction, @@ -20,23 +19,26 @@ import { useEditorIsEmpty, useEditorIsFocused } from 'solid-tiptap' -import { Modal } from '~/components/_shared/Modal' -import { useUI } from '~/context/ui' + +import { useEditorContext } from '~/context/editor' +import { useLocalize } from '~/context/localize' import { UploadedFile } from '~/types/upload' -import { useEditorContext } from '../../context/editor' -import { useLocalize } from '../../context/localize' import { Button } from '../_shared/Button' import { Icon } from '../_shared/Icon' import { Loading } from '../_shared/Loading' +import { Modal } from '../_shared/Modal' import { Popover } from '../_shared/Popover' import { ShowOnlyOnClient } from '../_shared/ShowOnlyOnClient' import { LinkBubbleMenuModule } from './LinkBubbleMenu' -import styles from './SimplifiedEditor.module.scss' import { TextBubbleMenu } from './TextBubbleMenu' import { UploadModalContent } from './UploadModalContent' import { Figcaption } from './extensions/Figcaption' import { Figure } from './extensions/Figure' +import { Editor } from '@tiptap/core' +import { useUI } from '~/context/ui' +import styles from './SimplifiedEditor.module.scss' + type Props = { placeholder: string initialContent?: string @@ -65,87 +67,98 @@ type Props = { const DEFAULT_MAX_LENGTH = 400 const SimplifiedEditor = (props: Props) => { - const maxLength = props.maxLength ?? DEFAULT_MAX_LENGTH - let wrapperEditorElRef: HTMLElement | undefined - let editorElRef: HTMLElement | undefined - let textBubbleMenuRef: HTMLDivElement | undefined - let linkBubbleMenuRef: HTMLDivElement | undefined - const { showModal, hideModal } = useUI() const { t } = useLocalize() + const { showModal, hideModal } = useUI() const [counter, setCounter] = createSignal(0) const [shouldShowLinkBubbleMenu, setShouldShowLinkBubbleMenu] = createSignal(false) const isCancelButtonVisible = createMemo(() => props.isCancelButtonVisible !== false) - const { setEditor, editor } = useEditorContext() + const [editorElement, setEditorElement] = createSignal() + const { editor, setEditor } = useEditorContext() + + const maxLength = props.maxLength ?? DEFAULT_MAX_LENGTH + let wrapperEditorElRef: HTMLElement | undefined + let textBubbleMenuRef: HTMLDivElement | undefined + let linkBubbleMenuRef: HTMLDivElement | undefined const ImageFigure = Figure.extend({ name: 'capturedImage', content: 'figcaption image' }) - createEffect(() => { - const e = createTiptapEditor(() => ({ - element: editorElRef as HTMLElement, - editorProps: { - attributes: { - class: styles.simplifiedEditorField + + createEffect( + on( + () => editorElement(), + (ee: HTMLDivElement | undefined) => { + if (ee && textBubbleMenuRef && linkBubbleMenuRef) { + const freshEditor = createTiptapEditor(() => ({ + element: ee, + editorProps: { + attributes: { + class: styles.simplifiedEditorField + } + }, + extensions: [ + Document, + Text, + Paragraph, + Bold, + Italic, + Link.extend({ + inclusive: false + }).configure({ + autolink: true, + openOnClick: false + }), + CharacterCount.configure({ + limit: props.noLimits ? null : maxLength + }), + Blockquote.configure({ + HTMLAttributes: { + class: styles.blockQuote + } + }), + BubbleMenu.configure({ + pluginKey: 'textBubbleMenu', + element: textBubbleMenuRef, + shouldShow: ({ view, state }) => { + if (!props.onlyBubbleControls) return false + const { selection } = state + const { empty } = selection + return view.hasFocus() && !empty + } + }), + BubbleMenu.configure({ + pluginKey: 'linkBubbleMenu', + element: linkBubbleMenuRef, + shouldShow: ({ state }) => { + const { selection } = state + const { empty } = selection + return !empty && shouldShowLinkBubbleMenu() + }, + tippyOptions: { + placement: 'bottom' + } + }), + ImageFigure, + Image, + Figcaption, + Placeholder.configure({ + emptyNodeClass: styles.emptyNode, + placeholder: props.placeholder + }) + ], + autofocus: props.autoFocus, + content: props.initialContent || null + })) + const editorInstance = freshEditor() + if (!editorInstance) return + setEditor(editorInstance) } }, - extensions: [ - Document, - Text, - Paragraph, - Bold, - Italic, - Link.extend({ - inclusive: false - }).configure({ - autolink: true, - openOnClick: false - }), - CharacterCount.configure({ - limit: props.noLimits ? null : maxLength - }), - Blockquote.configure({ - HTMLAttributes: { - class: styles.blockQuote - } - }), - BubbleMenu.configure({ - pluginKey: 'textBubbleMenu', - element: textBubbleMenuRef, - shouldShow: ({ view, state }) => { - if (!props.onlyBubbleControls) return false - const { selection } = state - const { empty } = selection - return view.hasFocus() && !empty - } - }), - BubbleMenu.configure({ - pluginKey: 'linkBubbleMenu', - element: linkBubbleMenuRef, - shouldShow: ({ state }) => { - const { selection } = state - const { empty } = selection - return !empty && shouldShowLinkBubbleMenu() - }, - tippyOptions: { - placement: 'bottom' - } - }), - ImageFigure, - Image, - Figcaption, - Placeholder.configure({ - emptyNodeClass: styles.emptyNode, - placeholder: props.placeholder - }) - ], - autofocus: props.autoFocus, - content: content ?? null - })) + { defer: true } + ) + ) - e() && setEditor(e() as Editor) - }) - const content = props.initialContent const isEmpty = useEditorIsEmpty(() => editor()) const isFocused = useEditorIsFocused(() => editor()) @@ -198,7 +211,7 @@ const SimplifiedEditor = (props: Props) => { } if (props.resetToInitial) { editor()?.commands.clearContent(true) - props.initialContent && editor()?.commands.setContent(props.initialContent) + if (props.initialContent) editor()?.commands.setContent(props.initialContent) } }) @@ -261,137 +274,133 @@ const SimplifiedEditor = (props: Props) => { return ( - -
(wrapperEditorElRef = el)} - class={clsx(styles.SimplifiedEditor, { - [styles.smallHeight]: props.smallHeight, - [styles.minimal]: props.variant === 'minimal', - [styles.bordered]: props.variant === 'bordered', - [styles.isFocused]: isFocused() || !isEmpty(), - [styles.labelVisible]: props.label && counter() > 0 - })} - > - -
{maxLength - counter()}
-
- 0}> -
{props.label}
-
- - (editorElRef = el)} />}> -
(editorElRef = el)} /> - - - -
-
- - {(triggerRef: (el: HTMLElement) => void) => ( - - )} - - +
(wrapperEditorElRef = el)} + class={clsx(styles.SimplifiedEditor, { + [styles.smallHeight]: props.smallHeight, + [styles.minimal]: props.variant === 'minimal', + [styles.bordered]: props.variant === 'bordered', + [styles.isFocused]: isFocused() || !isEmpty(), + [styles.labelVisible]: props.label && counter() > 0 + })} + > + +
{maxLength - counter()}
+
+ 0}> +
{props.label}
+
+
+ +
+
+ + {(triggerRef: (el: HTMLElement) => void) => ( + + )} + + + {(triggerRef) => ( + + )} + + + {(triggerRef) => ( + + )} + + + {(triggerRef) => ( )} - + + + {(triggerRef) => ( )} - - - {(triggerRef) => ( - - )} - - - - - {(triggerRef) => ( - - )} - - -
- -
- -
-
- - - - value && renderImage(value)} /> - - - - - - (textBubbleMenuRef = el)} - /> + +
+ +
- (linkBubbleMenuRef = el)} - onClose={handleHideLinkBubble} - /> -
-
- +
+ + + + + { + renderImage(value as UploadedFile) + }} + /> + + + + + (textBubbleMenuRef = el)} + /> + + (linkBubbleMenuRef = el)} + onClose={handleHideLinkBubble} + /> +
) } diff --git a/src/components/Feed/ArticleCard/ArticleCard.tsx b/src/components/Feed/ArticleCard/ArticleCard.tsx index 6f599901..7452067a 100644 --- a/src/components/Feed/ArticleCard/ArticleCard.tsx +++ b/src/components/Feed/ArticleCard/ArticleCard.tsx @@ -10,8 +10,8 @@ import type { Author, Maybe, Shout, Topic } from '~/graphql/schema/core.gen' import { capitalize } from '~/utils/capitalize' import { descFromBody } from '~/utils/meta' import { CoverImage } from '../../Article/CoverImage' -import { RatingControl as ShoutRatingControl } from '../../Article/RatingControl' import { SharePopup, getShareUrl } from '../../Article/SharePopup' +import { ShoutRatingControl } from '../../Article/ShoutRatingControl' import { AuthorLink } from '../../Author/AuthorLink' import stylesHeader from '../../HeaderNav/Header.module.scss' import { CardTopic } from '../CardTopic' diff --git a/src/components/HeaderNav/Header.module.scss b/src/components/HeaderNav/Header.module.scss index 1bf3481d..a4c8b461 100644 --- a/src/components/HeaderNav/Header.module.scss +++ b/src/components/HeaderNav/Header.module.scss @@ -753,12 +753,7 @@ white-space: nowrap; } - .rightItem { - margin-right: 0; - position: absolute; - right: 0; - top: 0; - } + } a:link, @@ -801,13 +796,6 @@ } } -.rightItemIcon { - display: inline-block; - margin-left: 0.3em; - position: relative; - top: 0.15em; -} - .editorPopup { border: 1px solid rgb(0 0 0 / 15%) !important; border-radius: 1.6rem; diff --git a/src/components/Views/AllAuthors/AllAuthors.tsx b/src/components/Views/AllAuthors/AllAuthors.tsx index d1c30b42..d81aac9c 100644 --- a/src/components/Views/AllAuthors/AllAuthors.tsx +++ b/src/components/Views/AllAuthors/AllAuthors.tsx @@ -18,6 +18,8 @@ import stylesAuthorList from './AuthorsList.module.scss' type Props = { authors: Author[] + authorsByFollowers?: Author[] + authorsByShouts?: Author[] isLoaded: boolean } @@ -33,43 +35,48 @@ export const AllAuthors = (props: Props) => { const [searchParams, changeSearchParams] = useSearchParams<{ by?: string }>() const { authorsSorted, setAuthorsSort, loadAuthors } = useAuthors() const [loading, setLoading] = createSignal(false) - const [searchQuery, setSearchQuery] = createSignal('') - const [filteredAuthors, setFilteredAuthors] = createSignal([]) + const [_currentAuthors, setCurrentAuthors] = createSignal([]) + // UPDATE Fetch authors initially and when searchParams.by changes createEffect(() => { - // Load all authors initially fetchAuthors(searchParams.by || 'name', 0) }) - /* const authors = createMemo(() => { - let sortedAuthors = [...props.authors] - sortedAuthors = authorsSorted() - if (!searchParams.by || searchParams.by === 'name') { + const authors = createMemo(() => { + let sortedAuthors = [...(props.authors || authorsSorted())] // Clone the array to avoid mutating the original + console.log('Before Sorting:', sortedAuthors.slice(0, 5)) // Log the first 5 authors for comparison + if (searchParams.by === 'name') { sortedAuthors = sortedAuthors.sort(byFirstChar) + console.log('Sorted by Name:', sortedAuthors.slice(0, 5)) } else if (searchParams.by === 'shouts') { sortedAuthors = sortedAuthors.sort(byStat('shouts')) + console.log('Sorted by Shouts:', sortedAuthors.slice(0, 5)) } else if (searchParams.by === 'followers') { sortedAuthors = sortedAuthors.sort(byStat('followers')) + console.log('Sorted by Followers:', sortedAuthors.slice(0, 5)) } - return sortedAuthors - }) */ - - const authors = createMemo(() => { - let sortedAuthors: Author[] = [] - if (!searchParams.by || searchParams.by === 'name') { - sortedAuthors = [...props.authors].sort(byFirstChar) - } else { - sortedAuthors = authorsSorted().sort(byStat(searchParams.by || 'shouts')) - } + console.log('After Sorting:', sortedAuthors.slice(0, 5)) return sortedAuthors }) + // Log authors data and searchParams for debugging createEffect(() => { - setFilteredAuthors(dummyFilter(authors(), searchQuery(), lang()) as Author[]) + console.log('Authors:', props.authors.slice(0, 5)) // Log the first 5 authors + console.log('Sorted Authors:', authors().slice(0, 5)) // Log the first 5 sorted authors + console.log('Search Params "by":', searchParams.by) }) + // filter + const [searchQuery, setSearchQuery] = createSignal('') + const [filteredAuthors, setFilteredAuthors] = createSignal([]) + createEffect( + () => authors() && setFilteredAuthors(dummyFilter(authors(), searchQuery(), lang()) as Author[]) + ) + + // store by first char const byLetterFiltered = createMemo<{ [letter: string]: Author[] }>(() => { if (!(filteredAuthors()?.length > 0)) return {} + console.debug('[components.AllAuthors] update byLetterFiltered', filteredAuthors()?.length) return filteredAuthors().reduce( (acc, author: Author) => authorLetterReduce(acc, author, lang()), {} as { [letter: string]: Author[] } @@ -86,6 +93,7 @@ export const AllAuthors = (props: Props) => { const fetchAuthors = async (queryType: string, page: number) => { try { + console.debug('[components.AuthorsList] fetching authors...') setLoading(true) setAuthorsSort?.(queryType) const offset = AUTHORS_PER_PAGE * page @@ -94,6 +102,8 @@ export const AllAuthors = (props: Props) => { limit: AUTHORS_PER_PAGE, offset }) + // UPDATE authors to currentAuthors state + setCurrentAuthors((prev) => [...prev, ...authorsSorted()]) } catch (error) { console.error('[components.AuthorsList] error fetching authors:', error) } finally { @@ -121,7 +131,7 @@ export const AllAuthors = (props: Props) => {
) - return ( <> }>
- }> + }> diff --git a/src/components/Views/Author/Author.tsx b/src/components/Views/Author/Author.tsx index 333c9afa..6cef65a1 100644 --- a/src/components/Views/Author/Author.tsx +++ b/src/components/Views/Author/Author.tsx @@ -61,7 +61,7 @@ export const AuthorView = (props: AuthorViewProps) => { on( [() => session()?.user?.app_data?.profile, () => props.authorSlug || ''], async ([me, slug]) => { - console.debug('[AuthorView] checking if my profile') + console.debug('check if my profile') const my = slug && me?.slug === slug if (my) { console.debug('[Author] my profile precached') @@ -86,7 +86,7 @@ export const AuthorView = (props: AuthorViewProps) => { () => authorsEntities()[props.author?.slug || props.authorSlug || ''], async (found) => { if (!found) return - console.debug('[AuthorView] ') + setAuthor(found) console.info(`[Author] profile for @${found.slug} fetched`) const followsResp = await query(getAuthorFollowsQuery, { slug: found.slug }).toPromise() const follows = followsResp?.data?.get_author_followers || {} @@ -96,7 +96,6 @@ export const AuthorView = (props: AuthorViewProps) => { setFollowers(followersResp?.data?.get_author_followers || []) console.info(`[Author] followers for @${found.slug} fetched`) setIsFetching(false) - setTimeout(() => setAuthor(found), 1) }, { defer: true } ) @@ -124,37 +123,7 @@ export const AuthorView = (props: AuthorViewProps) => { (tab) => tab && console.log('[views.Author] profile tab switched') ) ) - const AuthorFeed = () => ( - 0 && props.shouts[0]}> - - - - - - - - - - - - 3}> - - {(page) => ( - <> - - - - - - - - )} - - - - - ) return (
@@ -260,7 +229,34 @@ export const AuthorView = (props: AuthorViewProps) => {
- + 0 && props.shouts[0]}> + + + 1}> + + + + + + + + 3}> + + {(page) => ( + <> + + + + + + + + )} + + + + +
diff --git a/src/components/_shared/Icon/Icon.module.scss b/src/components/_shared/Icon/Icon.module.scss index bcf6c09e..b845ee7a 100644 --- a/src/components/_shared/Icon/Icon.module.scss +++ b/src/components/_shared/Icon/Icon.module.scss @@ -9,27 +9,6 @@ } } -.invert { - filter: invert(100%); -} - -.rotating { - /* Define the keyframes for the animation */ - @keyframes rotate { - from { - transform: rotate(0deg); - } - - to { - transform: rotate(360deg); - } - } - - /* Apply the animation to the element */ - animation: rotate .7s ease-out infinite; /* Rotate infinitely over 2 seconds using a linear timing function */ -} - - .notificationsCounter { @include media-breakpoint-up(md) { left: 1.8rem; diff --git a/src/components/_shared/Image/Image.tsx b/src/components/_shared/Image/Image.tsx index 97959e53..01966289 100644 --- a/src/components/_shared/Image/Image.tsx +++ b/src/components/_shared/Image/Image.tsx @@ -1,6 +1,8 @@ -import { Link } from '@solidjs/meta' import type { JSX } from 'solid-js' + +import { Link } from '@solidjs/meta' import { splitProps } from 'solid-js' + import { getImageUrl } from '~/lib/getThumbUrl' type Props = JSX.ImgHTMLAttributes & { diff --git a/src/components/_shared/LoadMoreWrapper.tsx b/src/components/_shared/LoadMoreWrapper.tsx index 0ad14020..9bb7887d 100644 --- a/src/components/_shared/LoadMoreWrapper.tsx +++ b/src/components/_shared/LoadMoreWrapper.tsx @@ -5,7 +5,6 @@ import { Author, Reaction, Shout } from '~/graphql/schema/core.gen' import { byCreated } from '~/lib/sort' import { SortFunction } from '~/types/common' import { restoreScrollPosition, saveScrollPosition } from '~/utils/scroll' -import { Loading } from './Loading' export type LoadMoreItems = Shout[] | Author[] | Reaction[] @@ -53,12 +52,14 @@ export const LoadMoreWrapper = (props: LoadMoreProps) => { return ( <> {props.children} - - - - +
-
diff --git a/src/context/authors.tsx b/src/context/authors.tsx index 0089c641..8287b443 100644 --- a/src/context/authors.tsx +++ b/src/context/authors.tsx @@ -125,7 +125,7 @@ export const AuthorsProvider = (props: { children: JSX.Element }) => { })) // Определяем функцию сортировки по рейтингу - const sortByRating: SortFunction<{ slug: string; rating: number }> = (a, b) => a.rating - b.rating + const sortByRating: SortFunction<{ slug: string; rating: number }> = (a, b) => b.rating - a.rating // Фильтруем и сортируем авторов const sortedTopAuthors = filterAndSort(authors, sortByRating) diff --git a/src/context/reactions.tsx b/src/context/reactions.tsx index 2605e8e0..b31515f8 100644 --- a/src/context/reactions.tsx +++ b/src/context/reactions.tsx @@ -2,12 +2,7 @@ import type { JSX } from 'solid-js' import { createContext, onCleanup, useContext } from 'solid-js' import { createStore, reconcile } from 'solid-js/store' -import { - loadCommentRatings, - loadReactions, - loadShoutComments, - loadShoutRatings -} from '~/graphql/api/public' +import { loadReactions } from '~/graphql/api/public' import createReactionMutation from '~/graphql/mutation/core/reaction-create' import destroyReactionMutation from '~/graphql/mutation/core/reaction-destroy' import updateReactionMutation from '~/graphql/mutation/core/reaction-update' @@ -22,16 +17,10 @@ import { useGraphQL } from './graphql' import { useLocalize } from './localize' import { useSnackbar } from './ui' -export const COMMENTS_PER_PAGE = 50 -export const RATINGS_PER_PAGE = 100 - type ReactionsContextType = { reactionEntities: Record reactionsByShout: Record loadReactionsBy: (args: QueryLoad_Reactions_ByArgs) => Promise - loadShoutComments: (shout: number, limit?: number, offset?: number) => Promise - loadShoutRatings: (shout: number, limit?: number, offset?: number) => Promise - loadCommentRatings: (comment: number, limit?: number, offset?: number) => Promise createReaction: (reaction: MutationCreate_ReactionArgs) => Promise updateReaction: (reaction: MutationUpdate_ReactionArgs) => Promise deleteReaction: (id: number) => Promise<{ error: string } | null> @@ -74,42 +63,6 @@ export const ReactionsProvider = (props: { children: JSX.Element }) => { return result } - const loadShoutRatingsAdding = async ( - shout: number, - limit = RATINGS_PER_PAGE, - offset = 0 - ): Promise => { - const fetcher = await loadShoutRatings({ shout, limit, offset }) - const result = (await fetcher()) || [] - console.debug('[context.reactions] shout ratings loaded', result) - result && addReactions(result) - return result - } - - const loadCommentRatingsAdding = async ( - comment: number, - limit = RATINGS_PER_PAGE, - offset = 0 - ): Promise => { - const fetcher = await loadCommentRatings({ comment, limit, offset }) - const result = (await fetcher()) || [] - console.debug('[context.reactions] shout ratings loaded', result) - result && addReactions(result) - return result - } - - const loadShoutCommentsAdding = async ( - shout: number, - limit = COMMENTS_PER_PAGE, - offset = 0 - ): Promise => { - const fetcher = await loadShoutComments({ shout, limit, offset }) - const result = (await fetcher()) || [] - console.debug('[context.reactions] shout comments loaded', result) - result && addReactions(result) - return result - } - const createReaction = async (input: MutationCreate_ReactionArgs): Promise => { const resp = await mutation(createReactionMutation, input).toPromise() const { error, reaction } = resp?.data?.create_reaction || {} @@ -169,9 +122,6 @@ export const ReactionsProvider = (props: { children: JSX.Element }) => { const actions = { loadReactionsBy, - loadShoutComments: loadShoutCommentsAdding, - loadShoutRatings: loadShoutRatingsAdding, - loadCommentRatings: loadCommentRatingsAdding, createReaction, updateReaction, deleteReaction, diff --git a/src/graphql/api/public.ts b/src/graphql/api/public.ts index 9d538a47..02fc58e9 100644 --- a/src/graphql/api/public.ts +++ b/src/graphql/api/public.ts @@ -1,14 +1,11 @@ import { cache } from '@solidjs/router' import { defaultClient } from '~/context/graphql' -import loadShoutCommentsQuery from '~/graphql/query/core/article-comments-load' import getShoutQuery from '~/graphql/query/core/article-load' -import loadShoutRatingsQuery from '~/graphql/query/core/article-ratings-load' import loadShoutsByQuery from '~/graphql/query/core/articles-load-by' import loadShoutsSearchQuery from '~/graphql/query/core/articles-load-search' import getAuthorQuery from '~/graphql/query/core/author-by' import loadAuthorsAllQuery from '~/graphql/query/core/authors-all' import loadAuthorsByQuery from '~/graphql/query/core/authors-load-by' -import loadCommentRatingsQuery from '~/graphql/query/core/comment-ratings-load' import loadReactionsByQuery from '~/graphql/query/core/reactions-load-by' import loadFollowersByTopicQuery from '~/graphql/query/core/topic-followers' import loadTopicsQuery from '~/graphql/query/core/topics-all' @@ -19,7 +16,6 @@ import { QueryGet_ShoutArgs, QueryLoad_Authors_ByArgs, QueryLoad_Reactions_ByArgs, - QueryLoad_Shout_RatingsArgs, QueryLoad_Shouts_SearchArgs, Reaction, Shout, @@ -61,39 +57,16 @@ export const loadShouts = (options: LoadShoutsOptions) => { }, `shouts-${filter}-${page}`) } -export const loadShoutComments = (options: QueryLoad_Shout_RatingsArgs) => { - const page = `${options.offset || 0}-${(options.limit || 1) + (options.offset || 0)}` - return cache(async () => { - const resp = await defaultClient.query(loadShoutCommentsQuery, options).toPromise() - const result = resp?.data?.load_reactions_by - if (result) return result as Reaction[] - }, `shout-${options.shout}-comments-${page}`) -} - -export const loadShoutRatings = (options: QueryLoad_Shout_RatingsArgs) => { - const page = `${options.offset || 0}-${(options.limit || 1) + (options.offset || 0)}` - return cache(async () => { - const resp = await defaultClient.query(loadShoutRatingsQuery, options).toPromise() - const result = resp?.data?.load_reactions_by - if (result) return result as Reaction[] - }, `shout-${options.shout}-ratings-${page}`) -} - -// biome-ignore lint/suspicious/noExplicitAny: FIXME: wait backend -export const loadCommentRatings = (options: any) => { - const page = `${options.offset || 0}-${(options.limit || 1) + (options.offset || 0)}` - return cache(async () => { - const resp = await defaultClient.query(loadCommentRatingsQuery, options).toPromise() - const result = resp?.data?.load_reactions_by - if (result) return result as Reaction[] - }, `comment-${options.comment}-ratings-${page}`) -} - export const loadReactions = (options: QueryLoad_Reactions_ByArgs) => { + if (!options.by) { + console.debug(options) + throw new Error('[api] wrong loadReactions call') + } const kind = options.by?.comment ? 'comments' : options.by?.rating ? 'votes' : 'reactions' const allorone = options.by?.shout ? `shout-${options.by.shout}` : 'all' const page = `${options.offset || 0}-${(options?.limit || 0) + (options.offset || 0)}` const filter = new URLSearchParams(options.by as Record) + // console.debug(options) return cache(async () => { const resp = await defaultClient.query(loadReactionsByQuery, options).toPromise() const result = resp?.data?.load_reactions_by @@ -102,6 +75,7 @@ export const loadReactions = (options: QueryLoad_Reactions_ByArgs) => { } export const getShout = (options: QueryGet_ShoutArgs) => { + // console.debug('[lib.api] get shout options', options) return cache( async () => { const resp = await defaultClient.query(getShoutQuery, { ...options }).toPromise() diff --git a/src/graphql/mutation/core/reaction-create.ts b/src/graphql/mutation/core/reaction-create.ts index e60824d1..72852d97 100644 --- a/src/graphql/mutation/core/reaction-create.ts +++ b/src/graphql/mutation/core/reaction-create.ts @@ -18,7 +18,6 @@ export default gql` slug } created_by { - id name slug pic diff --git a/src/graphql/mutation/core/reaction-destroy.ts b/src/graphql/mutation/core/reaction-destroy.ts index e3a608f8..be1b5828 100644 --- a/src/graphql/mutation/core/reaction-destroy.ts +++ b/src/graphql/mutation/core/reaction-destroy.ts @@ -1,8 +1,8 @@ import { gql } from '@urql/core' export default gql` - mutation DeleteReactionMutation($reaction: Int!) { - delete_reaction(reaction_id: $reaction) { + mutation DeleteReactionMutation($reaction_id: Int!) { + delete_reaction(reaction_id: $reaction_id) { error reaction { id diff --git a/src/graphql/query/core/article-comments-load.ts b/src/graphql/query/core/article-comments-load.ts deleted file mode 100644 index 8ffd4fd4..00000000 --- a/src/graphql/query/core/article-comments-load.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { gql } from '@urql/core' - -export default gql` - query LoadReactions($shout: Int!, $limit: Int, $offset: Int) { - load_shout_comments(shout: $shout, limit: $limit, offset: $offset) { - id - kind - body - reply_to - shout { - id - slug - title - } - created_by { - id - name - slug - pic - created_at - } - created_at - updated_at - stat { - rating - } - } - } -` diff --git a/src/graphql/query/core/article-ratings-load.ts b/src/graphql/query/core/article-ratings-load.ts deleted file mode 100644 index dddd8e67..00000000 --- a/src/graphql/query/core/article-ratings-load.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { gql } from '@urql/core' - -export default gql` - query LoadReactions($shout: Int!, $limit: Int, $offset: Int) { - load_shout_ratings(shout: $shout, limit: $limit, offset: $offset) { - id - kind - body - reply_to - shout { - id - slug - title - } - created_by { - id - name - slug - pic - created_at - } - created_at - updated_at - stat { - rating - } - } - } -` diff --git a/src/graphql/query/core/comment-ratings-load.ts b/src/graphql/query/core/comment-ratings-load.ts deleted file mode 100644 index b1eb12ee..00000000 --- a/src/graphql/query/core/comment-ratings-load.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { gql } from '@urql/core' - -export default gql` - query LoadReactions($comment: Int!, $limit: Int, $offset: Int) { - load_comment_ratings(comment: $comment, limit: $limit, offset: $offset) { - id - kind - body - reply_to - shout { - id - slug - title - } - created_by { - id - name - slug - pic - created_at - } - created_at - updated_at - stat { - rating - } - } - } -` diff --git a/src/graphql/query/core/reactions-load-by.ts b/src/graphql/query/core/reactions-load-by.ts index 0ef15693..c0700f07 100644 --- a/src/graphql/query/core/reactions-load-by.ts +++ b/src/graphql/query/core/reactions-load-by.ts @@ -13,7 +13,6 @@ export default gql` title } created_by { - id name slug pic diff --git a/src/intl/locales/ru/translation.json b/src/intl/locales/ru/translation.json index e108c0ae..f1bf6452 100644 --- a/src/intl/locales/ru/translation.json +++ b/src/intl/locales/ru/translation.json @@ -456,7 +456,7 @@ "Theory": "Теории", "There are unsaved changes in your profile settings. Are you sure you want to leave the page without saving?": "В настройках вашего профиля есть несохраненные изменения. Уверены, что хотите покинуть страницу без сохранения?", "There are unsaved changes in your publishing settings. Are you sure you want to leave the page without saving?": "В настройках публикации есть несохраненные изменения. Уверены, что хотите покинуть страницу без сохранения?", - "This comment has not been rated yet": "Этот комментарий еще пока никто не оценил", + "This comment has not yet been rated": "Этот комментарий еще пока никто не оценил", "This content is not published yet": "Содержимое ещё не опубликовано", "This email is": "Этот email", "This email is not verified": "Этот email не подтвержден", diff --git a/src/lib/sort.ts b/src/lib/sort.ts index 27235f92..8c34e79d 100644 --- a/src/lib/sort.ts +++ b/src/lib/sort.ts @@ -34,7 +34,7 @@ export const byStat = (metric: string) => { return (a: { stat?: SomeStat }, b: { stat?: SomeStat }) => { const aStat = a.stat?.[metric] ?? 0 const bStat = b.stat?.[metric] ?? 0 - return bStat - aStat + return aStat - bStat } } diff --git a/src/routes/author/(all-authors).tsx b/src/routes/author/(all-authors).tsx index 35e7ce27..931d77b5 100644 --- a/src/routes/author/(all-authors).tsx +++ b/src/routes/author/(all-authors).tsx @@ -1,29 +1,38 @@ -import { RouteDefinition, RoutePreloadFuncArgs, type RouteSectionProps, createAsync } from '@solidjs/router' +import { RouteDefinition, RouteLoadFuncArgs, type RouteSectionProps, createAsync } from '@solidjs/router' import { Suspense, createEffect, on } from 'solid-js' import { AllAuthors } from '~/components/Views/AllAuthors' +import { AUTHORS_PER_PAGE } from '~/components/Views/AllAuthors/AllAuthors' import { Loading } from '~/components/_shared/Loading' import { PageLayout } from '~/components/_shared/PageLayout' import { useAuthors } from '~/context/authors' import { useLocalize } from '~/context/localize' -import { loadAuthorsAll } from '~/graphql/api/public' -import { Author } from '~/graphql/schema/core.gen' +import { loadAuthors, loadAuthorsAll } from '~/graphql/api/public' +import { Author, AuthorsBy } from '~/graphql/schema/core.gen' + +const fetchAuthorsWithStat = async (offset = 0, order?: string) => { + const by: AuthorsBy = { order } + const authorsFetcher = loadAuthors({ by, offset, limit: AUTHORS_PER_PAGE }) + return await authorsFetcher() +} -// Fetch Function const fetchAllAuthors = async () => { const authorsAllFetcher = loadAuthorsAll() return await authorsAllFetcher() } -//Route Defenition export const route = { - load: async ({ location: { query: _q } }: RoutePreloadFuncArgs) => { + load: async ({ location: { query } }: RouteLoadFuncArgs) => { + const by = query.by + const isAll = !by || by === 'name' return { - authors: await fetchAllAuthors() - } + authors: isAll && (await fetchAllAuthors()), + authorsByFollowers: await fetchAuthorsWithStat(10, 'followers'), + authorsByShouts: await fetchAuthorsWithStat(10, 'shouts') + } as AllAuthorsData } } satisfies RouteDefinition -type AllAuthorsData = { authors: Author[] } +type AllAuthorsData = { authors: Author[]; authorsByFollowers: Author[]; authorsByShouts: Author[] } // addAuthors to context @@ -31,20 +40,25 @@ export default function AllAuthorsPage(props: RouteSectionProps) const { t } = useLocalize() const { addAuthors } = useAuthors() + // async load data: from ssr or fetch const data = createAsync(async () => { if (props.data) return props.data - const authors = await fetchAllAuthors() return { - authors: authors || [] - } + authors: await fetchAllAuthors(), + authorsByFollowers: await fetchAuthorsWithStat(10, 'followers'), + authorsByShouts: await fetchAuthorsWithStat(10, 'shouts') + } as AllAuthorsData }) + // update context when data is loaded createEffect( on( [data, () => addAuthors], ([data, aa]) => { if (data && aa) { aa(data.authors as Author[]) + aa(data.authorsByFollowers as Author[]) + aa(data.authorsByShouts as Author[]) console.debug('[routes.author] added all authors:', data.authors) } }, @@ -59,7 +73,12 @@ export default function AllAuthorsPage(props: RouteSectionProps) desc="List of authors of the open editorial community" > }> - + ) diff --git a/src/routes/author/[slug]/[...tab].tsx b/src/routes/author/[slug]/[...tab].tsx index b81a0fb4..01f68af2 100644 --- a/src/routes/author/[slug]/[...tab].tsx +++ b/src/routes/author/[slug]/[...tab].tsx @@ -1,5 +1,5 @@ -import { RouteSectionProps, createAsync } from '@solidjs/router' -import { ErrorBoundary, createEffect, createMemo } from 'solid-js' +import { RouteSectionProps } from '@solidjs/router' +import { ErrorBoundary, createEffect, createMemo, createSignal, on } from 'solid-js' import { AuthorView } from '~/components/Views/Author' import { FourOuFourView } from '~/components/Views/FourOuFour' import { LoadMoreItems, LoadMoreWrapper } from '~/components/_shared/LoadMoreWrapper' @@ -32,7 +32,6 @@ const fetchAllTopics = async () => { const fetchAuthor = async (slug: string) => { const authorFetcher = loadAuthors({ by: { slug }, limit: 1, offset: 0 } as QueryLoad_Authors_ByArgs) const aaa = await authorFetcher() - console.debug(aaa) return aaa?.[0] } @@ -50,20 +49,11 @@ export const route = { export type AuthorPageProps = { articles?: Shout[]; author?: Author; topics?: Topic[] } export default function AuthorPage(props: RouteSectionProps) { - const { authorsEntities } = useAuthors() - const { addFeed, feedByAuthor } = useFeed() + const { addAuthor, authorsEntities } = useAuthors() + const [author, setAuthor] = createSignal(undefined) + const { t } = useLocalize() - const author = createAsync( - async () => - props.data.author || authorsEntities()[props.params.slug] || (await fetchAuthor(props.params.slug)) - ) - const shoutsByAuthor = createMemo(() => feedByAuthor()[props.params.slug]) const title = createMemo(() => `${author()?.name || ''}`) - const cover = createMemo(() => - author()?.pic - ? getImageUrl(author()?.pic || '', { width: 1200 }) - : getImageUrl('production/image/logo_image.png') - ) createEffect(() => { if (author()) { @@ -76,7 +66,32 @@ export default function AuthorPage(props: RouteSectionProps) { } }) + const cover = createMemo(() => + author()?.pic + ? getImageUrl(author()?.pic || '', { width: 1200 }) + : getImageUrl('production/image/logo_image.png') + ) + // author shouts + const { addFeed, feedByAuthor } = useFeed() + const shoutsByAuthor = createMemo(() => feedByAuthor()[props.params.slug]) + + createEffect( + on( + [() => props.params.slug || '', author], + async ([slug, profile]) => { + if (!profile) { + const loadedAuthor = authorsEntities()[slug] || (await fetchAuthor(slug)) + if (loadedAuthor) { + addAuthor(loadedAuthor) + setAuthor(loadedAuthor) + } + } + }, + { defer: true } + ) + ) + const loadAuthorShoutsMore = async (offset: number) => { const loadedShouts = await fetchAuthorShouts(props.params.slug, offset) loadedShouts && addFeed(loadedShouts) diff --git a/src/routes/feed/[...order].tsx b/src/routes/feed/[...order].tsx index 26327de1..bd466b56 100644 --- a/src/routes/feed/[...order].tsx +++ b/src/routes/feed/[...order].tsx @@ -125,7 +125,7 @@ export default (props: RouteSectionProps<{ shouts: Shout[]; topics: Topic[] }>) key="feed" desc="Independent media project about culture, science, art and society with horizontal editing" > -