doc: specify advanced context menu design
This commit is contained in:
@@ -0,0 +1,219 @@
|
||||
# Advanced context menu design
|
||||
|
||||
Status: agreed conversational design, awaiting written-spec review.
|
||||
|
||||
## Purpose and scope
|
||||
|
||||
Preserve today's quick selection action while offering an optional advanced
|
||||
menu with useful built-in prompts. Adapt the advanced menu to selected text,
|
||||
links, or the current page. Translation is useful but optional, so it is hidden
|
||||
until enabled. Firefox Desktop remains the only target.
|
||||
|
||||
This work includes settings migration, contextual menus, dedicated prompts,
|
||||
translation and truncation dialogs, documentation, and tests. It does not
|
||||
include custom action editing, full-page extraction, model/effort selection,
|
||||
omnibox changes, MV3 migration, containers, or automatic submission.
|
||||
|
||||
## Settings and migration
|
||||
|
||||
Replace the existing context-menu checkbox with **Context menu**:
|
||||
|
||||
- **Off:** no extension context menu.
|
||||
- **Simple:** today's direct **Ask ChatGPT** item, only for selected text.
|
||||
- **Advanced:** one **Ask ChatGPT** submenu with contextual actions.
|
||||
|
||||
Only the selected menu variant is visible; do not leave the other grayed out.
|
||||
The keyboard shortcut continues to run the default selection action in every
|
||||
mode, including Off, and opens a blank chat when no selection is available.
|
||||
|
||||
New settings in the existing sync storage:
|
||||
|
||||
| Key | Values | Default |
|
||||
| --- | --- | --- |
|
||||
| `contextMenuMode` | `off`, `simple`, `advanced` | `simple` |
|
||||
| `showTranslate` | Boolean | `false` |
|
||||
| `translationMode` | `ask`, `preferred` | `ask` |
|
||||
| `translationLanguage` | Trimmed free text, maximum 100 Unicode code points | Empty |
|
||||
|
||||
Retain existing temporary-chat, web-search, open-location, and prompt-template
|
||||
settings. Read the legacy `showContextMenu` key during migration even though it
|
||||
is no longer in the new defaults. A valid new mode takes precedence; otherwise
|
||||
legacy false maps to Off and legacy true or absence maps to Simple. A subsequent
|
||||
save writes the new mode. Invalid stored values fall back safely.
|
||||
|
||||
Advanced mode reveals **Show Translate in advanced menu**, initially unchecked.
|
||||
When checked, reveal **Translate into** with **Ask each time** and **Preferred
|
||||
language**. Preferred language reveals a free-text field; it accepts Spanish
|
||||
or any other language without a fixed language list. Empty preferred language
|
||||
shows inline guidance and invokes the language dialog rather than constructing
|
||||
an incomplete prompt. Turning a feature off hides its controls but retains its
|
||||
preferences. Restore defaults resets all extension settings, including these,
|
||||
without changing Firefox's engine settings or keyboard shortcut.
|
||||
|
||||
## Context selection and menu layout
|
||||
|
||||
Choose one group for each opening, in this priority order:
|
||||
|
||||
1. Nonempty selected text, including selection inside a link.
|
||||
2. A clicked link when there is no selection.
|
||||
3. Page background when there is no selection or link.
|
||||
|
||||
Do not add special image, video, password-field, or browser-chrome actions.
|
||||
Native editable-field behavior must be checked in Firefox before claiming it
|
||||
is supported. Use menu event data for selection and URLs; no background page
|
||||
scraping or automatic navigation to the linked site.
|
||||
|
||||
| Context | Children, in order |
|
||||
| --- | --- |
|
||||
| Selection | Ask normally; separator; Explain; Summarize; Debug code; Translate when enabled |
|
||||
| Link | Ask about this link; Review link safety |
|
||||
| Page | Ask about this page; Summarize this page |
|
||||
|
||||
The selection presets are always present in Advanced mode except Translate.
|
||||
Do not infer whether text is code. Debug code appears for any selection and
|
||||
the user decides when it applies. With a valid preferred language, label the
|
||||
translation item **Translate to Spanish** (substituting the user's language);
|
||||
otherwise use **Translate…**. Escape menu-label access-key characters in
|
||||
user-supplied language names so the displayed text remains literal.
|
||||
|
||||
Use Firefox menu visibility updates when the menu opens to enforce precedence,
|
||||
then refresh the native menu. Serialize registration and settings updates, as
|
||||
the existing implementation does. Validate click data again before launching;
|
||||
visibility is not input validation.
|
||||
|
||||
## Prompt behavior
|
||||
|
||||
**Ask normally** and the keyboard shortcut apply the user's existing prompt
|
||||
template. Every other action uses its own dedicated prompt without appending
|
||||
or wrapping it in that template. All actions respect the existing open-location,
|
||||
temporary-chat, and web-search preferences. Hints retain their existing
|
||||
best-effort status. The address-bar search provider is unchanged.
|
||||
|
||||
Dedicated prompts should express these instructions, followed by a clearly
|
||||
labeled source block:
|
||||
|
||||
| Action | Instructions |
|
||||
| --- | --- |
|
||||
| Explain | Explain the selected text clearly, defining unfamiliar terms. |
|
||||
| Summarize | Summarize the selected text, preserving its main points and qualifications. |
|
||||
| Debug code | Identify likely problems and suggest fixes; explain the reasoning and ask for missing context when necessary. |
|
||||
| Translate | Translate the selected text into the specified language, preserving meaning and formatting where practical. |
|
||||
| Ask about link/page | Help the user understand the supplied URL, ask what they would like to know, and say if its content cannot be accessed. |
|
||||
| Review link safety | Review suspicious indicators and available evidence; distinguish URL inspection from checks actually performed, state uncertainty, and do not guarantee that the link is safe. |
|
||||
| Summarize page | Summarize the content at the URL; if it cannot be accessed, say so and ask the user to supply the text rather than inventing a summary. |
|
||||
|
||||
Source text and URLs are data, not extension instructions. Explicit framing
|
||||
helps communicate this but is not a security boundary. Users still review and
|
||||
submit in ChatGPT; no auto-submit or internal ChatGPT request modification.
|
||||
|
||||
Link/page actions share the relevant URL only, without reading page text or
|
||||
adding titles. Accept only HTTP(S) URLs. Reject malformed URLs, URLs containing
|
||||
embedded username/password credentials, and unsupported schemes with a clear
|
||||
message. Preserve accepted URLs intact, including their query/fragment rather
|
||||
than silently changing the destination. Documentation must explain that URLs
|
||||
can contain private information and are sent to ChatGPT by the chosen action.
|
||||
|
||||
## Translation and other dialogs
|
||||
|
||||
Use a packaged extension dialog window, not a JavaScript prompt injected into
|
||||
the source page. Reuse one small dialog surface for language entry, truncation
|
||||
confirmation, and actionable errors, with appropriately distinct copy.
|
||||
|
||||
For Ask each time, Translate focuses the language input. Enter with a nonempty
|
||||
trimmed language continues; Escape, Cancel, or closing the window cancels.
|
||||
The one-time language choice does not silently change the saved preference.
|
||||
Preferred language bypasses this dialog when valid.
|
||||
|
||||
Do not put selected text or source URLs in the dialog URL or persistent/sync
|
||||
storage. Use an opaque request identifier and extension-internal messaging to
|
||||
transfer the pending action. Scope requests to their dialog, allow concurrent
|
||||
requests without mixing data, and release them on completion or cancellation.
|
||||
Keep the nonpersistent background lifecycle in mind: do not depend on a global
|
||||
Map surviving while the user types. Transfer the snapshot to the dialog through
|
||||
an initial handshake while the launch handler is active; after acknowledgment,
|
||||
the dialog owns its in-memory snapshot and can complete the launch itself.
|
||||
If initialization fails or context is lost, show a retry message and never send
|
||||
partial or mismatched input. Do not persist pending selections to survive a
|
||||
browser restart. Disable Continue while launching to prevent duplicate tabs.
|
||||
|
||||
Capture the action, selected source, and settings together so later tab changes
|
||||
or preference updates do not alter an already-open dialog's operation. If the
|
||||
dialog window cannot open, attempt the same extension page in a tab. Launch
|
||||
failures within the dialog remain visible and allow retry or cancellation.
|
||||
|
||||
## Length limits and launch behavior
|
||||
|
||||
Retain the current 8,000-character serialized URL budget. Preserve dedicated
|
||||
instructions and language in full; shorten only selected source text, on Unicode
|
||||
code-point boundaries with a whitespace boundary where practical. Include any
|
||||
shortening marker in the budget calculation. If even the instructions cannot
|
||||
fit, explain the problem instead of emitting a misleading prompt.
|
||||
|
||||
When selected text must be shortened, show a brief confirmation before opening
|
||||
ChatGPT, with **Continue with shortened text** and **Cancel**. This applies to
|
||||
Simple, Advanced, and the keyboard shortcut so they share one launch contract.
|
||||
For Translate with Ask each time, calculate the final budget after language
|
||||
entry and present confirmation in the same dialog if needed. Never truncate a
|
||||
link/page URL: explain that it is too long and stop that action.
|
||||
|
||||
On successful continuation, reuse new-tab, background-tab, and new-window
|
||||
behavior, including the existing new-window failure fallback to a tab. Close
|
||||
the dialog after a successful launch. Direct-launch failures should use the
|
||||
same error surface when it remains available; avoid silent success messages.
|
||||
|
||||
## Code boundaries
|
||||
|
||||
- Pure modules under `lib/` own action definitions, prompt assembly, context
|
||||
selection, settings validation/migration, and budget calculations. No browser
|
||||
APIs in these modules.
|
||||
- The background owns Firefox menu registration/events and entry-point routing.
|
||||
- A shared browser-facing launch helper owns tab/window opening and fallback.
|
||||
- The packaged dialog owns input, confirmation, and its pending action after
|
||||
transfer; it uses the same pure prompt and URL logic as direct launches.
|
||||
- Options remain inline in `about:addons` and use existing visual styles.
|
||||
|
||||
Preserve the current `storage`, `menus`, and `activeTab` permissions. No new
|
||||
host permissions, telemetry, intermediary service, runtime dependency, or API
|
||||
key is part of this design. Re-read the original options design and Appendix B
|
||||
before any proposed permission or submission change. A discovered inability
|
||||
to meet this constraint requires revisiting the design, not silently adding
|
||||
permissions.
|
||||
|
||||
## Verification and documentation
|
||||
|
||||
Meaningful unit tests cover legacy migration/new-key precedence, invalid
|
||||
settings, context precedence, literal source substitution, dedicated-template
|
||||
isolation, language validation, URL validation, and encoded-length boundaries.
|
||||
Verify that long source truncation preserves instructions and that URLs are
|
||||
never partially sent. Test dialog state transitions and cancellation/duplicate
|
||||
submission behavior at browser boundaries where feasible.
|
||||
|
||||
Run `npm test` with a nonzero test count. Inspect the built ZIP: include the
|
||||
dialog assets; exclude `test/` and `docs/`, including empty directory entries.
|
||||
|
||||
Manual Firefox checks:
|
||||
- Off/Simple/Advanced updates immediately and persists; legacy users retain mode.
|
||||
- Selection, linked selection, bare link, and page background show the correct
|
||||
group with no duplicate or disabled alternate root.
|
||||
- All actions construct the intended prompts; keyboard shortcut remains default.
|
||||
- Translation visibility, preferred language, blank preferred fallback, Enter,
|
||||
Escape, Cancel, and closing the dialog behave as specified.
|
||||
- Concurrent dialogs, source-tab changes, background idle/wakeup, and failed
|
||||
dialog initialization do not mix or silently lose selections.
|
||||
- Long selected text requires consent; oversized/unsupported URLs do not launch.
|
||||
- Tab/window preferences and failure fallback work from direct and dialog paths.
|
||||
- Settings/dialogs work in light/dark themes, narrow layouts, and by keyboard.
|
||||
- Run the existing AGENTS.md frame-focus and restricted-page shortcut checks.
|
||||
|
||||
Update README, changelog, and privacy text for menu modes, presets, URL sharing,
|
||||
translation, and truncation. Remove the unsuccessful temporary model/effort
|
||||
URL-test controls as part of release cleanup. Do not promise that ChatGPT can
|
||||
access every supplied URL or perform a definitive security audit.
|
||||
|
||||
## Review outcome
|
||||
|
||||
The design separates selection text from whole URLs in its length handling,
|
||||
keeps translation opt-in, preserves legacy menu behavior, and leaves Firefox's
|
||||
search provider and shortcut ownership unchanged. The next step after written
|
||||
spec approval is an implementation plan; this document authorizes no additional
|
||||
features beyond the agreed scope.
|
||||
Reference in New Issue
Block a user