Skip to content

Conversation

feitianbubu
Copy link
Contributor

@feitianbubu feitianbubu commented Aug 10, 2025

部分视频地址无法在模态框中直接播放, 如火山云
无法播放的改为支持弹出新窗口播放
image

Summary by CodeRabbit

  • New Features

    • Enhanced video content display in modals, including improved loading indicators and detailed error messages for video playback issues.
    • Added options to open the video URL in a new tab or copy the URL to clipboard directly from the modal.
    • Displays the video URL in a styled text box for easier reference.
  • Bug Fixes

    • Improved handling of video loading and error states for a smoother user experience.

Copy link
Contributor

coderabbitai bot commented Aug 10, 2025

Walkthrough

The ContentModal component in the task logs table was updated to improve video content handling. It now tracks video loading and error states using React hooks, displays a spinner during loading, and shows a detailed error message with actionable options and the video URL if playback fails.

Changes

Cohort / File(s) Change Summary
Enhanced Video Handling in ContentModal
web/src/components/table/task-logs/modals/ContentModal.jsx
Improved video playback logic: added state for loading and error, spinner overlay, detailed error UI, and action buttons for failed loads.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ContentModal
    participant VideoElement

    User->>ContentModal: Open modal with video
    ContentModal->>ContentModal: Reset error, set isLoading=true
    ContentModal->>VideoElement: Render video
    VideoElement-->>ContentModal: onLoadStart
    VideoElement-->>ContentModal: onLoadedData (success)
    ContentModal->>ContentModal: Set isLoading=false

    alt Video load error
        VideoElement-->>ContentModal: onError
        ContentModal->>ContentModal: Set videoError=true, isLoading=false
        ContentModal->>User: Show error message with actions
    end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

  • feat: add video preview modal #1429: Added initial video modal opening logic and basic video rendering in ContentModal, which this PR directly enhances with improved loading and error handling.

Poem

A bunny pressed play, but the video stalled—
Now spinners and messages keep us enthralled.
With buttons to copy or open anew,
The modal’s much smarter in what it can do.
If errors arise, don’t hop in despair—
The bunny’s new modal will always play fair! 🐇✨

Note

🔌 MCP (Model Context Protocol) integration is now available in Early Access!

Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a 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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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

🧹 Nitpick comments (5)
web/src/components/table/task-logs/modals/ContentModal.jsx (5)

35-41: Reset loading/error when the video URL changes.

Include modalContent in deps to properly reset state if the source changes while open.

-  }, [isModalOpen, isVideo]);
+  }, [isModalOpen, isVideo, modalContent]);

117-126: Force video remount on URL change to avoid stale state.

Add a stable key; also consider playsInline for mobile autoplay behavior.

-        <video 
+        <video
+          key={modalContent}
           src={modalContent} 
           controls 
           style={{ width: '100%' }} 
           autoPlay
+          playsInline
           crossOrigin="anonymous"
           onError={handleVideoError}
           onLoadedData={handleVideoLoaded}
           onLoadStart={() => setIsLoading(true)}
         />

42-45: Align behavior with PR title: auto-open on error (subject to popup blockers).

If the requirement is to auto-open when playback fails, invoke the handler on error. Note many browsers block non-user-initiated window.open; keep the buttons as fallback.

   const handleVideoError = () => {
     setVideoError(true);
     setIsLoading(false);
+    // Optional: auto-open fallback (may be blocked by popup settings)
+    handleOpenInNewTab();
   };

If desired, we can gate this behind a prop (e.g., autoOpenOnError) for configurability.


107-115: Spinner overlay should not intercept clicks.

Set pointer-events to none so it doesn’t block interactions when visible.

-            zIndex: 10
+            zIndex: 10,
+            pointerEvents: 'none'
           }}>

61-75: Prefer semantic list markup for accessibility.

Replace multiple Text blocks with a ul/li list for screen readers; keep styles as needed.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dbde044 and ef0780c.

📒 Files selected for processing (1)
  • web/src/components/table/task-logs/modals/ContentModal.jsx (1 hunks)
🔇 Additional comments (1)
web/src/components/table/task-logs/modals/ContentModal.jsx (1)

121-123: Verify need for crossOrigin on video.

crossOrigin="anonymous" often triggers CORS failures unless the CDN sends appropriate CORS headers for media. If not strictly required, consider removing it or making it conditional.

Comment on lines +51 to +53
const handleCopyUrl = () => {
navigator.clipboard.writeText(modalContent);
};
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Clipboard: add error handling and user feedback (fallback included).

Improve resiliency and UX when copying.

