Skip to content

feat: per-website NVDA profile auto-switching with compatibility fixes#41

Open
adil-adysh wants to merge 1 commit intomltony:masterfrom
adil-adysh:master
Open

feat: per-website NVDA profile auto-switching with compatibility fixes#41
adil-adysh wants to merge 1 commit intomltony:masterfrom
adil-adysh:master

Conversation

@adil-adysh
Copy link
Copy Markdown

✨ Overview

This PR introduces automatic NVDA profile switching based on the current website, along with several compatibility fixes and internal cleanups.
Users can now assign an NVDA profile to a specific site, and the addon will:

  • Automatically activate that profile when visiting the site
  • Restore the previous manual profile when leaving

🎯 Key Features

🔹 Per-website NVDA profile switching

  • New
    vdaProfile\ field in site configuration
  • Applied on URL change
  • Supports all existing URL matching modes

🔹 Automatic restore behavior

  • Previous manual profile is preserved
  • Cleanly restored when no matching site is active

🔹 UI integration

  • Added dropdown in site editor dialog
  • Lists available NVDA profiles dynamically

🛡️ Compatibility Improvements

  • Handle missing
    vdaControllerInternal_reportLiveRegion\ safely
  • Avoid crashes when NVDA C-level symbols are unavailable
  • Add safe fallback for \generateBeep\ (prevents runtime errors)
  • Support URL values as \str, \�ytes, or \None
    These changes improve compatibility with newer NVDA builds.

🧹 Refactoring & Cleanup

  • Removed unused imports across multiple modules
  • Simplified exception handling (removed unused variables)
  • Fixed regex escaping issues
  • Avoided function name shadowing (\match → applyMatch)

🔄 Lifecycle Handling

  • Ensure profile auto-switching is stopped on addon termination
  • Restore previous profile to prevent persistent state issues

⚠️ Notes for Reviewers

  • Profile switching is synchronous and protected by a lock to avoid race conditions
  • Missing or invalid profiles are safely ignored
  • Existing behavior is preserved when no
    vdaProfile\ is configured

🧪 Testing

Tested with:

  • Multiple websites with different profiles
  • Rapid URL changes
  • NVDA versions with and without certain C-level APIs
  • Addon reload / termination scenarios

💬 Future Improvements (optional)

  • Debounce profile switching on rapid URL updates
  • Per-tab profile handling
  • Improved logging for debugging profile transitions

…fixes

- Add nvdaProfile field to site configuration
- Automatically switch NVDA profile based on current URL
- Restore previous manual profile when leaving matching sites
- Ensure profile switching is thread-safe using lock

Compatibility & stability:
- Safely handle missing NVDAHelper C-level symbols (live region)
- Add fallback for generateBeep when unavailable
- Normalize URL handling (bytes/None-safe)
- Avoid crashes on newer NVDA builds

Refactors & cleanup:
- Reduce unused imports across modules
- Improve exception handling (remove unused variables)
- Fix regex string escaping
- Rename internal match function to avoid shadowing

UI:
- Add NVDA profile selection dropdown in site editor dialog

Lifecycle:
- Ensure profile auto-switching is stopped and restored on addon termination
Copilot AI review requested due to automatic review settings March 18, 2026 08:55
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds per-website NVDA profile auto-switching to BrowserNav, and includes several compatibility-focused defensive changes (especially around NVDA internals and input types for URLs).

Changes:

  • Introduces a new nvdaProfile site setting, UI selection in the site editor, and a URL-driven profile state machine (auto-activate + restore).
  • Improves robustness around URL handling (str/bytes/None) and regex usage.
  • Adds compatibility guards for NVDA C-level hooks and missing generateBeep, plus various cleanup/refactors (unused imports, exception variable removal, name shadowing).

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
addon/globalPlugins/browserNav/utils.py Minor cleanup: remove unused import, simplify exception handling.
addon/globalPlugins/browserNav/quickJump.py Core implementation: new nvdaProfile config field, URL normalization, profile state machine, and site-editor UI integration.
addon/globalPlugins/browserNav/__init__.py Triggers profile switching on URL updates; adds/adjusts compatibility around live-region reporting hooks; stops auto-switch on termination.
addon/globalPlugins/browserNav/beeper.py Adds a safe fallback wrapper for NVDAHelper.localLib.generateBeep.
addon/globalPlugins/browserNav/editor.py Import cleanup (removes unused imports).
addon/globalPlugins/browserNav/clipboard.py Import cleanup and minor exception cleanup.
.vscode/typings/__builtins__.pyi Formatting cleanup of stubs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 1458 to 1462
# Something else found in clipboard - likely user has already copied something there. So just exit without restoring state
log.error(f"asdf something else in clipboard!")
log.error("asdf something else in clipboard!")
log.error(f"text='{text}'")
log.error(f"newText='{newText}'")
log.error(f"firstChar='{firstChar}'")
Comment on lines +754 to +763
# override the live region reporting function if available
quickJump.originalReportLiveRegion = getattr(NVDAHelper, 'nvdaControllerInternal_reportLiveRegion', None)
NVDAHelper.nvdaControllerInternal_reportLiveRegion = quickJump.newReportLiveRegion
NVDAHelper._setDllFuncPointer(NVDAHelper.localLib.dll,"_nvdaControllerInternal_reportLiveRegion", quickJump.newReportLiveRegion)
# The C-level symbol may not exist in newer NVDA builds; avoid crashing if missing.
try:
# localLib may either be a module or expose a .dll attribute depending on NVDA version.
lib = getattr(NVDAHelper.localLib, "dll", NVDAHelper.localLib)
if hasattr(lib, "_nvdaControllerInternal_reportLiveRegion"):
NVDAHelper._setDllFuncPointer(lib, "_nvdaControllerInternal_reportLiveRegion", quickJump.newReportLiveRegion)
except Exception:
Comment on lines +797 to +802
try:
lib = getattr(NVDAHelper.localLib, "dll", NVDAHelper.localLib)
if hasattr(lib, "_nvdaControllerInternal_reportLiveRegion"):
NVDAHelper._setDllFuncPointer(lib, "_nvdaControllerInternal_reportLiveRegion", quickJump.originalReportLiveRegion)
except Exception:
pass
self.versionTextCtrl.SetValue(self.site.version)
# Translators: NVDA profile selection for this website
label = _("Switch to NVDA profile")
self.nvdaProfileChoices = [None] + sorted(list(nvdaConfig.conf.listProfiles()))
@mltony
Copy link
Copy Markdown
Owner

mltony commented Mar 18, 2026

AI-generated PRs are hard to review. Please send PR with only one intended change at a time. No refactoring.

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