• 
      

    Add utilities for confirmation dialogs and error dialogs.

    Review Request #14651 — Created Oct. 24, 2025 and submitted

    Information

    Ink
    master

    Reviewers

    This introduces two new utility functions for easily constructing and
    processing common types of message dialogs:

    • Ink.showConfirmDialog: Shows a confirmation dialog (a replacement
      for window.confirm().

    • Ink.showErrorDialog: Shows an error dialog (a replacement
      for window.alert().

    These are designed as utility functions that take a minimal set of
    options (but can be fairly customized). They return a Promise, which is
    resolved only once a choice has been made, allowing an async function to
    await on the result and process it before continuing.

    If the user confirmed, they'll get a truthy object that contains further
    information that may be useful for processing. If they cancel, they'll
    get a null result instead.

    The confirmation dialog can also take an async onConfirm handler,
    which will keep the dialog open and the buttons in a busy state until
    completed. That may return false, which will abort the dialog the same
    way as if the user hit Cancel. This is intended for error reporting
    during an operation.

    Confirmation dialogs can also be suppressed, using the new functionality
    in DialogView. This is off by default, but can be opted into. It's up
    to the caller to handle all confirmation logic.

    Tested the dialogs in all supported conditions.

    Summary ID
    Add utilities for confirmation dialogs and error dialogs.
    This introduces two new utility functions for easily constructing and processing common types of message dialogs: * `Ink.showConfirmDialog`: Shows a confirmation dialog (a replacement for `window.confirm()`. * `Ink.showErrorDialog`: Shows an error dialog (a replacement for `window.alert()`. These are designed as utility functions that take a minimal set of options (but can be fairly customized). They return a Promise, which is resolved only once a choice has been made, allowing an async function to await on the result and process it before continuing. If the user confirmed, they'll get a truthy object that contains further information that may be useful for processing. If they cancel, they'll get a `null` result instead. The confirmation dialog can also take an async `onConfirm` handler, which will keep the dialog open and the buttons in a busy state until completed. That may return `false`, which will abort the dialog the same way as if the user hit Cancel. This is intended for error reporting during an operation. Confirmation dialogs can also be suppressed, using the new functionality in `DialogView`. This is off by default, but can be opted into. It's up to the caller to handle all confirmation logic.
    90b81552313febe82ba07a92a18cddbc62c2ec1c

    Description From Last Updated

    Do we want some kind of error icon? I feel like that can help trigger people to actually read the …

    daviddavid

    There's an extra period here.

    maubinmaubin

    The annotation here has ShowConfirmDialogResult as a parameter name. This should be: onConfirm?: ((result: ShowConfirmDialogResult) => Promise<boolean | void>);

    daviddavid

    The docs for this parameter in ShowConfirmDialogOptions say the default is "Confirm" Also, do we want to extract this out …

    daviddavid

    Do we want to extract this out into a constant somewhere and/or localize it somehow?

    daviddavid

    The documentation in ShowErrorDialogOptions says the default for the title is "Error". Also, do we want to extract this out …

    daviddavid

    This is calling done(null) but the promise is a Promise<void>. This should probably be changed to done()

    daviddavid

    Do we want to extract this out into a constant somewhere and/or localize it somehow?

    daviddavid

    Can we have this check if rawBody is iterable and have a separate else clause that logs an error?

    daviddavid

    According to the type of MessageDialogBody this shouldn't be reachable, so this should probably be an error case.

    daviddavid

    if rawBody is falsy, body is never initialized and we end up returning undefined

    daviddavid
    maubin
    1. 
        
    2. Show all issues

      There's an extra period here.

    3. 
        
    chipx86
    david
    1. 
        
    2. Show all issues

      Do we want some kind of error icon? I feel like that can help trigger people to actually read the text.

      1. Went back and forth on this. Probably worth doing, but I'm not doing it as part of this work. That'd be more support within the dialog component, and I'm down several rabbit holes as it is.

    3. Show all issues

      The annotation here has ShowConfirmDialogResult as a parameter name.

      This should be:

      onConfirm?: ((result: ShowConfirmDialogResult) => Promise<boolean | void>);
      
    4. Show all issues

      The docs for this parameter in ShowConfirmDialogOptions say the default is "Confirm"

      Also, do we want to extract this out into a constant somewhere and/or localize it somehow?

      1. Localization is a whole bag of worms. I want to figure that out but we don't exactly have Django's gettext API here.

        I don't think there's a lot of value in a constant for these until/if we do localize.

    5. Show all issues

      Do we want to extract this out into a constant somewhere and/or localize it somehow?

    6. Show all issues

      The documentation in ShowErrorDialogOptions says the default for the title is "Error".

      Also, do we want to extract this out into a constant somewhere and/or localize it somehow?

    7. Show all issues

      This is calling done(null) but the promise is a Promise<void>. This should probably be changed to done()

      1. Copy/paste from the Confirm dialog. Fixing.

    8. Show all issues

      Do we want to extract this out into a constant somewhere and/or localize it somehow?

      1. Same as above. For now I don't see value in that since it's used in one place only and we're nowhere near set up for localization.

    9. Show all issues

      Can we have this check if rawBody is iterable and have a separate else clause that logs an error?

    10. src/ink/js/components/utils/dialogUtils.ts (Diff revision 2)
       
       
       
       
      Show all issues

      According to the type of MessageDialogBody this shouldn't be reachable, so this should probably be an error case.

    11. Show all issues

      if rawBody is falsy, body is never initialized and we end up returning undefined

    12. 
        
    chipx86
    david
    1. Ship It!
    2. 
        
    chipx86
    Review request changed
    Status:
    Completed
    Change Summary:
    Pushed to master (9483c69)