Skip to content
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

Feedback on "Custom Dialog on Close" #147

Closed
bpasero opened this issue Jan 9, 2020 · 4 comments
Closed

Feedback on "Custom Dialog on Close" #147

bpasero opened this issue Jan 9, 2020 · 4 comments
Assignees

Comments

@bpasero
Copy link

bpasero commented Jan 9, 2020

This is an issue for https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/master/CustomDialogOnClose/explainer.md

With the introduction of the dialog property on the beforeUnload event I worry that now I am forced to show a dialog to the user every time on shutdown, even though I just need a bit of time to persist state. VSCode for Web can perfectly persist any state on shutdown without having to show a dialog to the user as long as it can execute a long running operation (talking about maybe 50-100ms here).

I see how the browser may want to indicate some feedback to the user and may even want to put a time limit, but I think that would work with my proposal as well. For example:

  • user closes PWA app
  • app code calls event.preventDefault() from onBeforeUnload handler and starts to run an async operation to persist state
    • PWA app will not close but will optionally indicate to the user that the close has been prevented (e.g. through some kind of notification in the title bar) after a certain time
    • If this short time is still exceeded, PWA app shows a native dialog to either close now (with the risk of loosing data) or continue to wait (similar to the dialog you see today when preventing the unload)
  • PWA app is in charge of continuing the unload once done (I see this as very similar to the flow when showing a prompt for installing PWA apps: https://pwa-workshop.js.org/6-pwa-setup/)

Sample code:

let isCustomUnload = false;

window.onbeforeunload = function (e) {
    if (isCustomUnload) {
        
        // Allow the unload to proceed as normal
        // if we know it is triggered from our code
        return null;
    }
    
    // Bypass any default browser unload handling
    e.preventDefault();

    // Run our custom function
    customCloseOrReload(e);
};

function customCloseOrReload(e) {
    someLongRunningOperation().then(() => {

        // NOTE: this is optional for VSCode!!!! We may decide to show a dialog but not in every case
        someCustomDialogToShow().then(() => {
            isCustomUnload = true;
    
            if (e.detail === 0) {
                window.close();
            } else {
                window.reload();
            }
        });
    });
}

function someLongRunningOperation() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve();
        }, 1000);
    });
}

function someCustomDialogToShow() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve();
        }, 1000);
    });
}
@bpasero
Copy link
Author

bpasero commented Jan 9, 2020

As a related note: VSCode has custom designed dialogs, such as:

image

Being forced into using the native browser dialogs on close is not a good option for us as the user would suddenly see a dialog that seems very different from the typical dialogs VSCode for Web shows.

@jungkees
Copy link
Contributor

@bpasero, we're doing some iteration based on your feedback and @MichaelEns's feedback. We'll update our discussion.

@bpasero
Copy link
Author

bpasero commented Jan 10, 2020

A couple of more notes on VSCode's usage on unload:

  • since we cannot perform a long running operation on unload, we currently simply periodically persist state and only block the unload if we detect that some state has not persisted yet (I think that is pretty much the behaviour in Gmail for example when you leave quickly enough after making a change to a mail)
  • our state to persist can be a combination of a websocket connection for writing files to the remote file system and IndexDB access for persisting UI state (e.g. list of opened editors)

As for prior art: Navigator.sendBeacon() seems related to this discussion as I think it is meant as a way to perform long running XHR requests even after the website is closed. It would be interesting to see if this API could be expanded to allow for other long running operations or even some custom code to be executed after the page has closed?

@jungkees
Copy link
Contributor

jungkees commented May 4, 2020

We have withdrawn our proposal on this problem due to the design conflict with the philosophy of keeping tab close as fast as possible. We have been exploring other alternatives including using Background Sync and Service Workers for sync'ing the app's state. However, we still see issues in sync'ing large data without loss between the document and service worker when the user closes the tab in an arbitrary moment.

We'll look at this problem space again when we have a strong signal from the community. We'll make sure to re-open this issue when that happens. Thanks!

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

No branches or pull requests

3 participants