Skip to content

Conversation

@HellowVirgil
Copy link
Contributor

@HellowVirgil HellowVirgil commented Nov 18, 2025

Types

  • 🎉 New Features
  • 🐛 Bug Fixes
  • 📚 Documentation Changes
  • 💄 Code Style Changes
  • 💄 Style Changes
  • 🪚 Refactors
  • 🚀 Performance Improvements
  • 🏗️ Build System
  • ⏱ Tests
  • 🧹 Chores
  • Other Changes

Background or solution

当前 .ipynb 文件(Notebook 文件)使用 LibroOpensumiView 组件,这是一个基于 Libro 框架的自定义视图
Notebook 的状态管理在 Libro 框架内部,而不是 OpenSumi 的标准编辑器状态系统
当前Notebook 编辑器没有实现类似的状态保存/恢复机制,Libro 框架的视图状态没有与 OpenSumi 的编辑器状态系统集成,所以当切换 .ipynb 文件时,整个 LibroView 会被重新创建,而不是恢复之前的状态。

Changelog

新增 libro-state-manager 来对 libro 视图进行状态管理,实现多个 ipynb 文件之间切换能够保留位置。

2025-11-18.19.44.16.mov

Summary by CodeRabbit

发布说明

  • 新功能
    • 添加笔记本视图状态持久化功能,可自动保存和恢复笔记本的滚动位置和活跃时间
    • 重新打开笔记本时,视图状态自动恢复到上次离开时的位置
    • 集成防抖滚动事件处理,提升性能

@coffeedeveloper
Copy link
Contributor

/next

@HellowVirgil HellowVirgil force-pushed the feat/keep-notebook-switch-position branch from cf5911c to bdfd315 Compare November 18, 2025 11:51
@coffeedeveloper
Copy link
Contributor

/next

@opensumi opensumi bot added the 🎨 feature feature required label Nov 18, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 18, 2025

功能概览

引入了笔记本视图状态管理系统,通过新建LibroStateManager服务实现每个URI的视图状态(滚动位置、最后活跃时间)持久化与恢复,集成DI容器并在notebook视图中绑定状态保存/恢复逻辑。

变更列表

内聚组 / 文件 变更摘要
状态管理核心
packages/notebook/src/browser/libro-state-manager.ts
新文件。引入INotebookViewState接口(uri、scrollTop、lastActiveTime),INotebookStateManager接口(saveState、restoreState、clearState、getAllStates),以及LibroStateManager实现类。包含存储提供者、内存缓存、从DOM提取scrollTop、存储持久化和基础错误处理。
依赖注入配置
packages/notebook/src/browser/libro-state.ts
新文件。导出LibroStateModule常量,配置Provider数组映射LibroStateManager token到其实现类。
模块集成
packages/notebook/src/browser/libro.contribution.tsx
添加LibroStateModule导入,在initialize方法中通过app.injector.addProviders注册状态管理提供者。
视图状态绑定
packages/notebook/src/browser/libro.view.tsx
添加状态持久化与恢复逻辑:注入LibroStateManager,实现防抖滚动事件监听器(500ms延迟),在视图创建和加载完成后恢复状态,统一使用uri变量替代参数,扩展effect依赖关系。

序列图

sequenceDiagram
    participant View as LibroView
    participant Manager as LibroStateManager
    participant Storage as StorageProvider
    participant Cache as StateCache

    Note over View,Storage: 初始化时恢复状态
    View->>Manager: restoreState(uri, libroView)
    Manager->>Cache: 查询缓存中的scrollTop
    alt 缓存命中
        Manager->>View: 应用scrollTop到DOM
        Manager-->>View: 返回true
    else 缓存未命中
        Manager-->>View: 返回false
    end

    Note over View,Storage: 滚动事件处理(防抖)
    View->>View: 监听scroll事件(500ms防抖)
    View->>Manager: saveState(uri, libroView)
    Manager->>View: 从.libro-view-content提取scrollTop
    Manager->>Cache: 更新缓存中的状态
    Manager->>Storage: saveToStorage()持久化整个缓存
    Storage->>Storage: 存储到localStorage
Loading

代码审查工作量估计

🎯 3 (中等) | ⏱️ ~20 分钟

需要关注的重点:

  • libro.view.tsx:防抖滚动处理逻辑的时序与effect依赖关系需要验证,确保状态保存和恢复的顺序正确,避免竞态条件
  • 存储格式兼容性:验证StateCache序列化/反序列化的完整性,检查类型守卫isValidState的覆盖范围
  • DOM选择器硬编码.libro-view-content选择器的稳定性需要确认,防止因DOM结构变化导致失效
  • 异步流程restoreState为异步方法,需确认调用处都正确处理Promise

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确反映了主要变更:为notebook添加在标签页切换时保持滚动位置的功能,与所有相关代码更改(LibroStateManager状态管理系统)相符。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


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
Contributor

@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: 0

Caution

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

⚠️ Outside diff range comments (1)
packages/notebook/src/browser/libro.view.tsx (1)

48-98: 在 effect 中正确清理 debounce 防抖的滚动监听,避免事件泄漏和定时器触发

原始审查评论正确识别了问题。验证确认:

  1. DOM 引用不匹配:effect 依赖数组中缺少 libroView,导致清理函数中使用的 libroView?.container?.current 总是初始值(通常为 undefined),而绑定时使用的是 .then() 回调中的 libro 对象

  2. 防抖回调未取消:推荐做法是在 cleanup 中既调用 removeEventListener(同一引用),也调用 debounced.cancel() 以取消任何待执行的延迟调用,防止卸载后触发副作用,但当前代码中没有调用 handleScroll.cancel()

