Skip to content

feat(video-editor): copy a clip's or layer's style and paste it onto others - #10307

Open
hm21 wants to merge 5 commits into
mainfrom
feat/video-editor-copy-paste-style
Open

hm21 wants to merge 5 commits into
mainfrom
feat/video-editor-copy-paste-style

Conversation

@hm21

@hm21 hm21 commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

Description

Giving five clips the same look, matching the EQ of two takes, or giving every caption the same enter animation meant setting each item up by hand, one tap at a time, and it was easy to end up slightly off. This adds Copy style and Paste style to the timeline's action bars.

Clips. Copy style takes a timeline clip's volume, EQ, speed, color mask and shape mask. Paste style puts them on the selected clip, or through clip multi-select on several clips at once. Pasting makes the target match the source, so a style copied from a clip without a color mask takes the target's color mask away (as a flat EQ flattens the target's).

  • The color mask is baked into a clip's file, so pasting it renders each target in turn behind the existing "Applying the color mask…" overlay. All targets land in one emit and the screen writes one undo step for the whole paste (clips, rebased markers, and sounds grown over a slowed-down end, as the speed sheet already does).
  • If one target's render fails, that clip keeps its own color mask, still takes the rest of the style, and a snackbar says how many clips failed.
  • Freeze frames only get Paste style and take only the shape mask; color/photo slots and stop-motion clips get neither action.
  • A paste that is still rendering counts as a pending clip operation, like the other renders, so the seamless-loop finder (feat(video-editor): suggest where the last clip ends for a seamless loop #10305) waits for it instead of slipping its temporary trim into the paste's undo step.

Layers (text, sticker, drawing, audio visualizer). Copy style takes opacity, enter/leave/loop animations and the shape mask, and for a text also its look (font, colors, background, alignment, size, outline, shadow — the same set saved title styles use). Each target takes what fits: a sticker takes a text's animations but not its look or its letter-by-letter/word-by-word typing, a visualizer takes no mask, and a layer with keyframes keeps the opacity its keyframes set. A shape mask keeps its proportions when pasted onto a differently shaped layer (a circle on a square sticker stays a circle on a wide text).

Layer multi-select is wider. Pasting onto several layers needs them selectable together, but multi-select only took static drawings or stickers, because it existed for Combine. It now takes every layer a style can go onto, mixed kinds included; Combine is offered only when the selection is two or more combinable drawings or two or more combinable stickers, and the bar names the selection "layers" when it is not only drawings or only stickers. The two kind-specific "Select multiple drawings/stickers" accessibility labels became one "Select multiple layers".

The copied clip style and the copied layer style live in a small cubit scoped to the open editor, kept apart because neither can be pasted where the other goes. The "Style copied" confirmation shows for 1.5 s instead of the default 4 s, because it floats over the action bar the next tap (Paste style or Select) needs.

Related Issue: Closes #10258

Demo

Clip style — copy speed and a color mask from the first clip, paste onto clips 2 and 3 in one go, undo and redo:

style_clips.mp4

Layer style — copy a text's look and animations, paste onto a plain text and a sticker, undo and redo:

style_layers.mp4

Out of Scope

  • Filters and adjustments are not part of a clip's style. They are timeline bars that can span several clips rather than clip settings, so "a clip's filter" has no single meaning; a whole-video filter already grades every clip.
  • Detached clips take no part yet: they are a clip and a layer at once, and their style would mix the two.
  • Across drafts: the copied style lasts while the editor is open, as the issue asks for first.

Verification

  • Verified on Galaxy S26: clip copy/paste with a 2× speed and a magenta color-mask backdrop onto two clips (both rendered, one undo reverts both), and layer copy/paste from an animated text onto a plain text and a sticker (one undo reverts both). See the videos above.
  • flutter analyze lib test integration_test: no issues.
  • All 65 CI guards via scripts/ci/run_guards.sh: pass (incl. plural categories, orphaned ARB keys, unpinned assertions).
  • Editor, model and l10n suites (3,697 tests) pass; new tests cover the paste bloc (per-target bakes, a failing bake, taking a mask off, freeze frames, no-op paste), ClipStyle/LayerStyle, mask transfer, the clipboard cubit, the paste result listener (one history entry, failure snackbar) and the copy/paste actions in both action bars.
  • New strings are translated into all 23 locales; docs/VIDEO_EDITOR_FEATURES.md describes the feature.

Type of Change

  • ✨ New feature (non-breaking change which adds functionality)
  • 🛠️ Bug fix (non-breaking change which fixes an issue)
  • ❌ Breaking change (fix or feature that would cause existing functionality to change)
  • 🧹 Code refactor
  • ✅ Build configuration change
  • 📝 Documentation
  • 🗑️ Chore

Agent identity

Agent-Model: anthropic/claude-opus-5-5
Agent-Effort: unknown
Agent-Harness: claude-code/unknown
Agent-Context: fresh
Initiated-By: @hm21

…others

Giving five clips the same look or four captions the same animation meant
repeating every setting by hand on each one. Copy style now takes a timeline
clip's volume, EQ, speed, color mask and shape mask, or a text, sticker,
drawing or visualizer's opacity, animations, shape mask and (for a text) its
look; Paste style puts it on the selected item or, through multi-select, on
several at once, as one undo step.

A pasted color mask is baked into each target in turn behind a progress
overlay; a target whose render fails keeps its own mask and takes the rest.
Filters and adjustments stay out of a clip's style because they are timeline
bars that can span several clips, not clip settings. Layer multi-select now
takes any layer a style can go onto, so Combine is only offered when the
selection can actually be combined.

Closes #10258
@hm21 hm21 self-assigned this Oct 19, 2026
@divine-roborev

divine-roborev Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

roborev: Review unavailable (a93af63)

No reviewer produced usable output. The automated review could not assess this change.

@hm21
hm21 marked this pull request as ready for review October 19, 2026 09:28
@hm21
hm21 requested a review from a team as a code owner October 19, 2026 09:28
@hm21
hm21 requested review from dcadenas and mbradley and removed request for a team October 19, 2026 09:28
@github-actions

This comment has been minimized.

…y-paste-style

# Conflicts:
#	mobile/lib/screens/video_editor/video_editor_screen.dart
#	mobile/lib/widgets/video_editor/timeline_editor/controls/video_editor_timeline_clip_controls.dart
#	mobile/test/widgets/video_editor/timeline_editor/controls/video_editor_timeline_clip_controls_test.dart
#	mobile/test/widgets/video_editor/timeline_editor/controls/video_editor_timeline_control_bar_test.dart
#	mobile/test/widgets/video_editor/timeline_editor/video_editor_timeline_test.dart
#	mobile/test/widgets/video_editor/video_editor_scaffold_test.dart
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

…y-paste-style

# Conflicts:
#	mobile/lib/widgets/video_editor/timeline_editor/controls/video_editor_timeline_multi_select_controls.dart
#	mobile/test/widgets/video_editor/timeline_editor/controls/video_editor_timeline_clip_controls_test.dart
#	mobile/test/widgets/video_editor/timeline_editor/controls/video_editor_timeline_multi_select_controls_test.dart
@github-actions

This comment has been minimized.

…y-paste-style

# Conflicts:
#	mobile/lib/l10n/app_am.arb
#	mobile/lib/l10n/app_ar.arb
#	mobile/lib/l10n/app_bg.arb
#	mobile/lib/l10n/app_de.arb
#	mobile/lib/l10n/app_es.arb
#	mobile/lib/l10n/app_fil.arb
#	mobile/lib/l10n/app_fr.arb
#	mobile/lib/l10n/app_id.arb
#	mobile/lib/l10n/app_it.arb
#	mobile/lib/l10n/app_ja.arb
#	mobile/lib/l10n/app_ko.arb
#	mobile/lib/l10n/app_nl.arb
#	mobile/lib/l10n/app_pl.arb
#	mobile/lib/l10n/app_pt.arb
#	mobile/lib/l10n/app_ro.arb
#	mobile/lib/l10n/app_sv.arb
#	mobile/lib/l10n/app_tr.arb
#	mobile/lib/widgets/video_editor/clip_editor_result_listeners.dart
@hm21

hm21 commented Oct 21, 2026

Copy link
Copy Markdown
Member Author

Hi @dcadenas and @mbradley 👋 friendly ping on this one — whenever you get a moment, a review would be great.

It looks bigger than it is: most of the files are translations and tests. The core is clip_style.dart, layer_style.dart, the paste handler in clip_editor_bloc.dart and the two action bars, and the videos in the description show the whole flow. The red roborev check is only the review service being down for every PR since yesterday.

Thanks a lot! Happy to walk through anything.

@github-actions

Copy link
Copy Markdown

Mobile PR Preview

Preview refreshed for b4073ad

Last refresh: b4073ad at 2026-10-21 05:53:30 UTC (preview run)

Property Value
Preview URL https://4638f852.openvine-app.pages.dev
Pages project openvine-app
Preview branch pr-10307
PR branch feat/video-editor-copy-paste-style
Commit b4073ad

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.

feat(video-editor): copy a clip's or layer's style and paste it onto others

1 participant