Skip to content

Fix sign language tool for draggable videos (BL-16131)#7836

Open
JohnThomson wants to merge 2 commits intoVersion6.4afrom
fixDraggableVideos
Open

Fix sign language tool for draggable videos (BL-16131)#7836
JohnThomson wants to merge 2 commits intoVersion6.4afrom
fixDraggableVideos

Conversation

@JohnThomson
Copy link
Copy Markdown
Contributor

@JohnThomson JohnThomson commented Apr 13, 2026

Fixing a few things here:

  • copying a draggable video to its target could put the bloom-selected class on the target. Having bloom-selected on a target could also happen during page open (because it was likely the first bloom-videoContainer in DOM order) or just because the page was saved that way. Several things work together to be sure this class is never put (or left) in a target.
  • trying to make the sign language (or any) tool selected was simulating a click on the check box for making it active (available). If it already was, this would hide it, and activate some other tool. I extracted the code for turning it on and selecting it, and call that explicitly.
  • seems we were counting on page-load code to reset the state of the tool after recording. That doesn't always happen, so I added code to reset some recording-in-process state, and make sure we see the new video.

Open with Devin

This change is Reviewable

Fixing a few things here:
- copying a draggable video to its target could put the bloom-selected class on the target. Having bloom-selected on a target could also happen during page open (because it was likely the first bloom-videoContainer in DOM order) or just because the page was saved that way. Several things work together to be sure this class is never put (or left) in a target.
- trying to make the sign language (or any) tool selected was simulating a click on the check box for making it active (available). If it already was, this would hide it, and activate some other tool. I extracted the code for turning it on and selecting it, and call that explicitly.
- seems we were counting on page-load code to reset the state of the tool after recording. That doesn't always happen, so I added code to reset some recording-in-process state, and make sure we see the new video.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 9 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/BloomBrowserUI/bookEdit/toolbox/games/GameTool.tsx">

<violation number="1" location="src/BloomBrowserUI/bookEdit/toolbox/games/GameTool.tsx:1895">
P2: The cleanup selector misses targets that themselves have `bloom-selected`, so the bug can persist after tab changes.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

}

