-
Notifications
You must be signed in to change notification settings - Fork 854
fix: call sidePanel.open() synchronously to fix context menu side panel #963
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 2 commits
46acd1c
792b6bc
327c967
810e8d3
0f82ecd
025cbb8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -5,10 +5,21 @@ import { config as menuConfig } from '../content-script/menu-tools/index.mjs' | |||||||||||||||||
|
|
||||||||||||||||||
| const menuId = 'ChatGPTBox-Menu' | ||||||||||||||||||
| const onClickMenu = (info, tab) => { | ||||||||||||||||||
| const itemId = info.menuItemId.replace(menuId, '') | ||||||||||||||||||
|
|
||||||||||||||||||
| // sidePanel.open() must be called synchronously within the user gesture handler. | ||||||||||||||||||
| // Calling it inside a Promise callback (e.g. Browser.tabs.query().then()) breaks | ||||||||||||||||||
| // Chrome's user gesture requirement and causes the error: | ||||||||||||||||||
| // "sidePanel.open() may only be called in response to a user gesture." | ||||||||||||||||||
| if (itemId === 'openSidePanel' && menuConfig.openSidePanel?.action) { | ||||||||||||||||||
| menuConfig.openSidePanel.action(true, tab) | ||||||||||||||||||
| return | ||||||||||||||||||
|
Comment on lines
+14
to
+34
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Description: Inspect side-panel action implementations and call sites.
# Expect: openSidePanel.action returns/awaits/catches chrome.sidePanel.open(...),
# and menus.mjs observes the action promise with .catch(...) or equivalent.
rg -n -C5 "openSidePanel|chrome\.sidePanel\.open|menuConfig\.openSidePanel\.action" --iglob "*.mjs"Repository: ChatGPTBox-dev/chatGPTBox Length of output: 2114 Handle side-panel action failures without moving the API call out of the gesture. Line 15 intentionally calls the action synchronously, which preserves the user-gesture requirement. However, if (itemId === 'openSidePanel' && menuConfig.openSidePanel?.action) {
- menuConfig.openSidePanel.action(true, tab)
+ void Promise.resolve(menuConfig.openSidePanel.action(true, tab)).catch((error) => {
+ console.error('failed to open side panel', error)
+ })
return
}Also update - chrome.sidePanel.open({ windowId: tab.windowId, tabId: tab.id })
+ return chrome.sidePanel.open({ windowId: tab.windowId, tabId: tab.id })📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| Browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => { | ||||||||||||||||||
| const currentTab = tabs[0] | ||||||||||||||||||
| const message = { | ||||||||||||||||||
| itemId: info.menuItemId.replace(menuId, ''), | ||||||||||||||||||
| itemId, | ||||||||||||||||||
| selectionText: info.selectionText, | ||||||||||||||||||
| useMenuPosition: tab.id === currentTab.id, | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -74,8 +74,8 @@ export class Claude { | |||||||||||||||||||||||||||
| if (!sessionKey) { | ||||||||||||||||||||||||||||
| throw new Error('Session key required') | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| if (!sessionKey.startsWith('sk-ant-sid01')) { | ||||||||||||||||||||||||||||
| throw new Error('Session key invalid: Must be in the format sk-ant-sid01-*****') | ||||||||||||||||||||||||||||
| if (!sessionKey.startsWith('sk-ant-sid')) { | ||||||||||||||||||||||||||||
| throw new Error('Session key invalid: Must be in the format sk-ant-sid01-***** or sk-ant-sid02-*****') | ||||||||||||||||||||||||||||
|
Comment on lines
+77
to
+78
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The validation check and the error message are inconsistent. The check now allows any session key starting with
Suggested change
Comment on lines
+77
to
+78
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Align the validation with the stated accepted formats. Line 77 accepts any Proposed fix- if (!sessionKey.startsWith('sk-ant-sid')) {
+ const isValidSessionKey = ['sk-ant-sid01-', 'sk-ant-sid02-'].some((prefix) =>
+ sessionKey.startsWith(prefix),
+ )
+ if (!isValidSessionKey) {
throw new Error('Session key invalid: Must be in the format sk-ant-sid01-***** or sk-ant-sid02-*****')
}If accepting all future 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
Comment on lines
+77
to
79
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1. Claude key validation too loose The constructor now only checks sessionKey.startsWith('sk-ant-sid') while the error message claims
only sk-ant-sid01-***** or sk-ant-sid02-***** are valid, allowing malformed keys to pass
validation and fail later during authenticated requests.
Agent Prompt
|
||||||||||||||||||||||||||||
| if (fetch) { | ||||||||||||||||||||||||||||
| this.fetch = fetch | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
actionfunction is asynchronous and returns a Promise. Since it is called here withoutawaitor a.catch()block, any errors occurring within the action (such as a failure in thechrome.sidePanel.openAPI call) will result in an unhandled promise rejection in the background script. It is recommended to add a.catch()block to handle potential errors gracefully.