diff --git a/pom.xml b/pom.xml index d294294..dff2e4a 100644 --- a/pom.xml +++ b/pom.xml @@ -89,11 +89,11 @@ spring-boot-starter-validation - - org.springframework.boot - spring-boot-devtools - true - + + + + + org.springframework.boot diff --git a/src/main/java/com/esp/espflow/configuration/LoadEsptoolBundleConfiguration.java b/src/main/java/com/esp/espflow/configuration/LoadEsptoolBundleConfiguration.java index 4dfb671..ecc09d0 100644 --- a/src/main/java/com/esp/espflow/configuration/LoadEsptoolBundleConfiguration.java +++ b/src/main/java/com/esp/espflow/configuration/LoadEsptoolBundleConfiguration.java @@ -5,7 +5,7 @@ import com.esp.espflow.service.EsptoolPathService; import com.esp.espflow.service.hashservice.ComputeSha256Service; import com.esp.espflow.service.respository.impl.EsptoolExecutableServiceImpl; -import com.esp.espflow.util.MakeExecutable; +import com.esp.espflow.util.IMakeExecutable; import lombok.extern.log4j.Log4j2; import org.springframework.boot.CommandLineRunner; import org.springframework.context.annotation.Bean; @@ -47,7 +47,7 @@ */ @Log4j2 @Configuration -public class LoadEsptoolBundleConfiguration implements MakeExecutable { +public class LoadEsptoolBundleConfiguration implements IMakeExecutable { /** * Move the esptool executable to the system's temporary directory in runtime @@ -103,7 +103,7 @@ private String moveBundleToTempDirectory(final String bundleFileName) { if (GetOsName.getOsName() == GetOsName.LINUX) { final var pathResourceAsStream = META_INF_RESOURCES_ESPTOOL_BUNDLE + bundleFileName; this.processResourceAsStream(pathResourceAsStream, outPathFileName); - this.makeExecutable(outPathFileName); + this.makeExecutable(outPathFileName.toString()); } return outPathFileName.toString(); diff --git a/src/main/java/com/esp/espflow/service/EsptoolPathService.java b/src/main/java/com/esp/espflow/service/EsptoolPathService.java index 429c5d8..7e0c873 100644 --- a/src/main/java/com/esp/espflow/service/EsptoolPathService.java +++ b/src/main/java/com/esp/espflow/service/EsptoolPathService.java @@ -3,14 +3,12 @@ import com.esp.espflow.entity.dto.EsptoolExecutableDto; import com.esp.espflow.enums.GetOsName; import com.esp.espflow.service.respository.impl.EsptoolExecutableServiceImpl; -import com.esp.espflow.util.MakeExecutable; +import com.esp.espflow.util.IMakeExecutable; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; -import java.nio.file.Path; - import static com.esp.espflow.util.EspFlowConstants.ESPTOOL_BUNDLE_DIR; import static com.esp.espflow.util.EspFlowConstants.JAVA_IO_TEMPORAL_DIR_OS; @@ -20,7 +18,7 @@ @Log4j2 @Service @RequiredArgsConstructor -public class EsptoolPathService implements MakeExecutable { +public class EsptoolPathService implements IMakeExecutable { private final EsptoolExecutableServiceImpl esptoolExecutableServiceImpl; private String esptoolPath = StringUtils.EMPTY; @@ -39,7 +37,6 @@ public String esptoolPath() { log.info("Loaded esptoolPath() esptool.py bundled {}", esptoolPath); } else { this.esptoolPath = esptoolBundleDto.absolutePathEsptool(); - this.makeExecutable(esptoolPath); log.info("Loaded esptoolPath() custom esptool.py from {}", esptoolBundleDto.absolutePathEsptool()); } }, () -> { @@ -70,7 +67,6 @@ public String esptoolPath(EsptoolExecutableDto esptoolExecutableDto) { log.info("Loaded esptool.py bundled {}", esptoolPath); } else { this.esptoolPath = esptoolBundleDto.absolutePathEsptool(); - this.makeExecutable(esptoolPath); log.info("Loaded custom esptool.py from {}", esptoolBundleDto.absolutePathEsptool()); } }, () -> { @@ -104,17 +100,4 @@ private String bundlePath() { } } - /** - * - */ - private void makeExecutable(String esptoolPath) { - if (GetOsName.getOsName() == GetOsName.LINUX) { - if (this.makeExecutable(Path.of(esptoolPath))) { - log.info("esptool is executable"); - } else { - log.info("Error when setting permissions in the esptool executable {}", esptoolPath); - } - } - } - } diff --git a/src/main/java/com/esp/espflow/service/hashservice/ComputeSha256Service.java b/src/main/java/com/esp/espflow/service/hashservice/ComputeSha256Service.java index 4da1c65..55180e9 100644 --- a/src/main/java/com/esp/espflow/service/hashservice/ComputeSha256Service.java +++ b/src/main/java/com/esp/espflow/service/hashservice/ComputeSha256Service.java @@ -35,7 +35,7 @@ public class ComputeSha256Service { /** * First dir /home/user/.espflow/1.0.0/esptool/esptool.py * - * @param fileName the input file + * @param fileName the input file /home/user/.espflow/1.0.0/esptool/esptool.py * @return A {@link Mono} with computed 256 hash */ public Mono computeSha256(final String fileName) { @@ -47,7 +47,7 @@ public Mono computeSha256(final String fileName) { } /** - * @param fileName the input file + * @param fileName the input file /home/user/.espflow/1.0.0/esptool/esptool.py * @return A {@link Mono} with sha256 computed String */ private Mono startComputeSha256(final String fileName) { diff --git a/src/main/java/com/esp/espflow/util/MakeExecutable.java b/src/main/java/com/esp/espflow/util/IMakeExecutable.java similarity index 51% rename from src/main/java/com/esp/espflow/util/MakeExecutable.java rename to src/main/java/com/esp/espflow/util/IMakeExecutable.java index 85d5c4a..b5a07ad 100644 --- a/src/main/java/com/esp/espflow/util/MakeExecutable.java +++ b/src/main/java/com/esp/espflow/util/IMakeExecutable.java @@ -1,25 +1,44 @@ package com.esp.espflow.util; +import com.esp.espflow.enums.GetOsName; + import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermissions; import java.util.Set; +import java.util.logging.Logger; import static com.esp.espflow.util.EspFlowConstants.SET_CHMOD_X; /** * @author rubn */ -public interface MakeExecutable { +public interface IMakeExecutable { + + Logger log = Logger.getLogger(IMakeExecutable.class.getName()); + + default boolean makeExecutable(String esptoolPath) { + boolean isExecutable = false; + if (GetOsName.getOsName() == GetOsName.LINUX) { + if (this.setPosixFilePermissions(Path.of(esptoolPath))) { + log.info("esptool is executable: " + esptoolPath); + isExecutable = true; + } else { + log.info("Error when setting permissions in the esptool executable " + esptoolPath); + isExecutable = false; + } + } + return isExecutable; + } /** * Set run permissions if it is a linux or macOS executable. * * @param esptoolPath contains the path where the esptool executable is located */ - default boolean makeExecutable(final Path esptoolPath) { + private boolean setPosixFilePermissions(final Path esptoolPath) { try { Set permissions = PosixFilePermissions.fromString(SET_CHMOD_X); Files.setPosixFilePermissions(esptoolPath, permissions); diff --git a/src/main/java/com/esp/espflow/util/console/OutPutConsole.java b/src/main/java/com/esp/espflow/util/console/OutPutConsole.java index 043160c..851f989 100644 --- a/src/main/java/com/esp/espflow/util/console/OutPutConsole.java +++ b/src/main/java/com/esp/espflow/util/console/OutPutConsole.java @@ -199,9 +199,9 @@ protected void onDetach(DetachEvent detachEvent) { @Override protected void onAttach(AttachEvent attachEvent) { super.onAttach(attachEvent); - if (attachEvent.isInitialAttach()) { + //if (attachEvent.isInitialAttach()) { this.getConsole(); this.xterm.getXTerm().fit(); - } + //} } } diff --git a/src/main/java/com/esp/espflow/views/flashesp/FlashEspView.java b/src/main/java/com/esp/espflow/views/flashesp/FlashEspView.java index 064e835..7a0bc68 100644 --- a/src/main/java/com/esp/espflow/views/flashesp/FlashEspView.java +++ b/src/main/java/com/esp/espflow/views/flashesp/FlashEspView.java @@ -26,6 +26,8 @@ import com.vaadin.flow.component.radiobutton.RadioButtonGroup; import com.vaadin.flow.component.splitlayout.SplitLayout; import com.vaadin.flow.component.splitlayout.SplitLayout.Orientation; +import com.vaadin.flow.router.AfterNavigationEvent; +import com.vaadin.flow.router.AfterNavigationObserver; import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; import com.vaadin.flow.router.RouteAlias; @@ -78,7 +80,7 @@ @RolesAllowed("ADMIN") @RequiredArgsConstructor //@PreserveOnRefresh -public class FlashEspView extends Div implements ResponsiveHeaderDiv { +public class FlashEspView extends Div implements AfterNavigationObserver, ResponsiveHeaderDiv { private final DivFlashUploader divFlashUploader; private final DivHeaderPorts divHeaderPorts; @@ -97,6 +99,7 @@ public class FlashEspView extends Div implements ResponsiveHeaderDiv { /** * OutputConsole */ + private Div divColumnItems = new Div(); private final OutPutConsole outPutConsole = new OutPutConsole(); private String[] commands; @@ -158,12 +161,12 @@ private SplitLayout getSplitLayout() { divRowToSecondary.addClassNames(Display.FLEX, FlexDirection.ROW); divRowToSecondary.getStyle().set(OVERFLOW_Y, HIDDEN); - outPutConsole.getStyle().set("overflow-x", "hidden"); - outPutConsole.getDivTextArea().removeClassNames(Left.LARGE, Right.LARGE); - outPutConsole.getButtonClear().addClassName(BOX_SHADOW_VAADIN_BUTTON); - outPutConsole.getButtonDownScroll().addClassName(BOX_SHADOW_VAADIN_BUTTON); - Div divColumnItems = new Div(outPutConsole.getButtonDownScroll(), - outPutConsole.getButtonClear()); +// outPutConsole.getStyle().set("overflow-x", "hidden"); +// outPutConsole.getDivTextArea().removeClassNames(Left.LARGE, Right.LARGE); +// outPutConsole.getButtonClear().addClassName(BOX_SHADOW_VAADIN_BUTTON); +// outPutConsole.getButtonDownScroll().addClassName(BOX_SHADOW_VAADIN_BUTTON); +// Div divColumnItems = new Div(outPutConsole.getButtonDownScroll(), +// outPutConsole.getButtonClear()); divColumnItems.setId("divColumnItems"); divColumnItems.addClassNames( @@ -194,7 +197,11 @@ private SplitLayout getSplitLayout() { splitLayout.getSecondaryComponent().getElement().getStyle().set("scrollbar-color", "#3b3b3b #202020"); - splitLayout.addClickListener(event -> this.outPutConsole.fit()); + splitLayout.addClickListener(event -> { + if(this.outPutConsole.isAttached()) { + this.outPutConsole.fit(); + } + }); return splitLayout; } @@ -419,4 +426,15 @@ protected void onAttach(AttachEvent attachEvent) { } + @Override + public void afterNavigation(AfterNavigationEvent event) { + //Ignored listener invocation for terminal-initialized event from the client side for an inert fc-xterm element + if(outPutConsole.isAttached()) { + outPutConsole.getStyle().set("overflow-x", "hidden"); + outPutConsole.getDivTextArea().removeClassNames(Left.LARGE, Right.LARGE); + outPutConsole.getButtonClear().addClassName(BOX_SHADOW_VAADIN_BUTTON); + outPutConsole.getButtonDownScroll().addClassName(BOX_SHADOW_VAADIN_BUTTON); + this.divColumnItems.add(outPutConsole.getButtonDownScroll(), outPutConsole.getButtonClear()); + } + } } diff --git a/src/main/java/com/esp/espflow/views/readflash/ReadFlashView.java b/src/main/java/com/esp/espflow/views/readflash/ReadFlashView.java index 88e4113..e0f2595 100644 --- a/src/main/java/com/esp/espflow/views/readflash/ReadFlashView.java +++ b/src/main/java/com/esp/espflow/views/readflash/ReadFlashView.java @@ -44,6 +44,8 @@ import com.vaadin.flow.component.splitlayout.SplitLayout.Orientation; import com.vaadin.flow.component.textfield.IntegerField; import com.vaadin.flow.data.value.ValueChangeMode; +import com.vaadin.flow.router.AfterNavigationEvent; +import com.vaadin.flow.router.AfterNavigationObserver; import com.vaadin.flow.router.BeforeEnterEvent; import com.vaadin.flow.router.BeforeEnterObserver; import com.vaadin.flow.router.PageTitle; @@ -97,7 +99,7 @@ @Route(value = "read-flash", layout = MainLayout.class) @RolesAllowed("ADMIN") @RequiredArgsConstructor -public class ReadFlashView extends Div implements ResponsiveHeaderDiv, BeforeEnterObserver { +public class ReadFlashView extends Div implements ResponsiveHeaderDiv, AfterNavigationObserver, BeforeEnterObserver { private final FlashDownloadButtonService flashDownloadButtonService; private final EsptoolService esptoolService; @@ -117,6 +119,7 @@ public class ReadFlashView extends Div implements ResponsiveHeaderDiv, BeforeEnt * Console output */ private final OutPutConsole outPutConsole = new OutPutConsole(); + private final Div divColumnItems = new Div(); private final Span spanTotalDevices = new Span("Total devices:"); private final Span spanPortFailure = new Span(PORT_FAILURE); private final Span spanTotalDevicesValue = new Span(); @@ -282,13 +285,13 @@ private Div divForConsoleOutput() { divRowToSecondary.getStyle().set(OVERFLOW_Y, HIDDEN); divRowToSecondary.getStyle().set("background", "linear-gradient(var(--lumo-shade-5pct), var(--lumo-shade-5pct))"); - outPutConsole.getStyle().set("overflow-x", "hidden"); - outPutConsole.getDivTextArea().removeClassNames(Left.LARGE, Right.LARGE); - outPutConsole.getButtonClear().addClassName(BOX_SHADOW_VAADIN_BUTTON); - outPutConsole.getButtonDownScroll().addClassName(BOX_SHADOW_VAADIN_BUTTON); - - Div divColumnItems = new Div(outPutConsole.getButtonDownScroll(), - outPutConsole.getButtonClear()); +// outPutConsole.getStyle().set("overflow-x", "hidden"); +// outPutConsole.getDivTextArea().removeClassNames(Left.LARGE, Right.LARGE); +// outPutConsole.getButtonClear().addClassName(BOX_SHADOW_VAADIN_BUTTON); +// outPutConsole.getButtonDownScroll().addClassName(BOX_SHADOW_VAADIN_BUTTON); +// +// Div divColumnItems = new Div(outPutConsole.getButtonDownScroll(), +// outPutConsole.getButtonClear()); divColumnItems.setId("divColumnItems"); divColumnItems.addClassNames( @@ -682,6 +685,18 @@ public void beforeEnter(BeforeEnterEvent event) { }); } + @Override + public void afterNavigation(AfterNavigationEvent event) { + //Ignored listener invocation for terminal-initialized event from the client side for an inert fc-xterm element + if(outPutConsole.isAttached()) { + outPutConsole.getStyle().set("overflow-x", "hidden"); + outPutConsole.getDivTextArea().removeClassNames(Left.LARGE, Right.LARGE); + outPutConsole.getButtonClear().addClassName(BOX_SHADOW_VAADIN_BUTTON); + outPutConsole.getButtonDownScroll().addClassName(BOX_SHADOW_VAADIN_BUTTON); + this.divColumnItems.add(outPutConsole.getButtonDownScroll(), outPutConsole.getButtonClear()); + } + } + @Override protected void onDetach(DetachEvent detachEvent) { super.onDetach(detachEvent); diff --git a/src/main/java/com/esp/espflow/views/settings/SettingsEsptoolHomePathContent.java b/src/main/java/com/esp/espflow/views/settings/SettingsEsptoolHomePathContent.java index 32f9ff5..9143ae0 100644 --- a/src/main/java/com/esp/espflow/views/settings/SettingsEsptoolHomePathContent.java +++ b/src/main/java/com/esp/espflow/views/settings/SettingsEsptoolHomePathContent.java @@ -13,7 +13,7 @@ import com.esp.espflow.util.ConfirmDialogBuilder; import com.esp.espflow.util.CreateCustomDirectory; import com.esp.espflow.util.EspFlowConstants; -import com.esp.espflow.util.MakeExecutable; +import com.esp.espflow.util.IMakeExecutable; import com.esp.espflow.util.svgfactory.SvgFactory; import com.esp.espflow.views.Layout; import com.infraleap.animatecss.Animated; @@ -69,15 +69,15 @@ import static com.esp.espflow.util.EspFlowConstants.JAVA_IO_USER_HOME_DIR_OS; /** - * - Architecture correctly - * - make executable ? + * - make executable before save on db calculate hash ? + * * @author rub'n */ @Log4j2 @UIScope @SpringComponent @RequiredArgsConstructor -public class SettingsEsptoolHomePathContent extends Layout implements CreateCustomDirectory, MakeExecutable { +public class SettingsEsptoolHomePathContent extends Layout implements CreateCustomDirectory, IMakeExecutable { private final EsptoolService esptoolService; private final ComputeSha256Service computeSha256Service; @@ -134,9 +134,14 @@ private void initListeners() { }); } + /** + * + * @param esptoolExecutableDtoItem select by the user, and will be marked as true for use. + * @return A {@link Consumer} with String + */ private Consumer subscribeComboListener(EsptoolExecutableDto esptoolExecutableDtoItem) { return esptoolVersion -> { - this.executeCommandFromCombo(() -> { + this.executeCommandIfPresent(() -> { this.updateTextFieldWithComputeSha256(esptoolExecutableDtoItem.sha256()); this.publishEventAndRefreshHelperText(esptoolExecutableDtoItem); }); @@ -144,10 +149,8 @@ private Consumer subscribeComboListener(EsptoolExecutableDto esptoolExec } /** - * * @param event - * @param fileName - * + * @param fileName the String absolute path file home/user/.espflow/1.0.0/esptool/esptool * @return A {@link Consumer} */ private Consumer subscribeUploadedExecutable(SucceededEvent event, String fileName) { @@ -166,7 +169,7 @@ private boolean isANewVersionOfExecutableEsptool(EsptoolExecutableDto esptoolExe /** * Mapping from EsptoolSha256Dto to EsptoolExecutableDto * - * @param fileName + * @param fileName the String absolute path file home/user/.espflow/1.0.0/esptool/esptool * @return A {@link Function} */ private Function esptoolSha256DtoToEsptoolExecutableDto(String fileName) { @@ -187,45 +190,33 @@ private Mono fallback() { } /** - *

If the executable exists, we notify, delete from dir, db, and send empty to trigger the fallback, otherwise we save

+ *

If the executable exists, we notify, delete from dir, and send empty to trigger the fallback, otherwise we save

* * @return A {@link Function} */ private Function> returnEmptyIfVersionAlreadyExists() { return esptoolExecutableParam -> { - final EsptoolExecutableDto esptoolExecutableDto = this.esptoolExecutableServiceImpl .findByEsptoolVersionWithBundle(esptoolExecutableParam.esptoolVersion(), false) .orElse(null); - if (Objects.nonNull(esptoolExecutableDto)) { - - getUI().ifPresent(ui -> { - ui.access(() -> { - ConfirmDialogBuilder.showWarning("This version of the executable has already been loaded. " + - esptoolExecutableParam.esptoolVersion()); - }); + this.executeCommandIfPresent(() -> { + ConfirmDialogBuilder.showWarning("This version of the executable has already been loaded. " + + esptoolExecutableParam.esptoolVersion()); }); - try { Files.deleteIfExists(Path.of(esptoolExecutableParam.absolutePathEsptool())); } catch (IOException e) { throw new CanNotBeDeleteExecutableException("Error when trying to delete invalid loaded executable"); } - - this.esptoolExecutableServiceImpl.deleteById(esptoolExecutableDto.id()); - return Mono.empty(); } - - final EsptoolExecutableDto saved = this.esptoolExecutableServiceImpl.save(esptoolExecutableParam); - - return Mono.just(saved); + return Mono.just(this.esptoolExecutableServiceImpl.save(esptoolExecutableParam)); }; } /** - * @param fileName + * @param fileName the String absolute path file home/user/.espflow/1.0.0/esptool/esptool * @return A {@link Consumer} */ private Consumer errorProcessingWhenComputingSha256(String fileName) { @@ -313,23 +304,24 @@ public Scroller createEsptoolHomePathContent() { * Create a new directory with the executable version, select the uploaded executable, and then refresh the other * components, as well as notify the main panel. * - * @param esptoolVersion - * @param fileName - * @param event - * @param savedEsptoolBundleDto + * @param esptoolVersion the String with esptool version + * @param fileName the String absolute path file home/user/.espflow/1.0.0/esptool/esptool + * @param event the SucceededEvent + * @param savedEsptoolBundleDto the saved entity */ private void configureDirectoryForTheNewUploadedExecutable(final String esptoolVersion, final String fileName, final SucceededEvent event, final EsptoolExecutableDto savedEsptoolBundleDto) { - this.executeCommandFromCombo(() -> { + this.executeCommandIfPresent(() -> { try { final String version = esptoolVersion.split(" ")[1]; - // home/user/.espflow/1.0.0/esptool/v4.x.x/esptool final Path newEsptoolVersionDir = Path.of(JAVA_IO_USER_HOME_DIR_OS.concat(ESPFLOW_DIR) .concat(CUSTOM_ESPTOOL) + version + "/" + event.getFileName()); Files.createDirectories(newEsptoolVersionDir.getParent()); - // target /home/rubn/.espflow/1.0.0/esptool/esptool + // newEsptoolVersionDir home/user/.espflow/1.0.0/esptool/v4.x.x/esptool Files.move(Path.of(fileName), newEsptoolVersionDir, StandardCopyOption.REPLACE_EXISTING); + //"rwx--x--x" + this.makeExecutable(newEsptoolVersionDir.toString()); final EsptoolExecutableDto entityToUpdate = EsptoolExecutableMapper.INSTANCE.executableDtoWithNewDirectory(esptoolVersion, savedEsptoolBundleDto, newEsptoolVersionDir); @@ -351,8 +343,9 @@ private void configureDirectoryForTheNewUploadedExecutable(final String esptoolV } /** - * @param textEsptoolVersion - * @param textAbsolutePathEsptool + * @param textEsptoolVersion the String with esptool version + * @param textAbsolutePathEsptool the String absolute path file + * * @return A {@link Component} */ private Component createHelperText(final String textEsptoolVersion, final String textAbsolutePathEsptool) { @@ -395,34 +388,28 @@ private Component createHelperText(final String textEsptoolVersion, final String } /** - * Simple utility + * Simple shortcut or ui.access() * * @param command */ - public void executeCommandFromCombo(final Command command) { - this.comboBoxEsptoolHome.getUI().ifPresent(ui -> { - ui.access(command); - }); + public void executeCommandIfPresent(final Command command) { + getUI().ifPresent(ui -> ui.access(command)); } /** * @param inputHash the String with sha256 */ public void updateTextFieldWithComputeSha256(final String inputHash) { - this.comboBoxEsptoolHome.getUI().ifPresent(ui -> { - ui.access(() -> { - if (Objects.nonNull(inputHash)) { - if (inputHash.contains("sha256 does not match!")) { - final String sha256 = inputHash.split("!")[1].trim(); - this.showSpanSha256Result(sha256, "sha256 does not match!", VaadinIcon.WARNING, LumoUtility.TextColor.ERROR); - } else { - this.showSpanSha256Result(inputHash, "sha256 match!", VaadinIcon.INFO, LumoUtility.TextColor.PRIMARY); - } - } else { - ConfirmDialogBuilder.showWarning("Input hash is null " + inputHash); - } - }); - }); + if (Objects.nonNull(inputHash)) { + if (inputHash.contains("sha256 does not match!")) { + final String sha256 = inputHash.split("!")[1].trim(); + this.showSpanSha256Result(sha256, "sha256 does not match!", VaadinIcon.WARNING, LumoUtility.TextColor.ERROR); + } else { + this.showSpanSha256Result(inputHash, "sha256 match!", VaadinIcon.INFO, LumoUtility.TextColor.PRIMARY); + } + } else { + ConfirmDialogBuilder.showWarning("Input hash is null " + inputHash); + } } /** @@ -457,26 +444,24 @@ private void showSpanSha256Result(String sha256, String spanText, VaadinIcon ico * @param error the String with Error */ public void executeErrorCommandFromTextField(final String error) { - this.textFieldHash.getUI().ifPresent(ui -> { - ui.access(() -> { - var icon = SvgFactory.createCopyButtonFromSvg(); - final Span span = new Span(icon); - final ClipboardHelper clipboardHelper = new ClipboardHelper("Error ".concat(error), span); - span.addClickListener(event -> { - Notification.show("Copied error: " + error, 2500, Notification.Position.MIDDLE); - }); - Tooltip.forComponent(span).setText("Copy error"); - this.progressBar.setVisible(false); - this.textFieldHash.setSuffixComponent(clipboardHelper); - this.textFieldHash.setValue(error); - this.textFieldHash.removeClassName(LumoUtility.TextColor.ERROR); - this.textFieldHash.addClassNames(LumoUtility.FontSize.SMALL, LumoUtility.TextColor.ERROR); - final Span spanSha256 = new Span(VaadinIcon.WARNING.create()); - spanSha256.add("unexpected error!"); - spanSha256.addClassNames(LumoUtility.FontSize.SMALL, LumoUtility.TextColor.ERROR); - this.textFieldHash.setHelperComponent(spanSha256); - ConfirmDialogBuilder.showWarning("This executable cannot be processed, the hashes do not match."); + this.executeCommandIfPresent(() -> { + var icon = SvgFactory.createCopyButtonFromSvg(); + final Span span = new Span(icon); + final ClipboardHelper clipboardHelper = new ClipboardHelper("Error ".concat(error), span); + span.addClickListener(event -> { + Notification.show("Copied error: " + error, 2500, Notification.Position.MIDDLE); }); + Tooltip.forComponent(span).setText("Copy error"); + this.progressBar.setVisible(false); + this.textFieldHash.setSuffixComponent(clipboardHelper); + this.textFieldHash.setValue(error); + this.textFieldHash.removeClassName(LumoUtility.TextColor.ERROR); + this.textFieldHash.addClassNames(LumoUtility.FontSize.SMALL, LumoUtility.TextColor.ERROR); + final Span spanSha256 = new Span(VaadinIcon.WARNING.create()); + spanSha256.add("unexpected error!"); + spanSha256.addClassNames(LumoUtility.FontSize.SMALL, LumoUtility.TextColor.ERROR); + this.textFieldHash.setHelperComponent(spanSha256); + ConfirmDialogBuilder.showWarning("This executable cannot be processed, the hashes do not match."); }); }