From e6459a5b63235755ca0e8acfa59db2d56ec40713 Mon Sep 17 00:00:00 2001 From: Konata <1025090504@qq.com> Date: Sat, 28 Sep 2024 00:22:20 +0800 Subject: [PATCH 01/88] feat(user-profile): smoother height switching (#674) --- apps/renderer/src/modules/profile/user-profile-modal.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/renderer/src/modules/profile/user-profile-modal.tsx b/apps/renderer/src/modules/profile/user-profile-modal.tsx index 6dfb1a9b0..aca92a8df 100644 --- a/apps/renderer/src/modules/profile/user-profile-modal.tsx +++ b/apps/renderer/src/modules/profile/user-profile-modal.tsx @@ -234,7 +234,7 @@ export const UserProfileModalContent: FC<{
@@ -242,7 +242,7 @@ export const UserProfileModalContent: FC<{ asChild className={cn("aspect-square", isHeaderSimple ? "size-12" : "size-16")} > - + Date: Sat, 28 Sep 2024 04:22:39 +0800 Subject: [PATCH 02/88] fix: add i18n in preview-media (#675) --- apps/renderer/src/components/ui/media/preview-media.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/renderer/src/components/ui/media/preview-media.tsx b/apps/renderer/src/components/ui/media/preview-media.tsx index 5cda99490..7ee043a22 100644 --- a/apps/renderer/src/components/ui/media/preview-media.tsx +++ b/apps/renderer/src/components/ui/media/preview-media.tsx @@ -2,6 +2,7 @@ import type { MediaModel } from "@follow/shared/hono" import type { FC } from "react" import { Fragment, useCallback, useEffect, useRef, useState } from "react" import { Blurhash } from "react-blurhash" +import { useTranslation } from "react-i18next" import { Keyboard, Mousewheel } from "swiper/modules" import type { SwiperRef } from "swiper/react" import { Swiper, SwiperSlide } from "swiper/react" @@ -25,6 +26,7 @@ const Wrapper: Component<{ entryId?: string }> = ({ children, src, showActions, entryId }) => { const { dismiss } = useCurrentModal() + const { t } = useTranslation(["shortcuts", "external"]) return (
@@ -50,7 +52,7 @@ const Wrapper: Component<{ {!!window.electron && ( { tipcClient?.download(src) }} @@ -59,7 +61,7 @@ const Wrapper: Component<{ )} { window.open(src) }} From 033887693bc805d3217a4251447bb1e7da00db9a Mon Sep 17 00:00:00 2001 From: Stephen Zhou Date: Sat, 28 Sep 2024 09:06:56 +0800 Subject: [PATCH 03/88] fix: proxy sp1.piokok.com and video preview url --- apps/renderer/src/components/ui/media.tsx | 16 ++++++++++++++-- packages/shared/src/image.ts | 4 ++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/apps/renderer/src/components/ui/media.tsx b/apps/renderer/src/components/ui/media.tsx index db7ec6474..f3fe45ba0 100644 --- a/apps/renderer/src/components/ui/media.tsx +++ b/apps/renderer/src/components/ui/media.tsx @@ -61,6 +61,18 @@ const MediaImpl: FC = ({ : src, ) + const previewImageSrc = useMemo( + () => + proxy && previewImageUrl + ? getImageProxyUrl({ + url: previewImageUrl, + width: proxy.width, + height: proxy.height, + }) + : previewImageUrl, + [previewImageUrl, proxy], + ) + const [mediaLoadState, setMediaLoadState] = useState<"loading" | "loaded" | "error">("loading") const errorHandle: React.ReactEventHandler = useEventCallback((e) => { if (imgSrc !== props.src) { @@ -135,7 +147,7 @@ const MediaImpl: FC = ({ )} onClick={handleClick} > - + ) } @@ -151,7 +163,7 @@ const MediaImpl: FC = ({ mediaContainerClassName, mediaLoadState, popper, - previewImageUrl, + previewImageSrc, props.height, props.width, rest, diff --git a/packages/shared/src/image.ts b/packages/shared/src/image.ts index c42b7427c..77b1d27c2 100644 --- a/packages/shared/src/image.ts +++ b/packages/shared/src/image.ts @@ -15,4 +15,8 @@ export const imageRefererMatches = [ url: /^https:\/\/(?:\w|-)+\.cdninstagram\.com/, referer: "https://www.instagram.com", }, + { + url: /^https:\/\/sp1\.piokok\.com/, + referer: "https://sp1.piokok.com", + }, ] From 36593cc05a1b94545266e65008ef4a52f80cfbfe Mon Sep 17 00:00:00 2001 From: Wenxuan Shen Date: Sat, 28 Sep 2024 10:37:53 +0800 Subject: [PATCH 04/88] feat(i18n): Chinese: Update translation (#679) --- locales/settings/zh-CN.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/locales/settings/zh-CN.json b/locales/settings/zh-CN.json index 51431edf9..90195f7b9 100644 --- a/locales/settings/zh-CN.json +++ b/locales/settings/zh-CN.json @@ -156,12 +156,13 @@ "lists.created.error": "创建列表失败", "lists.created.success": "创建列表成功", "lists.description": "描述", + "lists.earnings": "收入", "lists.edit.error": "编辑列表失败", "lists.edit.label": "编辑", "lists.edit.success": "编辑列表成功", "lists.fee.description": "其他人订阅这个列表时要支付的费用", "lists.fee.label": "费用", - "lists.feeds.actions": "自动化", + "lists.feeds.actions": "操作", "lists.feeds.add.error": "添加订阅源到列表时失败", "lists.feeds.add.label": "添加", "lists.feeds.add.success": "订阅源已添加到列表", @@ -177,6 +178,7 @@ "lists.info": "列表是一类可以分享或出售给他人订阅的订阅集合。订阅者将会同步和访问该列表中的所有订阅源。", "lists.noLists": "没有列表", "lists.submit": "提交", + "lists.subscriptions": "订阅", "lists.title": "标题", "lists.view": "视图", "profile.avatar.label": "头像", From b214c0db01edafced973ed9075ff6be3959c5f61 Mon Sep 17 00:00:00 2001 From: Zach Date: Sat, 28 Sep 2024 11:39:53 +0800 Subject: [PATCH 05/88] fix(i18n): add native french support (#670) Signed-off-by: Zach --- locales/native/fr.json | 68 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 locales/native/fr.json diff --git a/locales/native/fr.json b/locales/native/fr.json new file mode 100644 index 000000000..5a0ea9515 --- /dev/null +++ b/locales/native/fr.json @@ -0,0 +1,68 @@ +{ + "contextMenu.copy": "Copier", + "contextMenu.copyImage": "Copier l'image", + "contextMenu.copyImageAddress": "Copier l'adresse de l'image", + "contextMenu.copyLink": "Copier le lien", + "contextMenu.copyVideoAddress": "Copier l'adresse de la vidéo", + "contextMenu.cut": "Couper", + "contextMenu.inspect": "Inspecter l'élément", + "contextMenu.learnSpelling": "Apprendre l'orthographe", + "contextMenu.lookUpSelection": "Rechercher la sélection", + "contextMenu.openImageInBrowser": "Ouvrir l'image dans le navigateur", + "contextMenu.openLinkInBrowser": "Ouvrir le lien dans le navigateur", + "contextMenu.paste": "Coller", + "contextMenu.saveImage": "Enregistrer l'image", + "contextMenu.saveImageAs": "Enregistrer l'image sous...", + "contextMenu.saveLinkAs": "Enregistrer le lien sous...", + "contextMenu.saveVideo": "Enregistrer la vidéo", + "contextMenu.saveVideoAs": "Enregistrer la vidéo sous...", + "contextMenu.searchWithGoogle": "Rechercher avec Google", + "contextMenu.selectAll": "Tout sélectionner", + "contextMenu.services": "Services", + "dialog.clearAllData": "Êtes-vous sûr de vouloir effacer toutes les données ?", + "dialog.no": "Non", + "dialog.yes": "Oui", + "menu.about": "À propos de {{name}}", + "menu.actualSize": "Taille réelle", + "menu.bringAllToFront": "Tout ramener au premier plan", + "menu.checkForUpdates": "Vérifier les mises à jour", + "menu.clearAllData": "Effacer toutes les données", + "menu.close": "Fermer", + "menu.copy": "Copier", + "menu.cut": "Couper", + "menu.debug": "Déboguer", + "menu.delete": "Supprimer", + "menu.discover": "Découvrir", + "menu.edit": "Édition", + "menu.file": "Fichier", + "menu.followReleases": "Suivre les versions", + "menu.forceReload": "Forcer le rechargement", + "menu.front": "Mettre au premier plan", + "menu.help": "Aide", + "menu.hide": "Masquer {{name}}", + "menu.hideOthers": "Masquer les autres", + "menu.minimize": "Réduire", + "menu.openLogFile": "Ouvrir le fichier journal", + "menu.paste": "Coller", + "menu.pasteAndMatchStyle": "Coller et adapter le style", + "menu.quickAdd": "Ajout rapide", + "menu.quit": "Quitter {{name}}", + "menu.quitAndInstallUpdate": "Débogage : Quitter et installer la mise à jour", + "menu.redo": "Rétablir", + "menu.reload": "Recharger", + "menu.search": "Rechercher", + "menu.selectAll": "Tout sélectionner", + "menu.services": "Services", + "menu.settings": "Paramètres...", + "menu.speech": "Parole", + "menu.startSpeaking": "Commencer à parler", + "menu.stopSpeaking": "Arrêter de parler", + "menu.toggleDevTools": "Afficher/Masquer les outils de développement", + "menu.toggleFullScreen": "Basculer en mode plein écran", + "menu.undo": "Annuler", + "menu.view": "Affichage", + "menu.window": "Fenêtre", + "menu.zoom": "Zoom", + "menu.zoomIn": "Zoom avant", + "menu.zoomOut": "Zoom arrière" +} From a4ce7b16f476b8d72a0b1761709ec1ceba591242 Mon Sep 17 00:00:00 2001 From: Innei Date: Sat, 28 Sep 2024 12:51:33 +0800 Subject: [PATCH 06/88] fix(ci): nightly build Signed-off-by: Innei --- .github/workflows/nightly.yml | 47 +++++++++++------------------------ 1 file changed, 14 insertions(+), 33 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 0b56da27c..5be5b9140 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -13,22 +13,7 @@ env: NODE_OPTIONS: --max-old-space-size=8192 jobs: - check-for-changes: - runs-on: ubuntu-latest - # outputs: - # should_run: ${{ steps.check.outputs.should_run }} - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - # - name: Check for code changes - # id: check - # run: | - # git diff --quiet @{1.day.ago} HEAD -- ':!.github' || echo "should_run=true" >> $GITHUB_OUTPUT - nightly-release: - # needs: check-for-changes - # if: needs.check-for-changes.outputs.should_run == 'true' runs-on: ${{ matrix.os }} strategy: @@ -107,25 +92,20 @@ jobs: shell: bash run: | # Get the current version from package.json - if [ -f package.json ]; then - CURRENT_VERSION=$(node -p "require('./package.json').version") - # Remove any existing prerelease identifier (e.g., -alpha.1) - BASE_VERSION=$(echo $CURRENT_VERSION | sed -E 's/(-[a-zA-Z]+\.[0-9]+)$//') - # Generate the nightly version - NIGHTLY_DATE=$(date +'%Y%m%d') - NIGHTLY_VERSION="${BASE_VERSION}-nightly.${NIGHTLY_DATE}" - echo "NIGHTLY_VERSION=$NIGHTLY_VERSION" >> $GITHUB_ENV - # Update version in package.json - if [[ "$RUNNER_OS" == "Windows" ]]; then - sed -i "s/\"version\": \".*\"/\"version\": \"$NIGHTLY_VERSION\"/" package.json - else - sed -i '' "s/\"version\": \".*\"/\"version\": \"$NIGHTLY_VERSION\"/" package.json - fi - echo "Updated version to $NIGHTLY_VERSION" + CURRENT_VERSION=$(node -p "require('./package.json').version") + # Remove any existing prerelease identifier (e.g., -alpha.1) + BASE_VERSION=$(echo $CURRENT_VERSION | sed -E 's/(-[a-zA-Z]+\.[0-9]+)$//') + # Generate the nightly version + NIGHTLY_DATE=$(date +'%Y%m%d') + NIGHTLY_VERSION="${BASE_VERSION}-nightly.${NIGHTLY_DATE}" + echo "NIGHTLY_VERSION=$NIGHTLY_VERSION" >> $GITHUB_ENV + # Update version in package.json + if [[ "$RUNNER_OS" == "Windows" ]]; then + sed -i "s/\"version\": \".*\"/\"version\": \"$NIGHTLY_VERSION\"/" package.json else - echo "package.json not found" - exit 1 + sed -i '' "s/\"version\": \".*\"/\"version\": \"$NIGHTLY_VERSION\"/" package.json fi + echo "Updated version to $NIGHTLY_VERSION" - name: Build if: matrix.os != 'macos-latest' @@ -171,6 +151,7 @@ jobs: name: Nightly ${{ env.NIGHTLY_VERSION }} draft: false prerelease: true + tag_name: nightly-${{ env.NIGHTLY_VERSION }} files: | out/make/**/*.dmg out/make/**/*.zip @@ -179,7 +160,7 @@ jobs: out/make/**/*.yml body: | This is an automated nightly release for testing purposes. - Version: ${{ env.NIGHTLY_VERSION }} + Version: 0.0.0-nightly.${{ env.NIGHTLY_VERSION }} **Warning:** This build may be unstable and is not recommended for production use. env: From 7c76761ae748ac043c3adf6df00065920e03f18c Mon Sep 17 00:00:00 2001 From: Innei Date: Sat, 28 Sep 2024 13:45:42 +0800 Subject: [PATCH 07/88] chore: update deps Signed-off-by: Innei --- apps/main/package.json | 6 +- apps/renderer/package.json | 32 +- package.json | 22 +- packages/shared/package.json | 5 +- pnpm-lock.yaml | 2485 ++++++++++++++++++---------------- 5 files changed, 1333 insertions(+), 1217 deletions(-) diff --git a/apps/main/package.json b/apps/main/package.json index 5b2376d30..bc5600d57 100644 --- a/apps/main/package.json +++ b/apps/main/package.json @@ -42,17 +42,17 @@ "msedge-tts": "1.3.4", "nanoid": "5.0.7", "ofetch": "1.4.0", - "posthog-js": "1.163.0", + "posthog-js": "1.165.0", "posthog-node": "4.2.0", "semver": "7.6.3", "vscode-languagedetection": "npm:@vscode/vscode-languagedetection@^1.0.22" }, "devDependencies": { "@types/lodash-es": "4.17.12", - "@types/node": "^22.5.5", + "@types/node": "^22.7.4", "electron": "32.1.2", "electron-devtools-installer": "3.2.0", - "hono": "4.6.2", + "hono": "4.6.3", "typescript": "^5.6.2" } } diff --git a/apps/renderer/package.json b/apps/renderer/package.json index 2d9feadac..500e6bfb3 100644 --- a/apps/renderer/package.json +++ b/apps/renderer/package.json @@ -16,8 +16,8 @@ "@headlessui/react": "2.1.8", "@hono/auth-js": "1.0.10", "@hookform/resolvers": "3.9.0", - "@iconify/tools": "4.0.6", - "@lottiefiles/dotlottie-react": "0.8.12", + "@iconify/tools": "4.0.7", + "@lottiefiles/dotlottie-react": "0.9.0", "@microflash/remark-callout-directives": "4.3.1", "@mozilla/readability": "^0.5.0", "@radix-ui/react-alert-dialog": "1.1.1", @@ -38,13 +38,13 @@ "@radix-ui/react-tabs": "1.1.0", "@radix-ui/react-toast": "1.2.1", "@radix-ui/react-tooltip": "1.1.2", - "@sentry/react": "8.30.0", + "@sentry/react": "8.32.0", "@sentry/vite-plugin": "2.22.4", - "@shikijs/transformers": "1.18.0", + "@shikijs/transformers": "1.20.0", "@t3-oss/env-core": "^0.11.1", "@tanstack/query-sync-storage-persister": "5.56.2", "@tanstack/react-query": "5.56.2", - "@tanstack/react-query-devtools": "5.56.2", + "@tanstack/react-query-devtools": "5.58.0", "@tanstack/react-query-persist-client": "5.56.2", "@use-gesture/react": "10.3.1", "@yornaath/batshit": "0.10.1", @@ -54,10 +54,10 @@ "cmdk": "1.0.0", "dayjs": "1.11.13", "dexie": "4.0.8", - "dnum": "^2.13.1", + "dnum": "^2.14.0", "electron-log": "5.2.0", "foxact": "0.2.38", - "framer-motion": "11.5.6", + "framer-motion": "11.9.0", "franc-min": "6.2.0", "fuse.js": "7.0.0", "hast-util-to-jsx-runtime": "2.3.0", @@ -73,9 +73,9 @@ "masonic": "4.0.1", "nanoid": "5.0.7", "ofetch": "1.4.0", - "path-to-regexp": "8.1.0", - "posthog-js": "1.163.0", - "re-resizable": "6.9.18", + "path-to-regexp": "8.2.0", + "posthog-js": "1.165.0", + "re-resizable": "6.10.0", "react-blurhash": "^0.3.0", "react-error-boundary": "4.0.13", "react-fast-marquee": "1.6.5", @@ -89,19 +89,19 @@ "react-shadow": "20.5.0", "react-virtuoso": "4.10.4", "rehype-infer-description-meta": "2.0.0", - "rehype-parse": "9.0.0", + "rehype-parse": "9.0.1", "rehype-sanitize": "6.0.0", - "rehype-stringify": "10.0.0", + "rehype-stringify": "10.0.1", "remark-directive": "3.0.0", "remark-gfm": "4.0.0", "remark-gh-alerts": "0.0.3", "remark-parse": "11.0.0", "remark-rehype": "11.1.1", - "shiki": "1.18.0", + "shiki": "1.20.0", "sonner": "^1.5.0", "swiper": "11.1.14", "tailwind-merge": "2.5.2", - "tldts": "6.1.47", + "tldts": "6.1.48", "unified": "11.0.5", "use-context-selector": "2.0.0", "usehooks-ts": "3.1.0", @@ -113,8 +113,8 @@ "@babel/generator": "7.25.6", "@hono/node-server": "1.13.1", "@types/lodash-es": "4.17.12", - "@types/node": "^22.5.5", - "@types/react": "^18.3.8", + "@types/node": "^22.7.4", + "@types/react": "^18.3.10", "@types/react-dom": "^18.3.0", "fake-indexeddb": "6.0.0", "react": "^18.3.1", diff --git a/package.json b/package.json index 86c9c6265..c36b42e74 100644 --- a/package.json +++ b/package.json @@ -53,8 +53,8 @@ "@hookform/resolvers": "3.9.0", "@iconify-json/logos": "1.2.0", "@iconify-json/mingcute": "1.2.0", - "@iconify-json/simple-icons": "^1.2.3", - "@iconify/tools": "4.0.6", + "@iconify-json/simple-icons": "^1.2.4", + "@iconify/tools": "4.0.7", "@microflash/remark-callout-directives": "4.3.1", "@mozilla/readability": "^0.5.0", "@pengx17/electron-forge-maker-appimage": "1.2.1", @@ -63,23 +63,23 @@ "@tailwindcss/container-queries": "0.1.1", "@tailwindcss/typography": "0.5.15", "@types/lodash-es": "4.17.12", - "@types/node": "^22.5.5", - "@types/react": "^18.3.8", + "@types/node": "^22.7.4", + "@types/react": "^18.3.10", "@types/react-dom": "^18.3.0", "@vitejs/plugin-legacy": "5.4.2", "@vitejs/plugin-react": "^4.3.1", "cssnano": "7.0.6", - "dnum": "^2.13.1", + "dnum": "^2.14.0", "dotenv": "16.4.5", "drizzle-orm": "0.33.0", "electron": "32.1.2", "electron-devtools-installer": "3.2.0", "electron-packager-languages": "0.5.0", "electron-vite": "^2.3.0", - "eslint": "^9.11.0", - "eslint-config-hyoban": "^3.1.6", + "eslint": "^9.11.1", + "eslint-config-hyoban": "^3.1.7", "fake-indexeddb": "6.0.0", - "hono": "4.6.2", + "hono": "4.6.3", "lint-staged": "15.2.10", "nbump": "2.0.4", "postcss": "8.4.47", @@ -90,13 +90,13 @@ "rimraf": "6.0.1", "shx": "^0.3.4", "simple-git-hooks": "2.11.1", - "tailwindcss": "3.4.12", + "tailwindcss": "3.4.13", "tailwindcss-animate": "1.0.7", "tsup": "8.3.0", "tsx": "4.19.1", "typescript": "^5.6.2", - "vite": "^5.4.7", - "vite-bundle-analyzer": "0.10.6", + "vite": "^5.4.8", + "vite-bundle-analyzer": "0.12.1", "vite-plugin-mkcert": "1.17.6", "vite-tsconfig-paths": "5.0.1", "vitest": "2.0" diff --git a/packages/shared/package.json b/packages/shared/package.json index 42f490379..c13a64135 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -31,11 +31,10 @@ "@t3-oss/env-core": "^0.11.1", "drizzle-orm": "^0.33.0", "electron": "^32.1.2", - "hono": "^4.6.2", + "hono": "^4.6.3", "react": "^18.3.1", "react-dom": "^18.3.1", "sonner": "^1.5.0", "zod": "^3.23.8" - }, - "devDependencies": {} + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 57c4b0a54..c1bcce26c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,7 +40,7 @@ importers: version: 0.7.0 '@egoist/tailwindcss-icons': specifier: 1.8.1 - version: 1.8.1(tailwindcss@3.4.12) + version: 1.8.1(tailwindcss@3.4.13) '@electron-forge/cli': specifier: 7.5.0 version: 7.5.0(encoding@0.1.13) @@ -61,13 +61,13 @@ importers: version: 7.5.0(encoding@0.1.13) '@electron-toolkit/tsconfig': specifier: ^1.0.1 - version: 1.0.1(@types/node@22.5.5) + version: 1.0.1(@types/node@22.7.4) '@fontsource/sn-pro': specifier: 5.1.0 version: 5.1.0 '@hono/node-server': specifier: 1.13.1 - version: 1.13.1(hono@4.6.2(patch_hash=iej2g43ojhll5opwbnvyorjq4e)) + version: 1.13.1(hono@4.6.3(patch_hash=iej2g43ojhll5opwbnvyorjq4e)) '@hookform/resolvers': specifier: 3.9.0 version: 3.9.0(react-hook-form@7.53.0(react@18.3.1)) @@ -78,11 +78,11 @@ importers: specifier: 1.2.0 version: 1.2.0 '@iconify-json/simple-icons': - specifier: ^1.2.3 - version: 1.2.3 + specifier: ^1.2.4 + version: 1.2.4 '@iconify/tools': - specifier: 4.0.6 - version: 4.0.6 + specifier: 4.0.7 + version: 4.0.7 '@microflash/remark-callout-directives': specifier: 4.3.1 version: 4.3.1 @@ -100,40 +100,40 @@ importers: version: 0.11.1(typescript@5.6.2)(zod@3.23.8) '@tailwindcss/container-queries': specifier: 0.1.1 - version: 0.1.1(tailwindcss@3.4.12) + version: 0.1.1(tailwindcss@3.4.13) '@tailwindcss/typography': specifier: 0.5.15 - version: 0.5.15(tailwindcss@3.4.12) + version: 0.5.15(tailwindcss@3.4.13) '@types/lodash-es': specifier: 4.17.12 version: 4.17.12 '@types/node': - specifier: ^22.5.5 - version: 22.5.5 + specifier: ^22.7.4 + version: 22.7.4 '@types/react': - specifier: ^18.3.8 - version: 18.3.8 + specifier: ^18.3.10 + version: 18.3.10 '@types/react-dom': specifier: ^18.3.0 version: 18.3.0 '@vitejs/plugin-legacy': specifier: 5.4.2 - version: 5.4.2(terser@5.32.0)(vite@5.4.7(@types/node@22.5.5)(terser@5.32.0)) + version: 5.4.2(terser@5.34.1)(vite@5.4.8(@types/node@22.7.4)(terser@5.34.1)) '@vitejs/plugin-react': specifier: ^4.3.1 - version: 4.3.1(vite@5.4.7(@types/node@22.5.5)(terser@5.32.0)) + version: 4.3.1(vite@5.4.8(@types/node@22.7.4)(terser@5.34.1)) cssnano: specifier: 7.0.6 version: 7.0.6(postcss@8.4.47) dnum: - specifier: ^2.13.1 - version: 2.13.1 + specifier: ^2.14.0 + version: 2.14.0 dotenv: specifier: 16.4.5 version: 16.4.5 drizzle-orm: specifier: 0.33.0 - version: 0.33.0(@opentelemetry/api@1.9.0)(@types/pg@8.11.8)(@types/react@18.3.8)(react@18.3.1) + version: 0.33.0(@opentelemetry/api@1.9.0)(@types/pg@8.11.10)(@types/react@18.3.10)(react@18.3.1) electron: specifier: 32.1.2 version: 32.1.2 @@ -145,19 +145,19 @@ importers: version: 0.5.0 electron-vite: specifier: ^2.3.0 - version: 2.3.0(vite@5.4.7(@types/node@22.5.5)(terser@5.32.0)) + version: 2.3.0(vite@5.4.8(@types/node@22.7.4)(terser@5.34.1)) eslint: - specifier: ^9.11.0 - version: 9.11.0(jiti@1.21.6) + specifier: ^9.11.1 + version: 9.11.1(jiti@2.0.0) eslint-config-hyoban: - specifier: ^3.1.6 - version: 3.1.6(@typescript-eslint/eslint-plugin@8.6.0(@typescript-eslint/parser@8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2))(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2))(eslint@9.11.0(jiti@1.21.6))(tailwindcss@3.4.12)(typescript@5.6.2) + specifier: ^3.1.7 + version: 3.1.7(@typescript-eslint/eslint-plugin@8.7.0(@typescript-eslint/parser@8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2))(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2))(eslint@9.11.1(jiti@2.0.0))(tailwindcss@3.4.13)(typescript@5.6.2) fake-indexeddb: specifier: 6.0.0 version: 6.0.0 hono: - specifier: 4.6.2 - version: 4.6.2(patch_hash=iej2g43ojhll5opwbnvyorjq4e) + specifier: 4.6.3 + version: 4.6.3(patch_hash=iej2g43ojhll5opwbnvyorjq4e) lint-staged: specifier: 15.2.10 version: 15.2.10 @@ -189,14 +189,14 @@ importers: specifier: 2.11.1 version: 2.11.1 tailwindcss: - specifier: 3.4.12 - version: 3.4.12 + specifier: 3.4.13 + version: 3.4.13 tailwindcss-animate: specifier: 1.0.7 - version: 1.0.7(tailwindcss@3.4.12) + version: 1.0.7(tailwindcss@3.4.13) tsup: specifier: 8.3.0 - version: 8.3.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1)(typescript@5.6.2)(yaml@2.5.1) + version: 8.3.0(jiti@2.0.0)(postcss@8.4.47)(tsx@4.19.1)(typescript@5.6.2)(yaml@2.5.1) tsx: specifier: 4.19.1 version: 4.19.1 @@ -204,20 +204,20 @@ importers: specifier: ^5.6.2 version: 5.6.2 vite: - specifier: ^5.4.7 - version: 5.4.7(@types/node@22.5.5)(terser@5.32.0) + specifier: ^5.4.8 + version: 5.4.8(@types/node@22.7.4)(terser@5.34.1) vite-bundle-analyzer: - specifier: 0.10.6 - version: 0.10.6 + specifier: 0.12.1 + version: 0.12.1 vite-plugin-mkcert: specifier: 1.17.6 - version: 1.17.6(vite@5.4.7(@types/node@22.5.5)(terser@5.32.0)) + version: 1.17.6(vite@5.4.8(@types/node@22.7.4)(terser@5.34.1)) vite-tsconfig-paths: specifier: 5.0.1 - version: 5.0.1(typescript@5.6.2)(vite@5.4.7(@types/node@22.5.5)(terser@5.32.0)) + version: 5.0.1(typescript@5.6.2)(vite@5.4.8(@types/node@22.7.4)(terser@5.34.1)) vitest: specifier: '2.0' - version: 2.0.5(@types/node@22.5.5)(terser@5.32.0) + version: 2.0.5(@types/node@22.7.4)(terser@5.34.1) apps/main: dependencies: @@ -285,8 +285,8 @@ importers: specifier: 1.4.0 version: 1.4.0 posthog-js: - specifier: 1.163.0 - version: 1.163.0 + specifier: 1.165.0 + version: 1.165.0 posthog-node: specifier: 4.2.0 version: 4.2.0 @@ -301,8 +301,8 @@ importers: specifier: 4.17.12 version: 4.17.12 '@types/node': - specifier: ^22.5.5 - version: 22.5.5 + specifier: ^22.7.4 + version: 22.7.4 electron: specifier: 32.1.2 version: 32.1.2 @@ -310,8 +310,8 @@ importers: specifier: 3.2.0 version: 3.2.0 hono: - specifier: 4.6.2 - version: 4.6.2(patch_hash=iej2g43ojhll5opwbnvyorjq4e) + specifier: 4.6.3 + version: 4.6.3(patch_hash=iej2g43ojhll5opwbnvyorjq4e) typescript: specifier: ^5.6.2 version: 5.6.2 @@ -338,16 +338,16 @@ importers: version: 2.1.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@hono/auth-js': specifier: 1.0.10 - version: 1.0.10(@auth/core@0.34.2)(hono@4.6.2(patch_hash=iej2g43ojhll5opwbnvyorjq4e))(react@18.3.1) + version: 1.0.10(@auth/core@0.35.3)(hono@4.6.3(patch_hash=iej2g43ojhll5opwbnvyorjq4e))(react@18.3.1) '@hookform/resolvers': specifier: 3.9.0 version: 3.9.0(react-hook-form@7.53.0(react@18.3.1)) '@iconify/tools': - specifier: 4.0.6 - version: 4.0.6 + specifier: 4.0.7 + version: 4.0.7 '@lottiefiles/dotlottie-react': - specifier: 0.8.12 - version: 0.8.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 0.9.0 + version: 0.9.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@microflash/remark-callout-directives': specifier: 4.3.1 version: 4.3.1 @@ -356,67 +356,67 @@ importers: version: 0.5.0(patch_hash=fgkvsbckled47trggkhdkimzbm) '@radix-ui/react-alert-dialog': specifier: 1.1.1 - version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-avatar': specifier: 1.1.0 - version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-checkbox': specifier: 1.1.1 - version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-context-menu': specifier: 2.2.1 - version: 2.2.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 2.2.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-dialog': specifier: 1.1.1 - version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-dropdown-menu': specifier: 2.1.1 - version: 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-hover-card': specifier: 1.1.1 - version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-label': specifier: 2.1.0 - version: 2.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 2.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-popover': specifier: 1.1.1 - version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-radio-group': specifier: 1.2.0 - version: 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-scroll-area': specifier: 1.1.0 - version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-select': specifier: 2.1.1 - version: 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slider': specifier: ^1.2.0 - version: 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slot': specifier: 1.1.0 - version: 1.1.0(@types/react@18.3.8)(react@18.3.1) + version: 1.1.0(@types/react@18.3.10)(react@18.3.1) '@radix-ui/react-switch': specifier: 1.1.0 - version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-tabs': specifier: 1.1.0 - version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-toast': specifier: 1.2.1 - version: 1.2.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.2.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-tooltip': specifier: 1.1.2 - version: 1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@sentry/react': - specifier: 8.30.0 - version: 8.30.0(react@18.3.1) + specifier: 8.32.0 + version: 8.32.0(react@18.3.1) '@sentry/vite-plugin': specifier: 2.22.4 version: 2.22.4(encoding@0.1.13) '@shikijs/transformers': - specifier: 1.18.0 - version: 1.18.0 + specifier: 1.20.0 + version: 1.20.0 '@t3-oss/env-core': specifier: ^0.11.1 version: 0.11.1(typescript@5.6.2)(zod@3.23.8) @@ -427,8 +427,8 @@ importers: specifier: 5.56.2 version: 5.56.2(react@18.3.1) '@tanstack/react-query-devtools': - specifier: 5.56.2 - version: 5.56.2(@tanstack/react-query@5.56.2(react@18.3.1))(react@18.3.1) + specifier: 5.58.0 + version: 5.58.0(@tanstack/react-query@5.56.2(react@18.3.1))(react@18.3.1) '@tanstack/react-query-persist-client': specifier: 5.56.2 version: 5.56.2(@tanstack/react-query@5.56.2(react@18.3.1))(react@18.3.1) @@ -443,13 +443,13 @@ importers: version: 0.7.0 click-to-react-component: specifier: 1.1.0 - version: 1.1.0(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.0(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) clsx: specifier: 2.1.1 version: 2.1.1 cmdk: specifier: 1.0.0 - version: 1.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) dayjs: specifier: 1.11.13 version: 1.11.13 @@ -457,8 +457,8 @@ importers: specifier: 4.0.8 version: 4.0.8 dnum: - specifier: ^2.13.1 - version: 2.13.1 + specifier: ^2.14.0 + version: 2.14.0 electron-log: specifier: 5.2.0 version: 5.2.0 @@ -466,8 +466,8 @@ importers: specifier: 0.2.38 version: 0.2.38(react@18.3.1) framer-motion: - specifier: 11.5.6 - version: 11.5.6(@emotion/is-prop-valid@0.8.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 11.9.0 + version: 11.9.0(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) franc-min: specifier: 6.2.0 version: 6.2.0 @@ -494,7 +494,7 @@ importers: version: 10.1.1(patch_hash=og7mbnoo5vh43tjlw5rbmrdbvu) jotai: specifier: 2.10.0 - version: 2.10.0(@types/react@18.3.8)(react@18.3.1) + version: 2.10.0(@types/react@18.3.10)(react@18.3.1) lethargy: specifier: 1.0.9 version: 1.0.9 @@ -514,14 +514,14 @@ importers: specifier: 1.4.0 version: 1.4.0 path-to-regexp: - specifier: 8.1.0 - version: 8.1.0 + specifier: 8.2.0 + version: 8.2.0 posthog-js: - specifier: 1.163.0 - version: 1.163.0 + specifier: 1.165.0 + version: 1.165.0 re-resizable: - specifier: 6.9.18 - version: 6.9.18(patch_hash=yitcmpfwcomg2fky72uc3lhk2i)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 6.10.0 + version: 6.10.0(patch_hash=yitcmpfwcomg2fky72uc3lhk2i)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-blurhash: specifier: ^0.3.0 version: 0.3.0(blurhash@2.0.5)(react@18.3.1) @@ -562,14 +562,14 @@ importers: specifier: 2.0.0 version: 2.0.0 rehype-parse: - specifier: 9.0.0 - version: 9.0.0 + specifier: 9.0.1 + version: 9.0.1 rehype-sanitize: specifier: 6.0.0 version: 6.0.0 rehype-stringify: - specifier: 10.0.0 - version: 10.0.0 + specifier: 10.0.1 + version: 10.0.1 remark-directive: specifier: 3.0.0 version: 3.0.0 @@ -586,8 +586,8 @@ importers: specifier: 11.1.1 version: 11.1.1 shiki: - specifier: 1.18.0 - version: 1.18.0 + specifier: 1.20.0 + version: 1.20.0 sonner: specifier: ^1.5.0 version: 1.5.0(patch_hash=6s3tquyt5wnkqaogymn3mkivuq)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -598,8 +598,8 @@ importers: specifier: 2.5.2 version: 2.5.2 tldts: - specifier: 6.1.47 - version: 6.1.47 + specifier: 6.1.48 + version: 6.1.48 unified: specifier: 11.0.5 version: 11.0.5 @@ -617,23 +617,23 @@ importers: version: 3.23.8 zustand: specifier: 4.5.5 - version: 4.5.5(@types/react@18.3.8)(immer@10.1.1(patch_hash=og7mbnoo5vh43tjlw5rbmrdbvu))(react@18.3.1) + version: 4.5.5(@types/react@18.3.10)(immer@10.1.1(patch_hash=og7mbnoo5vh43tjlw5rbmrdbvu))(react@18.3.1) devDependencies: '@babel/generator': specifier: 7.25.6 version: 7.25.6 '@hono/node-server': specifier: 1.13.1 - version: 1.13.1(hono@4.6.2(patch_hash=iej2g43ojhll5opwbnvyorjq4e)) + version: 1.13.1(hono@4.6.3(patch_hash=iej2g43ojhll5opwbnvyorjq4e)) '@types/lodash-es': specifier: 4.17.12 version: 4.17.12 '@types/node': - specifier: ^22.5.5 - version: 22.5.5 + specifier: ^22.7.4 + version: 22.7.4 '@types/react': - specifier: ^18.3.8 - version: 18.3.8 + specifier: ^18.3.10 + version: 18.3.10 '@types/react-dom': specifier: ^18.3.0 version: 18.3.0 @@ -657,22 +657,22 @@ importers: version: 3.0.1(electron@32.1.2) '@electron-toolkit/tsconfig': specifier: ^1.0.1 - version: 1.0.1(@types/node@22.5.5) + version: 1.0.1(@types/node@22.7.4) '@hono/node-server': specifier: ^1.13.1 - version: 1.13.1(hono@4.6.2(patch_hash=iej2g43ojhll5opwbnvyorjq4e)) + version: 1.13.1(hono@4.6.3(patch_hash=iej2g43ojhll5opwbnvyorjq4e)) '@t3-oss/env-core': specifier: ^0.11.1 version: 0.11.1(typescript@5.6.2)(zod@3.23.8) drizzle-orm: specifier: ^0.33.0 - version: 0.33.0(@opentelemetry/api@1.9.0)(@types/pg@8.11.8)(@types/react@18.3.8)(react@18.3.1) + version: 0.33.0(@opentelemetry/api@1.9.0)(@types/pg@8.11.10)(@types/react@18.3.10)(react@18.3.1) electron: specifier: ^32.1.2 version: 32.1.2 hono: - specifier: ^4.6.2 - version: 4.6.2(patch_hash=iej2g43ojhll5opwbnvyorjq4e) + specifier: ^4.6.3 + version: 4.6.3(patch_hash=iej2g43ojhll5opwbnvyorjq4e) react: specifier: ^18.3.1 version: 18.3.1 @@ -708,8 +708,8 @@ packages: '@antfu/utils@0.7.10': resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==} - '@auth/core@0.34.2': - resolution: {integrity: sha512-KywHKRgLiF3l7PLyL73fjLSIBe1YNcA6sMeew4yMP6cfCWGXZrkkXd32AjRi1hlJ9nvovUBGZHvbn+LijO6ZeQ==} + '@auth/core@0.35.3': + resolution: {integrity: sha512-g6qfiqU4OtyvIEZ8J7UoIwAxEnNnLJV0/f/DW41U+4G5nhBlaCrnKhawJIJpU0D3uavXLeDT3B0BkjtiimvMDA==} peerDependencies: '@simplewebauthn/browser': ^9.0.1 '@simplewebauthn/server': ^9.0.2 @@ -1536,11 +1536,11 @@ packages: engines: {node: '>=14.14'} hasBin: true - '@emotion/is-prop-valid@0.8.8': - resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==} + '@emotion/is-prop-valid@1.3.1': + resolution: {integrity: sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==} - '@emotion/memoize@0.7.4': - resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==} + '@emotion/memoize@0.9.0': + resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} '@es-joy/jsdoccomment@0.48.0': resolution: {integrity: sha512-G6QUWIcC+KvSwXNsJyDTHvqUdNoAVJPPgkc3+Uk4WBKqZvoXhlvazOgm9aL0HwihJLQf0l+tOE2UFzXBqCqgDw==} @@ -1834,18 +1834,18 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.11.0': - resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==} + '@eslint-community/regexpp@4.11.1': + resolution: {integrity: sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint-react/ast@1.14.1': - resolution: {integrity: sha512-FzhWRl/kBF5cZky4G/I5kkRiwVUTjGNfP+fwwx94NImaH1CvnMk6ataBNNtvxXKrbWGpZSexT4vHjotfZTEXMA==} + '@eslint-react/ast@1.14.2': + resolution: {integrity: sha512-waFjfqN9estBOSPHB2QzLm0s+10rEK86qzww/BkSLAORZLSftxQ1YrAL7vECBw+7G8RI1ehEh6s5ZFkBedUirA==} - '@eslint-react/core@1.14.1': - resolution: {integrity: sha512-SK19+40fAYWtliPV9cRIZr0cnKIBkQJE8XWr0R2QobrWw2tkKKYqCLWwR0TpuxrjAd/JpG5TTcPHAgffCRtliw==} + '@eslint-react/core@1.14.2': + resolution: {integrity: sha512-DpyKNgYB+bYrBEhvlTzqcifzNuYH9GF0y4lyIeWD8Pr72M5zjMD8NgpzT6h+2Vx0TVcW12Ej8Kd86BsEqhmZPQ==} - '@eslint-react/eslint-plugin@1.14.1': - resolution: {integrity: sha512-aMuUJrSbUCj/+S4McaMNuEg2R8JA8aZVLgdLf5bYuNi7YYpZ7kIMaKdlLW53UlaER9kRb8lrorFUL3cyg7Yc4w==} + '@eslint-react/eslint-plugin@1.14.2': + resolution: {integrity: sha512-q8bIJYfMr4YBfLlqG+cIStp+8/J1trgSqkbZQy6C6+DVP/AtWB+Gqq3a5qshpbJ0WVbtbZ4Yed61hxhZCnxsZA==} engines: {bun: '>=1.0.15', node: '>=18.18.0'} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -1854,20 +1854,20 @@ packages: typescript: optional: true - '@eslint-react/jsx@1.14.1': - resolution: {integrity: sha512-NN8pIM3gZDk7Zusd2fFBaA78Zv98PxBDEBP/lxwSZNkuuUtgrHEBYWKRYs10hz1B6Vp1bvhIcnLO/BQThvJJog==} + '@eslint-react/jsx@1.14.2': + resolution: {integrity: sha512-Uu2URP5q935fK2NK59BZqjIwrRkD3zarCqmlZfig0Hy2vrllf8mileKkC7kAoIFhc8A6ilGLwaRdMWvEAVbR2A==} - '@eslint-react/shared@1.14.1': - resolution: {integrity: sha512-gceHz2fZeJh+EwxQC+ozh+cFbnpDALnDxpamDFxZI1QRdy0wtrB0MjJFSSZ9F6WUITWxoic2T3071U9BCjI3/Q==} + '@eslint-react/shared@1.14.2': + resolution: {integrity: sha512-VTN5QflFLgFHWKgnWwt/8sMedeT+7mn4/yrQ6ZrHhia95hDAW9fprMJtNR3AkJ30vnc/1x9I0KUisEvT1u3Cgw==} - '@eslint-react/tools@1.14.1': - resolution: {integrity: sha512-4kutt+JCXuLatE6fBuNJ6IA2+ndgdymEvq/HQuhW2Xs6+pEqaxwrHT2GeaQbc5U8pfJCEWAYvYX1r0XF/v9gJQ==} + '@eslint-react/tools@1.14.2': + resolution: {integrity: sha512-AgtqWGZEywBfECIbmrtqLeJdPRQkCsfgUzmKxEjHTgMV4nqt5nKirYVnAUxS5/HSs/OqNUM6l+awFFCnCEuLjQ==} - '@eslint-react/types@1.14.1': - resolution: {integrity: sha512-WWw6e8/EHMIMOmN3SvvfiNyKJdQOrt1ugTAJIPHnNyKzOgCKhpN0xbtIQY3ghjhAm3GBO87aWB42q6a/YZd00w==} + '@eslint-react/types@1.14.2': + resolution: {integrity: sha512-YPfdPYUHTXw+5KT+WgLJrRQAJcTyQ2rzUDAUq7Cl2x71J88USXzja8D7KNDFA9S+eeF5eaUVc9LJo3Uz7eq4Dw==} - '@eslint-react/var@1.14.1': - resolution: {integrity: sha512-dzjwC4XM5v3aT1pc+1JxV3aZne4eyjiu+/ajkpCgnDM7Cual63uaHNBTE4LBUQiA2/oYU4iHAa9EcEn31k3EhA==} + '@eslint-react/var@1.14.2': + resolution: {integrity: sha512-OOxwTPcWoNJbpaWnULpq+QJzsdZveU/QCHZ6Lb1oNIdVPBc6nCKz3PH97hqYFpk3q+gnnNx2q6qhNIAfeu/8Ug==} '@eslint/compat@1.1.1': resolution: {integrity: sha512-lpHyRyplhGPL5mGEh6M9O5nnKk0Gz4bFI+Zu6tKlPpDUN7XshWvH9C/px4UVm87IAANE0W81CEsNGbS1KlzXpA==} @@ -1877,16 +1877,16 @@ packages: resolution: {integrity: sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/core@0.6.0': + resolution: {integrity: sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/eslintrc@3.1.0': resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.10.0': - resolution: {integrity: sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/js@9.11.0': - resolution: {integrity: sha512-LPkkenkDqyzTFauZLLAPhIb48fj6drrfMvRGSL9tS3AcZBSVTllemLSNyCvHNNL2t797S/6DJNSIwRwXgMO/eQ==} + '@eslint/js@9.11.1': + resolution: {integrity: sha512-/qu+TWz8WwPWc7/HcIJKi+c+MOm46GdVaSlTTQcaqaL53+GsoA6MxWp5PtTx48qbSP7ylM1Kn7nhvkugfJvRSA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.4': @@ -2005,11 +2005,11 @@ packages: '@iconify-json/mingcute@1.2.0': resolution: {integrity: sha512-XEAOnEMwkv8BkHaeBZqiyVytrCBH8GffhUr7ozWeU77s5vodYq9J/hdWVK/cTah7PwcYSrzfXBkXjIek+u3+XQ==} - '@iconify-json/simple-icons@1.2.3': - resolution: {integrity: sha512-KZpqyPkDdyAvrpMz9/FYovwFsr3xrHf9esJeBng3iqNInhuZhF33XO1k6Yf8g2p10ynUW7AYEiGJkYzDi4DENQ==} + '@iconify-json/simple-icons@1.2.4': + resolution: {integrity: sha512-AKUGO7cX2KykFEJ+P6tY3wGhGgbrL3RMqbxNTfutGsKojaSEFosN/cmWQ9l9hmUiS2IN7fVLsPMAIvV1uJyyVw==} - '@iconify/tools@4.0.6': - resolution: {integrity: sha512-riEQggXVuZNXjRdo+aKT0rkzn2XHslIqat8mdW/oVu5mLmP/95Hi+iaq4keT7WwMD97jsYPXMQ6QMCw0EWpRNw==} + '@iconify/tools@4.0.7': + resolution: {integrity: sha512-zOJxKIfZn96ZRGGvIWzDRLD9vb2CsxjcLuM+QIdvwWbv6SWhm49gECzUnd4d2P0sq9sfodT7yCNobWK8nvavxQ==} '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} @@ -2017,6 +2017,9 @@ packages: '@iconify/utils@2.1.32': resolution: {integrity: sha512-LeifFZPPKu28O3AEDpYJNdEbvS4/ojAPyIW+pF/vUpJTYnbTiXUHkCh0bwgFRzKvdpb8H4Fbfd/742++MF4fPQ==} + '@iconify/utils@2.1.33': + resolution: {integrity: sha512-jP9h6v/g0BIZx0p7XGJJVtkVnydtbgTgt9mVNcGDYwaa7UhdHdI9dvoq+gKj9sijMSJKxUPEG2JyjsgXjxL7Kw==} + '@innei/react-resizable-layout@0.7.3-fork.1': resolution: {integrity: sha512-xBgY0+prk58+Hq235dmdi9AI60xYxqGEYxP44t2+3IqZoa/MUNC3FbGz1ICFGhaQurY/hUPQGOawZNVmcw8tNw==} peerDependencies: @@ -2048,14 +2051,14 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - '@lottiefiles/dotlottie-react@0.8.12': - resolution: {integrity: sha512-6S9q5mH2l8JDnKAruAq4NP7bzHVzJNUt8UsXONfveSyJPUgT5hGw5b5vCjW19Ra3hgN/d69qUtRLHfmyRAgblQ==} + '@lottiefiles/dotlottie-react@0.9.0': + resolution: {integrity: sha512-6vR3XA7YWWvv76TkNPKC6Hc4CU0WXJlVydYmEezgi6RZS+Au3IUsCxZBr/3Zt2JPvtS3mttvP4X7tfeTA+414g==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - '@lottiefiles/dotlottie-web@0.33.0': - resolution: {integrity: sha512-/KerIs0UkmwuDKYWlNGWYSSZkZaLNXXHqg6qCnP7P2JuzgI4bHRmlIk3+LoJjl/jWqd3WyI4t5oRV6ch0sQwvg==} + '@lottiefiles/dotlottie-web@0.34.0': + resolution: {integrity: sha512-lKayn0IaqFKcnLGxJKKaDlxwKqKBpHzZ7COMEZ0HYhd3cbI9GFJb9YDUgtdpzTH5uL9Eqnr19myWYmEXHPm9pQ==} '@malept/cross-spawn-promise@1.1.1': resolution: {integrity: sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==} @@ -3116,81 +3119,161 @@ packages: cpu: [arm] os: [android] + '@rollup/rollup-android-arm-eabi@4.22.5': + resolution: {integrity: sha512-SU5cvamg0Eyu/F+kLeMXS7GoahL+OoizlclVFX3l5Ql6yNlywJJ0OuqTzUx0v+aHhPHEB/56CT06GQrRrGNYww==} + cpu: [arm] + os: [android] + '@rollup/rollup-android-arm64@4.21.2': resolution: {integrity: sha512-xGU5ZQmPlsjQS6tzTTGwMsnKUtu0WVbl0hYpTPauvbRAnmIvpInhJtgjj3mcuJpEiuUw4v1s4BimkdfDWlh7gA==} cpu: [arm64] os: [android] + '@rollup/rollup-android-arm64@4.22.5': + resolution: {integrity: sha512-S4pit5BP6E5R5C8S6tgU/drvgjtYW76FBuG6+ibG3tMvlD1h9LHVF9KmlmaUBQ8Obou7hEyS+0w+IR/VtxwNMQ==} + cpu: [arm64] + os: [android] + '@rollup/rollup-darwin-arm64@4.21.2': resolution: {integrity: sha512-99AhQ3/ZMxU7jw34Sq8brzXqWH/bMnf7ZVhvLk9QU2cOepbQSVTns6qoErJmSiAvU3InRqC2RRZ5ovh1KN0d0Q==} cpu: [arm64] os: [darwin] + '@rollup/rollup-darwin-arm64@4.22.5': + resolution: {integrity: sha512-250ZGg4ipTL0TGvLlfACkIxS9+KLtIbn7BCZjsZj88zSg2Lvu3Xdw6dhAhfe/FjjXPVNCtcSp+WZjVsD3a/Zlw==} + cpu: [arm64] + os: [darwin] + '@rollup/rollup-darwin-x64@4.21.2': resolution: {integrity: sha512-ZbRaUvw2iN/y37x6dY50D8m2BnDbBjlnMPotDi/qITMJ4sIxNY33HArjikDyakhSv0+ybdUxhWxE6kTI4oX26w==} cpu: [x64] os: [darwin] + '@rollup/rollup-darwin-x64@4.22.5': + resolution: {integrity: sha512-D8brJEFg5D+QxFcW6jYANu+Rr9SlKtTenmsX5hOSzNYVrK5oLAEMTUgKWYJP+wdKyCdeSwnapLsn+OVRFycuQg==} + cpu: [x64] + os: [darwin] + '@rollup/rollup-linux-arm-gnueabihf@4.21.2': resolution: {integrity: sha512-ztRJJMiE8nnU1YFcdbd9BcH6bGWG1z+jP+IPW2oDUAPxPjo9dverIOyXz76m6IPA6udEL12reYeLojzW2cYL7w==} cpu: [arm] os: [linux] + '@rollup/rollup-linux-arm-gnueabihf@4.22.5': + resolution: {integrity: sha512-PNqXYmdNFyWNg0ma5LdY8wP+eQfdvyaBAojAXgO7/gs0Q/6TQJVXAXe8gwW9URjbS0YAammur0fynYGiWsKlXw==} + cpu: [arm] + os: [linux] + '@rollup/rollup-linux-arm-musleabihf@4.21.2': resolution: {integrity: sha512-flOcGHDZajGKYpLV0JNc0VFH361M7rnV1ee+NTeC/BQQ1/0pllYcFmxpagltANYt8FYf9+kL6RSk80Ziwyhr7w==} cpu: [arm] os: [linux] + '@rollup/rollup-linux-arm-musleabihf@4.22.5': + resolution: {integrity: sha512-kSSCZOKz3HqlrEuwKd9TYv7vxPYD77vHSUvM2y0YaTGnFc8AdI5TTQRrM1yIp3tXCKrSL9A7JLoILjtad5t8pQ==} + cpu: [arm] + os: [linux] + '@rollup/rollup-linux-arm64-gnu@4.21.2': resolution: {integrity: sha512-69CF19Kp3TdMopyteO/LJbWufOzqqXzkrv4L2sP8kfMaAQ6iwky7NoXTp7bD6/irKgknDKM0P9E/1l5XxVQAhw==} cpu: [arm64] os: [linux] + '@rollup/rollup-linux-arm64-gnu@4.22.5': + resolution: {integrity: sha512-oTXQeJHRbOnwRnRffb6bmqmUugz0glXaPyspp4gbQOPVApdpRrY/j7KP3lr7M8kTfQTyrBUzFjj5EuHAhqH4/w==} + cpu: [arm64] + os: [linux] + '@rollup/rollup-linux-arm64-musl@4.21.2': resolution: {integrity: sha512-48pD/fJkTiHAZTnZwR0VzHrao70/4MlzJrq0ZsILjLW/Ab/1XlVUStYyGt7tdyIiVSlGZbnliqmult/QGA2O2w==} cpu: [arm64] os: [linux] + '@rollup/rollup-linux-arm64-musl@4.22.5': + resolution: {integrity: sha512-qnOTIIs6tIGFKCHdhYitgC2XQ2X25InIbZFor5wh+mALH84qnFHvc+vmWUpyX97B0hNvwNUL4B+MB8vJvH65Fw==} + cpu: [arm64] + os: [linux] + '@rollup/rollup-linux-powerpc64le-gnu@4.21.2': resolution: {integrity: sha512-cZdyuInj0ofc7mAQpKcPR2a2iu4YM4FQfuUzCVA2u4HI95lCwzjoPtdWjdpDKyHxI0UO82bLDoOaLfpZ/wviyQ==} cpu: [ppc64] os: [linux] + '@rollup/rollup-linux-powerpc64le-gnu@4.22.5': + resolution: {integrity: sha512-TMYu+DUdNlgBXING13rHSfUc3Ky5nLPbWs4bFnT+R6Vu3OvXkTkixvvBKk8uO4MT5Ab6lC3U7x8S8El2q5o56w==} + cpu: [ppc64] + os: [linux] + '@rollup/rollup-linux-riscv64-gnu@4.21.2': resolution: {integrity: sha512-RL56JMT6NwQ0lXIQmMIWr1SW28z4E4pOhRRNqwWZeXpRlykRIlEpSWdsgNWJbYBEWD84eocjSGDu/XxbYeCmwg==} cpu: [riscv64] os: [linux] + '@rollup/rollup-linux-riscv64-gnu@4.22.5': + resolution: {integrity: sha512-PTQq1Kz22ZRvuhr3uURH+U/Q/a0pbxJoICGSprNLAoBEkyD3Sh9qP5I0Asn0y0wejXQBbsVMRZRxlbGFD9OK4A==} + cpu: [riscv64] + os: [linux] + '@rollup/rollup-linux-s390x-gnu@4.21.2': resolution: {integrity: sha512-PMxkrWS9z38bCr3rWvDFVGD6sFeZJw4iQlhrup7ReGmfn7Oukrr/zweLhYX6v2/8J6Cep9IEA/SmjXjCmSbrMQ==} cpu: [s390x] os: [linux] + '@rollup/rollup-linux-s390x-gnu@4.22.5': + resolution: {integrity: sha512-bR5nCojtpuMss6TDEmf/jnBnzlo+6n1UhgwqUvRoe4VIotC7FG1IKkyJbwsT7JDsF2jxR+NTnuOwiGv0hLyDoQ==} + cpu: [s390x] + os: [linux] + '@rollup/rollup-linux-x64-gnu@4.21.2': resolution: {integrity: sha512-B90tYAUoLhU22olrafY3JQCFLnT3NglazdwkHyxNDYF/zAxJt5fJUB/yBoWFoIQ7SQj+KLe3iL4BhOMa9fzgpw==} cpu: [x64] os: [linux] + '@rollup/rollup-linux-x64-gnu@4.22.5': + resolution: {integrity: sha512-N0jPPhHjGShcB9/XXZQWuWBKZQnC1F36Ce3sDqWpujsGjDz/CQtOL9LgTrJ+rJC8MJeesMWrMWVLKKNR/tMOCA==} + cpu: [x64] + os: [linux] + '@rollup/rollup-linux-x64-musl@4.21.2': resolution: {integrity: sha512-7twFizNXudESmC9oneLGIUmoHiiLppz/Xs5uJQ4ShvE6234K0VB1/aJYU3f/4g7PhssLGKBVCC37uRkkOi8wjg==} cpu: [x64] os: [linux] + '@rollup/rollup-linux-x64-musl@4.22.5': + resolution: {integrity: sha512-uBa2e28ohzNNwjr6Uxm4XyaA1M/8aTgfF2T7UIlElLaeXkgpmIJ2EitVNQxjO9xLLLy60YqAgKn/AqSpCUkE9g==} + cpu: [x64] + os: [linux] + '@rollup/rollup-win32-arm64-msvc@4.21.2': resolution: {integrity: sha512-9rRero0E7qTeYf6+rFh3AErTNU1VCQg2mn7CQcI44vNUWM9Ze7MSRS/9RFuSsox+vstRt97+x3sOhEey024FRQ==} cpu: [arm64] os: [win32] + '@rollup/rollup-win32-arm64-msvc@4.22.5': + resolution: {integrity: sha512-RXT8S1HP8AFN/Kr3tg4fuYrNxZ/pZf1HemC5Tsddc6HzgGnJm0+Lh5rAHJkDuW3StI0ynNXukidROMXYl6ew8w==} + cpu: [arm64] + os: [win32] + '@rollup/rollup-win32-ia32-msvc@4.21.2': resolution: {integrity: sha512-5rA4vjlqgrpbFVVHX3qkrCo/fZTj1q0Xxpg+Z7yIo3J2AilW7t2+n6Q8Jrx+4MrYpAnjttTYF8rr7bP46BPzRw==} cpu: [ia32] os: [win32] + '@rollup/rollup-win32-ia32-msvc@4.22.5': + resolution: {integrity: sha512-ElTYOh50InL8kzyUD6XsnPit7jYCKrphmddKAe1/Ytt74apOxDq5YEcbsiKs0fR3vff3jEneMM+3I7jbqaMyBg==} + cpu: [ia32] + os: [win32] + '@rollup/rollup-win32-x64-msvc@4.21.2': resolution: {integrity: sha512-6UUxd0+SKomjdzuAcp+HAmxw1FlGBnl1v2yEPSabtx4lBfdXHDVsW7+lQkgz9cNFJGY3AWR7+V8P5BqkD9L9nA==} cpu: [x64] os: [win32] + '@rollup/rollup-win32-x64-msvc@4.22.5': + resolution: {integrity: sha512-+lvL/4mQxSV8MukpkKyyvfwhH266COcWlXE/1qxwN08ajovta3459zrjLghYMgDerlzNwLAcFpvU+WWE5y6nAQ==} + cpu: [x64] + os: [win32] + '@scena/dragscroll@1.4.0': resolution: {integrity: sha512-3O8daaZD9VXA9CP3dra6xcgt/qrm0mg0xJCwiX6druCteQ9FFsXffkF8PrqxY4Z4VJ58fFKEa0RlKqbsi/XnRA==} @@ -3204,32 +3287,32 @@ packages: resolution: {integrity: sha512-O2Tj+WK33/ZVp5STnz6ZL0OO+/Idk2KqsH0ITQkQmyZ2z0kdzWOeqK7s7q3/My6rB1GfPcyqPcBBv4dVv92FYQ==} engines: {node: '>=14.18'} - '@sentry-internal/browser-utils@8.30.0': - resolution: {integrity: sha512-pwX+awNWaxSOAsBLVLqc1+Hw+Fm1Nci9mbKFA6Ed5YzCG049PnBVQwugpmx2dcyyCqJpORhcIqb9jHdCkYmCiA==} + '@sentry-internal/browser-utils@8.32.0': + resolution: {integrity: sha512-DpUGhk5O1OVjT0fo9wsbEdO1R/S9gGBRDtn9+FFVeRtieJHwXpeZiLK+tZhTOvaILmtSoTPUEY3L5sK4j5Xq9g==} engines: {node: '>=14.18'} '@sentry-internal/feedback@8.26.0': resolution: {integrity: sha512-hQtw1gg8n6ERK1UH47F7ZI1zOsbhu0J2VX+TrnkpaQR2FgxDW1oe9Ja6oCV4CQKuR4w+1ZI/Kj4imSt0K33kEw==} engines: {node: '>=14.18'} - '@sentry-internal/feedback@8.30.0': - resolution: {integrity: sha512-ParFRxQY6helxkwUDmro77Wc5uSIC6rZos88jYMrYwFmoTJaNWf4lDzPyECfdSiSYyzSMZk4dorSUN85Ul7DCg==} + '@sentry-internal/feedback@8.32.0': + resolution: {integrity: sha512-XB7hiVJQW1tNzpoXIHbvm3rjipIt7PZiJJtFg2vxaqu/FzdgOcYqQiwIKivJVAKuRZ9rIeJtK1jdXQFOc/TRJA==} engines: {node: '>=14.18'} '@sentry-internal/replay-canvas@8.26.0': resolution: {integrity: sha512-2CFQW6f9aJHIo/DqmqYa9PaYoLn1o36ywc0h8oyGrD4oPCbrnE5F++PmTdc71GBODu41HBn/yoCTLmxOD+UjpA==} engines: {node: '>=14.18'} - '@sentry-internal/replay-canvas@8.30.0': - resolution: {integrity: sha512-y/QqcvchhtMlVA6eOZicIfTxtZarazQZJuFW0018ynPxBTiuuWSxMCLqduulXUYsFejfD8/eKHb3BpCIFdDYjg==} + '@sentry-internal/replay-canvas@8.32.0': + resolution: {integrity: sha512-oBbhtDBkD+5z/T0NVJ5VenBWAid/S9QdVrod/UqxVqU7F8N+E9/INFQI48zCWr4iVlUMcszJPDElvJEsMDvvBQ==} engines: {node: '>=14.18'} '@sentry-internal/replay@8.26.0': resolution: {integrity: sha512-JDY7W2bswlp5c3483lKP4kcb75fHNwGNfwD8x8FsY9xMjv7nxeXjLpR5cCEk1XqPq2+n6w4j7mJOXhEXGiUIKg==} engines: {node: '>=14.18'} - '@sentry-internal/replay@8.30.0': - resolution: {integrity: sha512-/KFre+BrovPCiovgAu5N1ErJtkDVzkJA5hV3Jw011AlxRWxrmPwu6+9sV9/rn3tqYAGyq6IggYqeIOHhLh1Ihg==} + '@sentry-internal/replay@8.32.0': + resolution: {integrity: sha512-yiEUnn2yyo1AIQIFNeRX3tdK8fmyKIkxdFS1WiVQmeYI/hFwYBTZPly0FcO/g3xnRMSA2tvrS+hZEaaXfK4WhA==} engines: {node: '>=14.18'} '@sentry/babel-plugin-component-annotate@2.22.4': @@ -3240,8 +3323,8 @@ packages: resolution: {integrity: sha512-e5s6eKlwLZWzTwQcBwqyAGZMMuQROW9Z677VzwkSyREWAIkKjfH2VBxHATnNGc0IVkNHjD7iH3ixo3C0rLKM3w==} engines: {node: '>=14.18'} - '@sentry/browser@8.30.0': - resolution: {integrity: sha512-M+tKqawH9S3CqlAIcqdZcHbcsNQkEa9MrPqPCYvXco3C4LRpNizJP2XwBiGQY2yK+fOSvbaWpPtlI938/wuRZQ==} + '@sentry/browser@8.32.0': + resolution: {integrity: sha512-AEKFj64g4iYwEMRvVcxiY0FswmClRXCP1IEvCqujn8OBS8AjMOr1z/RwYieEs0D90yNNB3YEqF8adrKENblJmw==} engines: {node: '>=14.18'} '@sentry/bundler-plugin-core@2.22.4': @@ -3298,8 +3381,8 @@ packages: resolution: {integrity: sha512-g/tVmTZD4GNbLFf++hKJfBpcCAtduFEMLnbfa9iT/QEZjlmP+EzY+GsH9bafM5VsNe8DiOUp+kJKWtShzlVdBA==} engines: {node: '>=14.18'} - '@sentry/core@8.30.0': - resolution: {integrity: sha512-CJ/FuWLw0QEKGKXGL/nm9eaOdajEcmPekLuHAuOCxID7N07R9l9laz3vFbAkUZ97GGDv3sYrJZgywfY3Moropg==} + '@sentry/core@8.32.0': + resolution: {integrity: sha512-+xidTr0lZ0c755tq4k75dXPEb8PA+qvIefW3U9+dQMORLokBrYoKYMf5zZTG2k/OfSJS6OSxatUj36NFuCs3aA==} engines: {node: '>=14.18'} '@sentry/electron@5.4.0': @@ -3319,8 +3402,8 @@ packages: '@opentelemetry/sdk-trace-base': ^1.25.1 '@opentelemetry/semantic-conventions': ^1.25.1 - '@sentry/react@8.30.0': - resolution: {integrity: sha512-ktQjXs87jdsxW0YrHci3sb6zcSzhMECWnrTVU/KGZF8UoDsk4P4xRCknijd2SSmDIjSkwzUAANR43UkCi4BTQg==} + '@sentry/react@8.32.0': + resolution: {integrity: sha512-YljqK+k80XOvyXjK2p2neTncRcSuwlpL7qHtNgwR1MHx18FEi7HXlnm13J4g3kxao4ORMxlCXCEPNXlLT+vqQg==} engines: {node: '>=14.18'} peerDependencies: react: ^16.14.0 || 17.x || 18.x || 19.x @@ -3329,36 +3412,36 @@ packages: resolution: {integrity: sha512-zKmh6SWsJh630rpt7a9vP4Cm4m1C2gDTUqUiH565CajCL/4cePpNWYrNwalSqsOSL7B9OrczA1+n6a6XvND+ng==} engines: {node: '>=14.18'} - '@sentry/types@8.30.0': - resolution: {integrity: sha512-kgWW2BCjBmVlSQRG32GonHEVyeDbys74xf9mLPvynwHTgw3+NUlNAlEdu05xnb2ow4bCTHfbkS5G1zRgyv5k4Q==} + '@sentry/types@8.32.0': + resolution: {integrity: sha512-hxckvN2MzS5SgGDgVQ0/QpZXk13Vrq4BtZLwXhPhyeTmZtUiUfWvcL5TFQqLinfKdTKPe9q2MxeAJ0D4LalhMg==} engines: {node: '>=14.18'} '@sentry/utils@8.26.0': resolution: {integrity: sha512-xvlPU9Hd2BlyT+FhWHGNwnxWqdVRk2AHnDtVcW4Ma0Ri5EwS+uy4Jeik5UkSv8C5RVb9VlxFmS8LN3I1MPJsLw==} engines: {node: '>=14.18'} - '@sentry/utils@8.30.0': - resolution: {integrity: sha512-wZxU2HWlzsnu8214Xy7S7cRIuD6h8Z5DnnkojJfX0i0NLooepZQk2824el1Q13AakLb7/S8CHSHXOMnCtoSduw==} + '@sentry/utils@8.32.0': + resolution: {integrity: sha512-t1WVERhgmYURxbBj9J4/H2P2X+VKqm7B3ce9iQyrZbdf5NekhcU4jHIecPUWCPHjQkFIqkVTorqeBmDTlg/UmQ==} engines: {node: '>=14.18'} '@sentry/vite-plugin@2.22.4': resolution: {integrity: sha512-C51PUlTv0BXN3+e9SjPHptNX3b9E0clrsaR5c//l/sFkQjuteDHKChA1gNzZSvfoa3gm9NzZAgpk3hVF2O3nBA==} engines: {node: '>= 14'} - '@shikijs/core@1.18.0': - resolution: {integrity: sha512-VK4BNVCd2leY62Nm2JjyxtRLkyrZT/tv104O81eyaCjHq4Adceq2uJVFJJAIof6lT1mBwZrEo2qT/T+grv3MQQ==} + '@shikijs/core@1.20.0': + resolution: {integrity: sha512-KlO3iE0THzSdYkzDFugt8SHe6FR3qNYTkmpbdW1d6xo8juQkMjybxAw/cBi2npL2eb2F4PbbnSs5Z9tDusfvyg==} - '@shikijs/engine-javascript@1.18.0': - resolution: {integrity: sha512-qoP/aO/ATNwYAUw1YMdaip/YVEstMZEgrwhePm83Ll9OeQPuxDZd48szZR8oSQNQBT8m8UlWxZv8EA3lFuyI5A==} + '@shikijs/engine-javascript@1.20.0': + resolution: {integrity: sha512-ZUMo758uduM0Tfgzi/kd+0IKMbNdumCxxWjY36uf1DIs2Qyg9HIq3vA1Wfa/vc6HE7tHWFpANRi3mv7UzJ68MQ==} - '@shikijs/engine-oniguruma@1.18.0': - resolution: {integrity: sha512-B9u0ZKI/cud+TcmF8Chyh+R4V5qQVvyDOqXC2l2a4x73PBSBc6sZ0JRAX3eqyJswqir6ktwApUUGBYePdKnMJg==} + '@shikijs/engine-oniguruma@1.20.0': + resolution: {integrity: sha512-MQ40WkVTZk7by33ces4PGK6XNFSo6PYvKTSAr2kTWdRNhFmOcnaX+1XzvFwB26eySXR7U74t91czZ1qJkEgxTA==} - '@shikijs/transformers@1.18.0': - resolution: {integrity: sha512-EdX/UIVaaS8qp9NWRyHIXp2dmuLpdVvx+UVpbIn9eafFlLemAuljPb2+K40ie6jrlg0uUIqkg25CM/8I34yBNw==} + '@shikijs/transformers@1.20.0': + resolution: {integrity: sha512-TNS5KAErbNIOm1QqabuVaU77NOs5xWfpjpnqME059SA8yddr3mN5ZNAeCI+4QAAnNqZd8RKXjp+9hw66f5ak/A==} - '@shikijs/types@1.18.0': - resolution: {integrity: sha512-O9N36UEaGGrxv1yUrN2nye7gDLG5Uq0/c1LyfmxsvzNPqlHzWo9DI0A4+fhW2y3bGKuQu/fwS7EPdKJJCowcVA==} + '@shikijs/types@1.20.0': + resolution: {integrity: sha512-y+EaDvU2K6/GaXOKXxJaGnr1XtmZMF7MfS0pSEDdxEq66gCtKsLwQvVwoQFdp7R7dLlNAro3ijEE19sMZ0pzqg==} '@shikijs/vscode-textmate@9.2.2': resolution: {integrity: sha512-TMp15K+GGYrWlZM8+Lnj9EaHEFmOen0WJBrfa17hF7taDOYthuPPV0GWzfd/9iMij0akS/8Yw2ikquH7uVi/fg==} @@ -3402,8 +3485,8 @@ packages: '@tanstack/query-core@5.56.2': resolution: {integrity: sha512-gor0RI3/R5rVV3gXfddh1MM+hgl0Z4G7tj6Xxpq6p2I03NGPaJ8dITY9Gz05zYYb/EJq9vPas/T4wn9EaDPd4Q==} - '@tanstack/query-devtools@5.56.1': - resolution: {integrity: sha512-xnp9jq/9dHfSCDmmf+A5DjbIjYqbnnUL2ToqlaaviUQGRTapXQ8J+GxusYUu1IG0vZMaWdiVUA4HRGGZYAUU+A==} + '@tanstack/query-devtools@5.58.0': + resolution: {integrity: sha512-iFdQEFXaYYxqgrv63ots+65FGI+tNp5ZS5PdMU1DWisxk3fez5HG3FyVlbUva+RdYS5hSLbxZ9aw3yEs97GNTw==} '@tanstack/query-persist-client-core@5.56.2': resolution: {integrity: sha512-4OZ/rLAxCiQWaJCQjb5q1+UbSNIZclmF4pRMHrav1q2EUj3bjrqWzwTwdy2bUxrMTdY15ZKsFwCpAFGG4r+orA==} @@ -3411,8 +3494,8 @@ packages: '@tanstack/query-sync-storage-persister@5.56.2': resolution: {integrity: sha512-aNupwjlJgaDwYW01DThrblkBSarH9E8sKVl3ATafOLpZoGvDg5Jc4SVMCiMmOC1U+PRuRbt5bpS6a8lZnbiYaA==} - '@tanstack/react-query-devtools@5.56.2': - resolution: {integrity: sha512-7nINJtRZZVwhTTyDdMIcSaXo+EHMLYJu1S2e6FskvvD5prx87LlAXXWZDfU24Qm4HjshEtM5lS3HIOszNGblcw==} + '@tanstack/react-query-devtools@5.58.0': + resolution: {integrity: sha512-qF0xCyBeVuNLygTO1sAl1X4Gv52w52SeaDdbjYQmtTOooUJ3aAVlBEtiRJFfJblWQ9p/UQG8NIcC/65RjX8Jkw==} peerDependencies: '@tanstack/react-query': ^5.56.2 react: ^18 || ^19 @@ -3472,15 +3555,15 @@ packages: '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} - '@types/eslint@9.6.1': - resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} - '@types/estree-jsx@1.0.5': resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + '@types/fs-extra@9.0.13': resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} @@ -3517,11 +3600,11 @@ packages: '@types/mysql@2.15.22': resolution: {integrity: sha512-wK1pzsJVVAjYCSZWQoWHziQZbNggXFDUEIGf54g4ZM/ERuP86uGdWeKZWMYlqTPMZfHJJvLPyogXGvCOg87yLQ==} - '@types/node@20.16.5': - resolution: {integrity: sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==} + '@types/node@20.16.10': + resolution: {integrity: sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==} - '@types/node@22.5.5': - resolution: {integrity: sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==} + '@types/node@22.7.4': + resolution: {integrity: sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -3529,6 +3612,9 @@ packages: '@types/pg-pool@2.0.4': resolution: {integrity: sha512-qZAvkv1K3QbmHHFYSNRYPkRjOWRLBYrL4B9c+wG0GSVGBw0NtJwPcgx/DSddeDJvRGMHCEQ4VMEVfuJ/0gZ3XQ==} + '@types/pg@8.11.10': + resolution: {integrity: sha512-LczQUW4dbOQzsH2RQ5qoeJ6qJPdrcM/DcMLoqWQkMLMsq83J5lAX3LXjdkWdpscFy67JSOWDnh7Ny/sPFykmkg==} + '@types/pg@8.11.8': resolution: {integrity: sha512-IqpCf8/569txXN/HoP5i1LjXfKZWL76Yr2R77xgeIICUbAYHeoaEZFhYHo2uDftecLWrTJUq63JvQu8q3lnDyA==} @@ -3538,14 +3624,14 @@ packages: '@types/plist@3.0.5': resolution: {integrity: sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==} - '@types/prop-types@15.7.12': - resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} + '@types/prop-types@15.7.13': + resolution: {integrity: sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==} '@types/react-dom@18.3.0': resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==} - '@types/react@18.3.8': - resolution: {integrity: sha512-syBUrW3/XpnW4WJ41Pft+I+aPoDVbrBVQGEnbD7NijDGlVC+8gV/XKRY+7vMDlfPpbwYt0l1vd/Sj8bJGMbs9Q==} + '@types/react@18.3.10': + resolution: {integrity: sha512-02sAAlBnP39JgXwkAq3PeU9DVaaGpZyF3MGcC0MKgQVkZor5IiiDAipVaxQHtDJAmO4GIy/rVBy/LzVj76Cyqg==} '@types/responselike@1.0.3': resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} @@ -3571,8 +3657,8 @@ packages: '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@typescript-eslint/eslint-plugin@8.6.0': - resolution: {integrity: sha512-UOaz/wFowmoh2G6Mr9gw60B1mm0MzUtm6Ic8G2yM1Le6gyj5Loi/N+O5mocugRGY+8OeeKmkMmbxNqUCq3B4Sg==} + '@typescript-eslint/eslint-plugin@8.7.0': + resolution: {integrity: sha512-RIHOoznhA3CCfSTFiB6kBGLQtB/sox+pJ6jeFu6FxJvqL8qRxq/FfGO/UhsGgQM9oGdXkV4xUgli+dt26biB6A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 @@ -3582,8 +3668,8 @@ packages: typescript: optional: true - '@typescript-eslint/parser@8.6.0': - resolution: {integrity: sha512-eQcbCuA2Vmw45iGfcyG4y6rS7BhWfz9MQuk409WD47qMM+bKCGQWXxvoOs1DUp+T7UBMTtRTVT+kXr7Sh4O9Ow==} + '@typescript-eslint/parser@8.7.0': + resolution: {integrity: sha512-lN0btVpj2unxHlNYLI//BQ7nzbMJYBVQX5+pbNXvGYazdlgYonMn4AhhHifQ+J4fGRYA/m1DjaQjx+fDetqBOQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -3592,16 +3678,12 @@ packages: typescript: optional: true - '@typescript-eslint/scope-manager@8.4.0': - resolution: {integrity: sha512-n2jFxLeY0JmKfUqy3P70rs6vdoPjHK8P/w+zJcV3fk0b0BwRXC/zxRTEnAsgYT7MwdQDt/ZEbtdzdVC+hcpF0A==} + '@typescript-eslint/scope-manager@8.7.0': + resolution: {integrity: sha512-87rC0k3ZlDOuz82zzXRtQ7Akv3GKhHs0ti4YcbAJtaomllXoSO8hi7Ix3ccEvCd824dy9aIX+j3d2UMAfCtVpg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/scope-manager@8.6.0': - resolution: {integrity: sha512-ZuoutoS5y9UOxKvpc/GkvF4cuEmpokda4wRg64JEia27wX+PysIE9q+lzDtlHHgblwUWwo5/Qn+/WyTUvDwBHw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/type-utils@8.6.0': - resolution: {integrity: sha512-dtePl4gsuenXVwC7dVNlb4mGDcKjDT/Ropsk4za/ouMBPplCLyznIaR+W65mvCvsyS97dymoBRrioEXI7k0XIg==} + '@typescript-eslint/type-utils@8.7.0': + resolution: {integrity: sha512-tl0N0Mj3hMSkEYhLkjREp54OSb/FI6qyCzfiiclvJvOqre6hsZTGSnHtmFLDU8TIM62G7ygEa1bI08lcuRwEnQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '*' @@ -3609,16 +3691,12 @@ packages: typescript: optional: true - '@typescript-eslint/types@8.4.0': - resolution: {integrity: sha512-T1RB3KQdskh9t3v/qv7niK6P8yvn7ja1mS7QK7XfRVL6wtZ8/mFs/FHf4fKvTA0rKnqnYxl/uHFNbnEt0phgbw==} + '@typescript-eslint/types@8.7.0': + resolution: {integrity: sha512-LLt4BLHFwSfASHSF2K29SZ+ZCsbQOM+LuarPjRUuHm+Qd09hSe3GCeaQbcCr+Mik+0QFRmep/FyZBO6fJ64U3w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.6.0': - resolution: {integrity: sha512-rojqFZGd4MQxw33SrOy09qIDS8WEldM8JWtKQLAjf/X5mGSeEFh5ixQlxssMNyPslVIk9yzWqXCsV2eFhYrYUw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/typescript-estree@8.4.0': - resolution: {integrity: sha512-kJ2OIP4dQw5gdI4uXsaxUZHRwWAGpREJ9Zq6D5L0BweyOrWsL6Sz0YcAZGWhvKnH7fm1J5YFE1JrQL0c9dd53A==} + '@typescript-eslint/typescript-estree@8.7.0': + resolution: {integrity: sha512-MC8nmcGHsmfAKxwnluTQpNqceniT8SteVwd2voYlmiSWGOtjvGXdPl17dYu2797GVscK30Z04WRM28CrKS9WOg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '*' @@ -3626,51 +3704,32 @@ packages: typescript: optional: true - '@typescript-eslint/typescript-estree@8.6.0': - resolution: {integrity: sha512-MOVAzsKJIPIlLK239l5s06YXjNqpKTVhBVDnqUumQJja5+Y94V3+4VUFRA0G60y2jNnTVwRCkhyGQpavfsbq/g==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/utils@8.4.0': - resolution: {integrity: sha512-swULW8n1IKLjRAgciCkTCafyTHHfwVQFt8DovmaF69sKbOxTSFMmIZaSHjqO9i/RV0wIblaawhzvtva8Nmm7lQ==} + '@typescript-eslint/utils@8.7.0': + resolution: {integrity: sha512-ZbdUdwsl2X/s3CiyAu3gOlfQzpbuG3nTWKPoIvAu1pu5r8viiJvv2NPN2AqArL35NCYtw/lrPPfM4gxrMLNLPw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - '@typescript-eslint/utils@8.6.0': - resolution: {integrity: sha512-eNp9cWnYf36NaOVjkEUznf6fEgVy1TWpE0o52e4wtojjBx7D1UV2WAWGzR+8Y5lVFtpMLPwNbC67T83DWSph4A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - - '@typescript-eslint/visitor-keys@8.4.0': - resolution: {integrity: sha512-zTQD6WLNTre1hj5wp09nBIDiOc2U5r/qmzo7wxPn4ZgAjHql09EofqhF9WF+fZHzL5aCyaIpPcT2hyxl73kr9A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/visitor-keys@8.6.0': - resolution: {integrity: sha512-wapVFfZg9H0qOYh4grNVQiMklJGluQrOUiOhYRrQWhx7BY/+I1IYb8BczWNbbUpO+pqy0rDciv3lQH5E1bCLrg==} + '@typescript-eslint/visitor-keys@8.7.0': + resolution: {integrity: sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - '@unocss/config@0.62.3': - resolution: {integrity: sha512-zYOvFE0HfGIbnP/AvsbAlJpPRx9CQyXzL11m/8zgsHW5SGlJIYxuTll83l/xu026G5mPiksy7quoEOEgCLslqw==} + '@unocss/config@0.62.4': + resolution: {integrity: sha512-XKudKxxW8P44JvlIdS6HBpfE3qZA9rhbemy6/sb8HyZjKYjgeM9jx5yjk+9+4hXNma/KlwDXwjAqY29z0S0SrA==} engines: {node: '>=14'} - '@unocss/core@0.62.3': - resolution: {integrity: sha512-Pfyrj8S7jq9K1QXD6Z5BCeiQavaHpbMN5q958/kmdbNGp57hOg1e346fMJAvgPjLBR+lE/hgZEsDrijtRiZXnw==} + '@unocss/core@0.62.4': + resolution: {integrity: sha512-Cc+Vo6XlaQpyVejkJrrzzWtiK9pgMWzVVBpm9VCVtwZPUjD4GSc+g7VQCPXSsr7m03tmSuRySJx72QcASmauNQ==} - '@unocss/eslint-config@0.62.3': - resolution: {integrity: sha512-xj2XMjUP/LVkTESyDE08fo/Ejvt1SuQYvx9WVp4zr5HAoAITNDnenFLHtLgx+4h8sdWkiAhzHLa2plEfktw06Q==} + '@unocss/eslint-config@0.62.4': + resolution: {integrity: sha512-bulYXf80MhTlN2oG/d1r23/FJTNiGxK/gG+p9nl/UeJZc5NOnes7fsqVscFTXDxVQGVIFgeKfch3DRmzlxHe9Q==} engines: {node: '>=14'} - '@unocss/eslint-plugin@0.62.3': - resolution: {integrity: sha512-8aAx5QMVLar4kTUikq7XmD3NQs6o/by87PfZNAFxuGMhKQ5RBnUfH1pzpRs+FTHN7L09As0W90cjC97b3biEaA==} + '@unocss/eslint-plugin@0.62.4': + resolution: {integrity: sha512-L4pm8L96OvE99FK+fZHQBXxsu+B/yvhf471Mf5o3idaq+pzptfpZcKKRXCeQKSAYbC80IV4Fm1V5dFxOHbDdPg==} engines: {node: '>=14'} '@use-gesture/core@10.3.1': @@ -4670,8 +4729,8 @@ packages: os: [darwin] hasBin: true - dnum@2.13.1: - resolution: {integrity: sha512-4oZ+BtlvNtKFJji1Fc5073LyJFvgioBQ0PNu/C+r1A8P09Yvka/aXYYD5bsUHMTUPEu01iv4bk+5nPQmt5AA8A==} + dnum@2.14.0: + resolution: {integrity: sha512-xyP+csC3QlQY0YCCcpJ6VApTJ35Gh+QN9L7gRstqaZc2VCtd1W1844AuYTy3FlZtWePJ/2hXYY250I0dd3qH6Q==} doctrine@3.0.0: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} @@ -4969,8 +5028,8 @@ packages: peerDependencies: eslint: ^9.5.0 - eslint-config-hyoban@3.1.6: - resolution: {integrity: sha512-Te5+pGEU4y6qdgJbYIV2cQN4ucRWB5MsoRW7M3I4EcJX284z/AZV1V3gn473/afY83hzwhc2AX40CnE5aBahcg==} + eslint-config-hyoban@3.1.7: + resolution: {integrity: sha512-35r1FdI9lfa5aowbaDidpjsRcDn8HO+8/RhtcfFblkc30DqQkyxPmgAxY1ohn8NSzEUdLqzfyqIBlK2E9bOfmw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^9.0.0 @@ -4982,13 +5041,13 @@ packages: eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} - eslint-plugin-antfu@2.6.0: - resolution: {integrity: sha512-4dz0VgWGpZ6jUSEUPSI6OGFqBc+P8c7zFFXht5t+YwzIvBsruqVX7Hjl3I8KNNEyJmA4fL3+GIc+EWU1woTp1A==} + eslint-plugin-antfu@2.7.0: + resolution: {integrity: sha512-gZM3jq3ouqaoHmUNszb1Zo2Ux7RckSvkGksjLWz9ipBYGSv1EwwBETN6AdiUXn+RpVHXTbEMPAPlXJazcA6+iA==} peerDependencies: eslint: '*' - eslint-plugin-command@0.2.5: - resolution: {integrity: sha512-mbCaSHD37MT8nVJnJUz2oeDfhz0wdOjfrqQVWkSpXuj3uU8m7/FK/niV2bL922af3M1js5x7Xcu3PwqWsrahfA==} + eslint-plugin-command@0.2.6: + resolution: {integrity: sha512-T0bHZ1oblW1xUHUVoBKZJR2osSNNGkfZuK4iqboNwuNS/M7tdp3pmURaJtTi/XDzitxaQ02lvOdFH0mUd5QLvQ==} peerDependencies: eslint: '*' @@ -4997,8 +5056,8 @@ packages: peerDependencies: eslint: '*' - eslint-plugin-import-x@4.2.1: - resolution: {integrity: sha512-WWi2GedccIJa0zXxx3WDnTgouGQTtdYK1nhXMwywbqqAgB0Ov+p1pYBsWh3VaB0bvBOwLse6OfVII7jZD9xo5Q==} + eslint-plugin-import-x@4.3.0: + resolution: {integrity: sha512-PxGzP7gAjF2DLeRnQtbYkkgZDg1intFyYr/XS1LgTYXUDrSXMHGkXx8++6i2eDv2jMs0jfeO6G6ykyeWxiFX7w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -5022,8 +5081,8 @@ packages: peerDependencies: eslint: '>=7' - eslint-plugin-react-debug@1.14.1: - resolution: {integrity: sha512-VFkRmXGCgmCCgUsdBpmARYhFvKbK7XgF41hgQrEhJAfYA0lXE2Urb+VkVpk57xUk+ZxMQy3sy6A1P4tQ+83hrQ==} + eslint-plugin-react-debug@1.14.2: + resolution: {integrity: sha512-5DlSAx4dHhqbGpPMOyEu7lhdWExwxI1e/3MeKSJBfigQamdA0dIZi/K0ZkeVqbSS8ItU+G/Ba1ek6vYCtadNvA==} engines: {bun: '>=1.0.15', node: '>=18.18.0'} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -5032,8 +5091,8 @@ packages: typescript: optional: true - eslint-plugin-react-dom@1.14.1: - resolution: {integrity: sha512-hVcublIn4aAvudpl39I0l/1ldJJvn5rINHc71m+balFeKt5Qk0nPTUdPRCWRyp4ExD/mEbWAcEIP/pS0b5B/Vg==} + eslint-plugin-react-dom@1.14.2: + resolution: {integrity: sha512-qG1WqsOHj4BdoOBPt3gwtEbeTc43EKKqDzxcB4gRbT6euBxU0EluEMtcFO/bAy9950iehD7rRSvuLs7voE+bNg==} engines: {bun: '>=1.0.15', node: '>=18.18.0'} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -5042,8 +5101,8 @@ packages: typescript: optional: true - eslint-plugin-react-hooks-extra@1.14.1: - resolution: {integrity: sha512-R5BOTZYY9fm7qTPN1hRZxk9mj8JwvnpXbxhEZwphM3Sn2legwXVHdXXkuUqaDR6AWw+z3wfLkb8xhVBu+uY1Hg==} + eslint-plugin-react-hooks-extra@1.14.2: + resolution: {integrity: sha512-SMDEluUIFQMPksKtmHVT2etaKqGIN7Rvcp9R/MB1bFcO1sh5ON2dDHXcZUTomZHriTEn/fm6pANe44jk20l4jQ==} engines: {bun: '>=1.0.15', node: '>=18.18.0'} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -5058,8 +5117,8 @@ packages: peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 - eslint-plugin-react-naming-convention@1.14.1: - resolution: {integrity: sha512-F3HCtRXwtT66/KNBuhSPxk63z/1iIxV3LUrwKAPVomTpGEIGrF/vzvNjJK0eaxf2Ae7h+SGMrDvJcRaYtRpRvQ==} + eslint-plugin-react-naming-convention@1.14.2: + resolution: {integrity: sha512-LWJm5kF7hWL7OcJnn+dTmC/l75RV4n7gH5QRH4kjcsVRs/Ky/kTcmBQTlC+CsaMUsy9jro6VBzj7Rk9/IO5vcQ==} engines: {bun: '>=1.0.15', node: '>=18.18.0'} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -5068,13 +5127,13 @@ packages: typescript: optional: true - eslint-plugin-react-refresh@0.4.11: - resolution: {integrity: sha512-wrAKxMbVr8qhXTtIKfXqAn5SAtRZt0aXxe5P23Fh4pUAdC6XEsybGLB8P0PI4j1yYqOgUEUlzKAGDfo7rJOjcw==} + eslint-plugin-react-refresh@0.4.12: + resolution: {integrity: sha512-9neVjoGv20FwYtCP6CB1dzR1vr57ZDNOXst21wd2xJ/cTlM2xLq0GWVlSNTdMn/4BtP6cHYBMCSp1wFBJ9jBsg==} peerDependencies: eslint: '>=7' - eslint-plugin-react-web-api@1.14.1: - resolution: {integrity: sha512-1qS15Wfh+++1UHtGRf6palH2nfDVlKSNMaUjaANnUss04PW0PXeNF540cTuWwMPHyh8xIxcEgDzqx+8MokCtCw==} + eslint-plugin-react-web-api@1.14.2: + resolution: {integrity: sha512-Qq2AJmGsNaabYaWtZweLSTfVGoyPPrz+A7L+h4ecq0TzvnlfSPWFyfQF4biBsZt+V4RrkBpQ4cB9Cqn7TEsEMQ==} engines: {bun: '>=1.0.15', node: '>=18.18.0'} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -5083,8 +5142,8 @@ packages: typescript: optional: true - eslint-plugin-react-x@1.14.1: - resolution: {integrity: sha512-69KBSAX9X+1Az/wfWjvztPJyaZq2PSurlYYju0bH+iWon7pBV7zSqWiGhkizLpa2bSKFhAGzbMhSuaEqPiZQkA==} + eslint-plugin-react-x@1.14.2: + resolution: {integrity: sha512-iiizpXxc//MoOwOqk6J55BMuywrDhZW2wvdM1XK1H8D5OEekyEzZQLPtOaVT0WyO+6tCdvmegKaX/J+4mVcuAg==} engines: {bun: '>=1.0.15', node: '>=18.18.0'} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -5125,20 +5184,20 @@ packages: '@typescript-eslint/eslint-plugin': optional: true - eslint-scope@8.0.2: - resolution: {integrity: sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==} + eslint-scope@8.1.0: + resolution: {integrity: sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint-visitor-keys@4.0.0: - resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} + eslint-visitor-keys@4.1.0: + resolution: {integrity: sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.11.0: - resolution: {integrity: sha512-yVS6XODx+tMFMDFcG4+Hlh+qG7RM6cCJXtQhCKLSsr3XkLvWggHjCqjfh0XsPPnt1c56oaT6PMgW9XWQQjdHXA==} + eslint@9.11.1: + resolution: {integrity: sha512-MobhYKIoAO1s1e4VUrgx1l1Sk2JBR/Gqjjgw8+mfgoLE2xwsHur4gdfTxyTgShrhvdVFTaJSgMiQBl1jv/AWxg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -5147,8 +5206,8 @@ packages: jiti: optional: true - espree@10.1.0: - resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==} + espree@10.2.0: + resolution: {integrity: sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} espree@9.6.1: @@ -5333,8 +5392,8 @@ packages: react: optional: true - framer-motion@11.5.6: - resolution: {integrity: sha512-JMwUpAxv/DWgul9vPgX0ElKn0G66sUc6O9tOXsYwn3zxwvhxFljSXC0XT2QCzuTYBshwC8nyDAa1SYcV0Ldbhw==} + framer-motion@11.9.0: + resolution: {integrity: sha512-nCfGxvsQecVLjjYDu35G2F5ls+ArE3FBfhxV0RSiisMaUKqteq5DMBFNRKwMyVj+VqKTNhawt+BV480YCHKFlQ==} peerDependencies: '@emotion/is-prop-valid': '*' react: ^18.0.0 @@ -5473,6 +5532,9 @@ packages: get-tsconfig@4.8.0: resolution: {integrity: sha512-Pgba6TExTZ0FJAn1qkJAjIeKoDJ3CsI2ChuLohJnZl/tTU8MVrq3b+2t5UOPfRa4RMsorClBjJALkJUMjG1PAw==} + get-tsconfig@4.8.1: + resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==} + giget@1.2.3: resolution: {integrity: sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==} hasBin: true @@ -5613,8 +5675,8 @@ packages: hast-util-excerpt@2.0.0: resolution: {integrity: sha512-3hM4U3Tjvx8bn+KGM51BA2VL6poq3AyOHguq3dzDjI74lxYZfOV1zAEEiSbcGd8CXgx9N9JRS5MlS4izTWJRig==} - hast-util-from-html@2.0.1: - resolution: {integrity: sha512-RXQBLMl9kjKVNkJTIO6bZyb2n+cUH8LFaSSzo82jiLT6Tfc+Pt7VQCS+/h3YwG4jaNE2TA2sdJisGWR+aJrp0g==} + hast-util-from-html@2.0.3: + resolution: {integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==} hast-util-from-parse5@8.0.1: resolution: {integrity: sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==} @@ -5634,9 +5696,6 @@ packages: hast-util-select@6.0.2: resolution: {integrity: sha512-hT/SD/d/Meu+iobvgkffo1QecV8WeKWxwsNMzcTJsKw1cKTQKSR/7ArJeURLNJF9HDjp9nVoORyNNJxrvBye8Q==} - hast-util-to-html@9.0.2: - resolution: {integrity: sha512-RP5wNpj5nm1Z8cloDv4Sl4RS8jH5HYa0v93YB6Wb4poEzgMo/dAAL0KcT4974dCjcNG5pkLqTImeFHHCwwfY3g==} - hast-util-to-html@9.0.3: resolution: {integrity: sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==} @@ -5677,8 +5736,8 @@ packages: resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} engines: {node: '>=0.10.0'} - hono@4.6.2: - resolution: {integrity: sha512-v+39817TgAhetmHUEli8O0uHDmxp2Up3DnhS4oUZXOl5IQ9np9tYtldd42e5zgdLVS0wsOoXQNZ6mx+BGmEvCA==} + hono@4.6.3: + resolution: {integrity: sha512-0LeEuBNFeSHGqZ9sNVVgZjB1V5fmhkBSB0hZrpqStSMLOWgfLy0dHOvrjbJh0H2khsjet6rbHfWTHY0kpYThKQ==} engines: {node: '>=16.9.0'} hosted-git-info@2.8.9: @@ -5981,12 +6040,16 @@ packages: resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} hasBin: true + jiti@2.0.0: + resolution: {integrity: sha512-CJ7e7Abb779OTRv3lomfp7Mns/Sy1+U4pcAx5VbjxCZD5ZM/VJaXPpPjNKjtSvWQy/H86E49REXR34dl1JEz9w==} + hasBin: true + jiti@2.0.0-beta.3: resolution: {integrity: sha512-pmfRbVRs/7khFrSAYnSiJ8C0D5GvzkE4Ey2pAvUcJsw1ly/p+7ut27jbJrjY79BpAJQJ4gXYFtK6d1Aub+9baQ==} hasBin: true - jose@5.8.0: - resolution: {integrity: sha512-E7CqYpL/t7MMnfGnK/eg416OsFCVUrU/Y3Vwe7QjKhu/BkS1Ms455+2xsqZQVN57/U2MHMBvEb5SrmAZWAIntA==} + jose@5.9.3: + resolution: {integrity: sha512-egLIoYSpcd+QUF+UHgobt5YzI2Pkw/H39ou9suW687MY6PmCwPmkNV/4TNjn1p2tX5xO3j0d0sq5hiYE24bSlg==} jotai@2.10.0: resolution: {integrity: sha512-8W4u0aRlOIwGlLQ0sqfl/c6+eExl5D8lZgAUolirZLktyaj4WnxO/8a0HEPmtriQAB6X5LMhXzZVmw02X0P0qQ==} @@ -6640,8 +6703,8 @@ packages: encoding: optional: true - node-gyp-build@4.8.1: - resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==} + node-gyp-build@4.8.2: + resolution: {integrity: sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw==} hasBin: true node-gyp@9.4.1: @@ -6700,8 +6763,8 @@ packages: engines: {node: ^14.16.0 || >=16.10.0} hasBin: true - oauth4webapi@2.12.1: - resolution: {integrity: sha512-7lgyz74z5NJ1dRbZSnL/YCJt7UMhNOqQ8I6Jokh/Et66GVK6KfFikzU98i5PTbgbrsSmxzsQprJdI3Z+5Uwj2Q==} + oauth4webapi@2.17.0: + resolution: {integrity: sha512-lbC0Z7uzAFNFyzEYRIC+pkSVvDHJTbEW+dYlSBAlCYDe6RxUkJ26bClhk8ocBZip1wfI9uKTe0fm4Ib4RHn6uQ==} object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} @@ -6909,8 +6972,8 @@ packages: resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} engines: {node: 20 || >=22} - path-to-regexp@8.1.0: - resolution: {integrity: sha512-Bqn3vc8CMHty6zuD+tG23s6v2kwxslHEhTj4eYaVKGIEB+YX/2wd0/rgXLFD9G9id9KCtbVy/3ZgmvZjpa0UdQ==} + path-to-regexp@8.2.0: + resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==} engines: {node: '>=16'} path-type@2.0.0: @@ -6957,6 +7020,9 @@ packages: pg-protocol@1.6.1: resolution: {integrity: sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==} + pg-protocol@1.7.0: + resolution: {integrity: sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==} + pg-types@2.2.0: resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} engines: {node: '>=4'} @@ -7267,8 +7333,8 @@ packages: postgres-range@1.1.4: resolution: {integrity: sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==} - posthog-js@1.163.0: - resolution: {integrity: sha512-gpLbxZkOm06oOWg0uvCxBIVIHrhX3A5hxf9eAi/Z+aFP9DvWxwHQdGUkIWjnYUyxXilIbLxBPvWmiM98dYsAHA==} + posthog-js@1.165.0: + resolution: {integrity: sha512-rUfRJobvOz3Q9Er+zwb32Eq2qs+ToBe/B4k4IoKzmyszI7240Rf4xVWRB0ky8LvmdZfCeYX5knS2Uv3pnn/d5A==} posthog-node@4.2.0: resolution: {integrity: sha512-hgyCYMyzMvuF3qWMw6JvS8gT55v7Mtp5wKWcnDrw+nu39D0Tk9BXD7I0LOBp0lGlHEPaXCEVYUtviNKrhMALGA==} @@ -7287,8 +7353,8 @@ packages: preact@10.11.3: resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==} - preact@10.23.2: - resolution: {integrity: sha512-kKYfePf9rzKnxOAKDpsWhg/ysrHPqT+yQ7UW4JjdnqjFIeNUnNcEJvhuA8fDenxAGWzUqtd51DfVg7xp/8T9NA==} + preact@10.24.1: + resolution: {integrity: sha512-PnBAwFI3Yjxxcxw75n6VId/5TFxNW/81zexzWD9jn1+eSrOP84NdsS38H5IkF/UH3frqRPT+MvuCoVHjTDTnDw==} prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} @@ -7370,8 +7436,8 @@ packages: rc9@2.1.2: resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} - re-resizable@6.9.18: - resolution: {integrity: sha512-4RgEES1iizvpaNtvcJz2fUOw5efuK5Jaix3+nY4yQvI6pxKKkFaoKZB1KtiXd8hawR2BGdcoJFS4NGDPketAYQ==} + re-resizable@6.10.0: + resolution: {integrity: sha512-hysSK0xmA5nz24HBVztlk4yCqCLCvS32E6ZpWxVKop9x3tqCa4yAj1++facrmkOf62JsJHjmjABdKxXofYioCw==} peerDependencies: react: ^16.13.1 || ^17.0.0 || ^18.0.0 react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 @@ -7620,14 +7686,14 @@ packages: rehype-infer-description-meta@2.0.0: resolution: {integrity: sha512-8MZjKRfQiNB5+Qpt0fS9bpjcKe+nhF5GOTHo0M5e+XdStDpcZxkSMMnCfNIlpNaOyIQ7Hu1qEaUxm8ZL1lYI1g==} - rehype-parse@9.0.0: - resolution: {integrity: sha512-WG7nfvmWWkCR++KEkZevZb/uw41E8TsH4DsY9UxsTbIXCVGbAs4S+r8FrQ+OtH5EEQAs+5UxKC42VinkmpA1Yw==} + rehype-parse@9.0.1: + resolution: {integrity: sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==} rehype-sanitize@6.0.0: resolution: {integrity: sha512-CsnhKNsyI8Tub6L4sm5ZFsme4puGfc6pYylvXo1AeqaGbjOYyzNv3qZPwvs0oMJ39eryyeOdmxwUIo94IpEhqg==} - rehype-stringify@10.0.0: - resolution: {integrity: sha512-1TX1i048LooI9QoecrXy7nGFFbFSufxVRAfc6Y9YMRAi56l+oB0zP51mLSV312uRuvVLPV1opSlJmslozR1XHQ==} + rehype-stringify@10.0.1: + resolution: {integrity: sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==} remark-directive@3.0.0: resolution: {integrity: sha512-l1UyWJ6Eg1VPU7Hm/9tt0zKtReJQNOA4+iDMAxTyZNWnJnFlbS/7zhiel/rogTLQ2vMYwDzSJa4BiVNqGlqIMA==} @@ -7754,6 +7820,11 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + rollup@4.22.5: + resolution: {integrity: sha512-WoinX7GeQOFMGznEcWA1WrTQCd/tpEbMkc3nuMs9BT0CPjMdSjPMTVClwWd4pgSQwJdP65SK9mTCNvItlr5o7w==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -7839,8 +7910,8 @@ packages: engines: {node: '>=4'} hasBin: true - shiki@1.18.0: - resolution: {integrity: sha512-8jo7tOXr96h9PBQmOHVrltnETn1honZZY76YA79MHheGQg55jBvbm9dtU+MI5pjC5NJCFuA6rvVTLVeSW5cE4A==} + shiki@1.20.0: + resolution: {integrity: sha512-MZJJ1PCFsQB1Piq+25wiz0a75yUv8Q3/fzy7SzRx5ONdjdtGdyiKwYn8vb/FnK5kjS0voWGnPpjG16POauUR+g==} shimmer@1.2.1: resolution: {integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==} @@ -8113,8 +8184,8 @@ packages: peerDependencies: tailwindcss: '>=3.0.0 || insiders' - tailwindcss@3.4.12: - resolution: {integrity: sha512-Htf/gHj2+soPb9UayUNci/Ja3d8pTmu9ONTfh4QY8r3MATTZOzmv6UYWF7ZwikEIC8okpfqmGqrmDehua8mF8w==} + tailwindcss@3.4.13: + resolution: {integrity: sha512-KqjHOJKogOUt5Bs752ykCeiwvi0fKVkr5oqsFNt/8px/tA8scFPIlkygsf6jXrfCqGHz7VflA6+yytWuM+XhFw==} engines: {node: '>=14.0.0'} hasBin: true @@ -8133,8 +8204,8 @@ packages: resolution: {integrity: sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==} engines: {node: '>=6.0.0'} - terser@5.32.0: - resolution: {integrity: sha512-v3Gtw3IzpBJ0ugkxEX8U0W6+TnPKRRCWGh1jC/iM/e3Ki5+qvO1L1EAZ56bZasc64aXHwRHNIQEzm6//i5cemQ==} + terser@5.34.1: + resolution: {integrity: sha512-FsJZ7iZLd/BXkz+4xrRTGJ26o/6VTjQytUk8b8OxkwcD2I+79VPJlz7qss1+zE7h8GNIScFqXcDyJ/KqBYZFVA==} engines: {node: '>=10'} hasBin: true @@ -8169,15 +8240,15 @@ packages: resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} engines: {node: '>=14.0.0'} - tinyspy@3.0.0: - resolution: {integrity: sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA==} + tinyspy@3.0.2: + resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} engines: {node: '>=14.0.0'} - tldts-core@6.1.47: - resolution: {integrity: sha512-6SWyFMnlst1fEt7GQVAAu16EGgFK0cLouH/2Mk6Ftlwhv3Ol40L0dlpGMcnnNiiOMyD2EV/aF3S+U2nKvvLvrA==} + tldts-core@6.1.48: + resolution: {integrity: sha512-3gD9iKn/n2UuFH1uilBviK9gvTNT6iYwdqrj1Vr5mh8FuelvpRNaYVH4pNYqUgOGU4aAdL9X35eLuuj0gRsx+A==} - tldts@6.1.47: - resolution: {integrity: sha512-R/K2tZ5MiY+mVrnSkNJkwqYT2vUv1lcT6wJvd2emGaMJ7PHUGRY4e3tUsdFCXgqxi2QgbHjL3yJgXCo40v9Hxw==} + tldts@6.1.48: + resolution: {integrity: sha512-SPbnh1zaSzi/OsmHb1vrPNnYuwJbdWjwo5TbBYYMlTtH3/1DSb41t8bcSxkwDmmbG2q6VLPVvQc7Yf23T+1EEw==} hasBin: true tmp-promise@3.0.3: @@ -8245,8 +8316,8 @@ packages: ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - ts-pattern@5.3.1: - resolution: {integrity: sha512-1RUMKa8jYQdNfmnK4jyzBK3/PS/tnjcZ1CW0v1vWDeYe5RBklc/nquw03MEoB66hVBm4BnlCfmOqDVxHyT1DpA==} + ts-pattern@5.4.0: + resolution: {integrity: sha512-hgfOMfjlrARCnYtGD/xEAkFHDXuSyuqjzFSltyQCbN689uNvoQL20TVN2XFcLMjfNuwSsQGU+xtH6MrjIwhwUg==} tsconfck@3.1.1: resolution: {integrity: sha512-00eoI6WY57SvZEVjm13stEVE90VkEdJAFGgpFLTsZbJyW/LwFQ7uQxJHWpZ2hzSWgCPKc9AnBnNP+0X7o3hAmQ==} @@ -8309,8 +8380,8 @@ packages: resolution: {integrity: sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==} engines: {node: '>=16'} - typescript-eslint@8.6.0: - resolution: {integrity: sha512-eEhhlxCEpCd4helh3AO1hk0UP2MvbRi9CtIAJTVPQjuSXOOO2jsEacNi4UdcJzZJbeuVg1gMhtZ8UYb+NFYPrA==} + typescript-eslint@8.7.0: + resolution: {integrity: sha512-nEHbEYJyHwsuf7c3V3RS7Saq+1+la3i0ieR3qP0yjqWSzVmh8Drp47uOl9LjbPANac4S7EFSqvcYIKXUUwIfIQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '*' @@ -8510,8 +8581,8 @@ packages: vfile@6.0.3: resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} - vite-bundle-analyzer@0.10.6: - resolution: {integrity: sha512-w/5wvRZeZo2lKdJzRGCTn4YW/mT++fKeii2PQPK3odblfFqsODYHF72V+QTg1Xznbxy543N0WfT5vPiSosVWxA==} + vite-bundle-analyzer@0.12.1: + resolution: {integrity: sha512-mIYwsDvTYCqXAUtOZIL3f7NdwWUeL/MlNFhOJzlTdcZE4pye6h06IEnOvWhnc/e+HM4oVVNxuRHZt0Rz6VO7EA==} vite-node@2.0.5: resolution: {integrity: sha512-LdsW4pxj0Ot69FAoXZ1yTnA9bjGohr2yNBU7QKRxpz8ITSkhuDl6h3zS/tvgz4qrNjeRnvrWeXQ8ZF7Um4W00Q==} @@ -8532,8 +8603,8 @@ packages: vite: optional: true - vite@5.4.7: - resolution: {integrity: sha512-5l2zxqMEPVENgvzTuBpHer2awaetimj2BGkhBPdnwKbPNOlHsODU+oiazEZzLK7KhAnOrO+XGYJYn4ZlUhDtDQ==} + vite@5.4.8: + resolution: {integrity: sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -8733,8 +8804,8 @@ packages: resolution: {integrity: sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==} engines: {node: '>= 10'} - zod-validation-error@3.3.1: - resolution: {integrity: sha512-uFzCZz7FQis256dqw4AhPQgD6f3pzNca/Zh62RNELavlumQB3nDIUFbF5JQfFLcMbO1s02Q7Xg/gpcOBlEnYZA==} + zod-validation-error@3.4.0: + resolution: {integrity: sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==} engines: {node: '>=18.0.0'} peerDependencies: zod: ^3.18.0 @@ -8780,13 +8851,13 @@ snapshots: '@antfu/utils@0.7.10': {} - '@auth/core@0.34.2': + '@auth/core@0.35.3': dependencies: '@panva/hkdf': 1.2.1 '@types/cookie': 0.6.0 cookie: 0.6.0 - jose: 5.8.0 - oauth4webapi: 2.12.1 + jose: 5.9.3 + oauth4webapi: 2.17.0 preact: 10.11.3 preact-render-to-string: 5.2.3(preact@10.11.3) @@ -9607,10 +9678,10 @@ snapshots: '@egjs/list-differ@1.0.1': {} - '@egoist/tailwindcss-icons@1.8.1(tailwindcss@3.4.12)': + '@egoist/tailwindcss-icons@1.8.1(tailwindcss@3.4.13)': dependencies: '@iconify/utils': 2.1.32 - tailwindcss: 3.4.12 + tailwindcss: 3.4.13 transitivePeerDependencies: - supports-color @@ -9868,9 +9939,9 @@ snapshots: dependencies: electron: 32.1.2 - '@electron-toolkit/tsconfig@1.0.1(@types/node@22.5.5)': + '@electron-toolkit/tsconfig@1.0.1(@types/node@22.7.4)': dependencies: - '@types/node': 22.5.5 + '@types/node': 22.7.4 '@electron-toolkit/utils@3.0.0(electron@32.1.2)': dependencies: @@ -10071,12 +10142,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@emotion/is-prop-valid@0.8.8': + '@emotion/is-prop-valid@1.3.1': dependencies: - '@emotion/memoize': 0.7.4 + '@emotion/memoize': 0.9.0 optional: true - '@emotion/memoize@0.7.4': + '@emotion/memoize@0.9.0': optional: true '@es-joy/jsdoccomment@0.48.0': @@ -10226,115 +10297,115 @@ snapshots: '@esbuild/win32-x64@0.23.1': optional: true - '@eslint-community/eslint-utils@4.4.0(eslint@9.11.0(jiti@1.21.6))': + '@eslint-community/eslint-utils@4.4.0(eslint@9.11.1(jiti@2.0.0))': dependencies: - eslint: 9.11.0(jiti@1.21.6) + eslint: 9.11.1(jiti@2.0.0) eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.11.0': {} + '@eslint-community/regexpp@4.11.1': {} - '@eslint-react/ast@1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2)': + '@eslint-react/ast@1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2)': dependencies: - '@eslint-react/tools': 1.14.1 - '@eslint-react/types': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/types': 8.6.0 - '@typescript-eslint/typescript-estree': 8.6.0(typescript@5.6.2) - '@typescript-eslint/utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) + '@eslint-react/tools': 1.14.2 + '@eslint-react/types': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/types': 8.7.0 + '@typescript-eslint/typescript-estree': 8.7.0(typescript@5.6.2) + '@typescript-eslint/utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) birecord: 0.1.1 string-ts: 2.2.0 - ts-pattern: 5.3.1 + ts-pattern: 5.4.0 transitivePeerDependencies: - eslint - supports-color - typescript - '@eslint-react/core@1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2)': + '@eslint-react/core@1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2)': dependencies: - '@eslint-react/ast': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/jsx': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/shared': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/tools': 1.14.1 - '@eslint-react/types': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/var': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/scope-manager': 8.6.0 - '@typescript-eslint/type-utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/types': 8.6.0 - '@typescript-eslint/utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) + '@eslint-react/ast': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/jsx': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/shared': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/tools': 1.14.2 + '@eslint-react/types': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/var': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.7.0 + '@typescript-eslint/type-utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/types': 8.7.0 + '@typescript-eslint/utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) birecord: 0.1.1 short-unique-id: 5.2.0 - ts-pattern: 5.3.1 + ts-pattern: 5.4.0 transitivePeerDependencies: - eslint - supports-color - typescript - '@eslint-react/eslint-plugin@1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2)': + '@eslint-react/eslint-plugin@1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2)': dependencies: - '@eslint-react/shared': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/tools': 1.14.1 - '@eslint-react/types': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/scope-manager': 8.6.0 - '@typescript-eslint/type-utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/types': 8.6.0 - '@typescript-eslint/utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - eslint: 9.11.0(jiti@1.21.6) - eslint-plugin-react-debug: 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - eslint-plugin-react-dom: 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - eslint-plugin-react-hooks-extra: 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - eslint-plugin-react-naming-convention: 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - eslint-plugin-react-web-api: 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - eslint-plugin-react-x: 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) + '@eslint-react/shared': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/tools': 1.14.2 + '@eslint-react/types': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.7.0 + '@typescript-eslint/type-utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/types': 8.7.0 + '@typescript-eslint/utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + eslint: 9.11.1(jiti@2.0.0) + eslint-plugin-react-debug: 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + eslint-plugin-react-dom: 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + eslint-plugin-react-hooks-extra: 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + eslint-plugin-react-naming-convention: 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + eslint-plugin-react-web-api: 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + eslint-plugin-react-x: 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: - supports-color - '@eslint-react/jsx@1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2)': + '@eslint-react/jsx@1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2)': dependencies: - '@eslint-react/ast': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/tools': 1.14.1 - '@eslint-react/types': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/var': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/scope-manager': 8.6.0 - '@typescript-eslint/types': 8.6.0 - '@typescript-eslint/utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - ts-pattern: 5.3.1 + '@eslint-react/ast': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/tools': 1.14.2 + '@eslint-react/types': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/var': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.7.0 + '@typescript-eslint/types': 8.7.0 + '@typescript-eslint/utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + ts-pattern: 5.4.0 transitivePeerDependencies: - eslint - supports-color - typescript - '@eslint-react/shared@1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2)': + '@eslint-react/shared@1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2)': dependencies: - '@eslint-react/tools': 1.14.1 - '@typescript-eslint/utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) + '@eslint-react/tools': 1.14.2 + '@typescript-eslint/utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) picomatch: 4.0.2 transitivePeerDependencies: - eslint - supports-color - typescript - '@eslint-react/tools@1.14.1': {} + '@eslint-react/tools@1.14.2': {} - '@eslint-react/types@1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2)': + '@eslint-react/types@1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2)': dependencies: - '@eslint-react/tools': 1.14.1 - '@typescript-eslint/types': 8.6.0 - '@typescript-eslint/utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) + '@eslint-react/tools': 1.14.2 + '@typescript-eslint/types': 8.7.0 + '@typescript-eslint/utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) transitivePeerDependencies: - eslint - supports-color - typescript - '@eslint-react/var@1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2)': + '@eslint-react/var@1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2)': dependencies: - '@eslint-react/ast': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/tools': 1.14.1 - '@eslint-react/types': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/scope-manager': 8.6.0 - '@typescript-eslint/types': 8.6.0 - '@typescript-eslint/utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - ts-pattern: 5.3.1 + '@eslint-react/ast': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/tools': 1.14.2 + '@eslint-react/types': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.7.0 + '@typescript-eslint/types': 8.7.0 + '@typescript-eslint/utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + ts-pattern: 5.4.0 transitivePeerDependencies: - eslint - supports-color @@ -10350,11 +10421,13 @@ snapshots: transitivePeerDependencies: - supports-color + '@eslint/core@0.6.0': {} + '@eslint/eslintrc@3.1.0': dependencies: ajv: 6.12.6 debug: 4.3.7 - espree: 10.1.0 + espree: 10.2.0 globals: 14.0.0 ignore: 5.3.2 import-fresh: 3.3.0 @@ -10364,9 +10437,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.10.0': {} - - '@eslint/js@9.11.0': {} + '@eslint/js@9.11.1': {} '@eslint/object-schema@2.1.4': {} @@ -10399,23 +10470,23 @@ snapshots: '@floating-ui/core': 1.6.7 '@floating-ui/utils': 0.2.7 - '@floating-ui/react-dom-interactions@0.3.1(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@floating-ui/react-dom-interactions@0.3.1(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@floating-ui/react-dom': 0.6.3(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@floating-ui/react-dom': 0.6.3(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) aria-hidden: 1.2.4 point-in-polygon: 1.1.0 - use-isomorphic-layout-effect: 1.1.2(@types/react@18.3.8)(react@18.3.1) + use-isomorphic-layout-effect: 1.1.2(@types/react@18.3.10)(react@18.3.1) transitivePeerDependencies: - '@types/react' - react - react-dom - '@floating-ui/react-dom@0.6.3(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@floating-ui/react-dom@0.6.3(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@floating-ui/dom': 0.4.5 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - use-isomorphic-layout-effect: 1.1.2(@types/react@18.3.8)(react@18.3.1) + use-isomorphic-layout-effect: 1.1.2(@types/react@18.3.10)(react@18.3.1) transitivePeerDependencies: - '@types/react' @@ -10456,15 +10527,15 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@hono/auth-js@1.0.10(@auth/core@0.34.2)(hono@4.6.2(patch_hash=iej2g43ojhll5opwbnvyorjq4e))(react@18.3.1)': + '@hono/auth-js@1.0.10(@auth/core@0.35.3)(hono@4.6.3(patch_hash=iej2g43ojhll5opwbnvyorjq4e))(react@18.3.1)': dependencies: - '@auth/core': 0.34.2 - hono: 4.6.2(patch_hash=iej2g43ojhll5opwbnvyorjq4e) + '@auth/core': 0.35.3 + hono: 4.6.3(patch_hash=iej2g43ojhll5opwbnvyorjq4e) react: 18.3.1 - '@hono/node-server@1.13.1(hono@4.6.2(patch_hash=iej2g43ojhll5opwbnvyorjq4e))': + '@hono/node-server@1.13.1(hono@4.6.3(patch_hash=iej2g43ojhll5opwbnvyorjq4e))': dependencies: - hono: 4.6.2(patch_hash=iej2g43ojhll5opwbnvyorjq4e) + hono: 4.6.3(patch_hash=iej2g43ojhll5opwbnvyorjq4e) '@hookform/resolvers@3.9.0(react-hook-form@7.53.0(react@18.3.1))': dependencies: @@ -10484,14 +10555,14 @@ snapshots: dependencies: '@iconify/types': 2.0.0 - '@iconify-json/simple-icons@1.2.3': + '@iconify-json/simple-icons@1.2.4': dependencies: '@iconify/types': 2.0.0 - '@iconify/tools@4.0.6': + '@iconify/tools@4.0.7': dependencies: '@iconify/types': 2.0.0 - '@iconify/utils': 2.1.32 + '@iconify/utils': 2.1.33 '@types/tar': 6.1.13 axios: 1.7.7(debug@4.3.7) cheerio: 1.0.0 @@ -10519,6 +10590,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@iconify/utils@2.1.33': + dependencies: + '@antfu/install-pkg': 0.4.1 + '@antfu/utils': 0.7.10 + '@iconify/types': 2.0.0 + debug: 4.3.7 + kolorist: 1.8.0 + local-pkg: 0.5.0 + mlly: 1.7.1 + transitivePeerDependencies: + - supports-color + '@innei/react-resizable-layout@0.7.3-fork.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: react: 18.3.1 @@ -10555,13 +10638,13 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@lottiefiles/dotlottie-react@0.8.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@lottiefiles/dotlottie-react@0.9.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@lottiefiles/dotlottie-web': 0.33.0 + '@lottiefiles/dotlottie-web': 0.34.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@lottiefiles/dotlottie-web@0.33.0': {} + '@lottiefiles/dotlottie-web@0.34.0': {} '@malept/cross-spawn-promise@1.1.1': dependencies: @@ -11014,675 +11097,675 @@ snapshots: '@radix-ui/primitive@1.1.0': {} - '@radix-ui/react-alert-dialog@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-alert-dialog@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-dialog': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-dialog': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-arrow@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-arrow@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-avatar@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-avatar@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-context': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-checkbox@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-checkbox@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-collection@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-collection@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-compose-refs@1.0.1(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-compose-refs@1.0.1(@types/react@18.3.10)(react@18.3.1)': dependencies: '@babel/runtime': 7.25.4 react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-compose-refs@1.1.0(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-compose-refs@1.1.0(@types/react@18.3.10)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-context-menu@2.2.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-context-menu@2.2.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-context': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-menu': 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-menu': 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-context@1.0.1(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-context@1.0.1(@types/react@18.3.10)(react@18.3.1)': dependencies: '@babel/runtime': 7.25.4 react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-context@1.1.0(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-context@1.1.0(@types/react@18.3.10)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-dialog@1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-dialog@1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.25.4 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-context': 1.0.1(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.0.1(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.0.2(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-context': 1.0.1(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.0.1(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.0.2(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.3.10)(react@18.3.1) aria-hidden: 1.2.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.5.5(@types/react@18.3.8)(react@18.3.1) + react-remove-scroll: 2.5.5(@types/react@18.3.10)(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-dialog@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-dialog@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.10)(react@18.3.1) aria-hidden: 1.2.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.5.7(@types/react@18.3.8)(react@18.3.1) + react-remove-scroll: 2.5.7(@types/react@18.3.10)(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-direction@1.1.0(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-direction@1.1.0(@types/react@18.3.10)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.25.4 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-dismissable-layer@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-dismissable-layer@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-dropdown-menu@2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-dropdown-menu@2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-menu': 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-menu': 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-focus-guards@1.0.1(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-focus-guards@1.0.1(@types/react@18.3.10)(react@18.3.1)': dependencies: '@babel/runtime': 7.25.4 react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-focus-guards@1.1.0(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-focus-guards@1.1.0(@types/react@18.3.10)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-focus-scope@1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-focus-scope@1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.25.4 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-focus-scope@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-focus-scope@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-hover-card@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-hover-card@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-id@1.0.1(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-id@1.0.1(@types/react@18.3.10)(react@18.3.1)': dependencies: '@babel/runtime': 7.25.4 - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-id@1.1.0(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-id@1.1.0(@types/react@18.3.10)(react@18.3.1)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-label@2.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-label@2.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-menu@2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-menu@2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-direction': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-roving-focus': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.10)(react@18.3.1) aria-hidden: 1.2.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.5.7(@types/react@18.3.8)(react@18.3.1) + react-remove-scroll: 2.5.7(@types/react@18.3.10)(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-popover@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-popover@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.10)(react@18.3.1) aria-hidden: 1.2.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.5.7(@types/react@18.3.8)(react@18.3.1) + react-remove-scroll: 2.5.7(@types/react@18.3.10)(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-popper@1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-popper@1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@floating-ui/react-dom': 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-arrow': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-rect': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-arrow': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-rect': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.10)(react@18.3.1) '@radix-ui/rect': 1.1.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-portal@1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-portal@1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.25.4 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-portal@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-portal@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-presence@1.0.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-presence@1.0.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.25.4 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-presence@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-presence@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-primitive@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-primitive@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.25.4 - '@radix-ui/react-slot': 1.0.2(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-slot': 1.0.2(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-primitive@2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-primitive@2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-slot': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-radio-group@1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-radio-group@1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-direction': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-roving-focus': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-roving-focus@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-roving-focus@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-direction': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-scroll-area@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-scroll-area@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/number': 1.1.0 '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-direction': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-select@2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-select@2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/number': 1.1.0 '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-direction': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) aria-hidden: 1.2.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.5.7(@types/react@18.3.8)(react@18.3.1) + react-remove-scroll: 2.5.7(@types/react@18.3.10)(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-slider@1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-slider@1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/number': 1.1.0 '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-direction': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-slot@1.0.2(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-slot@1.0.2(@types/react@18.3.10)(react@18.3.1)': dependencies: '@babel/runtime': 7.25.4 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-slot@1.1.0(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-slot@1.1.0(@types/react@18.3.10)(react@18.3.1)': dependencies: - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-switch@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-switch@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-tabs@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-tabs@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-context': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-direction': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-roving-focus': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-toast@1.2.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-toast@1.2.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-tooltip@1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-tooltip@1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.8)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.10)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 - '@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.3.10)(react@18.3.1)': dependencies: '@babel/runtime': 7.25.4 react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-use-callback-ref@1.1.0(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-use-callback-ref@1.1.0(@types/react@18.3.10)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.3.10)(react@18.3.1)': dependencies: '@babel/runtime': 7.25.4 - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-use-controllable-state@1.1.0(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-use-controllable-state@1.1.0(@types/react@18.3.10)(react@18.3.1)': dependencies: - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.3.10)(react@18.3.1)': dependencies: '@babel/runtime': 7.25.4 - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@18.3.10)(react@18.3.1)': dependencies: - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.3.10)(react@18.3.1)': dependencies: '@babel/runtime': 7.25.4 react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-use-layout-effect@1.1.0(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-use-layout-effect@1.1.0(@types/react@18.3.10)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-use-previous@1.1.0(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-use-previous@1.1.0(@types/react@18.3.10)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-use-rect@1.1.0(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-use-rect@1.1.0(@types/react@18.3.10)(react@18.3.1)': dependencies: '@radix-ui/rect': 1.1.0 react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-use-size@1.1.0(@types/react@18.3.8)(react@18.3.1)': + '@radix-ui/react-use-size@1.1.0(@types/react@18.3.10)(react@18.3.1)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.10)(react@18.3.1) react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@radix-ui/react-visually-hidden@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-visually-hidden@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 '@types/react-dom': 18.3.0 '@radix-ui/rect@1.1.0': {} @@ -11767,51 +11850,99 @@ snapshots: '@rollup/rollup-android-arm-eabi@4.21.2': optional: true + '@rollup/rollup-android-arm-eabi@4.22.5': + optional: true + '@rollup/rollup-android-arm64@4.21.2': optional: true + '@rollup/rollup-android-arm64@4.22.5': + optional: true + '@rollup/rollup-darwin-arm64@4.21.2': optional: true + '@rollup/rollup-darwin-arm64@4.22.5': + optional: true + '@rollup/rollup-darwin-x64@4.21.2': optional: true + '@rollup/rollup-darwin-x64@4.22.5': + optional: true + '@rollup/rollup-linux-arm-gnueabihf@4.21.2': optional: true + '@rollup/rollup-linux-arm-gnueabihf@4.22.5': + optional: true + '@rollup/rollup-linux-arm-musleabihf@4.21.2': optional: true + '@rollup/rollup-linux-arm-musleabihf@4.22.5': + optional: true + '@rollup/rollup-linux-arm64-gnu@4.21.2': optional: true + '@rollup/rollup-linux-arm64-gnu@4.22.5': + optional: true + '@rollup/rollup-linux-arm64-musl@4.21.2': optional: true + '@rollup/rollup-linux-arm64-musl@4.22.5': + optional: true + '@rollup/rollup-linux-powerpc64le-gnu@4.21.2': optional: true + '@rollup/rollup-linux-powerpc64le-gnu@4.22.5': + optional: true + '@rollup/rollup-linux-riscv64-gnu@4.21.2': optional: true + '@rollup/rollup-linux-riscv64-gnu@4.22.5': + optional: true + '@rollup/rollup-linux-s390x-gnu@4.21.2': optional: true + '@rollup/rollup-linux-s390x-gnu@4.22.5': + optional: true + '@rollup/rollup-linux-x64-gnu@4.21.2': optional: true + '@rollup/rollup-linux-x64-gnu@4.22.5': + optional: true + '@rollup/rollup-linux-x64-musl@4.21.2': optional: true + '@rollup/rollup-linux-x64-musl@4.22.5': + optional: true + '@rollup/rollup-win32-arm64-msvc@4.21.2': optional: true + '@rollup/rollup-win32-arm64-msvc@4.22.5': + optional: true + '@rollup/rollup-win32-ia32-msvc@4.21.2': optional: true + '@rollup/rollup-win32-ia32-msvc@4.22.5': + optional: true + '@rollup/rollup-win32-x64-msvc@4.21.2': optional: true + '@rollup/rollup-win32-x64-msvc@4.22.5': + optional: true + '@scena/dragscroll@1.4.0': dependencies: '@daybrush/utils': 1.13.0 @@ -11831,11 +11962,11 @@ snapshots: '@sentry/types': 8.26.0 '@sentry/utils': 8.26.0 - '@sentry-internal/browser-utils@8.30.0': + '@sentry-internal/browser-utils@8.32.0': dependencies: - '@sentry/core': 8.30.0 - '@sentry/types': 8.30.0 - '@sentry/utils': 8.30.0 + '@sentry/core': 8.32.0 + '@sentry/types': 8.32.0 + '@sentry/utils': 8.32.0 '@sentry-internal/feedback@8.26.0': dependencies: @@ -11843,11 +11974,11 @@ snapshots: '@sentry/types': 8.26.0 '@sentry/utils': 8.26.0 - '@sentry-internal/feedback@8.30.0': + '@sentry-internal/feedback@8.32.0': dependencies: - '@sentry/core': 8.30.0 - '@sentry/types': 8.30.0 - '@sentry/utils': 8.30.0 + '@sentry/core': 8.32.0 + '@sentry/types': 8.32.0 + '@sentry/utils': 8.32.0 '@sentry-internal/replay-canvas@8.26.0': dependencies: @@ -11856,12 +11987,12 @@ snapshots: '@sentry/types': 8.26.0 '@sentry/utils': 8.26.0 - '@sentry-internal/replay-canvas@8.30.0': + '@sentry-internal/replay-canvas@8.32.0': dependencies: - '@sentry-internal/replay': 8.30.0 - '@sentry/core': 8.30.0 - '@sentry/types': 8.30.0 - '@sentry/utils': 8.30.0 + '@sentry-internal/replay': 8.32.0 + '@sentry/core': 8.32.0 + '@sentry/types': 8.32.0 + '@sentry/utils': 8.32.0 '@sentry-internal/replay@8.26.0': dependencies: @@ -11870,12 +12001,12 @@ snapshots: '@sentry/types': 8.26.0 '@sentry/utils': 8.26.0 - '@sentry-internal/replay@8.30.0': + '@sentry-internal/replay@8.32.0': dependencies: - '@sentry-internal/browser-utils': 8.30.0 - '@sentry/core': 8.30.0 - '@sentry/types': 8.30.0 - '@sentry/utils': 8.30.0 + '@sentry-internal/browser-utils': 8.32.0 + '@sentry/core': 8.32.0 + '@sentry/types': 8.32.0 + '@sentry/utils': 8.32.0 '@sentry/babel-plugin-component-annotate@2.22.4': {} @@ -11889,15 +12020,15 @@ snapshots: '@sentry/types': 8.26.0 '@sentry/utils': 8.26.0 - '@sentry/browser@8.30.0': + '@sentry/browser@8.32.0': dependencies: - '@sentry-internal/browser-utils': 8.30.0 - '@sentry-internal/feedback': 8.30.0 - '@sentry-internal/replay': 8.30.0 - '@sentry-internal/replay-canvas': 8.30.0 - '@sentry/core': 8.30.0 - '@sentry/types': 8.30.0 - '@sentry/utils': 8.30.0 + '@sentry-internal/browser-utils': 8.32.0 + '@sentry-internal/feedback': 8.32.0 + '@sentry-internal/replay': 8.32.0 + '@sentry-internal/replay-canvas': 8.32.0 + '@sentry/core': 8.32.0 + '@sentry/types': 8.32.0 + '@sentry/utils': 8.32.0 '@sentry/bundler-plugin-core@2.22.4(encoding@0.1.13)': dependencies: @@ -11958,10 +12089,10 @@ snapshots: '@sentry/types': 8.26.0 '@sentry/utils': 8.26.0 - '@sentry/core@8.30.0': + '@sentry/core@8.32.0': dependencies: - '@sentry/types': 8.30.0 - '@sentry/utils': 8.30.0 + '@sentry/types': 8.32.0 + '@sentry/utils': 8.32.0 '@sentry/electron@5.4.0': dependencies: @@ -12021,26 +12152,26 @@ snapshots: '@sentry/types': 8.26.0 '@sentry/utils': 8.26.0 - '@sentry/react@8.30.0(react@18.3.1)': + '@sentry/react@8.32.0(react@18.3.1)': dependencies: - '@sentry/browser': 8.30.0 - '@sentry/core': 8.30.0 - '@sentry/types': 8.30.0 - '@sentry/utils': 8.30.0 + '@sentry/browser': 8.32.0 + '@sentry/core': 8.32.0 + '@sentry/types': 8.32.0 + '@sentry/utils': 8.32.0 hoist-non-react-statics: 3.3.2 react: 18.3.1 '@sentry/types@8.26.0': {} - '@sentry/types@8.30.0': {} + '@sentry/types@8.32.0': {} '@sentry/utils@8.26.0': dependencies: '@sentry/types': 8.26.0 - '@sentry/utils@8.30.0': + '@sentry/utils@8.32.0': dependencies: - '@sentry/types': 8.30.0 + '@sentry/types': 8.32.0 '@sentry/vite-plugin@2.22.4(encoding@0.1.13)': dependencies: @@ -12050,31 +12181,31 @@ snapshots: - encoding - supports-color - '@shikijs/core@1.18.0': + '@shikijs/core@1.20.0': dependencies: - '@shikijs/engine-javascript': 1.18.0 - '@shikijs/engine-oniguruma': 1.18.0 - '@shikijs/types': 1.18.0 + '@shikijs/engine-javascript': 1.20.0 + '@shikijs/engine-oniguruma': 1.20.0 + '@shikijs/types': 1.20.0 '@shikijs/vscode-textmate': 9.2.2 '@types/hast': 3.0.4 hast-util-to-html: 9.0.3 - '@shikijs/engine-javascript@1.18.0': + '@shikijs/engine-javascript@1.20.0': dependencies: - '@shikijs/types': 1.18.0 + '@shikijs/types': 1.20.0 '@shikijs/vscode-textmate': 9.2.2 oniguruma-to-js: 0.4.3 - '@shikijs/engine-oniguruma@1.18.0': + '@shikijs/engine-oniguruma@1.20.0': dependencies: - '@shikijs/types': 1.18.0 + '@shikijs/types': 1.20.0 '@shikijs/vscode-textmate': 9.2.2 - '@shikijs/transformers@1.18.0': + '@shikijs/transformers@1.20.0': dependencies: - shiki: 1.18.0 + shiki: 1.20.0 - '@shikijs/types@1.18.0': + '@shikijs/types@1.20.0': dependencies: '@shikijs/vscode-textmate': 9.2.2 '@types/hast': 3.0.4 @@ -12083,12 +12214,12 @@ snapshots: '@sindresorhus/is@4.6.0': {} - '@stylistic/eslint-plugin@2.8.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2)': + '@stylistic/eslint-plugin@2.8.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2)': dependencies: - '@typescript-eslint/utils': 8.4.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - eslint: 9.11.0(jiti@1.21.6) - eslint-visitor-keys: 4.0.0 - espree: 10.1.0 + '@typescript-eslint/utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + eslint: 9.11.1(jiti@2.0.0) + eslint-visitor-keys: 4.1.0 + espree: 10.2.0 estraverse: 5.3.0 picomatch: 4.0.2 transitivePeerDependencies: @@ -12109,21 +12240,21 @@ snapshots: optionalDependencies: typescript: 5.6.2 - '@tailwindcss/container-queries@0.1.1(tailwindcss@3.4.12)': + '@tailwindcss/container-queries@0.1.1(tailwindcss@3.4.13)': dependencies: - tailwindcss: 3.4.12 + tailwindcss: 3.4.13 - '@tailwindcss/typography@0.5.15(tailwindcss@3.4.12)': + '@tailwindcss/typography@0.5.15(tailwindcss@3.4.13)': dependencies: lodash.castarray: 4.4.0 lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 postcss-selector-parser: 6.0.10 - tailwindcss: 3.4.12 + tailwindcss: 3.4.13 '@tanstack/query-core@5.56.2': {} - '@tanstack/query-devtools@5.56.1': {} + '@tanstack/query-devtools@5.58.0': {} '@tanstack/query-persist-client-core@5.56.2': dependencies: @@ -12134,9 +12265,9 @@ snapshots: '@tanstack/query-core': 5.56.2 '@tanstack/query-persist-client-core': 5.56.2 - '@tanstack/react-query-devtools@5.56.2(@tanstack/react-query@5.56.2(react@18.3.1))(react@18.3.1)': + '@tanstack/react-query-devtools@5.58.0(@tanstack/react-query@5.56.2(react@18.3.1))(react@18.3.1)': dependencies: - '@tanstack/query-devtools': 5.56.1 + '@tanstack/query-devtools': 5.58.0 '@tanstack/react-query': 5.56.2(react@18.3.1) react: 18.3.1 @@ -12165,7 +12296,7 @@ snapshots: '@types/appdmg@0.5.5': dependencies: - '@types/node': 22.5.5 + '@types/node': 22.7.4 optional: true '@types/babel__core@7.20.5': @@ -12193,12 +12324,12 @@ snapshots: dependencies: '@types/http-cache-semantics': 4.0.4 '@types/keyv': 3.1.4 - '@types/node': 22.5.5 + '@types/node': 22.7.4 '@types/responselike': 1.0.3 '@types/connect@3.4.36': dependencies: - '@types/node': 22.5.5 + '@types/node': 22.7.4 '@types/cookie@0.6.0': {} @@ -12206,25 +12337,22 @@ snapshots: dependencies: '@types/ms': 0.7.34 - '@types/eslint@9.6.1': - dependencies: - '@types/estree': 1.0.5 - '@types/json-schema': 7.0.15 - '@types/estree-jsx@1.0.5': dependencies: '@types/estree': 1.0.5 '@types/estree@1.0.5': {} + '@types/estree@1.0.6': {} + '@types/fs-extra@9.0.13': dependencies: - '@types/node': 22.5.5 + '@types/node': 22.7.4 '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 22.5.5 + '@types/node': 22.7.4 '@types/hast@3.0.4': dependencies: @@ -12236,7 +12364,7 @@ snapshots: '@types/keyv@3.1.4': dependencies: - '@types/node': 22.5.5 + '@types/node': 22.7.4 '@types/lodash-es@4.17.12': dependencies: @@ -12254,13 +12382,13 @@ snapshots: '@types/mysql@2.15.22': dependencies: - '@types/node': 22.5.5 + '@types/node': 22.7.4 - '@types/node@20.16.5': + '@types/node@20.16.10': dependencies: undici-types: 6.19.8 - '@types/node@22.5.5': + '@types/node@22.7.4': dependencies: undici-types: 6.19.8 @@ -12270,38 +12398,45 @@ snapshots: dependencies: '@types/pg': 8.11.8 + '@types/pg@8.11.10': + dependencies: + '@types/node': 22.7.4 + pg-protocol: 1.7.0 + pg-types: 4.0.2 + optional: true + '@types/pg@8.11.8': dependencies: - '@types/node': 22.5.5 + '@types/node': 22.7.4 pg-protocol: 1.6.1 pg-types: 4.0.2 '@types/pg@8.6.1': dependencies: - '@types/node': 22.5.5 + '@types/node': 22.7.4 pg-protocol: 1.6.1 pg-types: 2.2.0 '@types/plist@3.0.5': dependencies: - '@types/node': 22.5.5 + '@types/node': 22.7.4 xmlbuilder: 15.1.1 optional: true - '@types/prop-types@15.7.12': {} + '@types/prop-types@15.7.13': {} '@types/react-dom@18.3.0': dependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - '@types/react@18.3.8': + '@types/react@18.3.10': dependencies: - '@types/prop-types': 15.7.12 + '@types/prop-types': 15.7.13 csstype: 3.1.3 '@types/responselike@1.0.3': dependencies: - '@types/node': 22.5.5 + '@types/node': 22.7.4 '@types/semver@7.5.8': {} @@ -12309,7 +12444,7 @@ snapshots: '@types/tar@6.1.13': dependencies: - '@types/node': 22.5.5 + '@types/node': 22.7.4 minipass: 4.2.8 '@types/unist@2.0.11': {} @@ -12321,18 +12456,18 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.5.5 + '@types/node': 22.7.4 optional: true - '@typescript-eslint/eslint-plugin@8.6.0(@typescript-eslint/parser@8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2))(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2)': + '@typescript-eslint/eslint-plugin@8.7.0(@typescript-eslint/parser@8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2))(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2)': dependencies: - '@eslint-community/regexpp': 4.11.0 - '@typescript-eslint/parser': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/scope-manager': 8.6.0 - '@typescript-eslint/type-utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/visitor-keys': 8.6.0 - eslint: 9.11.0(jiti@1.21.6) + '@eslint-community/regexpp': 4.11.1 + '@typescript-eslint/parser': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.7.0 + '@typescript-eslint/type-utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/visitor-keys': 8.7.0 + eslint: 9.11.1(jiti@2.0.0) graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 @@ -12342,33 +12477,28 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2)': + '@typescript-eslint/parser@8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2)': dependencies: - '@typescript-eslint/scope-manager': 8.6.0 - '@typescript-eslint/types': 8.6.0 - '@typescript-eslint/typescript-estree': 8.6.0(typescript@5.6.2) - '@typescript-eslint/visitor-keys': 8.6.0 + '@typescript-eslint/scope-manager': 8.7.0 + '@typescript-eslint/types': 8.7.0 + '@typescript-eslint/typescript-estree': 8.7.0(typescript@5.6.2) + '@typescript-eslint/visitor-keys': 8.7.0 debug: 4.3.7 - eslint: 9.11.0(jiti@1.21.6) + eslint: 9.11.1(jiti@2.0.0) optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.4.0': + '@typescript-eslint/scope-manager@8.7.0': dependencies: - '@typescript-eslint/types': 8.4.0 - '@typescript-eslint/visitor-keys': 8.4.0 + '@typescript-eslint/types': 8.7.0 + '@typescript-eslint/visitor-keys': 8.7.0 - '@typescript-eslint/scope-manager@8.6.0': + '@typescript-eslint/type-utils@8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2)': dependencies: - '@typescript-eslint/types': 8.6.0 - '@typescript-eslint/visitor-keys': 8.6.0 - - '@typescript-eslint/type-utils@8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2)': - dependencies: - '@typescript-eslint/typescript-estree': 8.6.0(typescript@5.6.2) - '@typescript-eslint/utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) + '@typescript-eslint/typescript-estree': 8.7.0(typescript@5.6.2) + '@typescript-eslint/utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) debug: 4.3.7 ts-api-utils: 1.3.0(typescript@5.6.2) optionalDependencies: @@ -12377,14 +12507,12 @@ snapshots: - eslint - supports-color - '@typescript-eslint/types@8.4.0': {} + '@typescript-eslint/types@8.7.0': {} - '@typescript-eslint/types@8.6.0': {} - - '@typescript-eslint/typescript-estree@8.4.0(typescript@5.6.2)': + '@typescript-eslint/typescript-estree@8.7.0(typescript@5.6.2)': dependencies: - '@typescript-eslint/types': 8.4.0 - '@typescript-eslint/visitor-keys': 8.4.0 + '@typescript-eslint/types': 8.7.0 + '@typescript-eslint/visitor-keys': 8.7.0 debug: 4.3.7 fast-glob: 3.3.2 is-glob: 4.0.3 @@ -12396,77 +12524,46 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/typescript-estree@8.6.0(typescript@5.6.2)': + '@typescript-eslint/utils@8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2)': dependencies: - '@typescript-eslint/types': 8.6.0 - '@typescript-eslint/visitor-keys': 8.6.0 - debug: 4.3.7 - fast-glob: 3.3.2 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.6.3 - ts-api-utils: 1.3.0(typescript@5.6.2) - optionalDependencies: - typescript: 5.6.2 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/utils@8.4.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2)': - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.0(jiti@1.21.6)) - '@typescript-eslint/scope-manager': 8.4.0 - '@typescript-eslint/types': 8.4.0 - '@typescript-eslint/typescript-estree': 8.4.0(typescript@5.6.2) - eslint: 9.11.0(jiti@1.21.6) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.1(jiti@2.0.0)) + '@typescript-eslint/scope-manager': 8.7.0 + '@typescript-eslint/types': 8.7.0 + '@typescript-eslint/typescript-estree': 8.7.0(typescript@5.6.2) + eslint: 9.11.1(jiti@2.0.0) transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/utils@8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2)': + '@typescript-eslint/visitor-keys@8.7.0': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.0(jiti@1.21.6)) - '@typescript-eslint/scope-manager': 8.6.0 - '@typescript-eslint/types': 8.6.0 - '@typescript-eslint/typescript-estree': 8.6.0(typescript@5.6.2) - eslint: 9.11.0(jiti@1.21.6) - transitivePeerDependencies: - - supports-color - - typescript - - '@typescript-eslint/visitor-keys@8.4.0': - dependencies: - '@typescript-eslint/types': 8.4.0 - eslint-visitor-keys: 3.4.3 - - '@typescript-eslint/visitor-keys@8.6.0': - dependencies: - '@typescript-eslint/types': 8.6.0 + '@typescript-eslint/types': 8.7.0 eslint-visitor-keys: 3.4.3 '@ungap/structured-clone@1.2.0': {} - '@unocss/config@0.62.3': + '@unocss/config@0.62.4': dependencies: - '@unocss/core': 0.62.3 + '@unocss/core': 0.62.4 unconfig: 0.5.5 transitivePeerDependencies: - supports-color - '@unocss/core@0.62.3': {} + '@unocss/core@0.62.4': {} - '@unocss/eslint-config@0.62.3(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2)': + '@unocss/eslint-config@0.62.4(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2)': dependencies: - '@unocss/eslint-plugin': 0.62.3(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) + '@unocss/eslint-plugin': 0.62.4(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) transitivePeerDependencies: - eslint - supports-color - typescript - '@unocss/eslint-plugin@0.62.3(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2)': + '@unocss/eslint-plugin@0.62.4(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2)': dependencies: - '@typescript-eslint/utils': 8.4.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@unocss/config': 0.62.3 - '@unocss/core': 0.62.3 + '@typescript-eslint/utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@unocss/config': 0.62.4 + '@unocss/core': 0.62.4 magic-string: 0.30.11 synckit: 0.9.1 transitivePeerDependencies: @@ -12481,7 +12578,7 @@ snapshots: '@use-gesture/core': 10.3.1 react: 18.3.1 - '@vitejs/plugin-legacy@5.4.2(terser@5.32.0)(vite@5.4.7(@types/node@22.5.5)(terser@5.32.0))': + '@vitejs/plugin-legacy@5.4.2(terser@5.34.1)(vite@5.4.8(@types/node@22.7.4)(terser@5.34.1))': dependencies: '@babel/core': 7.25.2 '@babel/preset-env': 7.25.4(@babel/core@7.25.2) @@ -12491,19 +12588,19 @@ snapshots: magic-string: 0.30.11 regenerator-runtime: 0.14.1 systemjs: 6.15.1 - terser: 5.32.0 - vite: 5.4.7(@types/node@22.5.5)(terser@5.32.0) + terser: 5.34.1 + vite: 5.4.8(@types/node@22.7.4)(terser@5.34.1) transitivePeerDependencies: - supports-color - '@vitejs/plugin-react@4.3.1(vite@5.4.7(@types/node@22.5.5)(terser@5.32.0))': + '@vitejs/plugin-react@4.3.1(vite@5.4.8(@types/node@22.7.4)(terser@5.34.1))': dependencies: '@babel/core': 7.25.2 '@babel/plugin-transform-react-jsx-self': 7.24.7(@babel/core@7.25.2) '@babel/plugin-transform-react-jsx-source': 7.24.7(@babel/core@7.25.2) '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 5.4.7(@types/node@22.5.5)(terser@5.32.0) + vite: 5.4.8(@types/node@22.7.4)(terser@5.34.1) transitivePeerDependencies: - supports-color @@ -12535,7 +12632,7 @@ snapshots: '@vitest/spy@2.0.5': dependencies: - tinyspy: 3.0.0 + tinyspy: 3.0.2 '@vitest/utils@2.0.5': dependencies: @@ -12968,7 +13065,7 @@ snapshots: bufferutil@4.0.8: dependencies: - node-gyp-build: 4.8.1 + node-gyp-build: 4.8.2 optional: true builder-util-runtime@9.2.4: @@ -13228,9 +13325,9 @@ snapshots: slice-ansi: 5.0.0 string-width: 7.2.0 - click-to-react-component@1.1.0(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + click-to-react-component@1.1.0(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@floating-ui/react-dom-interactions': 0.3.1(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@floating-ui/react-dom-interactions': 0.3.1(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) htm: 3.1.1 react: 18.3.1 react-merge-refs: 1.1.0 @@ -13256,10 +13353,10 @@ snapshots: clsx@2.1.1: {} - cmdk@1.0.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + cmdk@1.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@radix-ui/react-dialog': 1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-dialog': 1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) transitivePeerDependencies: @@ -13717,7 +13814,7 @@ snapshots: verror: 1.10.1 optional: true - dnum@2.13.1: + dnum@2.14.0: dependencies: from-exponential: 1.1.1 @@ -13757,11 +13854,11 @@ snapshots: dotenv@9.0.2: {} - drizzle-orm@0.33.0(@opentelemetry/api@1.9.0)(@types/pg@8.11.8)(@types/react@18.3.8)(react@18.3.1): + drizzle-orm@0.33.0(@opentelemetry/api@1.9.0)(@types/pg@8.11.10)(@types/react@18.3.10)(react@18.3.1): optionalDependencies: '@opentelemetry/api': 1.9.0 - '@types/pg': 8.11.8 - '@types/react': 18.3.8 + '@types/pg': 8.11.10 + '@types/react': 18.3.10 react: 18.3.1 ds-store@0.1.6: @@ -13871,7 +13968,7 @@ snapshots: transitivePeerDependencies: - supports-color - electron-vite@2.3.0(vite@5.4.7(@types/node@22.5.5)(terser@5.32.0)): + electron-vite@2.3.0(vite@5.4.8(@types/node@22.7.4)(terser@5.34.1)): dependencies: '@babel/core': 7.25.2 '@babel/plugin-transform-arrow-functions': 7.24.7(@babel/core@7.25.2) @@ -13879,7 +13976,7 @@ snapshots: esbuild: 0.21.5 magic-string: 0.30.11 picocolors: 1.1.0 - vite: 5.4.7(@types/node@22.5.5)(terser@5.32.0) + vite: 5.4.8(@types/node@22.7.4)(terser@5.34.1) transitivePeerDependencies: - supports-color @@ -13899,7 +13996,7 @@ snapshots: electron@32.1.2: dependencies: '@electron/get': 2.0.3 - '@types/node': 20.16.5 + '@types/node': 20.16.10 extract-zip: 2.0.1 transitivePeerDependencies: - supports-color @@ -14023,46 +14120,45 @@ snapshots: escape-string-regexp@5.0.0: {} - eslint-compat-utils@0.5.1(eslint@9.11.0(jiti@1.21.6)): + eslint-compat-utils@0.5.1(eslint@9.11.1(jiti@2.0.0)): dependencies: - eslint: 9.11.0(jiti@1.21.6) + eslint: 9.11.1(jiti@2.0.0) semver: 7.6.3 - eslint-config-flat-gitignore@0.3.0(eslint@9.11.0(jiti@1.21.6)): + eslint-config-flat-gitignore@0.3.0(eslint@9.11.1(jiti@2.0.0)): dependencies: '@eslint/compat': 1.1.1 - eslint: 9.11.0(jiti@1.21.6) + eslint: 9.11.1(jiti@2.0.0) find-up-simple: 1.0.0 - eslint-config-hyoban@3.1.6(@typescript-eslint/eslint-plugin@8.6.0(@typescript-eslint/parser@8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2))(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2))(eslint@9.11.0(jiti@1.21.6))(tailwindcss@3.4.12)(typescript@5.6.2): + eslint-config-hyoban@3.1.7(@typescript-eslint/eslint-plugin@8.7.0(@typescript-eslint/parser@8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2))(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2))(eslint@9.11.1(jiti@2.0.0))(tailwindcss@3.4.13)(typescript@5.6.2): dependencies: - '@eslint-react/eslint-plugin': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint/js': 9.10.0 - '@stylistic/eslint-plugin': 2.8.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@types/eslint': 9.6.1 - '@unocss/eslint-config': 0.62.3(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) + '@eslint-react/eslint-plugin': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint/js': 9.11.1 + '@stylistic/eslint-plugin': 2.8.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@unocss/eslint-config': 0.62.4(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) defu: 6.1.4 - eslint: 9.11.0(jiti@1.21.6) - eslint-config-flat-gitignore: 0.3.0(eslint@9.11.0(jiti@1.21.6)) - eslint-plugin-antfu: 2.6.0(eslint@9.11.0(jiti@1.21.6)) - eslint-plugin-command: 0.2.5(eslint@9.11.0(jiti@1.21.6)) - eslint-plugin-hyoban: 0.6.1(eslint@9.11.0(jiti@1.21.6)) - eslint-plugin-import-x: 4.2.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - eslint-plugin-jsonc: 2.16.0(eslint@9.11.0(jiti@1.21.6)) - eslint-plugin-package-json: 0.15.3(eslint@9.11.0(jiti@1.21.6))(jsonc-eslint-parser@2.4.0) - eslint-plugin-react-compiler: 0.0.0-experimental-f8a5409-20240829(eslint@9.11.0(jiti@1.21.6)) - eslint-plugin-react-hooks: 5.1.0-rc-fb9a90fa48-20240614(eslint@9.11.0(jiti@1.21.6)) - eslint-plugin-react-refresh: 0.4.11(eslint@9.11.0(jiti@1.21.6)) - eslint-plugin-regexp: 2.6.0(eslint@9.11.0(jiti@1.21.6)) - eslint-plugin-simple-import-sort: 12.1.1(eslint@9.11.0(jiti@1.21.6)) - eslint-plugin-tailwindcss: 3.17.4(tailwindcss@3.4.12) - eslint-plugin-unicorn: 55.0.0(eslint@9.11.0(jiti@1.21.6)) - eslint-plugin-unused-imports: 4.1.4(@typescript-eslint/eslint-plugin@8.6.0(@typescript-eslint/parser@8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2))(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2))(eslint@9.11.0(jiti@1.21.6)) + eslint: 9.11.1(jiti@2.0.0) + eslint-config-flat-gitignore: 0.3.0(eslint@9.11.1(jiti@2.0.0)) + eslint-plugin-antfu: 2.7.0(eslint@9.11.1(jiti@2.0.0)) + eslint-plugin-command: 0.2.6(eslint@9.11.1(jiti@2.0.0)) + eslint-plugin-hyoban: 0.6.1(eslint@9.11.1(jiti@2.0.0)) + eslint-plugin-import-x: 4.3.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + eslint-plugin-jsonc: 2.16.0(eslint@9.11.1(jiti@2.0.0)) + eslint-plugin-package-json: 0.15.3(eslint@9.11.1(jiti@2.0.0))(jsonc-eslint-parser@2.4.0) + eslint-plugin-react-compiler: 0.0.0-experimental-f8a5409-20240829(eslint@9.11.1(jiti@2.0.0)) + eslint-plugin-react-hooks: 5.1.0-rc-fb9a90fa48-20240614(eslint@9.11.1(jiti@2.0.0)) + eslint-plugin-react-refresh: 0.4.12(eslint@9.11.1(jiti@2.0.0)) + eslint-plugin-regexp: 2.6.0(eslint@9.11.1(jiti@2.0.0)) + eslint-plugin-simple-import-sort: 12.1.1(eslint@9.11.1(jiti@2.0.0)) + eslint-plugin-tailwindcss: 3.17.4(tailwindcss@3.4.13) + eslint-plugin-unicorn: 55.0.0(eslint@9.11.1(jiti@2.0.0)) + eslint-plugin-unused-imports: 4.1.4(@typescript-eslint/eslint-plugin@8.7.0(@typescript-eslint/parser@8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2))(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2))(eslint@9.11.1(jiti@2.0.0)) globals: 15.9.0 jsonc-eslint-parser: 2.4.0 local-pkg: 0.5.0 read-package-up: 11.0.0 - typescript-eslint: 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) + typescript-eslint: 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: @@ -14078,28 +14174,28 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-antfu@2.6.0(eslint@9.11.0(jiti@1.21.6)): + eslint-plugin-antfu@2.7.0(eslint@9.11.1(jiti@2.0.0)): dependencies: '@antfu/utils': 0.7.10 - eslint: 9.11.0(jiti@1.21.6) + eslint: 9.11.1(jiti@2.0.0) - eslint-plugin-command@0.2.5(eslint@9.11.0(jiti@1.21.6)): + eslint-plugin-command@0.2.6(eslint@9.11.1(jiti@2.0.0)): dependencies: '@es-joy/jsdoccomment': 0.48.0 - eslint: 9.11.0(jiti@1.21.6) + eslint: 9.11.1(jiti@2.0.0) - eslint-plugin-hyoban@0.6.1(eslint@9.11.0(jiti@1.21.6)): + eslint-plugin-hyoban@0.6.1(eslint@9.11.1(jiti@2.0.0)): dependencies: - eslint: 9.11.0(jiti@1.21.6) + eslint: 9.11.1(jiti@2.0.0) - eslint-plugin-import-x@4.2.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2): + eslint-plugin-import-x@4.3.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2): dependencies: - '@typescript-eslint/utils': 8.4.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) + '@typescript-eslint/utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) debug: 4.3.7 doctrine: 3.0.0 - eslint: 9.11.0(jiti@1.21.6) + eslint: 9.11.1(jiti@2.0.0) eslint-import-resolver-node: 0.3.9 - get-tsconfig: 4.8.0 + get-tsconfig: 4.8.1 is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.6.3 @@ -14109,23 +14205,23 @@ snapshots: - supports-color - typescript - eslint-plugin-jsonc@2.16.0(eslint@9.11.0(jiti@1.21.6)): + eslint-plugin-jsonc@2.16.0(eslint@9.11.1(jiti@2.0.0)): dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.0(jiti@1.21.6)) - eslint: 9.11.0(jiti@1.21.6) - eslint-compat-utils: 0.5.1(eslint@9.11.0(jiti@1.21.6)) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.1(jiti@2.0.0)) + eslint: 9.11.1(jiti@2.0.0) + eslint-compat-utils: 0.5.1(eslint@9.11.1(jiti@2.0.0)) espree: 9.6.1 graphemer: 1.4.0 jsonc-eslint-parser: 2.4.0 natural-compare: 1.4.0 synckit: 0.6.2 - eslint-plugin-package-json@0.15.3(eslint@9.11.0(jiti@1.21.6))(jsonc-eslint-parser@2.4.0): + eslint-plugin-package-json@0.15.3(eslint@9.11.1(jiti@2.0.0))(jsonc-eslint-parser@2.4.0): dependencies: '@altano/repository-tools': 0.1.1 detect-indent: 6.1.0 detect-newline: 3.1.0 - eslint: 9.11.0(jiti@1.21.6) + eslint: 9.11.1(jiti@2.0.0) jsonc-eslint-parser: 2.4.0 package-json-validator: 0.6.5 semver: 7.6.3 @@ -14133,175 +14229,175 @@ snapshots: sort-package-json: 1.57.0 validate-npm-package-name: 5.0.1 - eslint-plugin-react-compiler@0.0.0-experimental-f8a5409-20240829(eslint@9.11.0(jiti@1.21.6)): + eslint-plugin-react-compiler@0.0.0-experimental-f8a5409-20240829(eslint@9.11.1(jiti@2.0.0)): dependencies: '@babel/core': 7.25.2 '@babel/parser': 7.25.6 '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.25.2) - eslint: 9.11.0(jiti@1.21.6) + eslint: 9.11.1(jiti@2.0.0) hermes-parser: 0.20.1 zod: 3.23.8 - zod-validation-error: 3.3.1(zod@3.23.8) + zod-validation-error: 3.4.0(zod@3.23.8) transitivePeerDependencies: - supports-color - eslint-plugin-react-debug@1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2): + eslint-plugin-react-debug@1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2): dependencies: - '@eslint-react/ast': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/core': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/jsx': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/shared': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/tools': 1.14.1 - '@eslint-react/types': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/var': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/scope-manager': 8.6.0 - '@typescript-eslint/type-utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/types': 8.6.0 - '@typescript-eslint/utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - eslint: 9.11.0(jiti@1.21.6) + '@eslint-react/ast': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/core': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/jsx': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/shared': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/tools': 1.14.2 + '@eslint-react/types': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/var': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.7.0 + '@typescript-eslint/type-utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/types': 8.7.0 + '@typescript-eslint/utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + eslint: 9.11.1(jiti@2.0.0) string-ts: 2.2.0 - ts-pattern: 5.3.1 + ts-pattern: 5.4.0 optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: - supports-color - eslint-plugin-react-dom@1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2): + eslint-plugin-react-dom@1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2): dependencies: - '@eslint-react/ast': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/core': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/jsx': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/shared': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/tools': 1.14.1 - '@eslint-react/types': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/var': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/scope-manager': 8.6.0 - '@typescript-eslint/types': 8.6.0 - '@typescript-eslint/utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - eslint: 9.11.0(jiti@1.21.6) - ts-pattern: 5.3.1 + '@eslint-react/ast': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/core': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/jsx': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/shared': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/tools': 1.14.2 + '@eslint-react/types': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/var': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.7.0 + '@typescript-eslint/types': 8.7.0 + '@typescript-eslint/utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + eslint: 9.11.1(jiti@2.0.0) + ts-pattern: 5.4.0 optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: - supports-color - eslint-plugin-react-hooks-extra@1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2): + eslint-plugin-react-hooks-extra@1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2): dependencies: - '@eslint-react/ast': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/core': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/jsx': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/shared': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/tools': 1.14.1 - '@eslint-react/types': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/var': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/scope-manager': 8.6.0 - '@typescript-eslint/type-utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/types': 8.6.0 - '@typescript-eslint/utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - eslint: 9.11.0(jiti@1.21.6) - ts-pattern: 5.3.1 + '@eslint-react/ast': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/core': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/jsx': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/shared': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/tools': 1.14.2 + '@eslint-react/types': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/var': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.7.0 + '@typescript-eslint/type-utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/types': 8.7.0 + '@typescript-eslint/utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + eslint: 9.11.1(jiti@2.0.0) + ts-pattern: 5.4.0 optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: - supports-color - eslint-plugin-react-hooks@5.1.0-rc-fb9a90fa48-20240614(eslint@9.11.0(jiti@1.21.6)): + eslint-plugin-react-hooks@5.1.0-rc-fb9a90fa48-20240614(eslint@9.11.1(jiti@2.0.0)): dependencies: - eslint: 9.11.0(jiti@1.21.6) + eslint: 9.11.1(jiti@2.0.0) - eslint-plugin-react-naming-convention@1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2): + eslint-plugin-react-naming-convention@1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2): dependencies: - '@eslint-react/ast': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/core': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/jsx': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/shared': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/tools': 1.14.1 - '@eslint-react/types': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/scope-manager': 8.6.0 - '@typescript-eslint/type-utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/types': 8.6.0 - '@typescript-eslint/utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - eslint: 9.11.0(jiti@1.21.6) - ts-pattern: 5.3.1 + '@eslint-react/ast': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/core': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/jsx': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/shared': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/tools': 1.14.2 + '@eslint-react/types': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.7.0 + '@typescript-eslint/type-utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/types': 8.7.0 + '@typescript-eslint/utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + eslint: 9.11.1(jiti@2.0.0) + ts-pattern: 5.4.0 optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: - supports-color - eslint-plugin-react-refresh@0.4.11(eslint@9.11.0(jiti@1.21.6)): + eslint-plugin-react-refresh@0.4.12(eslint@9.11.1(jiti@2.0.0)): dependencies: - eslint: 9.11.0(jiti@1.21.6) + eslint: 9.11.1(jiti@2.0.0) - eslint-plugin-react-web-api@1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2): + eslint-plugin-react-web-api@1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2): dependencies: - '@eslint-react/ast': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/core': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/jsx': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/shared': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/tools': 1.14.1 - '@eslint-react/types': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/var': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/scope-manager': 8.6.0 - '@typescript-eslint/types': 8.6.0 - '@typescript-eslint/utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) + '@eslint-react/ast': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/core': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/jsx': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/shared': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/tools': 1.14.2 + '@eslint-react/types': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/var': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.7.0 + '@typescript-eslint/types': 8.7.0 + '@typescript-eslint/utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) birecord: 0.1.1 - eslint: 9.11.0(jiti@1.21.6) - ts-pattern: 5.3.1 + eslint: 9.11.1(jiti@2.0.0) + ts-pattern: 5.4.0 optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: - supports-color - eslint-plugin-react-x@1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2): + eslint-plugin-react-x@1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2): dependencies: - '@eslint-react/ast': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/core': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/jsx': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/shared': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/tools': 1.14.1 - '@eslint-react/types': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@eslint-react/var': 1.14.1(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/scope-manager': 8.6.0 - '@typescript-eslint/type-utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/types': 8.6.0 - '@typescript-eslint/utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - eslint: 9.11.0(jiti@1.21.6) - is-immutable-type: 5.0.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - ts-pattern: 5.3.1 + '@eslint-react/ast': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/core': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/jsx': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/shared': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/tools': 1.14.2 + '@eslint-react/types': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@eslint-react/var': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.7.0 + '@typescript-eslint/type-utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/types': 8.7.0 + '@typescript-eslint/utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + eslint: 9.11.1(jiti@2.0.0) + is-immutable-type: 5.0.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + ts-pattern: 5.4.0 optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: - supports-color - eslint-plugin-regexp@2.6.0(eslint@9.11.0(jiti@1.21.6)): + eslint-plugin-regexp@2.6.0(eslint@9.11.1(jiti@2.0.0)): dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.0(jiti@1.21.6)) - '@eslint-community/regexpp': 4.11.0 + '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.1(jiti@2.0.0)) + '@eslint-community/regexpp': 4.11.1 comment-parser: 1.4.1 - eslint: 9.11.0(jiti@1.21.6) + eslint: 9.11.1(jiti@2.0.0) jsdoc-type-pratt-parser: 4.1.0 refa: 0.12.1 regexp-ast-analysis: 0.7.1 scslre: 0.3.0 - eslint-plugin-simple-import-sort@12.1.1(eslint@9.11.0(jiti@1.21.6)): + eslint-plugin-simple-import-sort@12.1.1(eslint@9.11.1(jiti@2.0.0)): dependencies: - eslint: 9.11.0(jiti@1.21.6) + eslint: 9.11.1(jiti@2.0.0) - eslint-plugin-tailwindcss@3.17.4(tailwindcss@3.4.12): + eslint-plugin-tailwindcss@3.17.4(tailwindcss@3.4.13): dependencies: fast-glob: 3.3.2 postcss: 8.4.47 - tailwindcss: 3.4.12 + tailwindcss: 3.4.13 - eslint-plugin-unicorn@55.0.0(eslint@9.11.0(jiti@1.21.6)): + eslint-plugin-unicorn@55.0.0(eslint@9.11.1(jiti@2.0.0)): dependencies: '@babel/helper-validator-identifier': 7.24.7 - '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.0(jiti@1.21.6)) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.1(jiti@2.0.0)) ci-info: 4.0.0 clean-regexp: 1.0.0 core-js-compat: 3.38.1 - eslint: 9.11.0(jiti@1.21.6) + eslint: 9.11.1(jiti@2.0.0) esquery: 1.6.0 globals: 15.9.0 indent-string: 4.0.0 @@ -14314,40 +14410,43 @@ snapshots: semver: 7.6.3 strip-indent: 3.0.0 - eslint-plugin-unused-imports@4.1.4(@typescript-eslint/eslint-plugin@8.6.0(@typescript-eslint/parser@8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2))(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2))(eslint@9.11.0(jiti@1.21.6)): + eslint-plugin-unused-imports@4.1.4(@typescript-eslint/eslint-plugin@8.7.0(@typescript-eslint/parser@8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2))(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2))(eslint@9.11.1(jiti@2.0.0)): dependencies: - eslint: 9.11.0(jiti@1.21.6) + eslint: 9.11.1(jiti@2.0.0) optionalDependencies: - '@typescript-eslint/eslint-plugin': 8.6.0(@typescript-eslint/parser@8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2))(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) + '@typescript-eslint/eslint-plugin': 8.7.0(@typescript-eslint/parser@8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2))(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) - eslint-scope@8.0.2: + eslint-scope@8.1.0: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 eslint-visitor-keys@3.4.3: {} - eslint-visitor-keys@4.0.0: {} + eslint-visitor-keys@4.1.0: {} - eslint@9.11.0(jiti@1.21.6): + eslint@9.11.1(jiti@2.0.0): dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.0(jiti@1.21.6)) - '@eslint-community/regexpp': 4.11.0 + '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.1(jiti@2.0.0)) + '@eslint-community/regexpp': 4.11.1 '@eslint/config-array': 0.18.0 + '@eslint/core': 0.6.0 '@eslint/eslintrc': 3.1.0 - '@eslint/js': 9.11.0 + '@eslint/js': 9.11.1 '@eslint/plugin-kit': 0.2.0 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.3.0 '@nodelib/fs.walk': 1.2.8 + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 debug: 4.3.7 escape-string-regexp: 4.0.0 - eslint-scope: 8.0.2 - eslint-visitor-keys: 4.0.0 - espree: 10.1.0 + eslint-scope: 8.1.0 + eslint-visitor-keys: 4.1.0 + espree: 10.2.0 esquery: 1.6.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 @@ -14366,15 +14465,15 @@ snapshots: strip-ansi: 6.0.1 text-table: 0.2.0 optionalDependencies: - jiti: 1.21.6 + jiti: 2.0.0 transitivePeerDependencies: - supports-color - espree@10.1.0: + espree@10.2.0: dependencies: acorn: 8.12.1 acorn-jsx: 5.3.2(acorn@8.12.1) - eslint-visitor-keys: 4.0.0 + eslint-visitor-keys: 4.1.0 espree@9.6.1: dependencies: @@ -14396,7 +14495,7 @@ snapshots: estree-walker@3.0.3: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 esutils@2.0.3: {} @@ -14580,11 +14679,11 @@ snapshots: optionalDependencies: react: 18.3.1 - framer-motion@11.5.6(@emotion/is-prop-valid@0.8.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + framer-motion@11.9.0(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: tslib: 2.7.0 optionalDependencies: - '@emotion/is-prop-valid': 0.8.8 + '@emotion/is-prop-valid': 1.3.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -14734,6 +14833,10 @@ snapshots: dependencies: resolve-pkg-maps: 1.0.0 + get-tsconfig@4.8.1: + dependencies: + resolve-pkg-maps: 1.0.0 + giget@1.2.3: dependencies: citty: 0.1.6 @@ -14937,7 +15040,7 @@ snapshots: '@types/hast': 3.0.4 hast-util-truncate: 2.0.0 - hast-util-from-html@2.0.1: + hast-util-from-html@2.0.3: dependencies: '@types/hast': 3.0.4 devlop: 1.1.0 @@ -14994,20 +15097,6 @@ snapshots: unist-util-visit: 5.0.0 zwitch: 2.0.4 - hast-util-to-html@9.0.2: - dependencies: - '@types/hast': 3.0.4 - '@types/unist': 3.0.3 - ccount: 2.0.1 - comma-separated-tokens: 2.0.3 - hast-util-whitespace: 3.0.0 - html-void-elements: 3.0.0 - mdast-util-to-hast: 13.2.0 - property-information: 6.5.0 - space-separated-tokens: 2.0.2 - stringify-entities: 4.0.4 - zwitch: 2.0.4 - hast-util-to-html@9.0.3: dependencies: '@types/hast': 3.0.4 @@ -15099,7 +15188,7 @@ snapshots: dependencies: parse-passwd: 1.0.0 - hono@4.6.2(patch_hash=iej2g43ojhll5opwbnvyorjq4e): {} + hono@4.6.3(patch_hash=iej2g43ojhll5opwbnvyorjq4e): {} hosted-git-info@2.8.9: {} @@ -15297,10 +15386,10 @@ snapshots: is-hexadecimal@2.0.1: {} - is-immutable-type@5.0.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2): + is-immutable-type@5.0.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2): dependencies: - '@typescript-eslint/type-utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - eslint: 9.11.0(jiti@1.21.6) + '@typescript-eslint/type-utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + eslint: 9.11.1(jiti@2.0.0) ts-api-utils: 1.3.0(typescript@5.6.2) ts-declaration-location: 1.0.4(typescript@5.6.2) typescript: 5.6.2 @@ -15381,13 +15470,16 @@ snapshots: jiti@1.21.6: {} + jiti@2.0.0: + optional: true + jiti@2.0.0-beta.3: {} - jose@5.8.0: {} + jose@5.9.3: {} - jotai@2.10.0(@types/react@18.3.8)(react@18.3.1): + jotai@2.10.0(@types/react@18.3.10)(react@18.3.1): optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 react: 18.3.1 joycon@3.1.1: {} @@ -16277,7 +16369,7 @@ snapshots: optionalDependencies: encoding: 0.1.13 - node-gyp-build@4.8.1: + node-gyp-build@4.8.2: optional: true node-gyp@9.4.1: @@ -16354,7 +16446,7 @@ snapshots: pkg-types: 1.2.0 ufo: 1.5.4 - oauth4webapi@2.12.1: {} + oauth4webapi@2.17.0: {} object-assign@4.1.1: {} @@ -16573,7 +16665,7 @@ snapshots: lru-cache: 11.0.0 minipass: 7.1.2 - path-to-regexp@8.1.0: {} + path-to-regexp@8.2.0: {} path-type@2.0.0: dependencies: @@ -16607,6 +16699,9 @@ snapshots: pg-protocol@1.6.1: {} + pg-protocol@1.7.0: + optional: true + pg-types@2.2.0: dependencies: pg-int8: 1.0.1 @@ -16713,11 +16808,11 @@ snapshots: optionalDependencies: postcss: 8.4.47 - postcss-load-config@6.0.1(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1)(yaml@2.5.1): + postcss-load-config@6.0.1(jiti@2.0.0)(postcss@8.4.47)(tsx@4.19.1)(yaml@2.5.1): dependencies: lilconfig: 3.1.2 optionalDependencies: - jiti: 1.21.6 + jiti: 2.0.0 postcss: 8.4.47 tsx: 4.19.1 yaml: 2.5.1 @@ -16879,10 +16974,10 @@ snapshots: postgres-range@1.1.4: {} - posthog-js@1.163.0: + posthog-js@1.165.0: dependencies: fflate: 0.4.8 - preact: 10.23.2 + preact: 10.24.1 web-vitals: 4.2.3 posthog-node@4.2.0: @@ -16903,7 +16998,7 @@ snapshots: preact@10.11.3: {} - preact@10.23.2: {} + preact@10.24.1: {} prelude-ls@1.2.1: {} @@ -16980,7 +17075,7 @@ snapshots: defu: 6.1.4 destr: 2.0.3 - re-resizable@6.9.18(patch_hash=yitcmpfwcomg2fky72uc3lhk2i)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + re-resizable@6.10.0(patch_hash=yitcmpfwcomg2fky72uc3lhk2i)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -17036,35 +17131,35 @@ snapshots: react-refresh@0.14.2: {} - react-remove-scroll-bar@2.3.6(@types/react@18.3.8)(react@18.3.1): + react-remove-scroll-bar@2.3.6(@types/react@18.3.10)(react@18.3.1): dependencies: react: 18.3.1 - react-style-singleton: 2.2.1(@types/react@18.3.8)(react@18.3.1) + react-style-singleton: 2.2.1(@types/react@18.3.10)(react@18.3.1) tslib: 2.7.0 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - react-remove-scroll@2.5.5(@types/react@18.3.8)(react@18.3.1): + react-remove-scroll@2.5.5(@types/react@18.3.10)(react@18.3.1): dependencies: react: 18.3.1 - react-remove-scroll-bar: 2.3.6(@types/react@18.3.8)(react@18.3.1) - react-style-singleton: 2.2.1(@types/react@18.3.8)(react@18.3.1) + react-remove-scroll-bar: 2.3.6(@types/react@18.3.10)(react@18.3.1) + react-style-singleton: 2.2.1(@types/react@18.3.10)(react@18.3.1) tslib: 2.7.0 - use-callback-ref: 1.3.2(@types/react@18.3.8)(react@18.3.1) - use-sidecar: 1.1.2(@types/react@18.3.8)(react@18.3.1) + use-callback-ref: 1.3.2(@types/react@18.3.10)(react@18.3.1) + use-sidecar: 1.1.2(@types/react@18.3.10)(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - react-remove-scroll@2.5.7(@types/react@18.3.8)(react@18.3.1): + react-remove-scroll@2.5.7(@types/react@18.3.10)(react@18.3.1): dependencies: react: 18.3.1 - react-remove-scroll-bar: 2.3.6(@types/react@18.3.8)(react@18.3.1) - react-style-singleton: 2.2.1(@types/react@18.3.8)(react@18.3.1) + react-remove-scroll-bar: 2.3.6(@types/react@18.3.10)(react@18.3.1) + react-style-singleton: 2.2.1(@types/react@18.3.10)(react@18.3.1) tslib: 2.7.0 - use-callback-ref: 1.3.2(@types/react@18.3.8)(react@18.3.1) - use-sidecar: 1.1.2(@types/react@18.3.8)(react@18.3.1) + use-callback-ref: 1.3.2(@types/react@18.3.10)(react@18.3.1) + use-sidecar: 1.1.2(@types/react@18.3.10)(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 react-router-dom@6.26.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: @@ -17089,14 +17184,14 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-style-singleton@2.2.1(@types/react@18.3.8)(react@18.3.1): + react-style-singleton@2.2.1(@types/react@18.3.10)(react@18.3.1): dependencies: get-nonce: 1.0.1 invariant: 2.2.4 react: 18.3.1 tslib: 2.7.0 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 react-virtuoso@4.10.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: @@ -17207,7 +17302,7 @@ snapshots: refa@0.12.1: dependencies: - '@eslint-community/regexpp': 4.11.0 + '@eslint-community/regexpp': 4.11.1 regenerate-unicode-properties@10.1.1: dependencies: @@ -17225,7 +17320,7 @@ snapshots: regexp-ast-analysis@0.7.1: dependencies: - '@eslint-community/regexpp': 4.11.0 + '@eslint-community/regexpp': 4.11.1 refa: 0.12.1 regexp-tree@0.1.27: {} @@ -17258,10 +17353,10 @@ snapshots: unist-util-remove-position: 5.0.0 vfile: 6.0.3 - rehype-parse@9.0.0: + rehype-parse@9.0.1: dependencies: '@types/hast': 3.0.4 - hast-util-from-html: 2.0.1 + hast-util-from-html: 2.0.3 unified: 11.0.5 rehype-sanitize@6.0.0: @@ -17269,10 +17364,10 @@ snapshots: '@types/hast': 3.0.4 hast-util-sanitize: 5.0.1 - rehype-stringify@10.0.0: + rehype-stringify@10.0.1: dependencies: '@types/hast': 3.0.4 - hast-util-to-html: 9.0.2 + hast-util-to-html: 9.0.3 unified: 11.0.5 remark-directive@3.0.0: @@ -17448,6 +17543,28 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.21.2 fsevents: 2.3.3 + rollup@4.22.5: + dependencies: + '@types/estree': 1.0.6 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.22.5 + '@rollup/rollup-android-arm64': 4.22.5 + '@rollup/rollup-darwin-arm64': 4.22.5 + '@rollup/rollup-darwin-x64': 4.22.5 + '@rollup/rollup-linux-arm-gnueabihf': 4.22.5 + '@rollup/rollup-linux-arm-musleabihf': 4.22.5 + '@rollup/rollup-linux-arm64-gnu': 4.22.5 + '@rollup/rollup-linux-arm64-musl': 4.22.5 + '@rollup/rollup-linux-powerpc64le-gnu': 4.22.5 + '@rollup/rollup-linux-riscv64-gnu': 4.22.5 + '@rollup/rollup-linux-s390x-gnu': 4.22.5 + '@rollup/rollup-linux-x64-gnu': 4.22.5 + '@rollup/rollup-linux-x64-musl': 4.22.5 + '@rollup/rollup-win32-arm64-msvc': 4.22.5 + '@rollup/rollup-win32-ia32-msvc': 4.22.5 + '@rollup/rollup-win32-x64-msvc': 4.22.5 + fsevents: 2.3.3 + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -17472,7 +17589,7 @@ snapshots: scslre@0.3.0: dependencies: - '@eslint-community/regexpp': 4.11.0 + '@eslint-community/regexpp': 4.11.1 refa: 0.12.1 regexp-ast-analysis: 0.7.1 @@ -17532,12 +17649,12 @@ snapshots: interpret: 1.4.0 rechoir: 0.6.2 - shiki@1.18.0: + shiki@1.20.0: dependencies: - '@shikijs/core': 1.18.0 - '@shikijs/engine-javascript': 1.18.0 - '@shikijs/engine-oniguruma': 1.18.0 - '@shikijs/types': 1.18.0 + '@shikijs/core': 1.20.0 + '@shikijs/engine-javascript': 1.20.0 + '@shikijs/engine-oniguruma': 1.20.0 + '@shikijs/types': 1.20.0 '@shikijs/vscode-textmate': 9.2.2 '@types/hast': 3.0.4 @@ -17799,11 +17916,11 @@ snapshots: tailwind-merge@2.5.2: {} - tailwindcss-animate@1.0.7(tailwindcss@3.4.12): + tailwindcss-animate@1.0.7(tailwindcss@3.4.13): dependencies: - tailwindcss: 3.4.12 + tailwindcss: 3.4.13 - tailwindcss@3.4.12: + tailwindcss@3.4.13: dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -17858,7 +17975,7 @@ snapshots: rimraf: 2.6.3 optional: true - terser@5.32.0: + terser@5.34.1: dependencies: '@jridgewell/source-map': 0.3.6 acorn: 8.12.1 @@ -17890,13 +18007,13 @@ snapshots: tinyrainbow@1.2.0: {} - tinyspy@3.0.0: {} + tinyspy@3.0.2: {} - tldts-core@6.1.47: {} + tldts-core@6.1.48: {} - tldts@6.1.47: + tldts@6.1.48: dependencies: - tldts-core: 6.1.47 + tldts-core: 6.1.48 tmp-promise@3.0.3: dependencies: @@ -17956,7 +18073,7 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-pattern@5.3.1: {} + ts-pattern@5.4.0: {} tsconfck@3.1.1(typescript@5.6.2): optionalDependencies: @@ -17964,7 +18081,7 @@ snapshots: tslib@2.7.0: {} - tsup@8.3.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1)(typescript@5.6.2)(yaml@2.5.1): + tsup@8.3.0(jiti@2.0.0)(postcss@8.4.47)(tsx@4.19.1)(typescript@5.6.2)(yaml@2.5.1): dependencies: bundle-require: 5.0.0(esbuild@0.23.1) cac: 6.7.14 @@ -17975,7 +18092,7 @@ snapshots: execa: 5.1.1 joycon: 3.1.1 picocolors: 1.1.0 - postcss-load-config: 6.0.1(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1)(yaml@2.5.1) + postcss-load-config: 6.0.1(jiti@2.0.0)(postcss@8.4.47)(tsx@4.19.1)(yaml@2.5.1) resolve-from: 5.0.0 rollup: 4.21.2 source-map: 0.8.0-beta.0 @@ -18013,11 +18130,11 @@ snapshots: type-fest@4.26.1: {} - typescript-eslint@8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2): + typescript-eslint@8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2): dependencies: - '@typescript-eslint/eslint-plugin': 8.6.0(@typescript-eslint/parser@8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2))(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/parser': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) - '@typescript-eslint/utils': 8.6.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.2) + '@typescript-eslint/eslint-plugin': 8.7.0(@typescript-eslint/parser@8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2))(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/parser': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/utils': 8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: @@ -18146,31 +18263,31 @@ snapshots: dependencies: punycode: 2.3.1 - use-callback-ref@1.3.2(@types/react@18.3.8)(react@18.3.1): + use-callback-ref@1.3.2(@types/react@18.3.10)(react@18.3.1): dependencies: react: 18.3.1 tslib: 2.7.0 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 use-context-selector@2.0.0(react@18.3.1)(scheduler@0.23.2): dependencies: react: 18.3.1 scheduler: 0.23.2 - use-isomorphic-layout-effect@1.1.2(@types/react@18.3.8)(react@18.3.1): + use-isomorphic-layout-effect@1.1.2(@types/react@18.3.10)(react@18.3.1): dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 - use-sidecar@1.1.2(@types/react@18.3.8)(react@18.3.1): + use-sidecar@1.1.2(@types/react@18.3.10)(react@18.3.1): dependencies: detect-node-es: 1.1.0 react: 18.3.1 tslib: 2.7.0 optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 use-sync-external-store@1.2.2(react@18.3.1): dependencies: @@ -18188,7 +18305,7 @@ snapshots: utf-8-validate@6.0.4: dependencies: - node-gyp-build: 4.8.1 + node-gyp-build: 4.8.2 optional: true utf8-byte-length@1.0.5: {} @@ -18224,15 +18341,15 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 - vite-bundle-analyzer@0.10.6: {} + vite-bundle-analyzer@0.12.1: {} - vite-node@2.0.5(@types/node@22.5.5)(terser@5.32.0): + vite-node@2.0.5(@types/node@22.7.4)(terser@5.34.1): dependencies: cac: 6.7.14 debug: 4.3.7 pathe: 1.1.2 tinyrainbow: 1.2.0 - vite: 5.4.7(@types/node@22.5.5)(terser@5.32.0) + vite: 5.4.8(@types/node@22.7.4)(terser@5.34.1) transitivePeerDependencies: - '@types/node' - less @@ -18244,38 +18361,38 @@ snapshots: - supports-color - terser - vite-plugin-mkcert@1.17.6(vite@5.4.7(@types/node@22.5.5)(terser@5.32.0)): + vite-plugin-mkcert@1.17.6(vite@5.4.8(@types/node@22.7.4)(terser@5.34.1)): dependencies: '@octokit/rest': 20.1.1 axios: 1.7.7(debug@4.3.7) debug: 4.3.7 picocolors: 1.1.0 - vite: 5.4.7(@types/node@22.5.5)(terser@5.32.0) + vite: 5.4.8(@types/node@22.7.4)(terser@5.34.1) transitivePeerDependencies: - supports-color - vite-tsconfig-paths@5.0.1(typescript@5.6.2)(vite@5.4.7(@types/node@22.5.5)(terser@5.32.0)): + vite-tsconfig-paths@5.0.1(typescript@5.6.2)(vite@5.4.8(@types/node@22.7.4)(terser@5.34.1)): dependencies: debug: 4.3.7 globrex: 0.1.2 tsconfck: 3.1.1(typescript@5.6.2) optionalDependencies: - vite: 5.4.7(@types/node@22.5.5)(terser@5.32.0) + vite: 5.4.8(@types/node@22.7.4)(terser@5.34.1) transitivePeerDependencies: - supports-color - typescript - vite@5.4.7(@types/node@22.5.5)(terser@5.32.0): + vite@5.4.8(@types/node@22.7.4)(terser@5.34.1): dependencies: esbuild: 0.21.5 postcss: 8.4.47 - rollup: 4.21.2 + rollup: 4.22.5 optionalDependencies: - '@types/node': 22.5.5 + '@types/node': 22.7.4 fsevents: 2.3.3 - terser: 5.32.0 + terser: 5.34.1 - vitest@2.0.5(@types/node@22.5.5)(terser@5.32.0): + vitest@2.0.5(@types/node@22.7.4)(terser@5.34.1): dependencies: '@ampproject/remapping': 2.3.0 '@vitest/expect': 2.0.5 @@ -18293,11 +18410,11 @@ snapshots: tinybench: 2.9.0 tinypool: 1.0.1 tinyrainbow: 1.2.0 - vite: 5.4.7(@types/node@22.5.5)(terser@5.32.0) - vite-node: 2.0.5(@types/node@22.5.5)(terser@5.32.0) + vite: 5.4.8(@types/node@22.7.4)(terser@5.34.1) + vite-node: 2.0.5(@types/node@22.7.4)(terser@5.34.1) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 22.5.5 + '@types/node': 22.7.4 transitivePeerDependencies: - less - lightningcss @@ -18435,17 +18552,17 @@ snapshots: compress-commons: 4.1.2 readable-stream: 3.6.2 - zod-validation-error@3.3.1(zod@3.23.8): + zod-validation-error@3.4.0(zod@3.23.8): dependencies: zod: 3.23.8 zod@3.23.8: {} - zustand@4.5.5(@types/react@18.3.8)(immer@10.1.1(patch_hash=og7mbnoo5vh43tjlw5rbmrdbvu))(react@18.3.1): + zustand@4.5.5(@types/react@18.3.10)(immer@10.1.1(patch_hash=og7mbnoo5vh43tjlw5rbmrdbvu))(react@18.3.1): dependencies: use-sync-external-store: 1.2.2(react@18.3.1) optionalDependencies: - '@types/react': 18.3.8 + '@types/react': 18.3.10 immer: 10.1.1(patch_hash=og7mbnoo5vh43tjlw5rbmrdbvu) react: 18.3.1 From 60f1af2409300e64ad351621abf71ed326188af8 Mon Sep 17 00:00:00 2001 From: Innei Date: Sat, 28 Sep 2024 14:00:53 +0800 Subject: [PATCH 08/88] fix(i18n-selector): hover cls --- apps/renderer/src/modules/settings/tabs/general.tsx | 6 ++++-- locales/errors/en.json | 12 +++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/apps/renderer/src/modules/settings/tabs/general.tsx b/apps/renderer/src/modules/settings/tabs/general.tsx index f0506e48b..38be254b9 100644 --- a/apps/renderer/src/modules/settings/tabs/general.tsx +++ b/apps/renderer/src/modules/settings/tabs/general.tsx @@ -245,13 +245,15 @@ export const LanguageSelector = () => { const originalLanguageName = defaultResources[lang].lang.name return ( - + {languageName} {typeof percent === "number" ? (percent >= 100 ? null : ` (${percent}%)`) : null} {originalLanguageName !== languageName && ( {originalLanguageName} diff --git a/locales/errors/en.json b/locales/errors/en.json index 1f8f017fc..40fef6b1e 100644 --- a/locales/errors/en.json +++ b/locales/errors/en.json @@ -1,4 +1,5 @@ { + "1": "Previous operation is not completed", "1000": "Unauthorized", "1001": "create session failed", "1002": "Invalid parameter", @@ -11,7 +12,6 @@ "2010": "Ownership challenge failed", "2011": "Subscription limit exceeded", "3000": "Entry not found", - "3001": "Entry not belong to user", "4000": "Already claimed", "4001": "User wallet error", "4002": "Insufficient balance", @@ -25,5 +25,11 @@ "7000": "Setting not found", "7001": "Invalid setting tab", "7002": "Invalid setting payload", - "7003": "Setting payload too large" -} + "7003": "Setting payload too large", + "8000": "List not found", + "8001": "List permission denied", + "8002": "List limit exceeded", + "8003": "Feed already added to list", + "9000": "Achievement not completed", + "9001": "Achievement already received" +} \ No newline at end of file From 65bfe8f13c969bc124fafc8841ae09247d9ddc05 Mon Sep 17 00:00:00 2001 From: Innei Date: Sat, 28 Sep 2024 14:10:36 +0800 Subject: [PATCH 09/88] chore: add eslint plugin for i18n check --- eslint.config.mjs | 2 ++ locales/errors/de.json | 1 - locales/errors/en.json | 2 +- locales/errors/fr.json | 1 - locales/errors/ja.json | 1 - locales/errors/ko.json | 1 - locales/errors/ru.json | 1 - locales/errors/tr.json | 1 - locales/errors/zh-CN.json | 1 - locales/errors/zh-HK.json | 1 - locales/errors/zh-TW.json | 1 - plugins/eslint-check-i18n-json.js | 55 +++++++++++++++++++++++++++++++ 12 files changed, 58 insertions(+), 10 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 36d901c74..1fa926d36 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -51,6 +51,7 @@ export default defineConfig( "@stylistic/jsx-self-closing-comp": "error", }, }, + // @ts-expect-error { files: ["locales/**/*.json"], plugins: { @@ -60,6 +61,7 @@ export default defineConfig( rules: { "recursive-sort/recursive-sort": "error", "check-i18n-json/valid-i18n-keys": "error", + "check-i18n-json/no-extra-keys": "error", }, }, ) diff --git a/locales/errors/de.json b/locales/errors/de.json index 503ff9847..6fdb0a64d 100644 --- a/locales/errors/de.json +++ b/locales/errors/de.json @@ -11,7 +11,6 @@ "2010": "Besitznachweis fehlgeschlagen", "2011": "Abonnementlimit überschritten", "3000": "Eintrag nicht gefunden", - "3001": "Eintrag gehört nicht zum Benutzer", "4000": "Bereits beansprucht", "4001": "Fehler in der Benutzer-Wallet", "4002": "Unzureichendes Guthaben", diff --git a/locales/errors/en.json b/locales/errors/en.json index 40fef6b1e..b27719fb8 100644 --- a/locales/errors/en.json +++ b/locales/errors/en.json @@ -32,4 +32,4 @@ "8003": "Feed already added to list", "9000": "Achievement not completed", "9001": "Achievement already received" -} \ No newline at end of file +} diff --git a/locales/errors/fr.json b/locales/errors/fr.json index b984e3a3e..95cb993c9 100644 --- a/locales/errors/fr.json +++ b/locales/errors/fr.json @@ -11,7 +11,6 @@ "2010": "Échec de la vérification de la propriété", "2011": "Limite d'abonnement dépassée", "3000": "Entrée introuvable", - "3001": "L'entrée n'appartient pas à l'utilisateur", "4000": "Déjà réclamé", "4001": "Erreur du portefeuille utilisateur", "4002": "Solde insuffisant", diff --git a/locales/errors/ja.json b/locales/errors/ja.json index 64edfeb9d..3dd1a044e 100644 --- a/locales/errors/ja.json +++ b/locales/errors/ja.json @@ -11,7 +11,6 @@ "2010": "所有権の確認に失敗しました", "2011": "サブスクリプションの上限に達しました", "3000": "エントリーが見つかりません", - "3001": "エントリーがユーザーに属していません", "4000": "すでに請求済みです", "4001": "ユーザーウォレットエラー", "4002": "残高不足", diff --git a/locales/errors/ko.json b/locales/errors/ko.json index cf4d4bfc2..2fff17ef6 100644 --- a/locales/errors/ko.json +++ b/locales/errors/ko.json @@ -11,7 +11,6 @@ "2010": "소유권 도전 실패", "2011": "구독 한도 초과", "3000": "항목을 찾을 수 없습니다", - "3001": "항목이 사용자에게 속하지 않습니다", "4000": "이미 클레임됨", "4001": "사용자 지갑 오류", "4002": "잔액 부족", diff --git a/locales/errors/ru.json b/locales/errors/ru.json index f0a9251e0..8a4898077 100644 --- a/locales/errors/ru.json +++ b/locales/errors/ru.json @@ -11,7 +11,6 @@ "2010": "Ошибка проверки права собственности", "2011": "Превышен лимит подписок", "3000": "Запись не найдена", - "3001": "Запись не принадлежит пользователю", "4000": "Уже получено", "4001": "Ошибка кошелька пользователя", "4002": "Недостаточно средств", diff --git a/locales/errors/tr.json b/locales/errors/tr.json index b1e4f899c..588d3bf7f 100644 --- a/locales/errors/tr.json +++ b/locales/errors/tr.json @@ -11,7 +11,6 @@ "2010": "Sahiplik doğrulaması başarısız oldu", "2011": "Abonelik limiti aşıldı", "3000": "Giriş bulunamadı", - "3001": "Giriş kullanıcıya ait değil", "4000": "Zaten talep edilmiş", "4001": "Kullanıcı cüzdan hatası", "4002": "Yetersiz bakiye", diff --git a/locales/errors/zh-CN.json b/locales/errors/zh-CN.json index 0b6a3bdb0..bc2799af0 100644 --- a/locales/errors/zh-CN.json +++ b/locales/errors/zh-CN.json @@ -11,7 +11,6 @@ "2010": "所有权验证失败", "2011": "订阅限制已超出", "3000": "未找到条目", - "3001": "条目不属于用户", "4000": "已领取", "4001": "用户钱包错误", "4002": "余额不足", diff --git a/locales/errors/zh-HK.json b/locales/errors/zh-HK.json index e9f9ab3fc..df08aa95a 100644 --- a/locales/errors/zh-HK.json +++ b/locales/errors/zh-HK.json @@ -11,7 +11,6 @@ "2010": "所有權驗證失敗", "2011": "訂閱數量已達上限", "3000": "未找到條目", - "3001": "條目不屬於該用戶", "4000": "已兌換", "4001": "用戶錢包錯誤", "4002": "餘額不足", diff --git a/locales/errors/zh-TW.json b/locales/errors/zh-TW.json index 05d90e4eb..7cbc69c09 100644 --- a/locales/errors/zh-TW.json +++ b/locales/errors/zh-TW.json @@ -11,7 +11,6 @@ "2010": "所有權驗證失敗", "2011": "訂閱數量已達上限", "3000": "找不到條目", - "3001": "條目不屬於該用戶", "4000": "已兌換", "4001": "使用者錢包錯誤", "4002": "餘額不足", diff --git a/plugins/eslint-check-i18n-json.js b/plugins/eslint-check-i18n-json.js index 8e58fd91d..af98d8a82 100644 --- a/plugins/eslint-check-i18n-json.js +++ b/plugins/eslint-check-i18n-json.js @@ -1,4 +1,7 @@ +// @ts-check /** @type {import("eslint").ESLint.Plugin} */ +import fs from "node:fs" + export default { rules: { "valid-i18n-keys": { @@ -60,5 +63,57 @@ export default { } }, }, + "no-extra-keys": { + meta: { + type: "problem", + docs: { + description: "Ensure non-English JSON files don't have extra keys not present in en.json", + category: "Possible Errors", + recommended: true, + }, + fixable: null, + }, + create(context) { + return { + Program(node) { + const { filename, sourceCode } = context + + if (!filename.endsWith(".json")) return + + const parts = filename.split("/") + const lang = parts.at(-1).split(".")[0] + const namespace = parts.at(-2) + + if (lang === "en") return + + let currentJson = {} + let englishJson = {} + + try { + currentJson = JSON.parse(sourceCode.text) + const englishFilePath = `${process.cwd()}/locales/${namespace}/en.json` + englishJson = JSON.parse(fs.readFileSync(englishFilePath, "utf8")) + } catch (error) { + context.report({ + node, + message: `Error parsing JSON: ${error.message}`, + }) + return + } + + const extraKeys = Object.keys(currentJson).filter( + (key) => !Object.prototype.hasOwnProperty.call(englishJson, key), + ) + + for (const key of extraKeys) { + context.report({ + node, + message: `Key "${key}" is present in ${lang}.json but not in en.json for namespace "${namespace}"`, + }) + } + }, + } + }, + }, }, } From 234cdd3c71bb2e1fb0548734f31b10093372bc90 Mon Sep 17 00:00:00 2001 From: Innei Date: Sat, 28 Sep 2024 15:27:31 +0800 Subject: [PATCH 10/88] fix(i18n): duplicated keys Signed-off-by: Innei --- .../src/modules/settings/tabs/general.tsx | 2 +- locales/app/ar-DZ.json | 1 - locales/app/ar-MA.json | 1 - locales/app/ar-SA.json | 1 - locales/app/es.json | 1 - locales/app/fi.json | 1 - locales/app/fr.json | 1 - locales/app/it.json | 1 - locales/app/ru.json | 1 - locales/common/de.json | 2 +- locales/common/zh-CN.json | 1 - locales/external/ar-DZ.json | 66 ++---- locales/external/ar-IQ.json | 66 ++---- locales/external/ar-MA.json | 66 ++---- locales/external/ar-SA.json | 66 ++---- locales/external/ar-TN.json | 68 +++--- locales/external/ar-kw.json | 68 +++--- locales/external/de.json | 66 ++---- locales/external/es.json | 66 ++---- locales/external/fi.json | 66 ++---- locales/external/fr.json | 68 +++--- locales/external/it.json | 66 ++---- locales/external/ja.json | 68 +++--- locales/external/pt.json | 68 +++--- locales/external/ru.json | 66 ++---- locales/external/tr.json | 1 - locales/lang/en.json | 1 + locales/shortcuts/ar-TN.json | 223 ++---------------- package.json | 2 +- pnpm-lock.yaml | 129 +++++----- 30 files changed, 472 insertions(+), 831 deletions(-) diff --git a/apps/renderer/src/modules/settings/tabs/general.tsx b/apps/renderer/src/modules/settings/tabs/general.tsx index 38be254b9..c7204e1ad 100644 --- a/apps/renderer/src/modules/settings/tabs/general.tsx +++ b/apps/renderer/src/modules/settings/tabs/general.tsx @@ -253,7 +253,7 @@ export const LanguageSelector = () => { {originalLanguageName !== languageName && ( {originalLanguageName} diff --git a/locales/app/ar-DZ.json b/locales/app/ar-DZ.json index cd7e015c1..7f8417649 100644 --- a/locales/app/ar-DZ.json +++ b/locales/app/ar-DZ.json @@ -2,7 +2,6 @@ "ai_daily.title": "أهم الأخبار - {{title}}", "ai_daily.tooltip.content": "هذه الأخبار مختارة بواسطة الذكاء الاصطناعي من جدولك الزمني ( - ) والتي قد تكون مهمة بالنسبة لك.", "ai_daily.tooltip.update_schedule": "يتم التحديث يوميًا في الساعة 8 صباحًا و 8 مساءً.", - "app.app_name": "APP_NAME", "app.copy_logo_svg": "نسخ الشعار SVG", "app.toggle_sidebar": "تبديل الشريط الجانبي", "discover.any_url_or_keyword": "أي رابط أو كلمة مفتاحية", diff --git a/locales/app/ar-MA.json b/locales/app/ar-MA.json index 0088eaca9..db0ec7180 100644 --- a/locales/app/ar-MA.json +++ b/locales/app/ar-MA.json @@ -2,7 +2,6 @@ "ai_daily.title": "أهم الأخبار - {{title}}", "ai_daily.tooltip.content": "إليك الأخبار التي تم اختيارها من قِبل الذكاء الاصطناعي من جدولك الزمني ( - ) والتي قد تكون مهمة بالنسبة لك.", "ai_daily.tooltip.update_schedule": "تحديث يومي في الساعة 8 صباحًا و 8 مساءً.", - "app.app_name": "APP_NAME", "app.copy_logo_svg": "نسخ شعار SVG", "app.toggle_sidebar": "تبديل الشريط الجانبي", "discover.any_url_or_keyword": "أي رابط أو كلمة مفتاحية", diff --git a/locales/app/ar-SA.json b/locales/app/ar-SA.json index 88513247c..b7ab184d0 100644 --- a/locales/app/ar-SA.json +++ b/locales/app/ar-SA.json @@ -2,7 +2,6 @@ "ai_daily.title": "أهم الأخبار - {{title}}", "ai_daily.tooltip.content": "إليك الأخبار التي تم اختيارها بواسطة الذكاء الاصطناعي من خطك الزمني ( - ) والتي قد تكون مهمة بالنسبة لك.", "ai_daily.tooltip.update_schedule": "يتم التحديث يوميًا في الساعة 8 صباحًا و8 مساءً.", - "app.app_name": "APP_NAME", "app.copy_logo_svg": "نسخ شعار SVG", "app.toggle_sidebar": "تبديل الشريط الجانبي", "discover.any_url_or_keyword": "أي عنوان URL أو كلمة مفتاحية", diff --git a/locales/app/es.json b/locales/app/es.json index eca8d2c23..d17a3ff23 100644 --- a/locales/app/es.json +++ b/locales/app/es.json @@ -2,7 +2,6 @@ "ai_daily.title": "Titular - {{title}}", "ai_daily.tooltip.content": "Aquí están las noticias principales seleccionadas por IA de su línea de tiempo ( - ), que pueden ser importantes para usted.", "ai_daily.tooltip.update_schedule": "Actualizado todos los días a las 8 AM y 8 PM.", - "app.app_name": "APP_NAME", "app.copy_logo_svg": "Copiar Logo SVG", "app.toggle_sidebar": "Alternar barra lateral", "discover.any_url_or_keyword": "Cualquier URL o palabra clave", diff --git a/locales/app/fi.json b/locales/app/fi.json index 11dba1ad4..797ee04eb 100644 --- a/locales/app/fi.json +++ b/locales/app/fi.json @@ -2,7 +2,6 @@ "ai_daily.title": "Pääuutiset - {{title}}", "ai_daily.tooltip.content": "Tässä ovat uutiset, jotka AI on valinnut aikajanaltasi ( - ), ja jotka saattavat olla sinulle tärkeitä.", "ai_daily.tooltip.update_schedule": "Päivitetään päivittäin klo 8 ja klo 20.", - "app.app_name": "SOVELLUKSEN_NIMI", "app.copy_logo_svg": "Kopioi Logo SVG", "app.toggle_sidebar": "Vaihda sivupalkki", "discover.any_url_or_keyword": "Mikä tahansa URL tai avainsana", diff --git a/locales/app/fr.json b/locales/app/fr.json index dc14f478e..5093ee53c 100644 --- a/locales/app/fr.json +++ b/locales/app/fr.json @@ -2,7 +2,6 @@ "ai_daily.title": "Actualités Principales - {{title}}", "ai_daily.tooltip.content": "Voici des nouvelles sélectionnées par l'IA à partir de votre chronologie ( - ) qui peuvent être importantes pour vous.", "ai_daily.tooltip.update_schedule": "Mise à jour quotidienne à 8h00 et 20h00.", - "app.app_name": "NOM_APP", "app.copy_logo_svg": "Copier le logo SVG", "app.toggle_sidebar": "Afficher/Masquer la barre latérale", "discover.any_url_or_keyword": "Toute URL ou mot-clé", diff --git a/locales/app/it.json b/locales/app/it.json index 0d550522b..eb4f0f315 100644 --- a/locales/app/it.json +++ b/locales/app/it.json @@ -2,7 +2,6 @@ "ai_daily.title": "Top News - {{title}}", "ai_daily.tooltip.content": "Qui ci sono notizie selezionate dall'IA dalla tua timeline ( - ) che potrebbero essere importanti per te.", "ai_daily.tooltip.update_schedule": "Aggiornato ogni giorno alle 8 AM e alle 8 PM.", - "app.app_name": "NOME_APP", "app.copy_logo_svg": "Copia Logo SVG", "app.toggle_sidebar": "Mostra/Nascondi Sidebar", "discover.any_url_or_keyword": "Qualsiasi URL o Parola Chiave", diff --git a/locales/app/ru.json b/locales/app/ru.json index cb02e972c..91c439e34 100644 --- a/locales/app/ru.json +++ b/locales/app/ru.json @@ -2,7 +2,6 @@ "ai_daily.title": "Главные новости - {{title}}", "ai_daily.tooltip.content": "Вот новости, выбранные ИИ из вашей ленты ( - ), которые могут быть для вас важны.", "ai_daily.tooltip.update_schedule": "Обновление ежедневно в 8:00 и 20:00.", - "app.app_name": "ИМЯ_ПРИЛОЖЕНИЯ", "app.copy_logo_svg": "Скопировать логотип SVG", "app.toggle_sidebar": "Переключить боковую панель", "discover.any_url_or_keyword": "Любой URL или ключевое слово", diff --git a/locales/common/de.json b/locales/common/de.json index 2070b16c6..ab7d43da7 100644 --- a/locales/common/de.json +++ b/locales/common/de.json @@ -5,6 +5,7 @@ "confirm": "Bestätigen", "ok": "OK", "quantifier.piece": "", + "space": " ", "time.last_night": "Letzte Nacht", "time.the_night_before_last": "Vorgestern Nacht", "time.today": "Heute", @@ -24,6 +25,5 @@ "words.result": "Ergebnis", "words.result_one": "Ergebnis", "words.result_other": "Ergebnisse", - "words.space": " ", "words.which.all": "Alle" } diff --git a/locales/common/zh-CN.json b/locales/common/zh-CN.json index 957e1ace8..b70d7d90d 100644 --- a/locales/common/zh-CN.json +++ b/locales/common/zh-CN.json @@ -18,7 +18,6 @@ "words.edit": "编辑", "words.entry": "条目", "words.id": "ID", - "words.items": "内容", "words.items_one": "内容", "words.items_other": "内容", "words.local": "本地", diff --git a/locales/external/ar-DZ.json b/locales/external/ar-DZ.json index e243855ea..18a102b59 100644 --- a/locales/external/ar-DZ.json +++ b/locales/external/ar-DZ.json @@ -1,42 +1,28 @@ { - "feed": { - "follow_one": "تابع", - "follow_other": "متابعات", - "followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} مع {{readCount}} {{readNoun}} على {{appName}}", - "read_one": "قراءة", - "read_other": "قراءات" - }, - "header": { - "app": "التطبيق", - "download": "تحميل" - }, - "invitation": { - "activate": "تفعيل", - "codeOptions": { - "1": "ابحث عن أي مستخدم اختبار ألفا لدعوتك.", - "2": "انضم إلى خادم Discord الخاص بنا للحصول على هدايا عرضية.", - "3": "تابع حسابنا على X للحصول على هدايا عرضية." - }, - "earlyAccess": "حاليًا Follow في مرحلة الوصول المبكر ويتطلب رمز دعوة للاستخدام.", - "earlyAccessMessage": "😰 عذرًا، Follow حاليًا في مرحلة الوصول المبكر ويتطلب رمز دعوة للاستخدام.", - "generateButton": "إنشاء رمز جديد", - "generateCost": "يمكنك إنفاق {{INVITATION_PRICE}} من Power لإنشاء رمز دعوة لأصدقائك.", - "getCodeMessage": "يمكنك الحصول على رمز دعوة من خلال الطرق التالية:", - "title": "رمز الدعوة" - }, - "login": { - "backToWebApp": "العودة إلى تطبيق الويب", - "continueWithGitHub": "تابع مع GitHub", - "continueWithGoogle": "تابع مع Google", - "logInTo": "تسجيل الدخول إلى", - "openApp": "افتح التطبيق", - "redirecting": "إعادة التوجيه", - "welcomeTo": "مرحبًا بك في" - }, - "redirect": { - "continueInBrowser": "المتابعة في المتصفح", - "instruction": "الآن هو الوقت المناسب لفتح {{APP_NAME}} وإغلاق هذه الصفحة بأمان.", - "openApp": "افتح {{APP_NAME}}", - "successMessage": "تم الاتصال بنجاح بحساب {{APP_NAME}}." - } + "feed.followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} مع {{readCount}} {{readNoun}} على {{appName}}", + "feed.read_one": "قراءة", + "feed.read_other": "قراءات", + "header.app": "التطبيق", + "header.download": "تحميل", + "invitation.activate": "تفعيل", + "invitation.codeOptions.1": "ابحث عن أي مستخدم اختبار ألفا لدعوتك.", + "invitation.codeOptions.2": "انضم إلى خادم Discord الخاص بنا للحصول على هدايا عرضية.", + "invitation.codeOptions.3": "تابع حسابنا على X للحصول على هدايا عرضية.", + "invitation.earlyAccess": "حاليًا Follow في مرحلة الوصول المبكر ويتطلب رمز دعوة للاستخدام.", + "invitation.earlyAccessMessage": "😰 عذرًا، Follow حاليًا في مرحلة الوصول المبكر ويتطلب رمز دعوة للاستخدام.", + "invitation.generateButton": "إنشاء رمز جديد", + "invitation.generateCost": "يمكنك إنفاق {{INVITATION_PRICE}} من Power لإنشاء رمز دعوة لأصدقائك.", + "invitation.getCodeMessage": "يمكنك الحصول على رمز دعوة من خلال الطرق التالية:", + "invitation.title": "رمز الدعوة", + "login.backToWebApp": "العودة إلى تطبيق الويب", + "login.continueWithGitHub": "تابع مع GitHub", + "login.continueWithGoogle": "تابع مع Google", + "login.logInTo": "تسجيل الدخول إلى", + "login.openApp": "افتح التطبيق", + "login.redirecting": "إعادة التوجيه", + "login.welcomeTo": "مرحبًا بك في", + "redirect.continueInBrowser": "المتابعة في المتصفح", + "redirect.instruction": "الآن هو الوقت المناسب لفتح {{APP_NAME}} وإغلاق هذه الصفحة بأمان.", + "redirect.openApp": "افتح {{APP_NAME}}", + "redirect.successMessage": "تم الاتصال بنجاح بحساب {{APP_NAME}}." } diff --git a/locales/external/ar-IQ.json b/locales/external/ar-IQ.json index e243855ea..18a102b59 100644 --- a/locales/external/ar-IQ.json +++ b/locales/external/ar-IQ.json @@ -1,42 +1,28 @@ { - "feed": { - "follow_one": "تابع", - "follow_other": "متابعات", - "followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} مع {{readCount}} {{readNoun}} على {{appName}}", - "read_one": "قراءة", - "read_other": "قراءات" - }, - "header": { - "app": "التطبيق", - "download": "تحميل" - }, - "invitation": { - "activate": "تفعيل", - "codeOptions": { - "1": "ابحث عن أي مستخدم اختبار ألفا لدعوتك.", - "2": "انضم إلى خادم Discord الخاص بنا للحصول على هدايا عرضية.", - "3": "تابع حسابنا على X للحصول على هدايا عرضية." - }, - "earlyAccess": "حاليًا Follow في مرحلة الوصول المبكر ويتطلب رمز دعوة للاستخدام.", - "earlyAccessMessage": "😰 عذرًا، Follow حاليًا في مرحلة الوصول المبكر ويتطلب رمز دعوة للاستخدام.", - "generateButton": "إنشاء رمز جديد", - "generateCost": "يمكنك إنفاق {{INVITATION_PRICE}} من Power لإنشاء رمز دعوة لأصدقائك.", - "getCodeMessage": "يمكنك الحصول على رمز دعوة من خلال الطرق التالية:", - "title": "رمز الدعوة" - }, - "login": { - "backToWebApp": "العودة إلى تطبيق الويب", - "continueWithGitHub": "تابع مع GitHub", - "continueWithGoogle": "تابع مع Google", - "logInTo": "تسجيل الدخول إلى", - "openApp": "افتح التطبيق", - "redirecting": "إعادة التوجيه", - "welcomeTo": "مرحبًا بك في" - }, - "redirect": { - "continueInBrowser": "المتابعة في المتصفح", - "instruction": "الآن هو الوقت المناسب لفتح {{APP_NAME}} وإغلاق هذه الصفحة بأمان.", - "openApp": "افتح {{APP_NAME}}", - "successMessage": "تم الاتصال بنجاح بحساب {{APP_NAME}}." - } + "feed.followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} مع {{readCount}} {{readNoun}} على {{appName}}", + "feed.read_one": "قراءة", + "feed.read_other": "قراءات", + "header.app": "التطبيق", + "header.download": "تحميل", + "invitation.activate": "تفعيل", + "invitation.codeOptions.1": "ابحث عن أي مستخدم اختبار ألفا لدعوتك.", + "invitation.codeOptions.2": "انضم إلى خادم Discord الخاص بنا للحصول على هدايا عرضية.", + "invitation.codeOptions.3": "تابع حسابنا على X للحصول على هدايا عرضية.", + "invitation.earlyAccess": "حاليًا Follow في مرحلة الوصول المبكر ويتطلب رمز دعوة للاستخدام.", + "invitation.earlyAccessMessage": "😰 عذرًا، Follow حاليًا في مرحلة الوصول المبكر ويتطلب رمز دعوة للاستخدام.", + "invitation.generateButton": "إنشاء رمز جديد", + "invitation.generateCost": "يمكنك إنفاق {{INVITATION_PRICE}} من Power لإنشاء رمز دعوة لأصدقائك.", + "invitation.getCodeMessage": "يمكنك الحصول على رمز دعوة من خلال الطرق التالية:", + "invitation.title": "رمز الدعوة", + "login.backToWebApp": "العودة إلى تطبيق الويب", + "login.continueWithGitHub": "تابع مع GitHub", + "login.continueWithGoogle": "تابع مع Google", + "login.logInTo": "تسجيل الدخول إلى", + "login.openApp": "افتح التطبيق", + "login.redirecting": "إعادة التوجيه", + "login.welcomeTo": "مرحبًا بك في", + "redirect.continueInBrowser": "المتابعة في المتصفح", + "redirect.instruction": "الآن هو الوقت المناسب لفتح {{APP_NAME}} وإغلاق هذه الصفحة بأمان.", + "redirect.openApp": "افتح {{APP_NAME}}", + "redirect.successMessage": "تم الاتصال بنجاح بحساب {{APP_NAME}}." } diff --git a/locales/external/ar-MA.json b/locales/external/ar-MA.json index b73818854..449de9769 100644 --- a/locales/external/ar-MA.json +++ b/locales/external/ar-MA.json @@ -1,42 +1,28 @@ { - "feed": { - "follow_one": "متابعة", - "follow_other": "متابعات", - "followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} مع {{readCount}} {{readNoun}} على {{appName}}", - "read_one": "قراءة", - "read_other": "قراءات" - }, - "header": { - "app": "تطبيق", - "download": "تحميل" - }, - "invitation": { - "activate": "تفعيل", - "codeOptions": { - "1": "ابحث عن أي مستخدم اختبار ألفا لدعوتك.", - "2": "انضم إلى سيرفر Discord الخاص بنا للحصول على هدايا بين الحين والآخر.", - "3": "تابع حسابنا على X للحصول على هدايا بين الحين والآخر." - }, - "earlyAccess": "التطبيق في مرحلة الوصول المبكر ويحتاج إلى رمز دعوة للاستخدام.", - "earlyAccessMessage": "😰 عذرًا، التطبيق في مرحلة الوصول المبكر ويحتاج إلى رمز دعوة للاستخدام.", - "generateButton": "إنشاء رمز جديد", - "generateCost": "يمكنك إنفاق {{INVITATION_PRICE}} Power لإنشاء رمز دعوة لأصدقائك.", - "getCodeMessage": "يمكنك الحصول على رمز دعوة عبر الطرق التالية:", - "title": "رمز الدعوة" - }, - "login": { - "backToWebApp": "العودة إلى التطبيق على الويب", - "continueWithGitHub": "المتابعة باستخدام GitHub", - "continueWithGoogle": "المتابعة باستخدام Google", - "logInTo": "تسجيل الدخول إلى ", - "openApp": "فتح التطبيق", - "redirecting": "إعادة التوجيه", - "welcomeTo": "مرحبًا بك في " - }, - "redirect": { - "continueInBrowser": "المتابعة في المتصفح", - "instruction": "حان الوقت الآن لفتح {{APP_NAME}} وإغلاق هذه الصفحة بأمان.", - "openApp": "افتح {{APP_NAME}}", - "successMessage": "لقد تم الاتصال بنجاح بحسابك على {{APP_NAME}}." - } + "feed.followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} مع {{readCount}} {{readNoun}} على {{appName}}", + "feed.read_one": "قراءة", + "feed.read_other": "قراءات", + "header.app": "تطبيق", + "header.download": "تحميل", + "invitation.activate": "تفعيل", + "invitation.codeOptions.1": "ابحث عن أي مستخدم اختبار ألفا لدعوتك.", + "invitation.codeOptions.2": "انضم إلى سيرفر Discord الخاص بنا للحصول على هدايا بين الحين والآخر.", + "invitation.codeOptions.3": "تابع حسابنا على X للحصول على هدايا بين الحين والآخر.", + "invitation.earlyAccess": "التطبيق في مرحلة الوصول المبكر ويحتاج إلى رمز دعوة للاستخدام.", + "invitation.earlyAccessMessage": "😰 عذرًا، التطبيق في مرحلة الوصول المبكر ويحتاج إلى رمز دعوة للاستخدام.", + "invitation.generateButton": "إنشاء رمز جديد", + "invitation.generateCost": "يمكنك إنفاق {{INVITATION_PRICE}} Power لإنشاء رمز دعوة لأصدقائك.", + "invitation.getCodeMessage": "يمكنك الحصول على رمز دعوة عبر الطرق التالية:", + "invitation.title": "رمز الدعوة", + "login.backToWebApp": "العودة إلى التطبيق على الويب", + "login.continueWithGitHub": "المتابعة باستخدام GitHub", + "login.continueWithGoogle": "المتابعة باستخدام Google", + "login.logInTo": "تسجيل الدخول إلى ", + "login.openApp": "فتح التطبيق", + "login.redirecting": "إعادة التوجيه", + "login.welcomeTo": "مرحبًا بك في ", + "redirect.continueInBrowser": "المتابعة في المتصفح", + "redirect.instruction": "حان الوقت الآن لفتح {{APP_NAME}} وإغلاق هذه الصفحة بأمان.", + "redirect.openApp": "افتح {{APP_NAME}}", + "redirect.successMessage": "لقد تم الاتصال بنجاح بحسابك على {{APP_NAME}}." } diff --git a/locales/external/ar-SA.json b/locales/external/ar-SA.json index 99ccef6bb..ee03a1bf7 100644 --- a/locales/external/ar-SA.json +++ b/locales/external/ar-SA.json @@ -1,42 +1,28 @@ { - "feed": { - "follow_one": "متابعة", - "follow_other": "متابعات", - "followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} مع {{readCount}} {{readNoun}} على {{appName}}", - "read_one": "قراءة", - "read_other": "قراءات" - }, - "header": { - "app": "تطبيق", - "download": "تحميل" - }, - "invitation": { - "activate": "تفعيل", - "codeOptions": { - "1": "ابحث عن أي مستخدم اختبار ألفا لدعوتك.", - "2": "انضم إلى خادمنا على Discord للحصول على هدايا دورية.", - "3": "تابع حسابنا على X للحصول على هدايا دورية." - }, - "earlyAccess": "حاليًا، Follow في مرحلة الوصول المبكر ويتطلب رمز دعوة لاستخدامه.", - "earlyAccessMessage": "😰 نأسف، Follow في مرحلة الوصول المبكر ويتطلب رمز دعوة لاستخدامه.", - "generateButton": "إنشاء رمز جديد", - "generateCost": "يمكنك إنفاق {{INVITATION_PRICE}} Power لإنشاء رمز دعوة لأصدقائك.", - "getCodeMessage": "يمكنك الحصول على رمز دعوة من خلال الطرق التالية:", - "title": "رمز الدعوة" - }, - "login": { - "backToWebApp": "العودة إلى تطبيق الويب", - "continueWithGitHub": "المتابعة باستخدام GitHub", - "continueWithGoogle": "المتابعة باستخدام Google", - "logInTo": "تسجيل الدخول إلى", - "openApp": "فتح التطبيق", - "redirecting": "إعادة التوجيه", - "welcomeTo": "مرحبًا بك في" - }, - "redirect": { - "continueInBrowser": "المتابعة في المتصفح", - "instruction": "الآن حان الوقت لفتح {{APP_NAME}} وإغلاق هذه الصفحة بأمان.", - "openApp": "فتح {{APP_NAME}}", - "successMessage": "تم الاتصال بحساب {{APP_NAME}} بنجاح." - } + "feed.followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} مع {{readCount}} {{readNoun}} على {{appName}}", + "feed.read_one": "قراءة", + "feed.read_other": "قراءات", + "header.app": "تطبيق", + "header.download": "تحميل", + "invitation.activate": "تفعيل", + "invitation.codeOptions.1": "ابحث عن أي مستخدم اختبار ألفا لدعوتك.", + "invitation.codeOptions.2": "انضم إلى خادمنا على Discord للحصول على هدايا دورية.", + "invitation.codeOptions.3": "تابع حسابنا على X للحصول على هدايا دورية.", + "invitation.earlyAccess": "حاليًا، Follow في مرحلة الوصول المبكر ويتطلب رمز دعوة لاستخدامه.", + "invitation.earlyAccessMessage": "😰 نأسف، Follow في مرحلة الوصول المبكر ويتطلب رمز دعوة لاستخدامه.", + "invitation.generateButton": "إنشاء رمز جديد", + "invitation.generateCost": "يمكنك إنفاق {{INVITATION_PRICE}} Power لإنشاء رمز دعوة لأصدقائك.", + "invitation.getCodeMessage": "يمكنك الحصول على رمز دعوة من خلال الطرق التالية:", + "invitation.title": "رمز الدعوة", + "login.backToWebApp": "العودة إلى تطبيق الويب", + "login.continueWithGitHub": "المتابعة باستخدام GitHub", + "login.continueWithGoogle": "المتابعة باستخدام Google", + "login.logInTo": "تسجيل الدخول إلى", + "login.openApp": "فتح التطبيق", + "login.redirecting": "إعادة التوجيه", + "login.welcomeTo": "مرحبًا بك في", + "redirect.continueInBrowser": "المتابعة في المتصفح", + "redirect.instruction": "الآن حان الوقت لفتح {{APP_NAME}} وإغلاق هذه الصفحة بأمان.", + "redirect.openApp": "فتح {{APP_NAME}}", + "redirect.successMessage": "تم الاتصال بحساب {{APP_NAME}} بنجاح." } diff --git a/locales/external/ar-TN.json b/locales/external/ar-TN.json index 1d623dcbb..dd04662ac 100644 --- a/locales/external/ar-TN.json +++ b/locales/external/ar-TN.json @@ -1,43 +1,31 @@ { "copied_link": "تم نسخ الرابط إلى الحافظة", - "feed": { - "follower_one": "متابع", - "follower_other": "متابعون", - "followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} مع {{readCount}} {{readNoun}} على {{appName}}", - "read_one": "قراءة", - "read_other": "قراءات" - }, - "header": { - "app": "التطبيق", - "download": "تحميل" - }, - "invitation": { - "activate": "تفعيل", - "codeOptions": { - "1": "ابحث عن أي مستخدم اختبار ألفا لدعوتك.", - "2": "انضم إلى خادم Discord الخاص بنا للحصول على هدايا عرضية.", - "3": "تابع حسابنا على X للحصول على هدايا عرضية." - }, - "earlyAccess": "Follow حالياً في مرحلة الوصول المبكر ويتطلب رمز دعوة للاستخدام.", - "earlyAccessMessage": "😰 عذراً، Follow حالياً في مرحلة الوصول المبكر ويتطلب رمز دعوة للاستخدام.", - "generateButton": "إنشاء رمز جديد", - "generateCost": "يمكنك إنفاق {{INVITATION_PRICE}} من Power لإنشاء رمز دعوة لأصدقائك.", - "getCodeMessage": "يمكنك الحصول على رمز دعوة من خلال الطرق التالية:", - "title": "رمز الدعوة" - }, - "login": { - "backToWebApp": "العودة إلى تطبيق الويب", - "continueWithGitHub": "المتابعة باستخدام GitHub", - "continueWithGoogle": "المتابعة باستخدام Google", - "logInTo": "تسجيل الدخول إلى ", - "openApp": "افتح التطبيق", - "redirecting": "جاري إعادة التوجيه", - "welcomeTo": "مرحباً بك في " - }, - "redirect": { - "continueInBrowser": "المتابعة في المتصفح", - "instruction": "الآن هو الوقت المناسب لفتح {{APP_NAME}} وإغلاق هذه الصفحة بأمان.", - "openApp": "افتح {{APP_NAME}}", - "successMessage": "تم الاتصال بحساب {{APP_NAME}} بنجاح." - } + "feed.follower_one": "متابع", + "feed.follower_other": "متابعون", + "feed.followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} مع {{readCount}} {{readNoun}} على {{appName}}", + "feed.read_one": "قراءة", + "feed.read_other": "قراءات", + "header.app": "التطبيق", + "header.download": "تحميل", + "invitation.activate": "تفعيل", + "invitation.codeOptions.1": "ابحث عن أي مستخدم اختبار ألفا لدعوتك.", + "invitation.codeOptions.2": "انضم إلى خادم Discord الخاص بنا للحصول على هدايا عرضية.", + "invitation.codeOptions.3": "تابع حسابنا على X للحصول على هدايا عرضية.", + "invitation.earlyAccess": "Follow حالياً في مرحلة الوصول المبكر ويتطلب رمز دعوة للاستخدام.", + "invitation.earlyAccessMessage": "😰 عذراً، Follow حالياً في مرحلة الوصول المبكر ويتطلب رمز دعوة للاستخدام.", + "invitation.generateButton": "إنشاء رمز جديد", + "invitation.generateCost": "يمكنك إنفاق {{INVITATION_PRICE}} من Power لإنشاء رمز دعوة لأصدقائك.", + "invitation.getCodeMessage": "يمكنك الحصول على رمز دعوة من خلال الطرق التالية:", + "invitation.title": "رمز الدعوة", + "login.backToWebApp": "العودة إلى تطبيق الويب", + "login.continueWithGitHub": "المتابعة باستخدام GitHub", + "login.continueWithGoogle": "المتابعة باستخدام Google", + "login.logInTo": "تسجيل الدخول إلى ", + "login.openApp": "افتح التطبيق", + "login.redirecting": "جاري إعادة التوجيه", + "login.welcomeTo": "مرحباً بك في ", + "redirect.continueInBrowser": "المتابعة في المتصفح", + "redirect.instruction": "الآن هو الوقت المناسب لفتح {{APP_NAME}} وإغلاق هذه الصفحة بأمان.", + "redirect.openApp": "افتح {{APP_NAME}}", + "redirect.successMessage": "تم الاتصال بحساب {{APP_NAME}} بنجاح." } diff --git a/locales/external/ar-kw.json b/locales/external/ar-kw.json index cffc4ea29..612578237 100644 --- a/locales/external/ar-kw.json +++ b/locales/external/ar-kw.json @@ -1,43 +1,31 @@ { "copied_link": "تم نسخ الرابط إلى الحافظة", - "feed": { - "follower_one": "متابع", - "follower_other": "متابعين", - "followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} مع {{readCount}} {{readNoun}} على {{appName}}", - "read_one": "قراءة", - "read_other": "قراءات" - }, - "header": { - "app": "التطبيق", - "download": "تنزيل" - }, - "invitation": { - "activate": "تفعيل", - "codeOptions": { - "1": "ابحث عن أي مستخدم اختبار ألفا لدعوتك.", - "2": "انضم إلى خادم Discord الخاص بنا للحصول على هدايا عرضية.", - "3": "تابع حسابنا على X للحصول على هدايا عرضية." - }, - "earlyAccess": "تطبيق Follow حاليًا في مرحلة الوصول المبكر ويتطلب رمز دعوة للاستخدام.", - "earlyAccessMessage": "😰 عذرًا، Follow في مرحلة الوصول المبكر ويتطلب رمز دعوة للاستخدام.", - "generateButton": "إنشاء رمز جديد", - "generateCost": "يمكنك إنفاق {{INVITATION_PRICE}} باور لإنشاء رمز دعوة لأصدقائك.", - "getCodeMessage": "يمكنك الحصول على رمز دعوة من خلال الطرق التالية:", - "title": "رمز الدعوة" - }, - "login": { - "backToWebApp": "العودة إلى تطبيق الويب", - "continueWithGitHub": "تابع مع GitHub", - "continueWithGoogle": "تابع مع Google", - "logInTo": "تسجيل الدخول إلى", - "openApp": "افتح التطبيق", - "redirecting": "إعادة التوجيه", - "welcomeTo": "مرحبًا بك في" - }, - "redirect": { - "continueInBrowser": "المتابعة في المتصفح", - "instruction": "الآن هو الوقت المناسب لفتح {{APP_NAME}} وإغلاق هذه الصفحة بأمان.", - "openApp": "افتح {{APP_NAME}}", - "successMessage": "تم الاتصال بنجاح بحساب {{APP_NAME}}." - } + "feed.follower_one": "متابع", + "feed.follower_other": "متابعين", + "feed.followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} مع {{readCount}} {{readNoun}} على {{appName}}", + "feed.read_one": "قراءة", + "feed.read_other": "قراءات", + "header.app": "التطبيق", + "header.download": "تنزيل", + "invitation.activate": "تفعيل", + "invitation.codeOptions.1": "ابحث عن أي مستخدم اختبار ألفا لدعوتك.", + "invitation.codeOptions.2": "انضم إلى خادم Discord الخاص بنا للحصول على هدايا عرضية.", + "invitation.codeOptions.3": "تابع حسابنا على X للحصول على هدايا عرضية.", + "invitation.earlyAccess": "تطبيق Follow حاليًا في مرحلة الوصول المبكر ويتطلب رمز دعوة للاستخدام.", + "invitation.earlyAccessMessage": "😰 عذرًا، Follow في مرحلة الوصول المبكر ويتطلب رمز دعوة للاستخدام.", + "invitation.generateButton": "إنشاء رمز جديد", + "invitation.generateCost": "يمكنك إنفاق {{INVITATION_PRICE}} باور لإنشاء رمز دعوة لأصدقائك.", + "invitation.getCodeMessage": "يمكنك الحصول على رمز دعوة من خلال الطرق التالية:", + "invitation.title": "رمز الدعوة", + "login.backToWebApp": "العودة إلى تطبيق الويب", + "login.continueWithGitHub": "تابع مع GitHub", + "login.continueWithGoogle": "تابع مع Google", + "login.logInTo": "تسجيل الدخول إلى", + "login.openApp": "افتح التطبيق", + "login.redirecting": "إعادة التوجيه", + "login.welcomeTo": "مرحبًا بك في", + "redirect.continueInBrowser": "المتابعة في المتصفح", + "redirect.instruction": "الآن هو الوقت المناسب لفتح {{APP_NAME}} وإغلاق هذه الصفحة بأمان.", + "redirect.openApp": "افتح {{APP_NAME}}", + "redirect.successMessage": "تم الاتصال بنجاح بحساب {{APP_NAME}}." } diff --git a/locales/external/de.json b/locales/external/de.json index 44ea6c279..ac3a56175 100644 --- a/locales/external/de.json +++ b/locales/external/de.json @@ -1,42 +1,28 @@ { - "feed": { - "follow_one": "follow", - "follow_other": "followers", - "followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} with {{readCount}} {{readNoun}} on {{appName}}", - "read_one": "read", - "read_other": "reads" - }, - "header": { - "app": "App", - "download": "Download" - }, - "invitation": { - "activate": "Activate", - "codeOptions": { - "1": "Looking for an alpha test user to invite you.", - "2": "Join our Discord server for occasional giveaways.", - "3": "Follow our X account for occasional giveaways." - }, - "earlyAccess": "Follow is currently in early access and requires an invitation code to use.", - "earlyAccessMessage": "😰 Sorry, Follow is currently in early access and requires an invitation code to use.", - "generateButton": "Generate new code", - "generateCost": "You can spend {{INVITATION_PRICE}} Power to generate an invitation code for your friends.", - "getCodeMessage": "You can get an invitation code through the following ways:", - "title": "Invitation Code" - }, - "login": { - "backToWebApp": "Back to the web app", - "continueWithGitHub": "Continue with GitHub", - "continueWithGoogle": "Continue with Google", - "logInTo": "Log in to ", - "openApp": "Open app", - "redirecting": "Redirecting", - "welcomeTo": "Welcome to " - }, - "redirect": { - "continueInBrowser": "Continue in browser", - "instruction": "It is time to open {{APP_NAME}} and safely close this page.", - "openApp": "Open {{APP_NAME}}", - "successMessage": "You have successfully connected to {{APP_NAME}} account." - } + "feed.followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} with {{readCount}} {{readNoun}} on {{appName}}", + "feed.read_one": "read", + "feed.read_other": "reads", + "header.app": "App", + "header.download": "Download", + "invitation.activate": "Activate", + "invitation.codeOptions.1": "Looking for an alpha test user to invite you.", + "invitation.codeOptions.2": "Join our Discord server for occasional giveaways.", + "invitation.codeOptions.3": "Follow our X account for occasional giveaways.", + "invitation.earlyAccess": "Follow is currently in early access and requires an invitation code to use.", + "invitation.earlyAccessMessage": "😰 Sorry, Follow is currently in early access and requires an invitation code to use.", + "invitation.generateButton": "Generate new code", + "invitation.generateCost": "You can spend {{INVITATION_PRICE}} Power to generate an invitation code for your friends.", + "invitation.getCodeMessage": "You can get an invitation code through the following ways:", + "invitation.title": "Invitation Code", + "login.backToWebApp": "Back to the web app", + "login.continueWithGitHub": "Continue with GitHub", + "login.continueWithGoogle": "Continue with Google", + "login.logInTo": "Log in to ", + "login.openApp": "Open app", + "login.redirecting": "Redirecting", + "login.welcomeTo": "Welcome to ", + "redirect.continueInBrowser": "Continue in browser", + "redirect.instruction": "It is time to open {{APP_NAME}} and safely close this page.", + "redirect.openApp": "Open {{APP_NAME}}", + "redirect.successMessage": "You have successfully connected to {{APP_NAME}} account." } diff --git a/locales/external/es.json b/locales/external/es.json index 102fd9ecc..344256c3f 100644 --- a/locales/external/es.json +++ b/locales/external/es.json @@ -1,42 +1,28 @@ { - "feed": { - "follow_one": "seguir", - "follow_other": "seguidores", - "followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} con {{readCount}} {{readNoun}} en {{appName}}", - "read_one": "leer", - "read_other": "lecturas" - }, - "header": { - "app": "Aplicación", - "download": "Descargar" - }, - "invitation": { - "activate": "Activar", - "codeOptions": { - "1": "Buscando a algún usuario de prueba alfa que te invite.", - "2": "Únete a nuestro servidor de Discord para sorteos ocasionales.", - "3": "Sigue nuestra cuenta de X para sorteos ocasionales." - }, - "earlyAccess": "Follow está actualmente en acceso anticipado y requiere un código de invitación para usarlo.", - "earlyAccessMessage": "😰 Lo sentimos, Follow está actualmente en acceso anticipado y requiere un código de invitación para usarlo.", - "generateButton": "Generar nuevo código", - "generateCost": "Puedes gastar {{INVITATION_PRICE}} Power para generar un código de invitación para tus amigos.", - "getCodeMessage": "Puedes obtener un código de invitación de las siguientes maneras:", - "title": "Código de Invitación" - }, - "login": { - "backToWebApp": "Volver a la aplicación web", - "continueWithGitHub": "Continuar con GitHub", - "continueWithGoogle": "Continuar con Google", - "logInTo": "Iniciar sesión en ", - "openApp": "Abrir aplicación", - "redirecting": "Redirigiendo", - "welcomeTo": "Bienvenido a " - }, - "redirect": { - "continueInBrowser": "Continuar en el navegador", - "instruction": "Es hora de abrir {{APP_NAME}} y cerrar esta página de forma segura.", - "openApp": "Abrir {{APP_NAME}}", - "successMessage": "Te has conectado exitosamente a la cuenta de {{APP_NAME}}." - } + "feed.followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} con {{readCount}} {{readNoun}} en {{appName}}", + "feed.read_one": "leer", + "feed.read_other": "lecturas", + "header.app": "Aplicación", + "header.download": "Descargar", + "invitation.activate": "Activar", + "invitation.codeOptions.1": "Buscando a algún usuario de prueba alfa que te invite.", + "invitation.codeOptions.2": "Únete a nuestro servidor de Discord para sorteos ocasionales.", + "invitation.codeOptions.3": "Sigue nuestra cuenta de X para sorteos ocasionales.", + "invitation.earlyAccess": "Follow está actualmente en acceso anticipado y requiere un código de invitación para usarlo.", + "invitation.earlyAccessMessage": "😰 Lo sentimos, Follow está actualmente en acceso anticipado y requiere un código de invitación para usarlo.", + "invitation.generateButton": "Generar nuevo código", + "invitation.generateCost": "Puedes gastar {{INVITATION_PRICE}} Power para generar un código de invitación para tus amigos.", + "invitation.getCodeMessage": "Puedes obtener un código de invitación de las siguientes maneras:", + "invitation.title": "Código de Invitación", + "login.backToWebApp": "Volver a la aplicación web", + "login.continueWithGitHub": "Continuar con GitHub", + "login.continueWithGoogle": "Continuar con Google", + "login.logInTo": "Iniciar sesión en ", + "login.openApp": "Abrir aplicación", + "login.redirecting": "Redirigiendo", + "login.welcomeTo": "Bienvenido a ", + "redirect.continueInBrowser": "Continuar en el navegador", + "redirect.instruction": "Es hora de abrir {{APP_NAME}} y cerrar esta página de forma segura.", + "redirect.openApp": "Abrir {{APP_NAME}}", + "redirect.successMessage": "Te has conectado exitosamente a la cuenta de {{APP_NAME}}." } diff --git a/locales/external/fi.json b/locales/external/fi.json index e596c13c7..25844d106 100644 --- a/locales/external/fi.json +++ b/locales/external/fi.json @@ -1,42 +1,28 @@ { - "feed": { - "follow_one": "seuraa", - "follow_other": "seuraajat", - "followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} ja {{readCount}} {{readNoun}} palvelussa {{appName}}", - "read_one": "lue", - "read_other": "lukee" - }, - "header": { - "app": "Sovellus", - "download": "Lataa" - }, - "invitation": { - "activate": "Aktivoi", - "codeOptions": { - "1": "Etsi mikä tahansa alpha-testaaja kutsumaan sinut.", - "2": "Liity Discord-palvelimeemme satunnaisia arvontoja varten.", - "3": "Seuraa X-tiliämme satunnaisia arvontoja varten." - }, - "earlyAccess": "Follow on tällä hetkellä varhaisessa käytössä ja vaatii kutsukoodin.", - "earlyAccessMessage": "😰 Pahoittelut, Follow on tällä hetkellä varhaisessa käytössä ja vaatii kutsukoodin.", - "generateButton": "Luo uusi koodi", - "generateCost": "Voit käyttää {{INVITATION_PRICE}} Poweria luodaksesi kutsukoodin ystävillesi.", - "getCodeMessage": "Voit saada kutsukoodin seuraavilla tavoilla:", - "title": "Kutsukoodi" - }, - "login": { - "backToWebApp": "Takaisin verkkosovellukseen", - "continueWithGitHub": "Jatka GitHubilla", - "continueWithGoogle": "Jatka Googlella", - "logInTo": "Kirjaudu sisään ", - "openApp": "Avaa sovellus", - "redirecting": "Uudelleenohjataan", - "welcomeTo": "Tervetuloa " - }, - "redirect": { - "continueInBrowser": "Jatka selaimessa", - "instruction": "Nyt on aika avata {{APP_NAME}} ja sulkea tämä sivu turvallisesti.", - "openApp": "Avaa {{APP_NAME}}", - "successMessage": "Olet onnistuneesti yhdistänyt {{APP_NAME}}-tilisi." - } + "feed.followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} ja {{readCount}} {{readNoun}} palvelussa {{appName}}", + "feed.read_one": "lue", + "feed.read_other": "lukee", + "header.app": "Sovellus", + "header.download": "Lataa", + "invitation.activate": "Aktivoi", + "invitation.codeOptions.1": "Etsi mikä tahansa alpha-testaaja kutsumaan sinut.", + "invitation.codeOptions.2": "Liity Discord-palvelimeemme satunnaisia arvontoja varten.", + "invitation.codeOptions.3": "Seuraa X-tiliämme satunnaisia arvontoja varten.", + "invitation.earlyAccess": "Follow on tällä hetkellä varhaisessa käytössä ja vaatii kutsukoodin.", + "invitation.earlyAccessMessage": "😰 Pahoittelut, Follow on tällä hetkellä varhaisessa käytössä ja vaatii kutsukoodin.", + "invitation.generateButton": "Luo uusi koodi", + "invitation.generateCost": "Voit käyttää {{INVITATION_PRICE}} Poweria luodaksesi kutsukoodin ystävillesi.", + "invitation.getCodeMessage": "Voit saada kutsukoodin seuraavilla tavoilla:", + "invitation.title": "Kutsukoodi", + "login.backToWebApp": "Takaisin verkkosovellukseen", + "login.continueWithGitHub": "Jatka GitHubilla", + "login.continueWithGoogle": "Jatka Googlella", + "login.logInTo": "Kirjaudu sisään ", + "login.openApp": "Avaa sovellus", + "login.redirecting": "Uudelleenohjataan", + "login.welcomeTo": "Tervetuloa ", + "redirect.continueInBrowser": "Jatka selaimessa", + "redirect.instruction": "Nyt on aika avata {{APP_NAME}} ja sulkea tämä sivu turvallisesti.", + "redirect.openApp": "Avaa {{APP_NAME}}", + "redirect.successMessage": "Olet onnistuneesti yhdistänyt {{APP_NAME}}-tilisi." } diff --git a/locales/external/fr.json b/locales/external/fr.json index b8ea48ffa..0cca5d9b8 100644 --- a/locales/external/fr.json +++ b/locales/external/fr.json @@ -1,42 +1,30 @@ { - "feed": { - "follower_one": "suivi", - "follower_other": "suivis", - "followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} avec {{readCount}} {{readNoun}} sur {{appName}}", - "read_one": "lecture", - "read_other": "lectures" - }, - "header": { - "app": "Application", - "download": "Télécharger" - }, - "invitation": { - "activate": "Activer", - "codeOptions": { - "1": "Cherchez un utilisateur de test alpha pour vous inviter.", - "2": "Rejoignez notre serveur Discord pour des cadeaux occasionnels.", - "3": "Suivez notre compte X pour des cadeaux occasionnels." - }, - "earlyAccess": "Follow est actuellement en accès anticipé et nécessite un code d'invitation pour être utilisé.", - "earlyAccessMessage": "😰 Désolé, Follow est actuellement en accès anticipé et nécessite un code d'invitation pour être utilisé.", - "generateButton": "Générer un nouveau code", - "generateCost": "Vous pouvez dépenser {{INVITATION_PRICE}} Power pour générer un code d'invitation pour vos amis.", - "getCodeMessage": "Vous pouvez obtenir un code d'invitation de la manière suivante :", - "title": "Code d'invitation" - }, - "login": { - "backToWebApp": "Retour à l'application web", - "continueWithGitHub": "Continuer avec GitHub", - "continueWithGoogle": "Continuer avec Google", - "logInTo": "Se connecter à", - "openApp": "Ouvrir l'application", - "redirecting": "Redirection", - "welcomeTo": "Bienvenue sur" - }, - "redirect": { - "continueInBrowser": "Continuer dans le navigateur", - "instruction": "Il est maintenant temps d'ouvrir {{APP_NAME}} et de fermer cette page en toute sécurité.", - "openApp": "Ouvrir {{APP_NAME}}", - "successMessage": "Vous vous êtes connecté avec succès à votre compte {{APP_NAME}}." - } + "feed.follower_one": "suivi", + "feed.follower_other": "suivis", + "feed.followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} avec {{readCount}} {{readNoun}} sur {{appName}}", + "feed.read_one": "lecture", + "feed.read_other": "lectures", + "header.app": "Application", + "header.download": "Télécharger", + "invitation.activate": "Activer", + "invitation.codeOptions.1": "Cherchez un utilisateur de test alpha pour vous inviter.", + "invitation.codeOptions.2": "Rejoignez notre serveur Discord pour des cadeaux occasionnels.", + "invitation.codeOptions.3": "Suivez notre compte X pour des cadeaux occasionnels.", + "invitation.earlyAccess": "Follow est actuellement en accès anticipé et nécessite un code d'invitation pour être utilisé.", + "invitation.earlyAccessMessage": "😰 Désolé, Follow est actuellement en accès anticipé et nécessite un code d'invitation pour être utilisé.", + "invitation.generateButton": "Générer un nouveau code", + "invitation.generateCost": "Vous pouvez dépenser {{INVITATION_PRICE}} Power pour générer un code d'invitation pour vos amis.", + "invitation.getCodeMessage": "Vous pouvez obtenir un code d'invitation de la manière suivante :", + "invitation.title": "Code d'invitation", + "login.backToWebApp": "Retour à l'application web", + "login.continueWithGitHub": "Continuer avec GitHub", + "login.continueWithGoogle": "Continuer avec Google", + "login.logInTo": "Se connecter à", + "login.openApp": "Ouvrir l'application", + "login.redirecting": "Redirection", + "login.welcomeTo": "Bienvenue sur", + "redirect.continueInBrowser": "Continuer dans le navigateur", + "redirect.instruction": "Il est maintenant temps d'ouvrir {{APP_NAME}} et de fermer cette page en toute sécurité.", + "redirect.openApp": "Ouvrir {{APP_NAME}}", + "redirect.successMessage": "Vous vous êtes connecté avec succès à votre compte {{APP_NAME}}." } diff --git a/locales/external/it.json b/locales/external/it.json index b57e20a50..d720e6133 100644 --- a/locales/external/it.json +++ b/locales/external/it.json @@ -1,42 +1,28 @@ { - "feed": { - "follow_one": "segui", - "follow_other": "seguono", - "followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} con {{readCount}} {{readNoun}} su {{appName}}", - "read_one": "letto", - "read_other": "letti" - }, - "header": { - "app": "App", - "download": "Scarica" - }, - "invitation": { - "activate": "Attiva", - "codeOptions": { - "1": "Cerca qualsiasi utente alpha test per invitarti.", - "2": "Unisciti al nostro server Discord per partecipare a estrazioni occasionali.", - "3": "Segui il nostro account X per partecipare a estrazioni occasionali." - }, - "earlyAccess": "Follow è attualmente in accesso anticipato e richiede un codice di invito per essere utilizzato.", - "earlyAccessMessage": "😰 Ci dispiace, Follow è attualmente in accesso anticipato e richiede un codice di invito per essere utilizzato.", - "generateButton": "Genera nuovo codice", - "generateCost": "Puoi spendere {{INVITATION_PRICE}} Power per generare un codice di invito per i tuoi amici.", - "getCodeMessage": "Puoi ottenere un codice di invito nei seguenti modi:", - "title": "Codice di Invito" - }, - "login": { - "backToWebApp": "Torna all'App Web", - "continueWithGitHub": "Continua con GitHub", - "continueWithGoogle": "Continua con Google", - "logInTo": "Accedi a", - "openApp": "Apri App", - "redirecting": "Reindirizzamento in corso", - "welcomeTo": "Benvenuto su" - }, - "redirect": { - "continueInBrowser": "Continua nel Browser", - "instruction": "Ora è il momento di aprire {{APP_NAME}} e chiudere in sicurezza questa pagina.", - "openApp": "Apri {{APP_NAME}}", - "successMessage": "Ti sei connesso con successo all'account {{APP_NAME}}." - } + "feed.followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} con {{readCount}} {{readNoun}} su {{appName}}", + "feed.read_one": "letto", + "feed.read_other": "letti", + "header.app": "App", + "header.download": "Scarica", + "invitation.activate": "Attiva", + "invitation.codeOptions.1": "Cerca qualsiasi utente alpha test per invitarti.", + "invitation.codeOptions.2": "Unisciti al nostro server Discord per partecipare a estrazioni occasionali.", + "invitation.codeOptions.3": "Segui il nostro account X per partecipare a estrazioni occasionali.", + "invitation.earlyAccess": "Follow è attualmente in accesso anticipato e richiede un codice di invito per essere utilizzato.", + "invitation.earlyAccessMessage": "😰 Ci dispiace, Follow è attualmente in accesso anticipato e richiede un codice di invito per essere utilizzato.", + "invitation.generateButton": "Genera nuovo codice", + "invitation.generateCost": "Puoi spendere {{INVITATION_PRICE}} Power per generare un codice di invito per i tuoi amici.", + "invitation.getCodeMessage": "Puoi ottenere un codice di invito nei seguenti modi:", + "invitation.title": "Codice di Invito", + "login.backToWebApp": "Torna all'App Web", + "login.continueWithGitHub": "Continua con GitHub", + "login.continueWithGoogle": "Continua con Google", + "login.logInTo": "Accedi a", + "login.openApp": "Apri App", + "login.redirecting": "Reindirizzamento in corso", + "login.welcomeTo": "Benvenuto su", + "redirect.continueInBrowser": "Continua nel Browser", + "redirect.instruction": "Ora è il momento di aprire {{APP_NAME}} e chiudere in sicurezza questa pagina.", + "redirect.openApp": "Apri {{APP_NAME}}", + "redirect.successMessage": "Ti sei connesso con successo all'account {{APP_NAME}}." } diff --git a/locales/external/ja.json b/locales/external/ja.json index 482dfdea2..839639fca 100644 --- a/locales/external/ja.json +++ b/locales/external/ja.json @@ -1,42 +1,30 @@ { - "feed": { - "follower_one": "フォロー", - "follower_other": "フォロー", - "followsAndReads": "{{appName}} で {{subscriptionCount}} {{subscriptionNoun}} と {{readCount}} {{readNoun}}", - "read_one": "読んだ", - "read_other": "既読" - }, - "header": { - "app": "アプリ", - "download": "ダウンロード" - }, - "invitation": { - "activate": "有効化", - "codeOptions": { - "1": "招待してくれるアルファテストユーザーを探しましょう。", - "2": "時折行われるプレゼント企画のために、私たちの Discord サーバーに参加しましょう。", - "3": "時折行われるプレゼント企画のために、私たちの X アカウントをフォローしましょう。" - }, - "earlyAccess": "現在、Follow はアーリーアクセス中で、利用には招待コードが必要です。", - "earlyAccessMessage": "😰 申し訳ありませんが、Follow は現在アーリーアクセス中で、招待コードが必要です。", - "generateButton": "新しいコードを生成", - "generateCost": "友達のために招待コードを生成するには、{{INVITATION_PRICE}} Power を消費できます。", - "getCodeMessage": "以下の方法で招待コードを入手できます:", - "title": "招待コード" - }, - "login": { - "backToWebApp": "ウェブアプリに戻る", - "continueWithGitHub": "GitHub で続行", - "continueWithGoogle": "Google で続行", - "logInTo": "ログイン ", - "openApp": "アプリを開く", - "redirecting": "リダイレクト中", - "welcomeTo": "ようこそ " - }, - "redirect": { - "continueInBrowser": "ブラウザで続行", - "instruction": "今が{{APP_NAME}}を開き、このページを安全に閉じる時です。", - "openApp": "{{APP_NAME}}を開く", - "successMessage": "{{APP_NAME}}アカウントに正常に接続されました。" - } + "feed.follower_one": "フォロー", + "feed.follower_other": "フォロー", + "feed.followsAndReads": "{{appName}} で {{subscriptionCount}} {{subscriptionNoun}} と {{readCount}} {{readNoun}}", + "feed.read_one": "読んだ", + "feed.read_other": "既読", + "header.app": "アプリ", + "header.download": "ダウンロード", + "invitation.activate": "有効化", + "invitation.codeOptions.1": "招待してくれるアルファテストユーザーを探しましょう。", + "invitation.codeOptions.2": "時折行われるプレゼント企画のために、私たちの Discord サーバーに参加しましょう。", + "invitation.codeOptions.3": "時折行われるプレゼント企画のために、私たちの X アカウントをフォローしましょう。", + "invitation.earlyAccess": "現在、Follow はアーリーアクセス中で、利用には招待コードが必要です。", + "invitation.earlyAccessMessage": "😰 申し訳ありませんが、Follow は現在アーリーアクセス中で、招待コードが必要です。", + "invitation.generateButton": "新しいコードを生成", + "invitation.generateCost": "友達のために招待コードを生成するには、{{INVITATION_PRICE}} Power を消費できます。", + "invitation.getCodeMessage": "以下の方法で招待コードを入手できます:", + "invitation.title": "招待コード", + "login.backToWebApp": "ウェブアプリに戻る", + "login.continueWithGitHub": "GitHub で続行", + "login.continueWithGoogle": "Google で続行", + "login.logInTo": "ログイン ", + "login.openApp": "アプリを開く", + "login.redirecting": "リダイレクト中", + "login.welcomeTo": "ようこそ ", + "redirect.continueInBrowser": "ブラウザで続行", + "redirect.instruction": "今が{{APP_NAME}}を開き、このページを安全に閉じる時です。", + "redirect.openApp": "{{APP_NAME}}を開く", + "redirect.successMessage": "{{APP_NAME}}アカウントに正常に接続されました。" } diff --git a/locales/external/pt.json b/locales/external/pt.json index 4613d598a..7f600bb93 100644 --- a/locales/external/pt.json +++ b/locales/external/pt.json @@ -1,42 +1,30 @@ { - "feed": { - "follower_one": "seguir", - "follower_other": "seguimentos", - "followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} com {{readCount}} {{readNoun}} no {{appName}}", - "read_one": "leitura", - "read_other": "leituras" - }, - "header": { - "app": "App", - "download": "Descarregar" - }, - "invitation": { - "activate": "Ativar", - "codeOptions": { - "1": "Procure um utilizador de teste alpha que o convide.", - "2": "Junte-se ao nosso servidor Discord para receber ofertas ocasionais.", - "3": "Siga a nossa conta no X para receber ofertas ocasionais." - }, - "earlyAccess": "O Follow está atualmente em acesso antecipado e requer um código de convite para ser utilizado.", - "earlyAccessMessage": "😰 Lamentamos, o Follow está atualmente em acesso antecipado e requer um código de convite.", - "generateButton": "Gerar novo código", - "generateCost": "Pode gastar {{INVITATION_PRICE}} Power para gerar um código de convite para os seus amigos.", - "getCodeMessage": "Pode obter um código de convite das seguintes maneiras:", - "title": "Código de Convite" - }, - "login": { - "backToWebApp": "Voltar à App Web", - "continueWithGitHub": "Continuar com GitHub", - "continueWithGoogle": "Continuar com Google", - "logInTo": "Iniciar sessão em ", - "openApp": "Abrir Aplicação", - "redirecting": "A redirecionar", - "welcomeTo": "Bem-vindo ao " - }, - "redirect": { - "continueInBrowser": "Continuar no Navegador", - "instruction": "Agora é o momento de abrir {{APP_NAME}} e fechar esta página com segurança.", - "openApp": "Abrir {{APP_NAME}}", - "successMessage": "Conectou-se com sucesso à conta {{APP_NAME}}." - } + "feed.follower_one": "seguir", + "feed.follower_other": "seguimentos", + "feed.followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} com {{readCount}} {{readNoun}} no {{appName}}", + "feed.read_one": "leitura", + "feed.read_other": "leituras", + "header.app": "App", + "header.download": "Descarregar", + "invitation.activate": "Ativar", + "invitation.codeOptions.1": "Procure um utilizador de teste alpha que o convide.", + "invitation.codeOptions.2": "Junte-se ao nosso servidor Discord para receber ofertas ocasionais.", + "invitation.codeOptions.3": "Siga a nossa conta no X para receber ofertas ocasionais.", + "invitation.earlyAccess": "O Follow está atualmente em acesso antecipado e requer um código de convite para ser utilizado.", + "invitation.earlyAccessMessage": "😰 Lamentamos, o Follow está atualmente em acesso antecipado e requer um código de convite.", + "invitation.generateButton": "Gerar novo código", + "invitation.generateCost": "Pode gastar {{INVITATION_PRICE}} Power para gerar um código de convite para os seus amigos.", + "invitation.getCodeMessage": "Pode obter um código de convite das seguintes maneiras:", + "invitation.title": "Código de Convite", + "login.backToWebApp": "Voltar à App Web", + "login.continueWithGitHub": "Continuar com GitHub", + "login.continueWithGoogle": "Continuar com Google", + "login.logInTo": "Iniciar sessão em ", + "login.openApp": "Abrir Aplicação", + "login.redirecting": "A redirecionar", + "login.welcomeTo": "Bem-vindo ao ", + "redirect.continueInBrowser": "Continuar no Navegador", + "redirect.instruction": "Agora é o momento de abrir {{APP_NAME}} e fechar esta página com segurança.", + "redirect.openApp": "Abrir {{APP_NAME}}", + "redirect.successMessage": "Conectou-se com sucesso à conta {{APP_NAME}}." } diff --git a/locales/external/ru.json b/locales/external/ru.json index 5bdf546a0..803f551da 100644 --- a/locales/external/ru.json +++ b/locales/external/ru.json @@ -1,42 +1,28 @@ { - "feed": { - "follow_one": "подписка", - "follow_other": "подписки", - "followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} с {{readCount}} {{readNoun}} на {{appName}}", - "read_one": "чтение", - "read_other": "чтений" - }, - "header": { - "app": "Приложение", - "download": "Скачать" - }, - "invitation": { - "activate": "Активировать", - "codeOptions": { - "1": "Ищите пользователей для приглашения на альфа-тестирование.", - "2": "Присоединяйтесь к нашему серверу Discord для участия в раздачах.", - "3": "Подпишитесь на наш аккаунт X для участия в раздачах." - }, - "earlyAccess": "В настоящее время Follow находится в раннем доступе и требует пригласительного кода для использования.", - "earlyAccessMessage": "😰 Извините, Follow находится в раннем доступе и требует пригласительного кода для использования.", - "generateButton": "Сгенерировать новый код", - "generateCost": "Вы можете потратить {{INVITATION_PRICE}} Power, чтобы сгенерировать пригласительный код для ваших друзей.", - "getCodeMessage": "Вы можете получить пригласительный код следующими способами:", - "title": "Пригласительный код" - }, - "login": { - "backToWebApp": "Вернуться к веб-приложению", - "continueWithGitHub": "Продолжить через GitHub", - "continueWithGoogle": "Продолжить через Google", - "logInTo": "Войти в ", - "openApp": "Открыть приложение", - "redirecting": "Перенаправление", - "welcomeTo": "Добро пожаловать в " - }, - "redirect": { - "continueInBrowser": "Продолжить в браузере", - "instruction": "Сейчас самое время открыть {{APP_NAME}} и безопасно закрыть эту страницу.", - "openApp": "Открыть {{APP_NAME}}", - "successMessage": "Вы успешно подключились к аккаунту {{APP_NAME}}." - } + "feed.followsAndReads": "{{subscriptionCount}} {{subscriptionNoun}} с {{readCount}} {{readNoun}} на {{appName}}", + "feed.read_one": "чтение", + "feed.read_other": "чтений", + "header.app": "Приложение", + "header.download": "Скачать", + "invitation.activate": "Активировать", + "invitation.codeOptions.1": "Ищите пользователей для приглашения на альфа-тестирование.", + "invitation.codeOptions.2": "Присоединяйтесь к нашему серверу Discord для участия в раздачах.", + "invitation.codeOptions.3": "Подпишитесь на наш аккаунт X для участия в раздачах.", + "invitation.earlyAccess": "В настоящее время Follow находится в раннем доступе и требует пригласительного кода для использования.", + "invitation.earlyAccessMessage": "😰 Извините, Follow находится в раннем доступе и требует пригласительного кода для использования.", + "invitation.generateButton": "Сгенерировать новый код", + "invitation.generateCost": "Вы можете потратить {{INVITATION_PRICE}} Power, чтобы сгенерировать пригласительный код для ваших друзей.", + "invitation.getCodeMessage": "Вы можете получить пригласительный код следующими способами:", + "invitation.title": "Пригласительный код", + "login.backToWebApp": "Вернуться к веб-приложению", + "login.continueWithGitHub": "Продолжить через GitHub", + "login.continueWithGoogle": "Продолжить через Google", + "login.logInTo": "Войти в ", + "login.openApp": "Открыть приложение", + "login.redirecting": "Перенаправление", + "login.welcomeTo": "Добро пожаловать в ", + "redirect.continueInBrowser": "Продолжить в браузере", + "redirect.instruction": "Сейчас самое время открыть {{APP_NAME}} и безопасно закрыть эту страницу.", + "redirect.openApp": "Открыть {{APP_NAME}}", + "redirect.successMessage": "Вы успешно подключились к аккаунту {{APP_NAME}}." } diff --git a/locales/external/tr.json b/locales/external/tr.json index f7fc56e1e..e6c9ee379 100644 --- a/locales/external/tr.json +++ b/locales/external/tr.json @@ -4,7 +4,6 @@ "feed.feeds_other": "besleme", "feed.follower_one": "takipçi", "feed.follower_other": "takipçi", - "feed.follower_to_view_all": "takipçi", "feed.followsAndFeeds": "{{subscriptionCount}} {{subscriptionNoun}} ve {{feedsCount}} {{feedsNoun}} {{appName}} üzerinde", "feed.followsAndReads": "{{appName}} üzerinde {{readCount}} {{readNoun}} ile {{subscriptionCount}} {{subscriptionNoun}}", "feed.read_one": "okuma", diff --git a/locales/lang/en.json b/locales/lang/en.json index a4495991e..6fef111da 100644 --- a/locales/lang/en.json +++ b/locales/lang/en.json @@ -5,6 +5,7 @@ "langs.ar-MA": "Arabic (Morocco)", "langs.ar-SA": "Arabic (Saudi Arabia)", "langs.ar-TN": "Arabic (Tunisia)", + "langs.de": "German", "langs.en": "English", "langs.es": "Spanish", "langs.fi": "Finnish", diff --git a/locales/shortcuts/ar-TN.json b/locales/shortcuts/ar-TN.json index e10cb0115..602f5affa 100644 --- a/locales/shortcuts/ar-TN.json +++ b/locales/shortcuts/ar-TN.json @@ -1,203 +1,24 @@ { - "about.changelog": "سجل التغييرات", - "about.feedbackInfo": "{{appName}} ({{commitSha}}) لا يزال في المراحل الأولى من التطوير. إذا كان لديك أي ملاحظات أو اقتراحات، لا تتردد في فتح تذكرة على GitHub الخاص بنا.", - "about.iconLibrary": "مكتبة الأيقونات المستخدمة محمية بحقوق الطبع والنشر بواسطة ولا يمكن إعادة توزيعها.", - "about.licenseInfo": "{{appName}} هو وسيظل دائمًا مشروعًا مجانيًا ومفتوح المصدر. تم ترخيصه بموجب {{license}}.", - "about.sidebar_title": "حول", - "about.socialMedia": "وسائل التواصل الاجتماعي", - "actions.actionName": "الإجراء {{number}}", - "actions.action_card.add": "إضافة", - "actions.action_card.all": "الكل", - "actions.action_card.block_rules": "قواعد الحظر", - "actions.action_card.custom_filters": "مرشحات مخصصة", - "actions.action_card.enable_readability": "تمكين إمكانية القراءة", - "actions.action_card.entry_options.all": "الكل", - "actions.action_card.entry_options.author": "المؤلف", - "actions.action_card.entry_options.content": "المحتوى", - "actions.action_card.entry_options.order": "الترتيب", - "actions.action_card.entry_options.title": "العنوان", - "actions.action_card.entry_options.url": "الرابط", - "actions.action_card.feed_options.category": "الفئة", - "actions.action_card.feed_options.feed_url": "رابط التغذية", - "actions.action_card.feed_options.site_url": "رابط الموقع", - "actions.action_card.feed_options.title": "العنوان", - "actions.action_card.feed_options.view": "عرض", - "actions.action_card.field": "الحقل", - "actions.action_card.from": "من", - "actions.action_card.generate_summary": "توليد ملخص باستخدام الذكاء الاصطناعي", - "actions.action_card.name": "الاسم", - "actions.action_card.operation_options.contains": "يحتوي على", - "actions.action_card.operation_options.does_not_contain": "لا يحتوي على", - "actions.action_card.operation_options.is_equal_to": "يساوي", - "actions.action_card.operation_options.is_greater_than": "أكبر من", - "actions.action_card.operation_options.is_less_than": "أقل من", - "actions.action_card.operation_options.is_not_equal_to": "ليس مساويًا لـ", - "actions.action_card.operation_options.matches_regex": "يطابق التعبير النمطي", - "actions.action_card.operator": "المشغل", - "actions.action_card.rewrite_rules": "إعادة كتابة القواعد", - "actions.action_card.then_do": "ثم قم بـ...", - "actions.action_card.to": "إلى", - "actions.action_card.translate_into": "ترجمة إلى", - "actions.action_card.value": "القيمة", - "actions.action_card.when_feeds_match": "عند مطابقة التغذيات...", - "actions.newRule": "قاعدة جديدة", - "actions.save": "حفظ", - "actions.saveSuccess": "🎉 تم حفظ الإجراءات.", - "actions.sidebar_title": "الإجراءات", - "actions.title": "الإجراءات", - "appearance.code_highlight_theme": "سمة تمييز الشيفرة", - "appearance.content": "المحتوى", - "appearance.content_font": "خط المحتوى", - "appearance.custom_font": "خط مخصص", - "appearance.fonts": "الخطوط", - "appearance.general": "عام", - "appearance.guess_code_language.description": "لغات البرمجة الرئيسية التي تستخدم النماذج لاستنتاج كتل الشيفرة غير المسماة", - "appearance.guess_code_language.label": "تخمين لغة الشيفرة", - "appearance.misc": "متنوع", - "appearance.modal_overlay.description": "عرض تراكب النافذة المنبثقة", - "appearance.modal_overlay.label": "عرض تراكب النافذة المنبثقة", - "appearance.opaque_sidebars.label": "أشرطة جانبية معتمة", - "appearance.reader_render_inline_style.description": "يسمح بعرض النمط المضمّن في HTML الأصلي.", - "appearance.reader_render_inline_style.label": "عرض النمط المضمّن", - "appearance.reduce_motion.description": "تقليل حركة العناصر لتحسين الأداء وتقليل استهلاك الطاقة", - "appearance.reduce_motion.label": "تقليل الحركة", - "appearance.save": "حفظ", - "appearance.show_dock_badge.label": "إظهار كشارة في Dock", - "appearance.sidebar_show_unread_count.label": "عرض في الشريط الجانبي", - "appearance.sidebar_title": "المظهر", - "appearance.text_size": "حجم النص", - "appearance.theme.dark": "داكن", - "appearance.theme.label": "السمة", - "appearance.theme.light": "فاتح", - "appearance.theme.system": "النظام", - "appearance.title": "المظهر", - "appearance.ui_font": "خط واجهة المستخدم", - "appearance.unread_count": "عدد العناصر غير المقروءة", - "feeds.claimTips": "للمطالبة بتغذياتك واستلام الإكراميات، انقر بزر الماوس الأيمن على التغذية في قائمة اشتراكاتك واختر المطالبة.", - "feeds.noFeeds": "لا توجد تغذيات مطالبة", - "feeds.tableHeaders.entryCount": "العناصر", - "feeds.tableHeaders.name": "الاسم", - "feeds.tableHeaders.subscriptionCount": "الاشتراكات", - "feeds.tableHeaders.tipAmount": "الإكراميات المستلمة", - "general.app": "التطبيق", - "general.data_persist.description": "الاحتفاظ بالبيانات محليًا لتمكين الوصول دون اتصال والبحث المحلي.", - "general.data_persist.label": "الاحتفاظ بالبيانات للاستخدام دون اتصال", - "general.group_by_date.description": "تجميع العناصر حسب التاريخ.", - "general.group_by_date.label": "تجميع حسب التاريخ", - "general.language": "اللغة", - "general.launch_at_login": "التشغيل عند تسجيل الدخول", - "general.mark_as_read.hover.description": "تحديد العناصر تلقائيًا كمقروءة عند التمرير فوقها.", - "general.mark_as_read.hover.label": "تحديد كمقروء عند التمرير", - "general.mark_as_read.render.description": "تحديد العناصر أحادية المستوى (مثل منشورات الوسائط الاجتماعية، والصور، وعروض الفيديو) تلقائيًا كمقروءة عند دخولها العرض.", - "general.mark_as_read.render.label": "تحديد كمقروء عند العرض", - "general.mark_as_read.scroll.description": "تحديد العناصر تلقائيًا كمقروءة عند التمرير خارج العرض.", - "general.mark_as_read.scroll.label": "تحديد كمقروء عند التمرير", - "general.privacy_data": "الخصوصية والبيانات", - "general.rebuild_database.button": "إعادة بناء", - "general.rebuild_database.description": "إذا كنت تواجه مشكلات في العرض، فقد يحل إعادة بناء قاعدة البيانات هذه المشكلات.", - "general.rebuild_database.label": "إعادة بناء قاعدة البيانات", - "general.rebuild_database.title": "إعادة بناء قاعدة البيانات", - "general.rebuild_database.warning.line1": "ستؤدي إعادة بناء قاعدة البيانات إلى مسح جميع بياناتك المحلية.", - "general.rebuild_database.warning.line2": "هل أنت متأكد أنك تريد المتابعة؟", - "general.send_anonymous_data.description": "من خلال اختيار إرسال بيانات عن بعد مجهولة، فإنك تساهم في تحسين تجربة المستخدم العامة لـ Follow.", - "general.send_anonymous_data.label": "إرسال بيانات مجهولة", - "general.show_unread_on_launch.description": "عرض المحتوى غير المقروء عند الإطلاق", - "general.show_unread_on_launch.label": "عرض المحتوى غير المقروء عند الإطلاق", - "general.sidebar_title": "عام", - "general.timeline": "الجدول الزمني", - "general.unread": "غير مقروء", - "general.voices": "الأصوات", - "integration.eagle.enable.description": "عرض زر 'حفظ الوسائط إلى Eagle' عندما يكون متاحًا.", - "integration.eagle.enable.label": "تمكين", - "integration.eagle.title": "Eagle", - "integration.instapaper.enable.description": "عرض زر 'حفظ إلى Instapaper' عندما يكون متاحًا.", - "integration.instapaper.enable.label": "تمكين", - "integration.instapaper.password.label": "كلمة مرور Instapaper", - "integration.instapaper.title": "Instapaper", - "integration.instapaper.username.label": "اسم مستخدم Instapaper", - "integration.readwise.enable.description": "عرض زر 'حفظ إلى Readwise' عندما يكون متاحًا.", - "integration.readwise.enable.label": "تمكين", - "integration.readwise.title": "Readwise", - "integration.readwise.token.description": "يمكنك الحصول عليه هنا: readwise.io/access_token.", - "integration.readwise.token.label": "رمز الوصول لـ Readwise", - "integration.sidebar_title": "التكامل", - "integration.tip": "نصيحة: يتم تخزين بياناتك الحساسة محليًا ولا يتم تحميلها إلى الخادم.", - "integration.title": "التكامل", - "invitation.activate": "تفعيل", - "invitation.codeOptions.betaUser": "1. ابحث عن مستخدم بيتا لدعوتك.", - "invitation.codeOptions.discord": "2. انضم إلى خادم Discord الخاص بنا واحصل على هدايا عرضية.", - "invitation.codeOptions.xAccount": "3. تابع حسابنا على X واحصل على هدايا من وقت لآخر.", - "invitation.confirmModal.cancel": "إلغاء", - "invitation.confirmModal.confirm": "هل تريد المتابعة؟", - "invitation.confirmModal.continue": "متابعة", - "invitation.confirmModal.message": "سيكلفك إنشاء رمز دعوة {{INVITATION_PRICE}} من Power.", - "invitation.confirmModal.title": "تأكيد", - "invitation.earlyAccess": "Follow حاليًا في الوصول المبكر ويتطلب رمز دعوة للاستخدام.", - "invitation.earlyAccessMessage": "😰 عذرًا، Follow حاليًا في مرحلة الوصول المبكر ويتطلب رمز دعوة للاستخدام.", - "invitation.generateButton": "إنشاء رمز جديد", - "invitation.generateCost": "يمكنك إنفاق {{INVITATION_PRICE}} من Power لإنشاء رمز دعوة لأصدقائك.", - "invitation.getCodeMessage": "يمكنك الحصول على رمز دعوة من خلال الطرق التالية:", - "invitation.limitationMessage": "بناءً على وقت استخدامك، يمكنك إنشاء ما يصل إلى {{limitation}} من رموز الدعوات.", - "invitation.newInvitationSuccess": "🎉 تم إنشاء دعوة جديدة، وتم نسخ رمز الدعوة", - "invitation.noInvitations": "لا توجد دعوات", - "invitation.notUsed": "لم يُستخدم", - "invitation.sidebar_title": "الدعوات", - "invitation.tableHeaders.code": "الرمز", - "invitation.tableHeaders.creationTime": "وقت الإنشاء", - "invitation.tableHeaders.usedBy": "استخدمه", - "invitation.title": "رمز الدعوة", - "profile.avatar.label": "الصورة الرمزية", - "profile.handle.description": "معرفك الفريد.", - "profile.handle.label": "المعرف", - "profile.name.description": "اسم العرض العام الخاص بك.", - "profile.name.label": "اسم العرض", - "profile.sidebar_title": "الملف الشخصي", - "profile.submit": "إرسال", - "profile.title": "إعدادات الملف الشخصي", - "profile.updateSuccess": "تم تحديث الملف الشخصي.", - "titles.about": "حول", - "titles.actions": "الإجراءات", - "titles.appearance": "المظهر", - "titles.feeds": "التغذيات", - "titles.general": "عام", - "titles.integration": "التكامل", - "titles.invitations": "الدعوات", - "titles.power": "الطاقة", - "titles.profile": "الملف الشخصي", - "titles.shortcuts": "الاختصارات", - "wallet.address.title": "عنوانك", - "wallet.balance.title": "رصيدك", - "wallet.balance.withdrawable": "قابل للسحب", - "wallet.balance.withdrawableTooltip": "تشمل الطاقة القابلة للسحب كلًا من الإكراميات التي تلقيتها والطاقة التي قمت بشحنها.", - "wallet.claim.button.claim": "استلام الطاقة اليومية", - "wallet.claim.button.claimed": "تم استلام الطاقة اليوم", - "wallet.claim.tooltip.alreadyClaimed": "لقد استلمت بالفعل اليوم.", - "wallet.claim.tooltip.canClaim": "استلم {{amount}} من الطاقة اليومية الآن!", - "wallet.create.button": "إنشاء محفظة", - "wallet.create.description": "أنشئ محفظة مجانية لاستلام Power، والتي يمكن استخدامها لمكافأة المبدعين وأيضًا الحصول على مكافآت مقابل مساهماتك في المحتوى.", - "wallet.power.dailyClaim": "يمكنك استلام {{amount}} من الطاقة المجانية يوميًا، والتي يمكن استخدامها لإكراميات عناصر RSS على Follow.", - "wallet.power.description": "Power هو رمز ERC-20 على سلسلة البلوكشين {{blockchainName}}.", - "wallet.sidebar_title": "الطاقة", - "wallet.transactions.amount": "المبلغ", - "wallet.transactions.date": "التاريخ", - "wallet.transactions.from": "من", - "wallet.transactions.noTransactions": "لا توجد معاملات", - "wallet.transactions.title": "المعاملات", - "wallet.transactions.to": "إلى", - "wallet.transactions.tx": "Tx", - "wallet.transactions.type": "النوع", - "wallet.transactions.types.burn": "حرق", - "wallet.transactions.types.mint": "سك", - "wallet.transactions.types.purchase": "شراء", - "wallet.transactions.types.tip": "إكرامية", - "wallet.transactions.types.withdraw": "سحب", - "wallet.transactions.you": "أنت", - "wallet.withdraw.addressLabel": "عنوان Ethereum الخاص بك", - "wallet.withdraw.amountLabel": "المبلغ", - "wallet.withdraw.availableBalance": "لديك من الطاقة القابلة للسحب في محفظتك.", - "wallet.withdraw.button": "سحب", - "wallet.withdraw.error": "فشل السحب: {{error}}", - "wallet.withdraw.modalTitle": "سحب الطاقة", - "wallet.withdraw.submitButton": "إرسال", - "wallet.withdraw.success": "تم السحب بنجاح!" + "keys.audio.playPause": "تشغيل/إيقاف مؤقت (عندما يكون مشغل الصوت مفتوحًا)", + "keys.entries.markAllAsRead": "وضع علامة على الكل كمقروء", + "keys.entries.next": "الإدخال التالي", + "keys.entries.previous": "الإدخال السابق", + "keys.entries.refetch": "إعادة التحميل", + "keys.entries.toggleUnreadOnly": "تبديل إلى غير المقروء فقط", + "keys.entry.copyLink": "نسخ الرابط", + "keys.entry.openInBrowser": "فتح في المتصفح", + "keys.entry.openInNewTab": "فتح في علامة تبويب جديدة", + "keys.entry.scrollDown": "التمرير لأسفل", + "keys.entry.scrollUp": "التمرير لأعلى", + "keys.entry.share": "مشاركة", + "keys.entry.tip": "إكرامية الطاقة", + "keys.entry.toggleRead": "تبديل حالة القراءة", + "keys.entry.toggleStarred": "تبديل التفضيل", + "keys.entry.tts": "تشغيل النص إلى كلام", + "keys.feeds.add": "إضافة اشتراك", + "keys.feeds.switchBetweenViews": "التبديل بين طرق العرض", + "keys.feeds.switchToView": "التبديل إلى العرض", + "keys.layout.showShortcuts": "إظهار/إخفاء الاختصارات", + "keys.layout.toggleSidebar": "إظهار/إخفاء الشريط الجانبي للتغذية", + "sidebar_title": "الاختصارات" } diff --git a/package.json b/package.json index c36b42e74..ee783eea7 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "electron-packager-languages": "0.5.0", "electron-vite": "^2.3.0", "eslint": "^9.11.1", - "eslint-config-hyoban": "^3.1.7", + "eslint-config-hyoban": "^3.1.8", "fake-indexeddb": "6.0.0", "hono": "4.6.3", "lint-staged": "15.2.10", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c1bcce26c..2fb1bfa82 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -150,8 +150,8 @@ importers: specifier: ^9.11.1 version: 9.11.1(jiti@2.0.0) eslint-config-hyoban: - specifier: ^3.1.7 - version: 3.1.7(@typescript-eslint/eslint-plugin@8.7.0(@typescript-eslint/parser@8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2))(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2))(eslint@9.11.1(jiti@2.0.0))(tailwindcss@3.4.13)(typescript@5.6.2) + specifier: ^3.1.8 + version: 3.1.8(@typescript-eslint/eslint-plugin@8.7.0(@typescript-eslint/parser@8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2))(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2))(eslint@9.11.1(jiti@2.0.0))(tailwindcss@3.4.13)(typescript@5.6.2) fake-indexeddb: specifier: 6.0.0 version: 6.0.0 @@ -217,7 +217,7 @@ importers: version: 5.0.1(typescript@5.6.2)(vite@5.4.8(@types/node@22.7.4)(terser@5.34.1)) vitest: specifier: '2.0' - version: 2.0.5(@types/node@22.7.4)(terser@5.34.1) + version: 2.1.1(@types/node@22.7.4)(terser@5.34.1) apps/main: dependencies: @@ -617,7 +617,7 @@ importers: version: 3.23.8 zustand: specifier: 4.5.5 - version: 4.5.5(@types/react@18.3.10)(immer@10.1.1(patch_hash=og7mbnoo5vh43tjlw5rbmrdbvu))(react@18.3.1) + version: 5.0.0-rc.2(@types/react@18.3.10)(immer@10.1.1(patch_hash=og7mbnoo5vh43tjlw5rbmrdbvu))(react@18.3.1)(use-sync-external-store@1.2.2(react@18.3.1)) devDependencies: '@babel/generator': specifier: 7.25.6 @@ -3753,26 +3753,35 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 - '@vitest/expect@2.0.5': - resolution: {integrity: sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA==} + '@vitest/expect@2.1.1': + resolution: {integrity: sha512-YeueunS0HiHiQxk+KEOnq/QMzlUuOzbU1Go+PgAsHvvv3tUkJPm9xWt+6ITNTlzsMXUjmgm5T+U7KBPK2qQV6w==} - '@vitest/pretty-format@2.0.5': - resolution: {integrity: sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ==} + '@vitest/mocker@2.1.1': + resolution: {integrity: sha512-LNN5VwOEdJqCmJ/2XJBywB11DLlkbY0ooDJW3uRX5cZyYCrc4PI/ePX0iQhE3BiEGiQmK4GE7Q/PqCkkaiPnrA==} + peerDependencies: + '@vitest/spy': 2.1.1 + msw: ^2.3.5 + vite: ^5.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true '@vitest/pretty-format@2.1.1': resolution: {integrity: sha512-SjxPFOtuINDUW8/UkElJYQSFtnWX7tMksSGW0vfjxMneFqxVr8YJ979QpMbDW7g+BIiq88RAGDjf7en6rvLPPQ==} - '@vitest/runner@2.0.5': - resolution: {integrity: sha512-TfRfZa6Bkk9ky4tW0z20WKXFEwwvWhRY+84CnSEtq4+3ZvDlJyY32oNTJtM7AW9ihW90tX/1Q78cb6FjoAs+ig==} + '@vitest/runner@2.1.1': + resolution: {integrity: sha512-uTPuY6PWOYitIkLPidaY5L3t0JJITdGTSwBtwMjKzo5O6RCOEncz9PUN+0pDidX8kTHYjO0EwUIvhlGpnGpxmA==} - '@vitest/snapshot@2.0.5': - resolution: {integrity: sha512-SgCPUeDFLaM0mIUHfaArq8fD2WbaXG/zVXjRupthYfYGzc8ztbFbu6dUNOblBG7XLMR1kEhS/DNnfCZ2IhdDew==} + '@vitest/snapshot@2.1.1': + resolution: {integrity: sha512-BnSku1WFy7r4mm96ha2FzN99AZJgpZOWrAhtQfoxjUU5YMRpq1zmHRq7a5K9/NjqonebO7iVDla+VvZS8BOWMw==} - '@vitest/spy@2.0.5': - resolution: {integrity: sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA==} + '@vitest/spy@2.1.1': + resolution: {integrity: sha512-ZM39BnZ9t/xZ/nF4UwRH5il0Sw93QnZXd9NAZGRpIgj0yvVwPpLd702s/Cx955rGaMlyBQkZJ2Ir7qyY48VZ+g==} - '@vitest/utils@2.0.5': - resolution: {integrity: sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ==} + '@vitest/utils@2.1.1': + resolution: {integrity: sha512-Y6Q9TsI+qJ2CC0ZKj6VBb+T8UPz593N113nnUykqwANqhgf3QkZeHFlusgKLTqrnVHbj/XDKZcDHol+dxVT+rQ==} '@vscode/vscode-languagedetection@1.0.22': resolution: {integrity: sha512-rQ/BgMyLuIXSmbA0MSkIPHtcOw14QkeDbAq19sjvaS9LTRr905yij0S8lsyqN5JgOsbtIx7pAcyOxFMzPmqhZQ==} @@ -5028,8 +5037,8 @@ packages: peerDependencies: eslint: ^9.5.0 - eslint-config-hyoban@3.1.7: - resolution: {integrity: sha512-35r1FdI9lfa5aowbaDidpjsRcDn8HO+8/RhtcfFblkc30DqQkyxPmgAxY1ohn8NSzEUdLqzfyqIBlK2E9bOfmw==} + eslint-config-hyoban@3.1.8: + resolution: {integrity: sha512-YRvuuQgzzrNw8+2Xmqbdrvx4BYeG06HeeU4AvAm5OBq5x31ShWY1s3Zu7AVVIoLGJCbDNECq8ViLtdS6yJtWug==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^9.0.0 @@ -8584,8 +8593,8 @@ packages: vite-bundle-analyzer@0.12.1: resolution: {integrity: sha512-mIYwsDvTYCqXAUtOZIL3f7NdwWUeL/MlNFhOJzlTdcZE4pye6h06IEnOvWhnc/e+HM4oVVNxuRHZt0Rz6VO7EA==} - vite-node@2.0.5: - resolution: {integrity: sha512-LdsW4pxj0Ot69FAoXZ1yTnA9bjGohr2yNBU7QKRxpz8ITSkhuDl6h3zS/tvgz4qrNjeRnvrWeXQ8ZF7Um4W00Q==} + vite-node@2.1.1: + resolution: {integrity: sha512-N/mGckI1suG/5wQI35XeR9rsMsPqKXzq1CdUndzVstBj/HvyxxGctwnK6WX43NGt5L3Z5tcRf83g4TITKJhPrA==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true @@ -8634,15 +8643,15 @@ packages: terser: optional: true - vitest@2.0.5: - resolution: {integrity: sha512-8GUxONfauuIdeSl5f9GTgVEpg5BTOlplET4WEDaeY2QBiN8wSm68vxN/tb5z405OwppfoCavnwXafiaYBC/xOA==} + vitest@2.1.1: + resolution: {integrity: sha512-97We7/VC0e9X5zBVkvt7SGQMGrRtn3KtySFQG5fpaMlS+l62eeXRQO633AYhSTC3z7IMebnPPNjGXVGNRFlxBA==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@types/node': ^18.0.0 || >=20.0.0 - '@vitest/browser': 2.0.5 - '@vitest/ui': 2.0.5 + '@vitest/browser': 2.1.1 + '@vitest/ui': 2.1.1 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -8813,13 +8822,14 @@ packages: zod@3.23.8: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} - zustand@4.5.5: - resolution: {integrity: sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==} - engines: {node: '>=12.7.0'} + zustand@5.0.0-rc.2: + resolution: {integrity: sha512-o2Nwuvnk8vQBX7CcHL8WfFkZNJdxB/VKeWw0tNglw8p4cypsZ3tRT7rTRTDNeUPFS0qaMBRSKe+fVwL5xpcE3A==} + engines: {node: '>=12.20.0'} peerDependencies: - '@types/react': '>=16.8' + '@types/react': '>=18.0.0' immer: '>=9.0.6' - react: '>=16.8' + react: '>=18.0.0' + use-sync-external-store: '>=1.2.0' peerDependenciesMeta: '@types/react': optional: true @@ -8827,6 +8837,8 @@ packages: optional: true react: optional: true + use-sync-external-store: + optional: true zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -12604,40 +12616,43 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitest/expect@2.0.5': + '@vitest/expect@2.1.1': dependencies: - '@vitest/spy': 2.0.5 - '@vitest/utils': 2.0.5 + '@vitest/spy': 2.1.1 + '@vitest/utils': 2.1.1 chai: 5.1.1 tinyrainbow: 1.2.0 - '@vitest/pretty-format@2.0.5': + '@vitest/mocker@2.1.1(@vitest/spy@2.1.1)(vite@5.4.8(@types/node@22.7.4)(terser@5.34.1))': dependencies: - tinyrainbow: 1.2.0 + '@vitest/spy': 2.1.1 + estree-walker: 3.0.3 + magic-string: 0.30.11 + optionalDependencies: + vite: 5.4.8(@types/node@22.7.4)(terser@5.34.1) '@vitest/pretty-format@2.1.1': dependencies: tinyrainbow: 1.2.0 - '@vitest/runner@2.0.5': + '@vitest/runner@2.1.1': dependencies: - '@vitest/utils': 2.0.5 + '@vitest/utils': 2.1.1 pathe: 1.1.2 - '@vitest/snapshot@2.0.5': + '@vitest/snapshot@2.1.1': dependencies: - '@vitest/pretty-format': 2.0.5 + '@vitest/pretty-format': 2.1.1 magic-string: 0.30.11 pathe: 1.1.2 - '@vitest/spy@2.0.5': + '@vitest/spy@2.1.1': dependencies: tinyspy: 3.0.2 - '@vitest/utils@2.0.5': + '@vitest/utils@2.1.1': dependencies: - '@vitest/pretty-format': 2.0.5 - estree-walker: 3.0.3 + '@vitest/pretty-format': 2.1.1 loupe: 3.1.1 tinyrainbow: 1.2.0 @@ -14131,7 +14146,7 @@ snapshots: eslint: 9.11.1(jiti@2.0.0) find-up-simple: 1.0.0 - eslint-config-hyoban@3.1.7(@typescript-eslint/eslint-plugin@8.7.0(@typescript-eslint/parser@8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2))(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2))(eslint@9.11.1(jiti@2.0.0))(tailwindcss@3.4.13)(typescript@5.6.2): + eslint-config-hyoban@3.1.8(@typescript-eslint/eslint-plugin@8.7.0(@typescript-eslint/parser@8.7.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2))(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2))(eslint@9.11.1(jiti@2.0.0))(tailwindcss@3.4.13)(typescript@5.6.2): dependencies: '@eslint-react/eslint-plugin': 1.14.2(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) '@eslint/js': 9.11.1 @@ -18292,6 +18307,7 @@ snapshots: use-sync-external-store@1.2.2(react@18.3.1): dependencies: react: 18.3.1 + optional: true usehooks-ts@3.1.0(react@18.3.1): dependencies: @@ -18343,12 +18359,11 @@ snapshots: vite-bundle-analyzer@0.12.1: {} - vite-node@2.0.5(@types/node@22.7.4)(terser@5.34.1): + vite-node@2.1.1(@types/node@22.7.4)(terser@5.34.1): dependencies: cac: 6.7.14 debug: 4.3.7 pathe: 1.1.2 - tinyrainbow: 1.2.0 vite: 5.4.8(@types/node@22.7.4)(terser@5.34.1) transitivePeerDependencies: - '@types/node' @@ -18392,32 +18407,33 @@ snapshots: fsevents: 2.3.3 terser: 5.34.1 - vitest@2.0.5(@types/node@22.7.4)(terser@5.34.1): + vitest@2.1.1(@types/node@22.7.4)(terser@5.34.1): dependencies: - '@ampproject/remapping': 2.3.0 - '@vitest/expect': 2.0.5 + '@vitest/expect': 2.1.1 + '@vitest/mocker': 2.1.1(@vitest/spy@2.1.1)(vite@5.4.8(@types/node@22.7.4)(terser@5.34.1)) '@vitest/pretty-format': 2.1.1 - '@vitest/runner': 2.0.5 - '@vitest/snapshot': 2.0.5 - '@vitest/spy': 2.0.5 - '@vitest/utils': 2.0.5 + '@vitest/runner': 2.1.1 + '@vitest/snapshot': 2.1.1 + '@vitest/spy': 2.1.1 + '@vitest/utils': 2.1.1 chai: 5.1.1 debug: 4.3.7 - execa: 8.0.1 magic-string: 0.30.11 pathe: 1.1.2 std-env: 3.7.0 tinybench: 2.9.0 + tinyexec: 0.3.0 tinypool: 1.0.1 tinyrainbow: 1.2.0 vite: 5.4.8(@types/node@22.7.4)(terser@5.34.1) - vite-node: 2.0.5(@types/node@22.7.4)(terser@5.34.1) + vite-node: 2.1.1(@types/node@22.7.4)(terser@5.34.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.7.4 transitivePeerDependencies: - less - lightningcss + - msw - sass - sass-embedded - stylus @@ -18558,12 +18574,11 @@ snapshots: zod@3.23.8: {} - zustand@4.5.5(@types/react@18.3.10)(immer@10.1.1(patch_hash=og7mbnoo5vh43tjlw5rbmrdbvu))(react@18.3.1): - dependencies: - use-sync-external-store: 1.2.2(react@18.3.1) + zustand@5.0.0-rc.2(@types/react@18.3.10)(immer@10.1.1(patch_hash=og7mbnoo5vh43tjlw5rbmrdbvu))(react@18.3.1)(use-sync-external-store@1.2.2(react@18.3.1)): optionalDependencies: '@types/react': 18.3.10 immer: 10.1.1(patch_hash=og7mbnoo5vh43tjlw5rbmrdbvu) react: 18.3.1 + use-sync-external-store: 1.2.2(react@18.3.1) zwitch@2.0.4: {} From 4eb47d42168b1002a63b0fd16570d564800ca823 Mon Sep 17 00:00:00 2001 From: Innei Date: Sat, 28 Sep 2024 15:30:39 +0800 Subject: [PATCH 11/88] chore(plugin): add autofix for i18n json Signed-off-by: Innei --- plugins/eslint-check-i18n-json.js | 11 ++++++++++- plugins/eslint-recursive-sort.js | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/plugins/eslint-check-i18n-json.js b/plugins/eslint-check-i18n-json.js index af98d8a82..fccdbe1c0 100644 --- a/plugins/eslint-check-i18n-json.js +++ b/plugins/eslint-check-i18n-json.js @@ -71,7 +71,7 @@ export default { category: "Possible Errors", recommended: true, }, - fixable: null, + fixable: "code", // 将 fixable 设置为 "code" }, create(context) { return { @@ -109,6 +109,15 @@ export default { context.report({ node, message: `Key "${key}" is present in ${lang}.json but not in en.json for namespace "${namespace}"`, + fix(fixer) { + const newJson = Object.fromEntries( + Object.entries(currentJson).filter(([k]) => !extraKeys.includes(k)), + ) + + const newText = `${JSON.stringify(newJson, null, 2)}\n` + + return fixer.replaceText(node, newText) + }, }) } }, diff --git a/plugins/eslint-recursive-sort.js b/plugins/eslint-recursive-sort.js index 113a070a3..924cbff62 100644 --- a/plugins/eslint-recursive-sort.js +++ b/plugins/eslint-recursive-sort.js @@ -34,7 +34,7 @@ export default { try { const json = JSON.parse(text) const sortedJson = sortObjectKeys(json) - const sortedText = JSON.stringify(sortedJson, null, 2) + const sortedText = `${JSON.stringify(sortedJson, null, 2)}\n` if (text.trim() !== sortedText.trim()) { context.report({ From 2f15900b087f1a0a511f82e559eae617dc2faf32 Mon Sep 17 00:00:00 2001 From: Innei Date: Sat, 28 Sep 2024 15:49:09 +0800 Subject: [PATCH 12/88] fix: downgrade vitest Signed-off-by: Innei --- apps/renderer/package.json | 3 +- apps/renderer/src/modules/profile/hooks.ts | 10 +- pnpm-lock.yaml | 122 ++++++++++----------- 3 files changed, 63 insertions(+), 72 deletions(-) diff --git a/apps/renderer/package.json b/apps/renderer/package.json index 500e6bfb3..c23bf9964 100644 --- a/apps/renderer/package.json +++ b/apps/renderer/package.json @@ -119,6 +119,7 @@ "fake-indexeddb": "6.0.0", "react": "^18.3.1", "react-dom": "^18.3.1", - "typescript": "^5.6.2" + "typescript": "^5.6.2", + "vitest": "2.0" } } diff --git a/apps/renderer/src/modules/profile/hooks.ts b/apps/renderer/src/modules/profile/hooks.ts index 5926d73ff..434f497c7 100644 --- a/apps/renderer/src/modules/profile/hooks.ts +++ b/apps/renderer/src/modules/profile/hooks.ts @@ -49,18 +49,20 @@ export const usePresentUserProfileModal = (variant: Variant = "dialog") => { return useCallback( (userId: string | undefined, overrideVariant?: Variant) => { if (!userId) return + const finalVariant = overrideVariant || variant present({ title: "User Profile", content: () => createElement(UserProfileModalContent, { userId, - variant: overrideVariant || variant, + variant: finalVariant, }), CustomModalComponent: PlainModal, clickOutsideToDismiss: true, - modal: variant === "dialog", - overlay: variant === "dialog", - modalContainerClassName: variant === "drawer" ? "right-4 left-[auto] top-4 bottom-4" : "", + modal: finalVariant === "dialog", + overlay: finalVariant === "dialog", + modalContainerClassName: + finalVariant === "drawer" ? "right-4 left-[auto] top-4 bottom-4" : "", }) }, [present, variant], diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2fb1bfa82..68519771c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -217,7 +217,7 @@ importers: version: 5.0.1(typescript@5.6.2)(vite@5.4.8(@types/node@22.7.4)(terser@5.34.1)) vitest: specifier: '2.0' - version: 2.1.1(@types/node@22.7.4)(terser@5.34.1) + version: 2.0.5(@types/node@22.7.4)(terser@5.34.1) apps/main: dependencies: @@ -617,7 +617,7 @@ importers: version: 3.23.8 zustand: specifier: 4.5.5 - version: 5.0.0-rc.2(@types/react@18.3.10)(immer@10.1.1(patch_hash=og7mbnoo5vh43tjlw5rbmrdbvu))(react@18.3.1)(use-sync-external-store@1.2.2(react@18.3.1)) + version: 4.5.5(@types/react@18.3.10)(immer@10.1.1(patch_hash=og7mbnoo5vh43tjlw5rbmrdbvu))(react@18.3.1) devDependencies: '@babel/generator': specifier: 7.25.6 @@ -649,6 +649,9 @@ importers: typescript: specifier: ^5.6.2 version: 5.6.2 + vitest: + specifier: '2.0' + version: 2.0.5(@types/node@22.7.4)(terser@5.34.1) packages/shared: dependencies: @@ -3753,35 +3756,26 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 - '@vitest/expect@2.1.1': - resolution: {integrity: sha512-YeueunS0HiHiQxk+KEOnq/QMzlUuOzbU1Go+PgAsHvvv3tUkJPm9xWt+6ITNTlzsMXUjmgm5T+U7KBPK2qQV6w==} + '@vitest/expect@2.0.5': + resolution: {integrity: sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA==} - '@vitest/mocker@2.1.1': - resolution: {integrity: sha512-LNN5VwOEdJqCmJ/2XJBywB11DLlkbY0ooDJW3uRX5cZyYCrc4PI/ePX0iQhE3BiEGiQmK4GE7Q/PqCkkaiPnrA==} - peerDependencies: - '@vitest/spy': 2.1.1 - msw: ^2.3.5 - vite: ^5.0.0 - peerDependenciesMeta: - msw: - optional: true - vite: - optional: true + '@vitest/pretty-format@2.0.5': + resolution: {integrity: sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ==} '@vitest/pretty-format@2.1.1': resolution: {integrity: sha512-SjxPFOtuINDUW8/UkElJYQSFtnWX7tMksSGW0vfjxMneFqxVr8YJ979QpMbDW7g+BIiq88RAGDjf7en6rvLPPQ==} - '@vitest/runner@2.1.1': - resolution: {integrity: sha512-uTPuY6PWOYitIkLPidaY5L3t0JJITdGTSwBtwMjKzo5O6RCOEncz9PUN+0pDidX8kTHYjO0EwUIvhlGpnGpxmA==} + '@vitest/runner@2.0.5': + resolution: {integrity: sha512-TfRfZa6Bkk9ky4tW0z20WKXFEwwvWhRY+84CnSEtq4+3ZvDlJyY32oNTJtM7AW9ihW90tX/1Q78cb6FjoAs+ig==} - '@vitest/snapshot@2.1.1': - resolution: {integrity: sha512-BnSku1WFy7r4mm96ha2FzN99AZJgpZOWrAhtQfoxjUU5YMRpq1zmHRq7a5K9/NjqonebO7iVDla+VvZS8BOWMw==} + '@vitest/snapshot@2.0.5': + resolution: {integrity: sha512-SgCPUeDFLaM0mIUHfaArq8fD2WbaXG/zVXjRupthYfYGzc8ztbFbu6dUNOblBG7XLMR1kEhS/DNnfCZ2IhdDew==} - '@vitest/spy@2.1.1': - resolution: {integrity: sha512-ZM39BnZ9t/xZ/nF4UwRH5il0Sw93QnZXd9NAZGRpIgj0yvVwPpLd702s/Cx955rGaMlyBQkZJ2Ir7qyY48VZ+g==} + '@vitest/spy@2.0.5': + resolution: {integrity: sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA==} - '@vitest/utils@2.1.1': - resolution: {integrity: sha512-Y6Q9TsI+qJ2CC0ZKj6VBb+T8UPz593N113nnUykqwANqhgf3QkZeHFlusgKLTqrnVHbj/XDKZcDHol+dxVT+rQ==} + '@vitest/utils@2.0.5': + resolution: {integrity: sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ==} '@vscode/vscode-languagedetection@1.0.22': resolution: {integrity: sha512-rQ/BgMyLuIXSmbA0MSkIPHtcOw14QkeDbAq19sjvaS9LTRr905yij0S8lsyqN5JgOsbtIx7pAcyOxFMzPmqhZQ==} @@ -8593,8 +8587,8 @@ packages: vite-bundle-analyzer@0.12.1: resolution: {integrity: sha512-mIYwsDvTYCqXAUtOZIL3f7NdwWUeL/MlNFhOJzlTdcZE4pye6h06IEnOvWhnc/e+HM4oVVNxuRHZt0Rz6VO7EA==} - vite-node@2.1.1: - resolution: {integrity: sha512-N/mGckI1suG/5wQI35XeR9rsMsPqKXzq1CdUndzVstBj/HvyxxGctwnK6WX43NGt5L3Z5tcRf83g4TITKJhPrA==} + vite-node@2.0.5: + resolution: {integrity: sha512-LdsW4pxj0Ot69FAoXZ1yTnA9bjGohr2yNBU7QKRxpz8ITSkhuDl6h3zS/tvgz4qrNjeRnvrWeXQ8ZF7Um4W00Q==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true @@ -8643,15 +8637,15 @@ packages: terser: optional: true - vitest@2.1.1: - resolution: {integrity: sha512-97We7/VC0e9X5zBVkvt7SGQMGrRtn3KtySFQG5fpaMlS+l62eeXRQO633AYhSTC3z7IMebnPPNjGXVGNRFlxBA==} + vitest@2.0.5: + resolution: {integrity: sha512-8GUxONfauuIdeSl5f9GTgVEpg5BTOlplET4WEDaeY2QBiN8wSm68vxN/tb5z405OwppfoCavnwXafiaYBC/xOA==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@types/node': ^18.0.0 || >=20.0.0 - '@vitest/browser': 2.1.1 - '@vitest/ui': 2.1.1 + '@vitest/browser': 2.0.5 + '@vitest/ui': 2.0.5 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -8822,14 +8816,13 @@ packages: zod@3.23.8: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} - zustand@5.0.0-rc.2: - resolution: {integrity: sha512-o2Nwuvnk8vQBX7CcHL8WfFkZNJdxB/VKeWw0tNglw8p4cypsZ3tRT7rTRTDNeUPFS0qaMBRSKe+fVwL5xpcE3A==} - engines: {node: '>=12.20.0'} + zustand@4.5.5: + resolution: {integrity: sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==} + engines: {node: '>=12.7.0'} peerDependencies: - '@types/react': '>=18.0.0' + '@types/react': '>=16.8' immer: '>=9.0.6' - react: '>=18.0.0' - use-sync-external-store: '>=1.2.0' + react: '>=16.8' peerDependenciesMeta: '@types/react': optional: true @@ -8837,8 +8830,6 @@ packages: optional: true react: optional: true - use-sync-external-store: - optional: true zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -12616,43 +12607,40 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitest/expect@2.1.1': + '@vitest/expect@2.0.5': dependencies: - '@vitest/spy': 2.1.1 - '@vitest/utils': 2.1.1 + '@vitest/spy': 2.0.5 + '@vitest/utils': 2.0.5 chai: 5.1.1 tinyrainbow: 1.2.0 - '@vitest/mocker@2.1.1(@vitest/spy@2.1.1)(vite@5.4.8(@types/node@22.7.4)(terser@5.34.1))': + '@vitest/pretty-format@2.0.5': dependencies: - '@vitest/spy': 2.1.1 - estree-walker: 3.0.3 - magic-string: 0.30.11 - optionalDependencies: - vite: 5.4.8(@types/node@22.7.4)(terser@5.34.1) + tinyrainbow: 1.2.0 '@vitest/pretty-format@2.1.1': dependencies: tinyrainbow: 1.2.0 - '@vitest/runner@2.1.1': + '@vitest/runner@2.0.5': dependencies: - '@vitest/utils': 2.1.1 + '@vitest/utils': 2.0.5 pathe: 1.1.2 - '@vitest/snapshot@2.1.1': + '@vitest/snapshot@2.0.5': dependencies: - '@vitest/pretty-format': 2.1.1 + '@vitest/pretty-format': 2.0.5 magic-string: 0.30.11 pathe: 1.1.2 - '@vitest/spy@2.1.1': + '@vitest/spy@2.0.5': dependencies: tinyspy: 3.0.2 - '@vitest/utils@2.1.1': + '@vitest/utils@2.0.5': dependencies: - '@vitest/pretty-format': 2.1.1 + '@vitest/pretty-format': 2.0.5 + estree-walker: 3.0.3 loupe: 3.1.1 tinyrainbow: 1.2.0 @@ -18307,7 +18295,6 @@ snapshots: use-sync-external-store@1.2.2(react@18.3.1): dependencies: react: 18.3.1 - optional: true usehooks-ts@3.1.0(react@18.3.1): dependencies: @@ -18359,11 +18346,12 @@ snapshots: vite-bundle-analyzer@0.12.1: {} - vite-node@2.1.1(@types/node@22.7.4)(terser@5.34.1): + vite-node@2.0.5(@types/node@22.7.4)(terser@5.34.1): dependencies: cac: 6.7.14 debug: 4.3.7 pathe: 1.1.2 + tinyrainbow: 1.2.0 vite: 5.4.8(@types/node@22.7.4)(terser@5.34.1) transitivePeerDependencies: - '@types/node' @@ -18407,33 +18395,32 @@ snapshots: fsevents: 2.3.3 terser: 5.34.1 - vitest@2.1.1(@types/node@22.7.4)(terser@5.34.1): + vitest@2.0.5(@types/node@22.7.4)(terser@5.34.1): dependencies: - '@vitest/expect': 2.1.1 - '@vitest/mocker': 2.1.1(@vitest/spy@2.1.1)(vite@5.4.8(@types/node@22.7.4)(terser@5.34.1)) + '@ampproject/remapping': 2.3.0 + '@vitest/expect': 2.0.5 '@vitest/pretty-format': 2.1.1 - '@vitest/runner': 2.1.1 - '@vitest/snapshot': 2.1.1 - '@vitest/spy': 2.1.1 - '@vitest/utils': 2.1.1 + '@vitest/runner': 2.0.5 + '@vitest/snapshot': 2.0.5 + '@vitest/spy': 2.0.5 + '@vitest/utils': 2.0.5 chai: 5.1.1 debug: 4.3.7 + execa: 8.0.1 magic-string: 0.30.11 pathe: 1.1.2 std-env: 3.7.0 tinybench: 2.9.0 - tinyexec: 0.3.0 tinypool: 1.0.1 tinyrainbow: 1.2.0 vite: 5.4.8(@types/node@22.7.4)(terser@5.34.1) - vite-node: 2.1.1(@types/node@22.7.4)(terser@5.34.1) + vite-node: 2.0.5(@types/node@22.7.4)(terser@5.34.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.7.4 transitivePeerDependencies: - less - lightningcss - - msw - sass - sass-embedded - stylus @@ -18574,11 +18561,12 @@ snapshots: zod@3.23.8: {} - zustand@5.0.0-rc.2(@types/react@18.3.10)(immer@10.1.1(patch_hash=og7mbnoo5vh43tjlw5rbmrdbvu))(react@18.3.1)(use-sync-external-store@1.2.2(react@18.3.1)): + zustand@4.5.5(@types/react@18.3.10)(immer@10.1.1(patch_hash=og7mbnoo5vh43tjlw5rbmrdbvu))(react@18.3.1): + dependencies: + use-sync-external-store: 1.2.2(react@18.3.1) optionalDependencies: '@types/react': 18.3.10 immer: 10.1.1(patch_hash=og7mbnoo5vh43tjlw5rbmrdbvu) react: 18.3.1 - use-sync-external-store: 1.2.2(react@18.3.1) zwitch@2.0.4: {} From 3dd705f3a427c53d000c4934513c97d6132399d0 Mon Sep 17 00:00:00 2001 From: Innei Date: Sat, 28 Sep 2024 16:04:05 +0800 Subject: [PATCH 13/88] fix: media fallback src overflow Signed-off-by: Innei --- apps/renderer/src/components/ui/media.tsx | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/apps/renderer/src/components/ui/media.tsx b/apps/renderer/src/components/ui/media.tsx index f3fe45ba0..5d3b78ef1 100644 --- a/apps/renderer/src/components/ui/media.tsx +++ b/apps/renderer/src/components/ui/media.tsx @@ -213,7 +213,7 @@ const FallbackMedia: FC = ({ type, mediaContainerClassName, classNam className={cn( !(props.width || props.height) && "size-full", "center rounded bg-zinc-100 dark:bg-neutral-900", - "not-prose !flex max-h-full flex-col space-y-1 p-4", + "not-prose !flex max-h-full flex-col space-y-1 p-4 @container", mediaContainerClassName, )} @@ -222,14 +222,16 @@ const FallbackMedia: FC = ({ type, mediaContainerClassName, classNam width: props.width ? `${props.width}px` : "100%", }} > - -

Media loaded failed

-
- Go to{" "} - - {props.src} - - +
+ +

Media loaded failed

+
+ Go to{" "} + + original media url + + +
From 3352e8c292e810bb9a333e2a3c5e23adbae2a57a Mon Sep 17 00:00:00 2001 From: Innei Date: Sat, 28 Sep 2024 18:31:58 +0800 Subject: [PATCH 14/88] fix: add safe inset-top for Windows, fixed #576 Signed-off-by: Innei --- .../src/components/ui/modal/stacked/modal.tsx | 1 + .../modules/profile/user-profile-modal.tsx | 2 +- apps/renderer/src/pages/(main)/layout.tsx | 2 +- apps/renderer/src/styles/tailwind-extend.css | 26 +++++++++++++------ 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/apps/renderer/src/components/ui/modal/stacked/modal.tsx b/apps/renderer/src/components/ui/modal/stacked/modal.tsx index 5d3961ea9..e67ec4350 100644 --- a/apps/renderer/src/components/ui/modal/stacked/modal.tsx +++ b/apps/renderer/src/components/ui/modal/stacked/modal.tsx @@ -263,6 +263,7 @@ export const ModalInternal = memo( className={cn( "no-drag-region fixed z-20", modal ? "inset-0 overflow-auto" : "left-0 top-0", + "safe-inset-top", currentIsClosing ? "!pointer-events-none" : "!pointer-events-auto", modalContainerClassName, )} diff --git a/apps/renderer/src/modules/profile/user-profile-modal.tsx b/apps/renderer/src/modules/profile/user-profile-modal.tsx index aca92a8df..636707528 100644 --- a/apps/renderer/src/modules/profile/user-profile-modal.tsx +++ b/apps/renderer/src/modules/profile/user-profile-modal.tsx @@ -190,7 +190,7 @@ export const UserProfileModalContent: FC<{ className={cn( "relative flex flex-col items-center overflow-hidden rounded-xl border bg-theme-background p-8 pb-0", variant === "drawer" - ? "shadow-drawer-left h-full w-[60ch] max-w-full" + ? "shadow-drawer-to-left h-full w-[60ch] max-w-full" : "h-[80vh] w-[800px] max-w-full shadow lg:max-h-[calc(100vh-10rem)]", )} > diff --git a/apps/renderer/src/pages/(main)/layout.tsx b/apps/renderer/src/pages/(main)/layout.tsx index 495c69ffe..500379994 100644 --- a/apps/renderer/src/pages/(main)/layout.tsx +++ b/apps/renderer/src/pages/(main)/layout.tsx @@ -234,7 +234,7 @@ const FeedResponsiveResizerContainer = ({ className={cn( "shrink-0 overflow-hidden", "absolute inset-y-0 z-[2]", - feedColumnTempShow && !feedColumnShow && "shadow-drawer-right z-[12] border-r", + feedColumnTempShow && !feedColumnShow && "shadow-drawer-to-right z-[12] border-r", !feedColumnShow && !feedColumnTempShow ? "-translate-x-full delay-200" : "", !isDragging ? "duration-200" : "", )} diff --git a/apps/renderer/src/styles/tailwind-extend.css b/apps/renderer/src/styles/tailwind-extend.css index 65be9b392..7501cea09 100644 --- a/apps/renderer/src/styles/tailwind-extend.css +++ b/apps/renderer/src/styles/tailwind-extend.css @@ -280,17 +280,21 @@ } @layer components { - .shadow-drawer-left { - box-shadow: -12px 0px 20px -6px rgba(41, 41, 41, 0.1); + .shadow-drawer-to-left { + box-shadow: + -12px 0 20px -6px rgba(41, 41, 41, 0.1), + 24px 0 20px -6px rgba(41, 41, 41, 0.1); } - [data-theme="dark"] .shadow-drawer-left { - box-shadow: -12px 0px 20px -6px rgba(0, 0, 0, 0.653); + [data-theme="dark"] .shadow-drawer-to-left { + box-shadow: + -12px 0px 20px -6px rgba(0, 0, 0, 0.653), + 24px 0 20px -6px rgba(0, 0, 0, 0.653); } - .shadow-drawer-right { + .shadow-drawer-to-right { box-shadow: 12px 0px 20px -6px rgba(41, 41, 41, 0.1); } - [data-theme="dark"] .shadow-drawer-right { + [data-theme="dark"] .shadow-drawer-to-right { box-shadow: 12px 0px 20px -6px rgba(0, 0, 0, 0.653); } } @@ -313,12 +317,12 @@ @layer components { .shadow-tooltip-bottom { - --bg: theme(colors.accent.DEFAULT/0.3); + --bg: theme(colors.accent/0.3); box-shadow: 0px 5px 20px -11px var(--bg); } .shadow-tooltip-top { - --bg: theme(colors.accent.DEFAULT/0.3); + --bg: theme(colors.accent/0.3); box-shadow: 0px -5px 20px -11px var(--bg); } } @@ -375,3 +379,9 @@ } } } + +@layer utilities { + .safe-inset-top { + top: var(--fo-window-padding-top, 0); + } +} From 368d23250817bb4033168d8736f8e0ed5cd9475f Mon Sep 17 00:00:00 2001 From: Wenxuan Shen Date: Sat, 28 Sep 2024 18:33:17 +0800 Subject: [PATCH 15/88] feat(i18n): Chinese: Update `errors` (#687) --- locales/errors/zh-CN.json | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/locales/errors/zh-CN.json b/locales/errors/zh-CN.json index bc2799af0..d02091013 100644 --- a/locales/errors/zh-CN.json +++ b/locales/errors/zh-CN.json @@ -1,4 +1,5 @@ { + "1": "上一操作未完成", "1000": "未授权", "1001": "创建会话失败", "1002": "参数无效", @@ -16,13 +17,19 @@ "4002": "余额不足", "4003": "可提余额不足", "4004": "目标用户钱包错误", - "5000": "邀请限制已超出。请几天后再试。", - "5001": "邀请已存在。", - "5002": "邀请码已使用。", - "5003": "邀请码不存在。", + "5000": "邀请限制已超出。请几天后再试", + "5001": "邀请已存在", + "5002": "邀请码已使用", + "5003": "邀请码不存在", "6000": "未找到用户", "7000": "未找到设置", "7001": "无效的设置标签", "7002": "无效的设置负载", - "7003": "设置负载过大" + "7003": "设置负载过大", + "8000": "未找到列表", + "8001": "列表无权限", + "8002": "超出列表限制", + "8003": "订阅源已添加到列表", + "9000": "成就未完成", + "9001": "已获得成就" } From 213a4bce2c22eba336981e57c3a2ebd321de63da Mon Sep 17 00:00:00 2001 From: Jerry Wong Date: Sat, 28 Sep 2024 18:36:56 +0800 Subject: [PATCH 16/88] feat(i18n): conditional display of 'browser' or 'new tab' (#692) --- apps/renderer/src/hooks/biz/useEntryActions.tsx | 4 +++- apps/renderer/src/hooks/biz/useFeedActions.tsx | 5 ++++- locales/app/en.json | 10 ++++++---- locales/app/zh-CN.json | 10 ++++++---- locales/app/zh-HK.json | 12 +++++++----- locales/app/zh-TW.json | 10 ++++++---- 6 files changed, 32 insertions(+), 19 deletions(-) diff --git a/apps/renderer/src/hooks/biz/useEntryActions.tsx b/apps/renderer/src/hooks/biz/useEntryActions.tsx index 0a87dac69..ad1eda01c 100644 --- a/apps/renderer/src/hooks/biz/useEntryActions.tsx +++ b/apps/renderer/src/hooks/biz/useEntryActions.tsx @@ -339,7 +339,9 @@ export const useEntryActions = ({ }, { key: "openInBrowser", - name: t("entry_actions.open_in_browser"), + name: t("entry_actions.open_in_browser", { + which: t(window.electron ? "words.browser" : "words.newTab"), + }), shortcut: shortcuts.entry.openInBrowser.key, className: "i-mgc-world-2-cute-re", hide: !populatedEntry.entries.url, diff --git a/apps/renderer/src/hooks/biz/useFeedActions.tsx b/apps/renderer/src/hooks/biz/useFeedActions.tsx index 40fe01425..b66ab8e9d 100644 --- a/apps/renderer/src/hooks/biz/useFeedActions.tsx +++ b/apps/renderer/src/hooks/biz/useFeedActions.tsx @@ -155,6 +155,7 @@ export const useFeedActions = ({ isList ? "sidebar.feed_actions.open_list_in_browser" : "sidebar.feed_actions.open_feed_in_browser", + { which: t(window.electron ? "words.browser" : "words.newTab") }, ), disabled: isEntryList, shortcut: "O", @@ -170,7 +171,9 @@ export const useFeedActions = ({ ? [ { type: "text" as const, - label: t("sidebar.feed_actions.open_site_in_browser"), + label: t("sidebar.feed_actions.open_site_in_browser", { + which: t(window.electron ? "words.browser" : "words.newTab"), + }), shortcut: "Meta+O", disabled: isEntryList, click: () => { diff --git a/locales/app/en.json b/locales/app/en.json index d6e1b0a67..b9b289aa0 100644 --- a/locales/app/en.json +++ b/locales/app/en.json @@ -35,7 +35,7 @@ "entry_actions.link_copied": "Link copied to clipboard.", "entry_actions.mark_as_read": "Mark as read", "entry_actions.mark_as_unread": "Mark as unread", - "entry_actions.open_in_browser": "Open in browser", + "entry_actions.open_in_browser": "Open in {{which}}", "entry_actions.save_media_to_eagle": "Save media to Eagle", "entry_actions.save_to_instapaper": "Save to Instapaper", "entry_actions.save_to_readwise": "Save to Readwise", @@ -177,9 +177,9 @@ "sidebar.feed_actions.mark_all_as_read": "Mark all as read", "sidebar.feed_actions.navigate_to_feed": "Navigate to feed", "sidebar.feed_actions.navigate_to_list": "Navigate to list", - "sidebar.feed_actions.open_feed_in_browser": "Open feed in browser", - "sidebar.feed_actions.open_list_in_browser": "Open list in browser", - "sidebar.feed_actions.open_site_in_browser": "Open site in browser", + "sidebar.feed_actions.open_feed_in_browser": "Open feed in {{which}}", + "sidebar.feed_actions.open_list_in_browser": "Open list in {{which}}", + "sidebar.feed_actions.open_site_in_browser": "Open site in {{which}}", "sidebar.feed_actions.unfollow": "Unfollow", "sidebar.feed_actions.unfollow_feed": "Unfollow feed", "sidebar.feed_column.context_menu.add_feeds_to_list": "Add feeds to list", @@ -220,6 +220,7 @@ "user_profile.toggle_item_style": "Toggle Item Style", "words.achievement": "Achievements", "words.add": "Add", + "words.browser": "Browser", "words.confirm": "Confirm", "words.discover": "Discover", "words.email": "Email", @@ -231,6 +232,7 @@ "words.load_archived_entries": "Load archived entries", "words.login": "Login", "words.mint": "Mint", + "words.newTab": "New Tab", "words.power": "Power", "words.rss": "RSS", "words.rss3": "RSS3", diff --git a/locales/app/zh-CN.json b/locales/app/zh-CN.json index 2e20769fc..60c090c08 100644 --- a/locales/app/zh-CN.json +++ b/locales/app/zh-CN.json @@ -35,7 +35,7 @@ "entry_actions.link_copied": "链接已复制到剪贴板", "entry_actions.mark_as_read": "标记为已读", "entry_actions.mark_as_unread": "标记为未读", - "entry_actions.open_in_browser": "在浏览器打开", + "entry_actions.open_in_browser": "在{{which}}打开", "entry_actions.save_media_to_eagle": "保存到 Eagle", "entry_actions.save_to_instapaper": "保存到 Instapaper", "entry_actions.save_to_readwise": "保存到 Readwise", @@ -177,9 +177,9 @@ "sidebar.feed_actions.mark_all_as_read": "全部标记为已读", "sidebar.feed_actions.navigate_to_feed": "跳转至", "sidebar.feed_actions.navigate_to_list": "跳转至列表", - "sidebar.feed_actions.open_feed_in_browser": "在浏览器打开订阅源", - "sidebar.feed_actions.open_list_in_browser": "在浏览器打开列表", - "sidebar.feed_actions.open_site_in_browser": "在浏览器打开网站", + "sidebar.feed_actions.open_feed_in_browser": "在{{which}}打开订阅源", + "sidebar.feed_actions.open_list_in_browser": "在{{which}}打开列表", + "sidebar.feed_actions.open_site_in_browser": "在{{which}}打开网站", "sidebar.feed_actions.unfollow": "取消订阅", "sidebar.feed_actions.unfollow_feed": "取消订阅", "sidebar.feed_column.context_menu.add_feeds_to_list": "添加订阅源到列表", @@ -220,6 +220,7 @@ "user_profile.toggle_item_style": "切换列表样式", "words.achievement": "成就", "words.add": "添加", + "words.browser": "浏览器", "words.confirm": "确认", "words.discover": "发现", "words.email": "邮箱", @@ -231,6 +232,7 @@ "words.load_archived_entries": "加载已归档条目", "words.login": "登录", "words.mint": "Mint", + "words.newTab": "新标签页", "words.power": "Power", "words.rss": "RSS", "words.rss3": "RSS3", diff --git a/locales/app/zh-HK.json b/locales/app/zh-HK.json index 2b7263e73..165b66f6f 100644 --- a/locales/app/zh-HK.json +++ b/locales/app/zh-HK.json @@ -35,7 +35,7 @@ "entry_actions.link_copied": "連結已複製到剪貼簿。", "entry_actions.mark_as_read": "標記為已讀", "entry_actions.mark_as_unread": "標記為未讀", - "entry_actions.open_in_browser": "在瀏覽器中開啟", + "entry_actions.open_in_browser": "在{{which}}中開啟", "entry_actions.save_media_to_eagle": "保存媒體至 Eagle", "entry_actions.save_to_instapaper": "保存至 Instapaper", "entry_actions.save_to_readwise": "保存至 Readwise", @@ -177,9 +177,9 @@ "sidebar.feed_actions.mark_all_as_read": "全部標記為已讀", "sidebar.feed_actions.navigate_to_feed": "導航到訂閱源", "sidebar.feed_actions.navigate_to_list": "導航到清單", - "sidebar.feed_actions.open_feed_in_browser": "在瀏覽器中打開訂閱源", - "sidebar.feed_actions.open_list_in_browser": "在瀏覽器中打開清單", - "sidebar.feed_actions.open_site_in_browser": "在瀏覽器中打開網站", + "sidebar.feed_actions.open_feed_in_browser": "在{{which}}中打開訂閱源", + "sidebar.feed_actions.open_list_in_browser": "在{{which}}中打開清單", + "sidebar.feed_actions.open_site_in_browser": "在{{which}}中打開網站", "sidebar.feed_actions.unfollow": "取消關注", "sidebar.feed_actions.unfollow_feed": "取消關注訂閱源", "sidebar.feed_column.context_menu.change_to_other_view": "切換到其他視圖", @@ -219,6 +219,7 @@ "user_profile.toggle_item_style": "切換條目樣式", "words.achievement": "成就", "words.add": "新增", + "words.browser": "瀏覽器", "words.confirm": "確認", "words.discover": "探索", "words.email": "電子郵件", @@ -230,6 +231,7 @@ "words.load_archived_entries": "加載已存檔的條目", "words.login": "登入", "words.mint": "Mint", + "words.newTab": "新分頁", "words.power": "Power", "words.rss": "RSS", "words.rss3": "RSS3", @@ -240,5 +242,5 @@ "words.unread": "未讀", "words.user": "用戶", "words.which.all": "所有", - "words.zero_items": "零項目" + "words.zero_items": "沒有項目" } diff --git a/locales/app/zh-TW.json b/locales/app/zh-TW.json index 3a85271d0..a87d67c3d 100644 --- a/locales/app/zh-TW.json +++ b/locales/app/zh-TW.json @@ -35,7 +35,7 @@ "entry_actions.link_copied": "連結已複製到剪貼簿。", "entry_actions.mark_as_read": "標記為已讀", "entry_actions.mark_as_unread": "標記為未讀", - "entry_actions.open_in_browser": "在瀏覽器中打開", + "entry_actions.open_in_browser": "在{{which}}中打開", "entry_actions.save_media_to_eagle": "儲存媒體至 Eagle", "entry_actions.save_to_instapaper": "儲存到 Instapaper", "entry_actions.save_to_readwise": "儲存到 Readwise", @@ -175,9 +175,9 @@ "sidebar.feed_actions.list_owned_by_you": "該列表歸你所有", "sidebar.feed_actions.mark_all_as_read": "全部標記為已讀", "sidebar.feed_actions.navigate_to_feed": "導航到摘要", - "sidebar.feed_actions.open_feed_in_browser": "使用瀏覽器打開這個摘要", - "sidebar.feed_actions.open_list_in_browser": "在瀏覽器開啟列表", - "sidebar.feed_actions.open_site_in_browser": "使用瀏覽器打開這個網站", + "sidebar.feed_actions.open_feed_in_browser": "使用{{which}}打開這個摘要", + "sidebar.feed_actions.open_list_in_browser": "在{{which}}開啟列表", + "sidebar.feed_actions.open_site_in_browser": "使用{{which}}打開這個網站", "sidebar.feed_actions.unfollow": "取消關注", "sidebar.feed_actions.unfollow_feed": "取消關注摘要", "sidebar.feed_column.context_menu.change_to_other_view": "切換到其他視圖", @@ -217,6 +217,7 @@ "user_profile.toggle_item_style": "切換項目樣式", "words.achievement": "成就", "words.add": "新增", + "words.browser": "瀏覽器", "words.confirm": "確認", "words.discover": "發現", "words.email": "Email", @@ -227,6 +228,7 @@ "words.lists": "列表", "words.load_archived_entries": "載入已封存項目", "words.login": "登入", + "words.newTab": "新分頁", "words.power": "Power", "words.rss": "RSS", "words.rss3": "RSS3", From 018b5b1b1b3ced06543189512f5bb2df39f946af Mon Sep 17 00:00:00 2001 From: Wenxuan Shen Date: Sat, 28 Sep 2024 18:59:22 +0800 Subject: [PATCH 17/88] fix(i18n): add de to langs (#683) * feat(i18n): Add de * chore: auto-fix linting and formatting issues * feat(i18n): Update lang/de * chore: auto-fix linting and formatting issues * feat(i18n): add de to ko * chore: auto-fix linting and formatting issues * feat(i18n): add de to ko --------- Co-authored-by: xuanxuan1231 --- locales/lang/ar-DZ.json | 1 + locales/lang/ar-IQ.json | 1 + locales/lang/ar-KW.json | 1 + locales/lang/ar-MA.json | 1 + locales/lang/ar-SA.json | 2 ++ locales/lang/ar-TN.json | 1 + locales/lang/de.json | 36 +++++++++++++++++++----------------- locales/lang/es.json | 1 + locales/lang/fi.json | 1 + locales/lang/fr.json | 1 + locales/lang/it.json | 1 + locales/lang/ja.json | 1 + locales/lang/ko.json | 3 ++- locales/lang/pt.json | 1 + locales/lang/ru.json | 1 + locales/lang/tr.json | 1 + locales/lang/zh-CN.json | 1 + locales/lang/zh-HK.json | 1 + locales/lang/zh-TW.json | 1 + 19 files changed, 39 insertions(+), 18 deletions(-) diff --git a/locales/lang/ar-DZ.json b/locales/lang/ar-DZ.json index 15f35f469..bbb4640c7 100644 --- a/locales/lang/ar-DZ.json +++ b/locales/lang/ar-DZ.json @@ -5,6 +5,7 @@ "langs.ar-MA": "العربية (المغرب)", "langs.ar-SA": "العربية (السعودية)", "langs.ar-TN": "العربية (تونس)", + "langs.de": "الألمانية", "langs.en": "الإنجليزية", "langs.es": "الإسبانية", "langs.fi": "الفنلندية", diff --git a/locales/lang/ar-IQ.json b/locales/lang/ar-IQ.json index 652d8a756..b674408cc 100644 --- a/locales/lang/ar-IQ.json +++ b/locales/lang/ar-IQ.json @@ -5,6 +5,7 @@ "langs.ar-MA": "العربية (المغرب)", "langs.ar-SA": "العربية (السعودية)", "langs.ar-TN": "العربية (تونس)", + "langs.de": "الألمانية", "langs.en": "الإنجليزية", "langs.es": "الإسبانية", "langs.fi": "الفنلندية", diff --git a/locales/lang/ar-KW.json b/locales/lang/ar-KW.json index ceb5b1a41..ea561db55 100644 --- a/locales/lang/ar-KW.json +++ b/locales/lang/ar-KW.json @@ -5,6 +5,7 @@ "langs.ar-MA": "العربية (المغرب)", "langs.ar-SA": "العربية (السعودية)", "langs.ar-TN": "العربية (تونس)", + "langs.de": "الألمانية", "langs.en": "الإنجليزية", "langs.es": "الإسبانية", "langs.fi": "الفنلندية", diff --git a/locales/lang/ar-MA.json b/locales/lang/ar-MA.json index f4bdf41cb..3a5293293 100644 --- a/locales/lang/ar-MA.json +++ b/locales/lang/ar-MA.json @@ -5,6 +5,7 @@ "langs.ar-MA": "العربية (المغرب)", "langs.ar-SA": "العربية (السعودية)", "langs.ar-TN": "العربية (تونس)", + "langs.de": "الألمانية", "langs.en": "الإنجليزية", "langs.es": "الإسبانية", "langs.fi": "الفنلندية", diff --git a/locales/lang/ar-SA.json b/locales/lang/ar-SA.json index 93fc2f791..1c123e022 100644 --- a/locales/lang/ar-SA.json +++ b/locales/lang/ar-SA.json @@ -5,6 +5,7 @@ "langs.ar-MA": "العربية (المغرب)", "langs.ar-SA": "العربية (السعودية)", "langs.ar-TN": "العربية (تونس)", + "langs.de": "الألمانية", "langs.en": "الإنجليزية", "langs.es": "الإسبانية", "langs.fi": "الفنلندية", @@ -14,6 +15,7 @@ "langs.ko": "الكورية", "langs.pt": "البرتغالية", "langs.ru": "الروسية", + "langs.tr": "التركية", "langs.zh-CN": "الصينية المبسطة", "langs.zh-HK": "الصينية التقليدية (هونغ كونغ)", "langs.zh-TW": "الصينية التقليدية (تايوان)", diff --git a/locales/lang/ar-TN.json b/locales/lang/ar-TN.json index 6a58394cf..bf328c964 100644 --- a/locales/lang/ar-TN.json +++ b/locales/lang/ar-TN.json @@ -5,6 +5,7 @@ "langs.ar-MA": "العربية (المغرب)", "langs.ar-SA": "العربية (السعودية)", "langs.ar-TN": "العربية (تونس)", + "langs.de": "الألمانية", "langs.en": "الإنجليزية", "langs.es": "الإسبانية", "langs.fi": "الفنلندية", diff --git a/locales/lang/de.json b/locales/lang/de.json index e15cc9b49..656e95fff 100644 --- a/locales/lang/de.json +++ b/locales/lang/de.json @@ -1,21 +1,23 @@ { - "langs.ar-DZ": "العربية (الجزائر)", - "langs.ar-IQ": "العربية (العراق)", - "langs.ar-KW": "العربية (الكويت)", - "langs.ar-MA": "العربية (المغرب)", - "langs.ar-SA": "العربية (السعودية)", - "langs.ar-TN": "العربية (تونس)", + "langs.ar-DZ": "Arabisch (Algerien)", + "langs.ar-IQ": "Arabisch (Irak)", + "langs.ar-KW": "Arabisch (Kuwait)", + "langs.ar-MA": "Arabisch (Marokko)", + "langs.ar-SA": "Arabisch (Saudi-Arabien)", + "langs.ar-TN": "Arabisch (Tunesien)", "langs.de": "Deutsch", - "langs.en": "English", - "langs.es": "Español", - "langs.fi": "Suomi", - "langs.fr": "Français", - "langs.it": "Italiano", - "langs.ja": "日本語", - "langs.pt": "Português", - "langs.ru": "Русский", - "langs.zh-CN": "简体中文", - "langs.zh-HK": "繁體中文(香港)", - "langs.zh-TW": "繁體中文(台灣)", + "langs.en": "Englisch", + "langs.es": "Spanisch", + "langs.fi": "Finnisch", + "langs.fr": "Französisch", + "langs.it": "Italienisch", + "langs.ja": "Japanisch", + "langs.ko": "Koreanisch", + "langs.pt": "Portugiesisch", + "langs.ru": "Russisch", + "langs.tr": "Türkisch", + "langs.zh-CN": "Vereinfachtes Chinesisch", + "langs.zh-HK": "Traditionelles Chinesisch (Hongkong)", + "langs.zh-TW": "Traditionelles Chinesisch (Taiwan)", "name": "Deutsch" } diff --git a/locales/lang/es.json b/locales/lang/es.json index 24420b752..2a19b913b 100644 --- a/locales/lang/es.json +++ b/locales/lang/es.json @@ -5,6 +5,7 @@ "langs.ar-MA": "Árabe (Marruecos)", "langs.ar-SA": "Árabe (Arabia Saudita)", "langs.ar-TN": "Árabe (Túnez)", + "langs.de": "Alemán", "langs.en": "Inglés", "langs.es": "Español", "langs.fi": "Finlandés", diff --git a/locales/lang/fi.json b/locales/lang/fi.json index d05e7da83..21d834d84 100644 --- a/locales/lang/fi.json +++ b/locales/lang/fi.json @@ -5,6 +5,7 @@ "langs.ar-MA": "Arabia (Marokko)", "langs.ar-SA": "Arabia (Saudi-Arabia)", "langs.ar-TN": "Arabia (Tunisia)", + "langs.de": "Saksaksi", "langs.en": "Englanti", "langs.es": "Espanja", "langs.fi": "Suomi", diff --git a/locales/lang/fr.json b/locales/lang/fr.json index 07bcd9e67..c7f4b5849 100644 --- a/locales/lang/fr.json +++ b/locales/lang/fr.json @@ -5,6 +5,7 @@ "langs.ar-MA": "Arabe (Maroc)", "langs.ar-SA": "Arabe (Arabie Saoudite)", "langs.ar-TN": "Arabe (Tunisie)", + "langs.de": "Allemand", "langs.en": "Anglais", "langs.es": "Espagnol", "langs.fi": "Finnois", diff --git a/locales/lang/it.json b/locales/lang/it.json index c5307bc01..d04afb7e6 100644 --- a/locales/lang/it.json +++ b/locales/lang/it.json @@ -5,6 +5,7 @@ "langs.ar-MA": "Arabo (Marocco)", "langs.ar-SA": "Arabo (Arabia Saudita)", "langs.ar-TN": "Arabo (Tunisia)", + "langs.de": "Germano", "langs.en": "Inglese", "langs.es": "Spagnolo", "langs.fi": "Finlandese", diff --git a/locales/lang/ja.json b/locales/lang/ja.json index 288f4577f..0ea3c0692 100644 --- a/locales/lang/ja.json +++ b/locales/lang/ja.json @@ -5,6 +5,7 @@ "langs.ar-MA": "アラビア語(モロッコ)", "langs.ar-SA": "アラビア語(サウジアラビア)", "langs.ar-TN": "アラビア語(チュニジア)", + "langs.de": "ドイツ語", "langs.en": "英語", "langs.es": "スペイン語", "langs.fi": "フィンランド語", diff --git a/locales/lang/ko.json b/locales/lang/ko.json index a648d776f..d67f9db36 100644 --- a/locales/lang/ko.json +++ b/locales/lang/ko.json @@ -5,6 +5,7 @@ "langs.ar-MA": "العربية (모로코)", "langs.ar-SA": "العربية (사우디아라비아)", "langs.ar-TN": "العربية (튀니지)", + "langs.de": "독일 사람", "langs.en": "영어", "langs.es": "스페인어", "langs.fi": "핀란드어", @@ -18,5 +19,5 @@ "langs.zh-CN": "간체 중국어", "langs.zh-HK": "번체 중국어 (홍콩)", "langs.zh-TW": "번체 중국어 (대만)", - "name": "영어" + "name": "한국어" } diff --git a/locales/lang/pt.json b/locales/lang/pt.json index 5bc119db0..d8e795636 100644 --- a/locales/lang/pt.json +++ b/locales/lang/pt.json @@ -5,6 +5,7 @@ "langs.ar-MA": "Árabe (Marrocos)", "langs.ar-SA": "Árabe (Arábia Saudita)", "langs.ar-TN": "Árabe (Tunísia)", + "langs.de": "Alemão", "langs.en": "Inglês", "langs.es": "Espanhol", "langs.fi": "Finlandês", diff --git a/locales/lang/ru.json b/locales/lang/ru.json index e11f9e070..ad9fd279d 100644 --- a/locales/lang/ru.json +++ b/locales/lang/ru.json @@ -5,6 +5,7 @@ "langs.ar-MA": "Арабский (Марокко)", "langs.ar-SA": "Арабский (Саудовская Аравия)", "langs.ar-TN": "Арабский (Тунис)", + "langs.de": "Немецкий", "langs.en": "Английский", "langs.es": "Испанский", "langs.fi": "Финский", diff --git a/locales/lang/tr.json b/locales/lang/tr.json index 6a8bf4841..d2d7a06af 100644 --- a/locales/lang/tr.json +++ b/locales/lang/tr.json @@ -5,6 +5,7 @@ "langs.ar-MA": "Arapça (Fas)", "langs.ar-SA": "Arapça (Suudi Arabistan)", "langs.ar-TN": "Arapça (Tunus)", + "langs.de": "Almanca", "langs.en": "İngilizce", "langs.es": "İspanyolca", "langs.fi": "Fince", diff --git a/locales/lang/zh-CN.json b/locales/lang/zh-CN.json index fcd629207..f2e4965e9 100644 --- a/locales/lang/zh-CN.json +++ b/locales/lang/zh-CN.json @@ -5,6 +5,7 @@ "langs.ar-MA": "阿拉伯语(摩洛哥)", "langs.ar-SA": "阿拉伯语(沙特阿拉伯)", "langs.ar-TN": "阿拉伯语(突尼斯)", + "langs.de": "德语", "langs.en": "英语", "langs.es": "西班牙语", "langs.fi": "芬兰语", diff --git a/locales/lang/zh-HK.json b/locales/lang/zh-HK.json index d8447c4b5..d0503f1ca 100644 --- a/locales/lang/zh-HK.json +++ b/locales/lang/zh-HK.json @@ -5,6 +5,7 @@ "langs.ar-MA": "阿拉伯語(摩洛哥)", "langs.ar-SA": "阿拉伯語(沙特阿拉伯)", "langs.ar-TN": "阿拉伯語(突尼斯)", + "langs.de": "德語", "langs.en": "英語", "langs.es": "西班牙語", "langs.fi": "芬蘭語", diff --git a/locales/lang/zh-TW.json b/locales/lang/zh-TW.json index aeb7cc9eb..643ae9bc9 100644 --- a/locales/lang/zh-TW.json +++ b/locales/lang/zh-TW.json @@ -5,6 +5,7 @@ "langs.ar-MA": "阿拉伯語(摩洛哥)", "langs.ar-SA": "阿拉伯語(沙特阿拉伯)", "langs.ar-TN": "阿拉伯語(突尼斯)", + "langs.de": "德語", "langs.en": "英語", "langs.es": "西班牙語", "langs.fi": "芬蘭語", From 843ffd39277168938ab92089c174300c02984992 Mon Sep 17 00:00:00 2001 From: Innei Date: Sat, 28 Sep 2024 19:04:27 +0800 Subject: [PATCH 18/88] chore: fix i18n usage Signed-off-by: Innei --- apps/renderer/src/modules/settings/tabs/lists.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/renderer/src/modules/settings/tabs/lists.tsx b/apps/renderer/src/modules/settings/tabs/lists.tsx index ab39e7411..4b0e86fc1 100644 --- a/apps/renderer/src/modules/settings/tabs/lists.tsx +++ b/apps/renderer/src/modules/settings/tabs/lists.tsx @@ -187,9 +187,7 @@ const formSchema = z.object({ }) const ListCreationModalContent = ({ dismiss, id }: { dismiss: () => void; id?: string }) => { - const { t } = useTranslation("settings") - - const appT = useI18n() + const { t } = useTranslation(["settings", "common"]) const list = useFeedById(id) as ListModel @@ -334,7 +332,7 @@ const ListCreationModalContent = ({ dismiss, id }: { dismiss: () => void; id?: s />
From 6eac9ddbb3290448a4b93747832378a11f2a1ad8 Mon Sep 17 00:00:00 2001 From: Innei Date: Sat, 28 Sep 2024 19:07:36 +0800 Subject: [PATCH 19/88] chore(ci): remove autocorrect Signed-off-by: Innei --- .github/workflows/auto-fix-lint-format-commit.yml | 4 ---- .github/workflows/build.yml | 4 ---- .github/workflows/lint.yml | 4 ---- 3 files changed, 12 deletions(-) diff --git a/.github/workflows/auto-fix-lint-format-commit.yml b/.github/workflows/auto-fix-lint-format-commit.yml index 1dba352b7..8a9d6ac4e 100644 --- a/.github/workflows/auto-fix-lint-format-commit.yml +++ b/.github/workflows/auto-fix-lint-format-commit.yml @@ -15,10 +15,6 @@ jobs: ref: ${{ github.head_ref }} repository: ${{ github.event.pull_request.head.repo.full_name }} - - name: AutoCorrect - if: runner.os == 'Linux' - uses: huacnlee/autocorrect-action@main - - name: Setup pnpm uses: pnpm/action-setup@v4 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 29b5540b4..e73176ce8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -51,10 +51,6 @@ jobs: fetch-depth: 1 lfs: true - - name: AutoCorrect - if: runner.os == 'Linux' - uses: huacnlee/autocorrect-action@main - - name: Setup pnpm uses: pnpm/action-setup@v4 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index e98661ddb..4dd340684 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -24,10 +24,6 @@ jobs: - name: Checkout LFS objects run: git lfs checkout - - name: AutoCorrect - if: runner.os == 'Linux' - uses: huacnlee/autocorrect-action@main - - uses: pnpm/action-setup@v4 - name: Use Node.js ${{ matrix.node-version }} From 9698fa69d110781d26b542e9e81a51dc7b16805e Mon Sep 17 00:00:00 2001 From: DIYgod Date: Sun, 29 Sep 2024 00:51:49 +0800 Subject: [PATCH 20/88] feat: optimize no showUnreadCount dot display --- .../src/modules/feed-column/category.tsx | 25 +++---------------- .../src/modules/feed-column/index.tsx | 16 +++++++++--- .../renderer/src/modules/feed-column/item.tsx | 12 ++------- .../renderer/src/modules/feed-column/list.tsx | 20 ++------------- .../src/modules/feed-column/unread-number.tsx | 13 +++++----- 5 files changed, 27 insertions(+), 59 deletions(-) diff --git a/apps/renderer/src/modules/feed-column/category.tsx b/apps/renderer/src/modules/feed-column/category.tsx index c9bc23c30..77c140784 100644 --- a/apps/renderer/src/modules/feed-column/category.tsx +++ b/apps/renderer/src/modules/feed-column/category.tsx @@ -31,15 +31,9 @@ interface FeedCategoryProps { data: FeedId[] view?: number expansion: boolean - showUnreadCount?: boolean } -function FeedCategoryImpl({ - data: ids, - view, - expansion, - showUnreadCount = true, -}: FeedCategoryProps) { +function FeedCategoryImpl({ data: ids, view, expansion }: FeedCategoryProps) { const { t } = useTranslation() const sortByUnreadFeedList = useFeedUnreadStore((state) => @@ -241,14 +235,7 @@ function FeedCategoryImpl({ /> ) : ( - - {folderName} - + {folderName} @@ -280,7 +267,6 @@ function FeedCategoryImpl({ ids={ids} showCollapse={showCollapse as boolean} view={view as FeedViewType} - showUnreadCount={showUnreadCount} />
)} @@ -368,7 +354,6 @@ const RenameCategoryForm: FC<{ type SortListProps = { ids: string[] - showUnreadCount?: boolean view: FeedViewType showCollapse: boolean } @@ -389,7 +374,7 @@ const SortedFeedItems = (props: SortListProps) => { } const SortByAlphabeticalList = (props: SortListProps) => { - const { ids, showUnreadCount, showCollapse, view } = props + const { ids, showCollapse, view } = props const isDesc = useFeedListSortSelector((s) => s.order === "desc") const sortedFeedList = useFeedStore((state) => { const res = ids.sort((a, b) => { @@ -407,7 +392,6 @@ const SortByAlphabeticalList = (props: SortListProps) => { {sortedFeedList.map((feedId) => ( { ) } -const SortByUnreadList = ({ ids, showUnreadCount, showCollapse, view }: SortListProps) => { +const SortByUnreadList = ({ ids, showCollapse, view }: SortListProps) => { const isDesc = useFeedListSortSelector((s) => s.order === "desc") const sortByUnreadFeedList = useFeedUnreadStore((state) => { const res = ids.sort((a, b) => (state.data[b] || 0) - (state.data[a] || 0)) @@ -428,7 +412,6 @@ const SortByUnreadList = ({ ids, showUnreadCount, showCollapse, view }: SortList {sortByUnreadFeedList.map((feedId) => ( { @@ -172,7 +171,7 @@ export function FeedColumn({ children, className }: PropsWithChildren<{ classNam }} > {item.icon} - {showSidebarUnreadCount && ( + {showSidebarUnreadCount ? (
{unreadByView[index] > 99 ? ( 99+ @@ -180,6 +179,17 @@ export function FeedColumn({ children, className }: PropsWithChildren<{ classNam unreadByView[index] )}
+ ) : ( + )} ))} diff --git a/apps/renderer/src/modules/feed-column/item.tsx b/apps/renderer/src/modules/feed-column/item.tsx index 3196d6c6f..82a45f1eb 100644 --- a/apps/renderer/src/modules/feed-column/item.tsx +++ b/apps/renderer/src/modules/feed-column/item.tsx @@ -26,9 +26,8 @@ interface FeedItemProps { feedId: string view?: number className?: string - showUnreadCount?: boolean } -const FeedItemImpl = ({ view, feedId, className, showUnreadCount = true }: FeedItemProps) => { +const FeedItemImpl = ({ view, feedId, className }: FeedItemProps) => { const { t } = useTranslation() const subscription = useSubscriptionByFeedId(feedId) const navigate = useNavigateEntry() @@ -120,14 +119,7 @@ const FeedItemImpl = ({ view, feedId, className, showUnreadCount = true }: FeedI )} > -
- {getPreferredTitle(feed)} -
+
{getPreferredTitle(feed)}
{isFeed && } {isFeed && feed.errorAt && ( diff --git a/apps/renderer/src/modules/feed-column/list.tsx b/apps/renderer/src/modules/feed-column/list.tsx index 578eab40e..deeb421a7 100644 --- a/apps/renderer/src/modules/feed-column/list.tsx +++ b/apps/renderer/src/modules/feed-column/list.tsx @@ -4,7 +4,6 @@ import { Fragment, memo, useMemo, useState } from "react" import { useTranslation } from "react-i18next" import { Link } from "react-router-dom" -import { useUISettingKey } from "~/atoms/settings/ui" import { ScrollArea } from "~/components/ui/scroll-area" import { IconOpacityTransition } from "~/components/ux/transition/icon" import { FEED_COLLECTION_LIST, views } from "~/constants" @@ -284,7 +283,6 @@ type FeedListProps = { data: Record } const SortByUnreadList = ({ view, expansion, data }: FeedListProps) => { - const showUnreadCount = useUISettingKey("sidebarShowUnreadCount") const isDesc = useFeedListSortSelector((s) => s.order === "desc") const sortedByUnread = useFeedUnreadStore((state) => { @@ -311,13 +309,7 @@ const SortByUnreadList = ({ view, expansion, data }: FeedListProps) => { return ( {sortedByUnread?.map(([category, ids]) => ( - + ))} ) @@ -358,18 +350,10 @@ const SortByAlphabeticalList = ({ view, expansion, data }: FeedListProps) => { sortedByAlphabetical = sortedByAlphabetical.reverse() } - const showUnreadCount = useUISettingKey("sidebarShowUnreadCount") - return ( {sortedByAlphabetical.map((category) => ( - + ))} ) diff --git a/apps/renderer/src/modules/feed-column/unread-number.tsx b/apps/renderer/src/modules/feed-column/unread-number.tsx index b5482156d..165727960 100644 --- a/apps/renderer/src/modules/feed-column/unread-number.tsx +++ b/apps/renderer/src/modules/feed-column/unread-number.tsx @@ -11,17 +11,16 @@ export const UnreadNumber = ({ isList?: boolean }) => { const showUnreadCount = useUISettingKey("sidebarShowUnreadCount") - if (!showUnreadCount) return null + if (!unread) return null return (
- {isList ? ( - - ) : ( - unread + className={cn( + "center text-[0.65rem] tabular-nums text-zinc-400 dark:text-neutral-500", + className, )} + > + {isList || !showUnreadCount ? : unread}
) } From 31591d68d595c9b44bf2ec49b7e3083acd612bb3 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Sun, 29 Sep 2024 01:42:07 +0800 Subject: [PATCH 21/88] feat: smaller lists image --- apps/renderer/src/modules/feed-column/item.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/renderer/src/modules/feed-column/item.tsx b/apps/renderer/src/modules/feed-column/item.tsx index 82a45f1eb..a68874128 100644 --- a/apps/renderer/src/modules/feed-column/item.tsx +++ b/apps/renderer/src/modules/feed-column/item.tsx @@ -118,7 +118,7 @@ const FeedItemImpl = ({ view, feedId, className }: FeedItemProps) => { isFeed && feed.errorAt && "text-red-900 dark:text-red-500", )} > - +
{getPreferredTitle(feed)}
{isFeed && } {isFeed && feed.errorAt && ( From 0016a0742b7ecd107152e09cb629d0d2ea637764 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Sun, 29 Sep 2024 04:17:51 +0800 Subject: [PATCH 22/88] feat: webhook action setting --- apps/renderer/src/models/types.ts | 24 ++++++ .../src/modules/settings/action-card.tsx | 80 ++++++++++++------- .../src/pages/settings/(settings)/actions.tsx | 25 +----- locales/errors/en.json | 1 + locales/settings/en.json | 1 + packages/shared/src/hono.ts | 31 +++++++ 6 files changed, 110 insertions(+), 52 deletions(-) diff --git a/apps/renderer/src/models/types.ts b/apps/renderer/src/models/types.ts index a9b376609..91fac5826 100644 --- a/apps/renderer/src/models/types.ts +++ b/apps/renderer/src/models/types.ts @@ -84,3 +84,27 @@ export type MediaModel = Exclude< ExtractBizResponse["data"], undefined >["entries"]["media"] + +export type ActionsInput = { + name: string + condition: { + field?: ActionFeedField + operator?: ActionOperation + value?: string + }[] + result: { + translation?: string + summary?: boolean + readability?: boolean + rewriteRules?: { + from: string + to: string + }[] + blockRules?: { + field?: ActionEntryField + operator?: ActionOperation + value?: string | number + }[] + webhooks?: string[] + } +}[] diff --git a/apps/renderer/src/modules/settings/action-card.tsx b/apps/renderer/src/modules/settings/action-card.tsx index 6c2a4c066..9700a9bc5 100644 --- a/apps/renderer/src/modules/settings/action-card.tsx +++ b/apps/renderer/src/modules/settings/action-card.tsx @@ -27,35 +27,7 @@ import { import { ViewSelectContent } from "~/components/view-select-content" import { stopPropagation } from "~/lib/dom" import { cn } from "~/lib/utils" -import type { - ActionEntryField, - ActionFeedField, - ActionOperation, - SupportedLanguages, -} from "~/models" - -type ActionsInput = { - name: string - condition: { - field?: ActionFeedField - operator?: ActionOperation - value?: string - }[] - result: { - translation?: string - summary?: boolean - readability?: boolean - rewriteRules?: { - from: string - to: string - }[] - blockRules?: { - field?: ActionEntryField - operator?: ActionOperation - value?: string | number - }[] - } -}[] +import type { ActionFeedField, ActionOperation, ActionsInput, SupportedLanguages } from "~/models" const TransitionOptions: { name: string @@ -620,6 +592,56 @@ export function ActionCard({ )} + + + { + if (open) { + data.result.webhooks = [""] + } else { + delete data.result.webhooks + } + onChange(data) + }} + > + {data.result.webhooks && data.result.webhooks.length > 0 && ( + <> + {data.result.webhooks.map((webhook, rewriteIdx) => { + return ( +
+ { + if (data.result.webhooks?.length === 1) { + delete data.result.webhooks + } else { + data.result.webhooks?.splice(rewriteIdx, 1) + } + onChange(data) + }} + /> + { + data.result.webhooks![rewriteIdx] = e.target.value + onChange(data) + }} + /> +
+ ) + })} + { + data.result.webhooks!.push("") + onChange(data) + }} + /> + + )} +
diff --git a/apps/renderer/src/pages/settings/(settings)/actions.tsx b/apps/renderer/src/pages/settings/(settings)/actions.tsx index 89fc2e25f..95858cdd4 100644 --- a/apps/renderer/src/pages/settings/(settings)/actions.tsx +++ b/apps/renderer/src/pages/settings/(settings)/actions.tsx @@ -7,7 +7,7 @@ import { Button } from "~/components/ui/button" import { useAuthQuery } from "~/hooks/common" import { apiClient } from "~/lib/api-fetch" import { toastFetchError } from "~/lib/error-parser" -import type { ActionEntryField, ActionFeedField, ActionOperation, ActionsResponse } from "~/models" +import type { ActionsInput, ActionsResponse } from "~/models" import { ActionCard } from "~/modules/settings/action-card" import { SettingsTitle } from "~/modules/settings/title" import { defineSettingPageData } from "~/modules/settings/utils" @@ -22,28 +22,6 @@ export const loader = defineSettingPageData({ priority, }) -type ActionsInput = { - name: string - condition: { - field?: ActionFeedField - operator?: ActionOperation - value?: string - }[] - result: { - translation?: string - summary?: boolean - rewriteRules?: { - from: string - to: string - }[] - blockRules?: { - field?: ActionEntryField - operator?: ActionOperation - value?: string | number - }[] - } -}[] - export function Component() { const { t } = useTranslation("settings") const actions = useAuthQuery(Queries.action.getAll()) @@ -63,6 +41,7 @@ export function Component() { action.result.blockRules = action.result.blockRules?.filter( (r) => r.field && r.operator && r.value, ) + action.result.webhooks = action.result.webhooks?.filter((w) => w) }) await apiClient.actions.$put({ json: { diff --git a/locales/errors/en.json b/locales/errors/en.json index b27719fb8..2645c057f 100644 --- a/locales/errors/en.json +++ b/locales/errors/en.json @@ -4,6 +4,7 @@ "1001": "create session failed", "1002": "Invalid parameter", "1003": "Invalid invitation", + "1004": "No permission", "2000": "Only admins can refresh feeds", "2001": "Feed not found", "2002": "feedId or url required", diff --git a/locales/settings/en.json b/locales/settings/en.json index 9f29e3a3a..25a780215 100644 --- a/locales/settings/en.json +++ b/locales/settings/en.json @@ -39,6 +39,7 @@ "actions.action_card.to": "To", "actions.action_card.translate_into": "Translate into", "actions.action_card.value": "Value", + "actions.action_card.webhooks": "Webhooks", "actions.action_card.when_feeds_match": "When feeds match…", "actions.newRule": "New Rule", "actions.save": "Save", diff --git a/packages/shared/src/hono.ts b/packages/shared/src/hono.ts index 274984fdb..9199002b4 100644 --- a/packages/shared/src/hono.ts +++ b/packages/shared/src/hono.ts @@ -224,6 +224,7 @@ declare const actions: drizzle_orm_pg_core.PgTableWithColumns<{ operator: z.infer; value: string | number; }[]; + webhooks?: string[]; }; }[]; driverParam: unknown; @@ -281,6 +282,7 @@ declare const actionsItemOpenAPISchema: z.ZodObject<{ field: "title" | "all" | "content" | "author" | "url" | "order"; operator: "contains" | "not_contains" | "eq" | "not_eq" | "gt" | "lt" | "regex"; }>, "many">>; + webhooks: z.ZodOptional>; }, "strip", z.ZodTypeAny, { summary?: boolean | undefined; translation?: "en" | "ja" | "zh-CN" | "zh-TW" | undefined; @@ -294,6 +296,7 @@ declare const actionsItemOpenAPISchema: z.ZodObject<{ field: "title" | "all" | "content" | "author" | "url" | "order"; operator: "contains" | "not_contains" | "eq" | "not_eq" | "gt" | "lt" | "regex"; }[] | undefined; + webhooks?: string[] | undefined; }, { summary?: boolean | undefined; translation?: "en" | "ja" | "zh-CN" | "zh-TW" | undefined; @@ -307,6 +310,7 @@ declare const actionsItemOpenAPISchema: z.ZodObject<{ field: "title" | "all" | "content" | "author" | "url" | "order"; operator: "contains" | "not_contains" | "eq" | "not_eq" | "gt" | "lt" | "regex"; }[] | undefined; + webhooks?: string[] | undefined; }>; }, "strip", z.ZodTypeAny, { name: string; @@ -323,6 +327,7 @@ declare const actionsItemOpenAPISchema: z.ZodObject<{ field: "title" | "all" | "content" | "author" | "url" | "order"; operator: "contains" | "not_contains" | "eq" | "not_eq" | "gt" | "lt" | "regex"; }[] | undefined; + webhooks?: string[] | undefined; }; condition: { value: string; @@ -344,6 +349,7 @@ declare const actionsItemOpenAPISchema: z.ZodObject<{ field: "title" | "all" | "content" | "author" | "url" | "order"; operator: "contains" | "not_contains" | "eq" | "not_eq" | "gt" | "lt" | "regex"; }[] | undefined; + webhooks?: string[] | undefined; }; condition: { value: string; @@ -401,6 +407,7 @@ declare const actionsOpenAPISchema: z.ZodObject, "many">>; + webhooks: z.ZodOptional>; }, "strip", z.ZodTypeAny, { summary?: boolean | undefined; translation?: "en" | "ja" | "zh-CN" | "zh-TW" | undefined; @@ -414,6 +421,7 @@ declare const actionsOpenAPISchema: z.ZodObject; }, "strip", z.ZodTypeAny, { name: string; @@ -443,6 +452,7 @@ declare const actionsOpenAPISchema: z.ZodObject; declare const _routes: hono_hono_base.HonoBase Date: Sun, 29 Sep 2024 09:23:51 +0800 Subject: [PATCH 23/88] fix: remove clamp limit, close #688 --- .../src/modules/entry-column/Items/social-media-item.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/renderer/src/modules/entry-column/Items/social-media-item.tsx b/apps/renderer/src/modules/entry-column/Items/social-media-item.tsx index 0d1703a9d..c3f9ccc34 100644 --- a/apps/renderer/src/modules/entry-column/Items/social-media-item.tsx +++ b/apps/renderer/src/modules/entry-column/Items/social-media-item.tsx @@ -58,7 +58,7 @@ export const SocialMediaItem: EntryListItemFC = ({ entryId, entryPreview, transl >
-
+
{entry.entries.author || feed.title} From fd30789d86a6980aa4b1c4ea45c81c7b7deb3e15 Mon Sep 17 00:00:00 2001 From: Stephen Zhou Date: Sun, 29 Sep 2024 09:58:33 +0800 Subject: [PATCH 24/88] fix: add feed from url, close #686 --- apps/main/src/lib/router.ts | 7 ++++--- .../src/providers/extension-expose-provider.tsx | 10 ++++++++-- packages/shared/src/bridge.ts | 2 +- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/apps/main/src/lib/router.ts b/apps/main/src/lib/router.ts index 8316cecfe..2d9421ac0 100644 --- a/apps/main/src/lib/router.ts +++ b/apps/main/src/lib/router.ts @@ -24,10 +24,11 @@ export const handleUrlRouting = (url: string) => { mainWindow.focus() const caller = callWindowExpose(mainWindow) - const id = searchParams.get("id") + const id = searchParams.get("id") ?? undefined const isList = searchParams.get("type") === "list" - if (!id) return - caller.follow(id, { isList }) + const urlParam = searchParams.get("url") ?? undefined + if (!id && !url) return + caller.follow({ isList, id, url: urlParam }) return } default: { diff --git a/apps/renderer/src/providers/extension-expose-provider.tsx b/apps/renderer/src/providers/extension-expose-provider.tsx index 46b875a06..48a35b321 100644 --- a/apps/renderer/src/providers/extension-expose-provider.tsx +++ b/apps/renderer/src/providers/extension-expose-provider.tsx @@ -33,13 +33,19 @@ export const ExtensionExposeProvider = () => { const presentUserProfile = usePresentUserProfileModal("dialog") useEffect(() => { registerGlobalContext({ - follow(id, options) { + follow(options) { present({ title: options?.isList ? t("sidebar.feed_actions.edit_list") : t("sidebar.feed_actions.edit_feed"), content: ({ dismiss }) => ( - + ), }) }, diff --git a/packages/shared/src/bridge.ts b/packages/shared/src/bridge.ts index e33e73dfb..13db314a3 100644 --- a/packages/shared/src/bridge.ts +++ b/packages/shared/src/bridge.ts @@ -21,7 +21,7 @@ interface RenderGlobalContext { onWindowShow: () => void /// Actions - follow: (id: string, options?: { isList: boolean }) => void + follow: (options?: { isList: boolean; id?: string; url?: string }) => void profile: (id: string, variant?: "drawer" | "dialog") => void /// Utils From a60ea08fca9462ea1acd18ee81d40c140bb9b5d5 Mon Sep 17 00:00:00 2001 From: Stephen Zhou Date: Sun, 29 Sep 2024 10:00:01 +0800 Subject: [PATCH 25/88] chore: update --- apps/main/src/lib/router.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/main/src/lib/router.ts b/apps/main/src/lib/router.ts index 2d9421ac0..925c40e28 100644 --- a/apps/main/src/lib/router.ts +++ b/apps/main/src/lib/router.ts @@ -27,7 +27,7 @@ export const handleUrlRouting = (url: string) => { const id = searchParams.get("id") ?? undefined const isList = searchParams.get("type") === "list" const urlParam = searchParams.get("url") ?? undefined - if (!id && !url) return + if (!id && !urlParam) return caller.follow({ isList, id, url: urlParam }) return } From a060986fa3107f8f5e050b430787014dd9bbdc10 Mon Sep 17 00:00:00 2001 From: Stephen Zhou Date: Sun, 29 Sep 2024 10:23:01 +0800 Subject: [PATCH 26/88] fix: reset feed search, close #701 --- apps/renderer/src/modules/settings/tabs/lists.tsx | 6 +++++- apps/renderer/src/store/feed/hooks.ts | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/apps/renderer/src/modules/settings/tabs/lists.tsx b/apps/renderer/src/modules/settings/tabs/lists.tsx index 4b0e86fc1..14eb31f6d 100644 --- a/apps/renderer/src/modules/settings/tabs/lists.tsx +++ b/apps/renderer/src/modules/settings/tabs/lists.tsx @@ -345,7 +345,11 @@ export const ListFeedsModalContent = ({ id }: { id: string }) => { const { t } = useTranslation("settings") const [feedSearchFor, setFeedSearchFor] = useState("") - const addMutation = useAddFeedToFeedList() + const addMutation = useAddFeedToFeedList({ + onSuccess: () => { + setFeedSearchFor("") + }, + }) const allFeeds = useSubscriptionStore((store) => { const feedInfo = [] as { title: string; id: string }[] diff --git a/apps/renderer/src/store/feed/hooks.ts b/apps/renderer/src/store/feed/hooks.ts index 726c58975..092eb9439 100644 --- a/apps/renderer/src/store/feed/hooks.ts +++ b/apps/renderer/src/store/feed/hooks.ts @@ -62,7 +62,10 @@ export const useFeedHeaderTitle = () => { } } -export const useAddFeedToFeedList = (options?: { onSuccess: () => void; onError: () => void }) => { +export const useAddFeedToFeedList = (options?: { + onSuccess?: () => void + onError?: () => void +}) => { const { t } = useTranslation("settings") return useMutation({ mutationFn: async ( From f1ce5df581c0a91967d3d093b6735e2fdd3ea906 Mon Sep 17 00:00:00 2001 From: Innei Date: Sun, 29 Sep 2024 14:19:56 +0800 Subject: [PATCH 27/88] fix: don't auto focus in user profile modal Signed-off-by: Innei --- apps/renderer/src/modules/profile/hooks.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/renderer/src/modules/profile/hooks.ts b/apps/renderer/src/modules/profile/hooks.ts index 434f497c7..e3bb10d00 100644 --- a/apps/renderer/src/modules/profile/hooks.ts +++ b/apps/renderer/src/modules/profile/hooks.ts @@ -50,6 +50,7 @@ export const usePresentUserProfileModal = (variant: Variant = "dialog") => { (userId: string | undefined, overrideVariant?: Variant) => { if (!userId) return const finalVariant = overrideVariant || variant + present({ title: "User Profile", content: () => @@ -61,6 +62,7 @@ export const usePresentUserProfileModal = (variant: Variant = "dialog") => { clickOutsideToDismiss: true, modal: finalVariant === "dialog", overlay: finalVariant === "dialog", + autoFocus: false, modalContainerClassName: finalVariant === "drawer" ? "right-4 left-[auto] top-4 bottom-4" : "", }) From 12f3965f6ac093d0b88eb5e25f47651649dc6ddd Mon Sep 17 00:00:00 2001 From: duo Date: Sun, 29 Sep 2024 14:20:47 +0800 Subject: [PATCH 28/88] fix: ShortcutMode cannot be closed using shortcuts keys (#708) Co-authored-by: Stephen Zhou --- .../src/components/ui/modal/stacked/hooks.tsx | 6 ++++++ apps/renderer/src/modules/modal/shortcuts.tsx | 16 +++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/apps/renderer/src/components/ui/modal/stacked/hooks.tsx b/apps/renderer/src/components/ui/modal/stacked/hooks.tsx index 38bb909a4..0598c5868 100644 --- a/apps/renderer/src/components/ui/modal/stacked/hooks.tsx +++ b/apps/renderer/src/components/ui/modal/stacked/hooks.tsx @@ -64,6 +64,12 @@ export const useModalStack = (options?: ModalStackOptions) => { } } const actions = { + getTopModalStack() { + return jotaiStore.get(modalStackAtom)[0] + }, + getModalStackById(id: string) { + return jotaiStore.get(modalStackAtom).find((item) => item.id === id) + }, dismiss(id: string) { jotaiStore.set(modalStackAtom, (p) => p.filter((item) => item.id !== id)) }, diff --git a/apps/renderer/src/modules/modal/shortcuts.tsx b/apps/renderer/src/modules/modal/shortcuts.tsx index 99d416f56..de07e170a 100644 --- a/apps/renderer/src/modules/modal/shortcuts.tsx +++ b/apps/renderer/src/modules/modal/shortcuts.tsx @@ -81,16 +81,26 @@ const ShortcutModalContent = () => { } export const useShortcutsModal = () => { - const { present } = useModalStack() + const { present, dismiss, getModalStackById } = useModalStack() + const id = "shortcuts" - return useCallback(() => { + const showShortcutsModal = useCallback(() => { present({ title: "Shortcuts", + id, overlay: false, - id: "shortcuts", content: () => , CustomModalComponent: PlainModal, clickOutsideToDismiss: true, }) }, [present]) + + return useCallback(() => { + const shortcutsModal = getModalStackById(id) + if (shortcutsModal && shortcutsModal.modal) { + dismiss(id) + return + } + showShortcutsModal() + }, [dismiss, getModalStackById, showShortcutsModal]) } From 248369afe6d085885fd76a4ecf6a3f9b692b14cf Mon Sep 17 00:00:00 2001 From: Innei Date: Sun, 29 Sep 2024 16:51:32 +0800 Subject: [PATCH 29/88] fix: drawer top edge anchor Signed-off-by: Innei --- .../src/components/ui/modal/stacked/modal.tsx | 1 - apps/renderer/src/modules/profile/hooks.ts | 2 +- apps/renderer/src/styles/tailwind-extend.css | 6 ---- tailwind.config.ts | 28 +++++++++++++++++++ 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/apps/renderer/src/components/ui/modal/stacked/modal.tsx b/apps/renderer/src/components/ui/modal/stacked/modal.tsx index e67ec4350..5d3961ea9 100644 --- a/apps/renderer/src/components/ui/modal/stacked/modal.tsx +++ b/apps/renderer/src/components/ui/modal/stacked/modal.tsx @@ -263,7 +263,6 @@ export const ModalInternal = memo( className={cn( "no-drag-region fixed z-20", modal ? "inset-0 overflow-auto" : "left-0 top-0", - "safe-inset-top", currentIsClosing ? "!pointer-events-none" : "!pointer-events-auto", modalContainerClassName, )} diff --git a/apps/renderer/src/modules/profile/hooks.ts b/apps/renderer/src/modules/profile/hooks.ts index e3bb10d00..d951ac364 100644 --- a/apps/renderer/src/modules/profile/hooks.ts +++ b/apps/renderer/src/modules/profile/hooks.ts @@ -64,7 +64,7 @@ export const usePresentUserProfileModal = (variant: Variant = "dialog") => { overlay: finalVariant === "dialog", autoFocus: false, modalContainerClassName: - finalVariant === "drawer" ? "right-4 left-[auto] top-4 bottom-4" : "", + finalVariant === "drawer" ? tw`right-4 left-[auto] safe-inset-top-4 bottom-4` : "", }) }, [present, variant], diff --git a/apps/renderer/src/styles/tailwind-extend.css b/apps/renderer/src/styles/tailwind-extend.css index 7501cea09..ecc73feba 100644 --- a/apps/renderer/src/styles/tailwind-extend.css +++ b/apps/renderer/src/styles/tailwind-extend.css @@ -379,9 +379,3 @@ } } } - -@layer utilities { - .safe-inset-top { - top: var(--fo-window-padding-top, 0); - } -} diff --git a/tailwind.config.ts b/tailwind.config.ts index 14526a5ad..e89d7e270 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -23,6 +23,9 @@ export default resolveConfig({ }, extend: { + spacing: { + "safe-inset-top": "var(--fo-window-padding-top, 0)", + }, fontFamily: { theme: "var(--fo-font-family)", default: "SN pro, sans-serif, system-ui", @@ -140,6 +143,31 @@ export default resolveConfig({ addVariant("group-motion-reduce", ':merge(.group)[data-motion-reduce="true"] &') addVariant("peer-motion-reduce", ':merge(.peer)[data-motion-reduce="true"] ~ &') }), + plugin(({ addUtilities, matchUtilities, theme }) => { + addUtilities({ + ".safe-inset-top": { + top: "var(--fo-window-padding-top, 0)", + }, + }) + + const safeInsetTopVariants = {} + for (let i = 1; i <= 16; i++) { + safeInsetTopVariants[`.safe-inset-top-${i}`] = { + top: `calc(var(--fo-window-padding-top, 0px) + ${theme(`spacing.${i}`)})`, + } + } + addUtilities(safeInsetTopVariants) + + // Add arbitrary value support + matchUtilities( + { + "safe-inset-top": (value) => ({ + top: `calc(var(--fo-window-padding-top, 0px) + ${value})`, + }), + }, + { values: theme("spacing") }, + ) + }), ], }) From 8ba5822a29a76a8e9817967a6af2bde0cb846460 Mon Sep 17 00:00:00 2001 From: Whitewater Date: Sun, 29 Sep 2024 16:57:36 +0800 Subject: [PATCH 30/88] feat: view source content in app (#655) * feat: support source content view * refactor: use context menu for toggling source content view * refactor: update source content view entry * refactor: show source content in modal in social media and video * refactor: add SourceContentView component for displaying external content * feat: add banner for unsupported websites in SourceContentView * refactor: replace iframe with SourceContentView in source content modal * chore: clean code * chore: update i18n * fix: overflow in image view * chore: add fi icon Signed-off-by: Innei * fix: improve loading stability in SourceContentView --------- Signed-off-by: Innei Co-authored-by: Innei --- apps/renderer/src/atoms/source-content.tsx | 31 ++++ .../src/hooks/biz/useEntryActions.tsx | 41 ++++- .../src/hooks/biz/useNavigateEntry.ts | 2 + .../components/SourceContentView.tsx | 95 +++++++++++ .../src/modules/entry-content/index.tsx | 154 +++++++++--------- icons/mgc/world_2_cute_fi.svg | 1 + locales/app/en.json | 1 + locales/app/zh-CN.json | 1 + 8 files changed, 250 insertions(+), 76 deletions(-) create mode 100644 apps/renderer/src/atoms/source-content.tsx create mode 100644 apps/renderer/src/modules/entry-content/components/SourceContentView.tsx create mode 100644 icons/mgc/world_2_cute_fi.svg diff --git a/apps/renderer/src/atoms/source-content.tsx b/apps/renderer/src/atoms/source-content.tsx new file mode 100644 index 000000000..e89de49b4 --- /dev/null +++ b/apps/renderer/src/atoms/source-content.tsx @@ -0,0 +1,31 @@ +import { atom } from "jotai" +import { useCallback } from "react" + +import { useModalStack } from "~/components/ui/modal" +import { createAtomHooks } from "~/lib/jotai" +import { SourceContentView } from "~/modules/entry-content/components/SourceContentView" + +export const [, , useShowSourceContent, , getShowSourceContent, setShowSourceContent] = + createAtomHooks(atom(false)) + +export const toggleShowSourceContent = () => setShowSourceContent(!getShowSourceContent()) +export const resetShowSourceContent = () => setShowSourceContent(false) + +export const useSourceContentModal = () => { + const { present } = useModalStack() + + return useCallback( + ({ title, src }: { title?: string; src: string }) => { + present({ + id: src, + title, + content: () => , + resizeable: true, + clickOutsideToDismiss: true, + // The number was picked arbitrarily + resizeDefaultSize: { width: 900, height: 700 }, + }) + }, + [present], + ) +} diff --git a/apps/renderer/src/hooks/biz/useEntryActions.tsx b/apps/renderer/src/hooks/biz/useEntryActions.tsx index ad1eda01c..52897d4ff 100644 --- a/apps/renderer/src/hooks/biz/useEntryActions.tsx +++ b/apps/renderer/src/hooks/biz/useEntryActions.tsx @@ -13,6 +13,12 @@ import { setReadabilityStatus, } from "~/atoms/readability" import { useIntegrationSettingKey } from "~/atoms/settings/integration" +import { + setShowSourceContent, + toggleShowSourceContent, + useShowSourceContent, + useSourceContentModal, +} from "~/atoms/source-content" import { whoami } from "~/atoms/user" import { mountLottie } from "~/components/ui/lottie-container" import { @@ -23,6 +29,7 @@ import { import { shortcuts } from "~/constants/shortcuts" import { tipcClient } from "~/lib/client" import { nextFrame } from "~/lib/dom" +import { FeedViewType } from "~/lib/enum" import { getOS } from "~/lib/utils" import StarAnimationUri from "~/lottie/star.lottie?url" import type { CombinedEntryModel } from "~/models" @@ -31,6 +38,8 @@ import type { FlatEntryModel } from "~/store/entry" import { entryActions } from "~/store/entry" import { useFeedById } from "~/store/feed" +import { navigateEntry } from "./useNavigateEntry" + const absoluteStarAnimationUri = new URL(StarAnimationUri, import.meta.url).href export const useEntryReadabilityToggle = ({ id, url }: { id: string; url: string }) => @@ -148,6 +157,9 @@ export const useEntryActions = ({ entryId: populatedEntry?.entries.id ?? undefined, }) + const showSourceContent = useShowSourceContent() + const showSourceContentModal = useSourceContentModal() + const collect = useCollect(populatedEntry) const uncollect = useUnCollect(populatedEntry) const read = useRead() @@ -344,12 +356,36 @@ export const useEntryActions = ({ }), shortcut: shortcuts.entry.openInBrowser.key, className: "i-mgc-world-2-cute-re", - hide: !populatedEntry.entries.url, + hide: type === "toolbar" || !populatedEntry.entries.url, onClick: () => { if (!populatedEntry.entries.url) return window.open(populatedEntry.entries.url, "_blank") }, }, + { + key: "viewSourceContent", + name: t("entry_actions.view_source_content"), + // shortcut: shortcuts.entry.openInBrowser.key, + className: !showSourceContent ? "i-mgc-world-2-cute-re" : tw`i-mgc-world-2-cute-fi`, + hide: !populatedEntry.entries.url, + active: showSourceContent, + onClick: () => { + if (!populatedEntry.entries.url) return + if (view === FeedViewType.SocialMedia || view === FeedViewType.Videos) { + showSourceContentModal({ + title: populatedEntry.entries.title ?? undefined, + src: populatedEntry.entries.url, + }) + return + } + if (type === "toolbar") { + toggleShowSourceContent() + return + } + navigateEntry({ entryId: populatedEntry.entries.id }) + setShowSourceContent(true) + }, + }, { name: t("entry_actions.share"), key: "share", @@ -406,9 +442,12 @@ export const useEntryActions = ({ instapaperPassword, instapaperUsername, feed?.ownerUserId, + type, + showSourceContent, openTipModal, collect, uncollect, + showSourceContentModal, read, unread, ]) diff --git a/apps/renderer/src/hooks/biz/useNavigateEntry.ts b/apps/renderer/src/hooks/biz/useNavigateEntry.ts index cd7f55f66..694ea88bf 100644 --- a/apps/renderer/src/hooks/biz/useNavigateEntry.ts +++ b/apps/renderer/src/hooks/biz/useNavigateEntry.ts @@ -2,6 +2,7 @@ import { isUndefined } from "lodash-es" import { getReadonlyRoute, getStableRouterNavigate } from "~/atoms/route" import { setSidebarActiveView } from "~/atoms/sidebar" +import { resetShowSourceContent } from "~/atoms/source-content" import { ROUTE_ENTRY_PENDING, ROUTE_FEED_IN_FOLDER, ROUTE_FEED_PENDING } from "~/constants" import { FeedViewType } from "~/lib/enum" @@ -37,6 +38,7 @@ export const navigateEntry = (options: NavigateEntryOptions) => { nextSearchParams.set("view", view.toString()) setSidebarActiveView(view) } + resetShowSourceContent() const finalView = nextSearchParams.get("view") diff --git a/apps/renderer/src/modules/entry-content/components/SourceContentView.tsx b/apps/renderer/src/modules/entry-content/components/SourceContentView.tsx new file mode 100644 index 000000000..fb10c85ad --- /dev/null +++ b/apps/renderer/src/modules/entry-content/components/SourceContentView.tsx @@ -0,0 +1,95 @@ +import { AnimatePresence } from "framer-motion" +import { useEffect, useRef, useState } from "react" + +import { useShowSourceContent } from "~/atoms/source-content" +import { m } from "~/components/common/Motion" +import { softSpringPreset } from "~/components/ui/constants/spring" + +import { EntryContentLoading } from "../loading" + +const ViewTag = window.electron ? "webview" : "iframe" +const variants = { + hidden: { x: "100%" }, + visible: { x: 0 }, + exit: { x: "100%" }, +} + +const Banner = () => { + return ( +
+
+

Some websites can't be displayed here. Download desktop app to view it.

+
+
+ ) +} + +export const SourceContentView = ({ src }: { src: string }) => { + const showSourceContent = useShowSourceContent() + const [loading, setLoading] = useState(true) + const webviewRef = useRef(null) + + useEffect(() => { + const abortController = new AbortController() + const webview = webviewRef.current + if (!webview) return + const handleDidStopLoading = () => setLoading(false) + + // See https://www.electronjs.org/docs/latest/api/webview-tag#example + webview.addEventListener("did-start-loading", handleDidStopLoading, { + signal: abortController.signal, + }) + + return () => { + abortController.abort() + } + }, [src, showSourceContent]) + + return ( + <> + {!window.electron && } +
+ {loading && ( +
+ +
+ )} + + setLoading(false)} + /> + +
+ + ) +} + +export const SourceContentPanel = ({ src }: { src: string | null }) => { + const showSourceContent = useShowSourceContent() + return ( + + {showSourceContent && src && ( + + + + )} + + ) +} diff --git a/apps/renderer/src/modules/entry-content/index.tsx b/apps/renderer/src/modules/entry-content/index.tsx index 986967ab5..a2854264b 100644 --- a/apps/renderer/src/modules/entry-content/index.tsx +++ b/apps/renderer/src/modules/entry-content/index.tsx @@ -45,6 +45,7 @@ import { EntryPlaceholderDaily } from "../ai/ai-daily/EntryPlaceholderDaily" import { setEntryContentScrollToTop, setEntryTitleMeta } from "./atoms" import { EntryPlaceholderLogo } from "./components/EntryPlaceholderLogo" import { EntryTitle } from "./components/EntryTitle" +import { SourceContentPanel } from "./components/SourceContentView" import { SupportCreator } from "./components/SupportCreator" import { EntryHeader } from "./header" import { EntryContentLoading } from "./loading" @@ -174,88 +175,91 @@ export const EntryContentRender: Component<{ compact={compact} /> - -
+ -
- +
+ - -
- - {(summary.isLoading || summary.data) && ( -
-
- - {t("entry_content.ai_summary")} + +
+ + {(summary.isLoading || summary.data) && ( +
+
+ + {t("entry_content.ai_summary")} +
+ + {summary.isLoading ? SummaryLoadingSkeleton : summary.data} +
- - {summary.isLoading ? SummaryLoadingSkeleton : summary.data} - -
- )} - - {!isInReadabilityMode ? ( - - - {content} - - - ) : ( - )} - -
- + + {!isInReadabilityMode ? ( + + + {content} + + + ) : ( + + )} + +
+ - {entry.settings?.readability && ( - - )} + {entry.settings?.readability && ( + + )} - {!content && ( -
- {isPending ? ( - - ) : error ? ( -
- - Network Error + {!content && ( +
+ {isPending ? ( + + ) : error ? ( +
+ + Network Error -
-                      {error.message}
-                    
-
- ) : ( - - )} -
- )} +
+                        {error.message}
+                      
+
+ ) : ( + + )} +
+ )} - {feed?.ownerUserId && } -
-
-
+ {feed?.ownerUserId && } + +
+ + +
) } @@ -346,13 +350,13 @@ const NoContent: FC<{ {t("entry_content.web_app_notice")}
)} - {url && window.electron && } + {url && window.electron && }
) } -const ReadabilityAutoToggle = ({ url, id }: { url: string; id: string }) => { +const ReadabilityAutoToggleEffect = ({ url, id }: { url: string; id: string }) => { const toggle = useEntryReadabilityToggle({ id, url, diff --git a/icons/mgc/world_2_cute_fi.svg b/icons/mgc/world_2_cute_fi.svg new file mode 100644 index 000000000..242779d70 --- /dev/null +++ b/icons/mgc/world_2_cute_fi.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/locales/app/en.json b/locales/app/en.json index b9b289aa0..0fb119b6e 100644 --- a/locales/app/en.json +++ b/locales/app/en.json @@ -48,6 +48,7 @@ "entry_actions.tip": "Tip", "entry_actions.unstar": "Unstar", "entry_actions.unstarred": "Unstarred.", + "entry_actions.view_source_content": "View source content", "entry_column.filtered_content_tip": "You have filtered content hidden.", "entry_column.filtered_content_tip_2": "In addition to the entries shown above, there is also filtered content.", "entry_column.refreshing": "Refreshing new entries...", diff --git a/locales/app/zh-CN.json b/locales/app/zh-CN.json index 60c090c08..12f0484d7 100644 --- a/locales/app/zh-CN.json +++ b/locales/app/zh-CN.json @@ -48,6 +48,7 @@ "entry_actions.tip": "打赏", "entry_actions.unstar": "取消收藏", "entry_actions.unstarred": "取消收藏", + "entry_actions.view_source_content": "查看原文", "entry_column.filtered_content_tip": "部分内容已被过滤隐藏", "entry_column.filtered_content_tip_2": "除了上面显示的内容外,还有一些被过滤的内容", "entry_column.refreshing": "正在刷新", From 67e305ccc6b33ca6e81ce68af9f9522219f9a067 Mon Sep 17 00:00:00 2001 From: Alan Ye Date: Sun, 29 Sep 2024 16:57:58 +0800 Subject: [PATCH 31/88] fix(i18n/zh): improve translation text in `wallet.transaction` table (#706) --- locales/settings/zh-CN.json | 4 ++-- locales/settings/zh-TW.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/locales/settings/zh-CN.json b/locales/settings/zh-CN.json index 90195f7b9..c70a1392d 100644 --- a/locales/settings/zh-CN.json +++ b/locales/settings/zh-CN.json @@ -216,10 +216,10 @@ "wallet.sidebar_title": "Power", "wallet.transactions.amount": "数量", "wallet.transactions.date": "日期", - "wallet.transactions.from": "发送至", + "wallet.transactions.from": "发送者", "wallet.transactions.noTransactions": "无交易记录", "wallet.transactions.title": "交易记录", - "wallet.transactions.to": "接收自", + "wallet.transactions.to": "接收者", "wallet.transactions.tx": "交易", "wallet.transactions.type": "类型", "wallet.transactions.types.burn": "销毁", diff --git a/locales/settings/zh-TW.json b/locales/settings/zh-TW.json index 97e1160b5..2e897d27b 100644 --- a/locales/settings/zh-TW.json +++ b/locales/settings/zh-TW.json @@ -181,10 +181,10 @@ "wallet.sidebar_title": "Power", "wallet.transactions.amount": "數量", "wallet.transactions.date": "日期", - "wallet.transactions.from": "發送至", + "wallet.transactions.from": "發送者", "wallet.transactions.noTransactions": "無交易紀錄", "wallet.transactions.title": "交易紀錄", - "wallet.transactions.to": "接收自", + "wallet.transactions.to": "接收者", "wallet.transactions.tx": "交易", "wallet.transactions.type": "類型", "wallet.transactions.types.burn": "burn", From 4478517566aced3e55928229433a4cc83dd0c3ae Mon Sep 17 00:00:00 2001 From: Alan Ye Date: Sun, 29 Sep 2024 16:58:47 +0800 Subject: [PATCH 32/88] fix(i18n/en): enhance English grammar (#698) * fix(i18n/en): enhance English grammar * chore: auto-fix linting and formatting issues --------- Co-authored-by: at-wr --- apps/renderer/src/pages/(main)/layout.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/renderer/src/pages/(main)/layout.tsx b/apps/renderer/src/pages/(main)/layout.tsx index 500379994..d11a3064a 100644 --- a/apps/renderer/src/pages/(main)/layout.tsx +++ b/apps/renderer/src/pages/(main)/layout.tsx @@ -86,12 +86,12 @@ export function Component() { return (
-
{APP_NAME} is not supported on mobile devices.
+
{APP_NAME} is not yet supported on mobile devices.
- Your device width is {`${window.innerWidth}`}px less than minimum supported width - 1024px. + Your device width is {`${window.innerWidth}`}px, which is less than the minimum + supported width 1024px.
-
Please use desktop app to using {APP_NAME}
+
Please switch to the desktop app to continue using {APP_NAME}
Download:{" "} From 715683339b14ff77b3e0bf7f5beac68e2d0f6db4 Mon Sep 17 00:00:00 2001 From: Innei Date: Sun, 29 Sep 2024 17:13:36 +0800 Subject: [PATCH 33/88] refactor: extract `getItemComponentByView` Signed-off-by: Innei --- .../src/modules/entry-column/Items/index.ts | 20 +++++++++ .../src/modules/entry-column/item.tsx | 45 ++++--------------- .../(with-layout)/feed/[id]/index.tsx | 36 ++------------- 3 files changed, 32 insertions(+), 69 deletions(-) create mode 100644 apps/renderer/src/modules/entry-column/Items/index.ts diff --git a/apps/renderer/src/modules/entry-column/Items/index.ts b/apps/renderer/src/modules/entry-column/Items/index.ts new file mode 100644 index 000000000..a3e538195 --- /dev/null +++ b/apps/renderer/src/modules/entry-column/Items/index.ts @@ -0,0 +1,20 @@ +import { FeedViewType } from "~/lib/enum" + +import { ArticleItem } from "./article-item" +import { AudioItem } from "./audio-item" +import { NotificationItem } from "./notification-item" +import { PictureItem } from "./picture-item" +import { SocialMediaItem } from "./social-media-item" +import { VideoItem } from "./video-item" + +const map = { + [FeedViewType.Articles]: ArticleItem, + [FeedViewType.SocialMedia]: SocialMediaItem, + [FeedViewType.Pictures]: PictureItem, + [FeedViewType.Videos]: VideoItem, + [FeedViewType.Audios]: AudioItem, + [FeedViewType.Notifications]: NotificationItem, +} +export const getItemComponentByView = (view: FeedViewType) => { + return map[view] || ArticleItem +} diff --git a/apps/renderer/src/modules/entry-column/item.tsx b/apps/renderer/src/modules/entry-column/item.tsx index 3aead765c..be29643cb 100644 --- a/apps/renderer/src/modules/entry-column/item.tsx +++ b/apps/renderer/src/modules/entry-column/item.tsx @@ -11,12 +11,13 @@ import type { FlatEntryModel } from "~/store/entry" import { useEntry } from "~/store/entry/hooks" import { ReactVirtuosoItemPlaceholder } from "../../components/ui/placeholder" -import { ArticleItem, ArticleItemSkeleton } from "./Items/article-item" -import { AudioItem, AudioItemSkeleton } from "./Items/audio-item" -import { NotificationItem, NotificationItemSkeleton } from "./Items/notification-item" -import { PictureItem, PictureItemSkeleton } from "./Items/picture-item" -import { SocialMediaItem, SocialMediaItemSkeleton } from "./Items/social-media-item" -import { VideoItem, VideoItemSkeleton } from "./Items/video-item" +import { getItemComponentByView } from "./Items" +import { ArticleItemSkeleton } from "./Items/article-item" +import { AudioItemSkeleton } from "./Items/audio-item" +import { NotificationItemSkeleton } from "./Items/notification-item" +import { PictureItemSkeleton } from "./Items/picture-item" +import { SocialMediaItemSkeleton } from "./Items/social-media-item" +import { VideoItemSkeleton } from "./Items/video-item" import { EntryItemWrapper } from "./layouts/EntryItemWrapper" import { girdClassNames } from "./styles" import type { EntryListItemFC } from "./types" @@ -42,37 +43,7 @@ function EntryItemImpl({ entry, view }: { entry: FlatEntryModel; view?: number } }, ) - let Item: EntryListItemFC - - switch (view) { - case FeedViewType.Articles: { - Item = ArticleItem - break - } - case FeedViewType.SocialMedia: { - Item = SocialMediaItem - break - } - case FeedViewType.Pictures: { - Item = PictureItem - break - } - case FeedViewType.Videos: { - Item = VideoItem - break - } - case FeedViewType.Audios: { - Item = AudioItem - break - } - case FeedViewType.Notifications: { - Item = NotificationItem - break - } - default: { - Item = ArticleItem - } - } + const Item: EntryListItemFC = getItemComponentByView(view as FeedViewType) return ( diff --git a/apps/renderer/src/pages/(external)/(with-layout)/feed/[id]/index.tsx b/apps/renderer/src/pages/(external)/(with-layout)/feed/[id]/index.tsx index ff4ec2824..d5df352b3 100644 --- a/apps/renderer/src/pages/(external)/(with-layout)/feed/[id]/index.tsx +++ b/apps/renderer/src/pages/(external)/(with-layout)/feed/[id]/index.tsx @@ -13,14 +13,10 @@ import { LoadingCircle } from "~/components/ui/loading" import { views } from "~/constants" import { usePresentFeedFormModal } from "~/hooks/biz/useFeedFormModal" import { useTitle } from "~/hooks/common" -import { FeedViewType } from "~/lib/enum" +import type { FeedViewType } from "~/lib/enum" import { cn } from "~/lib/utils" import type { FeedModel } from "~/models" -import { ArticleItem } from "~/modules/entry-column/Items/article-item" -import { NotificationItem } from "~/modules/entry-column/Items/notification-item" -import { PictureItem } from "~/modules/entry-column/Items/picture-item" -import { SocialMediaItem } from "~/modules/entry-column/Items/social-media-item" -import { VideoItem } from "~/modules/entry-column/Items/video-item" +import { getItemComponentByView } from "~/modules/entry-column/Items" import type { UniversalItemProps } from "~/modules/entry-column/types" import { useEntriesPreview } from "~/queries/entries" import { useFeed } from "~/queries/feed" @@ -39,32 +35,8 @@ export function Component() { id, }) - let Item: FC - switch (view) { - case FeedViewType.Articles: { - Item = ArticleItem - break - } - case FeedViewType.SocialMedia: { - Item = SocialMediaItem - break - } - case FeedViewType.Pictures: { - Item = PictureItem - break - } - case FeedViewType.Videos: { - Item = VideoItem - break - } - case FeedViewType.Notifications: { - Item = NotificationItem - break - } - default: { - Item = ArticleItem - } - } + const Item: FC = getItemComponentByView(view as FeedViewType) + const { t } = useTranslation("external") useTitle(feed.data?.feed.title) const presentFeedFormModal = usePresentFeedFormModal() From c0e2f92793c6b94cf8ad21e4e9a2c5ced740e281 Mon Sep 17 00:00:00 2001 From: Innei Date: Sun, 29 Sep 2024 17:14:47 +0800 Subject: [PATCH 34/88] chore: extract skeleton also Signed-off-by: Innei --- .../src/modules/entry-column/Items/index.ts | 29 ++++++++++++++----- .../src/modules/entry-column/item.tsx | 21 ++------------ 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/apps/renderer/src/modules/entry-column/Items/index.ts b/apps/renderer/src/modules/entry-column/Items/index.ts index a3e538195..3bddf6c65 100644 --- a/apps/renderer/src/modules/entry-column/Items/index.ts +++ b/apps/renderer/src/modules/entry-column/Items/index.ts @@ -1,13 +1,13 @@ import { FeedViewType } from "~/lib/enum" -import { ArticleItem } from "./article-item" -import { AudioItem } from "./audio-item" -import { NotificationItem } from "./notification-item" -import { PictureItem } from "./picture-item" -import { SocialMediaItem } from "./social-media-item" -import { VideoItem } from "./video-item" +import { ArticleItem, ArticleItemSkeleton } from "./article-item" +import { AudioItem, AudioItemSkeleton } from "./audio-item" +import { NotificationItem, NotificationItemSkeleton } from "./notification-item" +import { PictureItem, PictureItemSkeleton } from "./picture-item" +import { SocialMediaItem, SocialMediaItemSkeleton } from "./social-media-item" +import { VideoItem, VideoItemSkeleton } from "./video-item" -const map = { +const ItemMap = { [FeedViewType.Articles]: ArticleItem, [FeedViewType.SocialMedia]: SocialMediaItem, [FeedViewType.Pictures]: PictureItem, @@ -16,5 +16,18 @@ const map = { [FeedViewType.Notifications]: NotificationItem, } export const getItemComponentByView = (view: FeedViewType) => { - return map[view] || ArticleItem + return ItemMap[view] || ArticleItem +} + +const SkeletonItemMap = { + [FeedViewType.Articles]: ArticleItemSkeleton, + [FeedViewType.SocialMedia]: SocialMediaItemSkeleton, + [FeedViewType.Pictures]: PictureItemSkeleton, + [FeedViewType.Videos]: VideoItemSkeleton, + [FeedViewType.Audios]: AudioItemSkeleton, + [FeedViewType.Notifications]: NotificationItemSkeleton, +} + +export const getSkeletonItemComponentByView = (view: FeedViewType) => { + return SkeletonItemMap[view] } diff --git a/apps/renderer/src/modules/entry-column/item.tsx b/apps/renderer/src/modules/entry-column/item.tsx index be29643cb..b2db0719c 100644 --- a/apps/renderer/src/modules/entry-column/item.tsx +++ b/apps/renderer/src/modules/entry-column/item.tsx @@ -4,20 +4,14 @@ import { memo } from "react" import { LoadingCircle } from "~/components/ui/loading" import { views } from "~/constants" import { useAuthQuery } from "~/hooks/common" -import { FeedViewType } from "~/lib/enum" +import type { FeedViewType } from "~/lib/enum" import { cn } from "~/lib/utils" import { Queries } from "~/queries" import type { FlatEntryModel } from "~/store/entry" import { useEntry } from "~/store/entry/hooks" import { ReactVirtuosoItemPlaceholder } from "../../components/ui/placeholder" -import { getItemComponentByView } from "./Items" -import { ArticleItemSkeleton } from "./Items/article-item" -import { AudioItemSkeleton } from "./Items/audio-item" -import { NotificationItemSkeleton } from "./Items/notification-item" -import { PictureItemSkeleton } from "./Items/picture-item" -import { SocialMediaItemSkeleton } from "./Items/social-media-item" -import { VideoItemSkeleton } from "./Items/video-item" +import { getItemComponentByView, getSkeletonItemComponentByView } from "./Items" import { EntryItemWrapper } from "./layouts/EntryItemWrapper" import { girdClassNames } from "./styles" import type { EntryListItemFC } from "./types" @@ -58,15 +52,6 @@ export const EntryItem: FC = memo(({ entryId, view }) => { return }) -const SkeletonItemMap = { - [FeedViewType.Articles]: ArticleItemSkeleton, - [FeedViewType.SocialMedia]: SocialMediaItemSkeleton, - [FeedViewType.Pictures]: PictureItemSkeleton, - [FeedViewType.Videos]: VideoItemSkeleton, - [FeedViewType.Audios]: AudioItemSkeleton, - [FeedViewType.Notifications]: NotificationItemSkeleton, -} - const LoadingCircleFallback = (
@@ -77,7 +62,7 @@ export const EntryItemSkeleton: FC<{ view: FeedViewType count?: number }> = memo(({ view, count }) => { - const SkeletonItem = SkeletonItemMap[view] + const SkeletonItem = getSkeletonItemComponentByView(view) if (count === 1) { return SkeletonItem } From 440de7b737f9abcadc68ab1099fd28a8e6710699 Mon Sep 17 00:00:00 2001 From: Jerry Wong Date: Sun, 29 Sep 2024 18:59:54 +0800 Subject: [PATCH 35/88] fix: tooltip content of open image and improve i18n support (#689) feat: complete zh-TW and zh-HK fix: tooltip content of open image Co-authored-by: Innei --- .../src/modules/ai/ai-daily/daily.tsx | 3 +- .../src/modules/ai/ai-daily/hooks.tsx | 3 +- apps/renderer/src/modules/wallet/hooks.ts | 5 ++- locales/app/en.json | 3 ++ locales/app/zh-CN.json | 3 ++ locales/app/zh-HK.json | 4 ++ locales/app/zh-TW.json | 7 ++++ locales/common/zh-HK.json | 1 + locales/common/zh-TW.json | 6 +++ locales/native/zh-TW.json | 15 ++++++++ locales/settings/zh-HK.json | 2 + locales/settings/zh-TW.json | 37 ++++++++++++++++++- 12 files changed, 84 insertions(+), 5 deletions(-) diff --git a/apps/renderer/src/modules/ai/ai-daily/daily.tsx b/apps/renderer/src/modules/ai/ai-daily/daily.tsx index 527972693..077f4e3c8 100644 --- a/apps/renderer/src/modules/ai/ai-daily/daily.tsx +++ b/apps/renderer/src/modules/ai/ai-daily/daily.tsx @@ -184,6 +184,7 @@ export const DailyReportModalContent: Component = ({ }) => { const content = useQueryData({ endDate, startDate, view }) const RelatedEntryLink = useState(() => createRelatedEntryLink("toast"))[0] + const { t } = useTranslation() return (
{content.isLoading ? ( @@ -203,7 +204,7 @@ export const DailyReportModalContent: Component = ({ ) : (
-

No AI news found for this period.

+

{t("ai_daily.no_found")}

)} diff --git a/apps/renderer/src/modules/ai/ai-daily/hooks.tsx b/apps/renderer/src/modules/ai/ai-daily/hooks.tsx index f4c5dccb0..086500cfb 100644 --- a/apps/renderer/src/modules/ai/ai-daily/hooks.tsx +++ b/apps/renderer/src/modules/ai/ai-daily/hooks.tsx @@ -65,11 +65,12 @@ export const useParseDailyDate = (day: DayOf) => { export const useAIDailyReportModal = () => { const { present } = useModalStack() + const { t } = useTranslation() return useCallback(() => { present({ content: () => , - title: "AI Daily Report", + title: t("ai_daily.header"), resizeable: true, clickOutsideToDismiss: true, diff --git a/apps/renderer/src/modules/wallet/hooks.ts b/apps/renderer/src/modules/wallet/hooks.ts index 1fb5edd42..8a8c79705 100644 --- a/apps/renderer/src/modules/wallet/hooks.ts +++ b/apps/renderer/src/modules/wallet/hooks.ts @@ -1,4 +1,5 @@ import { createElement, useCallback } from "react" +import { useTranslation } from "react-i18next" import { toast } from "sonner" import { useModalStack } from "~/components/ui/modal/stacked/hooks" @@ -15,7 +16,7 @@ export const useTipModal = ({ entryId?: string }) => { const { present } = useModalStack() - + const { t } = useTranslation() return useCallback(() => { if (!feedId || !entryId) { // this should not happen unless there is a bug in the code @@ -24,7 +25,7 @@ export const useTipModal = ({ } window.posthog?.capture("tip_modal_opened", { entryId }) present({ - title: "Tip Power", + title: t("tip_modal.tip_title"), content: () => createElement(TipModalContent, { userId, feedId, entryId }), }) }, [present, userId, feedId, entryId]) diff --git a/locales/app/en.json b/locales/app/en.json index 0fb119b6e..64272ca93 100644 --- a/locales/app/en.json +++ b/locales/app/en.json @@ -3,6 +3,8 @@ "achievement.first_claim_feed": "Feed Owner", "achievement.first_claim_feed_description": "You own your feed on Follow", "achievement.mint_more_power": "Be a hardcore player and earn more ", + "ai_daily.header": "AI Daily Report", + "ai_daily.no_found": "No AI news found for this period.", "ai_daily.title": "Top News - {{title}}", "ai_daily.tooltip.content": "Here is news selected by AI from your timeline ( - ) that may be important to you.", "ai_daily.tooltip.update_schedule": "Update daily at 8 AM and 8 PM.", @@ -206,6 +208,7 @@ "tip_modal.tip_now": "Tip Now", "tip_modal.tip_sent": "Tip sent successfully! Thank you for your support.", "tip_modal.tip_support": "⭐ Tip to show your support!", + "tip_modal.tip_title": "Tip Power", "tip_modal.unclaimed_feed": "No one has claimed this feed yet. The received Power will be securely held in the blockchain contract until it is claimed.", "user_button.account": "Account", "user_button.achievement": "Achievements", diff --git a/locales/app/zh-CN.json b/locales/app/zh-CN.json index 12f0484d7..881bd3355 100644 --- a/locales/app/zh-CN.json +++ b/locales/app/zh-CN.json @@ -3,6 +3,8 @@ "achievement.first_claim_feed": "订阅源所有者", "achievement.first_claim_feed_description": "在 Follow 上认证订阅源", "achievement.mint_more_power": "成为硬核玩家,赚取更多 ", + "ai_daily.header": "AI 日报", + "ai_daily.no_found": "该期间未找到AI新闻", "ai_daily.title": "热点 - {{title}}", "ai_daily.tooltip.content": "AI 根据时间线( - )提取的重点信息", "ai_daily.tooltip.update_schedule": "每天 8:00 和 20:00 定时更新", @@ -206,6 +208,7 @@ "tip_modal.tip_now": "立即打赏", "tip_modal.tip_sent": "成功打赏!感谢支持", "tip_modal.tip_support": "⭐ 打赏表示支持!", + "tip_modal.tip_title": "打赏 Power", "tip_modal.unclaimed_feed": "这个订阅源还没有被认证,收到的 Power 将存放在区块链直到源所有者完成认证", "user_button.account": "账号", "user_button.achievement": "成就", diff --git a/locales/app/zh-HK.json b/locales/app/zh-HK.json index 165b66f6f..9762faff1 100644 --- a/locales/app/zh-HK.json +++ b/locales/app/zh-HK.json @@ -3,6 +3,8 @@ "achievement.first_claim_feed": "Feed 擁有者", "achievement.first_claim_feed_description": "你在 Follow 上擁有你的 Feed", "achievement.mint_more_power": "成為資深玩家,賺取更多 ", + "ai_daily.header": "AI 日報", + "ai_daily.no_found": "該期間未找到AI新聞", "ai_daily.title": "頭條新聞 - {{title}}", "ai_daily.tooltip.content": "以下是由 AI 從你的時間線中選出的新聞( - ),可能對你很重要。", "ai_daily.tooltip.update_schedule": "每天上午 8 點和下午 8 點更新。", @@ -182,6 +184,7 @@ "sidebar.feed_actions.open_site_in_browser": "在{{which}}中打開網站", "sidebar.feed_actions.unfollow": "取消關注", "sidebar.feed_actions.unfollow_feed": "取消關注訂閱源", + "sidebar.feed_column.context_menu.add_feeds_to_list": "添加訂閱源到清單", "sidebar.feed_column.context_menu.change_to_other_view": "切換到其他視圖", "sidebar.feed_column.context_menu.delete_category": "刪除分類", "sidebar.feed_column.context_menu.delete_category_confirmation": "確定刪除分類 {{folderName}}?", @@ -204,6 +207,7 @@ "tip_modal.tip_now": "立刻贊助", "tip_modal.tip_sent": "贊助成功!感謝你的支持。", "tip_modal.tip_support": "⭐ 贊助以顯示你的支持!", + "tip_modal.tip_title": "贊助 Power", "tip_modal.unclaimed_feed": "目前尚未有人認領此訂閱源。收到的 Power 將安全地保留在區塊鏈合約中,直到被認領為止。", "user_button.account": "帳戶", "user_button.achievement": "成就", diff --git a/locales/app/zh-TW.json b/locales/app/zh-TW.json index a87d67c3d..371ec804d 100644 --- a/locales/app/zh-TW.json +++ b/locales/app/zh-TW.json @@ -3,6 +3,8 @@ "achievement.first_claim_feed": "訂閱源所有者", "achievement.first_claim_feed_description": "在 Follow 上認證訂閱源", "achievement.mint_more_power": "成為核心玩家,賺取更多 ", + "ai_daily.header": "AI 日報", + "ai_daily.no_found": "該期間未找到AI新聞", "ai_daily.title": "頭條新聞 - {{title}}", "ai_daily.tooltip.content": "以下是 AI 從您的時間軸中選擇的新聞( - ),可能對您很重要。", "ai_daily.tooltip.update_schedule": "每天早上 8 點和晚上 8 點更新。", @@ -171,15 +173,18 @@ "sidebar.feed_actions.copy_list_url": "複製列表連結", "sidebar.feed_actions.edit": "編輯", "sidebar.feed_actions.edit_feed": "編輯摘要", + "sidebar.feed_actions.edit_list": "編輯列表", "sidebar.feed_actions.feed_owned_by_you": "此摘要由你所擁有", "sidebar.feed_actions.list_owned_by_you": "該列表歸你所有", "sidebar.feed_actions.mark_all_as_read": "全部標記為已讀", "sidebar.feed_actions.navigate_to_feed": "導航到摘要", + "sidebar.feed_actions.navigate_to_list": "導航到列表", "sidebar.feed_actions.open_feed_in_browser": "使用{{which}}打開這個摘要", "sidebar.feed_actions.open_list_in_browser": "在{{which}}開啟列表", "sidebar.feed_actions.open_site_in_browser": "使用{{which}}打開這個網站", "sidebar.feed_actions.unfollow": "取消關注", "sidebar.feed_actions.unfollow_feed": "取消關注摘要", + "sidebar.feed_column.context_menu.add_feeds_to_list": "添加摘要到列表", "sidebar.feed_column.context_menu.change_to_other_view": "切換到其他視圖", "sidebar.feed_column.context_menu.delete_category": "刪除類別", "sidebar.feed_column.context_menu.delete_category_confirmation": "刪除類別 {{folderName}}?", @@ -202,6 +207,7 @@ "tip_modal.tip_now": "立刻贊助", "tip_modal.tip_sent": "贊助成功!謝謝您的支持", "tip_modal.tip_support": "⭐ 贊助以表示你的支持!", + "tip_modal.tip_title": "贊助 Power", "tip_modal.unclaimed_feed": "目前尚無人認領此摘要。收到的 Power 將安全地保存在區塊鏈合約中,直到被認領為止。", "user_button.account": "帳戶", "user_button.achievement": "成就", @@ -228,6 +234,7 @@ "words.lists": "列表", "words.load_archived_entries": "載入已封存項目", "words.login": "登入", + "words.mint": "Mint", "words.newTab": "新分頁", "words.power": "Power", "words.rss": "RSS", diff --git a/locales/common/zh-HK.json b/locales/common/zh-HK.json index 02ee8f318..8f7c2df5a 100644 --- a/locales/common/zh-HK.json +++ b/locales/common/zh-HK.json @@ -12,6 +12,7 @@ "time.yesterday": "昨天", "tips.load-lng-error": "語言包載入失敗", "words.actions": "操作", + "words.ago": "前", "words.back": "返回", "words.copy": "複製", "words.create": "創建", diff --git a/locales/common/zh-TW.json b/locales/common/zh-TW.json index db2bf8ad2..c0b754db4 100644 --- a/locales/common/zh-TW.json +++ b/locales/common/zh-TW.json @@ -11,19 +11,25 @@ "time.today": "今天", "time.yesterday": "昨天", "tips.load-lng-error": "語言包載入失敗", + "words.actions": "操作", + "words.ago": "前", "words.back": "返回", "words.copy": "複製", + "words.create": "創建", "words.edit": "編輯", "words.entry": "條目", "words.id": "識別碼", "words.items_one": "項目", "words.items_other": "多個項目", "words.local": "本地", + "words.manage": "管理", "words.record": "記錄", "words.record_one": "記錄", "words.record_other": "多筆記錄", "words.result": "結果", "words.result_one": "結果", "words.result_other": "多筆結果", + "words.submit": "提交", + "words.update": "更新", "words.which.all": "全部" } diff --git a/locales/native/zh-TW.json b/locales/native/zh-TW.json index 23c737709..e0804f4ad 100644 --- a/locales/native/zh-TW.json +++ b/locales/native/zh-TW.json @@ -1,17 +1,32 @@ { + "contextMenu.copy": "複製", "contextMenu.copyImage": "複製圖片", "contextMenu.copyImageAddress": "複製圖片網址", "contextMenu.copyLink": "複製連結", "contextMenu.copyVideoAddress": "複製影片網址", + "contextMenu.cut": "剪下", "contextMenu.inspect": "檢查元素", + "contextMenu.learnSpelling": "學習拼寫", + "contextMenu.lookUpSelection": "查找選擇", "contextMenu.openImageInBrowser": "在瀏覽器中開啟圖片", "contextMenu.openLinkInBrowser": "在瀏覽器中開啟連結", + "contextMenu.paste": "貼上", + "contextMenu.saveImage": "儲存圖片", "contextMenu.saveImageAs": "圖片另存新檔...", + "contextMenu.saveLinkAs": "連結另存新檔...", + "contextMenu.saveVideo": "儲存影片", "contextMenu.saveVideoAs": "影片另存新檔...", + "contextMenu.searchWithGoogle": "使用 Google 搜尋", + "contextMenu.selectAll": "全選", + "contextMenu.services": "服務", + "dialog.clearAllData": "您確定要清除所有資料嗎?", + "dialog.no": "否", + "dialog.yes": "是", "menu.about": "關於 {{name}}", "menu.actualSize": "實際大小", "menu.bringAllToFront": "將所有視窗移至最上層", "menu.checkForUpdates": "檢查更新", + "menu.clearAllData": "清除所有資料", "menu.close": "關閉", "menu.copy": "複製", "menu.cut": "剪下", diff --git a/locales/settings/zh-HK.json b/locales/settings/zh-HK.json index 32ff5b01e..c9b3dd13e 100644 --- a/locales/settings/zh-HK.json +++ b/locales/settings/zh-HK.json @@ -156,6 +156,7 @@ "lists.created.error": "建立清單失敗。", "lists.created.success": "成功建立清單!", "lists.description": "描述", + "lists.earnings": "收益", "lists.edit.error": "編輯清單失敗。", "lists.edit.label": "編輯", "lists.edit.success": "成功編輯清單!", @@ -177,6 +178,7 @@ "lists.info": "清單是你可以分享或出售給其他人訂閱的資訊源集合。訂閱者將同步並存取清單中的所有資訊源。", "lists.noLists": "沒有清單", "lists.submit": "提交", + "lists.subscriptions": "訂閱", "lists.title": "標題", "lists.view": "查看", "profile.avatar.label": "頭像", diff --git a/locales/settings/zh-TW.json b/locales/settings/zh-TW.json index 2e897d27b..cc77c7271 100644 --- a/locales/settings/zh-TW.json +++ b/locales/settings/zh-TW.json @@ -73,6 +73,8 @@ "appearance.title": "外觀", "appearance.ui_font": "介面字體", "appearance.unread_count": "未讀計數", + "appearance.use_pointer_cursor.description": "將游標變更為指標,當滑鼠懸停在任何互動元素上時。", + "appearance.use_pointer_cursor.label": "使用指標游標", "common.give_star": "喜歡我們的產品嗎? 在 GitHub 上給我們 star 吧!", "feeds.claimTips": "要認領您的 feed 並接收贊助,請在您的訂閱列表中右鍵點擊該 feed,然後選擇「認領」。", "feeds.noFeeds": "無認領的 feed", @@ -93,7 +95,10 @@ "general.mark_as_read.render.label": "顯示時標記為已讀", "general.mark_as_read.scroll.description": "當條目捲動離開視圖時自動標記為已讀。", "general.mark_as_read.scroll.label": "捲動時標記為已讀", + "general.network": "網路", "general.privacy_data": "隱私與數據", + "general.proxy.description": "設定代理伺服器代理網絡流量,例如:socks://proxy.example.com:1080", + "general.proxy.label": "代理伺服器", "general.rebuild_database.button": "重建", "general.rebuild_database.description": "如果您遇到渲染問題,重建資料庫可能可以解決。", "general.rebuild_database.label": "重建資料庫", @@ -147,7 +152,36 @@ "invitation.tableHeaders.creationTime": "建立時間", "invitation.tableHeaders.usedBy": "使用者", "invitation.title": "邀請碼", - "profile.avatar.label": "大頭貼", + "lists.create": "建立新列表", + "lists.created.error": "建立列表失敗。", + "lists.created.success": "列表建立成功!", + "lists.description": "描述", + "lists.earnings": "收益", + "lists.edit.error": "編輯列表失敗。", + "lists.edit.label": "編輯", + "lists.edit.success": "列表編輯成功!", + "lists.fee.description": "其他人訂閱此列表需要支付的費用。", + "lists.fee.label": "費用", + "lists.feeds.actions": "操作", + "lists.feeds.add.error": "將訂閱源添加到列表失敗。", + "lists.feeds.add.label": "添加", + "lists.feeds.add.success": "訂閱源已添加到列表。", + "lists.feeds.delete.error": "從列表中移除訂閱源失敗。", + "lists.feeds.delete.success": "訂閱源已從列表中移除。", + "lists.feeds.id": "訂閱源 ID", + "lists.feeds.label": "訂閱源", + "lists.feeds.manage": "管理訂閱源", + "lists.feeds.owner": "擁有者", + "lists.feeds.search": "搜尋訂閱源", + "lists.feeds.title": "標題", + "lists.image": "圖片", + "lists.info": "列表是您可以分享或出售給他人訂閱的訂閱源集合。訂閱者將同步並訪問列表中的所有訂閱源。", + "lists.noLists": "沒有列表", + "lists.submit": "送出", + "lists.subscriptions": "訂閱", + "lists.title": "標題", + "lists.view": "查看", + "profile.avatar.label": "頭像", "profile.handle.description": "您的唯一識別碼", "profile.handle.label": "Handle", "profile.name.description": "您的公開顯示名稱。", @@ -163,6 +197,7 @@ "titles.general": "一般", "titles.integration": "整合", "titles.invitations": "邀請", + "titles.lists": "列表", "titles.power": "Power", "titles.profile": "個人資料", "titles.shortcuts": "快捷鍵", From 37a436eac52669113782a6db42d24398ad206165 Mon Sep 17 00:00:00 2001 From: Konata <1025090504@qq.com> Date: Sun, 29 Sep 2024 19:58:47 +0800 Subject: [PATCH 36/88] chore(transition): apply natural transition for avatar dropdown (#693) * feat:more natural transition * fix: role for list item and scroller Signed-off-by: Innei --------- Signed-off-by: Innei Co-authored-by: Innei --- .../components/EntryReadHistory.tsx | 62 +++++++++++-------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/apps/renderer/src/modules/entry-content/components/EntryReadHistory.tsx b/apps/renderer/src/modules/entry-content/components/EntryReadHistory.tsx index ba442f45e..d001bc459 100644 --- a/apps/renderer/src/modules/entry-content/components/EntryReadHistory.tsx +++ b/apps/renderer/src/modules/entry-content/components/EntryReadHistory.tsx @@ -10,7 +10,9 @@ import { memo } from "react" import { useWhoami } from "~/atoms/user" import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar" +import { ScrollArea } from "~/components/ui/scroll-area" import { Tooltip, TooltipContent, TooltipPortal, TooltipTrigger } from "~/components/ui/tooltip" +import { EllipsisHorizontalTextWithTooltip } from "~/components/ui/typography" import { useAuthQuery } from "~/hooks/common" import { useAppLayoutGridContainerWidth } from "~/providers/app-grid-layout-container-provider" import { Queries } from "~/queries" @@ -69,21 +71,28 @@ export const EntryReadHistory: Component<{ entryId: string }> = ({ entryId }) => sideOffset={12} align="start" side="right" - asChild className={clsx( - "z-10 flex max-h-[300px] flex-col overflow-y-auto rounded-md border bg-background drop-shadow", - // Animation, fade up - "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=open]:slide-in-from-bottom-3", + "z-10 rounded-md border bg-background drop-shadow", + "data-[state=open]:animate-in data-[state=closed]:animate-out", + "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", + "data-[state=closed]:slide-out-to-left-5 data-[state=open]:slide-in-from-left-5", + "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95", + "transition-all duration-200 ease-in-out", )} > -
    - {entryHistory.userIds - .filter((id) => id !== me?.id) - .slice(LIMIT) - .map((userId) => ( - - ))} -
+ +
    + {entryHistory.userIds + .filter((id) => id !== me?.id) + .slice(LIMIT) + .map((userId) => ( + + ))} +
+
)} @@ -99,21 +108,22 @@ const EntryUserRow: Component<{ userId: string }> = memo(({ userId }) => { if (!user) return null return ( -
  • - + {user.name && ( + + {user.name} + + )}
  • ) }) From cbb6317afb3c1638bf0f7d434698fc1510ab1fe2 Mon Sep 17 00:00:00 2001 From: Innei Date: Sun, 29 Sep 2024 21:55:54 +0800 Subject: [PATCH 37/88] chore: update issue configs Signed-off-by: Innei --- .github/ISSUE_TEMPLATE/config.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 5aba40786..f6ca40b70 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -3,3 +3,6 @@ contact_links: - name: 💬 Follow's Discord Server url: https://discord.gg/tUDVZjEr about: Want to discuss / chat with the community? Here you go! + - name: Discuss an issue + url: https://github.com/RSSNext/Follow/discussions + about: For general questions, ideas, or non-bug related discussions, please use GitHub Discussions. From cb2078da70ac93add77aee9da83d5687c4b8b9c8 Mon Sep 17 00:00:00 2001 From: Przeblysk Date: Mon, 30 Sep 2024 14:40:20 +0800 Subject: [PATCH 38/88] =?UTF-8?q?feat:=20Remember=20the=20open=20state=20o?= =?UTF-8?q?f=20the=20category,=20Ensure=20that=20each=20View'=E2=80=A6=20(?= =?UTF-8?q?#709)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/modules/feed-column/category.tsx | 39 +++++++------- .../renderer/src/modules/feed-column/list.tsx | 54 ++++++++++++++----- apps/renderer/src/store/subscription/hooks.ts | 4 ++ apps/renderer/src/store/subscription/store.ts | 52 +++++++++++++++++- 4 files changed, 118 insertions(+), 31 deletions(-) diff --git a/apps/renderer/src/modules/feed-column/category.tsx b/apps/renderer/src/modules/feed-column/category.tsx index 77c140784..536aa1762 100644 --- a/apps/renderer/src/modules/feed-column/category.tsx +++ b/apps/renderer/src/modules/feed-column/category.tsx @@ -30,10 +30,10 @@ type FeedId = string interface FeedCategoryProps { data: FeedId[] view?: number - expansion: boolean + categoryOpenStateData: Record } -function FeedCategoryImpl({ data: ids, view, expansion }: FeedCategoryProps) { +function FeedCategoryImpl({ data: ids, view, categoryOpenStateData }: FeedCategoryProps) { const { t } = useTranslation() const sortByUnreadFeedList = useFeedUnreadStore((state) => @@ -46,17 +46,29 @@ function FeedCategoryImpl({ data: ids, view, expansion }: FeedCategoryProps) { const folderName = subscription?.category || subscription.defaultCategory const showCollapse = sortByUnreadFeedList.length > 1 || subscription?.category - const [open, setOpen] = useState(!showCollapse) + const open = folderName ? categoryOpenStateData[folderName] : true - const shouldOpen = useRouteParamsSelector( - (s) => typeof s.feedId === "string" && ids.includes(s.feedId), - ) + const shouldOpen = + useRouteParamsSelector((s) => typeof s.feedId === "string" && ids.includes(s.feedId)) || + ids.length === 1 const itemsRef = useRef(null) + const toggleCategoryOpenState = (e) => { + e.stopPropagation() + if (!isCategoryEditing) { + setCategoryActive() + } + if (view !== undefined && folderName) { + subscriptionActions.toggleCategoryOpenState(view, folderName) + } + } + useEffect(() => { if (shouldOpen) { - setOpen(true) + if (!open && view !== undefined && folderName) { + subscriptionActions.toggleCategoryOpenState(view, folderName) + } const $items = itemsRef.current @@ -66,12 +78,7 @@ function FeedCategoryImpl({ data: ids, view, expansion }: FeedCategoryProps) { behavior: "smooth", }) } - }, [shouldOpen]) - useEffect(() => { - if (showCollapse) { - setOpen(expansion) - } - }, [expansion]) + }, [shouldOpen, open, view, folderName]) const setCategoryActive = () => { if (view !== undefined) { @@ -200,11 +207,7 @@ function FeedCategoryImpl({ data: ids, view, expansion }: FeedCategoryProps) {
    From ad5adc358933370bdff9b17f732d7a0d924fe10d Mon Sep 17 00:00:00 2001 From: Mike Lee <75201518+RechardLLee@users.noreply.github.com> Date: Mon, 30 Sep 2024 07:23:02 -0500 Subject: [PATCH 46/88] fix(i18n): complete the Chinese (Taiwan) and Chinese (Hong Kong) json files. (#720) Co-authored-by: RechardLLee --- locales/settings/zh-HK.json | 10 +++++----- locales/settings/zh-TW.json | 18 +++++++++--------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/locales/settings/zh-HK.json b/locales/settings/zh-HK.json index c9b3dd13e..403237d8e 100644 --- a/locales/settings/zh-HK.json +++ b/locales/settings/zh-HK.json @@ -222,11 +222,11 @@ "wallet.transactions.to": "發送至", "wallet.transactions.tx": "交易", "wallet.transactions.type": "類型", - "wallet.transactions.types.burn": "burn", - "wallet.transactions.types.mint": "mint", - "wallet.transactions.types.purchase": "purchase", - "wallet.transactions.types.tip": "tip", - "wallet.transactions.types.withdraw": "withdraw", + "wallet.transactions.types.burn": "銷燬", + "wallet.transactions.types.mint": "鑄造", + "wallet.transactions.types.purchase": "購買", + "wallet.transactions.types.tip": "打賞", + "wallet.transactions.types.withdraw": "提取", "wallet.transactions.you": "你", "wallet.withdraw.addressLabel": "你的以太坊地址", "wallet.withdraw.amountLabel": "數量", diff --git a/locales/settings/zh-TW.json b/locales/settings/zh-TW.json index cc77c7271..9445ebfec 100644 --- a/locales/settings/zh-TW.json +++ b/locales/settings/zh-TW.json @@ -21,7 +21,7 @@ "actions.action_card.feed_options.feed_url": "摘要 URL", "actions.action_card.feed_options.site_url": "網站 URL", "actions.action_card.feed_options.title": "標題", - "actions.action_card.feed_options.view": "View", + "actions.action_card.feed_options.view": "視圖", "actions.action_card.field": "欄位", "actions.action_card.from": "從", "actions.action_card.generate_summary": "使用 AI 生成摘要", @@ -182,8 +182,8 @@ "lists.title": "標題", "lists.view": "查看", "profile.avatar.label": "頭像", - "profile.handle.description": "您的唯一識別碼", - "profile.handle.label": "Handle", + "profile.handle.description": "唯一識別碼", + "profile.handle.label": "唯一識別碼", "profile.name.description": "您的公開顯示名稱。", "profile.name.label": "顯示名稱", "profile.sidebar_title": "個人資料", @@ -193,7 +193,7 @@ "titles.about": "關於", "titles.actions": "指令", "titles.appearance": "外觀", - "titles.feeds": "Feeds", + "titles.feeds": "訂閱源", "titles.general": "一般", "titles.integration": "整合", "titles.invitations": "邀請", @@ -222,11 +222,11 @@ "wallet.transactions.to": "接收者", "wallet.transactions.tx": "交易", "wallet.transactions.type": "類型", - "wallet.transactions.types.burn": "burn", - "wallet.transactions.types.mint": "mint", - "wallet.transactions.types.purchase": "purchase", - "wallet.transactions.types.tip": "tip", - "wallet.transactions.types.withdraw": "withdraw", + "wallet.transactions.types.burn": "銷燬", + "wallet.transactions.types.mint": "鑄造", + "wallet.transactions.types.purchase": "購入", + "wallet.transactions.types.tip": "打賞", + "wallet.transactions.types.withdraw": "提現", "wallet.transactions.you": "您", "wallet.withdraw.addressLabel": "您的以太坊地址", "wallet.withdraw.amountLabel": "數量", From 361b09eb23c86f377cc82d7e523781a7d4507689 Mon Sep 17 00:00:00 2001 From: Kieran Cui <78460423+cuikaipeng@users.noreply.github.com> Date: Mon, 30 Sep 2024 20:39:06 +0800 Subject: [PATCH 47/88] fix: grid mode for images and video content page, shadow not fully displayed when the mouse hovers over (#727) Co-authored-by: cuikaipeng --- apps/renderer/src/modules/entry-column/item.tsx | 11 ++++++++++- .../modules/entry-column/layouts/EntryItemWrapper.tsx | 8 ++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/apps/renderer/src/modules/entry-column/item.tsx b/apps/renderer/src/modules/entry-column/item.tsx index b2db0719c..039d4570d 100644 --- a/apps/renderer/src/modules/entry-column/item.tsx +++ b/apps/renderer/src/modules/entry-column/item.tsx @@ -5,6 +5,7 @@ import { LoadingCircle } from "~/components/ui/loading" import { views } from "~/constants" import { useAuthQuery } from "~/hooks/common" import type { FeedViewType } from "~/lib/enum" +import { FeedViewType as FeedViewTypeEnum } from "~/lib/enum" import { cn } from "~/lib/utils" import { Queries } from "~/queries" import type { FlatEntryModel } from "~/store/entry" @@ -38,9 +39,17 @@ function EntryItemImpl({ entry, view }: { entry: FlatEntryModel; view?: number } ) const Item: EntryListItemFC = getItemComponentByView(view as FeedViewType) + const overlayItemClassName = + view === FeedViewTypeEnum.Pictures || view === FeedViewTypeEnum.Videos ? "top-0" : "" return ( - + ) diff --git a/apps/renderer/src/modules/entry-column/layouts/EntryItemWrapper.tsx b/apps/renderer/src/modules/entry-column/layouts/EntryItemWrapper.tsx index a4d97e8a3..3c34b02cc 100644 --- a/apps/renderer/src/modules/entry-column/layouts/EntryItemWrapper.tsx +++ b/apps/renderer/src/modules/entry-column/layouts/EntryItemWrapper.tsx @@ -21,10 +21,11 @@ export const EntryItemWrapper: FC< entry: FlatEntryModel view?: number itemClassName?: string + overlayItemClassName?: string overlay?: boolean style?: React.CSSProperties } & PropsWithChildren -> = ({ entry, view, overlay, children, itemClassName, style }) => { +> = ({ entry, view, overlay, children, itemClassName, overlayItemClassName, style }) => { const { items } = useEntryActions({ view, entry, @@ -127,7 +128,10 @@ export const EntryItemWrapper: FC< onContextMenu={handleContextMenu} > {overlay ? ( - + {children} ) : ( From 447803488c1ed01769c134f3113b0a3926e07446 Mon Sep 17 00:00:00 2001 From: Innei Date: Mon, 30 Sep 2024 20:56:35 +0800 Subject: [PATCH 48/88] fix: entry column title top overflow Signed-off-by: Innei --- .../src/modules/entry-column/layouts/EntryListHeader.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/renderer/src/modules/entry-column/layouts/EntryListHeader.tsx b/apps/renderer/src/modules/entry-column/layouts/EntryListHeader.tsx index 043722ffd..73a6e77d4 100644 --- a/apps/renderer/src/modules/entry-column/layouts/EntryListHeader.tsx +++ b/apps/renderer/src/modules/entry-column/layouts/EntryListHeader.tsx @@ -45,7 +45,7 @@ export const EntryListHeader: FC<{ const titleInfo = !!headerTitle && (
    -
    +
    {headerTitle} From 6d765044fb30df639e5324f65e7e30e6dcb2e772 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Mon, 30 Sep 2024 21:13:02 +0800 Subject: [PATCH 49/88] fix: source content loading status --- .../src/modules/entry-content/components/SourceContentView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/renderer/src/modules/entry-content/components/SourceContentView.tsx b/apps/renderer/src/modules/entry-content/components/SourceContentView.tsx index fb10c85ad..14b23cf11 100644 --- a/apps/renderer/src/modules/entry-content/components/SourceContentView.tsx +++ b/apps/renderer/src/modules/entry-content/components/SourceContentView.tsx @@ -36,7 +36,7 @@ export const SourceContentView = ({ src }: { src: string }) => { const handleDidStopLoading = () => setLoading(false) // See https://www.electronjs.org/docs/latest/api/webview-tag#example - webview.addEventListener("did-start-loading", handleDidStopLoading, { + webview.addEventListener("did-stop-loading", handleDidStopLoading, { signal: abortController.signal, }) From 8d259878c30a987940d7e982c63b37f100008635 Mon Sep 17 00:00:00 2001 From: Whitewater Date: Mon, 30 Sep 2024 21:23:35 +0800 Subject: [PATCH 50/88] fix: truncate long title in dialog title (#729) --- apps/renderer/src/components/ui/modal/stacked/modal.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/renderer/src/components/ui/modal/stacked/modal.tsx b/apps/renderer/src/components/ui/modal/stacked/modal.tsx index 5d3961ea9..a8fdd2cc8 100644 --- a/apps/renderer/src/components/ui/modal/stacked/modal.tsx +++ b/apps/renderer/src/components/ui/modal/stacked/modal.tsx @@ -359,10 +359,9 @@ export const ModalInternal = memo( onPointerDownCapture={handleDrag} onPointerDown={handleResizeEnable} > - + {icon && {icon}} - - {title} + {title} {canClose && ( From a954eb93bc74fc6730244e15067888f88743d067 Mon Sep 17 00:00:00 2001 From: Innei Date: Mon, 30 Sep 2024 22:16:34 +0800 Subject: [PATCH 51/88] fix(styles): user subscription modal list item style Signed-off-by: Innei --- apps/renderer/src/modules/profile/user-profile-modal.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/renderer/src/modules/profile/user-profile-modal.tsx b/apps/renderer/src/modules/profile/user-profile-modal.tsx index 636707528..01133b8b8 100644 --- a/apps/renderer/src/modules/profile/user-profile-modal.tsx +++ b/apps/renderer/src/modules/profile/user-profile-modal.tsx @@ -234,7 +234,7 @@ export const UserProfileModalContent: FC<{
    @@ -328,7 +328,7 @@ const SubscriptionGroup: FC<{
    diff --git a/apps/renderer/src/modules/discover/form.tsx b/apps/renderer/src/modules/discover/form.tsx index 68e18bd31..d17d23ba3 100644 --- a/apps/renderer/src/modules/discover/form.tsx +++ b/apps/renderer/src/modules/discover/form.tsx @@ -30,6 +30,7 @@ import type { FeedViewType } from "~/lib/enum" import { FollowSummary } from "../../components/feed-summary" import { FeedForm } from "./feed-form" +import { ListForm } from "./list-form" const formSchema = z.object({ keyword: z.string().min(1), @@ -63,7 +64,7 @@ const info: Record< } type DiscoverSearchData = Awaited>["data"] -export function DiscoverForm({ type }: { type: string }) { +export function DiscoverForm({ type = "search" }: { type?: string }) { const { prefix, default: defaultValue } = info[type] const form = useForm>({ resolver: zodResolver(formSchema), @@ -320,21 +321,33 @@ const SearchCard: FC<{ onClick={() => { present({ title: "Add Feed", - content: ({ dismiss }) => ( - { - onSuccess(item) - dismiss() - }} - /> - ), + content: ({ dismiss }) => + item.list?.id ? ( + { + onSuccess(item) + dismiss() + }} + /> + ) : ( + { + onSuccess(item) + dismiss() + }} + /> + ), }) }} > diff --git a/apps/renderer/src/modules/discover/inbox-form.tsx b/apps/renderer/src/modules/discover/inbox-form.tsx new file mode 100644 index 000000000..993abe0ee --- /dev/null +++ b/apps/renderer/src/modules/discover/inbox-form.tsx @@ -0,0 +1,202 @@ +import { env } from "@follow/shared/env" +import { zodResolver } from "@hookform/resolvers/zod" +import { useMutation } from "@tanstack/react-query" +import { useForm } from "react-hook-form" +import { useTranslation } from "react-i18next" +import { toast } from "sonner" +import { z } from "zod" + +import { FollowSummary } from "~/components/feed-summary" +import { Logo } from "~/components/icons/logo" +import { Button } from "~/components/ui/button" +import { Card, CardHeader } from "~/components/ui/card" +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "~/components/ui/form" +import { Input } from "~/components/ui/input" +import { apiClient } from "~/lib/api-fetch" +import { FeedViewType } from "~/lib/enum" +import { cn } from "~/lib/utils" +import type { InboxModel } from "~/models" +import { useInbox } from "~/queries/inboxes" +import { useInboxById } from "~/store/inbox" +import { subscriptionActions } from "~/store/subscription" + +export const InboxForm: Component<{ + id?: string + asWidget?: boolean + onSuccess?: () => void +}> = ({ id: _id, asWidget, onSuccess }) => { + const queryParams = { id: _id } + + const feedQuery = useInbox(queryParams) + + const id = feedQuery.data?.id || _id + const inbox = useInboxById(id) + + const isSubscribed = true + + const { t } = useTranslation() + + return ( +
    + {!asWidget && ( +
    + + {isSubscribed ? t("feed_form.update_follow") : t("feed_form.add_follow")} +
    + )} + +
    + ) +} + +const inboxHandleSchema = z + .string() + .min(3) + .max(32) + .regex(/^[a-z0-9_-]+$/) + +const formSchema = z.object({ + handle: inboxHandleSchema, + title: z.string(), +}) + +const InboxInnerForm = ({ + onSuccess, + inbox, +}: { + onSuccess?: () => void + inbox?: Nullable +}) => { + const { t } = useTranslation() + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + handle: inbox?.id, + title: inbox?.title || "", + }, + }) + + const mutationCreate = useMutation({ + mutationFn: async ({ handle, title }: { handle: string; title: string }) => { + await apiClient.inboxes.$post({ + json: { + handle, + title, + }, + }) + onSuccess?.() + }, + onSuccess: (_) => { + subscriptionActions.fetchByView(FeedViewType.Articles) + toast.success(t("discover.inbox_create_success")) + }, + onError: () => { + toast.error(t("discover.inbox_create_error")) + }, + }) + + const mutationChange = useMutation({ + mutationFn: async ({ handle, title }: { handle: string; title: string }) => { + await apiClient.inboxes.$put({ + json: { + handle, + title, + }, + }) + onSuccess?.() + }, + onSuccess: () => { + subscriptionActions.fetchByView(FeedViewType.Articles) + toast.success(t("discover.inbox_update_success")) + }, + onError: () => { + toast.error(t("discover.inbox_update_error")) + }, + }) + + function onSubmit(values: z.infer) { + if (inbox) { + mutationChange.mutate({ handle: values.handle, title: values.title }) + } else { + mutationCreate.mutate({ handle: values.handle, title: values.title }) + } + } + + return ( +
    + {inbox && ( + + + + + + )} + <> +
    + + {!inbox && ( + ( + + {t("discover.inbox_handle")} + +
    + + {env.VITE_INBOXES_EMAIL} +
    +
    + +
    + )} + /> + )} + ( + + {t("discover.inbox_title")} + + + + + + )} + /> +
    + +
    + + + +
    + ) +} diff --git a/apps/renderer/src/modules/discover/inbox-list-form.tsx b/apps/renderer/src/modules/discover/inbox-list-form.tsx new file mode 100644 index 000000000..9a5f11562 --- /dev/null +++ b/apps/renderer/src/modules/discover/inbox-list-form.tsx @@ -0,0 +1,157 @@ +import { env } from "@follow/shared/env" +import { useMutation } from "@tanstack/react-query" +import { useTranslation } from "react-i18next" +import { toast } from "sonner" + +import { Button } from "~/components/ui/button" +import { CopyButton } from "~/components/ui/code-highlighter" +import { useModalStack } from "~/components/ui/modal" +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "~/components/ui/table" +import { apiClient } from "~/lib/api-fetch" +import { FeedViewType } from "~/lib/enum" +import { inboxActions, useInboxByView } from "~/store/inbox" + +import { InboxForm } from "./inbox-form" + +export function DiscoverInboxList() { + const { t } = useTranslation() + const inboxes = useInboxByView(FeedViewType.Articles) + + const { present } = useModalStack() + + return ( + <> +
    + {t("discover.inbox.description")} + + {t("discover.inbox.webhooks_docs")} + +
    + + + + {t("discover.inbox.handle")} + {t("discover.inbox.email")} + {t("discover.inbox.title")} + {t("discover.inbox.secret")} + {t("discover.inbox.actions")} + + + + {inboxes.map((inbox) => ( + + {inbox.id} + +
    + + {inbox.id} + {env.VITE_INBOXES_EMAIL} + + +
    +
    + {inbox.title} + +
    + **** + +
    +
    + + + + +
    + ))} +
    +
    +
    + +
    + + ) +} + +const ConfirmDestroyModalContent = ({ id, dismiss }: { id: string; dismiss: () => void }) => { + const { t } = useTranslation() + + const mutationDestroy = useMutation({ + mutationFn: async (id: string) => { + await apiClient.inboxes.$delete({ + json: { + handle: id, + }, + }) + }, + onSuccess: (_, handle) => { + inboxActions.clearByInboxId(handle) + toast.success(t("discover.inbox_destroy_success")) + dismiss() + }, + onError: () => { + toast.error(t("discover.inbox_destroy_error")) + }, + }) + + return ( +
    +
    {t("discover.inbox_destroy_warning")}
    +
    + +
    +
    + ) +} diff --git a/apps/renderer/src/modules/discover/list-form.tsx b/apps/renderer/src/modules/discover/list-form.tsx new file mode 100644 index 000000000..2b2e185ac --- /dev/null +++ b/apps/renderer/src/modules/discover/list-form.tsx @@ -0,0 +1,356 @@ +import { zodResolver } from "@hookform/resolvers/zod" +import { useMutation } from "@tanstack/react-query" +import { useEffect, useRef } from "react" +import { useForm } from "react-hook-form" +import { useTranslation } from "react-i18next" +import { toast } from "sonner" +import { z } from "zod" + +import { FollowSummary } from "~/components/feed-summary" +import { Logo } from "~/components/icons/logo" +import { Button } from "~/components/ui/button" +import { Card, CardHeader } from "~/components/ui/card" +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "~/components/ui/form" +import { Input } from "~/components/ui/input" +import { LoadingCircle } from "~/components/ui/loading" +import { useCurrentModal } from "~/components/ui/modal" +import { Switch } from "~/components/ui/switch" +import { useI18n } from "~/hooks/common" +import { apiClient } from "~/lib/api-fetch" +import { tipcClient } from "~/lib/client" +import { FeedViewType } from "~/lib/enum" +import { getFetchErrorMessage, toastFetchError } from "~/lib/error-parser" +import { getNewIssueUrl } from "~/lib/issues" +import { cn } from "~/lib/utils" +import type { ListModel } from "~/models" +import { lists as listsQuery, useList } from "~/queries/lists" +import { subscription as subscriptionQuery } from "~/queries/subscriptions" +import { useListById } from "~/store/list" +import { useSubscriptionByFeedId } from "~/store/subscription" +import { feedUnreadActions } from "~/store/unread" + +import { ViewSelectorRadioGroup } from "../shared/ViewSelectorRadioGroup" + +const formSchema = z.object({ + view: z.string(), + category: z.string().nullable().optional(), + isPrivate: z.boolean().optional(), + title: z.string().optional(), +}) + +const defaultValue = { view: FeedViewType.Articles.toString() } as z.infer + +export const ListForm: Component<{ + id?: string + + defaultValues?: z.infer + + asWidget?: boolean + + onSuccess?: () => void +}> = ({ id: _id, defaultValues = defaultValue, asWidget, onSuccess }) => { + const queryParams = { id: _id } + + const feedQuery = useList(queryParams) + + const id = feedQuery.data?.list.id || _id + const list = useListById(id) + + const hasSub = useSubscriptionByFeedId(list?.id || "") + const isSubscribed = !!feedQuery.data?.subscription || hasSub + + const { t } = useTranslation() + + return ( +
    + {!asWidget && ( +
    + + {isSubscribed ? t("feed_form.update_follow") : t("feed_form.add_follow")} +
    + )} + + {list ? ( + + ) : feedQuery.isLoading ? ( +
    + +
    + ) : feedQuery.error ? ( +
    + +

    {t("feed_form.error_fetching_feed")}

    +

    + {getFetchErrorMessage(feedQuery.error)} +

    + +
    + + + +
    +
    + ) : ( +
    + +

    {t("feed_form.feed_not_found")}

    +

    {id}

    +
    + )} +
    + ) +} + +const ListInnerForm = ({ + defaultValues, + id, + asWidget, + onSuccess, + subscriptionData, + list, +}: { + defaultValues?: z.infer + id?: string + asWidget?: boolean + onSuccess?: () => void + subscriptionData?: { + view?: number + category?: string | null + isPrivate?: boolean + title?: string | null + } + list: ListModel +}) => { + const subscription = useSubscriptionByFeedId(id || "") || subscriptionData + const isSubscribed = !!subscription + const buttonRef = useRef(null) + + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + ...defaultValues, + view: list.view.toString(), + }, + }) + + const { setClickOutSideToDismiss, dismiss } = useCurrentModal() + + useEffect(() => { + setClickOutSideToDismiss(!form.formState.isDirty) + }, [form.formState.isDirty]) + + useEffect(() => { + if (subscription) { + form.setValue("view", `${subscription?.view}`) + form.setValue("isPrivate", subscription?.isPrivate || false) + form.setValue("title", subscription?.title || "") + } + }, [subscription]) + + const followMutation = useMutation({ + mutationFn: async (values: z.infer) => { + const body = { + listId: list.id, + view: Number.parseInt(values.view), + category: values.category, + isPrivate: values.isPrivate, + title: values.title, + } + const $method = isSubscribed ? apiClient.subscriptions.$patch : apiClient.subscriptions.$post + + return $method({ + json: body, + }) + }, + onSuccess: (_, variables) => { + if (isSubscribed && variables.view !== `${subscription?.view}`) { + subscriptionQuery.byView(subscription?.view).invalidate() + tipcClient?.invalidateQuery(subscriptionQuery.byView(subscription?.view).key) + feedUnreadActions.fetchUnreadByView(subscription?.view) + } + subscriptionQuery.byView(Number.parseInt(variables.view)).invalidate() + tipcClient?.invalidateQuery(subscriptionQuery.byView(Number.parseInt(variables.view)).key) + feedUnreadActions.fetchUnreadByView(Number.parseInt(variables.view)) + + const listId = list.id + if (listId) { + listsQuery.byId({ id: listId }).invalidate() + tipcClient?.invalidateQuery(listsQuery.byId({ id: listId }).key) + } + toast(isSubscribed ? t("feed_form.updated") : t("feed_form.followed"), { + duration: 1000, + }) + + if (!asWidget && !isSubscribed) { + window.close() + } + + onSuccess?.() + }, + async onError(err) { + toastFetchError(err) + }, + }) + + function onSubmit(values: z.infer) { + followMutation.mutate(values) + } + + const t = useI18n() + + return ( +
    + + + + + +
    + + ( + + {t("feed_form.view")} + + + + + )} + /> + ( + +
    + {t("feed_form.title")} + {t("feed_form.title_description")} +
    + + + + +
    + )} + /> + ( + +
    +
    + {t("feed_form.private_follow")} + {t("feed_form.private_follow_description")} +
    + + + +
    +
    + )} + /> + {!!list.fee && !isSubscribed && ( +
    + + {t("feed_form.fee")}{" "} +
    + {list.fee} + +
    +
    + {t("feed_form.fee_description")} +
    + )} +
    + {isSubscribed && ( + + )} + +
    + + +
    + ) +} diff --git a/apps/renderer/src/modules/entry-column/hooks.ts b/apps/renderer/src/modules/entry-column/hooks.ts index 6c634833e..333894a57 100644 --- a/apps/renderer/src/modules/entry-column/hooks.ts +++ b/apps/renderer/src/modules/entry-column/hooks.ts @@ -8,7 +8,7 @@ import { useRouteParams, useRouteParamsSelector } from "~/hooks/biz/useRoutePara import { useAuthQuery } from "~/hooks/common" import { entries, useEntries } from "~/queries/entries" import { entryActions, useEntryIdsByFeedIdOrView } from "~/store/entry" -import { isListSubscription, useFolderFeedsByFeedId } from "~/store/subscription" +import { useFolderFeedsByFeedId } from "~/store/subscription" import { feedUnreadActions } from "~/store/unread" export const useEntryMarkReadHandler = (entriesIds: string[]) => { @@ -59,8 +59,7 @@ export const useEntriesByView = ({ const routeParams = useRouteParams() const unreadOnly = useGeneralSettingKey("unreadOnly") - const { feedId, view, isAllFeeds, isCollection } = routeParams - const isList = isListSubscription(feedId) + const { feedId, view, isAllFeeds, isCollection, listId, inboxId } = routeParams const folderIds = useFolderFeedsByFeedId({ feedId, @@ -68,11 +67,12 @@ export const useEntriesByView = ({ }) const entriesOptions = { - id: folderIds?.join(",") || feedId, + feedId: folderIds?.join(",") || feedId, + inboxId, + listId, view, ...(unreadOnly === true && { read: false }), isArchived, - isList, } const query = useEntries(entriesOptions) @@ -169,10 +169,10 @@ export const useEntriesByView = ({ () => isCollection ? sortEntriesIdByStarAt(mergedEntries[view]) - : isList + : listId ? sortEntriesIdByEntryInsertedAt(mergedEntries[view]) : sortEntriesIdByEntryPublishedAt(mergedEntries[view]), - [isCollection, isList, mergedEntries, view], + [isCollection, listId, mergedEntries, view], ) const groupByDate = useGeneralSettingKey("groupByDate") @@ -192,7 +192,7 @@ export const useEntriesByView = ({ continue } const date = new Date( - isList ? entry.entries.insertedAt : entry.entries.publishedAt, + listId ? entry.entries.insertedAt : entry.entries.publishedAt, ).toDateString() if (date !== lastDate) { counts.push(1) diff --git a/apps/renderer/src/modules/entry-column/index.tsx b/apps/renderer/src/modules/entry-column/index.tsx index db4c39b98..ef73b887a 100644 --- a/apps/renderer/src/modules/entry-column/index.tsx +++ b/apps/renderer/src/modules/entry-column/index.tsx @@ -99,7 +99,7 @@ function EntryColumnImpl() { !isCollection && routeFeedId !== ROUTE_FEED_PENDING && entries.totalCount < 40 && - feed?.type !== "list" + feed?.type === "feed" const scrollRef = useRef(null) const virtuosoOptions = { diff --git a/apps/renderer/src/modules/entry-column/templates/list-item-template.tsx b/apps/renderer/src/modules/entry-column/templates/list-item-template.tsx index 3ad946667..5685f5c02 100644 --- a/apps/renderer/src/modules/entry-column/templates/list-item-template.tsx +++ b/apps/renderer/src/modules/entry-column/templates/list-item-template.tsx @@ -46,7 +46,9 @@ export function ListItem({ const handlePrefetchEntry = useDebounceCallback( () => { - Queries.entries.byId(entryId).prefetch() + feed?.type === "inbox" + ? Queries.entries.byInboxId(entryId).prefetch() + : Queries.entries.byId(entryId).prefetch() }, 300, { leading: false }, diff --git a/apps/renderer/src/modules/feed-column/item.tsx b/apps/renderer/src/modules/feed-column/item.tsx index e2ca8ab0a..6daec9ddc 100644 --- a/apps/renderer/src/modules/feed-column/item.tsx +++ b/apps/renderer/src/modules/feed-column/item.tsx @@ -9,7 +9,7 @@ import { FeedIcon } from "~/components/feed-icon" import { OouiUserAnonymous } from "~/components/icons/OouiUserAnonymous" import { Tooltip, TooltipContent, TooltipPortal, TooltipTrigger } from "~/components/ui/tooltip" import { EllipsisHorizontalTextWithTooltip } from "~/components/ui/typography" -import { useFeedActions, useListActions } from "~/hooks/biz/useFeedActions" +import { useFeedActions, useInboxActions, useListActions } from "~/hooks/biz/useFeedActions" import { useNavigateEntry } from "~/hooks/biz/useNavigateEntry" import { useRouteParamsSelector } from "~/hooks/biz/useRouteParams" import { useAnyPointDown } from "~/hooks/common" @@ -19,6 +19,7 @@ import { getNewIssueUrl } from "~/lib/issues" import { showNativeMenu } from "~/lib/native-menu" import { cn } from "~/lib/utils" import { getPreferredTitle, useFeedById } from "~/store/feed" +import { useInboxById } from "~/store/inbox" import { useListById } from "~/store/list" import { subscriptionActions, useSubscriptionByFeedId } from "~/store/subscription" import { useFeedUnreadStore } from "~/store/unread" @@ -173,7 +174,7 @@ const ListItemImpl: Component<{ }> = ({ view, listId, className }) => { const list = useListById(listId) - const isActive = useRouteParamsSelector((routerParams) => routerParams.feedId === listId) + const isActive = useRouteParamsSelector((routerParams) => routerParams.listId === listId) const { items } = useListActions({ listId, view }) const listUnread = useFeedUnreadStore((state) => state.data[listId] || 0) @@ -189,7 +190,7 @@ const ListItemImpl: Component<{ e.stopPropagation() navigate({ - feedId: listId, + listId, entryId: null, view, }) @@ -220,7 +221,7 @@ const ListItemImpl: Component<{
    - {list.title} + {getPreferredTitle(list)} {subscription.isPrivate && ( @@ -240,3 +241,60 @@ const ListItemImpl: Component<{ } export const ListItem = memo(ListItemImpl) + +const InboxItemImpl: Component<{ + inboxId: string + view: FeedViewType +}> = ({ view, inboxId, className }) => { + const inbox = useInboxById(inboxId) + + const isActive = useRouteParamsSelector((routerParams) => routerParams.inboxId === inboxId) + const { items } = useInboxActions({ inboxId }) + + const inboxUnread = useFeedUnreadStore((state) => state.data[inboxId] || 0) + + const [isContextMenuOpen, setIsContextMenuOpen] = useState(false) + useAnyPointDown(() => { + setIsContextMenuOpen(false) + }) + const navigate = useNavigateEntry() + const handleNavigate = useCallback( + (e: React.MouseEvent) => { + e.stopPropagation() + + navigate({ + inboxId, + entryId: null, + view, + }) + }, + [inboxId, navigate, view], + ) + if (!inbox) return null + return ( +
    { + setIsContextMenuOpen(true) + showNativeMenu(items, e) + }} + > +
    + + + {getPreferredTitle(inbox)} + +
    + +
    + ) +} + +export const InboxItem = memo(InboxItemImpl) diff --git a/apps/renderer/src/modules/feed-column/list.tsx b/apps/renderer/src/modules/feed-column/list.tsx index dc8ca8786..32423c082 100644 --- a/apps/renderer/src/modules/feed-column/list.tsx +++ b/apps/renderer/src/modules/feed-column/list.tsx @@ -22,7 +22,7 @@ import { import { useFeedUnreadStore } from "~/store/unread" import { getFeedListSort, setFeedListSortBy, setFeedListSortOrder, useFeedListSort } from "./atom" -import { SortableFeedList, SortByAlphabeticalList } from "./sort-by" +import { SortableFeedList, SortByAlphabeticalInbox, SortByAlphabeticalList } from "./sort-by" import { UnreadNumber } from "./unread-number" const useFeedsGroupedData = (view: FeedViewType) => { @@ -57,12 +57,32 @@ const useListsGroupedData = (view: FeedViewType) => { return useMemo(() => { if (!data || data.length === 0) return {} + const lists = data.filter((s) => "listId" in s) + const groupFolder = {} as Record - for (const subscription of data) { - if (!subscription.category && !subscription.defaultCategory) { - groupFolder[subscription.feedId] = [subscription.feedId] - } + for (const subscription of lists) { + groupFolder[subscription.feedId] = [subscription.feedId] + } + + return groupFolder + }, [data]) +} + +const useInboxesGroupedData = (view: FeedViewType) => { + const { data: remoteData } = useAuthQuery(Queries.subscription.byView(view)) + + const data = useSubscriptionByView(view) || remoteData + + return useMemo(() => { + if (!data || data.length === 0) return {} + + const inboxes = data.filter((s) => "inboxId" in s) + + const groupFolder = {} as Record + + for (const subscription of inboxes) { + groupFolder[subscription.feedId] = [subscription.feedId] } return groupFolder @@ -78,6 +98,7 @@ const useUpdateUnreadCount = () => { function FeedListImpl({ className, view }: { className?: string; view: number }) { const feedsData = useFeedsGroupedData(view) const listsData = useListsGroupedData(view) + const inboxesData = useInboxesGroupedData(view) const categoryOpenStateData = useCategoryOpenStateByView(view) const expansion = Object.values(categoryOpenStateData).every((value) => value === true) useUpdateUnreadCount() @@ -93,7 +114,10 @@ function FeedListImpl({ className, view }: { className?: string; view: number }) return unread }) - const hasData = Object.keys(feedsData).length > 0 || Object.keys(listsData).length > 0 + const hasData = + Object.keys(feedsData).length > 0 || + Object.keys(listsData).length > 0 || + Object.keys(inboxesData).length > 0 const feedId = useRouteFeedId() const navigateEntry = useNavigateEntry() @@ -104,6 +128,8 @@ function FeedListImpl({ className, view }: { className?: string; view: number }) useAuthQuery(Queries.lists.list()) const hasListData = Object.keys(listsData).length > 0 + const hasInboxData = Object.keys(inboxesData).length > 0 + return (
    @@ -164,11 +190,18 @@ function FeedListImpl({ className, view }: { className?: string; view: number })
    {t("words.lists")}
    - )} - {hasListData && hasData && ( + {hasInboxData && ( + <> +
    + {t("words.inbox")} +
    + + + )} + {(hasListData || hasInboxData) && (
    {
    ) } + +export const SortByAlphabeticalInboxList = ({ view }: ListListProps) => { + const isDesc = useFeedListSortSelector((s) => s.order === "desc") + + const inboxes = useInboxByView(view) + + const sortedInboxes = useMemo(() => { + const res = inboxes.sort((a, b) => { + return sortByAlphabet(a.title ?? "", b.title ?? "") + }) + + return isDesc ? res.reverse() : res + }, [isDesc, inboxes]) + + return ( +
    + {sortedInboxes.map((inbox) => ( + + ))} +
    + ) +} diff --git a/apps/renderer/src/modules/feed-column/sort-by/index.tsx b/apps/renderer/src/modules/feed-column/sort-by/index.tsx index 171070b1c..26575ec26 100644 --- a/apps/renderer/src/modules/feed-column/sort-by/index.tsx +++ b/apps/renderer/src/modules/feed-column/sort-by/index.tsx @@ -1,5 +1,9 @@ import { useFeedListSortSelector } from "../atom" -import { SortByAlphabeticalFeedList, SortByAlphabeticalListList } from "./SortByAlphabeticalList" +import { + SortByAlphabeticalFeedList, + SortByAlphabeticalInboxList, + SortByAlphabeticalListList, +} from "./SortByAlphabeticalList" import { SortByUnreadFeedList } from "./SortByUnreadList" import type { FeedListProps, ListListProps } from "./types" @@ -25,3 +29,13 @@ export const SortByAlphabeticalList = (props: ListListProps) => { } } } + +export const SortByAlphabeticalInbox = (props: ListListProps) => { + const by = useFeedListSortSelector((s) => s.by) + + switch (by) { + default: { + return + } + } +} diff --git a/apps/renderer/src/pages/(main)/(layer)/(subview)/discover/index.tsx b/apps/renderer/src/pages/(main)/(layer)/(subview)/discover/index.tsx index 891e7c37d..1b6511252 100644 --- a/apps/renderer/src/pages/(main)/(layer)/(subview)/discover/index.tsx +++ b/apps/renderer/src/pages/(main)/(layer)/(subview)/discover/index.tsx @@ -5,6 +5,7 @@ import { useSearchParams } from "react-router-dom" import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/components/ui/tabs" import { DiscoverForm } from "~/modules/discover/form" import { DiscoverImport } from "~/modules/discover/import" +import { DiscoverInboxList } from "~/modules/discover/inbox-list-form" import { Recommendations } from "~/modules/discover/recommendations" import { DiscoverRSS3 } from "~/modules/discover/rss3-form" import { DiscoverUser } from "~/modules/discover/user-form" @@ -28,6 +29,10 @@ const tabs: { name: "words.rsshub", value: "rsshub", }, + { + name: "words.inbox", + value: "inbox", + }, { name: "words.rss3", value: "rss3", @@ -36,11 +41,6 @@ const tabs: { name: "words.user", value: "user", }, - { - name: "words.email", - value: "email", - disabled: true, - }, { name: "words.import", value: "import", @@ -84,9 +84,10 @@ export function Component() { ) } -const TabComponent: Record> = { +const TabComponent: Record> = { import: DiscoverImport, rss3: DiscoverRSS3, + inbox: DiscoverInboxList, user: DiscoverUser, default: DiscoverForm, } diff --git a/apps/renderer/src/providers/extension-expose-provider.tsx b/apps/renderer/src/providers/extension-expose-provider.tsx index 48a35b321..ee071d38f 100644 --- a/apps/renderer/src/providers/extension-expose-provider.tsx +++ b/apps/renderer/src/providers/extension-expose-provider.tsx @@ -8,6 +8,7 @@ import { getGeneralSettings } from "~/atoms/settings/general" import { getUISettings } from "~/atoms/settings/ui" import { useModalStack } from "~/components/ui/modal" import { FeedForm } from "~/modules/discover/feed-form" +import { ListForm } from "~/modules/discover/list-form" import { usePresentUserProfileModal } from "~/modules/profile/hooks" export const ExtensionExposeProvider = () => { @@ -38,15 +39,12 @@ export const ExtensionExposeProvider = () => { title: options?.isList ? t("sidebar.feed_actions.edit_list") : t("sidebar.feed_actions.edit_feed"), - content: ({ dismiss }) => ( - - ), + content: ({ dismiss }) => + options?.isList ? ( + + ) : ( + + ), }) }, diff --git a/apps/renderer/src/queries/entries.ts b/apps/renderer/src/queries/entries.ts index 21854f238..de09647ec 100644 --- a/apps/renderer/src/queries/entries.ts +++ b/apps/renderer/src/queries/entries.ts @@ -7,23 +7,29 @@ import { entryHistoryActions } from "~/store/entry-history/action" export const entries = { entries: ({ - id, + feedId, + inboxId, + listId, view, read, limit, isArchived, }: { - id?: number | string + feedId?: number | string + inboxId?: number | string + listId?: number | string view?: number read?: boolean limit?: number isArchived?: boolean }) => defineQuery( - ["entries", id, view, read, limit], + ["entries", inboxId || listId || feedId, view, read, limit], async ({ pageParam }) => entryActions.fetchEntries({ - id, + feedId, + inboxId, + listId, view, read, limit, @@ -31,7 +37,7 @@ export const entries = { isArchived, }), { - rootKey: ["entries", id], + rootKey: ["entries", inboxId || listId || feedId], structuralSharing: false, }, ), @@ -39,6 +45,10 @@ export const entries = { defineQuery(["entry", id], async () => entryActions.fetchEntryById(id), { rootKey: ["entries"], }), + byInboxId: (id: string) => + defineQuery(["entry", id], async () => entryActions.fetchInboxEntryById(id), { + rootKey: ["entries"], + }), preview: (id: string) => defineQuery( ["entries-preview", id], @@ -57,22 +67,28 @@ export const entries = { ), checkNew: ({ - id, + feedId, + inboxId, + listId, view, read, fetchedTime, }: { - id?: number | string + feedId?: number | string + inboxId?: number | string + listId?: number | string view?: number read?: boolean fetchedTime: number }) => defineQuery( - ["entry-checkNew", id, view, read, fetchedTime], + ["entry-checkNew", inboxId || listId || feedId, view, read, fetchedTime], async () => { const query = { ...getEntriesParams({ - id, + feedId, + inboxId, + listId, view, }), read, @@ -95,7 +111,7 @@ export const entries = { }, { - rootKey: ["entry-checkNew", id], + rootKey: ["entry-checkNew", inboxId || listId || feedId], }, ), @@ -110,22 +126,24 @@ export const entries = { } export const useEntries = ({ - id, + feedId, + inboxId, + listId, view, read, isArchived, - isList, }: { - id?: number | string + feedId?: number | string + inboxId?: number | string + listId?: number | string view?: number read?: boolean isArchived?: boolean - isList?: boolean }) => - useAuthInfiniteQuery(entries.entries({ id, view, read, isArchived }), { - enabled: id !== undefined, + useAuthInfiniteQuery(entries.entries({ feedId, inboxId, listId, view, read, isArchived }), { + enabled: feedId !== undefined || inboxId !== undefined || listId !== undefined, getNextPageParam: (lastPage) => - isList + inboxId ? lastPage.data?.at(-1)?.entries.insertedAt : lastPage.data?.at(-1)?.entries.publishedAt, initialPageParam: undefined, diff --git a/apps/renderer/src/queries/feed.ts b/apps/renderer/src/queries/feed.ts index 3419c3ef7..a1a4f27bf 100644 --- a/apps/renderer/src/queries/feed.ts +++ b/apps/renderer/src/queries/feed.ts @@ -12,14 +12,13 @@ import { feedActions } from "~/store/feed" import { entries } from "./entries" export const feed = { - byId: ({ id, url, isList }: FeedQueryParams) => + byId: ({ id, url }: FeedQueryParams) => defineQuery( ["feed", id, url], async () => feedActions.fetchFeedById({ id, url, - isList, }), { rootKey: ["feed"], @@ -41,12 +40,11 @@ export const feed = { }), } -export const useFeed = ({ id, url, isList }: FeedQueryParams) => +export const useFeed = ({ id, url }: FeedQueryParams) => useAuthQuery( feed.byId({ id, url, - isList, }), { enabled: @@ -78,7 +76,7 @@ export const useRefreshFeedMutation = (feedId?: string) => if (!feedId) return entries .entries({ - id: feedId!, + feedId: feedId!, }) .invalidateRoot() }, diff --git a/apps/renderer/src/queries/inboxes.ts b/apps/renderer/src/queries/inboxes.ts new file mode 100644 index 000000000..d715fa612 --- /dev/null +++ b/apps/renderer/src/queries/inboxes.ts @@ -0,0 +1,15 @@ +import { useAuthQuery } from "~/hooks/common" +import { defineQuery } from "~/lib/defineQuery" +import { inboxActions } from "~/store/inbox" + +export const inboxes = { + byId: ({ id }: { id: string }) => + defineQuery(["lists", id], async () => inboxActions.fetchInboxById(id), { + rootKey: ["lists"], + }), +} + +export const useInbox = ({ id }: { id?: string }) => + useAuthQuery(inboxes.byId({ id: id! }), { + enabled: !!id, + }) diff --git a/apps/renderer/src/queries/lists.ts b/apps/renderer/src/queries/lists.ts index 24da78477..b7475a4b7 100644 --- a/apps/renderer/src/queries/lists.ts +++ b/apps/renderer/src/queries/lists.ts @@ -13,7 +13,7 @@ export const lists = { }), } -export const useList = ({ id }: { id: string }) => - useAuthQuery(lists.byId({ id }), { +export const useList = ({ id }: { id?: string }) => + useAuthQuery(lists.byId({ id: id! }), { enabled: !!id, }) diff --git a/apps/renderer/src/services/inbox.ts b/apps/renderer/src/services/inbox.ts new file mode 100644 index 000000000..bb5038fb2 --- /dev/null +++ b/apps/renderer/src/services/inbox.ts @@ -0,0 +1,33 @@ +import { browserDB } from "~/database" +import type { InboxModel } from "~/models/types" + +import { BaseService } from "./base" +import { CleanerService } from "./cleaner" + +class ServiceStatic extends BaseService<{ id: string }> { + constructor() { + super(browserDB.inboxes) + } + + override async upsertMany(data: InboxModel[]) { + CleanerService.reset(data.map((d) => ({ type: "feed", id: d.id! }))) + + return this.table.bulkPut(data) + } + + override async findAll() { + return super.findAll() as unknown as InboxModel[] + } + + override async upsert(data: InboxModel): Promise { + if (!data.id) return null + CleanerService.reset([{ type: "feed", id: data.id }]) + return this.table.put(data) + } + + async bulkDelete(ids: string[]) { + return this.table.bulkDelete(ids) + } +} + +export const InboxService = new ServiceStatic() diff --git a/apps/renderer/src/services/subscription.ts b/apps/renderer/src/services/subscription.ts index af0952eb7..87f9bc0ce 100644 --- a/apps/renderer/src/services/subscription.ts +++ b/apps/renderer/src/services/subscription.ts @@ -27,7 +27,7 @@ class SubscriptionServiceStatic extends BaseService { override async upsertMany(data: SubscriptionFlatModel[]) { return this.table.bulkPut( - data.map(({ feeds, ...d }: any) => ({ + data.map(({ feeds, lists, inboxes, ...d }: any) => ({ ...d, id: this.uniqueId(d.userId, d.feedId), })), diff --git a/apps/renderer/src/store/entry/store.ts b/apps/renderer/src/store/entry/store.ts index 5ad529df2..06fb4f74a 100644 --- a/apps/renderer/src/store/entry/store.ts +++ b/apps/renderer/src/store/entry/store.ts @@ -10,6 +10,7 @@ import { EntryService } from "~/services" import { feedActions } from "../feed" import { imageActions } from "../image" +import { inboxActions } from "../inbox" import { feedUnreadActions } from "../unread" import { createZustandStore, doMutationAndTransaction } from "../utils/helper" import { internal_batchMarkRead } from "./helper" @@ -67,34 +68,65 @@ class EntryActions { return data } + async fetchInboxEntryById(entryId: string) { + const { data } = await apiClient.entries.inbox.$get({ + query: { + id: entryId, + }, + }) + if (data) { + this.upsertMany([ + // patch data, should omit `read` because the network race condition or server cache + omit(data, "read") as any, + ]) + inboxActions.upsertMany([data.feeds]) + } + + return data + } + async fetchEntries({ - id, + feedId, + inboxId, + listId, view, read, limit, pageParam, isArchived, }: { - id?: number | string + feedId?: number | string + inboxId?: number | string + listId?: number | string view?: number read?: boolean limit?: number pageParam?: string isArchived?: boolean }) { - const data = await apiClient.entries.$post({ - json: { - publishedAfter: pageParam, - read, - limit, - isArchived, - // withContent: true, - ...getEntriesParams({ - id, - view, - }), - }, - }) + const data = inboxId + ? await apiClient.entries.inbox.$post({ + json: { + publishedAfter: pageParam, + limit, + inboxId: `${inboxId}`, + }, + }) + : await apiClient.entries.$post({ + json: { + publishedAfter: pageParam, + read, + limit, + isArchived, + // withContent: true, + ...getEntriesParams({ + feedId, + inboxId, + listId, + view, + }), + }, + }) if (data.data) { this.upsertMany(data.data) @@ -226,7 +258,7 @@ class EntryActions { // Push entryFeedMap entryFeedMap[item.entries.id] = item.feeds.id // Push entryCollection - if (item.collections) { + if ("collections" in item) { entryCollection[item.entries.id] = item.collections } @@ -294,7 +326,7 @@ class EntryActions { ) // Push entryCollection - if (item.collections) { + if ("collections" in item) { entryCollection[item.entries.id] = item.collections } } diff --git a/apps/renderer/src/store/feed/store.ts b/apps/renderer/src/store/feed/store.ts index 3858cd224..9c62fdc15 100644 --- a/apps/renderer/src/store/feed/store.ts +++ b/apps/renderer/src/store/feed/store.ts @@ -133,6 +133,10 @@ export const getPreferredTitle = (feed?: FeedOrListRespModel | null) => { return feed?.title } + if (feed.type === "inbox") { + return feed.title || `${feed.id.slice(0, 1).toUpperCase()}${feed.id.slice(1)}'s Inbox` + } + const subscription = getSubscriptionByFeedId(feed.id) return subscription?.title || feed.title } diff --git a/apps/renderer/src/store/feed/types.ts b/apps/renderer/src/store/feed/types.ts index 1822b2e36..90f6d8cca 100644 --- a/apps/renderer/src/store/feed/types.ts +++ b/apps/renderer/src/store/feed/types.ts @@ -5,4 +5,4 @@ type FeedId = string export interface FeedState { feeds: Record } -export type FeedQueryParams = { id?: string; url?: string; isList?: boolean } +export type FeedQueryParams = { id?: string; url?: string } diff --git a/apps/renderer/src/store/inbox/hooks.ts b/apps/renderer/src/store/inbox/hooks.ts new file mode 100644 index 000000000..8120801ee --- /dev/null +++ b/apps/renderer/src/store/inbox/hooks.ts @@ -0,0 +1,11 @@ +import type { FeedViewType } from "~/lib/enum" +import type { InboxModel } from "~/models" + +import { useInboxStore } from "./store" + +export const useInboxById = (inboxId: Nullable): InboxModel | null => + useInboxStore((state) => (inboxId ? state.inboxes[inboxId] : null)) + +export const useInboxByView = (view: FeedViewType) => { + return useInboxStore((state) => (view === 0 ? Object.values(state.inboxes) : [])) +} diff --git a/apps/renderer/src/store/inbox/index.ts b/apps/renderer/src/store/inbox/index.ts new file mode 100644 index 000000000..a92fe14dc --- /dev/null +++ b/apps/renderer/src/store/inbox/index.ts @@ -0,0 +1,3 @@ +export * from "./hooks" +export * from "./store" +export * from "./types" diff --git a/apps/renderer/src/store/inbox/store.ts b/apps/renderer/src/store/inbox/store.ts new file mode 100644 index 000000000..f0a8b34ea --- /dev/null +++ b/apps/renderer/src/store/inbox/store.ts @@ -0,0 +1,52 @@ +import { runTransactionInScope } from "~/database" +import { apiClient } from "~/lib/api-fetch" +import type { InboxModel } from "~/models" +import { InboxService } from "~/services/inbox" + +import { createImmerSetter, createZustandStore } from "../utils/helper" +import type { InboxState } from "./types" + +export const useInboxStore = createZustandStore("inbox")(() => ({ + inboxes: {}, +})) + +const set = createImmerSetter(useInboxStore) + +class InboxActionStatic { + upsertMany(inboxs: InboxModel[]) { + if (inboxs.length === 0) return + set((state) => { + for (const inbox of inboxs) { + state.inboxes[inbox.id] = inbox + } + return state + }) + + runTransactionInScope(() => InboxService.upsertMany(inboxs)) + } + + async fetchInboxById(id: string) { + const res = await apiClient.inboxes.$get({ + query: { + handle: id, + }, + }) + this.upsertMany([res.data]) + + return res.data + } + + clear() { + set((state) => { + state.inboxes = {} + }) + } + + clearByInboxId(id: string) { + set((state) => { + delete state.inboxes[id] + }) + } +} + +export const inboxActions = new InboxActionStatic() diff --git a/apps/renderer/src/store/inbox/types.ts b/apps/renderer/src/store/inbox/types.ts new file mode 100644 index 000000000..2154082d0 --- /dev/null +++ b/apps/renderer/src/store/inbox/types.ts @@ -0,0 +1,7 @@ +import type { InboxModel } from "~/models" + +type InboxId = string + +export interface InboxState { + inboxes: Record +} diff --git a/apps/renderer/src/store/subscription/store.ts b/apps/renderer/src/store/subscription/store.ts index 988ba2055..9ba78a2c3 100644 --- a/apps/renderer/src/store/subscription/store.ts +++ b/apps/renderer/src/store/subscription/store.ts @@ -7,12 +7,13 @@ import { runTransactionInScope } from "~/database" import { apiClient } from "~/lib/api-fetch" import { FeedViewType } from "~/lib/enum" import { capitalizeFirstLetter } from "~/lib/utils" -import type { FeedModel, ListModelPoplutedFeeds, SubscriptionModel } from "~/models" +import type { FeedModel, InboxModel, ListModelPoplutedFeeds, SubscriptionModel } from "~/models" import { SubscriptionService } from "~/services" import { entryActions } from "../entry" import { feedActions, getFeedById } from "../feed" -import { listActions } from "../list/store" +import { inboxActions } from "../inbox" +import { listActions } from "../list" import { feedUnreadActions } from "../unread" import { createZustandStore, doMutationAndTransaction } from "../utils/helper" @@ -120,16 +121,20 @@ class SubscriptionActions { const feeds = [] as FeedModel[] const lists = [] as ListModelPoplutedFeeds[] + const inboxes = [] as InboxModel[] for (const subscription of res.data) { if ("feeds" in subscription) { feeds.push(subscription.feeds) - } else { + } else if ("lists" in subscription) { lists.push(subscription.lists) + } else if ("inboxes" in subscription) { + inboxes.push(subscription.inboxes) } } this.updateCategoryOpenState(transformedData.filter((s) => s.category || s.defaultCategory)) feedActions.upsertMany(feeds) listActions.upsertMany(lists) + inboxActions.upsertMany(inboxes) return res.data } @@ -141,7 +146,11 @@ class SubscriptionActions { set((state) => produce(state, (state) => { subscriptions.forEach((subscription) => { - state.data[subscription.feedId] = omit(subscription, "feeds") + state.data[subscription.feedId] = omit(subscription, [ + "feeds", + "lists", + "inboxes", + ]) as SubscriptionFlatModel state.feedIdByView[subscription.view].push(subscription.feedId) return state }) diff --git a/icons/mgc/inbox_cute_fi.svg b/icons/mgc/inbox_cute_fi.svg new file mode 100644 index 000000000..0450ef3f1 --- /dev/null +++ b/icons/mgc/inbox_cute_fi.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/locales/app/ar-DZ.json b/locales/app/ar-DZ.json index 7f8417649..1a6c47c52 100644 --- a/locales/app/ar-DZ.json +++ b/locales/app/ar-DZ.json @@ -188,7 +188,6 @@ "words.add": "إضافة", "words.confirm": "تأكيد", "words.discover": "استكشاف", - "words.email": "البريد الإلكتروني", "words.import": "استيراد", "words.items": "العناصر", "words.language": "اللغة", diff --git a/locales/app/ar-IQ.json b/locales/app/ar-IQ.json index 7fee8b035..ec3e70307 100644 --- a/locales/app/ar-IQ.json +++ b/locales/app/ar-IQ.json @@ -192,7 +192,6 @@ "words.add": "إضافة", "words.confirm": "تأكيد", "words.discover": "اكتشاف", - "words.email": "البريد الإلكتروني", "words.import": "استيراد", "words.items": "عناصر", "words.language": "اللغة", diff --git a/locales/app/ar-KW.json b/locales/app/ar-KW.json index 1e6151319..601b2d8ee 100644 --- a/locales/app/ar-KW.json +++ b/locales/app/ar-KW.json @@ -192,7 +192,6 @@ "words.add": "إضافة", "words.confirm": "تأكيد", "words.discover": "استكشاف", - "words.email": "البريد الإلكتروني", "words.import": "استيراد", "words.items": "عناصر", "words.language": "اللغة", diff --git a/locales/app/ar-MA.json b/locales/app/ar-MA.json index db0ec7180..8787e3590 100644 --- a/locales/app/ar-MA.json +++ b/locales/app/ar-MA.json @@ -188,7 +188,6 @@ "words.add": "إضافة", "words.confirm": "تأكيد", "words.discover": "استكشاف", - "words.email": "البريد الإلكتروني", "words.import": "استيراد", "words.items": "عناصر", "words.language": "اللغة", diff --git a/locales/app/ar-SA.json b/locales/app/ar-SA.json index b7ab184d0..78793ad86 100644 --- a/locales/app/ar-SA.json +++ b/locales/app/ar-SA.json @@ -188,7 +188,6 @@ "words.add": "إضافة", "words.confirm": "تأكيد", "words.discover": "استكشاف", - "words.email": "البريد الإلكتروني", "words.import": "استيراد", "words.items": "عناصر", "words.language": "اللغة", diff --git a/locales/app/ar-TN.json b/locales/app/ar-TN.json index 0867f3181..bfef62487 100644 --- a/locales/app/ar-TN.json +++ b/locales/app/ar-TN.json @@ -192,7 +192,6 @@ "words.add": "إضافة", "words.confirm": "تأكيد", "words.discover": "استكشاف", - "words.email": "البريد الإلكتروني", "words.import": "استيراد", "words.items": "عناصر", "words.language": "اللغة", diff --git a/locales/app/de.json b/locales/app/de.json index be19d1219..2aea303b8 100644 --- a/locales/app/de.json +++ b/locales/app/de.json @@ -192,7 +192,6 @@ "words.add": "Hinzufügen", "words.confirm": "Bestätigen", "words.discover": "Entdecken", - "words.email": "E-Mail", "words.import": "Importieren", "words.items": "Elemente", "words.language": "Sprache", diff --git a/locales/app/en.json b/locales/app/en.json index 64272ca93..9757eb883 100644 --- a/locales/app/en.json +++ b/locales/app/en.json @@ -21,6 +21,27 @@ "discover.import.parsedErrorItems": "Parsed Error Items", "discover.import.result": " feeds were successfully imported, were already subscribed to, and failed to import.", "discover.import.successfulItems": "Successful Items", + "discover.inbox.actions": "Actions", + "discover.inbox.description": "You can receive information via email and webhooks through the inbox.", + "discover.inbox.email": "Email", + "discover.inbox.handle": "Handle", + "discover.inbox.secret": "Secret", + "discover.inbox.title": "Title", + "discover.inbox.webhooks_docs": "Webhooks docs.", + "discover.inbox_create": "New Inbox", + "discover.inbox_create_description": "You don't have an inbox yet. Create an inbox to receive information via inbox.", + "discover.inbox_create_error": "Failed to create inbox.", + "discover.inbox_create_success": "Inbox created successfully.", + "discover.inbox_destroy": "Destroy", + "discover.inbox_destroy_confirm": "Confirm destroy the inbox?", + "discover.inbox_destroy_error": "Failed to destroy inbox.", + "discover.inbox_destroy_success": "Inbox destroyed successfully.", + "discover.inbox_destroy_warning": "Warning: once destroyed, the email will no longer be available, and all content will be permanently deleted and unrecoverable.", + "discover.inbox_handle": "Handle", + "discover.inbox_title": "Title", + "discover.inbox_update": "Update", + "discover.inbox_update_error": "Failed to change inbox.", + "discover.inbox_update_success": "Inbox updated successfully.", "discover.popular": "Popular", "discover.preview": "Preview", "discover.rss_hub_route": "RSSHub Route", @@ -168,18 +189,21 @@ "sidebar.category_remove_dialog.title": "Remove Category", "sidebar.feed_actions.claim": "Claim", "sidebar.feed_actions.claim_feed": "Claim Feed", + "sidebar.feed_actions.copy_email_address": "Copy email address", "sidebar.feed_actions.copy_feed_id": "Copy feed ID", "sidebar.feed_actions.copy_feed_url": "Copy feed URL", "sidebar.feed_actions.copy_list_id": "Copy list ID", "sidebar.feed_actions.copy_list_url": "Copy list URL", "sidebar.feed_actions.edit": "Edit", "sidebar.feed_actions.edit_feed": "Edit feed", + "sidebar.feed_actions.edit_inbox": "Edit inbox", "sidebar.feed_actions.edit_list": "Edit list", "sidebar.feed_actions.feed_owned_by_you": "This feed is owned by you", "sidebar.feed_actions.list_owned_by_you": "This list is owned by you", "sidebar.feed_actions.mark_all_as_read": "Mark all as read", "sidebar.feed_actions.navigate_to_feed": "Navigate to feed", "sidebar.feed_actions.navigate_to_list": "Navigate to list", + "sidebar.feed_actions.new_inbox": "New inbox", "sidebar.feed_actions.open_feed_in_browser": "Open feed in {{which}}", "sidebar.feed_actions.open_list_in_browser": "Open list in {{which}}", "sidebar.feed_actions.open_site_in_browser": "Open site in {{which}}", @@ -227,9 +251,9 @@ "words.browser": "Browser", "words.confirm": "Confirm", "words.discover": "Discover", - "words.email": "Email", "words.feeds": "Feeds", "words.import": "Import", + "words.inbox": "Inbox", "words.items": "Items", "words.language": "Language", "words.lists": "Lists", diff --git a/locales/app/es.json b/locales/app/es.json index d17a3ff23..279e715c0 100644 --- a/locales/app/es.json +++ b/locales/app/es.json @@ -121,7 +121,6 @@ "words.add": "Añadir", "words.confirm": "Confirmar", "words.discover": "Descubrir", - "words.email": "Correo electrónico", "words.import": "Importar", "words.items": "Contenido", "words.language": "Idioma", diff --git a/locales/app/fi.json b/locales/app/fi.json index 797ee04eb..def250507 100644 --- a/locales/app/fi.json +++ b/locales/app/fi.json @@ -188,7 +188,6 @@ "words.add": "Lisää", "words.confirm": "Vahvista", "words.discover": "Löydä", - "words.email": "Sähköposti", "words.import": "Tuo", "words.items": "Kohteet", "words.language": "Kieli", diff --git a/locales/app/fr.json b/locales/app/fr.json index 5093ee53c..a5275aa9f 100644 --- a/locales/app/fr.json +++ b/locales/app/fr.json @@ -188,7 +188,6 @@ "words.add": "Ajouter", "words.confirm": "Confirmer", "words.discover": "Découvrir", - "words.email": "Email", "words.import": "Importer", "words.items": "Éléments", "words.language": "Langue", diff --git a/locales/app/it.json b/locales/app/it.json index eb4f0f315..8e573688a 100644 --- a/locales/app/it.json +++ b/locales/app/it.json @@ -188,7 +188,6 @@ "words.add": "Aggiungi", "words.confirm": "Conferma", "words.discover": "Scopri", - "words.email": "Email", "words.import": "Importa", "words.items": "Elementi", "words.language": "Lingua", diff --git a/locales/app/ja.json b/locales/app/ja.json index 51b0dde27..69bf0291c 100644 --- a/locales/app/ja.json +++ b/locales/app/ja.json @@ -188,7 +188,6 @@ "words.add": "追加", "words.confirm": "確認", "words.discover": "発見", - "words.email": "メール", "words.import": "インポート", "words.items": "アイテム", "words.language": "言語", diff --git a/locales/app/ko.json b/locales/app/ko.json index a7823c011..579834208 100644 --- a/locales/app/ko.json +++ b/locales/app/ko.json @@ -220,7 +220,6 @@ "words.add": "추가", "words.confirm": "확인", "words.discover": "찾아보기", - "words.email": "이메일", "words.feeds": "피드", "words.import": "가져오기", "words.items": "항목", diff --git a/locales/app/pt.json b/locales/app/pt.json index 191a45783..3f6045d74 100644 --- a/locales/app/pt.json +++ b/locales/app/pt.json @@ -188,7 +188,6 @@ "words.add": "追加", "words.confirm": "確認", "words.discover": "発見", - "words.email": "メール", "words.import": "インポート", "words.items": "アイテム", "words.language": "言語", diff --git a/locales/app/ru.json b/locales/app/ru.json index 91c439e34..14b712523 100644 --- a/locales/app/ru.json +++ b/locales/app/ru.json @@ -188,7 +188,6 @@ "words.add": "Добавить", "words.confirm": "Подтвердить", "words.discover": "Открыть", - "words.email": "Электронная почта", "words.import": "Импорт", "words.items": "Элементы", "words.language": "Язык", diff --git a/locales/app/tr.json b/locales/app/tr.json index fca76847e..afe71a445 100644 --- a/locales/app/tr.json +++ b/locales/app/tr.json @@ -221,7 +221,6 @@ "words.add": "Ekle", "words.confirm": "Onayla", "words.discover": "Keşfet", - "words.email": "E-posta", "words.feeds": "Beslemeler", "words.import": "İçe Aktar", "words.items": "Öğeler", diff --git a/locales/app/zh-CN.json b/locales/app/zh-CN.json index 881bd3355..dccfe62aa 100644 --- a/locales/app/zh-CN.json +++ b/locales/app/zh-CN.json @@ -227,7 +227,6 @@ "words.browser": "浏览器", "words.confirm": "确认", "words.discover": "发现", - "words.email": "邮箱", "words.feeds": "订阅源", "words.import": "导入", "words.items": "内容", diff --git a/locales/app/zh-HK.json b/locales/app/zh-HK.json index 9762faff1..05021d1b6 100644 --- a/locales/app/zh-HK.json +++ b/locales/app/zh-HK.json @@ -226,7 +226,6 @@ "words.browser": "瀏覽器", "words.confirm": "確認", "words.discover": "探索", - "words.email": "電子郵件", "words.feeds": "訂閱源", "words.import": "匯入", "words.items": "項目", diff --git a/locales/app/zh-TW.json b/locales/app/zh-TW.json index 371ec804d..238cc7244 100644 --- a/locales/app/zh-TW.json +++ b/locales/app/zh-TW.json @@ -226,7 +226,6 @@ "words.browser": "瀏覽器", "words.confirm": "確認", "words.discover": "發現", - "words.email": "Email", "words.feeds": "摘要", "words.import": "匯入", "words.items": "內容", diff --git a/locales/errors/en.json b/locales/errors/en.json index 2645c057f..7075c8ff0 100644 --- a/locales/errors/en.json +++ b/locales/errors/en.json @@ -32,5 +32,8 @@ "8002": "List limit exceeded", "8003": "Feed already added to list", "9000": "Achievement not completed", - "9001": "Achievement already received" + "9001": "Achievement already received", + "10000": "Inbox not found", + "10001": "Inbox already exists", + "10002": "Inbox limit exceeded" } diff --git a/packages/shared/src/env.ts b/packages/shared/src/env.ts index 40d2af372..c114b890d 100644 --- a/packages/shared/src/env.ts +++ b/packages/shared/src/env.ts @@ -10,6 +10,7 @@ export const env = createEnv({ VITE_IMGPROXY_URL: z.string().url(), VITE_SENTRY_DSN: z.string().optional(), VITE_POSTHOG_KEY: z.string().optional(), + VITE_INBOXES_EMAIL: z.string().default("@follow.re"), }, emptyStringAsUndefined: true, diff --git a/packages/shared/src/hono.ts b/packages/shared/src/hono.ts index 9199002b4..2d28b4485 100644 --- a/packages/shared/src/hono.ts +++ b/packages/shared/src/hono.ts @@ -673,6 +673,111 @@ type ExtraModel = { content_html?: string; }[]; }; +declare const CommonEntryFields: { + id: drizzle_orm.HasRuntimeDefault>>>>; + title: drizzle_orm_pg_core.PgTextBuilder<{ + name: "title"; + dataType: "string"; + columnType: "PgText"; + data: string; + enumValues: [string, ...string[]]; + driverParam: string; + generated: undefined; + }>; + url: drizzle_orm_pg_core.PgTextBuilder<{ + name: "url"; + dataType: "string"; + columnType: "PgText"; + data: string; + enumValues: [string, ...string[]]; + driverParam: string; + generated: undefined; + }>; + content: drizzle_orm_pg_core.PgTextBuilder<{ + name: "content"; + dataType: "string"; + columnType: "PgText"; + data: string; + enumValues: [string, ...string[]]; + driverParam: string; + generated: undefined; + }>; + description: drizzle_orm_pg_core.PgTextBuilder<{ + name: "description"; + dataType: "string"; + columnType: "PgText"; + data: string; + enumValues: [string, ...string[]]; + driverParam: string; + generated: undefined; + }>; + guid: drizzle_orm.NotNull>; + author: drizzle_orm_pg_core.PgTextBuilder<{ + name: "author"; + dataType: "string"; + columnType: "PgText"; + data: string; + enumValues: [string, ...string[]]; + driverParam: string; + generated: undefined; + }>; + authorUrl: drizzle_orm_pg_core.PgTextBuilder<{ + name: "author_url"; + dataType: "string"; + columnType: "PgText"; + data: string; + enumValues: [string, ...string[]]; + driverParam: string; + generated: undefined; + }>; + authorAvatar: drizzle_orm_pg_core.PgTextBuilder<{ + name: "author_avatar"; + dataType: "string"; + columnType: "PgText"; + data: string; + enumValues: [string, ...string[]]; + driverParam: string; + generated: undefined; + }>; + insertedAt: drizzle_orm.NotNull>; + publishedAt: drizzle_orm.NotNull>; + media: drizzle_orm.$Type, MediaModel[]>; + categories: drizzle_orm_pg_core.PgArrayBuilder<{ + name: "categories"; + dataType: "array"; + columnType: "PgArray"; + data: string[]; + driverParam: string | string[]; + enumValues: [string, ...string[]]; + generated: drizzle_orm.GeneratedColumnConfig; + }, { + name: "categories"; + dataType: "string"; + columnType: "PgText"; + data: string; + enumValues: [string, ...string[]]; + driverParam: string; + generated: undefined; + }>; + attachments: drizzle_orm.$Type, AttachmentsModel[]>; + extra: drizzle_orm.$Type, ExtraModel>; +}; declare const entries: drizzle_orm_pg_core.PgTableWithColumns<{ name: "entries"; schema: undefined; @@ -693,22 +798,6 @@ declare const entries: drizzle_orm_pg_core.PgTableWithColumns<{ baseColumn: never; generated: undefined; }, {}, {}>; - feedId: drizzle_orm_pg_core.PgColumn<{ - name: "feed_id"; - tableName: "entries"; - dataType: "string"; - columnType: "PgText"; - data: string; - driverParam: string; - notNull: true; - hasDefault: false; - isPrimaryKey: false; - isAutoincrement: false; - hasRuntimeDefault: false; - enumValues: [string, ...string[]]; - baseColumn: never; - generated: undefined; - }, {}, {}>; title: drizzle_orm_pg_core.PgColumn<{ name: "title"; tableName: "entries"; @@ -948,12 +1037,95 @@ declare const entries: drizzle_orm_pg_core.PgTableWithColumns<{ baseColumn: never; generated: undefined; }, {}, {}>; + feedId: drizzle_orm_pg_core.PgColumn<{ + name: "feed_id"; + tableName: "entries"; + dataType: "string"; + columnType: "PgText"; + data: string; + driverParam: string; + notNull: true; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: [string, ...string[]]; + baseColumn: never; + generated: undefined; + }, {}, {}>; }; dialect: "pg"; }>; +declare const attachmentsZodSchema: z.ZodNullable; + mime_type: z.ZodOptional; + size_in_bytes: z.ZodOptional; + title: z.ZodOptional; +}, "strip", z.ZodTypeAny, { + url: string; + title?: string | undefined; + duration_in_seconds?: number | undefined; + mime_type?: string | undefined; + size_in_bytes?: number | undefined; +}, { + url: string; + title?: string | undefined; + duration_in_seconds?: number | undefined; + mime_type?: string | undefined; + size_in_bytes?: number | undefined; +}>, "many">>>; +declare const mediaZodSchema: z.ZodNullable; + width: z.ZodOptional; + height: z.ZodOptional; + preview_image_url: z.ZodOptional; + blurhash: z.ZodOptional; +}, "strip", z.ZodTypeAny, { + type: "photo" | "video"; + url: string; + width?: number | undefined; + height?: number | undefined; + preview_image_url?: string | undefined; + blurhash?: string | undefined; +}, { + type: "photo" | "video"; + url: string; + width?: number | undefined; + height?: number | undefined; + preview_image_url?: string | undefined; + blurhash?: string | undefined; +}>, "many">>>; +declare const extraZodSchema: z.ZodNullable; + }, "strip", z.ZodTypeAny, { + type: string; + url: string; + content_html?: string | undefined; + }, { + type: string; + url: string; + content_html?: string | undefined; + }>, "many">>>; +}, "strip", z.ZodTypeAny, { + links?: { + type: string; + url: string; + content_html?: string | undefined; + }[] | null | undefined; +}, { + links?: { + type: string; + url: string; + content_html?: string | undefined; + }[] | null | undefined; +}>>>; declare const entriesOpenAPISchema: z.ZodObject; url: z.ZodNullable; content: z.ZodNullable; @@ -980,6 +1152,7 @@ declare const entriesOpenAPISchema: z.ZodObject>; + feedId: z.ZodString; }, "media" | "attachments" | "extra">, { attachments: z.ZodNullable; }>; +declare const inboxesEntries: drizzle_orm_pg_core.PgTableWithColumns<{ + name: "inboxes_entries"; + schema: undefined; + columns: { + id: drizzle_orm_pg_core.PgColumn<{ + name: "id"; + tableName: "inboxes_entries"; + dataType: "string"; + columnType: "PgText"; + data: string; + driverParam: string; + notNull: true; + hasDefault: true; + isPrimaryKey: true; + isAutoincrement: false; + hasRuntimeDefault: true; + enumValues: [string, ...string[]]; + baseColumn: never; + generated: undefined; + }, {}, {}>; + title: drizzle_orm_pg_core.PgColumn<{ + name: "title"; + tableName: "inboxes_entries"; + dataType: "string"; + columnType: "PgText"; + data: string; + driverParam: string; + notNull: false; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: [string, ...string[]]; + baseColumn: never; + generated: undefined; + }, {}, {}>; + url: drizzle_orm_pg_core.PgColumn<{ + name: "url"; + tableName: "inboxes_entries"; + dataType: "string"; + columnType: "PgText"; + data: string; + driverParam: string; + notNull: false; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: [string, ...string[]]; + baseColumn: never; + generated: undefined; + }, {}, {}>; + content: drizzle_orm_pg_core.PgColumn<{ + name: "content"; + tableName: "inboxes_entries"; + dataType: "string"; + columnType: "PgText"; + data: string; + driverParam: string; + notNull: false; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: [string, ...string[]]; + baseColumn: never; + generated: undefined; + }, {}, {}>; + description: drizzle_orm_pg_core.PgColumn<{ + name: "description"; + tableName: "inboxes_entries"; + dataType: "string"; + columnType: "PgText"; + data: string; + driverParam: string; + notNull: false; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: [string, ...string[]]; + baseColumn: never; + generated: undefined; + }, {}, {}>; + guid: drizzle_orm_pg_core.PgColumn<{ + name: "guid"; + tableName: "inboxes_entries"; + dataType: "string"; + columnType: "PgText"; + data: string; + driverParam: string; + notNull: true; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: [string, ...string[]]; + baseColumn: never; + generated: undefined; + }, {}, {}>; + author: drizzle_orm_pg_core.PgColumn<{ + name: "author"; + tableName: "inboxes_entries"; + dataType: "string"; + columnType: "PgText"; + data: string; + driverParam: string; + notNull: false; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: [string, ...string[]]; + baseColumn: never; + generated: undefined; + }, {}, {}>; + authorUrl: drizzle_orm_pg_core.PgColumn<{ + name: "author_url"; + tableName: "inboxes_entries"; + dataType: "string"; + columnType: "PgText"; + data: string; + driverParam: string; + notNull: false; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: [string, ...string[]]; + baseColumn: never; + generated: undefined; + }, {}, {}>; + authorAvatar: drizzle_orm_pg_core.PgColumn<{ + name: "author_avatar"; + tableName: "inboxes_entries"; + dataType: "string"; + columnType: "PgText"; + data: string; + driverParam: string; + notNull: false; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: [string, ...string[]]; + baseColumn: never; + generated: undefined; + }, {}, {}>; + insertedAt: drizzle_orm_pg_core.PgColumn<{ + name: "inserted_at"; + tableName: "inboxes_entries"; + dataType: "date"; + columnType: "PgTimestamp"; + data: Date; + driverParam: string; + notNull: true; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: undefined; + baseColumn: never; + generated: undefined; + }, {}, {}>; + publishedAt: drizzle_orm_pg_core.PgColumn<{ + name: "published_at"; + tableName: "inboxes_entries"; + dataType: "date"; + columnType: "PgTimestamp"; + data: Date; + driverParam: string; + notNull: true; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: undefined; + baseColumn: never; + generated: undefined; + }, {}, {}>; + media: drizzle_orm_pg_core.PgColumn<{ + name: "media"; + tableName: "inboxes_entries"; + dataType: "json"; + columnType: "PgJsonb"; + data: MediaModel[]; + driverParam: unknown; + notNull: false; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: undefined; + baseColumn: never; + generated: undefined; + }, {}, {}>; + categories: drizzle_orm_pg_core.PgColumn<{ + name: "categories"; + tableName: "inboxes_entries"; + dataType: "array"; + columnType: "PgArray"; + data: string[]; + driverParam: string | string[]; + notNull: false; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: [string, ...string[]]; + baseColumn: drizzle_orm.Column<{ + name: "categories"; + tableName: "inboxes_entries"; + dataType: "string"; + columnType: "PgText"; + data: string; + driverParam: string; + notNull: false; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: [string, ...string[]]; + baseColumn: never; + generated: undefined; + }, object, object>; + generated: undefined; + }, {}, {}>; + attachments: drizzle_orm_pg_core.PgColumn<{ + name: "attachments"; + tableName: "inboxes_entries"; + dataType: "json"; + columnType: "PgJsonb"; + data: AttachmentsModel[]; + driverParam: unknown; + notNull: false; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: undefined; + baseColumn: never; + generated: undefined; + }, {}, {}>; + extra: drizzle_orm_pg_core.PgColumn<{ + name: "extra"; + tableName: "inboxes_entries"; + dataType: "json"; + columnType: "PgJsonb"; + data: ExtraModel; + driverParam: unknown; + notNull: false; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: undefined; + baseColumn: never; + generated: undefined; + }, {}, {}>; + inboxHandle: drizzle_orm_pg_core.PgColumn<{ + name: "inbox_handle"; + tableName: "inboxes_entries"; + dataType: "string"; + columnType: "PgText"; + data: string; + driverParam: string; + notNull: true; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: [string, ...string[]]; + baseColumn: never; + generated: undefined; + }, {}, {}>; + }; + dialect: "pg"; +}>; +declare const inboxesEntriesOpenAPISchema: z.ZodObject; + url: z.ZodNullable; + content: z.ZodNullable; + description: z.ZodNullable; + guid: z.ZodString; + author: z.ZodNullable; + authorUrl: z.ZodNullable; + authorAvatar: z.ZodNullable; + insertedAt: z.ZodString; + publishedAt: z.ZodString; + media: z.ZodNullable>; + categories: z.ZodNullable>; + attachments: z.ZodNullable>; + extra: z.ZodNullable>; + inboxHandle: z.ZodString; +}, "media" | "attachments" | "extra">, { + attachments: z.ZodNullable; + mime_type: z.ZodOptional; + size_in_bytes: z.ZodOptional; + title: z.ZodOptional; + }, "strip", z.ZodTypeAny, { + url: string; + title?: string | undefined; + duration_in_seconds?: number | undefined; + mime_type?: string | undefined; + size_in_bytes?: number | undefined; + }, { + url: string; + title?: string | undefined; + duration_in_seconds?: number | undefined; + mime_type?: string | undefined; + size_in_bytes?: number | undefined; + }>, "many">>>; + media: z.ZodNullable; + width: z.ZodOptional; + height: z.ZodOptional; + preview_image_url: z.ZodOptional; + blurhash: z.ZodOptional; + }, "strip", z.ZodTypeAny, { + type: "photo" | "video"; + url: string; + width?: number | undefined; + height?: number | undefined; + preview_image_url?: string | undefined; + blurhash?: string | undefined; + }, { + type: "photo" | "video"; + url: string; + width?: number | undefined; + height?: number | undefined; + preview_image_url?: string | undefined; + blurhash?: string | undefined; + }>, "many">>>; + extra: z.ZodNullable; + }, "strip", z.ZodTypeAny, { + type: string; + url: string; + content_html?: string | undefined; + }, { + type: string; + url: string; + content_html?: string | undefined; + }>, "many">>>; + }, "strip", z.ZodTypeAny, { + links?: { + type: string; + url: string; + content_html?: string | undefined; + }[] | null | undefined; + }, { + links?: { + type: string; + url: string; + content_html?: string | undefined; + }[] | null | undefined; + }>>>; +}>, "strip", z.ZodTypeAny, { + description: string | null; + title: string | null; + content: string | null; + id: string; + author: string | null; + url: string | null; + guid: string; + categories: string[] | null; + authorUrl: string | null; + authorAvatar: string | null; + insertedAt: string; + publishedAt: string; + inboxHandle: string; + media?: { + type: "photo" | "video"; + url: string; + width?: number | undefined; + height?: number | undefined; + preview_image_url?: string | undefined; + blurhash?: string | undefined; + }[] | null | undefined; + attachments?: { + url: string; + title?: string | undefined; + duration_in_seconds?: number | undefined; + mime_type?: string | undefined; + size_in_bytes?: number | undefined; + }[] | null | undefined; + extra?: { + links?: { + type: string; + url: string; + content_html?: string | undefined; + }[] | null | undefined; + } | null | undefined; +}, { + description: string | null; + title: string | null; + content: string | null; + id: string; + author: string | null; + url: string | null; + guid: string; + categories: string[] | null; + authorUrl: string | null; + authorAvatar: string | null; + insertedAt: string; + publishedAt: string; + inboxHandle: string; + media?: { + type: "photo" | "video"; + url: string; + width?: number | undefined; + height?: number | undefined; + preview_image_url?: string | undefined; + blurhash?: string | undefined; + }[] | null | undefined; + attachments?: { + url: string; + title?: string | undefined; + duration_in_seconds?: number | undefined; + mime_type?: string | undefined; + size_in_bytes?: number | undefined; + }[] | null | undefined; + extra?: { + links?: { + type: string; + url: string; + content_html?: string | undefined; + }[] | null | undefined; + } | null | undefined; +}>; +declare const inboxesEntriesInsertOpenAPISchema: z.ZodObject>; + title: z.ZodOptional>; + content: z.ZodOptional>; + id: z.ZodOptional; + author: z.ZodOptional>; + url: z.ZodOptional>; + guid: z.ZodString; + media: z.ZodOptional>>; + categories: z.ZodOptional>>; + attachments: z.ZodOptional>>; + extra: z.ZodOptional>>; + authorUrl: z.ZodOptional>; + authorAvatar: z.ZodOptional>; + insertedAt: z.ZodString; + publishedAt: z.ZodString; + inboxHandle: z.ZodString; +}, "id" | "media" | "attachments" | "extra" | "insertedAt" | "publishedAt" | "inboxHandle">, { + attachments: z.ZodNullable; + mime_type: z.ZodOptional; + size_in_bytes: z.ZodOptional; + title: z.ZodOptional; + }, "strip", z.ZodTypeAny, { + url: string; + title?: string | undefined; + duration_in_seconds?: number | undefined; + mime_type?: string | undefined; + size_in_bytes?: number | undefined; + }, { + url: string; + title?: string | undefined; + duration_in_seconds?: number | undefined; + mime_type?: string | undefined; + size_in_bytes?: number | undefined; + }>, "many">>>; + media: z.ZodNullable; + width: z.ZodOptional; + height: z.ZodOptional; + preview_image_url: z.ZodOptional; + blurhash: z.ZodOptional; + }, "strip", z.ZodTypeAny, { + type: "photo" | "video"; + url: string; + width?: number | undefined; + height?: number | undefined; + preview_image_url?: string | undefined; + blurhash?: string | undefined; + }, { + type: "photo" | "video"; + url: string; + width?: number | undefined; + height?: number | undefined; + preview_image_url?: string | undefined; + blurhash?: string | undefined; + }>, "many">>>; + extra: z.ZodNullable; + }, "strip", z.ZodTypeAny, { + type: string; + url: string; + content_html?: string | undefined; + }, { + type: string; + url: string; + content_html?: string | undefined; + }>, "many">>>; + }, "strip", z.ZodTypeAny, { + links?: { + type: string; + url: string; + content_html?: string | undefined; + }[] | null | undefined; + }, { + links?: { + type: string; + url: string; + content_html?: string | undefined; + }[] | null | undefined; + }>>>; + publishedAt: z.ZodString; +}>, "strip", z.ZodTypeAny, { + guid: string; + publishedAt: string; + description?: string | null | undefined; + title?: string | null | undefined; + content?: string | null | undefined; + author?: string | null | undefined; + url?: string | null | undefined; + media?: { + type: "photo" | "video"; + url: string; + width?: number | undefined; + height?: number | undefined; + preview_image_url?: string | undefined; + blurhash?: string | undefined; + }[] | null | undefined; + categories?: string[] | null | undefined; + attachments?: { + url: string; + title?: string | undefined; + duration_in_seconds?: number | undefined; + mime_type?: string | undefined; + size_in_bytes?: number | undefined; + }[] | null | undefined; + extra?: { + links?: { + type: string; + url: string; + content_html?: string | undefined; + }[] | null | undefined; + } | null | undefined; + authorUrl?: string | null | undefined; + authorAvatar?: string | null | undefined; +}, { + guid: string; + publishedAt: string; + description?: string | null | undefined; + title?: string | null | undefined; + content?: string | null | undefined; + author?: string | null | undefined; + url?: string | null | undefined; + media?: { + type: "photo" | "video"; + url: string; + width?: number | undefined; + height?: number | undefined; + preview_image_url?: string | undefined; + blurhash?: string | undefined; + }[] | null | undefined; + categories?: string[] | null | undefined; + attachments?: { + url: string; + title?: string | undefined; + duration_in_seconds?: number | undefined; + mime_type?: string | undefined; + size_in_bytes?: number | undefined; + }[] | null | undefined; + extra?: { + links?: { + type: string; + url: string; + content_html?: string | undefined; + }[] | null | undefined; + } | null | undefined; + authorUrl?: string | null | undefined; + authorAvatar?: string | null | undefined; +}>; +declare const inboxesEntriesRelations: drizzle_orm.Relations<"inboxes_entries", { + inboxes: drizzle_orm.One<"inboxes", true>; +}>; +type inboxesEntriesModel = InferInsertModel & { + attachments?: AttachmentsModel[] | null; + media?: MediaModel[] | null; +}; + +declare const inboxes: drizzle_orm_pg_core.PgTableWithColumns<{ + name: "inboxes"; + schema: undefined; + columns: { + userId: drizzle_orm_pg_core.PgColumn<{ + name: "user_id"; + tableName: "inboxes"; + dataType: "string"; + columnType: "PgText"; + data: string; + driverParam: string; + notNull: true; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: [string, ...string[]]; + baseColumn: never; + generated: undefined; + }, {}, {}>; + handle: drizzle_orm_pg_core.PgColumn<{ + name: "handle"; + tableName: "inboxes"; + dataType: "string"; + columnType: "PgText"; + data: string; + driverParam: string; + notNull: true; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: [string, ...string[]]; + baseColumn: never; + generated: undefined; + }, {}, {}>; + secret: drizzle_orm_pg_core.PgColumn<{ + name: "secret"; + tableName: "inboxes"; + dataType: "string"; + columnType: "PgText"; + data: string; + driverParam: string; + notNull: true; + hasDefault: true; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: true; + enumValues: [string, ...string[]]; + baseColumn: never; + generated: undefined; + }, {}, {}>; + title: drizzle_orm_pg_core.PgColumn<{ + name: "title"; + tableName: "inboxes"; + dataType: "string"; + columnType: "PgText"; + data: string; + driverParam: string; + notNull: false; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: [string, ...string[]]; + baseColumn: never; + generated: undefined; + }, {}, {}>; + }; + dialect: "pg"; +}>; +declare const inboxesOpenAPISchema: z.ZodObject<{ + userId: z.ZodString; + handle: z.ZodString; + secret: z.ZodString; + title: z.ZodNullable; +}, z.UnknownKeysParam, z.ZodTypeAny, { + title: string | null; + handle: string; + userId: string; + secret: string; +}, { + title: string | null; + handle: string; + userId: string; + secret: string; +}>; +declare const inboxesRelations: drizzle_orm.Relations<"inboxes", { + users: drizzle_orm.One<"user", true>; + entries: drizzle_orm.Many<"inboxes_entries">; +}>; +declare const inboxHandleSchema: z.ZodString; + declare const invitations: drizzle_orm_pg_core.PgTableWithColumns<{ name: "invitations"; schema: undefined; @@ -2826,6 +3715,7 @@ declare const usersRelations: drizzle_orm.Relations<"user", { actions: drizzle_orm.One<"actions", true>; wallets: drizzle_orm.One<"wallets", true>; feeds: drizzle_orm.Many<"feeds">; + inboxes: drizzle_orm.One<"inboxes", true>; }>; declare const wallets: drizzle_orm_pg_core.PgTableWithColumns<{ @@ -3224,6 +4114,146 @@ declare const feedPowerTokensRelations: drizzle_orm.Relations<"feedPowerTokens", }>; declare const _routes: hono_hono_base.HonoBase; type AppType = typeof _routes; -export { type ActionsModel, type AppType, type AttachmentsModel, type EntriesModel, type EntryReadHistoriesModel, type ExtraModel, type FeedModel, type MediaModel, type SettingsModel, accounts, achievements, achievementsOpenAPISchema, actions, actionsItemOpenAPISchema, actionsOpenAPISchema, actionsRelations, collections, collectionsOpenAPISchema, collectionsRelations, entries, entriesOpenAPISchema, entriesRelations, entryReadHistories, entryReadHistoriesOpenAPISchema, entryReadHistoriesRelations, feedPowerTokens, feedPowerTokensOpenAPISchema, feedPowerTokensRelations, feeds, feedsOpenAPISchema, feedsRelations, invitations, invitationsOpenAPISchema, invitationsRelations, languageSchema, lists, listsOpenAPISchema, listsRelations, listsSubscriptions, listsSubscriptionsOpenAPISchema, listsSubscriptionsRelations, listsTimeline, listsTimelineOpenAPISchema, listsTimelineRelations, sessions, settings, subscriptions, subscriptionsOpenAPISchema, subscriptionsRelations, timeline, timelineOpenAPISchema, timelineRelations, transactionType, transactions, transactionsOpenAPISchema, transactionsRelations, users, usersOpenApiSchema, usersRelations, verificationTokens, wallets, walletsOpenAPISchema, walletsRelations }; +export { type ActionsModel, type AppType, type AttachmentsModel, CommonEntryFields, type EntriesModel, type EntryReadHistoriesModel, type ExtraModel, type FeedModel, type MediaModel, type SettingsModel, accounts, achievements, achievementsOpenAPISchema, actions, actionsItemOpenAPISchema, actionsOpenAPISchema, actionsRelations, attachmentsZodSchema, collections, collectionsOpenAPISchema, collectionsRelations, entries, entriesOpenAPISchema, entriesRelations, entryReadHistories, entryReadHistoriesOpenAPISchema, entryReadHistoriesRelations, extraZodSchema, feedPowerTokens, feedPowerTokensOpenAPISchema, feedPowerTokensRelations, feeds, feedsOpenAPISchema, feedsRelations, inboxHandleSchema, inboxes, inboxesEntries, inboxesEntriesInsertOpenAPISchema, type inboxesEntriesModel, inboxesEntriesOpenAPISchema, inboxesEntriesRelations, inboxesOpenAPISchema, inboxesRelations, invitations, invitationsOpenAPISchema, invitationsRelations, languageSchema, lists, listsOpenAPISchema, listsRelations, listsSubscriptions, listsSubscriptionsOpenAPISchema, listsSubscriptionsRelations, listsTimeline, listsTimelineOpenAPISchema, listsTimelineRelations, mediaZodSchema, sessions, settings, subscriptions, subscriptionsOpenAPISchema, subscriptionsRelations, timeline, timelineOpenAPISchema, timelineRelations, transactionType, transactions, transactionsOpenAPISchema, transactionsRelations, users, usersOpenApiSchema, usersRelations, verificationTokens, wallets, walletsOpenAPISchema, walletsRelations }; From 66cca8ad7a8541cc9aa65884a822f10c2dd19be6 Mon Sep 17 00:00:00 2001 From: Innei Date: Thu, 3 Oct 2024 23:10:53 +0800 Subject: [PATCH 66/88] fix: populated image src in markdown Signed-off-by: Innei --- .../ui/markdown/renderers/InlineImage.tsx | 28 +++++++++++++++++++ apps/renderer/src/lib/parse-html.ts | 18 ++++-------- 2 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 apps/renderer/src/components/ui/markdown/renderers/InlineImage.tsx diff --git a/apps/renderer/src/components/ui/markdown/renderers/InlineImage.tsx b/apps/renderer/src/components/ui/markdown/renderers/InlineImage.tsx new file mode 100644 index 000000000..a2b77fc81 --- /dev/null +++ b/apps/renderer/src/components/ui/markdown/renderers/InlineImage.tsx @@ -0,0 +1,28 @@ +import { cn } from "~/lib/utils" +import { useEntryContentContext } from "~/modules/entry-content/hooks" + +import { Media } from "../../media" +import { usePopulatedFullUrl } from "../utils" + +export const MarkdownInlineImage = ( + props: React.ImgHTMLAttributes & { + proxy?: { + width: number + height: number + } + }, +) => { + const { feedId } = useEntryContentContext() + const populatedUrl = usePopulatedFullUrl(feedId, props.src) + return ( + + ) +} diff --git a/apps/renderer/src/lib/parse-html.ts b/apps/renderer/src/lib/parse-html.ts index bc7a81175..d9003aacf 100644 --- a/apps/renderer/src/lib/parse-html.ts +++ b/apps/renderer/src/lib/parse-html.ts @@ -21,6 +21,7 @@ import { ShikiHighLighter } from "~/components/ui/code-highlighter" import { MarkdownBlockImage, MarkdownLink, MarkdownP } from "~/components/ui/markdown/renderers" import { BlockError } from "~/components/ui/markdown/renderers/BlockErrorBoundary" import { createHeadingRenderer } from "~/components/ui/markdown/renderers/Heading" +import { MarkdownInlineImage } from "~/components/ui/markdown/renderers/InlineImage" import { Media } from "~/components/ui/media" function markInlineImage(node?: Element) { @@ -208,19 +209,10 @@ const Img: Components["img"] = ({ node, ...props }) => { proxy: { height: 0, width: 700 }, } - if (node?.properties.inline) { - return createElement(Media, { - type: "photo", - ...nextProps, - - mediaContainerClassName: tw`max-w-full inline rounded-md`, - popper: true, - className: tw`inline`, - showFallback: true, - }) - } - - return createElement(MarkdownBlockImage, nextProps) + return createElement( + node?.properties.inline ? MarkdownInlineImage : MarkdownBlockImage, + nextProps, + ) } function extractCodeFromHtml(htmlString: string) { From 020ea017eb9ebd4cb2e0033aa39d7d1acd5064b6 Mon Sep 17 00:00:00 2001 From: Innei Date: Thu, 3 Oct 2024 23:16:08 +0800 Subject: [PATCH 67/88] chore: fix typo Signed-off-by: Innei --- apps/renderer/src/store/inbox/store.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/renderer/src/store/inbox/store.ts b/apps/renderer/src/store/inbox/store.ts index f0a8b34ea..6068f256e 100644 --- a/apps/renderer/src/store/inbox/store.ts +++ b/apps/renderer/src/store/inbox/store.ts @@ -13,16 +13,16 @@ export const useInboxStore = createZustandStore("inbox")(() => ({ const set = createImmerSetter(useInboxStore) class InboxActionStatic { - upsertMany(inboxs: InboxModel[]) { - if (inboxs.length === 0) return + upsertMany(inboxes: InboxModel[]) { + if (inboxes.length === 0) return set((state) => { - for (const inbox of inboxs) { + for (const inbox of inboxes) { state.inboxes[inbox.id] = inbox } return state }) - runTransactionInScope(() => InboxService.upsertMany(inboxs)) + runTransactionInScope(() => InboxService.upsertMany(inboxes)) } async fetchInboxById(id: string) { From a66a415ad32bc64c11fe3c2dacd9046858584fcc Mon Sep 17 00:00:00 2001 From: Innei Date: Thu, 3 Oct 2024 23:30:36 +0800 Subject: [PATCH 68/88] refactor: hydrate service interface Signed-off-by: Innei --- .vscode/settings.json | 2 +- apps/renderer/src/initialize/hydrate.ts | 94 +++------------------- apps/renderer/src/services/cleaner.ts | 4 + apps/renderer/src/services/entry.ts | 49 ++++++++++- apps/renderer/src/services/feed-unread.ts | 11 ++- apps/renderer/src/services/feed.ts | 9 ++- apps/renderer/src/services/inbox.ts | 9 ++- apps/renderer/src/services/interface.ts | 3 + apps/renderer/src/services/list.ts | 9 ++- apps/renderer/src/services/subscription.ts | 10 ++- 10 files changed, 112 insertions(+), 88 deletions(-) create mode 100644 apps/renderer/src/services/interface.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index b9bc3075b..e6618b051 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -55,7 +55,7 @@ "severity": "off" } ], - "cSpell.words": ["rsshub", "Русский"], + "cSpell.words": ["Hydable", "rsshub", "Русский"], "editor.foldingImportsByDefault": true, "commentTranslate.hover.enabled": false, "typescript.tsdk": "node_modules/typescript/lib", diff --git a/apps/renderer/src/initialize/hydrate.ts b/apps/renderer/src/initialize/hydrate.ts index 374c8f7ef..a58dda80f 100644 --- a/apps/renderer/src/initialize/hydrate.ts +++ b/apps/renderer/src/initialize/hydrate.ts @@ -3,22 +3,10 @@ import { initializeDefaultIntegrationSettings } from "~/atoms/settings/integrati import { initializeDefaultUISettings } from "~/atoms/settings/ui" import { appLog } from "~/lib/log" import { sleep } from "~/lib/utils" -import { - EntryRelatedKey, - EntryRelatedService, - EntryService, - FeedService, - FeedUnreadService, - SubscriptionService, -} from "~/services" +import { EntryService, FeedService, FeedUnreadService, SubscriptionService } from "~/services" +import { InboxService } from "~/services/inbox" +import type { Hydable } from "~/services/interface" import { ListService } from "~/services/list" -import type { FlatEntryModel } from "~/store/entry" -import { listActions } from "~/store/list" - -import { entryActions, useEntryStore } from "../store/entry/store" -import { feedActions, useFeedStore } from "../store/feed" -import { subscriptionActions } from "../store/subscription" -import { feedUnreadActions } from "../store/unread" export const setHydrated = (v: boolean) => { window.__dbIsReady = v @@ -27,13 +15,16 @@ export const setHydrated = (v: boolean) => { export const hydrateDatabaseToStore = async () => { async function hydrate() { const now = Date.now() - await Promise.all([ - hydrateFeed(), - hydrateSubscription(), - hydrateFeedUnread(), - hydrateEntry(), - hydrateList(), - ]) + + const hydrates: Hydable[] = [ + FeedService, + SubscriptionService, + FeedUnreadService, + EntryService, + ListService, + InboxService, + ] + await Promise.all(hydrates.map((h) => h.hydrate())) window.__dbIsReady = true const costTime = Date.now() - now @@ -48,65 +39,6 @@ export const hydrateDatabaseToStore = async () => { }) } -async function hydrateFeed() { - const feeds = await FeedService.findAll() - feedActions.upsertMany(feeds) - return useFeedStore.getState().feeds -} - -async function hydrateFeedUnread() { - const unread = await FeedUnreadService.getAll() - - return feedUnreadActions.hydrate(unread) -} -async function hydrateEntry() { - const [entries, entryRelated, feedEntries, collections] = await Promise.all([ - EntryService.findAll(), - - EntryRelatedService.findAll(EntryRelatedKey.READ), - EntryRelatedService.findAll(EntryRelatedKey.FEED_ID), - EntryRelatedService.findAll(EntryRelatedKey.COLLECTION), - ]) - - const storeValue = [] as FlatEntryModel[] - for (const entry of entries) { - const entryRelatedFeedId = entry.feedId || feedEntries[entry.id] - if (!entryRelatedFeedId) { - logHydrateError(`Entry ${entry.id} has no related feed id`) - continue - } - - storeValue.push({ - entries: entry, - feedId: entryRelatedFeedId, - read: entryRelated[entry.id] || false, - collections: collections[entry.id] as { - createdAt: string - }, - }) - } - entryActions.hydrate(storeValue) - useEntryStore.setState({ - starIds: new Set(Object.keys(collections)), - }) -} - -async function hydrateSubscription() { - const subscriptions = await SubscriptionService.findAll() - - subscriptionActions.upsertMany(subscriptions) -} - -async function hydrateList() { - const lists = await ListService.findAll() - listActions.upsertMany(lists) -} - -const logHydrateError = (message: string) => { - // eslint-disable-next-line no-console - console.debug(`Hydrate error: ${message}, maybe local database data is dirty.`) -} - export const hydrateSettings = () => { initializeDefaultUISettings() initializeDefaultGeneralSettings() diff --git a/apps/renderer/src/services/cleaner.ts b/apps/renderer/src/services/cleaner.ts index 020c610ed..43b5aab75 100644 --- a/apps/renderer/src/services/cleaner.ts +++ b/apps/renderer/src/services/cleaner.ts @@ -80,5 +80,9 @@ class CleanerServiceStatic { cleanerModel.bulkDelete(data.map((d) => d.refId)), ]) } + + async cleanRefById(refIds: string[]) { + return cleanerModel.bulkDelete(refIds) + } } export const CleanerService = new CleanerServiceStatic() diff --git a/apps/renderer/src/services/entry.ts b/apps/renderer/src/services/entry.ts index 499628ec0..7bbc33fe7 100644 --- a/apps/renderer/src/services/entry.ts +++ b/apps/renderer/src/services/entry.ts @@ -1,14 +1,18 @@ import { browserDB } from "~/database" +import { appLog } from "~/lib/log" import type { EntryModel } from "~/models/types" +import type { FlatEntryModel } from "~/store/entry" +import { entryActions, useEntryStore } from "~/store/entry" import { BaseService } from "./base" import { CleanerService } from "./cleaner" import { EntryRelatedKey, EntryRelatedService } from "./entry-related" +import type { Hydable } from "./interface" type EntryCollection = { createdAt: string } -class EntryServiceStatic extends BaseService { +class EntryServiceStatic extends BaseService implements Hydable { constructor() { super(browserDB.entries) } @@ -77,6 +81,7 @@ class EntryServiceStatic extends BaseService { this.table.bulkDelete(entryIds), EntryRelatedService.deleteItems(EntryRelatedKey.READ, entryIds), EntryRelatedService.deleteItems(EntryRelatedKey.COLLECTION, entryIds), + CleanerService.cleanRefById(entryIds), ]) } @@ -88,6 +93,48 @@ class EntryServiceStatic extends BaseService { EntryRelatedService.deleteItems(EntryRelatedKey.COLLECTION, deleteEntryIds), ]) } + + async hydrate() { + const [entries, entryRelated, feedEntries, collections] = await Promise.all([ + EntryService.findAll(), + + EntryRelatedService.findAll(EntryRelatedKey.READ), + EntryRelatedService.findAll(EntryRelatedKey.FEED_ID), + EntryRelatedService.findAll(EntryRelatedKey.COLLECTION), + ]) + + const storeValue = [] as FlatEntryModel[] + const dirtyEntryIds = [] as string[] + for (const entry of entries) { + const entryRelatedFeedId = entry.feedId || feedEntries[entry.id] + if (!entryRelatedFeedId) { + appLog(`[Data hydrate warning]: Entry ${entry.id} has no related feed id`) + dirtyEntryIds.push(entry.id) + continue + } + + storeValue.push({ + entries: entry, + feedId: entryRelatedFeedId, + read: entryRelated[entry.id] || false, + collections: collections[entry.id] as { + createdAt: string + }, + }) + } + entryActions.hydrate(storeValue) + useEntryStore.setState({ + starIds: new Set(Object.keys(collections)), + }) + + if (dirtyEntryIds.length > 0) { + // Remove entries that have no related feed id + EntryService.deleteEntries(dirtyEntryIds) + appLog( + `[Data hydrate warning]: Entry ${dirtyEntryIds.join(", ")} has no related feed id, cleanup..`, + ) + } + } } export const EntryService = new EntryServiceStatic() diff --git a/apps/renderer/src/services/feed-unread.ts b/apps/renderer/src/services/feed-unread.ts index 74c791843..5df2e9963 100644 --- a/apps/renderer/src/services/feed-unread.ts +++ b/apps/renderer/src/services/feed-unread.ts @@ -1,7 +1,10 @@ import { browserDB } from "~/database" +import { feedUnreadActions } from "~/store/unread" + +import type { Hydable } from "./interface" const feedUnreadModel = browserDB.feedUnreads -class ServiceStatic { +class ServiceStatic implements Hydable { updateFeedUnread(list: [string, number][]) { return feedUnreadModel.bulkPut(list.map(([feedId, count]) => ({ id: feedId, count }))) } @@ -22,6 +25,12 @@ class ServiceStatic { async bulkDelete(ids: string[]) { return feedUnreadModel.bulkDelete(ids) } + + async hydrate() { + const unread = await FeedUnreadService.getAll() + + return feedUnreadActions.hydrate(unread) + } } export const FeedUnreadService = new ServiceStatic() diff --git a/apps/renderer/src/services/feed.ts b/apps/renderer/src/services/feed.ts index ee14c3a4a..c9ffafb8f 100644 --- a/apps/renderer/src/services/feed.ts +++ b/apps/renderer/src/services/feed.ts @@ -1,11 +1,13 @@ import { browserDB } from "~/database" import type { FeedModel, FeedOrListModel } from "~/models/types" +import { feedActions } from "~/store/feed" import { BaseService } from "./base" import { CleanerService } from "./cleaner" +import type { Hydable } from "./interface" type FeedModelWithId = FeedModel & { id: string } -class ServiceStatic extends BaseService { +class ServiceStatic extends BaseService implements Hydable { constructor() { super(browserDB.feeds) } @@ -27,6 +29,11 @@ class ServiceStatic extends BaseService { async bulkDelete(ids: string[]) { return this.table.bulkDelete(ids) } + + async hydrate() { + const feeds = await FeedService.findAll() + feedActions.upsertMany(feeds) + } } export const FeedService = new ServiceStatic() diff --git a/apps/renderer/src/services/inbox.ts b/apps/renderer/src/services/inbox.ts index bb5038fb2..fe69c2f56 100644 --- a/apps/renderer/src/services/inbox.ts +++ b/apps/renderer/src/services/inbox.ts @@ -1,10 +1,12 @@ import { browserDB } from "~/database" import type { InboxModel } from "~/models/types" +import { inboxActions } from "~/store/inbox" import { BaseService } from "./base" import { CleanerService } from "./cleaner" +import type { Hydable } from "./interface" -class ServiceStatic extends BaseService<{ id: string }> { +class ServiceStatic extends BaseService<{ id: string }> implements Hydable { constructor() { super(browserDB.inboxes) } @@ -28,6 +30,11 @@ class ServiceStatic extends BaseService<{ id: string }> { async bulkDelete(ids: string[]) { return this.table.bulkDelete(ids) } + + async hydrate() { + const data = await this.findAll() + inboxActions.upsertMany(data) + } } export const InboxService = new ServiceStatic() diff --git a/apps/renderer/src/services/interface.ts b/apps/renderer/src/services/interface.ts new file mode 100644 index 000000000..e57dd6d08 --- /dev/null +++ b/apps/renderer/src/services/interface.ts @@ -0,0 +1,3 @@ +export interface Hydable { + hydrate: () => Promise +} diff --git a/apps/renderer/src/services/list.ts b/apps/renderer/src/services/list.ts index 8a87a353b..c8022c333 100644 --- a/apps/renderer/src/services/list.ts +++ b/apps/renderer/src/services/list.ts @@ -2,11 +2,13 @@ import { omit } from "lodash-es" import { browserDB } from "~/database" import type { ListModel } from "~/models/types" +import { listActions } from "~/store/list" import { BaseService } from "./base" import { CleanerService } from "./cleaner" +import type { Hydable } from "./interface" -class ServiceStatic extends BaseService<{ id: string }> { +class ServiceStatic extends BaseService<{ id: string }> implements Hydable { constructor() { super(browserDB.lists) } @@ -32,6 +34,11 @@ class ServiceStatic extends BaseService<{ id: string }> { async bulkDelete(ids: string[]) { return this.table.bulkDelete(ids) } + + async hydrate() { + const lists = await ListService.findAll() + listActions.upsertMany(lists) + } } export const ListService = new ServiceStatic() diff --git a/apps/renderer/src/services/subscription.ts b/apps/renderer/src/services/subscription.ts index 87f9bc0ce..d5a0230b0 100644 --- a/apps/renderer/src/services/subscription.ts +++ b/apps/renderer/src/services/subscription.ts @@ -2,12 +2,14 @@ import { uniq } from "lodash-es" import { browserDB } from "~/database" import type { SubscriptionFlatModel } from "~/store/subscription" +import { subscriptionActions } from "~/store/subscription" import { BaseService } from "./base" +import type { Hydable } from "./interface" type SubscriptionModelWithId = SubscriptionFlatModel & { id: string } -class SubscriptionServiceStatic extends BaseService { +class SubscriptionServiceStatic extends BaseService implements Hydable { constructor() { super(browserDB.subscriptions) } @@ -68,6 +70,12 @@ class SubscriptionServiceStatic extends BaseService { .and((item) => feedIdList.includes(item.feedId)) .modify({ category }) } + + async hydrate() { + const subscriptions = await SubscriptionService.findAll() + + subscriptionActions.upsertMany(subscriptions) + } } export const SubscriptionService = new SubscriptionServiceStatic() From 2b496c4e49f223a9d00381983149e827bdb695fd Mon Sep 17 00:00:00 2001 From: DIYgod Date: Fri, 4 Oct 2024 00:52:23 +0800 Subject: [PATCH 69/88] fix: subscription inbox data --- .../renderer/src/modules/feed-column/list.tsx | 4 +- .../sort-by/SortByAlphabeticalList.tsx | 40 ++++--------------- .../src/modules/feed-column/sort-by/types.tsx | 1 + 3 files changed, 10 insertions(+), 35 deletions(-) diff --git a/apps/renderer/src/modules/feed-column/list.tsx b/apps/renderer/src/modules/feed-column/list.tsx index 32423c082..4649b9830 100644 --- a/apps/renderer/src/modules/feed-column/list.tsx +++ b/apps/renderer/src/modules/feed-column/list.tsx @@ -190,7 +190,7 @@ function FeedListImpl({ className, view }: { className?: string; view: number })
    {t("words.lists")}
    - + )} {hasInboxData && ( @@ -198,7 +198,7 @@ function FeedListImpl({ className, view }: { className?: string; view: number })
    {t("words.inbox")}
    - + )} {(hasListData || hasInboxData) && ( diff --git a/apps/renderer/src/modules/feed-column/sort-by/SortByAlphabeticalList.tsx b/apps/renderer/src/modules/feed-column/sort-by/SortByAlphabeticalList.tsx index 287604bc5..a9f0e352e 100644 --- a/apps/renderer/src/modules/feed-column/sort-by/SortByAlphabeticalList.tsx +++ b/apps/renderer/src/modules/feed-column/sort-by/SortByAlphabeticalList.tsx @@ -1,9 +1,7 @@ -import { Fragment, useMemo } from "react" +import { Fragment } from "react" import { sortByAlphabet } from "~/lib/utils" import { getPreferredTitle, useFeedStore } from "~/store/feed" -import { useInboxByView } from "~/store/inbox" -import { useListByView } from "~/store/list" import { getSubscriptionByFeedId } from "~/store/subscription" import { useFeedListSortSelector } from "../atom" @@ -64,45 +62,21 @@ export const SortByAlphabeticalFeedList = ({ ) } -export const SortByAlphabeticalListList = ({ view }: ListListProps) => { - const isDesc = useFeedListSortSelector((s) => s.order === "desc") - - const lists = useListByView(view) - - const sortedLists = useMemo(() => { - const res = lists.sort((a, b) => { - return sortByAlphabet(a.title ?? "", b.title ?? "") - }) - - return isDesc ? res.reverse() : res - }, [isDesc, lists]) - +export const SortByAlphabeticalListList = ({ view, data }: ListListProps) => { return (
    - {sortedLists.map((list) => ( - + {Object.keys(data).map((listId) => ( + ))}
    ) } -export const SortByAlphabeticalInboxList = ({ view }: ListListProps) => { - const isDesc = useFeedListSortSelector((s) => s.order === "desc") - - const inboxes = useInboxByView(view) - - const sortedInboxes = useMemo(() => { - const res = inboxes.sort((a, b) => { - return sortByAlphabet(a.title ?? "", b.title ?? "") - }) - - return isDesc ? res.reverse() : res - }, [isDesc, inboxes]) - +export const SortByAlphabeticalInboxList = ({ view, data }: ListListProps) => { return (
    - {sortedInboxes.map((inbox) => ( - + {Object.keys(data).map((inboxId) => ( + ))}
    ) diff --git a/apps/renderer/src/modules/feed-column/sort-by/types.tsx b/apps/renderer/src/modules/feed-column/sort-by/types.tsx index 030e5419e..68144fd49 100644 --- a/apps/renderer/src/modules/feed-column/sort-by/types.tsx +++ b/apps/renderer/src/modules/feed-column/sort-by/types.tsx @@ -9,4 +9,5 @@ export type SortBy = "count" | "alphabetical" export type ListListProps = { view: FeedViewType + data: Record } From 6da197c76bc4d08c80277fc8801a68bfbd413248 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Fri, 4 Oct 2024 01:39:56 +0800 Subject: [PATCH 70/88] feat: inbox list api --- .../src/modules/discover/inbox-list-form.tsx | 8 +++--- .../src/modules/entry-column/index.tsx | 7 ++--- apps/renderer/src/queries/inboxes.ts | 13 +++++++-- apps/renderer/src/store/inbox/store.ts | 7 +++++ packages/shared/src/hono.ts | 27 +++++++++++++++++++ 5 files changed, 53 insertions(+), 9 deletions(-) diff --git a/apps/renderer/src/modules/discover/inbox-list-form.tsx b/apps/renderer/src/modules/discover/inbox-list-form.tsx index 9a5f11562..d79612255 100644 --- a/apps/renderer/src/modules/discover/inbox-list-form.tsx +++ b/apps/renderer/src/modules/discover/inbox-list-form.tsx @@ -15,14 +15,14 @@ import { TableRow, } from "~/components/ui/table" import { apiClient } from "~/lib/api-fetch" -import { FeedViewType } from "~/lib/enum" -import { inboxActions, useInboxByView } from "~/store/inbox" +import { useInboxList } from "~/queries/inboxes" +import { inboxActions } from "~/store/inbox" import { InboxForm } from "./inbox-form" export function DiscoverInboxList() { const { t } = useTranslation() - const inboxes = useInboxByView(FeedViewType.Articles) + const inboxes = useInboxList() const { present } = useModalStack() @@ -50,7 +50,7 @@ export function DiscoverInboxList() { - {inboxes.map((inbox) => ( + {inboxes.data?.map((inbox) => ( {inbox.id} diff --git a/apps/renderer/src/modules/entry-column/index.tsx b/apps/renderer/src/modules/entry-column/index.tsx index ef73b887a..5e3f1eb66 100644 --- a/apps/renderer/src/modules/entry-column/index.tsx +++ b/apps/renderer/src/modules/entry-column/index.tsx @@ -178,9 +178,10 @@ function EntryColumnImpl() { } data-total-count={virtuosoOptions.totalCount} > - {virtuosoOptions.totalCount === 0 && !entries.isLoading && !entries.error && ( - - )} + {virtuosoOptions.totalCount === 0 && + !entries.isLoading && + !entries.error && + feed?.type === "feed" && } - defineQuery(["lists", id], async () => inboxActions.fetchInboxById(id), { - rootKey: ["lists"], + defineQuery(["inboxes", id], async () => inboxActions.fetchInboxById(id), { + rootKey: ["inboxes"], + }), + list: () => + defineQuery(["inboxes"], async () => inboxActions.fetchOwnedInboxes(), { + rootKey: ["inboxes"], }), } @@ -13,3 +17,8 @@ export const useInbox = ({ id }: { id?: string }) => useAuthQuery(inboxes.byId({ id: id! }), { enabled: !!id, }) + +export const useInboxList = () => + useAuthQuery(inboxes.list(), { + enabled: true, + }) diff --git a/apps/renderer/src/store/inbox/store.ts b/apps/renderer/src/store/inbox/store.ts index 6068f256e..791155ba2 100644 --- a/apps/renderer/src/store/inbox/store.ts +++ b/apps/renderer/src/store/inbox/store.ts @@ -47,6 +47,13 @@ class InboxActionStatic { delete state.inboxes[id] }) } + + async fetchOwnedInboxes() { + const res = await apiClient.inboxes.list.$get() + this.upsertMany(res.data) + + return res.data + } } export const inboxActions = new InboxActionStatic() diff --git a/packages/shared/src/hono.ts b/packages/shared/src/hono.ts index 2d28b4485..0dca651ae 100644 --- a/packages/shared/src/hono.ts +++ b/packages/shared/src/hono.ts @@ -4253,6 +4253,33 @@ declare const _routes: hono_hono_base.HonoBase Date: Fri, 4 Oct 2024 03:20:54 +0800 Subject: [PATCH 71/88] feat: inbox set read and unread --- .../src/hooks/biz/useEntryActions.tsx | 14 ++++++++-- .../src/modules/entry-column/hooks.ts | 2 +- .../src/modules/entry-column/index.tsx | 2 +- .../entry-column/layouts/EntryItemWrapper.tsx | 2 +- .../entry-column/layouts/EntryListHeader.tsx | 8 +++--- apps/renderer/src/store/entry/helper.ts | 9 +++++-- apps/renderer/src/store/entry/store.ts | 10 ++++--- apps/renderer/src/store/inbox/hooks.ts | 5 ---- packages/shared/src/hono.ts | 27 +++++++++++++++++++ 9 files changed, 59 insertions(+), 20 deletions(-) diff --git a/apps/renderer/src/hooks/biz/useEntryActions.tsx b/apps/renderer/src/hooks/biz/useEntryActions.tsx index 74a54fa4e..fe6346232 100644 --- a/apps/renderer/src/hooks/biz/useEntryActions.tsx +++ b/apps/renderer/src/hooks/biz/useEntryActions.tsx @@ -106,12 +106,22 @@ export const useUnCollect = (entry: Nullable) => { export const useRead = () => useMutation({ mutationFn: async (entry: Nullable) => - entry && entryActions.markRead(entry.feeds.id, entry.entries.id, true), + entry && + entryActions.markRead({ + feedId: entry.feeds.id, + entryId: entry.entries.id, + read: true, + }), }) export const useUnread = () => useMutation({ mutationFn: async (entry: Nullable) => - entry && entryActions.markRead(entry.feeds.id, entry.entries.id, false), + entry && + entryActions.markRead({ + feedId: entry.feeds.id, + entryId: entry.entries.id, + read: false, + }), }) export const useEntryActions = ({ diff --git a/apps/renderer/src/modules/entry-column/hooks.ts b/apps/renderer/src/modules/entry-column/hooks.ts index 333894a57..a7ce8c7ea 100644 --- a/apps/renderer/src/modules/entry-column/hooks.ts +++ b/apps/renderer/src/modules/entry-column/hooks.ts @@ -235,7 +235,7 @@ export function batchMarkRead(ids: string[]) { if (batchLikeIds.length > 0) { for (const [feedId, id] of batchLikeIds) { - entryActions.markRead(feedId, id, true) + entryActions.markRead({ feedId, entryId: id, read: true }) } } } diff --git a/apps/renderer/src/modules/entry-column/index.tsx b/apps/renderer/src/modules/entry-column/index.tsx index 5e3f1eb66..a18b787d5 100644 --- a/apps/renderer/src/modules/entry-column/index.tsx +++ b/apps/renderer/src/modules/entry-column/index.tsx @@ -76,7 +76,7 @@ function EntryColumnImpl() { const feedId = activeEntry?.feedId if (!feedId) return - entryActions.markRead(feedId, activeEntryId, true) + entryActions.markRead({ feedId, entryId: activeEntryId, read: true }) }, [activeEntry?.feedId, activeEntryId, isCollection, isPendingEntry]) const isInteracted = useRef(false) diff --git a/apps/renderer/src/modules/entry-column/layouts/EntryItemWrapper.tsx b/apps/renderer/src/modules/entry-column/layouts/EntryItemWrapper.tsx index 3c34b02cc..5bc7bc638 100644 --- a/apps/renderer/src/modules/entry-column/layouts/EntryItemWrapper.tsx +++ b/apps/renderer/src/modules/entry-column/layouts/EntryItemWrapper.tsx @@ -51,7 +51,7 @@ export const EntryItemWrapper: FC< if (!document.hasFocus()) return if (asRead) return - entryActions.markRead(entry.feedId, entry.entries.id, true) + entryActions.markRead({ feedId: entry.feedId, entryId: entry.entries.id, read: true }) }, 233, { diff --git a/apps/renderer/src/modules/entry-column/layouts/EntryListHeader.tsx b/apps/renderer/src/modules/entry-column/layouts/EntryListHeader.tsx index 73a6e77d4..b7b2fd1e8 100644 --- a/apps/renderer/src/modules/entry-column/layouts/EntryListHeader.tsx +++ b/apps/renderer/src/modules/entry-column/layouts/EntryListHeader.tsx @@ -35,7 +35,7 @@ export const EntryListHeader: FC<{ const unreadOnly = useGeneralSettingKey("unreadOnly") - const { feedId, entryId, view } = routerParams + const { feedId, entryId, view, listId } = routerParams const headerTitle = useFeedHeaderTitle() const os = getOS() @@ -58,13 +58,13 @@ export const EntryListHeader: FC<{
    ) - const { mutateAsync: refreshFeed, isPending } = useRefreshFeedMutation(routerParams.feedId) + const { mutateAsync: refreshFeed, isPending } = useRefreshFeedMutation(feedId) const user = useWhoami() const isOnline = useIsOnline() - const feed = useFeedById(routerParams.feedId) - const isList = feed?.type === "list" + const feed = useFeedById(feedId) + const isList = !!listId const titleStyleBasedView = ["pl-12", "pl-7", "pl-7", "pl-7", "px-5", "pl-12"] diff --git a/apps/renderer/src/store/entry/helper.ts b/apps/renderer/src/store/entry/helper.ts index 609f3ffc5..a211cfb62 100644 --- a/apps/renderer/src/store/entry/helper.ts +++ b/apps/renderer/src/store/entry/helper.ts @@ -33,8 +33,13 @@ export const getFilteredFeedIds = (feedIds: string[], filter?: EntryFilter) => { } const unread = create({ - fetcher: async (ids: [FeedId, EntryId][]) => { - await apiClient.reads.$post({ json: { entryIds: ids.map((i) => i[1]) } }) + fetcher: async (ids: ([FeedId, EntryId, boolean] | [FeedId, EntryId])[]) => { + await apiClient.reads.$post({ + json: { + entryIds: ids.map((i) => i[1]), + isInbox: ids[0][2], + }, + }) return [] }, diff --git a/apps/renderer/src/store/entry/store.ts b/apps/renderer/src/store/entry/store.ts index 06fb4f74a..10458477f 100644 --- a/apps/renderer/src/store/entry/store.ts +++ b/apps/renderer/src/store/entry/store.ts @@ -345,10 +345,11 @@ class EntryActions { })) } - async markRead(feedId: string, entryId: string, read: boolean) { - const currentIsRead = get().flatMapEntries[entryId]?.read + async markRead({ feedId, entryId, read }: { feedId: string; entryId: string; read: boolean }) { + const entry = get().flatMapEntries[entryId] + const isInbox = entry?.entries && "inboxHandle" in entry.entries - if (read && currentIsRead) { + if (read && entry?.read) { return } @@ -362,11 +363,12 @@ class EntryActions { // Send api request async () => { if (read) { - await internal_batchMarkRead([feedId, entryId]) + await internal_batchMarkRead([feedId, entryId, isInbox]) } else { await apiClient.reads.$delete({ json: { entryId, + isInbox, }, }) } diff --git a/apps/renderer/src/store/inbox/hooks.ts b/apps/renderer/src/store/inbox/hooks.ts index 8120801ee..1cfec8b99 100644 --- a/apps/renderer/src/store/inbox/hooks.ts +++ b/apps/renderer/src/store/inbox/hooks.ts @@ -1,11 +1,6 @@ -import type { FeedViewType } from "~/lib/enum" import type { InboxModel } from "~/models" import { useInboxStore } from "./store" export const useInboxById = (inboxId: Nullable): InboxModel | null => useInboxStore((state) => (inboxId ? state.inboxes[inboxId] : null)) - -export const useInboxByView = (view: FeedViewType) => { - return useInboxStore((state) => (view === 0 ? Object.values(state.inboxes) : [])) -} diff --git a/packages/shared/src/hono.ts b/packages/shared/src/hono.ts index 0dca651ae..5e90ca16a 100644 --- a/packages/shared/src/hono.ts +++ b/packages/shared/src/hono.ts @@ -2213,6 +2213,22 @@ declare const inboxesEntries: drizzle_orm_pg_core.PgTableWithColumns<{ baseColumn: never; generated: undefined; }, {}, {}>; + read: drizzle_orm_pg_core.PgColumn<{ + name: "read"; + tableName: "inboxes_entries"; + dataType: "boolean"; + columnType: "PgBoolean"; + data: boolean; + driverParam: boolean; + notNull: false; + hasDefault: false; + isPrimaryKey: false; + isAutoincrement: false; + hasRuntimeDefault: false; + enumValues: undefined; + baseColumn: never; + generated: undefined; + }, {}, {}>; }; dialect: "pg"; }>; @@ -2245,6 +2261,7 @@ declare const inboxesEntriesOpenAPISchema: z.ZodObject>; inboxHandle: z.ZodString; + read: z.ZodNullable; }, "media" | "attachments" | "extra">, { attachments: z.ZodNullable>; insertedAt: z.ZodString; publishedAt: z.ZodString; + read: z.ZodOptional>; inboxHandle: z.ZodString; }, "id" | "media" | "attachments" | "extra" | "insertedAt" | "publishedAt" | "inboxHandle">, { attachments: z.ZodNullable; declare const inboxesEntriesRelations: drizzle_orm.Relations<"inboxes_entries", { inboxes: drizzle_orm.One<"inboxes", true>; @@ -4219,6 +4241,7 @@ declare const _routes: hono_hono_base.HonoBase Date: Fri, 4 Oct 2024 03:21:17 +0800 Subject: [PATCH 72/88] fix: useFeedHeaderTitle --- apps/renderer/src/store/feed/hooks.ts | 39 ++++++++++++++++++--------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/apps/renderer/src/store/feed/hooks.ts b/apps/renderer/src/store/feed/hooks.ts index 03768359c..3320caa1c 100644 --- a/apps/renderer/src/store/feed/hooks.ts +++ b/apps/renderer/src/store/feed/hooks.ts @@ -1,5 +1,4 @@ import { useMutation } from "@tanstack/react-query" -import { useMemo } from "react" import { useTranslation } from "react-i18next" import { toast } from "sonner" import { useShallow } from "zustand/react/shallow" @@ -7,11 +6,11 @@ import { useShallow } from "zustand/react/shallow" import { FEED_COLLECTION_LIST, ROUTE_FEED_IN_FOLDER, ROUTE_FEED_PENDING, views } from "~/constants" import { useRouteParams } from "~/hooks/biz/useRouteParams" import { apiClient } from "~/lib/api-fetch" -import type { FeedOrListRespModel } from "~/models" +import type { FeedOrListRespModel, InboxModel, ListModel } from "~/models" -import { listActions } from "../list" -import { getSubscriptionByFeedId } from "../subscription" -import { useFeedStore } from "./store" +import { useInboxStore } from "../inbox" +import { listActions, useListStore } from "../list" +import { getPreferredTitle, useFeedStore } from "./store" import type { FeedQueryParams } from "./types" export const useFeedById = (feedId: Nullable): FeedOrListRespModel | null => @@ -36,16 +35,32 @@ export const useFeedByIdSelector = ( useShallow((state) => (feedId && state.feeds[feedId] ? selector(state.feeds[feedId]) : null)), ) +export const useListByIdSelector = ( + listId: Nullable, + selector: (list: ListModel) => T, +) => + useListStore( + useShallow((state) => (listId && state.lists[listId] ? selector(state.lists[listId]) : null)), + ) + +export const useInboxByIdSelector = ( + inboxId: Nullable, + selector: (inbox: InboxModel) => T, +) => + useInboxStore( + useShallow((state) => + inboxId && state.inboxes[inboxId] ? selector(state.inboxes[inboxId]) : null, + ), + ) + export const useFeedHeaderTitle = () => { const { t } = useTranslation() - const { feedId: currentFeedId, view } = useRouteParams() + const { feedId: currentFeedId, view, listId, inboxId } = useRouteParams() - const feedTitle = useFeedByIdSelector(currentFeedId, (feed) => feed.title) - const subscriptionTitle = useMemo( - () => (currentFeedId ? (getSubscriptionByFeedId(currentFeedId)?.title ?? "") : ""), - [currentFeedId], - ) + const listTitle = useListByIdSelector(listId, (list) => getPreferredTitle(list)) + const inboxTitle = useInboxByIdSelector(inboxId, (inbox) => getPreferredTitle(inbox)) + const feedTitle = useFeedByIdSelector(currentFeedId, (feed) => getPreferredTitle(feed)) switch (currentFeedId) { case ROUTE_FEED_PENDING: { @@ -58,7 +73,7 @@ export const useFeedHeaderTitle = () => { if (currentFeedId?.startsWith(ROUTE_FEED_IN_FOLDER)) { return currentFeedId.replace(ROUTE_FEED_IN_FOLDER, "") } - return subscriptionTitle || feedTitle + return feedTitle || listTitle || inboxTitle } } } From 61d9a48310d726205271d1d01026511fb4ccb276 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Fri, 4 Oct 2024 03:48:41 +0800 Subject: [PATCH 73/88] feat: inbox unread data updating --- .../src/modules/entry-column/hooks/useMarkAll.ts | 8 +++++++- apps/renderer/src/store/subscription/store.ts | 15 ++++++++++++--- packages/shared/src/hono.ts | 1 + 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/apps/renderer/src/modules/entry-column/hooks/useMarkAll.ts b/apps/renderer/src/modules/entry-column/hooks/useMarkAll.ts index 3aed36d21..7a0d5a48b 100644 --- a/apps/renderer/src/modules/entry-column/hooks/useMarkAll.ts +++ b/apps/renderer/src/modules/entry-column/hooks/useMarkAll.ts @@ -10,7 +10,7 @@ export interface MarkAllFilter { } export const useMarkAllByRoute = (filter?: MarkAllFilter) => { const routerParams = useRouteParams() - const { feedId, view } = routerParams + const { feedId, view, inboxId } = routerParams const folderIds = useFolderFeedsByFeedId({ feedId, view, @@ -21,6 +21,12 @@ export const useMarkAllByRoute = (filter?: MarkAllFilter) => { if (typeof routerParams.feedId === "number" || routerParams.isAllFeeds) { subscriptionActions.markReadByView(view, filter) + } else if (inboxId) { + subscriptionActions.markReadByFeedIds({ + inboxId, + view, + filter, + }) } else if (folderIds) { subscriptionActions.markReadByFeedIds({ feedIds: folderIds, diff --git a/apps/renderer/src/store/subscription/store.ts b/apps/renderer/src/store/subscription/store.ts index 9ba78a2c3..9ee4125e5 100644 --- a/apps/renderer/src/store/subscription/store.ts +++ b/apps/renderer/src/store/subscription/store.ts @@ -225,11 +225,13 @@ class SubscriptionActions { async markReadByFeedIds({ feedIds, + inboxId, view, filter, listId, }: { feedIds?: string[] + inboxId?: string view?: FeedViewType filter?: MarkReadFilter listId?: string @@ -244,15 +246,22 @@ class SubscriptionActions { ? { listId, } - : { - feedIdList: stableFeedIds, - }), + : inboxId + ? { + inboxId, + } + : { + feedIdList: stableFeedIds, + }), ...filter, }, }), async () => { if (listId) { feedUnreadActions.updateByFeedId(listId, 0) + } else if (inboxId) { + feedUnreadActions.updateByFeedId(inboxId, 0) + entryActions.patchManyByFeedId(inboxId, { read: true }, filter) } else { for (const feedId of stableFeedIds) { // We can not process this logic in local, so skip it. and then we will fetch the unread count from server. diff --git a/packages/shared/src/hono.ts b/packages/shared/src/hono.ts index 5e90ca16a..2fc0fea85 100644 --- a/packages/shared/src/hono.ts +++ b/packages/shared/src/hono.ts @@ -5086,6 +5086,7 @@ declare const _routes: hono_hono_base.HonoBase Date: Fri, 4 Oct 2024 04:06:34 +0800 Subject: [PATCH 74/88] fix: fetch inbox entry --- .../renderer/src/modules/entry-content/index.tsx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/apps/renderer/src/modules/entry-content/index.tsx b/apps/renderer/src/modules/entry-content/index.tsx index 1fd0e05e7..95cbd312a 100644 --- a/apps/renderer/src/modules/entry-content/index.tsx +++ b/apps/renderer/src/modules/entry-content/index.tsx @@ -30,7 +30,7 @@ import { stopPropagation } from "~/lib/dom" import { FeedViewType } from "~/lib/enum" import { getNewIssueUrl } from "~/lib/issues" import { cn } from "~/lib/utils" -import type { ActiveEntryId, FeedModel } from "~/models" +import type { ActiveEntryId, FeedModel, InboxModel } from "~/models" import { useIsSoFWrappedElement, useWrappedElement, @@ -89,15 +89,19 @@ export const EntryContentRender: Component<{ }> = ({ entryId, noMedia, className, compact }) => { const { t } = useTranslation() - const { error, data, isPending } = useAuthQuery(Queries.entries.byId(entryId), { - staleTime: 300_000, - }) - const entry = useEntry(entryId) useTitle(entry?.entries.title) - const feed = useFeedById(entry?.feedId) as FeedModel + const feed = useFeedById(entry?.feedId) as FeedModel | InboxModel const readerRenderInlineStyle = useUISettingKey("readerRenderInlineStyle") + + const { error, data, isPending } = useAuthQuery( + feed?.type === "inbox" ? Queries.entries.byInboxId(entryId) : Queries.entries.byId(entryId), + { + staleTime: 300_000, + }, + ) + const summary = useAuthQuery( Queries.ai.summary({ entryId, From f0767e2ad93d29db9a82b283f1163e340167be68 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Fri, 4 Oct 2024 04:13:12 +0800 Subject: [PATCH 75/88] fix: types --- apps/renderer/src/modules/entry-content/index.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/renderer/src/modules/entry-content/index.tsx b/apps/renderer/src/modules/entry-content/index.tsx index 95cbd312a..3bf23c1e0 100644 --- a/apps/renderer/src/modules/entry-content/index.tsx +++ b/apps/renderer/src/modules/entry-content/index.tsx @@ -246,7 +246,9 @@ export const EntryContentRender: Component<{ {!content && (
    {isPending ? ( - + ) : error ? (
    From cdb8dd5cf31ec2d43b18a50cdd3259302620867e Mon Sep 17 00:00:00 2001 From: DIYgod Date: Fri, 4 Oct 2024 04:26:12 +0800 Subject: [PATCH 76/88] fix: env example --- .env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.example b/.env.example index f0cde1cd6..5e74c8b1b 100644 --- a/.env.example +++ b/.env.example @@ -4,4 +4,4 @@ VITE_IMGPROXY_URL=http://localhost:2873 VITE_SENTRY_DSN= VITE_BUILD_TYPE=production VITE_POSTHOG_KEY= -VITE_INBOXES_EMAIL=__devdev@follow.re +VITE_INBOXES_EMAIL=@follow.re From f96df54ba77ba0bd864c389c38c454f76971ef51 Mon Sep 17 00:00:00 2001 From: Innei Date: Fri, 4 Oct 2024 22:33:52 +0800 Subject: [PATCH 77/88] chore: tailwindcss config glob Signed-off-by: Innei --- tailwind.config.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tailwind.config.ts b/tailwind.config.ts index fe080ee12..80a25a4f6 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -11,7 +11,13 @@ import resolveConfig from "tailwindcss/resolveConfig" /** @type {import('tailwindcss').Config} */ export default resolveConfig({ darkMode: ["class", '[data-theme="dark"]'], - content: ["./apps/renderer/**/*.{ts,tsx}", "./apps/web/**/*.{ts,tsx}"], + content: [ + "./apps/renderer/src/**/*.{ts,tsx}", + "./apps/web/src/**/*.{ts,tsx}", + + "./apps/renderer/index.html", + "./apps/web/index.html", + ], prefix: "", theme: { container: { From 8c6753d4a66d1e7ad09efcbbca24c8cf51ed8222 Mon Sep 17 00:00:00 2001 From: Innei Date: Fri, 4 Oct 2024 22:42:02 +0800 Subject: [PATCH 78/88] feat: native menu add `hide` prop Signed-off-by: Innei --- .../renderer/src/hooks/biz/useFeedActions.tsx | 33 +++++++++---------- apps/renderer/src/lib/native-menu.ts | 11 +++++-- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/apps/renderer/src/hooks/biz/useFeedActions.tsx b/apps/renderer/src/hooks/biz/useFeedActions.tsx index d78c0293d..57efba69c 100644 --- a/apps/renderer/src/hooks/biz/useFeedActions.tsx +++ b/apps/renderer/src/hooks/biz/useFeedActions.tsx @@ -6,7 +6,7 @@ import { useTranslation } from "react-i18next" import { whoami } from "~/atoms/user" import { useModalStack } from "~/components/ui/modal" import type { FeedViewType } from "~/lib/enum" -import type { NativeMenuItem } from "~/lib/native-menu" +import type { NativeMenuItem, NullableNativeMenuItem } from "~/lib/native-menu" import { useFeedClaimModal } from "~/modules/claim" import { FeedForm } from "~/modules/discover/feed-form" import { InboxForm } from "~/modules/discover/inbox-form" @@ -47,8 +47,8 @@ export const useFeedActions = ({ const navigateEntry = useNavigateEntry() const isEntryList = type === "entryList" - const addMutation = useAddFeedToFeedList() - const removeMutation = useRemoveFeedFromFeedList() + const { mutateAsync: addFeedToListMutation } = useAddFeedToFeedList() + const { mutateAsync: removeFeedFromListMutation } = useRemoveFeedFromFeedList() const listByView = useListByView(view!) @@ -101,12 +101,12 @@ export const useFeedActions = ({ checked: isIncluded, click() { if (!isIncluded) { - addMutation.mutate({ + addFeedToListMutation({ feedId, listId: list.id, }) } else { - removeMutation.mutate({ + removeFeedFromListMutation({ feedId, listId: list.id, }) @@ -209,7 +209,8 @@ export const useFeedActions = ({ listByView, feedId, claimFeed, - addMutation, + addFeedToListMutation, + removeFeedFromListMutation, present, deleteSubscription, subscription, @@ -226,25 +227,21 @@ export const useListActions = ({ listId, view }: { listId: string; view: FeedVie const subscription = useSubscriptionByFeedId(listId) const { present } = useModalStack() - const deleteSubscription = useDeleteSubscription({}) + const { mutateAsync: deleteSubscription } = useDeleteSubscription({}) const navigateEntry = useNavigateEntry() const items = useMemo(() => { if (!list) return [] - const items: NativeMenuItem[] = [ - ...(list.ownerUserId === whoami()?.id - ? [ - { - type: "text" as const, - label: t("sidebar.feed_actions.list_owned_by_you"), - }, - ] - : []), + const items: NullableNativeMenuItem[] = [ + list.ownerUserId === whoami()?.id && { + type: "text" as const, + label: t("sidebar.feed_actions.list_owned_by_you"), + }, { type: "separator" as const, - disabled: false, + hide: list.ownerUserId !== whoami()?.id, }, { @@ -262,7 +259,7 @@ export const useListActions = ({ listId, view }: { listId: string; view: FeedVie type: "text" as const, label: t("sidebar.feed_actions.unfollow"), shortcut: "Meta+Backspace", - click: () => deleteSubscription.mutate(subscription), + click: () => deleteSubscription(subscription), }, { type: "text" as const, diff --git a/apps/renderer/src/lib/native-menu.ts b/apps/renderer/src/lib/native-menu.ts index bc1d26c18..21fc153ac 100644 --- a/apps/renderer/src/lib/native-menu.ts +++ b/apps/renderer/src/lib/native-menu.ts @@ -3,7 +3,7 @@ import { get } from "lodash-es" import { tipcClient } from "./client" import { getOS } from "./utils" -export type NativeMenuItem = +export type NativeMenuItem = ( | { type: "text" label: string @@ -17,6 +17,9 @@ export type NativeMenuItem = checked?: boolean } | { type: "separator"; disabled?: boolean } +) & { hide?: boolean } + +export type NullableNativeMenuItem = NativeMenuItem | null | undefined | false | "" function sortShortcutsString(shortcut: string) { const order = ["Shift", "Ctrl", "Alt", "Meta"] @@ -32,7 +35,7 @@ function sortShortcutsString(shortcut: string) { return [...sortedModifiers, ...otherKeys].join("+") } export const showNativeMenu = async ( - items: Array>, + items: Array, e?: MouseEvent | React.MouseEvent, ) => { const nextItems = (items.filter(Boolean) as NativeMenuItem[]).map((item) => { @@ -42,6 +45,10 @@ export const showNativeMenu = async ( shortcut: item.shortcut ? sortShortcutsString(item.shortcut) : undefined, } } + + if (item.hide) { + return [] + } return item }) as NativeMenuItem[] From e05d2bab75bc6d3462f0a581a46cfe50b1a902ce Mon Sep 17 00:00:00 2001 From: Innei Date: Sat, 5 Oct 2024 00:37:08 +0800 Subject: [PATCH 79/88] refactor: vite config and re-optimize chunks Signed-off-by: Innei --- apps/renderer/package.json | 3 - apps/renderer/src/pages/(external)/debug.tsx | 33 ---- configs/vite.render.config.ts | 142 +----------------- eslint.config.mjs | 6 +- .../{ => eslint}/eslint-check-i18n-json.js | 0 plugins/{ => eslint}/eslint-no-debug.js | 0 plugins/{ => eslint}/eslint-recursive-sort.js | 0 plugins/vite/custom-asset.ts | 39 +++++ plugins/vite/deps.ts | 33 ++++ plugins/vite/html-inject.ts | 29 ++++ plugins/vite/i18n-hmr.ts | 24 +++ plugins/vite/locales.ts | 64 ++++++++ plugins/vite/short-alias.ts | 57 +++++++ plugins/vite/tw-macro.ts | 54 +++++++ .../vite/utils}/i18n-completeness.ts | 6 +- pnpm-lock.yaml | 33 ---- vite.config.ts | 75 +++++---- 17 files changed, 358 insertions(+), 240 deletions(-) delete mode 100644 apps/renderer/src/pages/(external)/debug.tsx rename plugins/{ => eslint}/eslint-check-i18n-json.js (100%) rename plugins/{ => eslint}/eslint-no-debug.js (100%) rename plugins/{ => eslint}/eslint-recursive-sort.js (100%) create mode 100644 plugins/vite/custom-asset.ts create mode 100644 plugins/vite/deps.ts create mode 100644 plugins/vite/html-inject.ts create mode 100644 plugins/vite/i18n-hmr.ts create mode 100644 plugins/vite/locales.ts create mode 100644 plugins/vite/short-alias.ts create mode 100644 plugins/vite/tw-macro.ts rename {configs => plugins/vite/utils}/i18n-completeness.ts (87%) diff --git a/apps/renderer/package.json b/apps/renderer/package.json index 0854d9b8f..a96edd51c 100644 --- a/apps/renderer/package.json +++ b/apps/renderer/package.json @@ -20,7 +20,6 @@ "@lottiefiles/dotlottie-react": "0.9.0", "@microflash/remark-callout-directives": "4.3.1", "@mozilla/readability": "^0.5.0", - "@radix-ui/react-alert-dialog": "1.1.1", "@radix-ui/react-avatar": "1.1.0", "@radix-ui/react-checkbox": "1.1.1", "@radix-ui/react-context-menu": "2.2.1", @@ -39,7 +38,6 @@ "@radix-ui/react-toast": "1.2.1", "@radix-ui/react-tooltip": "1.1.2", "@sentry/react": "8.32.0", - "@sentry/vite-plugin": "2.22.4", "@shikijs/transformers": "1.20.0", "@t3-oss/env-core": "^0.11.1", "@tanstack/query-sync-storage-persister": "5.56.2", @@ -68,7 +66,6 @@ "immer": "10.1.1", "jotai": "2.10.0", "lethargy": "1.0.9", - "linkedom": "^0.18.5", "lodash-es": "4.17.21", "masonic": "4.0.1", "nanoid": "5.0.7", diff --git a/apps/renderer/src/pages/(external)/debug.tsx b/apps/renderer/src/pages/(external)/debug.tsx deleted file mode 100644 index 87853ec89..000000000 --- a/apps/renderer/src/pages/(external)/debug.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import Versions from "../../components/Versions" - -export function Component() { - if (!import.meta.env.DEV) return null - const ipcHandle = (): void => window.electron?.ipcRenderer.send("ping") - - return ( - <> -
    Powered by electron-vite
    -
    - - Build an Electron app with React -  and TypeScript -
    -

    - Please try pressing F12 to open the devTool -

    - - - - ) -} diff --git a/configs/vite.render.config.ts b/configs/vite.render.config.ts index 6cac5dba4..0e6567d18 100644 --- a/configs/vite.render.config.ts +++ b/configs/vite.render.config.ts @@ -1,96 +1,19 @@ -import fs, { readFileSync } from "node:fs" -import path, { resolve } from "node:path" +import { readFileSync } from "node:fs" +import { resolve } from "node:path" -import * as babel from "@babel/core" -import generate from "@babel/generator" -import { parse } from "@babel/parser" -import * as t from "@babel/types" import { sentryVitePlugin } from "@sentry/vite-plugin" import react from "@vitejs/plugin-react" -import { set } from "lodash-es" import { prerelease } from "semver" -import type { Plugin, UserConfig } from "vite" +import type { UserConfig } from "vite" +import { customI18nHmrPlugin } from "../plugins/vite/i18n-hmr" +import { localesPlugin } from "../plugins/vite/locales" +import { twMacro } from "../plugins/vite/tw-macro" +import i18nCompleteness from "../plugins/vite/utils/i18n-completeness" import { getGitHash } from "../scripts/lib" -import i18nCompleteness from "./i18n-completeness" const pkg = JSON.parse(readFileSync("package.json", "utf8")) const isCI = process.env.CI === "true" || process.env.CI === "1" -function localesPlugin(): Plugin { - return { - name: "locales-merge", - enforce: "post", - generateBundle(_options, bundle) { - const localesDir = path.resolve(__dirname, "../locales") - const namespaces = fs.readdirSync(localesDir).filter((dir) => dir !== ".DS_Store") - const languageResources = {} - - namespaces.forEach((namespace) => { - const namespacePath = path.join(localesDir, namespace) - const files = fs.readdirSync(namespacePath).filter((file) => file.endsWith(".json")) - - files.forEach((file) => { - const lang = path.basename(file, ".json") - const filePath = path.join(namespacePath, file) - const content = JSON.parse(fs.readFileSync(filePath, "utf-8")) - - if (!languageResources[lang]) { - languageResources[lang] = {} - } - - const obj = {} - - const keys = Object.keys(content as object) - for (const accessorKey of keys) { - set(obj, accessorKey, (content as any)[accessorKey]) - } - - languageResources[lang][namespace] = obj - }) - }) - - Object.entries(languageResources).forEach(([lang, resources]) => { - const fileName = `locales/${lang}.js` - - const content = `export default ${JSON.stringify(resources)};` - - this.emitFile({ - type: "asset", - fileName, - source: content, - }) - }) - - // Remove original JSON chunks - Object.keys(bundle).forEach((key) => { - if (key.startsWith("locales/") && key.endsWith(".json")) { - delete bundle[key] - } - }) - }, - } -} - -function customI18nHmrPlugin(): Plugin { - return { - name: "custom-i18n-hmr", - handleHotUpdate({ file, server }) { - if (file.endsWith(".json") && file.includes("locales")) { - server.ws.send({ - type: "custom", - event: "i18n-update", - data: { - file, - content: readFileSync(file, "utf-8"), - }, - }) - - // return empty array to prevent the default HMR - return [] - } - }, - } -} export const viteRenderBaseConfig = { resolve: { @@ -130,7 +53,7 @@ export const viteRenderBaseConfig = { }), localesPlugin(), - viteTwToRawString(), + twMacro(), customI18nHmrPlugin(), ], define: { @@ -147,52 +70,3 @@ export const viteRenderBaseConfig = { I18N_COMPLETENESS_MAP: JSON.stringify({ ...i18nCompleteness, en: 100 }), }, } satisfies UserConfig - -function viteTwToRawString(): Plugin { - return { - name: "vite-plugin-tw-to-raw-string", - - transform(code, id) { - // Only Process .tsx .ts .jsx .js files - if (!/\.[jt]sx?$/.test(id)) { - return null - } - // Parse the code using Babel's parser with TypeScript support - const ast = parse(code, { - sourceType: "module", - plugins: ["jsx", "typescript"], // Add typescript support - }) - - babel.traverse(ast, { - TaggedTemplateExpression(path) { - if (t.isIdentifier(path.node.tag, { name: "tw" })) { - const { quasi } = path.node - if (t.isTemplateLiteral(quasi)) { - // Create a new template literal by combining quasis and expressions - const quasis = quasi.quasis.map((q) => q.value.raw) - - // Replace the tagged template expression with the new template literal as a string - path.replaceWith( - t.templateLiteral( - quasis.map((q, i) => - t.templateElement({ raw: q, cooked: q }, i === quasis.length - 1), - ), - quasi.expressions, - ), - ) - } - } - }, - }) - - // Generate the transformed code from the modified AST - // @ts-expect-error - const output = generate.default(ast, {}, code) - - return { - code: output.code, - map: null, // Source map generation can be added if necessary - } - }, - } -} diff --git a/eslint.config.mjs b/eslint.config.mjs index 1fa926d36..b09b7d814 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,9 +1,9 @@ // @ts-check import { defineConfig } from "eslint-config-hyoban" -import checkI18nJson from "./plugins/eslint-check-i18n-json.js" -import noDebug from "./plugins/eslint-no-debug.js" -import recursiveSort from "./plugins/eslint-recursive-sort.js" +import checkI18nJson from "./plugins/eslint/eslint-check-i18n-json.js" +import noDebug from "./plugins/eslint/eslint-no-debug.js" +import recursiveSort from "./plugins/eslint/eslint-recursive-sort.js" export default defineConfig( { diff --git a/plugins/eslint-check-i18n-json.js b/plugins/eslint/eslint-check-i18n-json.js similarity index 100% rename from plugins/eslint-check-i18n-json.js rename to plugins/eslint/eslint-check-i18n-json.js diff --git a/plugins/eslint-no-debug.js b/plugins/eslint/eslint-no-debug.js similarity index 100% rename from plugins/eslint-no-debug.js rename to plugins/eslint/eslint-no-debug.js diff --git a/plugins/eslint-recursive-sort.js b/plugins/eslint/eslint-recursive-sort.js similarity index 100% rename from plugins/eslint-recursive-sort.js rename to plugins/eslint/eslint-recursive-sort.js diff --git a/plugins/vite/custom-asset.ts b/plugins/vite/custom-asset.ts new file mode 100644 index 000000000..5fa0ccd57 --- /dev/null +++ b/plugins/vite/custom-asset.ts @@ -0,0 +1,39 @@ +import path from "node:path" + +import fs from "fs-extra" +import type { Plugin } from "vite" + +export default function customAssetOutput(options: { + dependencies: Record +}): Plugin { + const { dependencies = {} } = options + + return { + name: "vite-plugin-custom-asset-output", + + async generateBundle(_, bundle) { + for (const [dependencyName, config] of Object.entries(dependencies)) { + const { sourceDir, targetDir } = config + + for (const fileName in bundle) { + const file = bundle[fileName] + + if ( + file.type === "asset" && + file.name && + file.name.startsWith(`${dependencyName}/${sourceDir}`) + ) { + const newFileName = file.name.replace(`${dependencyName}/${sourceDir}`, targetDir) + + file.fileName = newFileName + + await fs.ensureDir(path.dirname(newFileName)) + + bundle[newFileName] = file + delete bundle[fileName] + } + } + } + }, + } +} diff --git a/plugins/vite/deps.ts b/plugins/vite/deps.ts new file mode 100644 index 000000000..ebf8ee6fd --- /dev/null +++ b/plugins/vite/deps.ts @@ -0,0 +1,33 @@ +import type { Plugin, UserConfig } from "vite" + +export function createDependencyChunksPlugin(dependencies: string[] | string[][]): Plugin { + return { + name: "dependency-chunks", + config(config: UserConfig) { + config.build = config.build || {} + config.build.rollupOptions = config.build.rollupOptions || {} + config.build.rollupOptions.output = config.build.rollupOptions.output || {} + + const { output } = config.build.rollupOptions + const outputConfig = Array.isArray(output) ? output[0] : output + outputConfig.manualChunks = outputConfig.manualChunks || {} + outputConfig.assetFileNames = "assets/[name].[hash][extname]" + outputConfig.chunkFileNames = (chunkInfo) => { + return chunkInfo.name.startsWith("vendor/") ? "[name].[hash].js" : "assets/[name].[hash].js" + } + + const manualChunks = Array.isArray(output) ? output[0].manualChunks : output.manualChunks + + if (typeof manualChunks !== "object") return + + dependencies.forEach((dep, index) => { + if (Array.isArray(dep)) { + const chunkName = `vendor/a${index}` + manualChunks[chunkName] = dep + } else { + manualChunks[`vendor/${dep}`] = [dep] + } + }) + }, + } +} diff --git a/plugins/vite/html-inject.ts b/plugins/vite/html-inject.ts new file mode 100644 index 000000000..6a3f33872 --- /dev/null +++ b/plugins/vite/html-inject.ts @@ -0,0 +1,29 @@ +import type { PluginOption } from "vite" + +import type { env as EnvType } from "../../packages/shared/src/env" + +export function htmlInjectPlugin(env: typeof EnvType): PluginOption { + return { + name: "html-transform", + enforce: "post", + transformIndexHtml(html) { + return html.replace( + "", + ``, + ) + }, + } +} diff --git a/plugins/vite/i18n-hmr.ts b/plugins/vite/i18n-hmr.ts new file mode 100644 index 000000000..c9ce5e5a8 --- /dev/null +++ b/plugins/vite/i18n-hmr.ts @@ -0,0 +1,24 @@ +import { readFileSync } from "node:fs" + +import type { Plugin } from "vite" + +export function customI18nHmrPlugin(): Plugin { + return { + name: "custom-i18n-hmr", + handleHotUpdate({ file, server }) { + if (file.endsWith(".json") && file.includes("locales")) { + server.ws.send({ + type: "custom", + event: "i18n-update", + data: { + file, + content: readFileSync(file, "utf-8"), + }, + }) + + // return empty array to prevent the default HMR + return [] + } + }, + } +} diff --git a/plugins/vite/locales.ts b/plugins/vite/locales.ts new file mode 100644 index 000000000..45b7b2433 --- /dev/null +++ b/plugins/vite/locales.ts @@ -0,0 +1,64 @@ +import fs from "node:fs" +import path, { dirname } from "node:path" +import { fileURLToPath } from "node:url" + +import { set } from "lodash-es" +import type { Plugin } from "vite" + +export function localesPlugin(): Plugin { + return { + name: "locales-merge", + enforce: "post", + generateBundle(_options, bundle) { + const __dirname = dirname(fileURLToPath(import.meta.url)) + + const localesDir = path.resolve(__dirname, "../../locales") + + const namespaces = fs.readdirSync(localesDir).filter((dir) => dir !== ".DS_Store") + const languageResources = {} + + namespaces.forEach((namespace) => { + const namespacePath = path.join(localesDir, namespace) + const files = fs.readdirSync(namespacePath).filter((file) => file.endsWith(".json")) + + files.forEach((file) => { + const lang = path.basename(file, ".json") + const filePath = path.join(namespacePath, file) + const content = JSON.parse(fs.readFileSync(filePath, "utf-8")) + + if (!languageResources[lang]) { + languageResources[lang] = {} + } + + const obj = {} + + const keys = Object.keys(content as object) + for (const accessorKey of keys) { + set(obj, accessorKey, (content as any)[accessorKey]) + } + + languageResources[lang][namespace] = obj + }) + }) + + Object.entries(languageResources).forEach(([lang, resources]) => { + const fileName = `locales/${lang}.js` + + const content = `export default ${JSON.stringify(resources)};` + + this.emitFile({ + type: "asset", + fileName, + source: content, + }) + }) + + // Remove original JSON chunks + Object.keys(bundle).forEach((key) => { + if (key.startsWith("locales/") && key.endsWith(".json")) { + delete bundle[key] + } + }) + }, + } +} diff --git a/plugins/vite/short-alias.ts b/plugins/vite/short-alias.ts new file mode 100644 index 000000000..988219caf --- /dev/null +++ b/plugins/vite/short-alias.ts @@ -0,0 +1,57 @@ +import type { Plugin } from "vite" + +export function shortAliasPlugin(): Plugin { + const aliasMap = new Map() + let aliasCounter = 0 + + function generateShortAlias(): string { + const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + let result = "_" + let counter = aliasCounter++ + + do { + result += chars[counter % chars.length] + counter = Math.floor(counter / chars.length) + } while (counter > 0) + + return result + } + + return { + name: "short-alias", + renderChunk(code, chunk) { + if (chunk.fileName.startsWith("vendor/")) return code + const importRegex = /import\s*(\{[^}]+\})\s*from\s*(['"])([^'"]+)\2/g + + return code.replaceAll(importRegex, (match, imports, quote, source) => { + // Only process imports with curly braces + if (!imports.startsWith("{") || !imports.endsWith("}")) { + return match + } + + const newImports = imports + .slice(1, -1) // Remove the curly braces + .split(",") + .map((imp) => { + const [original, alias] = imp.trim().split(/\s+as\s+/) + if (alias) { + // If an alias already exists, keep it or shorten it if it's too long + if (alias.length > 3) { + let shortAlias = aliasMap.get(alias) + if (!shortAlias) { + shortAlias = generateShortAlias() + aliasMap.set(alias, shortAlias) + } + return `${original} as ${shortAlias}` + } + return imp.trim() + } + return imp.trim() + }) + .join(", ") + + return `import {${newImports}} from ${quote}${source}${quote}` + }) + }, + } +} diff --git a/plugins/vite/tw-macro.ts b/plugins/vite/tw-macro.ts new file mode 100644 index 000000000..5207e0981 --- /dev/null +++ b/plugins/vite/tw-macro.ts @@ -0,0 +1,54 @@ +import * as babel from "@babel/core" +import generate from "@babel/generator" +import { parse } from "@babel/parser" +import * as t from "@babel/types" +import type { Plugin } from "vite" + +export function twMacro(): Plugin { + return { + name: "vite-plugin-tw-to-raw-string", + + transform(code, id) { + // Only Process .tsx .ts .jsx .js files + if (!/\.[jt]sx?$/.test(id)) { + return null + } + // Parse the code using Babel's parser with TypeScript support + const ast = parse(code, { + sourceType: "module", + plugins: ["jsx", "typescript"], // Add typescript support + }) + + babel.traverse(ast, { + TaggedTemplateExpression(path) { + if (t.isIdentifier(path.node.tag, { name: "tw" })) { + const { quasi } = path.node + if (t.isTemplateLiteral(quasi)) { + // Create a new template literal by combining quasis and expressions + const quasis = quasi.quasis.map((q) => q.value.raw) + + // Replace the tagged template expression with the new template literal as a string + path.replaceWith( + t.templateLiteral( + quasis.map((q, i) => + t.templateElement({ raw: q, cooked: q }, i === quasis.length - 1), + ), + quasi.expressions, + ), + ) + } + } + }, + }) + + // Generate the transformed code from the modified AST + // @ts-expect-error + const output = generate.default(ast, {}, code) + + return { + code: output.code, + map: null, // Source map generation can be added if necessary + } + }, + } +} diff --git a/configs/i18n-completeness.ts b/plugins/vite/utils/i18n-completeness.ts similarity index 87% rename from configs/i18n-completeness.ts rename to plugins/vite/utils/i18n-completeness.ts index 3de328b31..479e7790a 100644 --- a/configs/i18n-completeness.ts +++ b/plugins/vite/utils/i18n-completeness.ts @@ -1,5 +1,6 @@ import fs from "node:fs" -import path from "node:path" +import path, { dirname } from "node:path" +import { fileURLToPath } from "node:url" type LanguageCompletion = Record @@ -55,6 +56,7 @@ function calculateCompleteness(localesDir: string): LanguageCompletion { return completeness } +const __dirname = dirname(fileURLToPath(import.meta.url)) -const i18n = calculateCompleteness(path.resolve(__dirname, "../locales")) +const i18n = calculateCompleteness(path.resolve(__dirname, "../../../locales")) export default i18n diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0bf024112..dd479186d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -351,9 +351,6 @@ importers: '@mozilla/readability': specifier: ^0.5.0 version: 0.5.0(patch_hash=fgkvsbckled47trggkhdkimzbm) - '@radix-ui/react-alert-dialog': - specifier: 1.1.1 - version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-avatar': specifier: 1.1.0 version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -408,9 +405,6 @@ importers: '@sentry/react': specifier: 8.32.0 version: 8.32.0(react@18.3.1) - '@sentry/vite-plugin': - specifier: 2.22.4 - version: 2.22.4(encoding@0.1.13) '@shikijs/transformers': specifier: 1.20.0 version: 1.20.0 @@ -2398,19 +2392,6 @@ packages: '@radix-ui/primitive@1.1.0': resolution: {integrity: sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==} - '@radix-ui/react-alert-dialog@1.1.1': - resolution: {integrity: sha512-wmCoJwj7byuVuiLKqDLlX7ClSUU0vd9sdCeM+2Ls+uf13+cpSJoMgwysHq1SGVVkJj5Xn0XWi1NoRCdkMpr6Mw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - '@radix-ui/react-arrow@1.1.0': resolution: {integrity: sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==} peerDependencies: @@ -11099,20 +11080,6 @@ snapshots: '@radix-ui/primitive@1.1.0': {} - '@radix-ui/react-alert-dialog@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) - '@radix-ui/react-dialog': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.10)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.10 - '@types/react-dom': 18.3.0 - '@radix-ui/react-arrow@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) diff --git a/vite.config.ts b/vite.config.ts index 559d8fe52..e4481e761 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -9,38 +9,14 @@ import { analyzer } from "vite-bundle-analyzer" import mkcert from "vite-plugin-mkcert" import { viteRenderBaseConfig } from "./configs/vite.render.config" -import type { env as EnvType } from "./src/env" +import type { env as EnvType } from "./packages/shared/src/env" +import { createDependencyChunksPlugin } from "./plugins/vite/deps" +import { htmlInjectPlugin } from "./plugins/vite/html-inject" const __dirname = fileURLToPath(new URL(".", import.meta.url)) const isCI = process.env.CI === "true" || process.env.CI === "1" const ROOT = "./apps/renderer" -function htmlPlugin(env: typeof EnvType): PluginOption { - return { - name: "html-transform", - enforce: "post", - transformIndexHtml(html) { - return html.replace( - "", - ``, - ) - }, - } -} - const devPrint = (): PluginOption => ({ name: "dev-print", configureServer(server: ViteDevServer) { @@ -78,10 +54,6 @@ export default ({ mode }) => { main: resolve(ROOT, "/index.html"), __debug_proxy: resolve(ROOT, "/__debug_proxy.html"), }, - output: { - // 10KB - experimentalMinChunkSize: 10_000, - }, }, }, server: { @@ -99,12 +71,51 @@ export default ({ mode }) => { modernTargets: ">0.3%, last 2 versions, Firefox ESR, not dead", modernPolyfills: ["es.array.find-last-index", "es.array.find-last"], }), - htmlPlugin(typedEnv), + htmlInjectPlugin(typedEnv), mkcert(), devPrint(), + createDependencyChunksPlugin([ + ["react", "react-dom"], + ["zustand", "jotai", "use-context-selector", "immer", "dexie"], + [ + "remark-directive", + "remark-gfm", + "remark-parse", + "remark-stringify", + "remark-rehype", + "@microflash/remark-callout-directives", + "remark-gh-alerts", + ], + [ + "rehype-parse", + "rehype-sanitize", + "rehype-stringify", + "rehype-infer-description-meta", + "hast-util-to-jsx-runtime", + "hast-util-to-text", + ], + ["vfile", "unified"], + ["lodash-es"], + ["framer-motion"], + ["clsx", "tailwind-merge", "class-variance-authority"], + ["@radix-ui/react-dialog", "re-resizable"], + ["i18next", "i18next-browser-languagedetector", "react-i18next"], + [ + "@tanstack/react-query", + "@tanstack/react-query-persist-client", + "@tanstack/query-sync-storage-persister", + ], + ["blurhash", "react-blurhash"], + ["tldts"], + ["shiki", "@shikijs/transformers"], + ["@sentry/react", "posthog-js"], + ["zod", "react-hook-form", "@hookform/resolvers"], + ]), + // shortAliasPlugin(), process.env.ANALYZER && analyzer(), ], + define: { ...viteRenderBaseConfig.define, ELECTRON: "false", From 8e571e7fa77fdfc5c0e992bda53cea1c5eb0fb76 Mon Sep 17 00:00:00 2001 From: Innei Date: Sat, 5 Oct 2024 00:41:43 +0800 Subject: [PATCH 80/88] fix: lockfile Signed-off-by: Innei --- pnpm-lock.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dd479186d..6a7b3c165 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -489,9 +489,6 @@ importers: lethargy: specifier: 1.0.9 version: 1.0.9 - linkedom: - specifier: ^0.18.5 - version: 0.18.5 lodash-es: specifier: 4.17.21 version: 4.17.21 From 8bc477100b8e5d3532d09875eda32004762eacca Mon Sep 17 00:00:00 2001 From: Innei Date: Sat, 5 Oct 2024 00:54:45 +0800 Subject: [PATCH 81/88] perf: reduce vite alias length Signed-off-by: Innei --- plugins/vite/short-alias.ts | 56 +++++++++++++++++++++---------------- vite.config.ts | 3 +- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/plugins/vite/short-alias.ts b/plugins/vite/short-alias.ts index 988219caf..8a82a88b9 100644 --- a/plugins/vite/short-alias.ts +++ b/plugins/vite/short-alias.ts @@ -1,5 +1,14 @@ +import generate from "@babel/generator" +import { parse } from "@babel/parser" +import traverse from "@babel/traverse" +import * as t from "@babel/types" import type { Plugin } from "vite" +// @ts-expect-error +const traverseApply: typeof traverse = traverse.default || traverse +// @ts-expect-error +const generateApply: typeof generate = generate.default || generate + export function shortAliasPlugin(): Plugin { const aliasMap = new Map() let aliasCounter = 0 @@ -21,37 +30,36 @@ export function shortAliasPlugin(): Plugin { name: "short-alias", renderChunk(code, chunk) { if (chunk.fileName.startsWith("vendor/")) return code - const importRegex = /import\s*(\{[^}]+\})\s*from\s*(['"])([^'"]+)\2/g - return code.replaceAll(importRegex, (match, imports, quote, source) => { - // Only process imports with curly braces - if (!imports.startsWith("{") || !imports.endsWith("}")) { - return match - } + const ast = parse(code, { + sourceType: "module", + plugins: ["typescript"], + }) - const newImports = imports - .slice(1, -1) // Remove the curly braces - .split(",") - .map((imp) => { - const [original, alias] = imp.trim().split(/\s+as\s+/) - if (alias) { - // If an alias already exists, keep it or shorten it if it's too long - if (alias.length > 3) { - let shortAlias = aliasMap.get(alias) + traverseApply(ast, { + ImportDeclaration(path) { + path.node.specifiers.forEach((specifier) => { + if (t.isImportSpecifier(specifier)) { + const imported = specifier.imported as t.Identifier + const local = specifier.local as t.Identifier + + if (local.name !== imported.name && local.name.length > 3) { + let shortAlias = aliasMap.get(local.name) if (!shortAlias) { shortAlias = generateShortAlias() - aliasMap.set(alias, shortAlias) + aliasMap.set(local.name, shortAlias) } - return `${original} as ${shortAlias}` - } - return imp.trim() - } - return imp.trim() - }) - .join(", ") - return `import {${newImports}} from ${quote}${source}${quote}` + path.scope.rename(local.name, shortAlias) + local.name = shortAlias + } + } + }) + }, }) + + const output = generateApply(ast, { retainLines: true }, code) + return output.code }, } } diff --git a/vite.config.ts b/vite.config.ts index e4481e761..2789e567c 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -12,6 +12,7 @@ import { viteRenderBaseConfig } from "./configs/vite.render.config" import type { env as EnvType } from "./packages/shared/src/env" import { createDependencyChunksPlugin } from "./plugins/vite/deps" import { htmlInjectPlugin } from "./plugins/vite/html-inject" +import { shortAliasPlugin } from "./plugins/vite/short-alias" const __dirname = fileURLToPath(new URL(".", import.meta.url)) const isCI = process.env.CI === "true" || process.env.CI === "1" @@ -111,7 +112,7 @@ export default ({ mode }) => { ["@sentry/react", "posthog-js"], ["zod", "react-hook-form", "@hookform/resolvers"], ]), - // shortAliasPlugin(), + shortAliasPlugin(), process.env.ANALYZER && analyzer(), ], From e474bbf45d99da1aca68d8fcc1110a8f3ccb45fa Mon Sep 17 00:00:00 2001 From: DIYgod Date: Sat, 5 Oct 2024 02:40:54 +0800 Subject: [PATCH 82/88] feat: update icons --- apps/renderer/src/modules/entry-content/header.tsx | 4 ++-- apps/renderer/src/modules/entry-content/index.tsx | 2 +- apps/renderer/src/modules/entry-content/loading.tsx | 2 +- apps/renderer/src/modules/settings/tabs/invitations.tsx | 2 +- apps/renderer/src/pages/settings/(settings)/invitations.tsx | 2 +- icons/mgc/docment_cute_fi.svg | 1 + icons/mgc/docment_cute_re.svg | 1 + icons/mgc/heart_hand_cute_re.svg | 1 - icons/mgc/love_cute_re.svg | 1 + icons/mgc/sparkles_2_cute_re.svg | 1 - icons/mgc/sparkles_2_filled.svg | 1 - packages/shared/src/hono.ts | 3 +-- 12 files changed, 10 insertions(+), 11 deletions(-) create mode 100644 icons/mgc/docment_cute_fi.svg create mode 100644 icons/mgc/docment_cute_re.svg delete mode 100644 icons/mgc/heart_hand_cute_re.svg create mode 100644 icons/mgc/love_cute_re.svg delete mode 100644 icons/mgc/sparkles_2_cute_re.svg delete mode 100644 icons/mgc/sparkles_2_filled.svg diff --git a/apps/renderer/src/modules/entry-content/header.tsx b/apps/renderer/src/modules/entry-content/header.tsx index 97171e12c..fa9f9c258 100644 --- a/apps/renderer/src/modules/entry-content/header.tsx +++ b/apps/renderer/src/modules/entry-content/header.tsx @@ -186,8 +186,8 @@ const ElectronAdditionActions = window.electron name: t("entry_content.header.readability"), className: cn( isInReadability(entryReadabilityStatus) - ? `i-mgc-sparkles-2-filled` - : `i-mgc-sparkles-2-cute-re`, + ? `i-mgc-docment-cute-fi` + : `i-mgc-docment-cute-re`, entryReadabilityStatus === ReadabilityStatus.WAITING ? `animate-pulse` : "", ), key: "readability", diff --git a/apps/renderer/src/modules/entry-content/index.tsx b/apps/renderer/src/modules/entry-content/index.tsx index 3bf23c1e0..b005c3bdf 100644 --- a/apps/renderer/src/modules/entry-content/index.tsx +++ b/apps/renderer/src/modules/entry-content/index.tsx @@ -324,7 +324,7 @@ const ReadabilityContent = ({ entryId }: { entryId: string }) => {

    ) : (
    - } /> + } /> {t("entry_content.fetching_content")}
    )} diff --git a/apps/renderer/src/modules/entry-content/loading.tsx b/apps/renderer/src/modules/entry-content/loading.tsx index b247876c8..7b450d67c 100644 --- a/apps/renderer/src/modules/entry-content/loading.tsx +++ b/apps/renderer/src/modules/entry-content/loading.tsx @@ -4,7 +4,7 @@ import { getUrlIcon } from "~/lib/utils" export const EntryContentLoading = (props: { icon?: string }) => { if (!props.icon) { - return } /> + return } /> } return (
    diff --git a/apps/renderer/src/modules/settings/tabs/invitations.tsx b/apps/renderer/src/modules/settings/tabs/invitations.tsx index b853d3ac6..b2d7c9723 100644 --- a/apps/renderer/src/modules/settings/tabs/invitations.tsx +++ b/apps/renderer/src/modules/settings/tabs/invitations.tsx @@ -71,7 +71,7 @@ export const SettingInvitations = () => { }) }} > - + {t("invitation.generateButton")} diff --git a/apps/renderer/src/pages/settings/(settings)/invitations.tsx b/apps/renderer/src/pages/settings/(settings)/invitations.tsx index 02a3e81d0..1978463ff 100644 --- a/apps/renderer/src/pages/settings/(settings)/invitations.tsx +++ b/apps/renderer/src/pages/settings/(settings)/invitations.tsx @@ -2,7 +2,7 @@ import { SettingInvitations } from "~/modules/settings/tabs/invitations" import { SettingsTitle } from "~/modules/settings/title" import { defineSettingPageData } from "~/modules/settings/utils" -const iconName = "i-mgc-heart-hand-cute-re" +const iconName = "i-mgc-love-cute-re" const priority = 1070 export const loader = defineSettingPageData({ diff --git a/icons/mgc/docment_cute_fi.svg b/icons/mgc/docment_cute_fi.svg new file mode 100644 index 000000000..784ae2c8d --- /dev/null +++ b/icons/mgc/docment_cute_fi.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/mgc/docment_cute_re.svg b/icons/mgc/docment_cute_re.svg new file mode 100644 index 000000000..e49f9de87 --- /dev/null +++ b/icons/mgc/docment_cute_re.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/mgc/heart_hand_cute_re.svg b/icons/mgc/heart_hand_cute_re.svg deleted file mode 100644 index 34c371546..000000000 --- a/icons/mgc/heart_hand_cute_re.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icons/mgc/love_cute_re.svg b/icons/mgc/love_cute_re.svg new file mode 100644 index 000000000..5ef542f61 --- /dev/null +++ b/icons/mgc/love_cute_re.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/mgc/sparkles_2_cute_re.svg b/icons/mgc/sparkles_2_cute_re.svg deleted file mode 100644 index 068f11279..000000000 --- a/icons/mgc/sparkles_2_cute_re.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icons/mgc/sparkles_2_filled.svg b/icons/mgc/sparkles_2_filled.svg deleted file mode 100644 index f7e901c40..000000000 --- a/icons/mgc/sparkles_2_filled.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/shared/src/hono.ts b/packages/shared/src/hono.ts index 2fc0fea85..1587c678b 100644 --- a/packages/shared/src/hono.ts +++ b/packages/shared/src/hono.ts @@ -4257,12 +4257,11 @@ declare const _routes: hono_hono_base.HonoBase Date: Sat, 5 Oct 2024 13:25:56 +0800 Subject: [PATCH 83/88] feat: wide mode --- apps/renderer/src/atoms/settings/ui.ts | 1 + .../entry-column/layouts/EntryListHeader.tsx | 34 +++++++++++++++++++ .../templates/list-item-template.tsx | 16 ++++++--- .../feeds/[feedId]/[entryId]/index.tsx | 31 ++++++++++++++--- .../(main)/(layer)/feeds/[feedId]/layout.tsx | 5 +-- icons/mgc/align_justify_cute_re.svg | 1 + icons/mgc/align_left_cute_re.svg | 1 + locales/app/en.json | 2 ++ packages/shared/src/interface/settings.ts | 1 + 9 files changed, 82 insertions(+), 10 deletions(-) create mode 100644 icons/mgc/align_justify_cute_re.svg create mode 100644 icons/mgc/align_left_cute_re.svg diff --git a/apps/renderer/src/atoms/settings/ui.ts b/apps/renderer/src/atoms/settings/ui.ts index 8a0fb1e25..96b08a748 100644 --- a/apps/renderer/src/atoms/settings/ui.ts +++ b/apps/renderer/src/atoms/settings/ui.ts @@ -33,6 +33,7 @@ export const createDefaultSettings = (): UISettings => ({ // View pictureViewMasonry: true, pictureViewFilterNoImage: false, + wideMode: false, // TTS voice: "en-US-AndrewMultilingualNeural", diff --git a/apps/renderer/src/modules/entry-column/layouts/EntryListHeader.tsx b/apps/renderer/src/modules/entry-column/layouts/EntryListHeader.tsx index b7b2fd1e8..2cdb1c338 100644 --- a/apps/renderer/src/modules/entry-column/layouts/EntryListHeader.tsx +++ b/apps/renderer/src/modules/entry-column/layouts/EntryListHeader.tsx @@ -98,6 +98,7 @@ export const EntryListHeader: FC<{ )} + {!views[view].wideMode && } {view === FeedViewType.SocialMedia && } {view === FeedViewType.Pictures && } {view === FeedViewType.Pictures && } @@ -231,6 +232,39 @@ const SwitchToMasonryButton = () => { ) } +const WideModeButton = () => { + const isWideMode = useUISettingKey("wideMode") + const { t } = useTranslation() + + return ( + + { + setUISetting("wideMode", !isWideMode) + window.posthog?.capture("Switch to Wide Mode", { + wideMode: !isWideMode ? 1 : 0, + click: 1, + }) + }} + tooltip={ + !isWideMode + ? t("entry_list_header.switch_to_widemode") + : t("entry_list_header.switch_to_normalmode") + } + > + + + + ) +} + const AppendTaildingDivider = ({ children }: { children: React.ReactNode }) => ( <> {children} diff --git a/apps/renderer/src/modules/entry-column/templates/list-item-template.tsx b/apps/renderer/src/modules/entry-column/templates/list-item-template.tsx index 5685f5c02..d686aa4af 100644 --- a/apps/renderer/src/modules/entry-column/templates/list-item-template.tsx +++ b/apps/renderer/src/modules/entry-column/templates/list-item-template.tsx @@ -2,6 +2,7 @@ import { env } from "@follow/shared/env" import { useDebounceCallback } from "usehooks-ts" import { AudioPlayer, useAudioPlayerAtomSelector } from "~/atoms/player" +import { useUISettingKey } from "~/atoms/settings/ui" import { FeedIcon } from "~/components/feed-icon" import { FollowIcon } from "~/components/icons/follow" import { Button } from "~/components/ui/button" @@ -61,19 +62,23 @@ export function ListItem({ const isFollowed = !!useSubscriptionStore((state) => feedId && state.data[feedId]) const { present } = useModalStack() + const settingWideMode = useUISettingKey("wideMode") + // NOTE: prevent 0 height element, react virtuoso will not stop render any more if (!entry || !feed) return const displayTime = inInCollection ? entry.collections?.createdAt : entry.entries.publishedAt const envIsSafari = isSafari() + return (
    {!withAudio && } @@ -82,7 +87,7 @@ export function ListItem({ "-mt-0.5 flex-1 text-sm leading-tight", // FIXME: Safari bug, not support line-clamp cross elements - !envIsSafari && "line-clamp-4", + !envIsSafari && (settingWideMode ? "line-clamp-2" : "line-clamp-4"), )} >
    @@ -191,7 +196,10 @@ export function ListItem({ src={entry.entries.media[0].url} type={entry.entries.media[0].type} previewImageUrl={entry.entries.media[0].preview_image_url} - className="center ml-2 flex size-20 max-w-20 shrink-0 rounded" + className={cn( + "center ml-2 flex shrink-0 rounded", + settingWideMode ? "size-12" : "size-20", + )} mediaContainerClassName={"w-auto h-auto rounded"} loading="lazy" proxy={{ diff --git a/apps/renderer/src/pages/(main)/(layer)/feeds/[feedId]/[entryId]/index.tsx b/apps/renderer/src/pages/(main)/(layer)/feeds/[feedId]/[entryId]/index.tsx index e598bc25e..ad61cc914 100644 --- a/apps/renderer/src/pages/(main)/(layer)/feeds/[feedId]/[entryId]/index.tsx +++ b/apps/renderer/src/pages/(main)/(layer)/feeds/[feedId]/[entryId]/index.tsx @@ -1,21 +1,44 @@ import { AnimatePresence } from "framer-motion" import { useParams } from "react-router-dom" +import { useUISettingKey } from "~/atoms/settings/ui" +import { ActionButton } from "~/components/ui/button" import { ROUTE_ENTRY_PENDING, views } from "~/constants" +import { useNavigateEntry } from "~/hooks/biz/useNavigateEntry" import { useRouteView } from "~/hooks/biz/useRouteParams" +import { cn } from "~/lib/utils" import { EntryContent } from "~/modules/entry-content" import { AppLayoutGridContainerProvider } from "~/providers/app-grid-layout-container-provider" export const Component = () => { const { entryId } = useParams() const view = useRouteView() - const inWideMode = view ? views[view].wideMode : false + const navigate = useNavigateEntry() + + const settingWideMode = useUISettingKey("wideMode") + const realEntryId = entryId === ROUTE_ENTRY_PENDING ? "" : entryId + const disable = views[view].wideMode || (settingWideMode && !realEntryId) + const wideMode = settingWideMode && realEntryId + return ( - {!inWideMode && ( -
    - + {!disable && ( +
    + {wideMode && ( + navigate({ entryId: null })} + > + + + )} +
    )} diff --git a/apps/renderer/src/pages/(main)/(layer)/feeds/[feedId]/layout.tsx b/apps/renderer/src/pages/(main)/(layer)/feeds/[feedId]/layout.tsx index 3efa90a13..064bb2b72 100644 --- a/apps/renderer/src/pages/(main)/(layer)/feeds/[feedId]/layout.tsx +++ b/apps/renderer/src/pages/(main)/(layer)/feeds/[feedId]/layout.tsx @@ -15,9 +15,10 @@ export function Component() { // Memo this initial value to avoid re-render + const settingWideMode = useUISettingKey("wideMode") const entryColWidth = useMemo(() => getUISettings().entryColWidth, []) const { view } = useRouteParams() - const inWideMode = view ? views[view].wideMode : false + const inWideMode = (view ? views[view].wideMode : false) || settingWideMode const feedColumnWidth = useUISettingKey("feedColWidth") const { position, separatorProps, isDragging, separatorCursor } = useResizable({ axis: "x", @@ -32,7 +33,7 @@ export function Component() { }) return ( -
    +
    \ No newline at end of file diff --git a/icons/mgc/align_left_cute_re.svg b/icons/mgc/align_left_cute_re.svg new file mode 100644 index 000000000..8466c0724 --- /dev/null +++ b/icons/mgc/align_left_cute_re.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/locales/app/en.json b/locales/app/en.json index 9757eb883..39d68601a 100644 --- a/locales/app/en.json +++ b/locales/app/en.json @@ -98,6 +98,8 @@ "entry_list_header.show_unread_only": "Show unread Only", "entry_list_header.switch_to_grid": "Switch to Grid", "entry_list_header.switch_to_masonry": "Switch to Masonry", + "entry_list_header.switch_to_normalmode": "Switch to Normal Mode", + "entry_list_header.switch_to_widemode": "Switch to Wide Mode", "entry_list_header.unread": "unread", "feed_claim_modal.choose_verification_method": "There are three ways to choose from, you can choose one of them to verify.", "feed_claim_modal.claim_button": "Claim", diff --git a/packages/shared/src/interface/settings.ts b/packages/shared/src/interface/settings.ts index 2f4496125..a613d695b 100644 --- a/packages/shared/src/interface/settings.ts +++ b/packages/shared/src/interface/settings.ts @@ -33,6 +33,7 @@ export interface UISettings { // view pictureViewMasonry: boolean pictureViewFilterNoImage: boolean + wideMode: boolean // tts voice: string From b5a1457196c008e5c78efd2bb8e0897c2cf57e5a Mon Sep 17 00:00:00 2001 From: DIYgod Date: Sat, 5 Oct 2024 13:30:24 +0800 Subject: [PATCH 84/88] chore(release): release v0.0.1-alpha.19 --- CHANGELOG.md | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++- package.json | 2 +- 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92aa38892..6258a0cb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # CHANGELOG -## [0.0.1-alpha.18](https://github.com/RSSNext/follow/compare/v0.0.1-alpha.3...v0.0.1-alpha.18) (2024-09-27) +## [0.0.1-alpha.19](https://github.com/RSSNext/follow/compare/v0.0.1-alpha.3...v0.0.1-alpha.19) (2024-10-05) ### Bug Fixes @@ -20,10 +20,12 @@ * add download app fab ([0f8309b](https://github.com/RSSNext/follow/commit/0f8309b2031d53a17eb74ed36f2a0f504c54c431)) * add en lang fixed[#641](https://github.com/RSSNext/follow/issues/641) ([23d6988](https://github.com/RSSNext/follow/commit/23d6988a63ce6ecdce562fb632fe85823082d38b)) * add environment in error report issue template ([232c24d](https://github.com/RSSNext/follow/commit/232c24de3dbc135f4064c17680fbe6e429c92697)) +* add feed from url, close [#686](https://github.com/RSSNext/follow/issues/686) ([fd30789](https://github.com/RSSNext/follow/commit/fd30789d86a6980aa4b1c4ea45c81c7b7deb3e15)) * add feed should validate feed id first ([767710d](https://github.com/RSSNext/follow/commit/767710deda41af1842179ef03f9b6b1b79208f9e)) * add feed temp store use nonce ([6e36232](https://github.com/RSSNext/follow/commit/6e36232b41f1b6d877caf74e1ad7be50da716381)) * add feed when site url not match ([1a2190c](https://github.com/RSSNext/follow/commit/1a2190c1aa834a33932788e65269a1128fd3a7e2)) * add hover bg color when context menu opened ([6ceb263](https://github.com/RSSNext/follow/commit/6ceb263b777ccc9681cd086a28e019ce9bda3a43)) +* add i18n in preview-media ([#675](https://github.com/RSSNext/follow/issues/675)) ([935c87d](https://github.com/RSSNext/follow/commit/935c87de285ecabb44a92bc3536135e3c2c0e14f)) * add language selector loading lock map ([2d14c1e](https://github.com/RSSNext/follow/commit/2d14c1e5b5ad086b3556dd9a8862a6ce00368c4d)) * add link ([d9168c0](https://github.com/RSSNext/follow/commit/d9168c01b3f2a16fbfeadb722173e819dd3feb80)) * add lock when login button click ([539f3bc](https://github.com/RSSNext/follow/commit/539f3bc599f4df9784662ca2bf972a94edf556c4)) @@ -32,6 +34,7 @@ * add nonce id for temp feed ([8f81d99](https://github.com/RSSNext/follow/commit/8f81d99f1dd48e60f9861d69c840c77fa70bde93)) * add page error boundary ([86d366d](https://github.com/RSSNext/follow/commit/86d366db76add0ad07eb921290b9444b211e2c4f)) * add rounded class to video fallback message ([#665](https://github.com/RSSNext/follow/issues/665)) ([86d7b8c](https://github.com/RSSNext/follow/commit/86d7b8cc1293d4ec7cca79155a50a5f7ea01dd75)) +* add safe inset-top for Windows, fixed [#576](https://github.com/RSSNext/follow/issues/576) ([3352e8c](https://github.com/RSSNext/follow/commit/3352e8c292e810bb9a333e2a3c5e23adbae2a57a)) * add show readability tip condition ([208e404](https://github.com/RSSNext/follow/commit/208e4040cea5d3485acf5750e7120fb5f715e30f)) * add some polyfills for old browser, fixed [#236](https://github.com/RSSNext/follow/issues/236) ([b1fbfbd](https://github.com/RSSNext/follow/commit/b1fbfbd7e38a6a10430f7ed2d4b0644c2d5bbf22)) * add tooltip for resize panel ([cdec351](https://github.com/RSSNext/follow/commit/cdec3510352cc7281e75ef1957e32bc6e712cf04)) @@ -77,6 +80,7 @@ * ci and tootip portal ([3729917](https://github.com/RSSNext/follow/commit/37299173c8fcaf88d44b1a54baf7ddc03aa20ca6)) * ci env `NODE_OPTIONS` max-old-space-size ([b4f9b1b](https://github.com/RSSNext/follow/commit/b4f9b1b8ea326b1613ca291ed5bbcd932c5e837a)) * **ci:** fetch all depth ([a504a12](https://github.com/RSSNext/follow/commit/a504a127bca93a6675b3ff02bcea0b1eca6e9707)) +* **ci:** nightly build ([a4ce7b1](https://github.com/RSSNext/follow/commit/a4ce7b16f476b8d72a0b1761709ec1ceba591242)) * **ci:** remove check diff ([32f3a9e](https://github.com/RSSNext/follow/commit/32f3a9edba28ec2368730c6038ff6d3f8d55b404)) * clean local async data ([ae26dd7](https://github.com/RSSNext/follow/commit/ae26dd7763fe32990086e76fa896ec09dec170cd)) * cls when star in gird item ([#636](https://github.com/RSSNext/follow/issues/636)) ([b993ae0](https://github.com/RSSNext/follow/commit/b993ae050e282c22e40f649141677f7905ede601)) @@ -103,19 +107,24 @@ * discover form overflow scrollbar ([1145e92](https://github.com/RSSNext/follow/commit/1145e92ae7125873d69f2689d86418b004d93319)) * discover form should preview twice when has optional value ([f0f8185](https://github.com/RSSNext/follow/commit/f0f8185d92e447943c14a4ceeeceb7211498bc28)) * discover page title i18n ([b92d317](https://github.com/RSSNext/follow/commit/b92d317e9c1dbdd674a6b122a02f3f6a3826682f)) +* discover recommendation card link button style ([1ac465c](https://github.com/RSSNext/follow/commit/1ac465cbb96bda4a189dea086caf3bbe77aa64ee)) * **discover:** update follow status after add feed, closes [#269](https://github.com/RSSNext/follow/issues/269), closes ([32a55ec](https://github.com/RSSNext/follow/commit/32a55ece6440f80f837adc6d558029ea5fbd6982)) * display white block ([#633](https://github.com/RSSNext/follow/issues/633)) ([d9bb749](https://github.com/RSSNext/follow/commit/d9bb74937b5b2f528707e80fc2a76a89df10a1a8)) +* don't auto focus in user profile modal ([f1ce5df](https://github.com/RSSNext/follow/commit/f1ce5df581c0a91967d3d093b6735e2fdd3ea906)) * don't retry when 404 ([8bd9bd0](https://github.com/RSSNext/follow/commit/8bd9bd0a8bf92764d8dd13a0728e3ab821b3484b)) * dont handle unread when filter applied ([acfb35a](https://github.com/RSSNext/follow/commit/acfb35abd0edb85989549849d0176c4a65e5f9fa)) * downgarde vitest ([dee089e](https://github.com/RSSNext/follow/commit/dee089e1c75bf9031663b682aff9cee33b60db76)) +* downgrade vitest ([2f15900](https://github.com/RSSNext/follow/commit/2f15900b087f1a0a511f82e559eae617dc2faf32)) * draggable panel dragging bg color ([8de7078](https://github.com/RSSNext/follow/commit/8de7078d10b733456c480117ba8ed8d2166e20b9)) * drawer edge shadow style ([cbb8649](https://github.com/RSSNext/follow/commit/cbb8649fde99e7a800153ad35aa041aaf44e6dcf)) +* drawer top edge anchor ([248369a](https://github.com/RSSNext/follow/commit/248369afe6d085885fd76a4ecf6a3f9b692b14cf)) * duplicated separator ([6e1ee50](https://github.com/RSSNext/follow/commit/6e1ee50536ded4b65f76cdb35bdf98c4657a1a74)) * dynamic load i18n resource in electron prod ([2328648](https://github.com/RSSNext/follow/commit/232864852a934d571a2b47af7f4d02c787cc8250)) * eagle icon ([021dfab](https://github.com/RSSNext/follow/commit/021dfab5eeb888f155982cc1cd3636b2b4ca52a3)) * electron context menu i18n ([1a1d8ab](https://github.com/RSSNext/follow/commit/1a1d8ab5c1ff4917d3b3368059eff0b4cdf57520)) * electron exit webview fullscreen sidebar color ([bc7914f](https://github.com/RSSNext/follow/commit/bc7914f803939897d817080972e5307cf58f8caf)) * electron external window size option ([399d5d7](https://github.com/RSSNext/follow/commit/399d5d7a2cda5c7a7f9ce91ae9b9125f9ece7c54)) +* electron menu support checkbox ([7881f23](https://github.com/RSSNext/follow/commit/7881f236ad7f69725a25daa01deeb81aa9dc76ab)) * electron search ([63bea18](https://github.com/RSSNext/follow/commit/63bea180f545e2f64cdc7e379f807333fee0ded6)) * electron title bar drag-region ([29ab323](https://github.com/RSSNext/follow/commit/29ab32344fafda613b0c9d49b587786eaa40b00a)) * electron window frame and `backgroundMaterial` ([e18ec75](https://github.com/RSSNext/follow/commit/e18ec754a05231fb82a7cbdb80632d79a6232872)) @@ -127,10 +136,13 @@ * entries hasNext ([4cb5678](https://github.com/RSSNext/follow/commit/4cb56784acfb46516a4320f0088c294eafb32fcf)) * entry bar action ([ba23dcf](https://github.com/RSSNext/follow/commit/ba23dcf46ff7569562d0a786ab85d46093b8abe8)) * entry column padding top and filter unread/read in tweet view ([d181771](https://github.com/RSSNext/follow/commit/d181771a7bf314cdb30f2fdd76294c5cded524ab)) +* entry column title line height ([b615c17](https://github.com/RSSNext/follow/commit/b615c171d551f27932a7a42a814388bd8e07cf84)) +* entry column title top overflow ([4478034](https://github.com/RSSNext/follow/commit/447803488c1ed01769c134f3113b0a3926e07446)) * entry item overlay flash ([687e039](https://github.com/RSSNext/follow/commit/687e039ca2ad43eed2b4b48a29df96595dcdbc0f)) * entry preview modal content ([8492c2a](https://github.com/RSSNext/follow/commit/8492c2afb3af79726b9448359a63b432b04a3518)) * entry read history more not showing on desktop ([0c6494b](https://github.com/RSSNext/follow/commit/0c6494b5682078fa1da1ea2e6f5d81aa436a5155)) * entry view tracker params ([0c05a8b](https://github.com/RSSNext/follow/commit/0c05a8b88c1c385b7809f1ea9e3355f0d11e69dd)) +* env example ([cdb8dd5](https://github.com/RSSNext/follow/commit/cdb8dd5cf31ec2d43b18a50cdd3259302620867e)) * **error:** filter user is empty ([83b4031](https://github.com/RSSNext/follow/commit/83b4031405d2a6e979a32fbb18095f22d19d6a70)) * **eslint:** json sort key ([5a81dd6](https://github.com/RSSNext/follow/commit/5a81dd6786b7c0e4a533f3cb4e50d7900d005875)) * exit full screen before hiding window ([#341](https://github.com/RSSNext/follow/issues/341)) ([bd5b08f](https://github.com/RSSNext/follow/commit/bd5b08f314ddaddb9b079b3d10b6928d28962df5)) @@ -151,6 +163,7 @@ * feed list can switch view, fix [#278](https://github.com/RSSNext/follow/issues/278) ([76a33b6](https://github.com/RSSNext/follow/commit/76a33b6f905bac61f6390b01b13c6a43b94f535f)) * feed list overflow ([4941cf7](https://github.com/RSSNext/follow/commit/4941cf7b93a751f585ab5032974fe6eb191f7968)) * **feed-icon:** re-render loop ([b6f78bb](https://github.com/RSSNext/follow/commit/b6f78bbbf89b804fc4a0ad89b524f0a24673c19a)) +* fetch inbox entry ([ecb2d33](https://github.com/RSSNext/follow/commit/ecb2d3397993ba019019cbf82c6e969dcf7851ed)) * fill relative url in entry title link, fix [#372](https://github.com/RSSNext/follow/issues/372) ([7c3aab6](https://github.com/RSSNext/follow/commit/7c3aab6f042a710aaa99d8fb7a774fce89af2b08)) * fix the fixed misalignment when image is empty and name is also empty ([#179](https://github.com/RSSNext/follow/issues/179)) ([f6b62c8](https://github.com/RSSNext/follow/commit/f6b62c8ce0908772c394d653857197c9302e332b)) * fixed text overlap issues caused by style ([#527](https://github.com/RSSNext/follow/issues/527)) ([103bd6a](https://github.com/RSSNext/follow/commit/103bd6a414beb9a808a9ad661348ff416626bc18)) @@ -162,6 +175,7 @@ * generate-i18n scripti ([fd361e8](https://github.com/RSSNext/follow/commit/fd361e88864c57c6f76793519a2e57a650aa4a2b)) * gird item text and icon align center ([eabd59c](https://github.com/RSSNext/follow/commit/eabd59cf1feb774759279832005fcd0e26aa7bb6)) * gird mode skeleton ([0a7f648](https://github.com/RSSNext/follow/commit/0a7f6488c176ee059f7c87f3c51e0234c85c1d4c)) +* grid mode for images and video content page, shadow not fully displayed when the mouse hovers over ([#727](https://github.com/RSSNext/follow/issues/727)) ([361b09e](https://github.com/RSSNext/follow/commit/361b09eb23c86f377cc82d7e523781a7d4507689)) * group header extra action button for wider mode ([213b4a5](https://github.com/RSSNext/follow/commit/213b4a5864c78716648b2319f5d6f0dfcb531e3a)) * grouped list data item render ([da486bc](https://github.com/RSSNext/follow/commit/da486bce3eeafc84aeb3e560ff368c41771688cf)) * handle empty title in entry translation ([#362](https://github.com/RSSNext/follow/issues/362)) ([a2457a7](https://github.com/RSSNext/follow/commit/a2457a7789aff5928714cbe55e3e7863bb51719b)) @@ -174,7 +188,14 @@ * hono.ts ([fd03caa](https://github.com/RSSNext/follow/commit/fd03caac22f9e035734d369351134ed63da93439)) * i18n dispatcher ([c038c79](https://github.com/RSSNext/follow/commit/c038c791af14418ee641af08e689a619b99a1735)) * i18n persist ([18e0353](https://github.com/RSSNext/follow/commit/18e035394b8d1a77f8454f47e0049359e69d750a)) +* **i18n-selector:** hover cls ([60f1af2](https://github.com/RSSNext/follow/commit/60f1af2409300e64ad351621abf71ed326188af8)) +* **i18n/en:** enhance English grammar ([#698](https://github.com/RSSNext/follow/issues/698)) ([4478517](https://github.com/RSSNext/follow/commit/4478517566aced3e55928229433a4cc83dd0c3ae)) +* **i18n/zh:** improve translation text in `wallet.transaction` table ([#706](https://github.com/RSSNext/follow/issues/706)) ([67e305c](https://github.com/RSSNext/follow/commit/67e305ccc6b33ca6e81ce68af9f9522219f9a067)) +* **i18n:** add de to langs ([#683](https://github.com/RSSNext/follow/issues/683)) ([018b5b1](https://github.com/RSSNext/follow/commit/018b5b1b1b3ced06543189512f5bb2df39f946af)) +* **i18n:** add native french support ([#670](https://github.com/RSSNext/follow/issues/670)) ([b214c0d](https://github.com/RSSNext/follow/commit/b214c0db01edafced973ed9075ff6be3959c5f61)) +* **i18n:** complete the Chinese (Taiwan) and Chinese (Hong Kong) json files. ([#720](https://github.com/RSSNext/follow/issues/720)) ([ad5adc3](https://github.com/RSSNext/follow/commit/ad5adc358933370bdff9b17f732d7a0d924fe10d)) * **i18n:** dup key ([d90964e](https://github.com/RSSNext/follow/commit/d90964ea9e32d5d7b162d6d7525df213ac732e12)) +* **i18n:** duplicated keys ([234cdd3](https://github.com/RSSNext/follow/commit/234cdd3c71bb2e1fb0548734f31b10093372bc90)) * **i18n:** fix json nested key fixes [#605](https://github.com/RSSNext/follow/issues/605) ([34b9a20](https://github.com/RSSNext/follow/commit/34b9a20acf41f62c2710699cc6190fdc95c7d749)) * **i18n:** give star ([#502](https://github.com/RSSNext/follow/issues/502)) ([9ead475](https://github.com/RSSNext/follow/commit/9ead4754d31fee3a1c14a3ef9210a621c2dd039f)) * **i18n:** hk language resource ([43c89e0](https://github.com/RSSNext/follow/commit/43c89e007d50620fbf298bbf571db0c3cf43e028)) @@ -183,6 +204,7 @@ * **i18n:** relative time add `ago` postfix ([9fe48c5](https://github.com/RSSNext/follow/commit/9fe48c57133e0360a74aa46c06f01393cc044136)) * icon button transition ([596538b](https://github.com/RSSNext/follow/commit/596538ba10b6b70d12ccc4efdd9f206d9ba11817)) * icon fallback line height ([02cd98d](https://github.com/RSSNext/follow/commit/02cd98d9cc9c09006a91277a5b976d753054738d)) +* image blurhash `aspectRatio` ([9239483](https://github.com/RSSNext/follow/commit/9239483081e6e4adfda4934695c03df394e873fa)) * image url replacement ([8e75a8c](https://github.com/RSSNext/follow/commit/8e75a8cc6931b354e3206ea22917842c991d4c45)) * **image:** error fallback ([18fdaa2](https://github.com/RSSNext/follow/commit/18fdaa20610fba875054c3d298ecb07e099ad584)) * import circular and copywrite i18n ([725f9f5](https://github.com/RSSNext/follow/commit/725f9f5509c3b34079923fad47096b108568ccd6)) @@ -212,6 +234,7 @@ * loadFile options hash ([b41fa66](https://github.com/RSSNext/follow/commit/b41fa665fa334f0037de294d8e0585a5cf94c649)) * loading circle clip path ([ba396be](https://github.com/RSSNext/follow/commit/ba396beaa78eae3c1b250fd846cc8434c2abc07f)) * loading style ([61ee2cc](https://github.com/RSSNext/follow/commit/61ee2ccb3e30d3ab82de0bfe6aca35df38794dca)) +* lockfile ([8e571e7](https://github.com/RSSNext/follow/commit/8e571e7fa77fdfc5c0e992bda53cea1c5eb0fb76)) * login button transition ([0f566e7](https://github.com/RSSNext/follow/commit/0f566e757bdc15fc72c4cd3681384d7b4242b55a)) * login page style ([094a668](https://github.com/RSSNext/follow/commit/094a6684b62de69748f20011f5bd0f68833c30e1)) * **login-button:** add overflow ([650aeeb](https://github.com/RSSNext/follow/commit/650aeeb099a18341a6fd25b006e77818f040fa93)) @@ -221,6 +244,8 @@ * markdown link populate relative link ([bad5869](https://github.com/RSSNext/follow/commit/bad5869f3f974b96fa5513b99574f60fb8aba963)) * masonry layout cls ([9428368](https://github.com/RSSNext/follow/commit/9428368cfc4a00afb1c72f9ca3a4267b311c5b2b)) * **masonry:** in view mark read and scroll out mark read ([1c5a1ef](https://github.com/RSSNext/follow/commit/1c5a1ef9a58d7953e0966d2fe8d8fe4543463b84)) +* media fallback src overflow ([3dd705f](https://github.com/RSSNext/follow/commit/3dd705f3a427c53d000c4934513c97d6132399d0)) +* media preview image fixed size ([14c7028](https://github.com/RSSNext/follow/commit/14c7028347b22eb1cf768d5c3a4c20ffe9497b93)) * **media-preview:** solve image cls ([e0bcb71](https://github.com/RSSNext/follow/commit/e0bcb718aee57e7eeef31c3ffcdf5564c823c845)) * **media:** if no src then return null ([183009a](https://github.com/RSSNext/follow/commit/183009adee6d5674923a72ae0f5a10b85d4c7ba6)) * missing feed caused by parsing domain error ([1385876](https://github.com/RSSNext/follow/commit/13858762b4fed592ab7e5040ae6a59a9f3872747)) @@ -228,6 +253,8 @@ * modal max height, fixed [#230](https://github.com/RSSNext/follow/issues/230) ([fbf4727](https://github.com/RSSNext/follow/commit/fbf4727608ada80ba0f42349f2dace0543e22f9e)) * modal overlay zindex, fixed [#271](https://github.com/RSSNext/follow/issues/271) ([7a5000f](https://github.com/RSSNext/follow/commit/7a5000f20503ade15033822d9ad1c11303424728)) * modal prevent dimiss when mouse select text ([d99dfbc](https://github.com/RSSNext/follow/commit/d99dfbc79a2d6adb19eb7086fbc3aff8e860fb7b)) +* modal title overflow tooltip ([5146dd2](https://github.com/RSSNext/follow/commit/5146dd23487f98080bf246f50101e6d13ed79aea)) +* **modal:** limit setting modal drag range ([#732](https://github.com/RSSNext/follow/issues/732)) ([34f462f](https://github.com/RSSNext/follow/commit/34f462f2877ed979a59644e666ce27ba14dadc5b)) * modify the Tooltip content of the list dates title ([#663](https://github.com/RSSNext/follow/issues/663)) ([f99ba5d](https://github.com/RSSNext/follow/commit/f99ba5de916fc17904f6716b4d7eb4ccc295f79c)) * more highlighted player thumb ([a17ea00](https://github.com/RSSNext/follow/commit/a17ea00c23604312b09283ef89946140b61b2be9)) * new invitation button zindex ([0d79392](https://github.com/RSSNext/follow/commit/0d79392cde4c282cbc3faf69fd697b3726638279)) @@ -247,6 +274,8 @@ * picture entry preview in Grid view ([#658](https://github.com/RSSNext/follow/issues/658)) ([634978f](https://github.com/RSSNext/follow/commit/634978f427865f646088f13a315207cde63d532c)) * player holder size ([78cb08c](https://github.com/RSSNext/follow/commit/78cb08c7dc98aeab9cb5575296470106dbeb4e84)) * player marquee mask ([aa9ca62](https://github.com/RSSNext/follow/commit/aa9ca624a8d0304838bc05c330a8165a41430d3e)) +* populate image src ([426a1d4](https://github.com/RSSNext/follow/commit/426a1d48ddf3131019be80889d00dc394d6ba36f)) +* populated image src in markdown ([66cca8a](https://github.com/RSSNext/follow/commit/66cca8ad7a8541cc9aa65884a822f10c2dd19be6)) * position of swiper navigation buttons ([#541](https://github.com/RSSNext/follow/issues/541)) ([0d760e7](https://github.com/RSSNext/follow/commit/0d760e7bf9e4e74f823c715237c300773865650a)) * posthog capture app info ([8cf7ae2](https://github.com/RSSNext/follow/commit/8cf7ae26f47d6cbc58322978d915c699d16f95a3)) * posthog tracker ([f4790da](https://github.com/RSSNext/follow/commit/f4790da8b1f27937b47b27d127497742684e9cc1)) @@ -263,6 +292,7 @@ * prose max widht ([2bd5b45](https://github.com/RSSNext/follow/commit/2bd5b45e6bb4cc127dd07aa073d3b83c0a8bee82)) * provide a default ctx value for modal ([38ab5bf](https://github.com/RSSNext/follow/commit/38ab5bffafad32f97ac11a743a35be0a6012403d)) * proxy instagram picture ([ae05f1d](https://github.com/RSSNext/follow/commit/ae05f1da2b6d214aa615ad36189e7336f69e1fa1)) +* proxy sp1.piokok.com and video preview url ([0338876](https://github.com/RSSNext/follow/commit/033887693bc805d3217a4251447bb1e7da00db9a)) * radix auto focus issue ([b3d05b4](https://github.com/RSSNext/follow/commit/b3d05b42e9b0afd8b4e828bdf57eb564a53e613f)) * read entry history more button position ([61ca6b4](https://github.com/RSSNext/follow/commit/61ca6b452b61cd0770e15e908102c258e29b1c13)) * read history always show ([#413](https://github.com/RSSNext/follow/issues/413)) ([c3675b2](https://github.com/RSSNext/follow/commit/c3675b25886ddd33f232f0c146208cb8f42c0b36)) @@ -276,6 +306,7 @@ * regarding the style issue of selecting subscription types using the Tab and arrow keys ([#525](https://github.com/RSSNext/follow/issues/525)) ([cea7f4a](https://github.com/RSSNext/follow/commit/cea7f4a95ab7336c85613cc551c48639e20b2b9d)) * remove `src` ([9aa16b6](https://github.com/RSSNext/follow/commit/9aa16b62d84f40c90334396d219ee9ab2a371750)) * remove button leading ([84835c5](https://github.com/RSSNext/follow/commit/84835c5ed9df6ac1370b532980929049e8c0d245)) +* remove clamp limit, close [#688](https://github.com/RSSNext/follow/issues/688) ([553ba7d](https://github.com/RSSNext/follow/commit/553ba7d61f48d94b7dd2fa89538ec8bd68956d1b)) * remove comment ([5343ab2](https://github.com/RSSNext/follow/commit/5343ab2dbe3549a740509e150ebb27cad8b770a4)) * remove debug `zh_CN` args ([d650b47](https://github.com/RSSNext/follow/commit/d650b473b966471105c06841876183bc79fad714)) * remove duplicated en and tweak lang sort ([#547](https://github.com/RSSNext/follow/issues/547)) ([2bd3d0b](https://github.com/RSSNext/follow/commit/2bd3d0b4c8c68014771375d97d75e491bfd28385)) @@ -285,8 +316,11 @@ * rename category input composition and style ([1ab3770](https://github.com/RSSNext/follow/commit/1ab3770f0279eb043f7a37a1b5251e5ead0ef0b6)) * reorganize package.json ([b2c48a4](https://github.com/RSSNext/follow/commit/b2c48a49e3789cb3dfd9e9170f5371fc6b25c4b1)) * require title for list form ([#575](https://github.com/RSSNext/follow/issues/575)) ([b5aeada](https://github.com/RSSNext/follow/commit/b5aeada3cbe1f9f1b1a856c5a3a766a886e29d0d)) +* reset feed search, close [#701](https://github.com/RSSNext/follow/issues/701) ([a060986](https://github.com/RSSNext/follow/commit/a060986fa3107f8f5e050b430787014dd9bbdc10)) * reset is archived state on reset ([b701dd6](https://github.com/RSSNext/follow/commit/b701dd6e1badeaf0d0470bcff28abc3fb4057893)) +* reset state ([b0a8831](https://github.com/RSSNext/follow/commit/b0a88312f52b2832d3b449aef15f5835b1cf3afc)) * resizeable panel ([e2664c2](https://github.com/RSSNext/follow/commit/e2664c2dda663343fa8f53536d6b625daaba6103)) +* resolve content blur after modal dragged ([#746](https://github.com/RSSNext/follow/issues/746)) ([a4cbec4](https://github.com/RSSNext/follow/commit/a4cbec45e2af245a3d44648d8b59946aca67ddd1)) * Respect app light/dark mode over OS preference [#228](https://github.com/RSSNext/follow/issues/228) ([ecef3e9](https://github.com/RSSNext/follow/commit/ecef3e961a79ac9c99bf9a419fa7573433148da0)) * rewrite ([3a8cbf2](https://github.com/RSSNext/follow/commit/3a8cbf243903f08392dd1d3eab723b31ff86143a)) * round left only in electron ([2d10811](https://github.com/RSSNext/follow/commit/2d10811273d2053b889b2688189b4212b6e9d6a1)) @@ -308,6 +342,7 @@ * shadow dom style injection in prod ([#270](https://github.com/RSSNext/follow/issues/270)) ([c05d95d](https://github.com/RSSNext/follow/commit/c05d95d495393f1957de609c1ba4de5e707b5a81)) * shiki block style ([75908d4](https://github.com/RSSNext/follow/commit/75908d4a6f43847539accd4bad876983902bd5d8)) * shortcut modal overlay and id ([c210dc9](https://github.com/RSSNext/follow/commit/c210dc900eda2b30e05a9a5434f06810c1a6cd14)) +* ShortcutMode cannot be closed using shortcuts keys ([#708](https://github.com/RSSNext/follow/issues/708)) ([12f3965](https://github.com/RSSNext/follow/commit/12f3965f6ac093d0b88eb5e25f47651649dc6ddd)) * shortcuts kbd shake ([#433](https://github.com/RSSNext/follow/issues/433)) ([7e8f462](https://github.com/RSSNext/follow/commit/7e8f462424e6b2b98b316c9814610034db93f8c9)) * should dismiss when outside (quick new panel) ([675ac84](https://github.com/RSSNext/follow/commit/675ac845d4b9d7c6a71b7891440d2860ca34f0a4)) * should use markdown to render link in rsshub parameter desc ([#505](https://github.com/RSSNext/follow/issues/505)) ([2f64787](https://github.com/RSSNext/follow/commit/2f64787e4bc1bc21bf1c1741ed0179f80c66549a)) @@ -323,6 +358,7 @@ * social media typography ([5d27d29](https://github.com/RSSNext/follow/commit/5d27d29e4bd2791248d6a907a889a4907f0e0d20)) * sort by preferred title, fix [#390](https://github.com/RSSNext/follow/issues/390) ([cc25c67](https://github.com/RSSNext/follow/commit/cc25c6785e98f7a200904bdac2b36ff03cf358dd)) * sort shortcut ([1f8e4a3](https://github.com/RSSNext/follow/commit/1f8e4a3b966891787f05d9b6d0ec0fe327260e49)) +* source content loading status ([6d76504](https://github.com/RSSNext/follow/commit/6d765044fb30df639e5324f65e7e30e6dcb2e772)) * split entry history api and accurate count ([8f3acd6](https://github.com/RSSNext/follow/commit/8f3acd648eab7f44f61c1685b996f02cfe8cc443)) * stable mark all feed list, fixed [#245](https://github.com/RSSNext/follow/issues/245) ([c9d098f](https://github.com/RSSNext/follow/commit/c9d098f4e9bc5d3e3ca5bd026f1947adf6dbcca7)) * stable shadow dom key ([06cafb5](https://github.com/RSSNext/follow/commit/06cafb50d8490a29856c27d9344b76090e9f81af)) @@ -334,8 +370,11 @@ * **style:** add `thumbnail` for video preview ([#632](https://github.com/RSSNext/follow/issues/632)) ([afecb71](https://github.com/RSSNext/follow/commit/afecb71b4657c297613b8ba9be61de61f131ad9f)) * **style:** button align center and ([38a5cb6](https://github.com/RSSNext/follow/commit/38a5cb682dc0c3082664a2192686ad16f68ecec3)) * **styles:** add gap for received button ([f1b86b3](https://github.com/RSSNext/follow/commit/f1b86b3068eaebee1d123a7c1b5cedb4b4ebef4f)) +* **styles:** align the styles of Skeleton and Item ([#749](https://github.com/RSSNext/follow/issues/749)) ([ebceaf6](https://github.com/RSSNext/follow/commit/ebceaf6be4f702bab22749a4305bf52174200dfc)) +* **styles:** user subscription modal list item style ([a954eb9](https://github.com/RSSNext/follow/commit/a954eb93bc74fc6730244e15067888f88743d067)) * **style:** video play button align center ([465f1a6](https://github.com/RSSNext/follow/commit/465f1a6acf6a1d96a28e724f071f8a68a327a56d)) * subcription status & category empty, input value null ([#263](https://github.com/RSSNext/follow/issues/263)) ([93e2ccf](https://github.com/RSSNext/follow/commit/93e2ccfd5831f8a7f43932acd2976785e3adfbff)) +* subscription inbox data ([2b496c4](https://github.com/RSSNext/follow/commit/2b496c4e49f223a9d00381983149e827bdb695fd)) * subview layout ([36a34de](https://github.com/RSSNext/follow/commit/36a34de26caf2ff00847827635eedd3771faadc0)) * supports Windows ([#189](https://github.com/RSSNext/follow/issues/189)) ([486a328](https://github.com/RSSNext/follow/commit/486a328d357317361ef24222fab09eb47e26d07d)) * swap show all and unread only copy, fixed [#307](https://github.com/RSSNext/follow/issues/307) ([2b366d1](https://github.com/RSSNext/follow/commit/2b366d1e28e78649e1a7ed6d221d704bcbe4c520)) @@ -351,10 +390,12 @@ * toc not responsive in dev mode ([ee1894c](https://github.com/RSSNext/follow/commit/ee1894c2d0c420ecf0e63a6dd6bafda57a25a6e3)) * toc range calcation ([2ebcc58](https://github.com/RSSNext/follow/commit/2ebcc58414802cffc84fc25ad30bb9fe272ea773)) * toc scroll logic ([261d12e](https://github.com/RSSNext/follow/commit/261d12e5600028a5bff3b2c1451271ee962403ed)) +* tooltip content of open image and improve i18n support ([#689](https://github.com/RSSNext/follow/issues/689)) ([440de7b](https://github.com/RSSNext/follow/commit/440de7b737f9abcadc68ab1099fd28a8e6710699)) * tooltip in dark mode shadow ([55266ce](https://github.com/RSSNext/follow/commit/55266ce2cceea4e348c33989398f8f9bb92644a7)) * tooltip style in dark mode ([a61c79e](https://github.com/RSSNext/follow/commit/a61c79ee7d4bd73fdf35fa5565c711297a29c7a0)) * transcation table text overflow ([a026c6e](https://github.com/RSSNext/follow/commit/a026c6e34c0eeac1ee6acec1c8181c009ca0ab36)) * translation markdown tooltip wrapper style ([639bace](https://github.com/RSSNext/follow/commit/639bace313311db6319fb1fe168b68af7aa1e8e0)) +* truncate long title in dialog title ([#729](https://github.com/RSSNext/follow/issues/729)) ([8d25987](https://github.com/RSSNext/follow/commit/8d259878c30a987940d7e982c63b37f100008635)) * try fix vercel config ([968dea9](https://github.com/RSSNext/follow/commit/968dea91f474a76298091de6a23f3ba7a11fb22f)) * try to fix linux build ([89eda0f](https://github.com/RSSNext/follow/commit/89eda0f2148b5cc4d45d95f462c6a721022d0bc8)) * try to fix some sentry error ([0b31c1e](https://github.com/RSSNext/follow/commit/0b31c1e998212900dda0044acda8a3d4d5df1189)) @@ -366,6 +407,7 @@ * type error ([c7f11f9](https://github.com/RSSNext/follow/commit/c7f11f99f28bf918aaf8c03b74145b2f9b126a72)) * type error ([5cd41ad](https://github.com/RSSNext/follow/commit/5cd41ad10ccbd241083d6f951509eb0bafe6e25f)) * type error ([60f8347](https://github.com/RSSNext/follow/commit/60f8347eec118176681a9ad7fcab7f45e383fc1b)) +* types ([f0767e2](https://github.com/RSSNext/follow/commit/f0767e2ad93d29db9a82b283f1163e340167be68)) * types ([831f0f8](https://github.com/RSSNext/follow/commit/831f0f892ac32bdb2963267e94c3130805924b59)) * types ([a116dd4](https://github.com/RSSNext/follow/commit/a116dd4018f90886239f7583cbc82b511ff2a902)) * types ([3c5b224](https://github.com/RSSNext/follow/commit/3c5b224904e8db1c8ba6b78cfb87d09cd81de98c)) @@ -374,6 +416,7 @@ * types ([d9458a1](https://github.com/RSSNext/follow/commit/d9458a1850b3e83e9bbb9374d4fc3b6884a24837)) * typing ([a386fd6](https://github.com/RSSNext/follow/commit/a386fd6e97fb98c42b3eedf156c5b167ff67bd34)) * typo ([deb96c5](https://github.com/RSSNext/follow/commit/deb96c538258c939c60762c723d58955899031cf)) +* **ui:** entry title line height ([#608](https://github.com/RSSNext/follow/issues/608)) ([5309491](https://github.com/RSSNext/follow/commit/53094912981ad8cfc79120621725bab1708250f8)) * **ui:** social media gap if no media ([1435632](https://github.com/RSSNext/follow/commit/14356325e42d87c43f33b975fbb1d963cfa67251)) * **ui:** social media unread dot position ([e760676](https://github.com/RSSNext/follow/commit/e760676827297f60a4d00a51f4be98579c93c9f7)) * undo kbd color in dark mode ([2a106ae](https://github.com/RSSNext/follow/commit/2a106ae632e0641d58d0d45b88f61a1c5c6eafa5)) @@ -394,6 +437,7 @@ * use feed enabled condition ([9726d43](https://github.com/RSSNext/follow/commit/9726d4396673e2be02c60ce049ed07c5bf978380)) * use insertedAt as cursor for list ([#580](https://github.com/RSSNext/follow/issues/580)) ([e420451](https://github.com/RSSNext/follow/commit/e420451afc4eba6308ecf72ff710f390ee2b0b8b)) * use official embed player in bilibili video when use web ([#219](https://github.com/RSSNext/follow/issues/219)) ([9177a34](https://github.com/RSSNext/follow/commit/9177a349e087cdc60b22e2338146caaefd377694)) +* useFeedHeaderTitle ([edbdc86](https://github.com/RSSNext/follow/commit/edbdc8626161f9bcc7c93fc372e8a2e247d13a50)) * user avatar use profile data if userId passed, fixed [#550](https://github.com/RSSNext/follow/issues/550) ([176afa7](https://github.com/RSSNext/follow/commit/176afa72ba1e0801ac383982f826cc19b215b242)) * user button color in dark mode ([04e3c38](https://github.com/RSSNext/follow/commit/04e3c386c5699e6b0907de2a98701668fc7f278b)) * user modal list padding ([992ea15](https://github.com/RSSNext/follow/commit/992ea1594af02e3815adae2fe99de4f205543239)) @@ -401,6 +445,7 @@ * userActions in feed store ([8da4fb7](https://github.com/RSSNext/follow/commit/8da4fb71d9cc14832bc985cf8c1bd6f04dbe4e4c)) * video preview ([e38820c](https://github.com/RSSNext/follow/commit/e38820c1aa2294f45e05d331bf4bce0e4d8efb44)) * view icon color in dark mode ([991bff7](https://github.com/RSSNext/follow/commit/991bff7660e93b872f1398c89c0fe4316f4327d9)) +* view source content in picture view ([16938f6](https://github.com/RSSNext/follow/commit/16938f60786f8496152361405c0fcff4635f7d59)) * virtuosoitem height zero issue ([3c5c7ba](https://github.com/RSSNext/follow/commit/3c5c7babc9b3f83ef89ef1007f25d7b3ccb8f6a1)) * wait language load then switch to target language ([bbe4ea6](https://github.com/RSSNext/follow/commit/bbe4ea66e75a8911e9ef39764d02d22251ba743e)) * wallet table latyout ([6c60dd2](https://github.com/RSSNext/follow/commit/6c60dd265245d08d622c59d035d2124285ff68f1)) @@ -413,6 +458,7 @@ * windows multi-display ([7490cd1](https://github.com/RSSNext/follow/commit/7490cd12d0e42a7f41931acd9d77bf64be39a26d)) * **windows:** dont remove locale ([7305eba](https://github.com/RSSNext/follow/commit/7305eba3fee218330818d96ca155f833aa99d631)) * **windows:** skip remove locle ([5df82d0](https://github.com/RSSNext/follow/commit/5df82d0c0f98bebb6e78a694a6ceda3644eb36ef)) +* wrong opening status of newly added feed ([#726](https://github.com/RSSNext/follow/issues/726)) ([2520ddb](https://github.com/RSSNext/follow/commit/2520ddb0f4f1923b729ae707a703713f1a158f06)) * wrong text wrap ([#316](https://github.com/RSSNext/follow/issues/316)) ([0cee7ef](https://github.com/RSSNext/follow/commit/0cee7eff25ed1058b108f1c7a9c643ea17b479c0)) * wtf, cursor deleted my code ([1852d1e](https://github.com/RSSNext/follow/commit/1852d1ee812567c473ff26d316b93d1ccf8e8a88)) * zero tipUsers ([7f994d7](https://github.com/RSSNext/follow/commit/7f994d7a21080468cb07908b4b8fc694ebfeba37)) @@ -441,6 +487,7 @@ * add more words i18n ([#516](https://github.com/RSSNext/follow/issues/516)) ([e2b8ec8](https://github.com/RSSNext/follow/commit/e2b8ec88624ad1e8e7f6136a624fc284ae3fb77b)) * add object-cover to feed icon, add zh-HK and zh-TW errors lang ([#508](https://github.com/RSSNext/follow/issues/508)) ([9351a8f](https://github.com/RSSNext/follow/commit/9351a8fe735977ae02320370f9aa6a83854d7adf)) * add og image, fixed [#242](https://github.com/RSSNext/follow/issues/242) ([5d4e958](https://github.com/RSSNext/follow/commit/5d4e9586569e4afe212138d2001ed9007ce9950b)) +* add overflow tooltip for feed title ([a89ad8b](https://github.com/RSSNext/follow/commit/a89ad8be84384c1851587d02f6b21ce64ad24bdb)) * add player download src ([fc50751](https://github.com/RSSNext/follow/commit/fc5075139f2f82a66c703349a719927c35b11b09)) * add preview image bottom indicator ([bbc1591](https://github.com/RSSNext/follow/commit/bbc15913e8a1afd148c4c70a8056c64d46587791)) * add readability action rules ([5e8fb17](https://github.com/RSSNext/follow/commit/5e8fb17f4a849abd755d92d32d3e5e1a76a2d2ab)) @@ -476,6 +523,7 @@ * context menu of adding feeds to lists ([afb79a2](https://github.com/RSSNext/follow/commit/afb79a27fba87d43e62ea06c3a64267ac3d7f4e4)) * context sub menu ([2d18c53](https://github.com/RSSNext/follow/commit/2d18c53de0cb8c99336d0e915941b1fdee36df98)) * copy logo svg ([512699c](https://github.com/RSSNext/follow/commit/512699c07080f3064f984f23a21e28356ef9fcc0)) +* **corner-player:** support now playing ([#717](https://github.com/RSSNext/follow/issues/717)) ([553f71b](https://github.com/RSSNext/follow/commit/553f71b1babb7a483fe8ddef741e281f1eb77730)) * custom feed title ([#300](https://github.com/RSSNext/follow/issues/300)) ([501e2f4](https://github.com/RSSNext/follow/commit/501e2f44c1d3eb9a1a316549faedb2e1288f7fbe)) * date item in entry column ([#199](https://github.com/RSSNext/follow/issues/199)) ([9d5a811](https://github.com/RSSNext/follow/commit/9d5a81112e873f5b422356fa0b3fcf526abb84e5)) * dayjs locale ([6ed0a3b](https://github.com/RSSNext/follow/commit/6ed0a3bf3a937a95985c98bb24c4bc23f6b776de)) @@ -526,7 +574,11 @@ * **i18n:** add Spanish language support ([#400](https://github.com/RSSNext/follow/issues/400)) ([6b7823d](https://github.com/RSSNext/follow/commit/6b7823d9b314509f209516b1d7412446ff4ac1a3)) * **i18n:** add zh-CN i18n for external page ([#399](https://github.com/RSSNext/follow/issues/399)) ([49a5c50](https://github.com/RSSNext/follow/commit/49a5c50236d51c3c728bb51cd19f34915291e59a)) * **i18n:** added Turkish language ([#544](https://github.com/RSSNext/follow/issues/544)) ([3751363](https://github.com/RSSNext/follow/commit/3751363d45af3096ccefb81bf60ac72040fce505)) +* **i18n:** Chinese: Update `errors` ([#687](https://github.com/RSSNext/follow/issues/687)) ([368d232](https://github.com/RSSNext/follow/commit/368d23250817bb4033168d8736f8e0ed5cd9475f)) +* **i18n:** Chinese: Update translation ([#679](https://github.com/RSSNext/follow/issues/679)) ([36593cc](https://github.com/RSSNext/follow/commit/36593cc05a1b94545266e65008ef4a52f80cfbfe)) +* **i18n:** Chinese: webhook action setting ([#705](https://github.com/RSSNext/follow/issues/705)) ([1d63489](https://github.com/RSSNext/follow/commit/1d6348919f850f28c007a0e589deb7a29b56ec25)) * **i18n:** complete Traditional Chinese translation for native file ([#506](https://github.com/RSSNext/follow/issues/506)) ([2059329](https://github.com/RSSNext/follow/commit/2059329691b375a73cd9cb4f2389b68bbb544e41)) +* **i18n:** conditional display of 'browser' or 'new tab' ([#692](https://github.com/RSSNext/follow/issues/692)) ([213a4bc](https://github.com/RSSNext/follow/commit/213a4bce2c22eba336981e57c3a2ebd321de63da)) * **i18n:** fill out and optimized partial Chinese translations ([#431](https://github.com/RSSNext/follow/issues/431)) ([5f87190](https://github.com/RSSNext/follow/commit/5f87190f018fea7f34c3ccbfad081fd8b855f5b8)) * **i18n:** improve zh-CN ([#410](https://github.com/RSSNext/follow/issues/410)) ([0b0304e](https://github.com/RSSNext/follow/commit/0b0304eaa1dfa8396e78612a9a6a50653ce9669e)) * **i18n:** Korean and fallback language name ([#582](https://github.com/RSSNext/follow/issues/582)) ([2ae12c9](https://github.com/RSSNext/follow/commit/2ae12c9d2b976c8165414cc74c7494b2cfd7ea7c)) @@ -535,9 +587,14 @@ * **i18n:** Update Chinese Translation ([#572](https://github.com/RSSNext/follow/issues/572)) ([d24139b](https://github.com/RSSNext/follow/commit/d24139b82233ea04674c8b93ddee323d2c84a8ef)) * **i18n:** zh-CN: context menu of adding feeds to lists ([#661](https://github.com/RSSNext/follow/issues/661)) ([c3b2fa9](https://github.com/RSSNext/follow/commit/c3b2fa9274ef1e199e66d07c94dc6674f1de6045)) * ignore feed errors within 9 hours ([b71926e](https://github.com/RSSNext/follow/commit/b71926ec286b77dd1b9fc25df459176063b194da)) +* **image:** blurhash for entry media preview, and other adjustment ([b688848](https://github.com/RSSNext/follow/commit/b688848dacc25f3106c90681b3044a69571a54d5)) * impl cmd+b ([ea8a832](https://github.com/RSSNext/follow/commit/ea8a83271e9be37c277540eb605651d7166d2ea4)) * impl masonry in view mark read and scroll to mark read ([4263658](https://github.com/RSSNext/follow/commit/4263658e3240850ca74fcaa666bf8145553f8874)) * improve shiki code block renderer and show language ([590d9cb](https://github.com/RSSNext/follow/commit/590d9cbb94a63f843d00bf54848bba40157d2452)) +* inbox ([#742](https://github.com/RSSNext/follow/issues/742)) ([2fba746](https://github.com/RSSNext/follow/commit/2fba746447c1c10f2d58ac9eb908cd0d6a5fb364)) +* inbox list api ([6da197c](https://github.com/RSSNext/follow/commit/6da197c76bc4d08c80277fc8801a68bfbd413248)) +* inbox set read and unread ([6da8bce](https://github.com/RSSNext/follow/commit/6da8bce04cb0da99efbad473879350131f993c16)) +* inbox unread data updating ([61d9a48](https://github.com/RSSNext/follow/commit/61d9a48310d726205271d1d01026511fb4ccb276)) * integration settings page ([f9f1938](https://github.com/RSSNext/follow/commit/f9f19386b28e853eb03b3ca5bae629d4f6542cb3)) * invitation limitation message ([fa37a0c](https://github.com/RSSNext/follow/commit/fa37a0ca2c8235fb5fd47f96c26de7fdcd762ad8)) * **invitation:** add signout button ([3c0f4e7](https://github.com/RSSNext/follow/commit/3c0f4e779c68a933d57e232d62774fca1c0b86ed)) @@ -563,9 +620,11 @@ * mark read doesn't require manual confirmation if hotkey called, fixed [#293](https://github.com/RSSNext/follow/issues/293) ([6ce06be](https://github.com/RSSNext/follow/commit/6ce06be58d9c5017c77b774cc53fa6076167d563)) * mark read for cateogry in ctx menu ([da79f1c](https://github.com/RSSNext/follow/commit/da79f1c2783fa65f164aaf4942ebfa2156b4bf26)) * markdown heading render ([f3ac1ac](https://github.com/RSSNext/follow/commit/f3ac1ac3c6e2c36203288921f0ea8c3635eec539)) +* masonry item blur hash and html render also ([6f94ec5](https://github.com/RSSNext/follow/commit/6f94ec5027813b0d3804b1b0ab057d484036c8f2)) * modal resize and draggable to absolute position ([aad5eba](https://github.com/RSSNext/follow/commit/aad5eba2edb66039d123e9e60e484b55d9a037df)) * more excluded path params ([3d16aa9](https://github.com/RSSNext/follow/commit/3d16aa9f8b3b369a146537f19ab9a2fe230e9553)) * more i18n text ([6f8acce](https://github.com/RSSNext/follow/commit/6f8acced7bc51d2bb22325506e1c9bc97ee963f7)) +* native menu add `hide` prop ([8c6753d](https://github.com/RSSNext/follow/commit/8c6753d4a66d1e7ad09efcbbca24c8cf51ed8222)) * navigator bar ([56750fd](https://github.com/RSSNext/follow/commit/56750fd1722eaca7416e5c8617fb501fcf055cac)) * new design for mark read in date item ([e5b0583](https://github.com/RSSNext/follow/commit/e5b0583d38e41d81663bec1ee16e0c24cb385d7a)) * new platform icons ([7513130](https://github.com/RSSNext/follow/commit/7513130c17c501f3e2d7c29fc13e2315edb4dc8c)) @@ -577,6 +636,7 @@ * optimize 404 page ([f51b1e2](https://github.com/RSSNext/follow/commit/f51b1e2de9e8d8c3bdea9db79476c17cd7247a4b)) * optimize compact picture entry preview title ([5e6d73a](https://github.com/RSSNext/follow/commit/5e6d73a728164dcb0603e03fbcb9fb1825c5c2ef)) * optimize daily report and report modal for social media ([252962c](https://github.com/RSSNext/follow/commit/252962c188e29293f4b6baca2e99568a064f79f4)) +* optimize no showUnreadCount dot display ([9698fa6](https://github.com/RSSNext/follow/commit/9698fa69d110781d26b542e9e81a51dc7b16805e)) * optimize the style of the profile to maximize the presentation of the content ([96769fb](https://github.com/RSSNext/follow/commit/96769fbe49eb68ea09f1307ac27d0c0d904d0abf)) * parse newsletter embedded `