Skip to content

Conversation

@minhhlki
Copy link

@minhhlki minhhlki commented Nov 5, 2025

This feature allows users to quickly import multiple time ranges using a simple text format like "03:05-03:10|40:05-40:10|1:03:05-1:04:05" to cut and concatenate video segments.

Key changes:

  • Created new TimeRangeImport dialog component with live preview
  • Supports flexible time format: HH:MM:SS, MM:SS, or SS
  • Shows total duration and segment count before import
  • Added scissors button in TopMenu to trigger the feature
  • Integrated with existing segment management system

The dialog provides:

  • Real-time validation and preview of parsed segments
  • Example format shown to guide users
  • Total duration calculation
  • Clear error messages for invalid input

This makes it much faster to extract and concatenate specific portions of long videos without manually creating each segment.

Summary by CodeRabbit

  • New Features

    • Time-range import via a new top‑menu button
    • Interactive import dialog with live preview, validation, per‑segment durations, and bulk import action
    • Supports common time formats and shows helpful error feedback
  • Documentation

    • Added a user guide and UI layout describing the import workflow, formats, examples, and troubleshooting

This feature allows users to quickly import multiple time ranges using a simple text format
like "03:05-03:10|40:05-40:10|1:03:05-1:04:05" to cut and concatenate video segments.

Key changes:
- Created new TimeRangeImport dialog component with live preview
- Supports flexible time format: HH:MM:SS, MM:SS, or SS
- Shows total duration and segment count before import
- Added scissors button in TopMenu to trigger the feature
- Integrated with existing segment management system

The dialog provides:
- Real-time validation and preview of parsed segments
- Example format shown to guide users
- Total duration calculation
- Clear error messages for invalid input

This makes it much faster to extract and concatenate specific portions
of long videos without manually creating each segment.
@coderabbitai
Copy link

coderabbitai bot commented Nov 5, 2025

Walkthrough

Adds a TimeRangeImport modal component, integrates it into App by wiring state and handlers, exposes a new "Import time ranges" button in TopMenu, and threads a toggle prop through StreamsSelector to trigger the import flow. Also exports a TimeRange type.

Changes

Cohort / File(s) Change Summary
Time Range Import Component
src/renderer/src/components/TimeRangeImport.tsx
New React component: modal UI to input, parse, validate, preview, and submit time-range segments. Exports TimeRange interface and default (memo-wrapped) component. Includes parseTimeRanges and formatTime utilities.
App Integration
src/renderer/src/App.tsx
Adds local state and handlers to show/hide TimeRangeImport, imports TimeRangeImport and TimeRange type, renders the modal, and wires toggleTimeRangeImport into child components.
TopMenu Button
src/renderer/src/TopMenu.tsx
Adds toggleTimeRangeImport: () => void prop to TopMenu signature and renders a new Button (FaScissors) that calls the prop to open the TimeRangeImport modal.
StreamsSelector Prop
src/renderer/src/StreamsSelector.tsx
Adds toggleTimeRangeImport: () => void prop to StreamsSelector and exposes it for triggering the import flow.
Docs / Guides
FEATURE_GUIDE.md, UI_LAYOUT.txt
Adds documentation and UI layout describing the Import Time Ranges feature, formats, examples, and workflow (no code changes).

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant TopMenu
    participant App
    participant TimeRangeImport
    participant StreamsSelector
    participant ImportHandler as onImport

    User->>TopMenu: Click "Import time ranges"
    TopMenu->>App: toggleTimeRangeImport()
    App->>TimeRangeImport: show modal (isShown=true)
    Note right of TimeRangeImport: Modal displayed (input, preview)

    User->>TimeRangeImport: Enter ranges / preview
    TimeRangeImport->>TimeRangeImport: parseTimeRanges() / formatTime()
    TimeRangeImport->>User: Show preview or validation error

    User->>TimeRangeImport: Click "Import Segments"
    TimeRangeImport->>TimeRangeImport: Validate parsed ranges
    alt success
        TimeRangeImport->>ImportHandler: onImport(parsedRanges)
        ImportHandler->>App: apply ranges (update state)
        App->>TimeRangeImport: hide modal (isShown=false)
    else failure
        TimeRangeImport->>User: Show error
    end

    %% StreamsSelector may also trigger modal
    User->>StreamsSelector: Request import
    StreamsSelector->>App: toggleTimeRangeImport()
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review parseTimeRanges for edge cases and locale/time-format handling.
  • Verify App state wiring and that isShown and callbacks are passed consistently.
  • Confirm TopMenu and StreamsSelector prop signatures and usages updated everywhere they are imported/used.
  • Inspect modal focus/cleanup and error paths in TimeRangeImport.

Poem

🐰 I nibble text and trim the time,
Scissors click in a tiny rhyme,
Ranges parsed and previews gleam,
Segments hop into the stream,
Happy cuts and export dreams ✂️

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and clearly describes the main feature being added—a time range import capability for video segment trimming—and directly reflects the changeset's primary purpose.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • 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

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

Copy link

@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

🧹 Nitpick comments (3)
src/renderer/src/App.tsx (1)

1656-1665: Consider adding a confirmation or append option.

The current implementation replaces all existing segments (append: false). Users who already have segments might lose their work unexpectedly. Consider either:

  1. Adding a confirmation dialog when segments exist
  2. Providing an option to append vs. replace
  3. At minimum, documenting this behavior clearly in the UI
src/renderer/src/components/TimeRangeImport.tsx (2)

29-29: Consider ESLint-compliant arrow function syntax.

ESLint flags the arrow function parameters without parentheses and suggests using Boolean directly instead of s => s.

Apply this diff for cleaner code:

-const segments = input.split('|').map(s => s.trim()).filter(s => s);
+const segments = input.split('|').map((s) => s.trim()).filter(Boolean);

176-184: Consider using a stable key for list items.

Using array index as key can cause issues with React's reconciliation, especially if the list order changes.

Use a more stable key:

-{previewRanges.map((range, index) => (
-  <div key={index} style={{ marginBottom: '.3em', fontSize: '.9em' }}>
+{previewRanges.map((range, index) => (
+  <div key={`${range.start}-${range.end}`} style={{ marginBottom: '.3em', fontSize: '.9em' }}>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2511045 and 55530c4.

📒 Files selected for processing (3)
  • src/renderer/src/App.tsx (5 hunks)
  • src/renderer/src/TopMenu.tsx (4 hunks)
  • src/renderer/src/components/TimeRangeImport.tsx (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/renderer/src/App.tsx (1)
src/renderer/src/components/TimeRangeImport.tsx (1)
  • TimeRange (210-210)
src/renderer/src/components/TimeRangeImport.tsx (3)
src/renderer/src/util/duration.ts (1)
  • parseDuration (53-80)
src/renderer/src/colors.ts (1)
  • dangerColor (2-2)
src/renderer/src/components/Button.tsx (1)
  • DialogButton (17-20)
🪛 ESLint
src/renderer/src/components/TimeRangeImport.tsx

[error] 29-29: Expected parentheses around arrow function argument.

(arrow-parens)


[error] 29-29: Expected parentheses around arrow function argument.

(arrow-parens)


[error] 29-29: arrow function is equivalent to Boolean. Use Boolean directly.

(unicorn/prefer-native-coercion-functions)


[error] 32-32: Expected parentheses around arrow function argument.

(arrow-parens)


[error] 177-177: Do not use Array index in keys

(react/no-array-index-key)

🔇 Additional comments (4)
src/renderer/src/TopMenu.tsx (1)

157-159: LGTM! Clean integration.

The new Import time ranges button follows existing patterns and is well-placed in the toolbar.

src/renderer/src/App.tsx (1)

2785-2785: LGTM! Proper component integration.

The TimeRangeImport component is correctly wired with appropriate props.

src/renderer/src/components/TimeRangeImport.tsx (2)

10-13: LGTM! Clean interface definition.

The TimeRange interface is simple and appropriate for representing time segments.


56-207: Well-designed component with good UX!

The TimeRangeImport component provides:

  • Live preview of parsed segments
  • Clear validation feedback
  • Auto-focus for better UX
  • Total duration calculation
  • Helpful examples and placeholders

The implementation is clean and follows React best practices.

Comment on lines +39 to +48
const start = parseDuration(startStr);
const end = parseDuration(endStr);

if (start == null || end == null) {
return null; // Invalid time format
}

if (start >= end) {
return null; // Start must be before end
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add validation for negative time values.

The function doesn't validate that start and end are non-negative. Since parseDuration can return negative values (as seen in the codebase context), segments with negative times could be created, which doesn't make sense for video trimming.

Add validation after parsing:

 const start = parseDuration(startStr);
 const end = parseDuration(endStr);

 if (start == null || end == null) {
   return null; // Invalid time format
 }

+if (start < 0 || end < 0) {
+  return null; // Times must be non-negative
+}
+
 if (start >= end) {
   return null; // Start must be before end
 }
📝 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 start = parseDuration(startStr);
const end = parseDuration(endStr);
if (start == null || end == null) {
return null; // Invalid time format
}
if (start >= end) {
return null; // Start must be before end
}
const start = parseDuration(startStr);
const end = parseDuration(endStr);
if (start == null || end == null) {
return null; // Invalid time format
}
if (start < 0 || end < 0) {
return null; // Times must be non-negative
}
if (start >= end) {
return null; // Start must be before end
}
🤖 Prompt for AI Agents
In src/renderer/src/components/TimeRangeImport.tsx around lines 39 to 48, the
parsed start/end values are not checked for negativity; after calling
parseDuration for startStr and endStr, validate that both start and end are >= 0
and return null (invalid) if either is negative (in addition to the existing
null and ordering checks), ensuring segments with negative times are rejected
before further processing.

@mifi
Copy link
Owner

mifi commented Nov 5, 2025

Thanks for your PR. How is it different from the Import YoutTube chapters feature? just the format?

Copy link

@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)
UI_LAYOUT.txt (2)

15-45: Mixed language content: Consider UI localization strategy.

The dialog description mixes Vietnamese and English text. If this is meant to reflect actual UI strings, clarify whether:

  1. The UI will be fully localized based on user preferences, or
  2. Vietnamese guidance is temporary for development purposes

If documentation, consider standardizing on a single language or clearly marking which parts represent translatable strings vs. developer notes.


24-27: Format specification is clear but consider documenting edge cases.

The time range format example is well-presented. For completeness, the documentation could clarify:

  • Are leading zeros required (e.g., 03:05 vs 3:05)?
  • What happens with invalid ranges (e.g., start time > end time)?
  • Are duplicate ranges allowed?

These details are likely implemented in TimeRangeImport.tsx but documenting them here would help users understand constraints.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 55530c4 and 7a65ce4.

📒 Files selected for processing (2)
  • FEATURE_GUIDE.md (1 hunks)
  • UI_LAYOUT.txt (1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.18.1)
FEATURE_GUIDE.md

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

(MD040, fenced-code-language)


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

(MD040, fenced-code-language)


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

(MD040, fenced-code-language)


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

(MD040, fenced-code-language)


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

(MD040, fenced-code-language)


122-122: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

🔇 Additional comments (3)
FEATURE_GUIDE.md (2)

7-11: Add language identifiers to fenced code blocks and fix heading formatting to pass markdown lint.

The static analysis detected markdown lint violations:

  • Lines 7, 44, 78, 84, 90: Fenced code blocks need language specification (MD040)
  • Line 122: Emphasis should not be used as heading (MD036)

Apply these fixes:

-```
+```bash
 ┌─────────────────────────────────────────────────────────────┐
 │  [Tracks] [Filter] [Working Dir] [Format] [Mode] 🌙 ✂️ ⚙️   │  <- TopMenu
 └─────────────────────────────────────────────────────────────┘
-```
+```
-  ```
+  ```bash
-  ```
+  ```
-```
+```bash
-```
+```
-```
+```bash
-```
+```
-```
+```bash
-```
+```
----
+## Additional Notes
-
-**Chúc bạn sử dụng tính năng hiệu quả! 🎬✂️**

Also applies to: 44-46, 78-80, 84-86, 90-92, 122-122


1-122: Comprehensive guide with clear structure and practical examples.

The feature guide is well-organized with step-by-step instructions, practical examples, and troubleshooting guidance. The Vietnamese documentation is clear and aligns well with the PR objectives. The guide effectively explains:

  • UI entry point (Scissors button in TopMenu)
  • Setup and execution flow
  • Flexible time format support with examples
  • Real-world use cases (intro/outro trimming, multi-segment extraction)
  • Common validation issues and troubleshooting
UI_LAYOUT.txt (1)

1-45: Documentation file: Clarify the purpose and location of this design document.

This file appears to be a UI specification/design document rather than executable code. While it clearly describes the intended feature layout with helpful ASCII diagrams and examples, consider whether this belongs in the main repository or should be kept in design/documentation folders or pull request discussions instead.

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.

3 participants