Skip to content

chore: housekeeping: clean up code and remove unused files#533

Open
NekoCharm01 wants to merge 4 commits intomasterfrom
patch-cleanup
Open

chore: housekeeping: clean up code and remove unused files#533
NekoCharm01 wants to merge 4 commits intomasterfrom
patch-cleanup

Conversation

@NekoCharm01
Copy link
Copy Markdown
Member

@NekoCharm01 NekoCharm01 commented Apr 4, 2026

Summary by Sourcery

重构应用结构和配置,将 Pinia store 迁移到 composable,并移除未使用的类型和工具定义。

Bug 修复:

  • 确保「关注用户最新作品」的获取逻辑使用来自专用 composable store 的共享 Pixiv 客户端实例。
  • 通过对 intersection observer 的 entries 做防护检查,并在访问随机消息数组时进行更严格的类型收窄,修复潜在的运行时错误。

增强:

  • 将 Pinia 及相关状态管理的导入路径从旧的 stores 目录切换到 composables,以构建更加以 composable 为中心的架构。
  • 更新 Nuxt 配置以使用 @bg-dev/nuxt-naiveui,将图标相关处理移动到 modules 配置中,并通过 TypeScript 设置来配置 Vue Pug 支持。
  • 简化或移除 utils 和 server API 文件中未使用的类型导入、常量以及辅助接口,以减少无效代码。
  • 调整 Pug 模板和组件标记,以获得更佳的格式,并在少量可访问性(accessibility)属性上保持一致性。

构建:

  • axiosvue@tabler/icons-vue@types/nodesass-embedded 升级到较新的补丁版本,并新增 @bg-dev/nuxt-naiveui 作为开发依赖。
  • 移除 nuxtjs-naive-ui 以及基于 unplugin 的 Naive UI 自动导入配置,改为使用新的 Nuxt Naive UI 模块。
  • 简化顶层 TypeScript 配置,改为依赖 Nuxt 生成的 tsconfig,并将 Vue 编译器插件相关配置移动到 nuxt.config.ts 中。
Original summary in English

Summary by Sourcery

Refactor application structure and configuration, migrate Pinia stores to composables, and remove unused types and utility definitions.

Bug Fixes:

  • Ensure following latest artworks fetching uses the shared Pixiv client instance from the dedicated composable store.
  • Fix potential runtime errors by guarding intersection observer entries and narrowing random message array access.

Enhancements:

  • Switch Pinia and related state management imports from the legacy stores directory to composables for a more composable-centric architecture.
  • Update Nuxt configuration to use @bg-dev/nuxt-naiveui, move icon handling into the modules section, and configure Vue Pug support via TypeScript settings.
  • Simplify or remove unused type imports, constants, and helper interfaces across utils and server API files to reduce dead code.
  • Adjust Pug templates and component markup for better formatting and minor accessibility attribute consistency.

Build:

  • Bump axios, vue, @tabler/icons-vue, @types/node, and sass-embedded versions to newer patch releases and add @bg-dev/nuxt-naiveui dev dependency.
  • Remove nuxtjs-naive-ui and unplugin-based Naive UI auto-import configuration in favor of the new Nuxt Naive UI module.
  • Simplify top-level TypeScript configuration to rely on Nuxt-generated tsconfig and move Vue compiler plugin configuration into nuxt.config.ts.

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai bot commented Apr 4, 2026

Reviewer's Guide

重构应用的状态管理和构建配置,使其与 Nuxt 4 和基于 composable 的 store 方案保持一致;清理未使用的类型/工具代码;统一 Pug/ARIA 格式;并升级若干前端依赖。

基于 composable 的 Pinia stores 与 Pixiv client 更新后的类图