-  const handleCopyUrl = () => {
-    navigator.clipboard.writeText(modalContent);
-  };
+  const handleCopyUrl = async () => {
+    try {
+      await navigator.clipboard.writeText(modalContent);
+      Toast.success('链接已复制');
+    } catch {
+      try {
+        const el = document.createElement('textarea');
+        el.value = modalContent;
+        el.setAttribute('readonly', '');
+        el.style.position = 'absolute';
+        el.style.left = '-9999px';
+        document.body.appendChild(el);
+        el.select();
+        const ok = document.execCommand('copy');
+        document.body.removeChild(el);
+        if (ok) {
+          Toast.success('链接已复制');
+        } else {
+          throw new Error('copy failed');
+        }
+      } catch {
+        Toast.error('复制失败');
+      }
+    }
+  };
📝 Committable suggestion

‼️ 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.

Suggested change
const handleCopyUrl = () => {
navigator.clipboard.writeText(modalContent);
};
const handleCopyUrl = async () => {
try {
await navigator.clipboard.writeText(modalContent);
Toast.success('链接已复制');
} catch {
try {
const el = document.createElement('textarea');
el.value = modalContent;
el.setAttribute('readonly', '');
el.style.position = 'absolute';
el.style.left = '-9999px';
document.body.appendChild(el);
el.select();
const ok = document.execCommand('copy');
document.body.removeChild(el);
if (ok) {
Toast.success('链接已复制');
} else {
throw new Error('copy failed');
}
} catch {
Toast.error('复制失败');
}
}
};
🤖 Prompt for AI Agents
In web/src/components/table/task-logs/modals/ContentModal.jsx around lines 51 to
53, the handleCopyUrl function currently writes text to the clipboard without
error handling or user feedback. Update this function to include a try-catch
block to handle potential errors when accessing the clipboard API. Provide user
feedback on success or failure, and implement a fallback method for copying the
text if the clipboard API is unavailable or fails.

Comment on lines +55 to +57
const handleOpenInNewTab = () => {
window.open(modalContent, '_blank');
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Secure window.open and validate URL before opening (prevent tabnabbing + unsafe schemes).

Harden the open logic and block unsafe protocols. Also add Toast feedback.

Apply these diffs:

- import { Modal, Button, Typography, Spin } from '@douyinfe/semi-ui';
+ import { Modal, Button, Typography, Spin, Toast } from '@douyinfe/semi-ui';
-  const handleOpenInNewTab = () => {
-    window.open(modalContent, '_blank');
-  };
+  const handleOpenInNewTab = () => {
+    try {
+      const u = new URL(modalContent, window.location.href);
+      if (!['http:', 'https:', 'blob:'].includes(u.protocol)) {
+        Toast.error('链接协议不被支持');
+        return;
+      }
+      const w = window.open(u.toString(), '_blank', 'noopener,noreferrer');
+      if (w) {
+        w.opener = null;
+      } else {
+        Toast.warning('浏览器阻止了弹窗,请允许弹窗或手动点击按钮');
+      }
+    } catch {
+      Toast.error('链接无效');
+    }
+  };

Also applies to: 21-21

🤖 Prompt for AI Agents
In web/src/components/table/task-logs/modals/ContentModal.jsx around lines 55 to
57, the handleOpenInNewTab function uses window.open without validating the URL
or securing against tabnabbing. To fix this, validate that modalContent is a
safe URL with allowed protocols (e.g., http, https), prevent tabnabbing by
adding rel="noopener noreferrer" to the window.open call, and add a Toast
notification to inform the user if the URL is invalid or blocked.

Comment on lines 136 to +141
closable={null}
bodyStyle={{ height: '400px', overflow: 'auto' }}
bodyStyle={{
height: isVideo ? '450px' : '400px',
overflow: 'auto',
padding: isVideo && videoError ? '0' : '24px'
}}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid non-boolean closable prop; make modal sizing responsive.

Use a proper boolean and use viewport-based height for better small-screen UX.

-      closable={null}
-      bodyStyle={{ 
-        height: isVideo ? '450px' : '400px', 
-        overflow: 'auto',
-        padding: isVideo && videoError ? '0' : '24px'
-      }}
+      closable={false}
+      bodyStyle={{
+        height: isVideo ? '70vh' : '60vh',
+        maxHeight: '80vh',
+        overflow: 'auto',
+        padding: isVideo && videoError ? '0' : '24px'
+      }}
📝 Committable suggestion

‼️ 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.

Suggested change
closable={null}
bodyStyle={{ height: '400px', overflow: 'auto' }}
bodyStyle={{
height: isVideo ? '450px' : '400px',
overflow: 'auto',
padding: isVideo && videoError ? '0' : '24px'
}}
closable={false}
bodyStyle={{
height: isVideo ? '70vh' : '60vh',
maxHeight: '80vh',
overflow: 'auto',
padding: isVideo && videoError ? '0' : '24px'
}}
🤖 Prompt for AI Agents
In web/src/components/table/task-logs/modals/ContentModal.jsx around lines 136
to 141, the closable prop is set to null which is not a valid boolean value and
the modal height is fixed in pixels. Change the closable prop to a proper
boolean value (true or false) as required. Replace the fixed height values with
viewport-relative units (e.g., vh) to make the modal height responsive and
improve usability on small screens.

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