Convert the thumbnail context menu to display in React (BL-15895)#7702
Convert the thumbnail context menu to display in React (BL-15895)#7702andrew-polk merged 1 commit intomasterfrom
Conversation
@StephenMcConnel would it be more natural for the UI (typescript) to know the menu items it wants? |
StephenMcConnel
left a comment
There was a problem hiding this comment.
I thought about it but came up with two reasons for keeping the way the AI structured things:
- There would need to be an API call for each menu item to get its localized label.
- 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.
hatton
left a comment
There was a problem hiding this comment.
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.
StephenMcConnel
left a comment
There was a problem hiding this comment.
OK.
@StephenMcConnel made 1 comment.
Reviewable status: 0 of 4 files reviewed, all discussions resolved.
6136efd to
b81c283
Compare
StephenMcConnel
left a comment
There was a problem hiding this comment.
Done.
@StephenMcConnel made 1 comment.
Reviewable status: 0 of 4 files reviewed, all discussions resolved.
andrew-polk
left a comment
There was a problem hiding this comment.
@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.
b81c283 to
a4933bb
Compare
StephenMcConnel
left a comment
There was a problem hiding this comment.
@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.
a4933bb to
3ca1765
Compare
StephenMcConnel
left a comment
There was a problem hiding this comment.
@StephenMcConnel made 1 comment.
Reviewable status: 2 of 5 files reviewed, 3 unresolved discussions (waiting on andrew-polk).
andrew-polk
left a comment
There was a problem hiding this comment.
@andrew-polk reviewed all commit messages and resolved 1 discussion.
Reviewable status: 2 of 5 files reviewed, 1 unresolved discussion (waiting on StephenMcConnel).
3ca1765 to
513143e
Compare
| // 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(); |
There was a problem hiding this comment.
🚩 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.
Was this helpful? React with 👍 or 👎 to provide feedback.
andrew-polk
left a comment
There was a problem hiding this comment.
@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)
513143e to
16761a0
Compare
StephenMcConnel
left a comment
There was a problem hiding this comment.
@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
itemCssprop and just setcss. TheclassName={props.className}in LocalizableMenuItem means thecssprop 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.
StephenMcConnel
left a comment
There was a problem hiding this comment.
@StephenMcConnel resolved 1 discussion.
Reviewable status: 2 of 5 files reviewed, 1 unresolved discussion (waiting on andrew-polk).
andrew-polk
left a comment
There was a problem hiding this comment.
@andrew-polk reviewed 3 files and all commit messages, and resolved 1 discussion.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on StephenMcConnel).
This change is