classDiagram
  class PixivWebClient {
    +number timeout
    +getFollowLatest(p)
    +getRankings(params)
    +searchIllust(params)
    +getUserDetail(userId)
    +getUserIllusts(userId, params)
    +getIllustDetail(illustId)
    +getRecommend(params)
  }

  class usePixivClientStore {
    +PixivWebClient client
  }

  class useUserStore {
    +boolean isLoggedIn
    +string userId
    +string userPixivId
    +string userName
    +string userProfileImg
    +string userProfileImgBig
    +loginWithToken(token)
    +logout()
  }

  class useSideNavStore {
    +boolean isOpened
    +open()
    +close()
    +toggle()
  }

  class useArtworkStore {
    +Map~string_Artwork~ artworkCache
    +Map~string_ArtworkGallery~ galleryCache
    +Artwork current
    +boolean loading
    +fetchArtwork(id)
    +fetchGallery(id)
    +fetchRecommendations(id)
  }

  class useFollowingStore {
    +UserListItem[] publicList
    +UserListItem[] hiddenList
    +ArtworkInfo[] latestIllusts
    +boolean isLoadingPublic
    +boolean isLoadingHidden
    +boolean latestLoading
    +number latestNextPage
    +fetchPublicList()
    +fetchHiddenList()
    +fetchLatest()
  }

  class useHomeStore {
    +ArtworkInfo randomBg
    +boolean loading
    +fetchRandomBackground()
  }

  class useRankingStore {
    +Date date
    +string mode
    +ArtworkRank[] list
    +boolean loading
    +fetchRanking(mode, date)
  }

  class useSearchStore {
    +ArtworkInfo[] results
    +number total
    +boolean loading
    +string keyword
    +number page
    +search(keyword, page)
  }

  class useUserArtworksStore {
    +string[] allIds
    +ArtworkInfo[] currentPageItems
    +number page
    +boolean loading
    +fetchUserArtworks(userId, category, page)
  }

  class useUserProfileStore {
    +Map~string_User~ userCache
    +ArtworkInfo[] illusts
    +ArtworkInfo[] mangas
    +boolean loading
    +fetchUser(userId)
    +fetchUserIllusts(userId)
    +fetchUserMangas(userId)
  }

  usePixivClientStore --> PixivWebClient : wraps
  useUserStore --> usePixivClientStore : may_use
  useArtworkStore --> usePixivClientStore : uses_client
  useFollowingStore --> usePixivClientStore : uses_client
  useHomeStore --> usePixivClientStore : uses_client
  useRankingStore --> usePixivClientStore : uses_client
  useSearchStore --> usePixivClientStore : uses_client
  useUserArtworksStore --> usePixivClientStore : uses_client
  useUserProfileStore --> usePixivClientStore : uses_client

  class useUserStore{
  }
  class useSideNavStore{
  }
Loading

File-Level Changes