function removeBloomSelectedFromTargets(page: HTMLElement): void {
page.querySelectorAll("[data-target-of] .bloom-selected").forEach((el) => {
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Apr 13, 2026

Choose a reason for hiding this comment

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

P2: The cleanup selector misses targets that themselves have bloom-selected, so the bug can persist after tab changes.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/BloomBrowserUI/bookEdit/toolbox/games/GameTool.tsx, line 1895:

<comment>The cleanup selector misses targets that themselves have `bloom-selected`, so the bug can persist after tab changes.</comment>

<file context>
@@ -1891,6 +1891,18 @@ export function getActiveDragActivityTab(): number {
 }
 
+function removeBloomSelectedFromTargets(page: HTMLElement): void {
+    page.querySelectorAll("[data-target-of] .bloom-selected").forEach((el) => {
+        el.classList.remove("bloom-selected");
+    });
</file context>
Suggested change
page.querySelectorAll("[data-target-of] .bloom-selected").forEach((el) => {
page.querySelectorAll("[data-target-of].bloom-selected, [data-target-of] .bloom-selected").forEach((el) => {
Fix with Cubic

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not worried. Pretty sure .bloom-selected is never added to elements that actually have the data-target-of attribute. They are normally put on bloom-videoContainer elements, which are always a child of a target (or bloom-canvas-element)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the feedback! I've saved this as a new learning to improve future reviews.

Copy link
Copy Markdown
Contributor Author

@JohnThomson JohnThomson left a comment

Choose a reason for hiding this comment

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

@JohnThomson made 1 comment.
Reviewable status: 0 of 9 files reviewed, 1 unresolved discussion.

}

function removeBloomSelectedFromTargets(page: HTMLElement): void {
page.querySelectorAll("[data-target-of] .bloom-selected").forEach((el) => {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not worried. Pretty sure .bloom-selected is never added to elements that actually have the data-target-of attribute. They are normally put on bloom-videoContainer elements, which are always a child of a target (or bloom-canvas-element)

devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor

@StephenMcConnel StephenMcConnel left a comment

Choose a reason for hiding this comment

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

There's a "new" Devin comment around line 870 of signLanguageTool.tsx that seems relevant. Another "new" comment on line 312 of bloomVideo.ts that might or might not be relevant. Everything else looks okay as far as I can tell.

@StephenMcConnel reviewed 9 files and all commit messages, and made 2 comments.
Reviewable status: all files reviewed, 4 unresolved discussions (waiting on JohnThomson).


src/BloomBrowserUI/bookEdit/toolbox/toolbox.ts line 648 at r1 (raw file):

                    ToolBox.addToolToString(toolId),
                    true,
                );

getting rid of checkBox.click() is probably long overdue. :-) 🥇

Copy link
Copy Markdown
Contributor

@StephenMcConnel StephenMcConnel left a comment

Choose a reason for hiding this comment

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

@StephenMcConnel resolved 1 discussion.
Reviewable status: all files reviewed, 3 unresolved discussions (waiting on JohnThomson).

Copy link
Copy Markdown
Contributor Author

@JohnThomson JohnThomson left a comment

Choose a reason for hiding this comment

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

@JohnThomson made 2 comments and resolved 1 discussion.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on JohnThomson).

Comment thread src/BloomBrowserUI/bookEdit/js/bloomVideo.ts Outdated
Comment thread src/BloomBrowserUI/bookEdit/toolbox/signLanguage/signLanguageTool.tsx Outdated
Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 3 new potential issues.

View 6 additional findings in Devin Review.

Open in Devin Review

updateVideoInContainer(container, url);
}

public leaveCurrentVideoContext(onComplete?: () => void) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Missing comment on new public method leaveCurrentVideoContext

AGENTS.md mandates: "All public methods should have a comment." The new leaveCurrentVideoContext method is public but has no comment explaining its purpose or behavior.

Suggested change
public leaveCurrentVideoContext(onComplete?: () => void) {
// Reset the video recording state so the tool is ready for a new video context.
// Cleans up event listeners, timers, and overlays left over from any active recording session.
public leaveCurrentVideoContext(onComplete?: () => void) {
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

return `${baseUrl}${search ? `?${search}` : ""}${hash}`;
}

export function stripTransientVideoTimestampParam(url: string): string {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Missing comment on exported function stripTransientVideoTimestampParam

AGENTS.md mandates: "All public methods should have a comment." The exported function stripTransientVideoTimestampParam has no comment.

Suggested change
export function stripTransientVideoTimestampParam(url: string): string {
// Remove the transient cache-busting query parameter from a video URL, preserving any other params and fragment.
export function stripTransientVideoTimestampParam(url: string): string {
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

return `${baseUrl}${search ? `?${search}` : ""}${hash}`;
}

export function removeTransientVideoTimestampParams(root: ParentNode): void {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Missing comment on exported function removeTransientVideoTimestampParams

AGENTS.md mandates: "All public methods should have a comment." The exported function removeTransientVideoTimestampParams has no comment.

Suggested change
export function removeTransientVideoTimestampParams(root: ParentNode): void {
// Strip transient cache-busting query parameters from all video and video-source elements under the given root.
export function removeTransientVideoTimestampParams(root: ParentNode): void {
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor Author

@JohnThomson JohnThomson left a comment

Choose a reason for hiding this comment

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

I think I've dealt with all Devin's comments except where it is being picky about commenting public methods.

@JohnThomson made 1 comment.
Reviewable status: 7 of 11 files reviewed, 4 unresolved discussions (waiting on StephenMcConnel).

@andrew-polk andrew-polk changed the base branch from master to Version6.4a April 14, 2026 20:59
Copy link
Copy Markdown
Contributor

@StephenMcConnel StephenMcConnel left a comment

Choose a reason for hiding this comment

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

@StephenMcConnel reviewed 4 files and all commit messages.
Reviewable status: all files reviewed, 4 unresolved discussions (waiting on JohnThomson).

Copy link
Copy Markdown
Contributor

@StephenMcConnel StephenMcConnel left a comment

Choose a reason for hiding this comment

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

Reviewable status: all files reviewed, 4 unresolved discussions (waiting on JohnThomson).

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.

2 participants