Skip to content

Conversation

@lulusir
Copy link
Contributor

@lulusir lulusir commented Nov 6, 2025

Types

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

Background or solution

Changelog

Summary by CodeRabbit

发布说明

  • 新功能
    • 新增图像文件变更事件通道,专门通知图像相关的文件更新。
    • 图像预览加入缓存刷新机制:检测到图像变更时自动更新预览以显示最新内容。
  • 测试
    • 新增单元测试覆盖图像变更事件的触发与过滤行为。

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

coderabbitai bot commented Nov 6, 2025

Walkthrough

在文件服务中新增图像专用变更事件通道,并在预览组件中订阅该事件;预览组件维护 fileChanged 计数并将其作为 _t 查询参数追加到图片 src,以在图像文件变更时重建并刷新预览 URL。

Changes

Cohort / File(s) 变更摘要
接口扩展
packages/file-service/src/common/file-service-client.ts
IFileServiceClient 接口新增 onImageFilesChanged: Event<FileChangeEvent> 事件属性。
文件服务客户端实现
packages/file-service/src/browser/file-service-client.ts
引入 EXT_LIST_IMAGE;在 FileServiceClient 中新增受保护发射器 _onImageFilesChanged 与公开事件 onImageFilesChanged;在 fireFilesChange 中过滤图像文件变更并条件触发该事件;在 dispose() 中销毁发射器。
预览组件(客户端视图)
packages/file-scheme/src/browser/preview.view.tsx
新增订阅图像变更的内部 hook(useResourceChange),维护 fileChanged 计数;将该计数作为 _t 查询参数追加到图片 src(安全构建 URL,回退原始 src);调整 effect 依赖为 [src, fileChanged],在资源或文件变更时重建并应用新 src。
测试新增
packages/file-service/__tests__/browser/file-service-client.test.ts
新增 onImageFilesChanged 测试:触发包含图像和非图像变更,断言事件仅包含图像 URI;测试中使用 FileChangeType

Sequence Diagram(s)

sequenceDiagram
    participant FS as 文件系统
    participant FSC as FileServiceClient
    participant PV as PreviewView
    participant B as 浏览器缓存

    FS->>FSC: 通知文件变更列表
    activate FSC
    FSC->>FSC: 过滤 EXT_LIST_IMAGE 得到 imageChanges
    alt imageChanges 非空
        FSC->>PV: 触发 onImageFilesChanged(imageChanges)
    end
    deactivate FSC

    activate PV
    PV->>PV: useResourceChange 匹配当前资源 URI
    PV->>PV: fileChanged += 1
    PV->>PV: 构建新 src(原始 src + ?_t=fileChanged)
    PV->>B: 请求新 src(强制刷新)
    B-->>PV: 返回最新图像
    deactivate PV
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 分钟

需重点复核:

  • fireFilesChange 中基于 EXT_LIST_IMAGE 的扩展名匹配与过滤逻辑(大小写、查询/片段处理、边界情况)。
  • useResourceChange / 资源 URI 对比逻辑(URI 标准化、编码与相对/绝对路径差异)。
  • 通过追加 _t 查询参数实现的缓存破坏:URL 构建的健壮性和回退分支(非 URL 字符串处理)。
  • 新增测试的确定性,确保对混合变更(图像/非图像)的断言稳定。

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 拉取请求标题准确反映了主要变化,即在图片内容更改后触发重新渲染图片。标题与所有更改的核心目标相符。
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/image-preview

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4fdb275 and 369cbaa.

📒 Files selected for processing (2)
  • packages/file-service/src/browser/file-service-client.ts (4 hunks)
  • packages/file-service/src/common/file-service-client.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 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/file-service/src/browser/file-service-client.ts
🧬 Code graph analysis (2)
packages/file-service/src/browser/file-service-client.ts (5)
packages/utils/src/event.ts (2)
  • Emitter (590-775)
  • Event (24-24)
packages/core-common/src/types/file-watch.ts (1)
  • FileChangeEvent (139-139)
packages/core-browser/src/fs/index.ts (1)
  • FilesChangeEvent (10-10)
packages/utils/src/uri.ts (2)
  • URI (6-6)
  • URI (17-311)
packages/file-service/src/common/file-ext.ts (1)
  • EXT_LIST_IMAGE (3-27)
packages/file-service/src/common/file-service-client.ts (1)
packages/core-common/src/types/file-watch.ts (1)
  • FileChangeEvent (139-139)
⏰ 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). (7)
  • GitHub Check: ubuntu-latest, Node.js 20.x
  • GitHub Check: build (ubuntu-latest, 20.x)
  • GitHub Check: build (macos-latest, 20.x)
  • GitHub Check: unittest (macos-latest, 18.x, jsdom)
  • GitHub Check: unittest (ubuntu-latest, 18.x, jsdom)
  • GitHub Check: unittest (ubuntu-latest, 18.x, node)
  • GitHub Check: unittest (macos-latest, 18.x, node)
🔇 Additional comments (5)
packages/file-service/src/common/file-service-client.ts (1)

37-38: 新增的事件属性定义正确

接口中新增 onImageFilesChanged 事件属性的定义符合现有模式,类型正确,位置合理。

packages/file-service/src/browser/file-service-client.ts (4)

54-54: 导入语句正确

导入的 EXT_LIST_IMAGE 用于后续的图片文件过滤逻辑,导入路径正确。


87-88: Emitter 声明符合规范

新增的 _onImageFilesChanged emitter 和对应的公开事件 onImageFilesChanged 遵循了类中现有的事件模式,命名和类型都正确。


178-178: 资源清理已正确实现

_onImageFilesChanged 的清理逻辑已在 dispose 方法中正确实现,防止内存泄漏。


365-379: 原始审查意见不正确 - 无需修改

根据代码验证,Path 类中的 ext 属性始终是 string 类型(第 68 行声明为 readonly ext: string),构造函数确保在所有分支中都将其初始化为字符串值:无扩展名文件时为空字符串 ''(第 91、95 行),有扩展名时为子字符串(第 98 行)。

因此 Line 373 的代码是安全的,不会抛出 TypeError。可选链操作符 ?. 虽然多余,但不会导致问题。建议的防御性写法不必要。

Likely an incorrect or invalid review comment.


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: 4

🧹 Nitpick comments (3)
packages/file-service/src/browser/file-service-client.ts (1)

361-369: 考虑性能优化:减少 URI 对象创建

在高频文件变更场景下,为每个变更事件都创建 URI 对象可能影响性能。考虑以下优化方案:

优化方案 1 - 使用字符串操作预筛选:

 // 过滤图片文件变化并触发专门的事件
 const imageChanges = changes.filter((change) => {
+  // 快速字符串检查,避免创建 URI 对象
+  const uriStr = change.uri;
+  const lastDotIndex = uriStr.lastIndexOf('.');
+  if (lastDotIndex === -1) return false;
+  
+  const ext = uriStr.substring(lastDotIndex + 1).toLowerCase();
+  if (!EXT_LIST_IMAGE.has(ext)) return false;
+  
+  // 只有匹配时才创建 URI 对象进行精确验证
   const uri = new URI(change.uri);
-  const ext = uri.path.ext?.toLowerCase().replace('.', '');
-  return ext && EXT_LIST_IMAGE.has(ext);
+  return uri.path.ext?.toLowerCase().replace('.', '') === ext;
 });

优化方案 2 - 批量处理:

 const imageChanges = changes.filter((change) => {
   const uri = new URI(change.uri);
   const ext = uri.path.ext?.toLowerCase().replace('.', '');
   return ext && EXT_LIST_IMAGE.has(ext);
 });

 if (imageChanges.length > 0) {
+  // 考虑使用 debounce 或节流来避免频繁触发
   this._onImageFilesChanged.fire(imageChanges);
 }
packages/file-service/src/common/file-service-client.ts (1)