Change Details Files
将 Pinia stores 从旧的 ~/stores 路径迁移为基于 composable 的写法,放到 ~/composables 下,并相应更新所有 import。
  • 将 store 文件(session, artwork, home, ranking, search, user-artworks, user-profile, following, pixiv-client)从 app/stores/* 重命名/迁移到 app/composables/*,同时保持它们的 Pinia API 不变。
  • 更新所有组件和页面,使其从 '~/composables/...' 而不是 '~/stores/...' 引入 use*Store composable。
  • 在 following store 拉取最新关注作品时,补充缺失的 pixiv-client 获取逻辑。
app/composables/session.ts
app/composables/artwork.ts
app/composables/home.ts
app/composables/ranking.ts
app/composables/search.ts
app/composables/user-artworks.ts
app/composables/user-profile.ts
app/composables/following.ts
app/composables/pixiv-client.ts
app/app.vue
app/components/AuthorCard.vue
app/components/Comment/Comment.vue
app/components/Comment/CommentSubmit.vue
app/components/SideNav/SideNav.vue
app/components/Artwork/ArtworkListByUser.vue
app/components/FollowUserCard.vue
app/pages/index.vue
app/pages/login.vue
app/pages/ranking.vue
app/pages/search/[keyword]/[p].vue
app/pages/users/[id]/index.vue
app/pages/users/[id]/following.vue
app/pages/following/latest.vue
按照最新生态约定更新 Nuxt、Naive UI、图标以及相关工具链配置。
  • 从使用 nuxtjs-naive-ui + Vite 层面的 unplugin-auto-import / unplugin-vue-components 配置,切换为使用 @bg-dev/nuxt-naiveui Nuxt 模块,并移除手动 Vite 插件配置。
  • 通过 Nuxt modules 注册 unplugin-icons/nuxt,而不是通过 Vite 插件。
  • 将 Vue Pug 语言插件配置从根目录 tsconfig.jsonnuxt.configvite.vue.template 部分迁移到 nuxt.config 中的 typescript.tsConfig.vueCompilerOptions
  • 简化 i18n 配置:删除懒加载和 langDir 设置,仅保留一个 zh-Hans 语言环境。
  • 删除在新配置下已不再需要的、由 app 自动生成的声明和类型文件。
nuxt.config.ts
tsconfig.json
package.json
.vscode/settings.json
app/auto-imports.d.ts
app/components.d.ts
app/composables/states.ts
app/types/Artworks.ts
app/types/Comment.ts
app/types/Users.ts
app/types/index.ts
app/utils/constants.ts
梳理组件的 Pug 模板和 ARIA 属性,在不改变行为的前提下提升可读性和可访问性。
  • 在 Pug 模板中(按钮、RouterLink、NTabPane、NPagination、ArtworkList 等)统一属性顺序和换行风格。
  • 重新缩进 SiteHeader 中用户下拉菜单的标记结构,并修正注释对齐问题。
  • 新增或明确 ARIA 属性,并在合适的位置用逗号分隔,同时保证现有行为保持不变。
app/components/SiteHeader.vue
app/pages/users/[id]/index.vue
app/pages/users/[id]/following.vue
app/components/Artwork/ArtworkLargeCard.vue
app/pages/search/[keyword]/[p].vue
app/pages/artworks/[id].vue
app/components/AuthorCard.vue
app/pages/following/latest.vue
app/components/SideNav/SideNav.vue
app/pages/index.vue
app/pages/login.vue
app/pages/ranking.vue
移除未使用的类型、常量和 import,并做了一些小的安全性/清理改动。
  • 删除旧版 pixiv-client 中未使用的接口和类型(如 UgoiraMeta)以及若干 app 级别的类型文件。
  • 从各个工具函数和服务端处理器中移除未使用的 import,例如 IllustTypeArtworkUrlsArtworkInfo/ArtworkInfoOrAdPixivUserpixivAjaxPXIMG_BASEURL_I 等。
  • 简化 pximg URL 替换逻辑和泛型 sortArtList 实现,只依赖 id,而不再依赖额外的类型。
  • DeferLoad.vue 中调整 useIntersectionObserver 的回调签名,避免解构参数,并处理可能缺失的 entry。
  • 确保 ErrorPage 的 randomMsg 使用非空断言访问 msgList 条目。
  • 修改 ajax 工具,使用 axios 默认导出进行导入,同时保留 AxiosRequestConfig 类型的导入。
app/utils/pixiv-client.ts
app/utils/pximg.ts
app/utils/index.ts
app/utils/ajax.ts
app/components/Artwork/ArtworkCard.vue
app/components/Artwork/ArtworkLargeCard.vue
app/composables/userData.ts
server/api/illust/random.ts
server/api/user.ts
app/components/DeferLoad.vue
app/components/ErrorPage.vue
app/api/pixiv-client.ts
server/middleware/pixiv-proxy.ts
server/middleware/pximg-proxy.ts
app/utils/UgoiraPlayer.ts
更新依赖和元数据以匹配重构后的架构。
  • 升级 axios、vue、@tabler/icons-vue@types/nodesass-embedded 以及其他一些依赖到更新的补丁版本。
  • 新增 @bg-dev/nuxt-naiveui 作为依赖,并移除 nuxtjs-naive-ui
  • 更新 pnpm-lock.yaml 以反映新的依赖关系图。
  • 更新贡献者列表,将 “AlPha5130” 替换为 “NekoCharm01”。
package.json
pnpm-lock.yaml

Tips and commands

Interacting with Sourcery

  • 触发新的一轮审查: 在 pull request 中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审查评论即可继续对话。
  • 从审查评论生成 GitHub issue: 在某条审查评论下回复,要求 Sourcery 从该评论生成一个 issue。你也可以直接在评论中回复 @sourcery-ai issue 来从该评论创建 issue。
  • 生成 pull request 标题: 在 pull request 标题中任意位置写上 @sourcery-ai,即可随时生成标题。你也可以在 pull request 中评论 @sourcery-ai title 来(重新)生成标题。
  • 生成 pull request 摘要: 在 pull request 描述(body)中任意位置写上 @sourcery-ai summary,即可在对应位置生成 PR 摘要。你也可以在 pull request 中评论 @sourcery-ai summary 来在任意时间(重新)生成摘要。
  • 生成审查者指南: 在 pull request 中评论 @sourcery-ai guide,即可随时(重新)生成审查者指南。
  • 解决所有 Sourcery 评论: 在 pull request 中评论 @sourcery-ai resolve,以标记所有 Sourcery 评论为已解决。如果你已经处理完所有评论且不想再看到它们,这会很有用。
  • 忽略所有 Sourcery 审查: 在 pull request 中评论 @sourcery-ai dismiss,以忽略所有现有的 Sourcery 审查。尤其适用于你想从头开始一轮新的审查时——别忘了再评论 @sourcery-ai review 以触发新的审查!

Customizing Your Experience

打开你的 dashboard 以:

  • 启用或禁用审查功能,例如 Sourcery 自动生成的 pull request 摘要、审查者指南等。
  • 更改审查语言。
  • 添加、删除或编辑自定义审查说明。
  • 调整其他审查相关设置。

Getting Help

Original review guide in English

Reviewer's Guide

Refactors the app’s state management and build configuration to align with Nuxt 4 + composables-based stores, cleans up unused/types/utility code, standardizes Pug/ARIA formatting, and bumps several frontend dependencies.

Updated class diagram for composables-based Pinia stores and Pixiv client

classDiagram
  class PixivWebClient {
    +number timeout
    +getFollowLatest(p)
    +getRankings(params)
    +searchIllust(params)
    +getUserDetail(userId)
    +getUserIllusts(userId, params)
    +getIllustDetail(illustId)
    +getRecommend(params)
  }

  class usePixivClientStore {
    +PixivWebClient client
  }

  class useUserStore {
    +boolean isLoggedIn
    +string userId
    +string userPixivId
    +string userName
    +string userProfileImg
    +string userProfileImgBig
    +loginWithToken(token)
    +logout()
  }

  class useSideNavStore {
    +boolean isOpened
    +open()
    +close()
    +toggle()
  }

  class useArtworkStore {
    +Map~string_Artwork~ artworkCache
    +Map~string_ArtworkGallery~ galleryCache
    +Artwork current
    +boolean loading
    +fetchArtwork(id)
    +fetchGallery(id)
    +fetchRecommendations(id)
  }

  class useFollowingStore {
    +UserListItem[] publicList
    +UserListItem[] hiddenList
    +ArtworkInfo[] latestIllusts
    +boolean isLoadingPublic
    +boolean isLoadingHidden
    +boolean latestLoading
    +number latestNextPage
    +fetchPublicList()
    +fetchHiddenList()
    +fetchLatest()
  }

  class useHomeStore {
    +ArtworkInfo randomBg
    +boolean loading
    +fetchRandomBackground()
  }

  class useRankingStore {
    +Date date
    +string mode
    +ArtworkRank[] list
    +boolean loading
    +fetchRanking(mode, date)
  }

  class useSearchStore {
    +ArtworkInfo[] results
    +number total
    +boolean loading
    +string keyword
    +number page
    +search(keyword, page)
  }

  class useUserArtworksStore {
    +string[] allIds
    +ArtworkInfo[] currentPageItems
    +number page
    +boolean loading
    +fetchUserArtworks(userId, category, page)
  }

  class useUserProfileStore {
    +Map~string_User~ userCache
    +ArtworkInfo[] illusts
    +ArtworkInfo[] mangas
    +boolean loading
    +fetchUser(userId)
    +fetchUserIllusts(userId)
    +fetchUserMangas(userId)
  }

  usePixivClientStore --> PixivWebClient : wraps
  useUserStore --> usePixivClientStore : may_use
  useArtworkStore --> usePixivClientStore : uses_client
  useFollowingStore --> usePixivClientStore : uses_client
  useHomeStore --> usePixivClientStore : uses_client
  useRankingStore --> usePixivClientStore : uses_client
  useSearchStore --> usePixivClientStore : uses_client
  useUserArtworksStore --> usePixivClientStore : uses_client
  useUserProfileStore --> usePixivClientStore : uses_client

  class useUserStore{
  }
  class useSideNavStore{
  }
Loading

File-Level Changes

Change Details Files
Migrate Pinia stores from the legacy ~/stores path to composables under ~/composables and update all imports accordingly.
  • Rename store files (session, artwork, home, ranking, search, user-artworks, user-profile, following, pixiv-client) from app/stores/* to app/composables/* while keeping their Pinia API intact.
  • Adjust all components and pages to import use*Store composables from '/composables/...'' instead of '/stores/...'.
  • Add missing pixiv-client acquisition in following store when fetching latest followed artworks.
app/composables/session.ts
app/composables/artwork.ts
app/composables/home.ts
app/composables/ranking.ts
app/composables/search.ts
app/composables/user-artworks.ts
app/composables/user-profile.ts
app/composables/following.ts
app/composables/pixiv-client.ts
app/app.vue
app/components/AuthorCard.vue
app/components/Comment/Comment.vue
app/components/Comment/CommentSubmit.vue
app/components/SideNav/SideNav.vue
app/components/Artwork/ArtworkListByUser.vue
app/components/FollowUserCard.vue
app/pages/index.vue
app/pages/login.vue
app/pages/ranking.vue
app/pages/search/[keyword]/[p].vue
app/pages/users/[id]/index.vue
app/pages/users/[id]/following.vue
app/pages/following/latest.vue
Update Nuxt, Naive UI, icons, and tooling configuration to the latest ecosystem conventions.
  • Switch from 'nuxtjs-naive-ui' + Vite-level unplugin-auto-import/unplugin-vue-components setup to '@bg-dev/nuxt-naiveui' Nuxt module and remove manual Vite plugin configuration.
  • Register 'unplugin-icons/nuxt' via Nuxt modules instead of Vite plugins.
  • Move Vue Pug language plugin configuration from root tsconfig.json and nuxt.config vite.vue.template section into nuxt.config typescript.tsConfig.vueCompilerOptions.
  • Simplify i18n config by removing lazy loading and langDir settings, keeping a single zh-Hans locale.
  • Remove obsolete app auto-generated declaration and type files that are no longer needed with the new setup.
nuxt.config.ts
tsconfig.json
package.json
.vscode/settings.json
app/auto-imports.d.ts
app/components.d.ts
app/composables/states.ts
app/types/Artworks.ts
app/types/Comment.ts
app/types/Users.ts
app/types/index.ts
app/utils/constants.ts
Tidy components’ Pug templates and ARIA attributes for better readability and accessibility without changing behavior.
  • Normalize attribute ordering and line breaks in Pug templates (buttons, RouterLink, NTabPane, NPagination, ArtworkList, etc.) to a consistent style.
  • Re-indent user dropdown menu markup in the SiteHeader and correct comment alignment.
  • Add or clarify ARIA attributes and separate them with commas where appropriate while keeping existing behavior.
app/components/SiteHeader.vue
app/pages/users/[id]/index.vue
app/pages/users/[id]/following.vue
app/components/Artwork/ArtworkLargeCard.vue
app/pages/search/[keyword]/[p].vue
app/pages/artworks/[id].vue
app/components/AuthorCard.vue
app/pages/following/latest.vue
app/components/SideNav/SideNav.vue
app/pages/index.vue
app/pages/login.vue
app/pages/ranking.vue
Remove unused types, constants, and imports, and perform small safety/cleanup tweaks.
  • Delete unused interfaces and types such as UgoiraMeta in the old pixiv-client and several app-level types files.
  • Drop unused imports like IllustType, ArtworkUrls, ArtworkInfo/ArtworkInfoOrAd, PixivUser, pixivAjax, PXIMG_BASEURL_I from various utils and server handlers.
  • Simplify pximg URL replacement logic and generic sortArtList implementation to only rely on id without external types.
  • Adjust useIntersectionObserver callback signature in DeferLoad.vue to avoid destructuring and handle potentially missing entries.
  • Ensure ErrorPage randomMsg accesses msgList entries with non-null assertion.
  • Change ajax util to import the axios default export while retaining AxiosRequestConfig type import.
app/utils/pixiv-client.ts
app/utils/pximg.ts
app/utils/index.ts
app/utils/ajax.ts
app/components/Artwork/ArtworkCard.vue
app/components/Artwork/ArtworkLargeCard.vue
app/composables/userData.ts
server/api/illust/random.ts
server/api/user.ts
app/components/DeferLoad.vue
app/components/ErrorPage.vue
app/api/pixiv-client.ts
server/middleware/pixiv-proxy.ts
server/middleware/pximg-proxy.ts
app/utils/UgoiraPlayer.ts
Update dependencies and metadata to match the refactored architecture.
  • Bump axios, vue, @tabler/icons-vue, @types/node, sass-embedded, and a few other dependencies to newer patch versions.
  • Add '@bg-dev/nuxt-naiveui' devDependency and remove 'nuxtjs-naive-ui'.
  • Update pnpm-lock.yaml to reflect the new dependency graph.
  • Update contributors list to replace 'AlPha5130' with 'NekoCharm01'.
package.json
pnpm-lock.yaml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我发现了两个问题,并给出了一些整体性的反馈:

  • DeferLoad.vue 中,useIntersectionObserver 回调现在直接访问 entries[0];建议在 !entries.length 时尽早 return,这样可以避免当观察器在 entries 为空数组时触发而导致的潜在 undefined 访问。
  • ErrorPage.vue 中,当随机到相同的消息时,randomMsg() 会递归调用自身;如果增加一个 msgList.length <= 1 的短路判断,就可以避免不必要的递归(以及在只有一条消息时可能出现的无限递归)。
给 AI Agent 的提示
Please address the comments from this code review:

## Overall Comments
- In `DeferLoad.vue`, the `useIntersectionObserver` callback now indexes `entries[0]` directly; consider early-returning when `!entries.length` to avoid potential undefined access if the observer fires with an empty entries array.
- In `ErrorPage.vue`, `randomMsg()` recursively calls itself when the same message is chosen; adding a short-circuit for `msgList.length <= 1` would prevent unnecessary recursion (and a potential infinite loop if there is ever only a single message).

## Individual Comments

### Comment 1
<location path="nuxt.config.ts" line_range="44-47" />
<code_context>
   i18n: {
     locales: [{ code: 'zh-Hans', file: 'zh-Hans.json' }],
     defaultLocale: 'zh-Hans',
-    lazy: true,
-    langDir: '../app/locales',
     strategy: 'no_prefix',
   },

</code_context>
<issue_to_address>
**issue (bug_risk):** Using `file` in `locales` without `langDir` may break locale loading after moving config from `app/locales`.

The config still references `file: 'zh-Hans.json'`, but `langDir` has been removed. In @nuxtjs/i18n v10, using `file` relies on `langDir` (defaulting to `locales/` at the project root), whereas this was previously set to `../app/locales`. Unless the JSON file has been moved to the default directory, this will prevent the locale from loading. Please either restore `langDir` to the folder containing `zh-Hans.json` or switch to inlined messages if the file is no longer used.
</issue_to_address>

### Comment 2
<location path="app/components/ErrorPage.vue" line_range="77" />
<code_context>
 const msg = ref('')
 function randomMsg(): void {
-  const newValue = msgList[Math.floor(Math.random() * msgList.length)]
+  const newValue = msgList[Math.floor(Math.random() * msgList.length)]!
   if (newValue !== msg.value) {
     msg.value = newValue
</code_context>
<issue_to_address>
**suggestion:** Non-null assertion on `msgList[...]` hides potential empty-list issues and keeps the existing recursion pitfall.

Using `!` just silences TS but still risks a runtime error if `msgList` is empty and unnecessary recursion if it has only one element. Consider returning early when `msgList.length === 0`, and in the single-item case, just assign that item directly. This removes the need for `!` and makes the function more robust to future changes in `msgList`.

Suggested implementation:

```
const msg = ref('')
function randomMsg(): void {
  const { length } = msgList
  if (length === 0) {
    // Nothing to show
    return
  }

  if (length === 1) {
    // Only one possible message, avoid recursion/extra work
    msg.value = msgList[0]
    return
  }

  const newIndex = Math.floor(Math.random() * length)
  const newValue = msgList[newIndex]
  if (newValue !== msg.value) {
    msg.value = newValue
  } else {

```

The current `else { ... }` branch likely contains a recursive `randomMsg()` call to avoid repeating the same message. With the above `length === 1` guard, that recursion should no longer be needed for the single-item case. Consider updating the `else` branch to either:
1. Return early (do nothing if the same message is randomly chosen), or
2. Select a different index deterministically (e.g. `(newIndex + 1) % length`) instead of recursively calling `randomMsg()`.

Adjust the `else` block accordingly to avoid unbounded recursion if `msgList` is ever changed back to a single-element list.
</issue_to_address>

Sourcery 对开源项目是免费的——如果你觉得这个 Review 有帮助,欢迎分享 ✨
帮我变得更有用!请对每条评论点 👍 或 👎,我会根据你的反馈改进后续的 Review。
Original comment in English

Hey - I've found 2 issues, and left some high level feedback:

  • In DeferLoad.vue, the useIntersectionObserver callback now indexes entries[0] directly; consider early-returning when !entries.length to avoid potential undefined access if the observer fires with an empty entries array.
  • In ErrorPage.vue, randomMsg() recursively calls itself when the same message is chosen; adding a short-circuit for msgList.length <= 1 would prevent unnecessary recursion (and a potential infinite loop if there is ever only a single message).
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `DeferLoad.vue`, the `useIntersectionObserver` callback now indexes `entries[0]` directly; consider early-returning when `!entries.length` to avoid potential undefined access if the observer fires with an empty entries array.
- In `ErrorPage.vue`, `randomMsg()` recursively calls itself when the same message is chosen; adding a short-circuit for `msgList.length <= 1` would prevent unnecessary recursion (and a potential infinite loop if there is ever only a single message).

## Individual Comments

### Comment 1
<location path="nuxt.config.ts" line_range="44-47" />
<code_context>
   i18n: {
     locales: [{ code: 'zh-Hans', file: 'zh-Hans.json' }],
     defaultLocale: 'zh-Hans',
-    lazy: true,
-    langDir: '../app/locales',
     strategy: 'no_prefix',
   },

</code_context>
<issue_to_address>
**issue (bug_risk):** Using `file` in `locales` without `langDir` may break locale loading after moving config from `app/locales`.

The config still references `file: 'zh-Hans.json'`, but `langDir` has been removed. In @nuxtjs/i18n v10, using `file` relies on `langDir` (defaulting to `locales/` at the project root), whereas this was previously set to `../app/locales`. Unless the JSON file has been moved to the default directory, this will prevent the locale from loading. Please either restore `langDir` to the folder containing `zh-Hans.json` or switch to inlined messages if the file is no longer used.
</issue_to_address>

### Comment 2
<location path="app/components/ErrorPage.vue" line_range="77" />
<code_context>
 const msg = ref('')
 function randomMsg(): void {
-  const newValue = msgList[Math.floor(Math.random() * msgList.length)]
+  const newValue = msgList[Math.floor(Math.random() * msgList.length)]!
   if (newValue !== msg.value) {
     msg.value = newValue
</code_context>
<issue_to_address>
**suggestion:** Non-null assertion on `msgList[...]` hides potential empty-list issues and keeps the existing recursion pitfall.

Using `!` just silences TS but still risks a runtime error if `msgList` is empty and unnecessary recursion if it has only one element. Consider returning early when `msgList.length === 0`, and in the single-item case, just assign that item directly. This removes the need for `!` and makes the function more robust to future changes in `msgList`.

Suggested implementation:

```
const msg = ref('')
function randomMsg(): void {
  const { length } = msgList
  if (length === 0) {
    // Nothing to show
    return
  }

  if (length === 1) {
    // Only one possible message, avoid recursion/extra work
    msg.value = msgList[0]
    return
  }

  const newIndex = Math.floor(Math.random() * length)
  const newValue = msgList[newIndex]
  if (newValue !== msg.value) {
    msg.value = newValue
  } else {

```

The current `else { ... }` branch likely contains a recursive `randomMsg()` call to avoid repeating the same message. With the above `length === 1` guard, that recursion should no longer be needed for the single-item case. Consider updating the `else` branch to either:
1. Return early (do nothing if the same message is randomly chosen), or
2. Select a different index deterministically (e.g. `(newIndex + 1) % length`) instead of recursively calling `randomMsg()`.

Adjust the `else` block accordingly to avoid unbounded recursion if `msgList` is ever changed back to a single-element list.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant