Skip to content

Convert the thumbnail context menu to display in React (BL-15895)#7702

Merged
andrew-polk merged 1 commit intomasterfrom
BL-15895-ReactPageThumbnailMenu
Feb 24, 2026
Merged

Convert the thumbnail context menu to display in React (BL-15895)#7702
andrew-polk merged 1 commit intomasterfrom
BL-15895-ReactPageThumbnailMenu

Conversation

@StephenMcConnel
Copy link
Copy Markdown
Contributor

@StephenMcConnel StephenMcConnel commented Feb 19, 2026


Open with Devin

This change is Reviewable

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: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 5 additional findings.

Open in Devin Review

@hatton
Copy link
Copy Markdown
Member

hatton commented Feb 19, 2026

  1. JS requests menu items from C# → receives [{id, label, enabled}, ...]
  2. User clicks an item → JS sends the commandId back to C# for execution

@StephenMcConnel would it be more natural for the UI (typescript) to know the menu items it wants?

Copy link
Copy Markdown
Contributor Author

@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.

I thought about it but came up with two reasons for keeping the way the AI structured things:

  1. There would need to be an API call for each menu item to get its localized label.
  2. There would need to be an API call for each menu item to get its enabled state, although maybe that could be computed on the client side. I haven't really looked at that.
    Making a single API call to get all of the menu items with those values already computed seemed like a reasonable choice with
    simpler setup.

@StephenMcConnel made 1 comment.
Reviewable status: 0 of 4 files reviewed, all discussions resolved.

Copy link
Copy Markdown
Member

@hatton hatton left a comment

Choose a reason for hiding this comment

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

Yeah, let's "go native" for all of these menus, not rely on the server to act like part of the UI. We have UI all over in typescript land that manages to localize itself one way or the other :-)

@hatton made 1 comment.
Reviewable status: 0 of 4 files reviewed, all discussions resolved.

Copy link
Copy Markdown
Contributor Author

@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.

OK.

@StephenMcConnel made 1 comment.
Reviewable status: 0 of 4 files reviewed, all discussions resolved.

@StephenMcConnel StephenMcConnel force-pushed the BL-15895-ReactPageThumbnailMenu branch from 6136efd to b81c283 Compare February 23, 2026 17:48
Copy link
Copy Markdown
Contributor Author

@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.

Done.

@StephenMcConnel made 1 comment.
Reviewable status: 0 of 4 files reviewed, all discussions resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor

@andrew-polk andrew-polk left a comment

Choose a reason for hiding this comment

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

@andrew-polk reviewed 4 files and all commit messages, and made 1 comment.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on StephenMcConnel).


