Skip to content

feat: Add "Wait for space" and settings toggle#56

Merged
rngadam merged 5 commits intomainfrom
feature/dictation-settings
Oct 9, 2025
Merged

feat: Add "Wait for space" and settings toggle#56
rngadam merged 5 commits intomainfrom
feature/dictation-settings

Conversation

@rngadam
Copy link
Owner

@rngadam rngadam commented Oct 8, 2025

Adds two new features to the dictation page:

  1. A "Wait for space before correction" setting. When enabled (default), the persistent red correction underline on an incorrect word only appears after the user types a space or punctuation. While an incorrect word is being typed, the input box border flashes briefly to provide feedback.

  2. A settings panel toggle button. This allows the user to show or hide the settings panel. The panel also automatically collapses when the user clicks into the text input area to begin typing.

Adds two new features to the dictation page:

1. A "Wait for space before correction" setting. When enabled (default), the persistent red correction underline on an incorrect word only appears after the user types a space or punctuation. While an incorrect word is being typed, the input box border flashes briefly to provide feedback.

2. A settings panel toggle button. This allows the user to show or hide the settings panel. The panel also automatically collapses when the user clicks into the text input area to begin typing.
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @rngadam, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the dictation page by adding a new user-configurable setting for correction timing and improving the usability of the settings panel. The 'Wait for space before correction' feature provides a more fluid typing experience by only marking words incorrect after they are completed, with a subtle flash for in-progress errors. The settings panel can now be toggled open/closed and automatically hides when the user starts typing.

Highlights

  • New Features: This PR introduces two new features: a 'Wait for space before correction' setting and a toggle button for the settings panel.
  • Correction Behavior: The 'Wait for space before correction' setting (enabled by default) delays the persistent red underline for incorrect words until a space or punctuation is typed. While typing an incorrect word, the input box will briefly flash to provide immediate feedback.
  • Settings Panel Usability: A new 'Settings' button allows users to show or hide the configuration panel. The panel also automatically collapses when the user clicks into the text input area, improving focus during dictation.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

I've reviewed your pull request. The new features, 'Wait for space' and the settings panel toggle, are well-implemented and align with the description. The logic for handling word correction is particularly clever. I have one suggestion to improve code maintainability by reducing some duplication. Overall, great work!