建议修复方案(保持原评论的 diff)完全符合最佳实践。需实施该修改以确保:

  • 绑定和解绑使用同一 DOM 元素引用
  • 组件卸载时取消待执行的防抖回调
🧹 Nitpick comments (1)
packages/notebook/src/browser/libro-state-manager.ts (1)

6-17: 考虑优化 StorageProvider 实例复用模式以提升效率

当前实现在 saveToStorage()(第 48-59 行)中每次调用都会通过 this.storageProvider(new URI('libro-notebook-storage')) 创建新的存储实例。由于 saveToStorage()saveState()(第 82 行)和 clearState()(第 107 行)多次调用,这会导致频繁的实例创建开销。

根据 OpenSumi 存储最佳实践,不建议为每次读/写都新建同一命名空间的存储实例,推荐在模块/服务生命周期内创建一次(或按必需的更大粒度)并复用该实例,以减少创建/初始化开销并保持一致性。

建议方案:在 LibroStateManager 中添加一个 storage 成员变量,在构造函数或 loadFromStorage() 初始化时创建一次,后续在 saveToStorage()restoreState() 等方法中复用该实例,避免重复创建。

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6d5fec0 and 195efff.

📒 Files selected for processing (4)
  • packages/notebook/src/browser/libro-state-manager.ts (1 hunks)
  • packages/notebook/src/browser/libro-state.ts (1 hunks)
  • packages/notebook/src/browser/libro.contribution.tsx (2 hunks)
  • packages/notebook/src/browser/libro.view.tsx (3 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2024-11-12T08:27:06.038Z
Learnt from: ensorrow
Repo: opensumi/core PR: 3945
File: packages/notebook/src/browser/libro.contribution.tsx:170-174
Timestamp: 2024-11-12T08:27:06.038Z
Learning: 在文件 'packages/notebook/src/browser/libro.contribution.tsx' 中,notebook 图标已适配暗色和亮色主题,无需修改。

Applied to files:

  • packages/notebook/src/browser/libro.view.tsx
  • packages/notebook/src/browser/libro.contribution.tsx
📚 Learning: 2024-10-12T07:43:08.790Z
Learnt from: bytemain
Repo: opensumi/core PR: 4088
File: packages/ai-native/src/browser/widget/inline-stream-diff/live-preview.decoration.tsx:73-74
Timestamp: 2024-10-12T07:43:08.790Z
Learning: 在 `LivePreviewDiffDecorationModel` 类(位于 `packages/ai-native/src/browser/widget/inline-stream-diff/live-preview.decoration.tsx`)中,通过依赖注入(`Autowired`)从 module 的 `providers` 声明中获取的依赖(如 `_onPartialEditEvent`),其销毁逻辑由 `ClientApp` 的生命周期管理,不需要手动调用 `dispose()` 进行销毁。

Applied to files:

  • packages/notebook/src/browser/libro.view.tsx
  • packages/notebook/src/browser/libro.contribution.tsx
🧬 Code graph analysis (2)
packages/notebook/src/browser/libro.view.tsx (1)
packages/core-browser/src/react-hooks/injectable-hooks.tsx (1)
  • useInjectable (16-39)
packages/notebook/src/browser/libro.contribution.tsx (1)
packages/notebook/src/browser/libro-state.ts (1)
  • LibroStateModule (5-10)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: unittest (ubuntu-latest, 18.x, jsdom)
  • GitHub Check: ubuntu-latest, Node.js 20.x
  • GitHub Check: unittest (macos-latest, 18.x, node)
  • GitHub Check: unittest (ubuntu-latest, 18.x, node)
  • GitHub Check: unittest (macos-latest, 18.x, jsdom)
  • GitHub Check: build (macos-latest, 20.x)
  • GitHub Check: build (ubuntu-latest, 20.x)
  • GitHub Check: build-windows
🔇 Additional comments (3)
packages/notebook/src/browser/libro.contribution.tsx (1)

47-48: Libro 状态模块注入方式合理

initialize 中通过 app.injector.addProviders(...LibroStateModule) 注册 LibroStateManager,配合 useInjectable(LibroStateManager) 的使用方式是符合 OpenSumi DI 模式的,不会影响现有逻辑,只是补充了状态管理能力,看起来没有问题。

Also applies to: 136-138

packages/notebook/src/browser/libro-state.ts (1)

1-10: DI 模块定义简洁有效

LibroStateModule 采用 { token: LibroStateManager, useClass: LibroStateManager } 的 ClassProvider 方式注册,能满足通过 useInjectable(LibroStateManager) 获取单例状态管理器的需求,实现上很干净,没有明显问题。

packages/notebook/src/browser/libro.view.tsx (1)

21-42: 状态保存 / 恢复整体思路清晰

通过 useInjectable(LibroStateManager) 注入服务,再用 saveNotebookStaterestoreNotebookState 以 URI 为 key 读写视图状态,同时用 isStateRestored 作为防重入标志,并在首个 effect 和 “延迟 100ms” 的第二个 effect 中各尝试一次恢复,基本可以覆盖视图创建早期 DOM 未完全 ready 的情况,逻辑上是合理的。

Also applies to: 100-108

@HellowVirgil
Copy link
Contributor Author

/next

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

Labels

🎨 feature feature required

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants