Install any skill in seconds. Free to start, no credit card required.
Get Started Free →当 learner 端听课模式需要接入 markdown-flow-ui 的移动端播放器新能力时使用本技能。覆盖横竖屏状态透传、自定义横屏 header、以及播放器文案国际化接入。
.claude/skills/ai-shifu-listen-mode-slide-mobile-integration/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 89% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 24% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 85% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 64% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 42% | 0% |
ListenModeSlideRenderer 这一层完成 Slide 新 props 的业务接入,再按需把状态回调向 NewChatComp、ChatUi、页面层逐层透传。markdown-flow-ui。src/i18n/<locale>/modules/chat.json,不要在组件里写死字符串。aria-label 也必须走 module.chat 命名空间;共享 TS 模块只保留 mode 和 i18n key,禁止导出已经翻译好的“听课/阅读”等渲染文案。t('module.chat.xxx') 这类字面量调用;不要只导出 key 常量再在调用方 t(dynamicKey),否则 check_translation_usage.py 的静态扫描会把文案误判为未使用。Slide 新增 playerTexts.subtitleLabel、playerTexts.subtitleToggleAriaLabel 这类播放器字幕文案时,ai-shifu 侧也要在 ListenModeSlideRenderer 同步透传,并补齐 chat.json 与 i18n-keys.d.ts,避免 history slide 设置面板回退到英文。markdown-flow-ui 发布版类型暂未同步,使用 src/cook-web/src/types/markdown-flow-ui.d.ts 做最小化 module augmentation,避免覆盖上游完整声明。useCourseStore,章节/课时标题优先复用当前 lessonTitle 或 sectionTitle,不要在聊天组件里重复请求课程信息。useCourseStore 的 courseAvatar/courseName,并把 header 高度抽成共享 CSS 变量,避免 page、NavDrawer、ChatUi 各自写死不同高度。module.chat 下的独立 i18n key(例如“听 / 读”)。当前 LearningModeSwitch 是不带状态徽标的统一实现,不要假设 learner header 仍有 BETA badge;若产品重新要求状态标记,应在现有共享开关内设计并补齐测试,而不是引用已经删除的 badge 组件。learningModeOptions 中的选项顺序,让移动端和桌面端一起复用同一套展示顺序,不要在单个组件里额外写条件分支。desktop 尺寸变体做定向覆盖,不要回退成桌面端单独实现。courseId 维度使用 localStorage 保存,并把“读取缓存决定初始模式”和“用户切换后回写缓存”都收敛在学习页 layout 或共享 storage helper 中,避免按钮组件直接耦合存储细节。ListenModeSlideRenderer 本地消费 onMobileViewModeChange 维护 view mode,再用 modifier class 做定位差异,不要把这种纯展示状态继续上抛到更多层。onMobileViewModeChange 这类上抛回调并逐层透传时,中间层组件优先保持可选参数,并为页面层保留安全退化,避免只改一半导致 next build 在 JSX 调用点直接报 props 缺失。Slide 内部视口,业务层要为 portal 容器尚未就绪的首帧提供回退渲染,避免按钮因容器时序问题直接消失。Slide 的 fullscreen 态来自“设备自动检测 + 用户手动切换”混合模型,业务层消费 onMobileViewModeChange 时应以“当前生效态”为准,不要再额外假设物理横屏一定不可退出。dvh 视口误差时,优先在页面根节点切换 class,并通过全局 CSS 变量统一把相关高度从 dvh 映射到 vh,不要在多个组件里散落同一套条件判断。page 或宿主层是否把键盘触发的 resize / visualViewport.resize 当成横竖屏变化处理;输入框聚焦期间应过滤这类 resize,避免整页布局状态重算导致浮层或输入组件重渲染。ListenModeRenderer.scss 约束 slide 外层 flex/grid 链路的 min-width: 0、max-width: 100% 和局部 overflow-x,让代码块内部滚动,不要先改 markdown-flow-ui。Slide 的新增能力已经在 markdown-flow-ui 暴露,重点核对 fullscreenHeader、playerTexts、onMobileViewModeChange 的真实类型。markdown-flow-ui 已把移动端模式字段从 landscape / portrait 改为 fullscreen / nonFullscreen,ai-shifu 侧的 handler、props、state 与文案字段也要同步换名,例如 onListenMobileViewModeChange、mobileViewMode、fullscreenHeader、fullscreenLabel、nonFullscreenLabel。dvh/vh 计算,优先把 fullscreen + landscape + mobile 的命中条件收敛到页面根节点 class,再由全局变量驱动页面与弹层样式。chat i18n 命名空间,并同步更新生成型的 key 类型文件。| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 15,848 | 20,420 | +29% | 1 | 1 | 0% | 3,152 | 5,971 | +89% | 0 | 0 | — |
case-02 | fail→pass | 23,982 | 18,150 | -24% | 1 | 1 | 0% | 4,170 | 5,187 | +24% | 0 | 0 | — |
case-03 | fail→pass | 20,573 | 29,080 | +41% | 1 | 1 | 0% | 3,983 | 7,378 | +85% | 0 | 0 | — |
case-04 | fail→pass | 12,120 | 7,475 | -38% | 1 | 1 | 0% | 1,878 | 3,071 | +64% | 0 | 0 | — |
case-05 | fail→pass | 10,138 | 3,972 | -61% | 1 | 1 | 0% | 1,655 | 2,345 | +42% | 0 | 0 | — |
case-06 | fail→pass | 12,318 | 9,662 | -22% | 1 | 1 | 0% | 2,218 | 3,566 | +61% | 0 | 0 | — |
case-07 | pass→pass | 11,451 | 5,837 | -49% | 1 | 1 | 0% | 1,782 | 2,674 | +50% | 0 | 0 | — |
case-08 | fail→fail | 9,760 | 2,814 | -71% | 1 | 1 | 0% | 1,526 | 2,170 | +42% | 0 | 0 | — |
case-09 | fail→pass | 15,348 | 7,991 | -48% | 1 | 1 | 0% | 2,570 | 3,071 | +19% | 0 | 0 | — |
case-10 | pass→pass | 13,313 | 4,129 | -69% | 1 | 1 | 0% | 1,962 | 2,363 | +20% | 0 | 0 | — |
case-11 | fail→pass | 16,242 | 9,180 | -43% | 1 | 1 | 0% | 2,757 | 3,253 | +18% | 0 | 0 | — |
case-12 | fail→pass | 12,863 | 5,571 | -57% | 1 | 1 | 0% | 1,916 | 2,673 | +40% | 0 | 0 | — |
case-13 | pass→pass | 8,876 | 4,827 | -46% | 1 | 1 | 0% | 1,572 | 2,487 | +58% | 0 | 0 | — |
case-14 | pass→pass | 12,821 | 5,631 | -56% | 1 | 1 | 0% | 2,164 | 2,713 | +25% | 0 | 0 | — |
case-15 | fail→pass | 11,371 | 4,952 | -56% | 1 | 1 | 0% | 1,878 | 2,530 | +35% | 0 | 0 | — |
case-16 | pass→pass | 21,036 | 5,354 | -75% | 1 | 1 | 0% | 1,786 | 2,523 | +41% | 0 | 0 | — |
case-17 | fail→pass | 11,042 | 5,945 | -46% | 1 | 1 | 0% | 1,738 | 2,307 | +33% | 0 | 0 | — |
case-18 | pass→pass | 10,776 | 3,370 | -69% | 1 | 1 | 0% | 1,610 | 2,249 | +40% | 0 | 0 | — |
case-19 | pass→pass | 14,272 | 15,768 | +10% | 1 | 1 | 0% | 2,588 | 4,394 | +70% | 0 | 0 | — |
case-20 | pass→pass | 16,487 | 13,324 | -19% | 1 | 1 | 0% | 2,907 | 4,514 | +55% | 0 | 0 | — |
case-21 | pass→pass | 15,952 | 12,438 | -22% | 1 | 1 | 0% | 2,844 | 4,133 | +45% | 0 | 0 | — |
case-22 | fail→pass | 10,144 | 4,033 | -60% | 1 | 1 | 0% | 1,739 | 2,378 | +37% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +55 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.