dictation.js Outdated
Comment on lines 239 to 253
if (waitForSpaceCheckbox.checked) {
if (isWordInteractionComplete) {
span.classList.add('incorrect');
if (!firstErrorFound) {
firstErrorFound = { input: inputWord, source: sourceWords[index] };
}
} else {
flashIncorrect();
}
} else {
span.classList.add('incorrect');
if (!firstErrorFound) {
firstErrorFound = { input: inputWord, source: sourceWords[index] };
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

There's some duplicated code here for marking a word as incorrect. The logic that adds the incorrect class and sets firstErrorFound is repeated in two separate branches.

To improve maintainability and adhere to the DRY (Don't Repeat Yourself) principle, you can refactor this conditional logic. This will make the code more concise and easier to maintain, as any future changes to the 'mark as incorrect' logic will only need to be made in one place.

                    if (waitForSpaceCheckbox.checked && !isWordInteractionComplete) {
                        flashIncorrect();
                    } else {
                        span.classList.add('incorrect');
                        if (!firstErrorFound) {
                            firstErrorFound = { input: inputWord, source: sourceWords[index] };
                        }
                    }

This commit introduces several enhancements to the dictation page based on user feedback.

Features and Fixes:
- **Settings Panel:** The settings panel now correctly toggles with a smooth slide-in/out animation. It also automatically collapses when the user focuses on the text input area.
- **"Wait for space" Correction:** A new "Wait for space before correction" setting is added. When enabled, a transient border flash indicates an incorrect word during typing, and the persistent correction is shown only after a space or punctuation is entered.
- **"Hide Text" Mode Overhaul:** The "Hide Text" mode has been completely redesigned. Instead of a blank area, it now displays the text with alphanumeric characters replaced by black boxes (■), preserving the text's shape and punctuation. Incorrect words are revealed as a rich-text diff directly within the obscured text.
- **Code Refactoring:** Duplicated code in the word correction logic has been refactored for improved maintainability, adhering to the DRY principle.
- **UI Cleanup:** The "Reveal Text" button and its associated hotkey have been removed to streamline the user interface.
This commit introduces several enhancements and bug fixes to the dictation page based on user feedback.

Features and Fixes:
- **JavaScript Error:** Fixed a `TypeError` in the `obscureWord` function that occurred when displaying correction diffs in "Hide Text" mode. The element selection logic was made more specific to prevent errors.
- **Keep Correct Words Unobscured:** Updated the "Hide Text" mode so that correctly typed words remain visible instead of reverting to black boxes, providing clearer user feedback.
- **Settings Panel:** The settings panel has been converted from a sidebar to a slide-in overlay menu. The "Settings" button has been replaced with a hamburger icon (☰) that toggles the menu's visibility. The panel also correctly auto-collapses when the user focuses on the main text input area.
- **"Hide Text" Mode Overhaul:** The "Hide Text" mode has been redesigned to display obscured text using black boxes (■) while keeping punctuation visible. Incorrect words are revealed as a rich-text diff in place.
- **Code Refactoring:** Duplicated code in the word correction logic has been refactored for improved maintainability.
- **UI Cleanup:** The "Reveal Text" button and its associated hotkey have been removed.
This commit resolves a bug where the settings panel would not become visible when the hamburger menu icon was clicked.

The issue was caused by a CSS specificity conflict. The ID selector `#config-panel` has a higher specificity than the class selector `.config-panel-visible`, causing the `transform: translateX(100%)` rule to always take precedence over the `transform: translateX(0)` rule.

The fix increases the specificity of the visibility rule by changing the selector from `.config-panel-visible` to `#config-panel.config-panel-visible`. This ensures that when the panel is meant to be visible, its style is correctly applied.

Additionally, a z-index issue that prevented the menu button from being clicked when the panel was open has been resolved by giving the button a higher z-index.
@rngadam
Copy link
Owner Author

rngadam commented Oct 8, 2025

@gemini-code-assist /review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

Thank you for this pull request. The new features for 'Wait for space' and the settings panel toggle are great additions. The refactoring of the hidden mode logic is also a significant improvement, making the code cleaner and easier to maintain. I've found a few areas where we can make further improvements, including a security enhancement and some minor refactoring for better maintainability and user experience. Please see my detailed comments below.

dictation.js Outdated
Comment on lines +291 to +298
if (!sourceWords.length) {
textDisplay.innerHTML = '';
return;
}
const isHidden = hideTextCheckbox.checked;
// Render words, obscuring if in hidden mode.
const wordsToRender = isHidden ? sourceWords.map(obscureWord) : sourceWords;
textDisplay.innerHTML = wordsToRender.map(word => `<span class="word-span">${word}</span>`).join(' ');
Copy link
Contributor

Choose a reason for hiding this comment

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

high

This function uses innerHTML to render sourceWords, which can come from user input. This creates a potential Cross-Site Scripting (XSS) vulnerability if a user saves text containing malicious HTML.

To fix this, we should build the DOM nodes programmatically using document.createElement and set their content using textContent, which automatically escapes any HTML.

    textDisplay.innerHTML = ''; // Clear previous content
    if (!sourceWords.length) {
        return;
    }

    const isHidden = hideTextCheckbox.checked;
    // Render words, obscuring if in hidden mode.
    const wordsToRender = isHidden ? sourceWords.map(obscureWord) : sourceWords;

    const fragment = document.createDocumentFragment();
    wordsToRender.forEach((word, index) => {
        const span = document.createElement('span');
        span.className = 'word-span';
        span.textContent = word; // Use textContent to prevent XSS
        fragment.appendChild(span);

        // Add a space after each word except the last one
        if (index < wordsToRender.length - 1) {
            fragment.appendChild(document.createTextNode(' '));
        }
    });
    textDisplay.appendChild(fragment);

dictation.js Outdated
return fragment;
};

const obscureWord = (word) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

For better code organization, this new obscureWord helper function should be moved to the // ** Level 1: No Dependencies ** section (around line 47). Since it's a pure function with no external dependencies from this file, placing it with other similar functions will improve code readability and maintainability.

dictation.js Outdated
writingInput.classList.add('input-incorrect-flash');
setTimeout(() => {
writingInput.classList.remove('input-incorrect-flash');
}, 300);
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The timeout duration 300 is a magic number. It's better to define it as a named constant at the top of the file (e.g., INCORRECT_FLASH_DURATION = 300). This improves readability and makes it easier to manage timing-related values, especially since the corresponding CSS transition has a different duration.

dictation.js Outdated
ignoreAccentsCheckbox.addEventListener('change', saveConfig);
ignorePunctuationCheckbox.addEventListener('change', saveConfig);
ignoreCaseCheckbox.addEventListener('change', saveConfig);
waitForSpaceCheckbox.addEventListener('change', saveConfig);
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

When the 'Wait for space' checkbox is toggled, the change should be reflected immediately in the UI. Currently, it only saves the configuration, and the user has to type something for the change to take effect.

By also calling handleContinuousInput(), we can re-evaluate the current input and apply the new display logic instantly, which provides a better user experience.

    waitForSpaceCheckbox.addEventListener('change', () => { 
        saveConfig(); 
        handleContinuousInput(); 
    });

This commit addresses a wide range of user feedback, introducing new features, fixing bugs, and improving code quality.

Key changes include:

- **XSS Vulnerability Fix:** The `renderText` function was refactored to use `document.createElement` and `textContent` instead of `innerHTML`, mitigating a potential Cross-Site Scripting vulnerability from user-provided text.

- **"Hide Text" Mode Overhaul:**
    - Correctly typed words now remain unobscured, providing clear feedback to the user.
    - The underlying logic was improved to prevent a `TypeError` that occurred when displaying correction diffs.

- **Settings Panel to Hamburger Menu:**
    - The settings panel has been converted from a persistent sidebar to a slide-in overlay menu.
    - The "Settings" button is now a hamburger icon (☰).
    - Fixed a CSS specificity issue that prevented the menu from opening correctly.
    - Fixed a `z-index` issue that made the menu button unclickable when the panel was open.

- **Code Quality Improvements:**
    - The `obscureWord` helper function was moved to a more logical location.
    - A magic number for the incorrect-word flash duration was replaced with a named constant.
    - An immediate UI update was added when the "Wait for space" checkbox is toggled.
    - The readability of correction diffs was improved by adding a `line-through` text decoration to removed characters.
@rngadam rngadam merged commit 6b0f9e1 into main Oct 9, 2025
5 checks passed
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.

1 participant