35-35: 接口扩展正确

新增的 onImageFilesChanged 事件接口定义正确,类型与实现保持一致。建议添加 JSDoc 注释说明事件的用途和触发时机,以提高可维护性。

可以添加文档注释:

  onFilesChanged: Event<FileChangeEvent>;

+  /**
+   * Event that fires when image files are changed.
+   * This event only includes changes to files with image extensions.
+   */
  onImageFilesChanged: Event<FileChangeEvent>;
packages/file-scheme/src/browser/preview.view.tsx (1)

28-28: 优化 effect 依赖项

fileServiceClient 是通过 DI 注入的稳定实例,通常不需要作为依赖项。可以考虑移除以避免不必要的重新订阅。

-  }, [resource.uri, fileServiceClient]);
+  }, [resource.uri]);

或者使用 useRef 保存 fileServiceClient 以确保稳定引用。

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c92dcee and 801c008.

📒 Files selected for processing (3)
  • packages/file-scheme/src/browser/preview.view.tsx (2 hunks)
  • packages/file-service/src/browser/file-service-client.ts (3 hunks)
  • packages/file-service/src/common/file-service-client.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
packages/file-scheme/src/browser/preview.view.tsx (3)
packages/editor/src/common/resource.ts (1)
  • IResource (114-132)
packages/core-browser/src/react-hooks/injectable-hooks.tsx (1)
  • useInjectable (16-39)
packages/file-service/src/common/file-service-client.ts (2)
  • IFileServiceClient (27-27)
  • IFileServiceClient (29-118)
packages/file-service/src/common/file-service-client.ts (1)
packages/core-common/src/types/file-watch.ts (1)
  • FileChangeEvent (91-91)
packages/file-service/src/browser/file-service-client.ts (5)
packages/utils/src/event.ts (2)
  • Emitter (590-775)
  • Event (24-24)
packages/core-common/src/types/file-watch.ts (1)
  • FileChangeEvent (91-91)
packages/core-browser/src/fs/index.ts (1)
  • FilesChangeEvent (3-3)
packages/utils/src/uri.ts (2)
  • URI (6-6)
  • URI (17-311)
packages/file-service/src/common/file-ext.ts (1)
  • EXT_LIST_IMAGE (3-27)
🔇 Additional comments (1)
packages/file-service/src/browser/file-service-client.ts (1)

361-365: 代码扩展名提取逻辑验证完毕,无需改动

基于代码库验证,uri.path.ext 的行为已确认:

  • 返回带点的扩展名(如 .png),或空字符串(文件无扩展名)
  • 多个点的情况下返回最后一个点之后的部分(如 file.backup.png 返回 .png
  • 第 363-364 行的逻辑正确处理所有边界情况:
    • 无扩展名时,ext 为空字符串(falsy),过滤返回 false ✓
    • replace('.', '') 仅移除首个点,结果准确 ✓

无附加问题发现。

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

🧹 Nitpick comments (2)
packages/file-service/__tests__/browser/file-service-client.test.ts (1)

168-190: 建议改进异步测试的错误处理

当前测试使用了 inner() 异步函数但没有等待其完成或处理错误。如果 fireFilesChange 抛出异常,可能导致未捕获的 Promise 拒绝或测试挂起。

建议改进错误处理:

  it('onImageFilesChanged event', (done) => {
    async function inner() {
      fileServiceClient.onImageFilesChanged((event) => {
        // 期望只收到一个image的event
        expect(event.every((v) => v.uri.includes('a.jpg'))).toBeTruthy();
        done();
      });
      // 触发两个change
      await fileServiceClient.fireFilesChange({
        changes: [
          {
            uri: 'a.jpg',
            type: FileChangeType.UPDATED,
          },
          {
            uri: 'a.log',
            type: FileChangeType.UPDATED,
          },
        ],
      });
    }
-   inner();
+   inner().catch(done);
  });
packages/file-scheme/src/browser/preview.view.tsx (1)

61-76: 移除未使用的 Disposable 对象

Effect 中创建的 Disposable 对象没有被实际使用,只是创建后立即销毁,没有实际用途。

建议简化代码:

  React.useEffect(() => {
-   const disposer = new Disposable();
    if (imgRef.current) {
      try {
        const url = new URL(src);
        url.searchParams.set('_t', fileChanged.toString());
        imgRef.current.src = url.href;
      } catch (error) {
        // 如果 src 不是有效的 URL,直接使用原始 src
        imgRef.current.src = src;
      }
    }
-   return () => {
-     disposer.dispose();
-   };
  }, [src, fileChanged]);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 801c008 and 4fdb275.

📒 Files selected for processing (3)
  • packages/file-scheme/src/browser/preview.view.tsx (2 hunks)
  • packages/file-service/__tests__/browser/file-service-client.test.ts (2 hunks)
  • packages/file-service/src/browser/file-service-client.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/file-service/src/browser/file-service-client.ts
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2024-10-30T12:55:07.459Z
Learnt from: weiwen111
Repo: opensumi/core PR: 4139
File: packages/core-browser/src/window/window.service.ts:0-0
Timestamp: 2024-10-30T12:55:07.459Z
Learning: 在 `packages/core-browser/src/window/window.service.ts` 中,`workspace` 可能是以 `http` 开头的 URI,此时 `fsPath` 方法不可用。需要根据 `workspaceUri.scheme` 来判断并分别处理不同协议的 URI。

Applied to files:

  • packages/file-service/__tests__/browser/file-service-client.test.ts
  • packages/file-scheme/src/browser/preview.view.tsx
📚 Learning: 2024-10-30T12:51:05.546Z
Learnt from: weiwen111
Repo: opensumi/core PR: 4139
File: packages/core-browser/src/window/window.service.ts:0-0
Timestamp: 2024-10-30T12:51:05.546Z
Learning: 在 Web 环境中,使用 `workspaceUri.path.toString()` 获取路径可能仍然包含 `file://` 前缀,应该使用 `workspaceUri.fsPath` 来获取不含 `file://` 前缀的路径。

Applied to files:

  • packages/file-scheme/src/browser/preview.view.tsx
🧬 Code graph analysis (1)
packages/file-scheme/src/browser/preview.view.tsx (3)
packages/editor/src/common/resource.ts (1)
  • IResource (114-132)
packages/core-browser/src/react-hooks/injectable-hooks.tsx (1)
  • useInjectable (16-39)
packages/file-service/src/common/file-service-client.ts (2)
  • IFileServiceClient (27-27)
  • IFileServiceClient (29-118)
🔇 Additional comments (1)
packages/file-scheme/src/browser/preview.view.tsx (1)

14-34: 实现正确,已解决之前的 URI 比较问题

Hook 的实现逻辑正确:

  • 正确订阅图片文件变更事件
  • 使用 URI.isEqual 进行可靠的 URI 比较(已解决之前的问题)
  • 依赖项设置合理,确保资源变更时重新订阅

@lulusir
Copy link
Contributor Author

lulusir commented Nov 6, 2025

/next

@opensumi
Copy link
Contributor

opensumi bot commented Nov 6, 2025

🎉 PR Next publish successful!

3.9.1-next-1762421442.0

@codecov
Copy link

codecov bot commented Nov 6, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.64%. Comparing base (c92dcee) to head (369cbaa).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4662   +/-   ##
=======================================
  Coverage   52.63%   52.64%           
=======================================
  Files        1686     1686           
  Lines      104458   104468   +10     
  Branches    22707    22701    -6     
=======================================
+ Hits        54986    55000   +14     
+ Misses      41103    41099    -4     
  Partials     8369     8369           
Flag Coverage Δ
jsdom 48.18% <100.00%> (+<0.01%) ⬆️
node 12.03% <0.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Member

@Ricbet Ricbet left a comment

Choose a reason for hiding this comment

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

LGTM

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.

3 participants