src/BloomBrowserUI/bookEdit/pageThumbnailList/pageThumbnailList.tsx line 496 at r2 (raw file):

                >
                    {contextMenuItems.map((item) => (
                        <MenuItem

Should we be using LocalizableMenuItem here?
If not, let's add a comment.

@StephenMcConnel StephenMcConnel force-pushed the BL-15895-ReactPageThumbnailMenu branch from b81c283 to a4933bb Compare February 23, 2026 22:44
Copy link
Copy Markdown
Contributor Author

@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 made 1 comment.
Reviewable status: 3 of 5 files reviewed, 2 unresolved discussions (waiting on andrew-polk).


src/BloomBrowserUI/bookEdit/pageThumbnailList/pageThumbnailList.tsx line 496 at r2 (raw file):

Previously, andrew-polk wrote…

Should we be using LocalizableMenuItem here?
If not, let's add a comment.

Done. I had to enhance LocalizableMenuItem to accept a pair of css attributes to make the menu look reasonable.

devin-ai-integration[bot]

This comment was marked as resolved.

@StephenMcConnel StephenMcConnel force-pushed the BL-15895-ReactPageThumbnailMenu branch from a4933bb to 3ca1765 Compare February 23, 2026 23:12
Copy link
Copy Markdown
Contributor Author

@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 made 1 comment.
Reviewable status: 2 of 5 files reviewed, 3 unresolved discussions (waiting on andrew-polk).

Comment thread src/BloomExe/web/PageListApi.cs Outdated
devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor

@andrew-polk andrew-polk left a comment

Choose a reason for hiding this comment

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

@andrew-polk reviewed all commit messages and resolved 1 discussion.
Reviewable status: 2 of 5 files reviewed, 1 unresolved discussion (waiting on StephenMcConnel).

@StephenMcConnel StephenMcConnel force-pushed the BL-15895-ReactPageThumbnailMenu branch from 3ca1765 to 513143e Compare February 23, 2026 23:30
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 2 new potential issues.

View 10 additional findings in Devin Review.

Open in Devin Review

Comment thread src/BloomBrowserUI/bookEdit/pageThumbnailList/pageThumbnailList.tsx
Comment on lines +146 to 178
// Execute the command asynchronously after a short delay
// The discard operator _ indicates we're intentionally not awaiting this
_ = Task.Run(async () =>
{
await Task.Delay(100); // 100ms delay to let the UI respond

// Execute on the UI thread using the form's synchronization context
var form = Shell.GetShellOrOtherOpenForm();
if (form != null && !form.IsDisposed)
{
form.BeginInvoke(
new Action(() =>
{
try
{
PageList.ExecuteContextMenuCommand(page, commandId);
}
catch (Exception ex)
{
// Log the error. Should we notify the user as well?
Logger.WriteEvent(
$"Error executing content menu command for {commandId} on page {pageId}"
);
Logger.WriteError(ex);
}
})
);
}
});
}

// Return success immediately without waiting for the command to execute
request.PostSucceeded();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚩 Task.Run + BeginInvoke pattern: command execution is fire-and-forget with error swallowing

The HandleContextMenuItemClickedRequest at PageListApi.cs:148-174 uses Task.Run with a 100ms delay, then BeginInvoke to execute commands on the UI thread. The request.PostSucceeded() is returned immediately at line 178. If the command fails (e.g., ConfirmRemovePageDialog.Confirm() throws, or Model.DeletePage fails), the error is caught and logged at lines 163-169, but the user gets no feedback — the JS side already received a success response. The comment on line 165 acknowledges this concern ("Should we notify the user as well?"). For commands like removePage and chooseDifferentLayout that show modal dialogs, the 100ms delay is needed to let the React menu close first; without it, the modal could fight with the menu for focus.

Open in Devin Review

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

Copy link
Copy Markdown
Contributor

@andrew-polk andrew-polk left a comment

Choose a reason for hiding this comment

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

@andrew-polk partially reviewed 3 files and made 1 comment.
Reviewable status: 4 of 5 files reviewed, 3 unresolved discussions (waiting on StephenMcConnel).


src/BloomBrowserUI/bookEdit/pageThumbnailList/pageThumbnailList.tsx line 510 at r4 (raw file):

                                min-height: 24px !important;
                                padding: 3px 8px !important;
                            `}

Sorry I wasn't clear about this earlier. Here's another try with specifics...

You can get rid of the itemCss prop and just set css. The className={props.className} in LocalizableMenuItem means the css prop gets passed to the underlying MenuItem.

(and you can get rid of setting the className here)

@StephenMcConnel StephenMcConnel force-pushed the BL-15895-ReactPageThumbnailMenu branch from 513143e to 16761a0 Compare February 24, 2026 00:32
Copy link
Copy Markdown
Contributor Author

@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 made 2 comments and resolved 1 discussion.
Reviewable status: 2 of 5 files reviewed, 2 unresolved discussions (waiting on andrew-polk).


src/BloomBrowserUI/bookEdit/pageThumbnailList/pageThumbnailList.tsx line 510 at r4 (raw file):

Previously, andrew-polk wrote…

Sorry I wasn't clear about this earlier. Here's another try with specifics...

You can get rid of the itemCss prop and just set css. The className={props.className} in LocalizableMenuItem means the css prop gets passed to the underlying MenuItem.

(and you can get rid of setting the className here)

I think I see what is happening, but it's way too magical and obscure. You have to 1) NOT pass in a className value as well as pass in a css value for this magic to work.

Comment thread src/BloomBrowserUI/bookEdit/pageThumbnailList/pageThumbnailList.tsx
Copy link
Copy Markdown
Contributor Author

@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: 2 of 5 files reviewed, 1 unresolved discussion (waiting on andrew-polk).

Copy link
Copy Markdown
Contributor

@andrew-polk andrew-polk left a comment

Choose a reason for hiding this comment

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

@andrew-polk reviewed 3 files and all commit messages, and resolved 1 discussion.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on StephenMcConnel).

@andrew-polk andrew-polk merged commit b7ed954 into master Feb 24, 2026
1 check passed
@andrew-polk andrew-polk deleted the BL-15895-ReactPageThumbnailMenu branch February 24, 2026 14:51
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