How to provide a wait image/popup through StreamResource before file is provided for download with vaadin

Viewed 122

I use streamResource to dynamically create files (after user click on the link) and then allow user to download the file. Sometimes it takes more than 10 seconds to create the file so I want to provide a waiting image or a related message and make inactive the link. However, all the changes and the new window I provide are executed only when the file is ready for the download and not earlier.
Is there any way to provide a message at the beginning of the process to the user? I am using Vaadin v8.

private StreamResource createResource(ExportItem exportItem, String exportType) {


    return new StreamResource(new StreamResource.StreamSource() {

        @Override
        public InputStream getStream()
        {
            //Provide a new wait Popup window to let the user know about the delay
            getView().showWaitPopup(true, "Your file is being generated!Please be patient.");

            //the following getFile() method needs about 10-20 seconds to generate the file.
            File file = getFile(exportItem, exportType);

            try {
                return new FileInputStream(file);
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
    }, exportItem.getFilename());
}
1 Answers

What you need is Push.

Without it (by default), any changes to the UI will only be performed once the "main" Request-Thread has finished.

In order to "push" changes to the UI immediately, you need to first enable @Push on your view, and then put the desired code which changes the ui inside a ui.access(() -> {...}); call. (actually not 100% sure if ui.access is needed in Vaadin 8 when in the request thread)

@Push
public class SomeUI extends UI {

    ...

    private StreamResource createResource(ExportItem exportItem, String exportType) {
        return new StreamResource(new StreamResource.StreamSource() {

            @Override
            public InputStream getStream()
            {
                // *Immediately* provide a new wait Popup window to let the user know about the delay
                access(() -> {
                    getView().showWaitPopup(true, "Your file is being generated!Please be patient.");
                });

                //the following getFile() method needs about 10-20 seconds to generate the file.
                File file = getFile(exportItem, exportType);

                // TODO: restore original state, or make user know it's ready (close popup?)

                try {
                    return new FileInputStream(file);
                } catch (IOException e) {
                    e.printStackTrace();
                    return null;
                }
            }
        }, exportItem.getFilename());
    }
}

As you may have noticed in the code I have added a TODO where you would usually restore the original state of the component that used to show a waiting spinner.

I personally would not show a Pop-up to tell the user he must wait, because you then have no good option to tell him afterwards that it's now ready. What I like to do usually is change the icon of the downloadbutton to VaadinIcon.HOURGLASS upon process start, and then change it back at the end.

Related