Skip to content

perf: improve perf#180

Merged
roitium merged 17 commits into
devfrom
perf/search-perf-improve
Jan 28, 2026
Merged

perf: improve perf#180
roitium merged 17 commits into
devfrom
perf/search-perf-improve

Conversation

@roitium
Copy link
Copy Markdown
Collaborator

@roitium roitium commented Jan 28, 2026

Summary by CodeRabbit

发布说明

  • New Features

    • 全局键盘支持与更可靠的播放器初始化;播放列表支持布局动画准备调用以改善删除动画体验
  • Performance

    • 搜索输入采用延迟更新减少抖动
    • 标签页切换使用并发过渡提升流畅度
    • 歌词滚动与列表渲染重构以提升帧率与响应性
  • Documentation

    • 新增详尽的 React Native 性能与实践指南集合
  • Chores

    • 版本更新至 2.2.3;添加/更新运行时依赖和配置调整

✏️ Tip: You can customize this high-level summary in your review settings.

@roitium roitium added the enhancement New feature or request label Jan 28, 2026
@safedep
Copy link
Copy Markdown

safedep Bot commented Jan 28, 2026

SafeDep Report Summary

Green Malicious Packages Badge Green Vulnerable Packages Badge Green Risky License Badge

Package Details
Package Malware Vulnerability Risky License Report
icon @oxfmt/darwin-arm64 @ 0.27.0
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon @oxfmt/darwin-x64 @ 0.27.0
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon @oxfmt/linux-arm64-gnu @ 0.27.0
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon @oxfmt/linux-arm64-musl @ 0.27.0
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon @oxfmt/linux-x64-gnu @ 0.27.0
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon @oxfmt/linux-x64-musl @ 0.27.0
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon @oxfmt/win32-arm64 @ 0.27.0
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon @oxfmt/win32-x64 @ 0.27.0
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon @react-native-community/cli @ 20.1.1
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon @react-native-community/cli-clean @ 20.1.1
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon @react-native-community/cli-config @ 20.1.1
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon @react-native-community/cli-config-android @ 20.1.1
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon @react-native-community/cli-config-apple @ 20.1.1
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon @react-native-community/cli-doctor @ 20.1.1
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon @react-native-community/cli-platform-android @ 20.1.1
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon @react-native-community/cli-platform-apple @ 20.1.1
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon @react-native-community/cli-platform-ios @ 20.1.1
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon @react-native-community/cli-server-api @ 20.1.1
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon @react-native-community/cli-tools @ 20.1.1
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon @react-native-community/cli-types @ 20.1.1
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon @roitium/expo-orpheus @ 0.11.2
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon oxfmt @ 0.27.0
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon react-native-keyboard-controller @ 1.20.4
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon strict-url-sanitise @ 0.0.1
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗
icon tinypool @ 2.0.0
pnpm-lock.yaml
ok icon
ok icon
ok icon
🔗

This report is generated by SafeDep Github App

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 28, 2026

Important

Review skipped

Too many files!

This PR contains 159 files, which is 59 over the limit of 100.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • 🔍 Trigger a full review

Walkthrough

该 PR 大量新增 React Native 最佳实践与规则文档,并在应用中引入基于 Zustand 的播放器存储(usePlayerStore),将若干搜索/标签页更新为并发模式(useDeferredValue / startTransition),改造 LocalTrackList 为 forwardRef 并新增布局动画准备调用,同时简化全局键盘动画处理与提供者结构。

Changes

Cohort / File(s) 变更摘要
Skills — React Native 最佳实践
.agents/skills/react-native-best-practices/SKILL.md, .../references/*.md
新增大量文档参考(打包、树摇、Hermes mmap、代码分割、动画、内存、原生模块、TTI 等),纯文档改动。
Skills — Vercel React Native 规则集
.agents/skills/vercel-react-native-skills/SKILL.md, .../rules/*.md
新增规则集与具体实践文件(列表性能、动画、导航、UI、状态管理、monorepo 等),纯文档。
Skill 引用文件
.agent/skills/*, .continue/skills/*, .github/skills/*, .opencode/skills/*, skills/*
新增若干短引用文件,指向 .agents/skills 下的新技能目录。
播放器状态管理(Zustand)
src/hooks/stores/usePlayerStore.ts, src/hooks/player/useCurrentTrack.ts, src/hooks/player/useCurrentTrackId.ts, src/hooks/player/useIsCurrentTrack.ts
新增 usePlayerStore,公开 initialize()/sync() 等;若干现有钩子改为从本地 store 读取,简化并新增同步/错误处理逻辑。
并发/搜索优化
src/app/(tabs)/index.tsx, src/app/playlist/local/[id].tsx, src/features/library/local/LocalPlaylistList.tsx
将防抖/即时更新替换为 useDeferredValue 驱动的延迟搜索渲染,并在列表渲染时通过不透明度提示“正在同步/未就绪”状态。
标签页切换并发化
src/app/(tabs)/library/[tab].tsx
使用 React startTransition 包装标签索引更新以减轻主线程阻塞。
LocalTrackList forwardRef + 布局动画准备
src/features/playlist/local/components/LocalTrackList.tsx, src/app/playlist/local/[id].tsx
将 LocalTrackList 改为 forwardRef,暴露 LocalTrackListRef.prepareForLayoutAnimationRender 并在删除等操作前调用以准备布局动画。
键盘/模态处理重构 & Provider 调整
src/components/common/AnimatedModalOverlay.tsx, src/components/providers.tsx, src/app/_layout.tsx
用 react-native-keyboard-controller 的 Hook 与 KeyboardProvider 替换旧的 Keyboard + Reanimated wiring;providers 包裹层级调整;Root layout 在启动时调用 usePlayerStore.getState().initialize()。
UI 消费者改动
src/app/player.tsx
Player 相关组件改用本地 useCurrentTrack,artwork 字段改为 coverUrl;相应绑定字段调整。
配置与依赖
package.json, app.config.ts, rnrepo.config.json, CHANGELOG.md
版本 2.2.2→2.2.3,新增依赖 react-native-keyboard-controller@1.20.4,更新 @roitium/expo-orpheus,新增 reanimated staticFeatureFlags,调整 Android packagingOptions、添加 rnrepo denyList。

Sequence Diagram(s)

sequenceDiagram
  participant Root as App Root (/src/app/_layout.tsx)
  participant Store as usePlayerStore (Zustand)
  participant Orpheus as Orpheus (native player)
  participant TrackSvc as trackService (JS API)
  participant UI as UI Components (Player, Pages)

  Root->>Store: initialize()
  Store->>Orpheus: query currentTrack & index
  Orpheus-->>Store: currentTrack info
  alt currentTrack exists
    Store->>TrackSvc: getTrackByUniqueKey(currentTrack.id)
    TrackSvc-->>Store: Track (or error)
    Store-->>UI: set internalTrack & orpheusTrack
  else no currentTrack
    Store-->>UI: clear internalTrack
  end

  UI->>Store: read selectors (useCurrentTrack / useCurrentTrackId / useIsCurrentTrack)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 新技能我来报到行,文档如萝卜一箩筐,
用Zustand把歌安放,搜索缓影步更轻,
键盘随风软又香,并发切换舞翩跹。

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive Pull request title is too vague and generic. 'perf: improve perf' uses non-descriptive language without specifying which performance aspect is improved or what changes were made. 建议更新标题以具体说明改进了哪些性能方面。例如:'perf: optimize search performance with useDeferredValue' 或 'perf: refactor player store and add layout animations'。
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 20

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/app/playlist/local/[id].tsx (1)

29-78: 延迟查询的实现方向正确,但需补充关键最佳实践。

useDeferredValuestartSearch 结合确实能保持输入的响应性,但需注意:

  1. 网络请求优化useDeferredValue 本身不会减少网络调用。由于 useSearchTracksInPlaylist 直接使用 deferredQuery,应在fetch 层添加防抖、缓存或请求取消机制,否则仍会频繁请求。

  2. 推荐补充

    • 为结果列表组件添加 memo 包装,避免不必要的重渲染
    • searchQuery !== deferredQuery 时添加视觉反馈(如灰显结果),指示数据正在更新
🤖 Fix all issues with AI agents
In @.agents/skills/react-native-best-practices/references/bundle-analyze-js.md:
- Around line 155-162: The snippet in rspack.config.js uses hard tabs for
indentation; replace tabs with spaces in the JavaScript code block so formatting
is consistent with Markdown lint rules — update the lines containing
RsdoctorRspackPlugin, the plugins array and the process.env.RSDOCTOR expression
to use spaces instead of tabs (e.g., two or two/consistent spaces) across the
code block.

In
@.agents/skills/react-native-best-practices/references/bundle-barrel-exports.md:
- Around line 107-113: The code block containing the export default array
(starts with "export default [" and includes the plugins/rules object and
'no-barrel-files/no-barrel-files') uses hard tabs for indentation which violates
MD010; open that code block and replace each tab character with spaces (use the
repository's markdown indentation style, e.g., 2 or 4 spaces consistently) so
the lines for plugins, rules, and the rule entry are space-indented instead of
tab-indented.
- Around line 77-80: The fenced code block that currently contains the Require
cycle warning (the block starting with "Warning: Require cycle:
components/index.ts -> Button.tsx -> utils/index.ts -> components/index.ts") is
missing a language tag; update that code fence to include a language identifier
(for example `text` or `tsx`) so MarkdownLint rule MD040 is satisfied — locate
the fenced block and change the opening backticks from ``` to ```text (or
```tsx) accordingly.

In
@.agents/skills/react-native-best-practices/references/bundle-native-assets.md:
- Around line 33-38: The markdown contains multiple fenced code blocks without a
language tag (e.g., the blocks starting with "assets/",
"android/app/build/outputs/bundle/release/", "ios/RNAssets.xcassets/", "App
bundle contains:", "iPhone 15 Pro receives:", and "Variant: MyApp-<UUID>.ipa");
update each of these backtick-fenced blocks to use a language identifier of
"text" (i.e., replace ``` with ```text) so markdownlint MD040 is satisfied and
rendering/linting is consistent across the document.

In @.agents/skills/react-native-best-practices/references/bundle-r8-android.md:
- Around line 168-170: Update the header text "### Library Specific Rules" to
use a hyphenated form "### Library-specific Rules" to correct the grammar;
locate the header string in the markdown (the line containing "Library Specific
Rules") and replace it with the hyphenated version.

In
@.agents/skills/react-native-best-practices/references/bundle-tree-shaking.md:
- Around line 19-35: The code blocks contain hard tab characters triggering
MD010; replace all tab characters with spaces inside the shown snippets (and
other similar code blocks) so lint passes — specifically edit the
metro.config.js snippet (the config.transformer.getTransformOptions function)
and the babel.config.js snippet (the module.exports preset entry that sets
disableImportExportTransform) to use spaces instead of tabs throughout.

In
@.agents/skills/react-native-best-practices/references/js-animations-reanimated.md:
- Line 52: The markdown has fenced code blocks missing language identifiers
(reporting markdownlint MD040); update each offending fence (the triple-backtick
blocks) in
.agents/skills/react-native-best-practices/references/js-animations-reanimated.md
by adding an explicit language tag (e.g., text, bash, jsx) after the opening ```
for the code blocks noted (the three unlabelled fenced blocks) so lint passes.

In
@.agents/skills/react-native-best-practices/references/js-lists-flatlist-flashlist.md:
- Around line 83-99: The example component BetterList uses index.toString() in
the keyExtractor which contradicts the guidance to avoid array indices; update
BetterList to expect items with a stable identifier (e.g., id or key) and change
the keyExtractor to return that stable id (for example keyExtractor={item =>
item.id.toString() || item.key}) or, if the list is truly static, add an
explicit comment stating the index fallback is only for immutable static lists;
apply the same change to the other example referenced (lines ~125-130) and
update the items prop description to require a stable id field.

In
@.agents/skills/react-native-best-practices/references/native-turbo-modules.md:
- Around line 108-137: Code blocks for the Swift and Objective-C++ examples use
hard tab characters for indentation; replace all tab characters with spaces (use
2 or 4 spaces per indent consistently) across the code blocks so Markdown
renders correctly—update the Swift example in AwesomeLibrary.swift (extension
AwesomeLibrary and func multiply) and the ObjC++ bridge in AwesomeLibrary.mm
(implementation AwesomeLibrary, RCT_EXPORT_MODULE(), and the
RCT_EXTERN_METHOD(multiply:b:)) by running a "replace tabs with spaces" in your
editor or linter and verify no remaining \t characters remain in those snippets.
- Around line 13-34: The Swift examples use hard tab characters for indentation;
update the code blocks for the sync example (the `@objc` func heavyWork() ->
NSNumber implementation) and the async example (the `@objc` func
heavyWork(resolve:reject:) implementation that uses DispatchQueue.global().async
and resolve/reject) to replace tabs with spaces so indentation is consistent
across both snippets, keeping Swift-style 2 (or project standard) spaces per
indent and preserving line breaks and punctuation.

In
@.agents/skills/react-native-best-practices/references/native-view-flattening.md:
- Around line 17-18: 文件中的多处行(例如包含 <Tab1 /> 和 <Tab2 /> 的行,以及评论提到的其他段落)使用了硬制表符,触发
MD010。请将这些硬 tab 全部替换为空格(例如 2 或 4 个空格,遵循项目约定),确保所有 Markdown 行首与行中缩进不含 \t 字符并重新运行
lint 验证;检查并修复所有列出的区块(包括第 26-27、54-69、77-79、123-156、165-170、175-177
所示区域)以消除所有硬制表符引用,如 <Tab1 /> 和 <Tab2 /> 所在行。

In @.agents/skills/vercel-react-native-skills/rules/js-hoist-intl.md:
- Around line 18-22: 这些行使用了硬制表符(tabs)触发 markdownlint 的 MD010;在包含
Intl.NumberFormat
的片段(formatter、Intl.NumberFormat(...)、formatter.format(amount)、<Text>)将行缩进中的所有
tab 替换为等价数量的空格以保持一致缩进风格,并在同一规则适用的其他位置(第 30-31, 35, 43-44, 56)做相同处理,确认保存后重新运行
lint。

In
@.agents/skills/vercel-react-native-skills/rules/list-performance-callbacks.md:
- Line 5: Update the YAML frontmatter `tags` entry that currently uses
placeholder values `tag1, tag2` by replacing them with relevant, descriptive
tags (for example: list, performance, callbacks, memoization) so the document's
metadata accurately reflects its content; edit the `tags:` line in the markdown
frontmatter to contain the new comma-separated tags.
- Around line 32-42: The current useCallback defines onPress outside renderItem
but references item.id which is out of scope; fix by making onPress accept id
(useCallback((id) => handlePress(id), [handlePress])) and pass that to
LegendList/Item, or alternatively move the id-specific handler into the Item
component (e.g., Item uses its own useCallback(() => onPress(item.id), [onPress,
item.id]) while the parent onPress only depends on handlePress); update
references to onPress, handlePress, LegendList, and Item accordingly.

In
@.agents/skills/vercel-react-native-skills/rules/list-performance-function-references.md:
- Around line 82-84: 示例中使用了 ES2023 的 toSorted()(sortedTlds =
tlds.toSorted(...)),这在部分 React Native/Hermes 版本上可能不受支持;请将其替换为先复制原数组再调用 sort
的兼容写法:创建一个新数组副本(使用扩展运算符复制 tlds)然后在副本上调用 Array.prototype.sort 并传入原有的比较函数(基于
a.name.localeCompare(b.name)),确保 sortedTlds 为新实例且不直接变更原始 tlds。

In
@.agents/skills/vercel-react-native-skills/rules/navigation-native-navigators.md:
- Around line 29-193: 文件中的多个 Markdown 代码块使用了硬 Tab 导致 MD010 报告;在包含示例的代码块(例如函数/组件名
App、Layout、TabLayout、以及 JSX 片段含
Stack.Navigator、Tab.Navigator、Stack.Screen、NativeTabs.Trigger 等)中将所有硬制 Tab
字符替换为一致的空格缩进(例如 2 个或 4 个空格),对所有代码块执行相同替换并保存,然后重新运行 markdownlint/MD010 验证修复。

In @.agents/skills/vercel-react-native-skills/rules/ui-measure-views.md:
- Around line 22-43: 代码块第22-43行使用硬Tab导致 markdownlint MD010 报错;请在该代码片段中将所有硬 Tab
替换为空格(建议每级缩进用两个或四个空格),检查并修复涉及到 useRef<View>(null), useLayoutEffect, onLayout 和
LayoutChangeEvent 的缩进以保持一致性,确保返回的 JSX <View ref={ref} onLayout={onLayout}>
区块及内部子节点也使用空格缩进以通过 lint 校验。

In @.agents/skills/vercel-react-native-skills/rules/ui-menus.md:
- Around line 21-39: 代码块中使用了硬 Tab 导致 markdownlint MD010 报错;在包含
useState、setOpen、Pressable、View、Text 的组件示例(the JSX block shown)中把所有 Tab
缩进替换为空格缩进(建议 2 或 4 个空格与项目风格一致),确保代码块内每一行的开头没有制表符字符并保存文件后再次运行 lint 验证。

In @.agents/skills/vercel-react-native-skills/rules/ui-styling.md:
- Around line 19-23: The file contains hard tab characters triggering
markdownlint MD010 (e.g., within the code block showing "{ borderRadius: 12,
borderCurve: 'continuous' }" and the following "Use `gap` instead of margin for
spacing between elements:" lines and the region noted also applies to lines
32-39); replace all hard tabs with spaces in those sections so the code block,
headings, and list content use spaces consistently (convert any '\t' to
appropriate number of spaces) and re-run markdownlint to confirm MD010 is
resolved.

In `@src/hooks/stores/usePlayerStore.ts`:
- Around line 32-57: The sync() function can suffer a race where an earlier
getTrackByUniqueKey result overwrites a newer track; after awaiting
trackService.getTrackByUniqueKey(currentTrack.id) (and before calling set({
internalTrack: ... }) or set({ internalTrack: null })), re-read the current
store orpheusTrack?.id (via get()) and compare it to the original newTrackId;
only apply the set if they still match. Apply the same check both on success
(set internalTrack) and on error (set internalTrack to null / toast) so stale
async responses do not mutate state for a newer track.
🧹 Nitpick comments (22)
.agents/skills/vercel-react-native-skills/rules/ui-safe-area-scroll.md (1)

1-65: iOS 安全区域处理文档准确,但可考虑补充跨平台说明。

文档正确地推荐在 iOS 上使用 contentInsetAdjustmentBehavior="automatic" 来处理安全区域。这种原生方法确实能更好地处理动态安全区域(键盘、工具栏)。

不过需要注意:contentInsetAdjustmentBehavior 是 iOS 专属属性,在 Android 上无效。如果这份文档面向跨平台开发,可以考虑添加关于 Android 平台处理方式的说明。

.agents/skills/react-native-best-practices/references/native-threading-model.md (1)

124-165: 替换硬制表符为空格以保持一致性。

markdownlint 工具检测到多处使用了硬制表符(hard tabs)。为了保持 Markdown 文件的一致性和跨编辑器的可读性,建议将所有硬制表符替换为空格。

🔧 修复建议

在整个文件中,将代码块和表格中的制表符替换为空格(通常使用 2 或 4 个空格)。可以使用编辑器的"将制表符转换为空格"功能批量处理。

.agents/skills/vercel-react-native-skills/rules/ui-pressable.md (1)

21-64: 替换代码块中的硬制表符。

代码示例中检测到硬制表符。建议将所有制表符替换为空格(通常使用制表符宽度对应的空格数),以保持代码格式的一致性。

.agents/skills/vercel-react-native-skills/rules/react-compiler-reanimated-shared-values.md (1)

20-52: 将代码示例中的制表符替换为空格。

代码块中使用了硬制表符。为了保持代码格式的一致性,建议将制表符转换为空格。

.agents/skills/vercel-react-native-skills/rules/scroll-position-no-state.md (1)

18-61: 代码块中存在硬制表符。

多个代码示例中使用了制表符进行缩进。建议统一使用空格以保持格式一致性。

.agents/skills/vercel-react-native-skills/rules/list-performance-item-expensive.md (1)

1-98: 建议修复代码块中的制表符格式问题。

文档内容优秀,准确展示了列表项性能优化的最佳实践:

  • 正确识别了在列表项中进行数据查询、多次访问 Context 和昂贵计算的问题
  • Zustand 选择器示例很好地展示了替代 Context 的方案
  • 使用 Set.has() 而非 Array.includes() 是很好的性能建议

但代码块中使用了硬制表符(hard tabs),在 Markdown 中应使用空格以保持一致性。

♻️ 建议将代码块中的制表符替换为空格

静态分析工具标记了以下行中的硬制表符:

  • Lines 18-28, 30 (第一个代码块)
  • Lines 38-45 (第二个代码块)
  • Lines 54-67 (第三个代码块)
  • Lines 76-78, 83-85 (最后两个代码块)

建议将所有代码块中的制表符替换为空格(通常使用 2 或 4 个空格缩进)。

.agents/skills/vercel-react-native-skills/rules/ui-native-modals.md (1)

1-86: 文档内容准确,但存在格式问题。

这份关于原生模态框的指导很有价值:

  • 正确推荐使用原生 Modal 组件而非 JS 底部弹出层库
  • presentationStyle='formSheet' 的使用正确
  • React Navigation v7 的 sheetAllowedDetents 配置准确
  • 强调原生手势、无障碍功能和性能优势的观点合理

但代码块中存在硬制表符格式问题,建议替换为空格以保持 Markdown 一致性(影响行:21-38, 48-67, 76-81)。

.agents/skills/react-native-best-practices/references/js-measure-fps.md (2)

76-82: 代码块缺少语言标识符。

Line 76 的围栏代码块应该指定语言标识符以提高可读性和语法高亮。由于这是标记列表的文本输出,建议使用 textplaintext

♻️ 建议的修复
-```
+```text
 1. Native Process Init     (nativeLaunchStart → nativeLaunchEnd)
 2. Native App Init         (appCreationStart → appCreationEnd)

151-157: 代码示例准确,但存在格式问题。

阻塞循环示例正确展示了如何导致丢帧问题,frame budget 的计算也准确:

  • 60 FPS = 16.6ms
  • 120 FPS = 8.3ms

但代码块中使用了硬制表符(lines 152-156),建议替换为空格。

.agents/skills/react-native-best-practices/references/native-measure-tti.md (3)

76-82: 代码块缺少语言标识符。

Line 76 的围栏代码块应该指定语言标识符。建议使用 text 以提高可读性。


90-117: 原生代码示例准确。

iOS 和 Android 的冷启动检测实现都正确:

  • Swift 中使用 ProcessInfo.processInfo.environment["ActivePrewarm"] 检测预热启动
  • Kotlin 中使用 Handler().postActivityLifecycleCallbacks 检测冷启动
  • 逻辑清晰,实现可靠

但代码块中存在硬制表符格式问题(建议使用空格)。


176-204: JavaScript 性能标记实现正确。

代码示例准确展示了:

  • 使用 performance.mark('screenInteractive') 标记交互时机
  • 使用 performance.getEntriesByType('mark') 收集指标
  • 正确计算各阶段的持续时间

但存在硬制表符格式问题(lines 177-180, 182, 192-203),建议替换为空格。

.agents/skills/vercel-react-native-skills/rules/list-performance-images.md (1)

1-53: 图片优化指导准确且实用。

这份文档正确展示了列表中图片优化的最佳实践:

  • 清晰对比了加载全分辨率图片(4000x3000)与缩略图(200x200)的区别
  • URL 查询参数 ?w=200&h=200&fit=cover 是常见的 CDN 图片调整模式
  • 推荐在 Retina 屏幕上使用 2x 尺寸(显示 100x100,请求 200x200)是正确的
  • contentFit='cover'expo-image 的正确属性
  • 推荐使用 expo-imageSolitoImage 以获得缓存和占位符支持

但代码块中存在硬制表符格式问题(lines 21-47),建议替换为空格以保持一致性。

.agents/skills/vercel-react-native-skills/rules/react-state-dispatcher.md (1)

21-25: 考虑使用空格代替硬制表符以保持格式一致性。

代码块中使用了硬制表符进行缩进。虽然这不会影响文档功能,但使用空格(通常是2或4个)可以提高跨不同编辑器和查看器的一致性。

Also applies to: 35-39, 54-55, 65-66, 79-79, 89-89

.agents/skills/vercel-react-native-skills/rules/animation-gpu-properties.md (1)

20-22: 考虑使用空格代替硬制表符以保持格式一致性。

与其他文档文件类似,代码块中使用了硬制表符。为了在整个文档集中保持一致性,建议使用空格进行缩进。

Also applies to: 26-43, 51-60, 62-63

.agents/skills/react-native-best-practices/references/bundle-library-size.md (1)

52-60: 考虑为代码块添加语言标识符。

某些代码块缺少语言标识符(例如 bashtextplaintext),这可能会影响语法高亮显示。添加适当的语言标识符可以提高可读性。

♻️ 建议的改进

例如,对于 URL 示例:

-```
+```text
 https://bundlephobia.com/package/[package-name]

对于大小比较示例:
```diff
-```
+```text
 moment (289 kB) vs date-fns (75 kB) vs dayjs (6 kB)
</details>




Also applies to: 103-105, 109-111

</blockquote></details>
<details>
<summary>.agents/skills/vercel-react-native-skills/rules/list-performance-virtualize.md (1)</summary><blockquote>

`19-28`: **考虑使用空格代替硬制表符以保持格式一致性。**

代码块中的硬制表符缩进与项目中其他文档文件的模式一致。为了提高一致性,可以考虑统一使用空格。




Also applies to: 39-47, 58-65

</blockquote></details>
<details>
<summary>src/app/(tabs)/library/[tab].tsx (1)</summary><blockquote>

`8-97`: **使用 `startTransition` 包裹 Tab 切换更新是最佳实践。**  
可降低高频状态更新对主线程的影响,提升切换流畅度。建议进一步利用 `useTransition` 返回的 `isPending` 状态为用户提供视觉反馈(如高亮待切换的 Tab 或显示加载指示器),以进一步优化用户体验。

</blockquote></details>
<details>
<summary>src/hooks/player/useCurrentTrack.ts (1)</summary><blockquote>

`5-5`: **`useShallow` 对于单值选择器是不必要的。**

`useShallow` 用于浅比较多个选择值(如解构对象),以避免不必要的重新渲染。对于选择单个值(如 `state.internalTrack`),直接使用普通选择器即可,`useShallow` 只会增加额外开销。


<details>
<summary>♻️ 建议的修改</summary>

```diff
-import { useShallow } from 'zustand/react/shallow'
-
 export function useCurrentTrack() {
-	return usePlayerStore(useShallow((state) => state.internalTrack))
+	return usePlayerStore((state) => state.internalTrack)
 }
src/hooks/player/useIsCurrentTrack.ts (1)

5-7: useShallow 对于返回布尔值的选择器是不必要的。

选择器返回的是原始布尔值 (state.orpheusTrack?.id === trackUniqueKey)。Zustand 默认使用 Object.is 进行相等性比较,对于原始类型(如 boolean、string、number)已经足够高效。useShallow 主要用于浅比较对象/数组,在这里没有实际作用。

♻️ 建议的修改
-import { useShallow } from 'zustand/react/shallow'
-
 export function useIsCurrentTrack(trackUniqueKey: string) {
-	return usePlayerStore(
-		useShallow((state) => state.orpheusTrack?.id === trackUniqueKey),
-	)
+	return usePlayerStore((state) => state.orpheusTrack?.id === trackUniqueKey)
 }
.agents/skills/react-native-best-practices/references/js-atomic-state.md (1)

15-237: 建议:将代码块中的硬制表符替换为空格

文档的代码示例中使用了硬制表符(hard tabs)进行缩进。为保持与 Markdown 最佳实践的一致性,建议将所有代码块中的制表符替换为空格(通常使用 2 或 4 个空格)。

这样可以确保代码在不同编辑器和查看器中显示一致。

📝 修复建议

可以使用以下命令批量替换:

# 将制表符替换为 2 个空格
sed -i 's/\t/  /g' .agents/skills/react-native-best-practices/references/js-atomic-state.md

或在代码编辑器中使用"将制表符转换为空格"功能。

基于代码规范:markdownlint 规则 MD010 建议在 Markdown 文件中使用空格而非硬制表符。

.agents/skills/react-native-best-practices/references/bundle-analyze-app.md (1)

130-135: 建议:为代码块指定语言标识符

第 130 行的代码块缺少语言标识符。这是一个示例输出文本,建议添加 textplaintext 标识符以提高文档的清晰度。

📝 修复建议
-```
+```text
 Variant: SampleApp-<UUID>.ipa
 App + On Demand Resources size: 3.5 MB compressed, 10.6 MB uncompressed
 App size: 3.5 MB compressed, 10.6 MB uncompressed
</details>

基于代码规范:markdownlint 规则 MD040 要求为所有代码块指定语言。

</blockquote></details>

</blockquote></details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Comment on lines +155 to +162
```javascript
// rspack.config.js
const { RsdoctorRspackPlugin } = require('@rsdoctor/rspack-plugin')

module.exports = {
plugins: [process.env.RSDOCTOR && new RsdoctorRspackPlugin()].filter(Boolean),
}
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

将制表符替换为空格以保持一致性

JavaScript 代码示例中使用了硬制表符(hard tabs)进行缩进,这违反了 Markdown 格式规范。建议使用空格代替制表符以保持文档格式的一致性。

🔧 建议的修复
 ```javascript
 // rspack.config.js
 const { RsdoctorRspackPlugin } = require('@rsdoctor/rspack-plugin')
 
 module.exports = {
-	plugins: [process.env.RSDOCTOR && new RsdoctorRspackPlugin()].filter(Boolean),
+  plugins: [process.env.RSDOCTOR && new RsdoctorRspackPlugin()].filter(Boolean),
 }

</details>

基于静态分析工具 markdownlint-cli2 的提示。

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.18.1)</summary>

160-160: Hard tabs
Column: 1

(MD010, no-hard-tabs)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

In @.agents/skills/react-native-best-practices/references/bundle-analyze-js.md
around lines 155 - 162, The snippet in rspack.config.js uses hard tabs for
indentation; replace tabs with spaces in the JavaScript code block so formatting
is consistent with Markdown lint rules — update the lines containing
RsdoctorRspackPlugin, the plugins array and the process.env.RSDOCTOR expression
to use spaces instead of tabs (e.g., two or two/consistent spaces) across the
code block.


</details>

<!-- fingerprinting:phantom:triton:puma -->

<!-- This is an auto-generated comment by CodeRabbit -->

Comment on lines +77 to +80
```
Warning: Require cycle:
components/index.ts -> Button.tsx -> utils/index.ts -> components/index.ts
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

为代码块补充语言标识以满足 MD040。

Line 77 的 fenced code block 没有语言标识,markdownlint 会报错。建议补上(如 texttsx)。

🛠️ 建议修复
-```
+```text
 Warning: Require cycle:
   components/index.ts -> Button.tsx -> utils/index.ts -> components/index.ts
</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

77-77: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In
@.agents/skills/react-native-best-practices/references/bundle-barrel-exports.md
around lines 77 - 80, The fenced code block that currently contains the Require
cycle warning (the block starting with "Warning: Require cycle:
components/index.ts -> Button.tsx -> utils/index.ts -> components/index.ts") is
missing a language tag; update that code fence to include a language identifier
(for example `text` or `tsx`) so MarkdownLint rule MD040 is satisfied — locate
the fenced block and change the opening backticks from ``` to ```text (or
```tsx) accordingly.

Comment on lines +107 to +113
export default [
{
plugins: { 'no-barrel-files': noBarrelFiles },
rules: {
'no-barrel-files/no-barrel-files': 'error',
},
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

将代码块中的 Tab 替换为空格以通过 MD010。

Line 108-113 使用了硬 Tab,markdownlint 会报错;建议统一为空格缩进。

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

108-108: Hard tabs
Column: 1

(MD010, no-hard-tabs)


109-109: Hard tabs
Column: 1

(MD010, no-hard-tabs)


110-110: Hard tabs
Column: 1

(MD010, no-hard-tabs)


111-111: Hard tabs
Column: 1

(MD010, no-hard-tabs)


112-112: Hard tabs
Column: 1

(MD010, no-hard-tabs)


113-113: Hard tabs
Column: 1

(MD010, no-hard-tabs)

🤖 Prompt for AI Agents
In
@.agents/skills/react-native-best-practices/references/bundle-barrel-exports.md
around lines 107 - 113, The code block containing the export default array
(starts with "export default [" and includes the plugins/rules object and
'no-barrel-files/no-barrel-files') uses hard tabs for indentation which violates
MD010; open that code block and replace each tab character with spaces (use the
repository's markdown indentation style, e.g., 2 or 4 spaces consistently) so
the lines for plugins, rules, and the rule entry are space-indented instead of
tab-indented.

Comment on lines +33 to +38
```
assets/
├── image.jpg # 1x resolution (base)
├── image@2x.jpg # 2x resolution
└── image@3x.jpg # 3x resolution
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

为未标注语言的代码围栏补充语言标识以通过 lint。
markdownlint 报告 MD040。建议为纯文本输出统一标注 text(或 plaintext),避免渲染与 lint 失败。

🛠️ 建议修改
-```
+```text
 assets/
 ├── image.jpg       # 1x resolution (base)
 ├── image@2x.jpg    # 2x resolution
 └── image@3x.jpg    # 3x resolution
-```
+```

-```
+```text
 android/app/build/outputs/bundle/release/
 └── base/
     └── res/
         ├── drawable-mdpi-v4/     # 1x
         ├── drawable-hdpi-v4/     # 1.5x
         ├── drawable-xhdpi-v4/    # 2x
         ├── drawable-xxhdpi-v4/   # 3x
         └── drawable-xxxhdpi-v4/  # 4x
-```
+```

-```
+```text
 ios/RNAssets.xcassets/
-```
+```

-```
+```text
 ios/RNAssets.xcassets/
 └── assets_image_image.imageset/
     ├── Contents.json
     ├── image.jpg
     ├── image@2x.jpg
     └── image@3x.jpg
-```
+```

-```
+```text
 App bundle contains:
 ├── image.jpg       (100 KB)
 ├── image@2x.jpg    (300 KB)
 └── image@3x.jpg    (600 KB)
 Total: 1 MB
-```
+```

-```
+```text
 iPhone 15 Pro receives:
 └── image@3x.jpg    (600 KB)
 Total: 600 KB  (40% smaller)
-```
+```

-```
+```text
 Variant: MyApp-<UUID>.ipa
 Supported variant descriptors: iPhone15,2 ...
 App size: 3.5 MB compressed, 10.6 MB uncompressed
-```
+```

Also applies to: 59-68, 82-84, 125-132, 140-146, 150-154, 193-197

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

33-33: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In
@.agents/skills/react-native-best-practices/references/bundle-native-assets.md
around lines 33 - 38, The markdown contains multiple fenced code blocks without
a language tag (e.g., the blocks starting with "assets/",
"android/app/build/outputs/bundle/release/", "ios/RNAssets.xcassets/", "App
bundle contains:", "iPhone 15 Pro receives:", and "Variant: MyApp-<UUID>.ipa");
update each of these backtick-fenced blocks to use a language identifier of
"text" (i.e., replace ``` with ```text) so markdownlint MD040 is satisfied and
rendering/linting is consistent across the document.

Comment on lines +168 to +170
### Library Specific Rules

Many libraries provide ProGuard rules. Check:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

小幅语法修正:建议使用连字符。

“Library Specific Rules” 建议改为 “Library-specific Rules”。

🧰 Tools
🪛 LanguageTool

[grammar] ~168-~168: Use a hyphen to join words.
Context: ... ``` 3. Rebuild and test ### Library Specific Rules Many libraries provide P...

(QB_NEW_EN_HYPHEN)

🤖 Prompt for AI Agents
In @.agents/skills/react-native-best-practices/references/bundle-r8-android.md
around lines 168 - 170, Update the header text "### Library Specific Rules" to
use a hyphenated form "### Library-specific Rules" to correct the grammar;
locate the header string in the markdown (the line containing "Library Specific
Rules") and replace it with the hyphenated version.

Comment on lines +29 to +193
function App() {
return (
<Stack.Navigator>
<Stack.Screen
name='Home'
component={HomeScreen}
/>
<Stack.Screen
name='Details'
component={DetailsScreen}
/>
</Stack.Navigator>
)
}
```

**Correct (native stack with react-navigation):**

```tsx
import { createNativeStackNavigator } from '@react-navigation/native-stack'

const Stack = createNativeStackNavigator()

function App() {
return (
<Stack.Navigator>
<Stack.Screen
name='Home'
component={HomeScreen}
/>
<Stack.Screen
name='Details'
component={DetailsScreen}
/>
</Stack.Navigator>
)
}
```

**Correct (expo-router uses native stack by default):**

```tsx
// app/_layout.tsx
import { Stack } from 'expo-router'

export default function Layout() {
return <Stack />
}
```

### Tab Navigation

**Incorrect (JS bottom tabs):**

```tsx
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'

const Tab = createBottomTabNavigator()

function App() {
return (
<Tab.Navigator>
<Tab.Screen
name='Home'
component={HomeScreen}
/>
<Tab.Screen
name='Settings'
component={SettingsScreen}
/>
</Tab.Navigator>
)
}
```

**Correct (native bottom tabs with react-navigation):**

```tsx
import { createNativeBottomTabNavigator } from '@bottom-tabs/react-navigation'

const Tab = createNativeBottomTabNavigator()

function App() {
return (
<Tab.Navigator>
<Tab.Screen
name='Home'
component={HomeScreen}
options={{
tabBarIcon: () => ({ sfSymbol: 'house' }),
}}
/>
<Tab.Screen
name='Settings'
component={SettingsScreen}
options={{
tabBarIcon: () => ({ sfSymbol: 'gear' }),
}}
/>
</Tab.Navigator>
)
}
```

**Correct (expo-router native tabs):**

```tsx
// app/(tabs)/_layout.tsx
import { NativeTabs } from 'expo-router/unstable-native-tabs'

export default function TabLayout() {
return (
<NativeTabs>
<NativeTabs.Trigger name='index'>
<NativeTabs.Trigger.Label>Home</NativeTabs.Trigger.Label>
<NativeTabs.Trigger.Icon
sf='house.fill'
md='home'
/>
</NativeTabs.Trigger>
<NativeTabs.Trigger name='settings'>
<NativeTabs.Trigger.Label>Settings</NativeTabs.Trigger.Label>
<NativeTabs.Trigger.Icon
sf='gear'
md='settings'
/>
</NativeTabs.Trigger>
</NativeTabs>
)
}
```

On iOS, native tabs automatically enable `contentInsetAdjustmentBehavior` on the
first `ScrollView` at the root of each tab screen, so content scrolls correctly
behind the translucent tab bar. If you need to disable this, use
`disableAutomaticContentInsets` on the trigger.

### Prefer Native Header Options Over Custom Components

**Incorrect (custom header component):**

```tsx
<Stack.Screen
name='Profile'
component={ProfileScreen}
options={{
header: () => <CustomHeader title='Profile' />,
}}
/>
```

**Correct (native header options):**

```tsx
<Stack.Screen
name='Profile'
component={ProfileScreen}
options={{
title: 'Profile',
headerLargeTitleEnabled: true,
headerSearchBarOptions: {
placeholder: 'Search',
},
}}
/>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

将示例代码中的硬 Tab 替换为空格以通过 markdownlint。
MD010 报告了多处硬 Tab;建议在所有代码块内统一用空格缩进。

🛠️ 示例修正(其余代码块同样处理)
-function App() {
-	return (
-		<Stack.Navigator>
-			<Stack.Screen
-				name='Home'
-				component={HomeScreen}
-			/>
-			<Stack.Screen
-				name='Details'
-				component={DetailsScreen}
-			/>
-		</Stack.Navigator>
-	)
-}
+function App() {
+  return (
+    <Stack.Navigator>
+      <Stack.Screen
+        name='Home'
+        component={HomeScreen}
+      />
+      <Stack.Screen
+        name='Details'
+        component={DetailsScreen}
+      />
+    </Stack.Navigator>
+  )
+}
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

30-30: Hard tabs
Column: 1

(MD010, no-hard-tabs)


31-31: Hard tabs
Column: 1

(MD010, no-hard-tabs)


32-32: Hard tabs
Column: 1

(MD010, no-hard-tabs)


33-33: Hard tabs
Column: 1

(MD010, no-hard-tabs)


34-34: Hard tabs
Column: 1

(MD010, no-hard-tabs)


35-35: Hard tabs
Column: 1

(MD010, no-hard-tabs)


36-36: Hard tabs
Column: 1

(MD010, no-hard-tabs)


37-37: Hard tabs
Column: 1

(MD010, no-hard-tabs)


38-38: Hard tabs
Column: 1

(MD010, no-hard-tabs)


39-39: Hard tabs
Column: 1

(MD010, no-hard-tabs)


40-40: Hard tabs
Column: 1

(MD010, no-hard-tabs)


41-41: Hard tabs
Column: 1

(MD010, no-hard-tabs)


53-53: Hard tabs
Column: 1

(MD010, no-hard-tabs)


54-54: Hard tabs
Column: 1

(MD010, no-hard-tabs)


55-55: Hard tabs
Column: 1

(MD010, no-hard-tabs)


56-56: Hard tabs
Column: 1

(MD010, no-hard-tabs)


57-57: Hard tabs
Column: 1

(MD010, no-hard-tabs)


58-58: Hard tabs
Column: 1

(MD010, no-hard-tabs)


59-59: Hard tabs
Column: 1

(MD010, no-hard-tabs)


60-60: Hard tabs
Column: 1

(MD010, no-hard-tabs)


61-61: Hard tabs
Column: 1

(MD010, no-hard-tabs)


62-62: Hard tabs
Column: 1

(MD010, no-hard-tabs)


63-63: Hard tabs
Column: 1

(MD010, no-hard-tabs)


64-64: Hard tabs
Column: 1

(MD010, no-hard-tabs)


75-75: Hard tabs
Column: 1

(MD010, no-hard-tabs)


89-89: Hard tabs
Column: 1

(MD010, no-hard-tabs)


90-90: Hard tabs
Column: 1

(MD010, no-hard-tabs)


91-91: Hard tabs
Column: 1

(MD010, no-hard-tabs)


92-92: Hard tabs
Column: 1

(MD010, no-hard-tabs)


93-93: Hard tabs
Column: 1

(MD010, no-hard-tabs)


94-94: Hard tabs
Column: 1

(MD010, no-hard-tabs)


95-95: Hard tabs
Column: 1

(MD010, no-hard-tabs)


96-96: Hard tabs
Column: 1

(MD010, no-hard-tabs)


97-97: Hard tabs
Column: 1

(MD010, no-hard-tabs)


98-98: Hard tabs
Column: 1

(MD010, no-hard-tabs)


99-99: Hard tabs
Column: 1

(MD010, no-hard-tabs)


100-100: Hard tabs
Column: 1

(MD010, no-hard-tabs)


112-112: Hard tabs
Column: 1

(MD010, no-hard-tabs)


113-113: Hard tabs
Column: 1

(MD010, no-hard-tabs)


114-114: Hard tabs
Column: 1

(MD010, no-hard-tabs)


115-115: Hard tabs
Column: 1

(MD010, no-hard-tabs)


116-116: Hard tabs
Column: 1

(MD010, no-hard-tabs)


117-117: Hard tabs
Column: 1

(MD010, no-hard-tabs)


118-118: Hard tabs
Column: 1

(MD010, no-hard-tabs)


119-119: Hard tabs
Column: 1

(MD010, no-hard-tabs)


120-120: Hard tabs
Column: 1

(MD010, no-hard-tabs)


121-121: Hard tabs
Column: 1

(MD010, no-hard-tabs)


122-122: Hard tabs
Column: 1

(MD010, no-hard-tabs)


123-123: Hard tabs
Column: 1

(MD010, no-hard-tabs)


124-124: Hard tabs
Column: 1

(MD010, no-hard-tabs)


125-125: Hard tabs
Column: 1

(MD010, no-hard-tabs)


126-126: Hard tabs
Column: 1

(MD010, no-hard-tabs)


127-127: Hard tabs
Column: 1

(MD010, no-hard-tabs)


128-128: Hard tabs
Column: 1

(MD010, no-hard-tabs)


129-129: Hard tabs
Column: 1

(MD010, no-hard-tabs)


140-140: Hard tabs
Column: 1

(MD010, no-hard-tabs)


141-141: Hard tabs
Column: 1

(MD010, no-hard-tabs)


142-142: Hard tabs
Column: 1

(MD010, no-hard-tabs)


143-143: Hard tabs
Column: 1

(MD010, no-hard-tabs)


144-144: Hard tabs
Column: 1

(MD010, no-hard-tabs)


145-145: Hard tabs
Column: 1

(MD010, no-hard-tabs)


146-146: Hard tabs
Column: 1

(MD010, no-hard-tabs)


147-147: Hard tabs
Column: 1

(MD010, no-hard-tabs)


148-148: Hard tabs
Column: 1

(MD010, no-hard-tabs)


149-149: Hard tabs
Column: 1

(MD010, no-hard-tabs)


150-150: Hard tabs
Column: 1

(MD010, no-hard-tabs)


151-151: Hard tabs
Column: 1

(MD010, no-hard-tabs)


152-152: Hard tabs
Column: 1

(MD010, no-hard-tabs)


153-153: Hard tabs
Column: 1

(MD010, no-hard-tabs)


154-154: Hard tabs
Column: 1

(MD010, no-hard-tabs)


155-155: Hard tabs
Column: 1

(MD010, no-hard-tabs)


156-156: Hard tabs
Column: 1

(MD010, no-hard-tabs)


157-157: Hard tabs
Column: 1

(MD010, no-hard-tabs)


172-172: Hard tabs
Column: 1

(MD010, no-hard-tabs)


173-173: Hard tabs
Column: 1

(MD010, no-hard-tabs)


174-174: Hard tabs
Column: 1

(MD010, no-hard-tabs)


175-175: Hard tabs
Column: 1

(MD010, no-hard-tabs)


176-176: Hard tabs
Column: 1

(MD010, no-hard-tabs)


184-184: Hard tabs
Column: 1

(MD010, no-hard-tabs)


185-185: Hard tabs
Column: 1

(MD010, no-hard-tabs)


186-186: Hard tabs
Column: 1

(MD010, no-hard-tabs)


187-187: Hard tabs
Column: 1

(MD010, no-hard-tabs)


188-188: Hard tabs
Column: 1

(MD010, no-hard-tabs)


189-189: Hard tabs
Column: 1

(MD010, no-hard-tabs)


190-190: Hard tabs
Column: 1

(MD010, no-hard-tabs)


191-191: Hard tabs
Column: 1

(MD010, no-hard-tabs)


192-192: Hard tabs
Column: 1

(MD010, no-hard-tabs)

🤖 Prompt for AI Agents
In
@.agents/skills/vercel-react-native-skills/rules/navigation-native-navigators.md
around lines 29 - 193, 文件中的多个 Markdown 代码块使用了硬 Tab 导致 MD010
报告;在包含示例的代码块(例如函数/组件名 App、Layout、TabLayout、以及 JSX 片段含
Stack.Navigator、Tab.Navigator、Stack.Screen、NativeTabs.Trigger 等)中将所有硬制 Tab
字符替换为一致的空格缩进(例如 2 个或 4 个空格),对所有代码块执行相同替换并保存,然后重新运行 markdownlint/MD010 验证修复。

Comment on lines +22 to +43
const ref = useRef<View>(null)
const [height, setHeight] = useState<number | undefined>(undefined)

useLayoutEffect(() => {
// Sync measurement on mount (RN 0.82+)
const rect = ref.current?.getBoundingClientRect()
if (rect) setHeight(rect.height)
// Pre-0.82: ref.current?.measure((x, y, w, h) => setHeight(h))
}, [])

const onLayout = (e: LayoutChangeEvent) => {
setHeight(e.nativeEvent.layout.height)
}

return (
<View
ref={ref}
onLayout={onLayout}
>
{children}
</View>
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

代码块内请避免硬 Tab(MD010)。

Line 22-43 使用 Tab 缩进,markdownlint 会报错;建议统一替换为空格。

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

22-22: Hard tabs
Column: 1

(MD010, no-hard-tabs)


23-23: Hard tabs
Column: 1

(MD010, no-hard-tabs)


25-25: Hard tabs
Column: 1

(MD010, no-hard-tabs)


26-26: Hard tabs
Column: 1

(MD010, no-hard-tabs)


27-27: Hard tabs
Column: 1

(MD010, no-hard-tabs)


28-28: Hard tabs
Column: 1

(MD010, no-hard-tabs)


29-29: Hard tabs
Column: 1

(MD010, no-hard-tabs)


30-30: Hard tabs
Column: 1

(MD010, no-hard-tabs)


32-32: Hard tabs
Column: 1

(MD010, no-hard-tabs)


33-33: Hard tabs
Column: 1

(MD010, no-hard-tabs)


34-34: Hard tabs
Column: 1

(MD010, no-hard-tabs)


36-36: Hard tabs
Column: 1

(MD010, no-hard-tabs)


37-37: Hard tabs
Column: 1

(MD010, no-hard-tabs)


38-38: Hard tabs
Column: 1

(MD010, no-hard-tabs)


39-39: Hard tabs
Column: 1

(MD010, no-hard-tabs)


40-40: Hard tabs
Column: 1

(MD010, no-hard-tabs)


41-41: Hard tabs
Column: 1

(MD010, no-hard-tabs)


42-42: Hard tabs
Column: 1

(MD010, no-hard-tabs)


43-43: Hard tabs
Column: 1

(MD010, no-hard-tabs)

🤖 Prompt for AI Agents
In @.agents/skills/vercel-react-native-skills/rules/ui-measure-views.md around
lines 22 - 43, 代码块第22-43行使用硬Tab导致 markdownlint MD010 报错;请在该代码片段中将所有硬 Tab
替换为空格(建议每级缩进用两个或四个空格),检查并修复涉及到 useRef<View>(null), useLayoutEffect, onLayout 和
LayoutChangeEvent 的缩进以保持一致性,确保返回的 JSX <View ref={ref} onLayout={onLayout}>
区块及内部子节点也使用空格缩进以通过 lint 校验。

Comment on lines +21 to +39
const [open, setOpen] = useState(false)

return (
<View>
<Pressable onPress={() => setOpen(!open)}>
<Text>Open Menu</Text>
</Pressable>
{open && (
<View style={{ position: 'absolute', top: 40 }}>
<Pressable onPress={() => console.log('edit')}>
<Text>Edit</Text>
</Pressable>
<Pressable onPress={() => console.log('delete')}>
<Text>Delete</Text>
</Pressable>
</View>
)}
</View>
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

代码块内请避免硬 Tab(MD010)。

Line 21-39 使用 Tab 缩进,markdownlint 会报错;建议统一替换为空格。

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

21-21: Hard tabs
Column: 1

(MD010, no-hard-tabs)


23-23: Hard tabs
Column: 1

(MD010, no-hard-tabs)


24-24: Hard tabs
Column: 1

(MD010, no-hard-tabs)


25-25: Hard tabs
Column: 1

(MD010, no-hard-tabs)


26-26: Hard tabs
Column: 1

(MD010, no-hard-tabs)


27-27: Hard tabs
Column: 1

(MD010, no-hard-tabs)


28-28: Hard tabs
Column: 1

(MD010, no-hard-tabs)


29-29: Hard tabs
Column: 1

(MD010, no-hard-tabs)


30-30: Hard tabs
Column: 1

(MD010, no-hard-tabs)


31-31: Hard tabs
Column: 1

(MD010, no-hard-tabs)


32-32: Hard tabs
Column: 1

(MD010, no-hard-tabs)


33-33: Hard tabs
Column: 1

(MD010, no-hard-tabs)


34-34: Hard tabs
Column: 1

(MD010, no-hard-tabs)


35-35: Hard tabs
Column: 1

(MD010, no-hard-tabs)


36-36: Hard tabs
Column: 1

(MD010, no-hard-tabs)


37-37: Hard tabs
Column: 1

(MD010, no-hard-tabs)


38-38: Hard tabs
Column: 1

(MD010, no-hard-tabs)


39-39: Hard tabs
Column: 1

(MD010, no-hard-tabs)

🤖 Prompt for AI Agents
In @.agents/skills/vercel-react-native-skills/rules/ui-menus.md around lines 21
- 39, 代码块中使用了硬 Tab 导致 markdownlint MD010 报错;在包含
useState、setOpen、Pressable、View、Text 的组件示例(the JSX block shown)中把所有 Tab
缩进替换为空格缩进(建议 2 或 4 个空格与项目风格一致),确保代码块内每一行的开头没有制表符字符并保存文件后再次运行 lint 验证。

Comment on lines +19 to +23
{ borderRadius: 12, borderCurve: 'continuous' }
```

**Use `gap` instead of margin for spacing between elements:**

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

请移除硬制表符(MD010)
这些行含硬 tabs,建议统一改为空格,避免 markdownlint 报错。

✅ 示例修正
-	<Text>First</Text>
-	<Text>Second</Text>
+  <Text>First</Text>
+  <Text>Second</Text>

Also applies to: 32-39

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

19-19: Hard tabs
Column: 1

(MD010, no-hard-tabs)


20-20: Hard tabs
Column: 1

(MD010, no-hard-tabs)


21-21: Hard tabs
Column: 1

(MD010, no-hard-tabs)


22-22: Hard tabs
Column: 1

(MD010, no-hard-tabs)


23-23: Hard tabs
Column: 1

(MD010, no-hard-tabs)

🤖 Prompt for AI Agents
In @.agents/skills/vercel-react-native-skills/rules/ui-styling.md around lines
19 - 23, The file contains hard tab characters triggering markdownlint MD010
(e.g., within the code block showing "{ borderRadius: 12, borderCurve:
'continuous' }" and the following "Use `gap` instead of margin for spacing
between elements:" lines and the region noted also applies to lines 32-39);
replace all hard tabs with spaces in those sections so the code block, headings,
and list content use spaces consistently (convert any '\t' to appropriate number
of spaces) and re-run markdownlint to confirm MD010 is resolved.

Comment thread src/hooks/stores/usePlayerStore.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@package.json`:
- Line 98: This dependency "react-native-keyboard-controller" is native and
requires a dev client build and proper synchronized deps: install both
react-native-keyboard-controller and react-native-reanimated, ensure you wrap
your app root with KeyboardProvider in your entry component (e.g., App.tsx),
then rebuild using the Expo dev client (Expo Go won't work); if you hit Android
Kotlin version conflicts, add expo-build-properties configuration in app.json to
set the Kotlin/Gradle versions to match the native modules.

Comment thread package.json
"react-native-fast-shimmer": "^1.3.4",
"react-native-gesture-handler": "~2.30.0",
"react-native-gradle-plugin": "^0.71.19",
"react-native-keyboard-controller": "1.20.4",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

react-native-keyboard-controller Expo installation setup documentation

💡 Result:

react-native-keyboard-controller (Expo) — install & setup

1) Use a development build (not Expo Go)

This library includes native code, so it won’t run in Expo Go; use a dev build / prebuild flow. [2]

2) Install the package

npx expo install react-native-keyboard-controller

[1][2]

3) Install/verify peer dependency: react-native-reanimated

Keyboard Controller requires react-native-reanimated. [2][3]

4) Wrap your app with KeyboardProvider

Example (Expo Router root layout):

import { Stack } from 'expo-router';
import { KeyboardProvider } from 'react-native-keyboard-controller';

export default function RootLayout() {
  return (
    <KeyboardProvider>
      <Stack />
    </KeyboardProvider>
  );
}

[2][3]

5) Build & run

After adding native deps, rebuild your dev client (for example via EAS build or local prebuild). [3]

(If needed) Expo managed workflow Android Kotlin version fix

If you hit Android build issues related to Kotlin version, the library docs recommend using expo-build-properties and setting a Kotlin version in app.json/app.config.js. [9]

Sources: Expo SDK docs for Keyboard Controller [1], Expo keyboard-handling guide [2], library installation docs [3], library troubleshooting (Expo managed workflow) [9].


确认 dev client 构建要求并关注同步依赖配置
该库包含原生代码,必须使用 dev client 构建(不支持 Expo Go)。核心集成步骤:(1) 安装 react-native-keyboard-controller 和其同步依赖 react-native-reanimated;(2) 在应用入口处用 KeyboardProvider 包装根组件;(3) 执行 dev client 重新构建。如遇 Android Kotlin 版本冲突,可通过 expo-build-properties 在 app.json 中配置。

🤖 Prompt for AI Agents
In `@package.json` at line 98, This dependency "react-native-keyboard-controller"
is native and requires a dev client build and proper synchronized deps: install
both react-native-keyboard-controller and react-native-reanimated, ensure you
wrap your app root with KeyboardProvider in your entry component (e.g.,
App.tsx), then rebuild using the Expo dev client (Expo Go won't work); if you
hit Android Kotlin version conflicts, add expo-build-properties configuration in
app.json to set the Kotlin/Gradle versions to match the native modules.

@roitium roitium merged commit ee81ff4 into dev Jan 28, 2026
1 check failed
@roitium roitium deleted the perf/search-perf-improve branch January 28, 2026 12:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant